TextRenderInfoUnitTest.java
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2025 Apryse Group NV
Authors: Apryse Software.
This program is offered under a commercial and under the AGPL license.
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
AGPL licensing:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itextpdf.kernel.pdf.canvas;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Matrix;
import com.itextpdf.kernel.pdf.PdfArray;
import com.itextpdf.kernel.pdf.PdfDictionary;
import com.itextpdf.kernel.pdf.PdfName;
import com.itextpdf.kernel.pdf.PdfNumber;
import com.itextpdf.kernel.pdf.PdfObject;
import com.itextpdf.kernel.pdf.PdfString;
import com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo;
import com.itextpdf.test.ExtendedITextTest;
import java.util.Arrays;
import java.util.Stack;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Tag;
@Tag("UnitTest")
public class TextRenderInfoUnitTest extends ExtendedITextTest {
@Test
public void textExtractGlyphAverageWidth() {
String text = "i";
PdfDictionary fontDict = initFontDictWithNotSpecifiedWidthOfSpaceChar();
CanvasGraphicsState gs = new CanvasGraphicsState();
gs.setFont(PdfFontFactory.createFont(fontDict));
gs.setFontSize(12);
TextRenderInfo testTRI = new TextRenderInfo(new PdfString(text), gs, new Matrix(), new Stack<CanvasTag>());
float singleSpaceWidth = testTRI.getSingleSpaceWidth();
float iWidth = testTRI.getUnscaledWidth();
Assertions.assertTrue(iWidth < singleSpaceWidth);
Assertions.assertEquals(6.671999931335449, singleSpaceWidth, 0);
}
private static PdfDictionary initFontDictWithNotSpecifiedWidthOfSpaceChar() {
PdfDictionary fontDict = new PdfDictionary();
// Initializing all the usual font dictionary entries to make this font more "normal".
// The entries below should not affect the test.
fontDict.put(PdfName.BaseFont, new PdfName("GIXYEW+CMMI10"));
fontDict.put(PdfName.Type, PdfName.Font);
fontDict.put(PdfName.LastChar, new PdfNumber(122));
fontDict.put(PdfName.Subtype, PdfName.Type1);
// /ToUnicode is omitted for the sake of test brevity.
// Normally it should be in the font however it's not needed in this test and iText seems to process such font normally.
// fontDict.put(PdfName.ToUnicode, ...);
PdfDictionary fontDescriptor = new PdfDictionary();
fontDescriptor.put(PdfName.Ascent, new PdfNumber(694));
fontDescriptor.put(PdfName.CapHeight, new PdfNumber(683));
fontDescriptor.put(PdfName.Descent, new PdfNumber(-194));
fontDescriptor.put(PdfName.Flags, new PdfNumber(4));
fontDescriptor.put(PdfName.FontBBox, new PdfArray(Arrays.asList(new PdfObject[]{new PdfNumber(-32), new PdfNumber(-250), new PdfNumber(1048), new PdfNumber(750)})));
// normally /FontFile should be in the font, however the situation here is the same as for /ToUnicode.
// fontDescriptor.put(PdfName.FontFile, ...);
fontDescriptor.put(PdfName.FontName, new PdfName("GIXYEW+CMMI10"));
fontDescriptor.put(PdfName.ItalicAngle, new PdfNumber(-14));
fontDescriptor.put(PdfName.StemV, new PdfNumber(72));
fontDescriptor.put(PdfName.Type, PdfName.FontDescriptor);
fontDescriptor.put(PdfName.XHeight, new PdfNumber(431));
fontDict.put(PdfName.FontDescriptor, fontDescriptor);
// Specifying widths and /FirstChar. /MissingWidth is not specified. Here the result is that font does not specify
// whitespace character width.
fontDict.put(PdfName.FirstChar, new PdfNumber(82));
String widths = "759 613 584 682 583 944 828 580 682 388 388 388 1000 1000 416 528" +
" 429 432 520 465 489 477 576 344 411 520 298 878 600 484 503 446 451 468" +
" 361 572 484 715 571 490 465";
PdfArray widthsArray = new PdfArray();
for (String w : widths.split(" ")) {
widthsArray.add(new PdfNumber(Integer.parseInt(w)));
}
fontDict.put(PdfName.Widths, widthsArray);
return fontDict;
}
}