Skip to content

Commit ef08bfa

Browse files
committed
Detect automatically if reordering should be applied based on script detection in case no base direction is specified. If base direction is specified, it has a priority over automatic detection
DEVSIX-474
1 parent 8e46d97 commit ef08bfa

File tree

4 files changed

+37
-59
lines changed

4 files changed

+37
-59
lines changed

forms/src/main/java/com/itextpdf/forms/fields/PdfFormField.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,7 +1966,6 @@ protected void drawTextAppearance(Rectangle rect, PdfFont font, int fontSize, St
19661966
newPath();
19671967

19681968
Paragraph paragraph = new Paragraph(value).setFont(font).setFontSize(fontSize).setMultipliedLeading(1).setPaddings(0, 2, 0, 2);
1969-
setParagraphProperties(paragraph, value);
19701969
if (color != null) {
19711970
paragraph.setFontColor(color);
19721971
}
@@ -2025,7 +2024,6 @@ protected void drawMultiLineTextAppearance(Rectangle rect, PdfFont font, int fon
20252024
Canvas modelCanvas = new Canvas(canvas, getDocument(), new Rectangle(3, 0, Math.max(0, width - 6), Math.max(0, height - 2)));
20262025
for (int index = 0; index < strings.size(); index++) {
20272026
Paragraph paragraph = new Paragraph(strings.get(index)).setFont(font).setFontSize(fontSize).setMargins(0, 0, 0, 0).setMultipliedLeading(1);
2028-
setParagraphProperties(paragraph, strings.get(index));
20292027
if (color != null) {
20302028
paragraph.setFontColor(color);
20312029
}
@@ -2227,7 +2225,6 @@ protected void drawButton(PdfCanvas canvas, float x, float y, float width, float
22272225

22282226
Paragraph paragraph = new Paragraph(text).setFont(font).setFontSize(fontSize).setMargin(0).setMultipliedLeading(1).
22292227
setVerticalAlignment(Property.VerticalAlignment.MIDDLE);
2230-
setParagraphProperties(paragraph, text);
22312228
new Canvas(canvas, getDocument(), new Rectangle(0, -height, width, 2 * height)).showTextAligned(paragraph, width / 2, height / 2, Property.TextAlignment.CENTER, Property.VerticalAlignment.MIDDLE);
22322229
}
22332230

@@ -2274,16 +2271,6 @@ private String obfuscatePassword(String text) {
22742271
return new String(pchar);
22752272
}
22762273

2277-
private void setParagraphProperties(Paragraph paragraph, String value) {
2278-
// TODO this is temporary and will be replaced by script autodetection logic on layout level
2279-
if (value != null && value.length() > 0) {
2280-
Character.UnicodeScript script = Character.UnicodeScript.of(value.charAt(0));
2281-
if (script == Character.UnicodeScript.ARABIC || script == Character.UnicodeScript.HEBREW) {
2282-
paragraph.setBaseDirection(Property.BaseDirection.RIGHT_TO_LEFT);
2283-
}
2284-
}
2285-
}
2286-
22872274
private void applyRotation(PdfFormXObject xObject, float height, float width) {
22882275
switch (rotation) {
22892276
case 90:

layout/src/main/java/com/itextpdf/layout/renderer/LineRenderer.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,16 @@ public LineLayoutResult layout(LayoutContext layoutContext) {
3636
int childPos = 0;
3737

3838
Property.BaseDirection baseDirection = getProperty(Property.BASE_DIRECTION);
39-
if (levels == null && baseDirection != Property.BaseDirection.NO_BIDI) {
40-
for (IRenderer renderer : childRenderers) {
41-
if (renderer instanceof TextRenderer) {
42-
((TextRenderer) renderer).applyOtf();
39+
for (IRenderer renderer : childRenderers) {
40+
if (renderer instanceof TextRenderer) {
41+
((TextRenderer) renderer).applyOtf();
42+
if (baseDirection == null || baseDirection == Property.BaseDirection.NO_BIDI) {
43+
baseDirection = renderer.getOwnProperty(Property.BASE_DIRECTION);
4344
}
4445
}
46+
}
47+
48+
if (levels == null && baseDirection != null && baseDirection != Property.BaseDirection.NO_BIDI) {
4549
List<Integer> unicodeIdsLst = new ArrayList<>();
4650
for (IRenderer child : childRenderers) {
4751
if (child instanceof TextRenderer) {
@@ -176,7 +180,7 @@ public LineLayoutResult layout(LayoutContext layoutContext) {
176180

177181
// Consider for now that all the children have the same font, and that after reordering text pieces
178182
// can be reordered, but cannot be split.
179-
if (baseDirection != Property.BaseDirection.NO_BIDI) {
183+
if (baseDirection != null && baseDirection != Property.BaseDirection.NO_BIDI) {
180184
List<IRenderer> children = null;
181185
if (result.getStatus() == LayoutResult.PARTIAL) {
182186
children = result.getSplitRenderer().getChildRenderers();

layout/src/main/java/com/itextpdf/layout/renderer/TextRenderer.java

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ public TextLayoutResult layout(LayoutContext layoutContext) {
105105
float italicSkewAddition = Boolean.valueOf(true).equals(getPropertyAsBoolean(Property.ITALIC_SIMULATION)) ? ITALIC_ANGLE * fontSize : 0;
106106
float boldSimulationAddition = Boolean.valueOf(true).equals(getPropertyAsBoolean(Property.BOLD_SIMULATION)) ? BOLD_SIMULATION_STROKE_COEFF * fontSize : 0;
107107

108-
applyOtf();
109108
line = new GlyphLine(text);
110109
line.start = line.end = -1;
111110

@@ -325,31 +324,33 @@ public void applyOtf() {
325324
if (script == null && TypographyUtils.isTypographyModuleInitialized()) {
326325
// Try to autodetect complex script.
327326
Collection<Character.UnicodeScript> supportedScripts = TypographyUtils.getSupportedScripts();
328-
if (supportedScripts != null) {
329-
Map<Character.UnicodeScript, Integer> scriptFrequency = new EnumMap<>(Character.UnicodeScript.class);
330-
for (int i = text.start; i < text.end; i++) {
331-
Integer unicode = text.get(i).getUnicode();
332-
Character.UnicodeScript glyphScript = unicode != null ? Character.UnicodeScript.of(unicode) : null;
333-
if (glyphScript != null && supportedScripts.contains(glyphScript)) {
334-
if (scriptFrequency.containsKey(glyphScript)) {
335-
scriptFrequency.put(glyphScript, scriptFrequency.get(glyphScript));
336-
} else {
337-
scriptFrequency.put(glyphScript, 1);
338-
}
339-
}
340-
}
341-
int max = 0;
342-
Character.UnicodeScript selectScript = null;
343-
for (Map.Entry<Character.UnicodeScript, Integer> entry : scriptFrequency.entrySet()) {
344-
if (entry.getValue() > max) {
345-
max = entry.getValue();
346-
selectScript = entry.getKey();
327+
Map<Character.UnicodeScript, Integer> scriptFrequency = new EnumMap<>(Character.UnicodeScript.class);
328+
for (int i = text.start; i < text.end; i++) {
329+
Integer unicode = text.get(i).getUnicode();
330+
Character.UnicodeScript glyphScript = unicode != null ? Character.UnicodeScript.of(unicode) : null;
331+
if (glyphScript != null) {
332+
if (scriptFrequency.containsKey(glyphScript)) {
333+
scriptFrequency.put(glyphScript, scriptFrequency.get(glyphScript) + 1);
334+
} else {
335+
scriptFrequency.put(glyphScript, 1);
347336
}
348337
}
349-
if (selectScript != null) {
350-
script = selectScript;
338+
}
339+
int max = 0;
340+
Character.UnicodeScript selectScript = null;
341+
for (Map.Entry<Character.UnicodeScript, Integer> entry : scriptFrequency.entrySet()) {
342+
Character.UnicodeScript entryScript = entry.getKey();
343+
if (entry.getValue() > max && !Character.UnicodeScript.COMMON.equals(entryScript) && !Character.UnicodeScript.UNKNOWN.equals(entryScript)) {
344+
max = entry.getValue();
345+
selectScript = entryScript;
351346
}
352347
}
348+
if (selectScript == Character.UnicodeScript.ARABIC || selectScript == Character.UnicodeScript.HEBREW && parent instanceof LineRenderer) {
349+
setProperty(Property.BASE_DIRECTION, Property.BaseDirection.DEFAULT_BIDI);
350+
}
351+
if (selectScript != null && supportedScripts != null && supportedScripts.contains(selectScript)) {
352+
script = selectScript;
353+
}
353354
}
354355

355356
if (isOtfFont(font) && script != null) {

sign/src/main/java/com/itextpdf/signatures/PdfSignatureAppearance.java

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
package com.itextpdf.signatures;
22

3-
import com.itextpdf.kernel.geom.Rectangle;
3+
import com.itextpdf.forms.PdfAcroForm;
4+
import com.itextpdf.forms.fields.PdfFormField;
45
import com.itextpdf.io.image.Image;
56
import com.itextpdf.kernel.font.PdfFont;
67
import com.itextpdf.kernel.font.PdfFontFactory;
8+
import com.itextpdf.kernel.geom.Rectangle;
79
import com.itextpdf.kernel.pdf.PdfDocument;
810
import com.itextpdf.kernel.pdf.PdfName;
911
import com.itextpdf.kernel.pdf.PdfStream;
1012
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
1113
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
12-
import com.itextpdf.forms.PdfAcroForm;
13-
import com.itextpdf.forms.fields.PdfFormField;
1414
import com.itextpdf.layout.Canvas;
15-
import com.itextpdf.layout.Property;
1615
import com.itextpdf.layout.element.Paragraph;
1716

1817
import java.io.IOException;
@@ -650,8 +649,7 @@ protected PdfFormXObject getAppearance() throws IOException {
650649
}
651650

652651
PdfCanvas canvas = new PdfCanvas(n2, document);
653-
Paragraph paragraph = setParagraphProperties(new Paragraph(signedBy).
654-
setFont(font).setFontSize(layer2FontSize).setMargin(0).setMultipliedLeading(0.9f), signedBy);
652+
Paragraph paragraph = new Paragraph(signedBy).setFont(font).setFontSize(layer2FontSize).setMargin(0).setMultipliedLeading(0.9f);
655653
new Canvas(canvas, document, signatureRect).add(paragraph);
656654

657655
break;
@@ -714,8 +712,7 @@ protected PdfFormXObject getAppearance() throws IOException {
714712

715713
if (renderingMode != RenderingMode.GRAPHIC) {
716714
PdfCanvas canvas = new PdfCanvas(n2, document);
717-
Paragraph paragraph = setParagraphProperties(new Paragraph(text).
718-
setFont(font).setFontSize(layer2FontSize).setMargin(0).setMultipliedLeading(0.9f), text);
715+
Paragraph paragraph = new Paragraph(text).setFont(font).setFontSize(layer2FontSize).setMargin(0).setMultipliedLeading(0.9f);
719716
new Canvas(canvas, document, dataRect).add(paragraph);
720717
}
721718
}
@@ -819,17 +816,6 @@ private void createBlankN0() {
819816
canvas.writeLiteral("% DSBlank\n");
820817
}
821818

822-
private Paragraph setParagraphProperties(Paragraph paragraph, String value) {
823-
// TODO this is temporary and will be replaced by script autodetection logic on layout level
824-
if (value != null && value.length() > 0) {
825-
Character.UnicodeScript script = Character.UnicodeScript.of(value.charAt(0));
826-
if (script == Character.UnicodeScript.ARABIC || script == Character.UnicodeScript.HEBREW) {
827-
paragraph.setBaseDirection(Property.BaseDirection.RIGHT_TO_LEFT);
828-
}
829-
}
830-
return paragraph;
831-
}
832-
833819
/**
834820
* Signature rendering modes.
835821
*/

0 commit comments

Comments
 (0)