Skip to content

Commit 0761a0c

Browse files
committed
Enable khmer and lao word wrapping
- handle multiple chars within a glyph on word wrapping - check each char rather than a whole glyph when detecting script for word wrapping DEVSIX-4106 Autoported commit. Original commit hash: [fc5d1b2]
1 parent e33da9d commit 0761a0c

File tree

6 files changed

+202
-62
lines changed

6 files changed

+202
-62
lines changed

itext.tests/itext.layout.tests/itext/layout/renderer/WordWrapUnitTest.cs

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ You should have received a copy of the GNU Affero General Public License
2525
using System.IO;
2626
using System.Text;
2727
using iText.IO.Font;
28+
using iText.IO.Font.Otf;
2829
using iText.IO.Util;
2930
using iText.Kernel.Font;
3031
using iText.Kernel.Geom;
@@ -47,6 +48,9 @@ public class WordWrapUnitTest : ExtendedITextTest {
4748
public static readonly String REGULAR_FONT = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
4849
.CurrentContext.TestDirectory) + "/resources/itext/layout/fonts/NotoSans-Regular.ttf";
4950

51+
public static readonly String KHMER_FONT = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
52+
.CurrentContext.TestDirectory) + "/resources/itext/layout/fonts/KhmerOS.ttf";
53+
5054
// หากอากาศดีในวันพรุ่งนี้เราจะไปปิกนิก - one sentence, multiple words.
5155
public const String THAI_TEXT = "\u0E2B\u0E32\u0E01\u0E2D\u0E32\u0E01\u0E32\u0E28\u0E14\u0E35" + "\u0E43\u0E19\u0E27\u0E31\u0E19\u0E1E\u0E23\u0E38\u0E48\u0E07\u0E19\u0E35\u0E49"
5256
+ "\u0E40\u0E23\u0E32\u0E08\u0E30\u0E44\u0E1B\u0E1B\u0E34\u0E01\u0E19\u0E34\u0E01";
@@ -285,9 +289,7 @@ public virtual void OneThaiWordSplitAcrossMultipleRenderersGetIndexAndLayoutResu
285289
NUnit.Framework.Assert.AreEqual(5, lastFittingChildRendererData.childIndex);
286290
NUnit.Framework.Assert.AreEqual(LayoutResult.NOTHING, lastFittingChildRendererData.childLayoutResult.GetStatus
287291
());
288-
float occupiedAreaWidth = lastFittingChildRendererData.childLayoutResult.GetOccupiedArea().GetBBox().GetWidth
289-
();
290-
NUnit.Framework.Assert.AreEqual(500, occupiedAreaWidth, 0.0001);
292+
NUnit.Framework.Assert.IsNull(lastFittingChildRendererData.childLayoutResult.GetOccupiedArea());
291293
}
292294

293295
[NUnit.Framework.Test]
@@ -595,8 +597,8 @@ public virtual void UpdateSpecialScriptLayoutResultsTextRendererWithSpecialScrip
595597
[NUnit.Framework.Test]
596598
public virtual void CurWidthZeroDecrement() {
597599
int oldNewChildPos = 1;
598-
float decrement = LineRenderer.GetCurWidthSpecialScriptsDecrement(oldNewChildPos, oldNewChildPos, new LayoutResult
599-
(0, null, null, null), new Dictionary<int, LayoutResult>());
600+
float decrement = LineRenderer.GetCurWidthSpecialScriptsDecrement(oldNewChildPos, oldNewChildPos, new Dictionary
601+
<int, LayoutResult>());
600602
NUnit.Framework.Assert.AreEqual(0.0f, decrement, 0.0001);
601603
}
602604

