Skip to content

Commit

Permalink
UnitTest for #534: Justified Text not supporting RTL
Browse files Browse the repository at this point in the history
- UnitTest added
  • Loading branch information
asturio committed May 13, 2021
1 parent 1a9c971 commit 3a9205b
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 18 deletions.
32 changes: 17 additions & 15 deletions openpdf/src/main/java/com/lowagie/text/pdf/LayoutProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@

package com.lowagie.text.pdf;

import com.lowagie.text.FontFactory;
import com.lowagie.text.error_messages.MessageLocalization;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
Expand All @@ -56,12 +58,8 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.lowagie.text.FontFactory;
import com.lowagie.text.error_messages.MessageLocalization;

/**
* Provides glyph layout e.g. for accented Latin letters.
*
* Provides glyph layout e.g. for accented Latin letters.
*/
public class LayoutProcessor {
private static final int DEFAULT_FLAGS = -1;
Expand All @@ -70,7 +68,7 @@ public class LayoutProcessor {
// Static variables can only be set once
private static boolean enabled = false;
private static int flags = DEFAULT_FLAGS;

private LayoutProcessor() {
throw new UnsupportedOperationException("static class");
}
Expand All @@ -85,7 +83,7 @@ public static void enable() {
/**
* Enables the processor providing flags
* This method can only be called once.
*
*
* @param flags see java.awt.Font.layoutGlyphVector
*/
public static void enable(int flags) {
Expand All @@ -104,17 +102,21 @@ public static int getFlags() {
return flags;
}

public static boolean isSet(int queryFlags) {
return (flags & queryFlags) == queryFlags;
}

public static boolean supportsFont(BaseFont baseFont) {
boolean supports = enabled && (awtFontMap.get(baseFont) != null);
return supports;
}

/**
* Loads the AWT font needed for layout
*
*
* @param baseFont OpenPdf base font
* @param filename of the font file
*
*
* @throws RuntimeException if font can not be loaded
*/
public static void loadFont(BaseFont baseFont, String filename) {
Expand Down Expand Up @@ -168,7 +170,7 @@ public static void loadFont(BaseFont baseFont, String filename) {

/**
* Computes glyph positioning
*
*
* @param baseFont OpenPdf base font
* @param text input text
* @return glyph vector containing reordered text, width and positioning info
Expand All @@ -194,15 +196,15 @@ public static GlyphVector computeGlyphVector(BaseFont baseFont, float fontSize,
/**
* Checks if the glyphVector contains adjustments
* that make advanced layout necessary
*
*
* @param glyphVector glyph vector containing the positions
* @return true, if the glyphVector contains adjustments
*/
private static boolean hasAdjustments(GlyphVector glyphVector) {
boolean retVal = false;
float lastX = 0f;
float lastY = 0f;

for (int i = 0; i < glyphVector.getNumGlyphs(); i++) {
Point2D p = glyphVector.getGlyphPosition(i);
float dx = (float) p.getX() - lastX;
Expand All @@ -223,9 +225,9 @@ private static boolean hasAdjustments(GlyphVector glyphVector) {

/**
* Shows a text using glyph positioning (if needed)
*
*
* @param cb object containing the content of the page
* @param baseFont base font to use
* @param baseFont base font to use
* @param fontSize font size to apply
* @param text text to show
* @return layout position correction to correct the start of the next line
Expand All @@ -242,7 +244,7 @@ public static Point2D showText(PdfContentByte cb, BaseFont baseFont, float fontS
}
float lastX = 0f;
float lastY = 0f;

for (int i = 0; i < glyphVector.getNumGlyphs(); i++) {
Point2D p = glyphVector.getGlyphPosition(i);

Expand Down
7 changes: 5 additions & 2 deletions openpdf/src/main/java/com/lowagie/text/pdf/PdfDocument.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@

package com.lowagie.text.pdf;

import static java.awt.Font.LAYOUT_RIGHT_TO_LEFT;

import com.lowagie.text.Anchor;
import com.lowagie.text.Annotation;
import com.lowagie.text.BadElementException;
Expand Down Expand Up @@ -1415,7 +1417,7 @@ void writeLineToContent(PdfLine line, PdfContentByte text, PdfContentByte graphi
}
else if (isJustified) {
if (line.isNewlineSplit() && line.widthLeft() >= (lastBaseFactor * (ratio * numberOfSpaces + lineLen - 1))) {
if (line.isRTL()||(LayoutProcessor.isEnabled()&&LayoutProcessor.getFlags() == java.awt.Font.LAYOUT_RIGHT_TO_LEFT)) {
if (line.isRTL() || (LayoutProcessor.isEnabled() && LayoutProcessor.isSet(LAYOUT_RIGHT_TO_LEFT))) {
text.moveText(line.widthLeft() - lastBaseFactor * (ratio * numberOfSpaces + lineLen - 1), 0);
}
baseWordSpacing = ratio * lastBaseFactor;
Expand Down Expand Up @@ -1701,8 +1703,9 @@ else if (isJustified && numberOfSpaces > 0 && chunk.isSpecialEncoding()) {
else {
float spaceCorrection = - baseWordSpacing * 1000f / chunk.font.size() / hScale;
PdfTextArray textArray = new PdfTextArray();
if (LayoutProcessor.isEnabled()&&LayoutProcessor.getFlags() == java.awt.Font.LAYOUT_RIGHT_TO_LEFT)
if (LayoutProcessor.isEnabled() && LayoutProcessor.isSet(LAYOUT_RIGHT_TO_LEFT)) {
textArray.setRTL(true);
}
textArray.add(s.substring(0, idx));
int lastIdx = idx;
while ((idx = s.indexOf(' ', lastIdx + 1)) >= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
class LayoutProcessor534Test {

@Test
public void whenLayoutRightToLeft_thenRevertCharOrder() throws IOException {
public void whenLayoutRightToLeftLatin_thenRevertCharOrder() throws IOException {
// given
Document document = new Document(PageSize.A4.rotate(), 10, 10, 10, 10);
ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
Expand Down Expand Up @@ -44,4 +44,39 @@ public void whenLayoutRightToLeft_thenRevertCharOrder() throws IOException {
+ " ytriht eniNytnewt thgiEytnewt");
}

@Test
public void whenLayoutRightToLeftHebrew_thenRevertCharOrder() throws IOException {
// given
Document document = new Document(PageSize.A4.rotate(), 10, 10, 10, 10);
ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
PdfWriter.getInstance(document, pdfOut);
document.open();
// when
LayoutProcessor.enable(java.awt.Font.LAYOUT_RIGHT_TO_LEFT);
String text = "שוב היתה זו שעת לילה. דממה שררה בפונדק אבן־הדרך, והיתה זו דממה בת שלושה חלקים." +
"החלק המתבקש מאליו היה שקט חלול, מהדהד, עשוי מן הדברים שלא היו. אילו היתה רוח, כי" +
"אז היתה נאנחת בעוברה בין העצים, מטלטלת את שלט הפונדק בחריקה על ציריו וסוחפת את" +
"הדממה במורד הדרך, כפי שהיא גורפת עלי סתיו. אילו היה קהל בפונדק, אפילו קומץ אנשים, כי" +
"אז היו ממלאים את הדממה בשיחה ובצחוק, בהמולה ובשאון שהיה מקום לצַפות להם במסבאה," +
"בשעות הלילה החשוכות. אילו היתה מוסיקה... אבל לא , ודאי שלא היתה מוסיקה. למען האמת, אף" +
"לא אחד מהדברים האלה היה שם, ולכן נותרה הדממה בעינה.";

Paragraph paragraph = new Paragraph(new Chunk(text));
paragraph.setAlignment(Element.ALIGN_JUSTIFIED);
document.add(paragraph);
document.close();

// then
PdfTextExtractor extractor = new PdfTextExtractor(new PdfReader(pdfOut.toByteArray()));
Assertions.assertThat(extractor.getTextFromPage(1))
.isEqualTo(".ויה אלש םירבדה ןמ יושע ,דהדהמ ,לולח טקש היה וילאמ"
+ " שקבתמה קלחה.םיקלח השולש תב הממד וז התיהו ,ךרדה־ןבא קדנופב הררש הממד .הליל תעש וז התיה בוש\n"
+ " וליא .ויתס ילע תפרוג איהש יפכ ,ךרדה דרומב הממדהתא"
+ " תפחוסו ויריצ לע הקירחב קדנופה טלש תא תלטלטמ ,םיצעה ןיב הרבועב תחנאנ התיה זאיכ ,חור התיה וליא\n"
+ " וליא .תוכושחה הלילה תועשב,האבסמב םהל תופַצל"
+ " םוקמ היהש ןואשבו הלומהב ,קוחצבו החישב הממדה תא םיאלממ ויה זאיכ ,םישנא ץמוק וליפא ,קדנופב להק היה\n"
+ " .הניעב הממדה"
+ " הרתונ ןכלו ,םש היה הלאה םירבדהמ דחא אלףא ,תמאה ןעמל .הקיסומ התיה אלש יאדו , אל לבא ...הקיסומ התיה");
}

}

0 comments on commit 3a9205b

Please sign in to comment.