@@ -605,35 +607,30 @@ public virtual void CurWidthLayoutResultNothing() {
605607
float widthOfNewNothingResult = 500;
606608
LayoutArea occupiedArea = new LayoutArea(1, new Rectangle(0, 0, widthOfNewNothingResult, 0));
607609
LayoutResult oldResult = new LayoutResult(LayoutResult.FULL, occupiedArea, null, null);
608-
LayoutResult newResult = new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, null);
609610
float simpleWidth = 200;
610611
LayoutResult simpleDecrement = new LayoutResult(LayoutResult.FULL, new LayoutArea(1, new Rectangle(0, 0, simpleWidth
611612
, 0)), null, null);
612613
IDictionary<int, LayoutResult> specialScriptLayoutResults = new Dictionary<int, LayoutResult>();
613614
specialScriptLayoutResults.Put(0, oldResult);
614615
// leave specialScriptLayoutResults.get(1) null, as if childRenderers.get(1) is floating
615616
specialScriptLayoutResults.Put(2, simpleDecrement);
616-
float decrement = LineRenderer.GetCurWidthSpecialScriptsDecrement(3, 0, newResult, specialScriptLayoutResults
617-
);
618-
NUnit.Framework.Assert.AreEqual(2 * widthOfNewNothingResult + simpleWidth, decrement, 0.00001);
617+
float decrement = LineRenderer.GetCurWidthSpecialScriptsDecrement(3, 0, specialScriptLayoutResults);
618+
NUnit.Framework.Assert.AreEqual(widthOfNewNothingResult + simpleWidth, decrement, 0.00001);
619619
}
620620

621621
[NUnit.Framework.Test]
622622
public virtual void CurWidthLayoutResultPartial() {
623623
float widthOfNewPartialResult = 500;
624624
LayoutArea oldOccupiedArea = new LayoutArea(1, new Rectangle(0, 0, widthOfNewPartialResult, 0));
625-
LayoutArea newOccupiedArea = new LayoutArea(1, new Rectangle(0, 0, widthOfNewPartialResult / 2, 0));
626625
LayoutResult oldResult = new LayoutResult(LayoutResult.FULL, oldOccupiedArea, null, null);
627-
LayoutResult newResult = new LayoutResult(LayoutResult.PARTIAL, newOccupiedArea, null, null);
628626
float simpleWidth = 200;
629627
LayoutResult simpleDecrement = new LayoutResult(LayoutResult.FULL, new LayoutArea(1, new Rectangle(0, 0, simpleWidth
630628
, 0)), null, null);
631629
IDictionary<int, LayoutResult> specialScriptLayoutResults = new Dictionary<int, LayoutResult>();
632630
specialScriptLayoutResults.Put(0, oldResult);
633631
// leave specialScriptLayoutResults.get(1) null, as if childRenderers.get(1) is floating
634632
specialScriptLayoutResults.Put(2, simpleDecrement);
635-
float decrement = LineRenderer.GetCurWidthSpecialScriptsDecrement(3, 0, newResult, specialScriptLayoutResults
636-
);
633+
float decrement = LineRenderer.GetCurWidthSpecialScriptsDecrement(3, 0, specialScriptLayoutResults);
637634
NUnit.Framework.Assert.AreEqual(widthOfNewPartialResult + simpleWidth, decrement, 0.00001);
638635
}
639636

@@ -659,5 +656,53 @@ public virtual void UpdateFloatsOverflowedToNextLine() {
659656
NUnit.Framework.Assert.AreEqual(1, floatsOverflowedToNextLineIRenderers.Count);
660657
NUnit.Framework.Assert.AreEqual(onlyFloatToRemain, floatsOverflowedToNextLineIRenderers[0]);
661658
}
659+
660+
[NUnit.Framework.Test]
661+
public virtual void PossibleBreakWithinActualText() {
662+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new MemoryStream()));
663+
Document document = new Document(pdfDocument);
664+
LineRenderer lineRenderer = new LineRenderer();
665+
lineRenderer.SetParent(document.GetRenderer());
666+
TextRenderer textRenderer = new TextRenderer(new iText.Layout.Element.Text(""));
667+
IList<Glyph> glyphs = new List<Glyph>();
668+
glyphs.Add(new Glyph(629, 378, new char[] { '\u17c3' }));
669+
glyphs.Add(new Glyph(578, 756, new char[] { '\u1790' }));
670+
glyphs.Add(new Glyph(386, 0, new char[] { '\u17d2', '\u1784' }));
671+
glyphs.Add(new Glyph(627, 378, new char[] { '\u17c1' }));
672+
glyphs.Add(new Glyph(581, 756, new char[] { '\u1793' }));
673+
glyphs.Add(new Glyph(633, 512, new char[] { '\u17c7' }));
674+
GlyphLine glyphLine = new GlyphLine(glyphs);
675+
glyphLine.SetActualText(0, 3, "\u1790\u17d2\u1784\u17c3");
676+
glyphLine.SetActualText(3, 6, "\u1793\u17c1\u17c7");
677+
textRenderer.SetText(glyphLine, PdfFontFactory.CreateFont(KHMER_FONT, PdfEncodings.IDENTITY_H));
678+
lineRenderer.AddChild(textRenderer);
679+
IList<int> possibleBreakPoints = new List<int>(JavaUtil.ArraysAsList(1, 2, 3, 4, 5, 6, 7));
680+
lineRenderer.DistributePossibleBreakPointsOverSequentialTextRenderers(0, 1, possibleBreakPoints, new List<
681+
int>());
682+
IList<int> distributed = ((TextRenderer)lineRenderer.GetChildRenderers()[0]).GetSpecialScriptsWordBreakPoints
683+
();
684+
NUnit.Framework.Assert.AreEqual(new List<int>(JavaUtil.ArraysAsList(3, 6)), distributed);
685+
}
686+
687+
[NUnit.Framework.Test]
688+
public virtual void TrimFirstOnePossibleBreak() {
689+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new MemoryStream()));
690+
Document document = new Document(pdfDocument);
691+
PdfFont pdfFont = PdfFontFactory.CreateFont(THAI_FONT, PdfEncodings.IDENTITY_H);
692+
// " อากาศ"
693+
String thai = "\u0020" + THAI_WORD;
694+
TextRenderer textRenderer = new TextRenderer(new iText.Layout.Element.Text(""));
695+
textRenderer.SetProperty(Property.FONT, pdfFont);
696+
textRenderer.SetText(thai);
697+
textRenderer.SetSpecialScriptsWordBreakPoints(new List<int>(JavaUtil.ArraysAsList(1)));
698+
LineRenderer lineRenderer = new LineRenderer();
699+
lineRenderer.SetParent(document.GetRenderer());
700+
lineRenderer.AddChild(textRenderer);
701+
lineRenderer.TrimFirst();
702+
TextRenderer childTextRenderer = (TextRenderer)lineRenderer.GetChildRenderers()[0];
703+
NUnit.Framework.Assert.IsNotNull(childTextRenderer.GetSpecialScriptsWordBreakPoints());
704+
NUnit.Framework.Assert.AreEqual(1, childTextRenderer.GetSpecialScriptsWordBreakPoints().Count);
705+
NUnit.Framework.Assert.AreEqual(-1, (int)childTextRenderer.GetSpecialScriptsWordBreakPoints()[0]);
706+
}
662707
}
663708
}
Binary file not shown.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Please notice that the following fonts are used with the mentioned below licenses.
2+
3+
* FreeSans - GPL license you can find following the link: https://www.gnu.org/licenses
4+
* KhmerOS - LGPL license you can find following the link: https://www.gnu.org/licenses
5+
* NotoColorEmoji - SIL Open Font License v1.1
6+
* NotoEmoji-Regular - SIL Open Font License v1.1
7+
* NotoSansCJKjp-Bold - SIL Open Font License v1.1
8+
* NotoSansCJKsc-Regular - SIL Open Font License v1.1
9+
* NotoSansCJKtc-Regular - SIL Open Font License v1.1
10+
* NotoSans-Regular - SIL Open Font License v1.1
11+
* NotoSansThai-Regular - SIL Open Font License v1.1
12+
* Puritan2 - SIL Open Font License v1.1
13+
14+
15+
16+
All the used bold Google Noto fonts have been taken from the https://github.com/googlefonts.

0 commit comments

Comments
 (0)