Skip to content

Commit f87cac1

Browse files
vitali-priText-CI
authored andcommitted
Check font glyphs for existence
DEVSIX-2975 Autoported commit. Original commit hash: [cf1eaa783]
1 parent b41dec2 commit f87cac1

File tree

18 files changed

+221
-54
lines changed

18 files changed

+221
-54
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2023 Apryse Group NV
4+
Authors: Apryse Software.
5+
6+
This program is offered under a commercial and under the AGPL license.
7+
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
8+
9+
AGPL licensing:
10+
This program is free software: you can redistribute it and/or modify
11+
it under the terms of the GNU Affero General Public License as published by
12+
the Free Software Foundation, either version 3 of the License, or
13+
(at your option) any later version.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU Affero General Public License for more details.
19+
20+
You should have received a copy of the GNU Affero General Public License
21+
along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
using iText.Test;
24+
25+
namespace iText.IO.Font {
26+
[NUnit.Framework.Category("UnitTest")]
27+
public class PdfEncodingsTest : ExtendedITextTest {
28+
[NUnit.Framework.Test]
29+
public virtual void ConvertToBytesNoEncodingTest() {
30+
NUnit.Framework.Assert.AreEqual(new byte[] { (byte)194 }, PdfEncodings.ConvertToBytes('Â', null));
31+
NUnit.Framework.Assert.AreEqual(new byte[] { (byte)194 }, PdfEncodings.ConvertToBytes('Â', ""));
32+
NUnit.Framework.Assert.AreEqual(new byte[] { (byte)194 }, PdfEncodings.ConvertToBytes('Â', "symboltt"));
33+
}
34+
}
35+
}

itext.tests/itext.kernel.tests/itext/kernel/pdf/canvas/PdfCanvasTest.cs

+26-6
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ public class PdfCanvasTest : ExtendedITextTest {
5757

5858
private const String TITLE = "Empty iText Document";
5959

60-
private sealed class _ContentProvider_83 : PdfCanvasTest.ContentProvider {
61-
public _ContentProvider_83() {
60+
private sealed class _ContentProvider_74 : PdfCanvasTest.ContentProvider {
61+
public _ContentProvider_74() {
6262
}
6363

6464
public void DrawOnCanvas(PdfCanvas canvas, int pageNumber) {
@@ -68,7 +68,7 @@ public void DrawOnCanvas(PdfCanvas canvas, int pageNumber) {
6868
}
6969
}
7070

71-
private static readonly PdfCanvasTest.ContentProvider DEFAULT_CONTENT_PROVIDER = new _ContentProvider_83();
71+
private static readonly PdfCanvasTest.ContentProvider DEFAULT_CONTENT_PROVIDER = new _ContentProvider_74();
7272

7373
[NUnit.Framework.OneTimeSetUp]
7474
public static void BeforeClass() {
@@ -231,12 +231,12 @@ public virtual void Create10PagesDocument() {
231231
public virtual void Create1000PagesDocumentWithText() {
232232
int pageCount = 1000;
233233
String filename = DESTINATION_FOLDER + "1000PagesDocumentWithText.pdf";
234-
CreateStandardDocument(new PdfWriter(filename), pageCount, new _ContentProvider_375());
234+
CreateStandardDocument(new PdfWriter(filename), pageCount, new _ContentProvider_366());
235235
AssertStandardDocument(filename, pageCount);
236236
}
237237

238-
private sealed class _ContentProvider_375 : PdfCanvasTest.ContentProvider {
239-
public _ContentProvider_375() {
238+
private sealed class _ContentProvider_366 : PdfCanvasTest.ContentProvider {
239+
public _ContentProvider_366() {
240240
}
241241

242242
public void DrawOnCanvas(PdfCanvas canvas, int pageNumber) {
@@ -1104,6 +1104,26 @@ public virtual void SetPositiveHorizontalScalingValueTest() {
11041104
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outPdf, cmpPdf, DESTINATION_FOLDER));
11051105
}
11061106

1107+
[NUnit.Framework.Test]
1108+
public virtual void CreateSimpleCanvasWithPdfArrayText() {
1109+
String outPdf = DESTINATION_FOLDER + "createSimpleCanvasWithPdfArrayText.pdf";
1110+
String cmpPdf = SOURCE_FOLDER + "cmp_createSimpleCanvasWithPdfArrayText.pdf";
1111+
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf));
1112+
PdfPage page1 = pdfDoc.AddNewPage();
1113+
PdfCanvas canvas = new PdfCanvas(page1);
1114+
PdfArray pdfArray = new PdfArray();
1115+
pdfArray.Add(new PdfString("ABC"));
1116+
pdfArray.Add(new PdfNumber(-250));
1117+
pdfArray.Add(new PdfString("DFG"));
1118+
//Initialize canvas and write text to it
1119+
canvas.SaveState().BeginText().MoveText(36, 750).SetFontAndSize(PdfFontFactory.CreateFont(StandardFonts.HELVETICA
1120+
), 16).ShowText(pdfArray).EndText().RestoreState();
1121+
canvas.Release();
1122+
pdfDoc.Close();
1123+
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outPdf, cmpPdf, DESTINATION_FOLDER, "diff_"
1124+
));
1125+
}
1126+
11071127
private void CreateStandardDocument(PdfWriter writer, int pageCount, PdfCanvasTest.ContentProvider contentProvider
11081128
) {
11091129
PdfDocument pdfDoc = new PdfDocument(writer);

itext.tests/itext.layout.tests/itext/layout/font/FontSelectorLayoutTest.cs

-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ private static Paragraph CreateParagraph(String textParagraph, String font) {
7979

8080
[NUnit.Framework.Test]
8181
public virtual void UtfToGlyphToUtfRountripTest() {
82-
// See DEVSIX-4945
8382
// this should not throw a null pointer exception
8483
using (PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new MemoryStream()))) {
8584
using (Document doc = new Document(pdfDoc)) {

itext.tests/itext.pdfa.tests/itext/pdfa/PdfAFontTest.cs

+79-37
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ You should have received a copy of the GNU Affero General Public License
3030
using iText.Kernel.Pdf;
3131
using iText.Kernel.Pdf.Canvas;
3232
using iText.Kernel.Utils;
33+
using iText.Layout;
34+
using iText.Layout.Element;
3335
using iText.Pdfa.Exceptions;
3436
using iText.Test;
3537
using iText.Test.Pdfa;
@@ -211,60 +213,68 @@ public virtual void CidFontCheckTest3() {
211213
[NUnit.Framework.Test]
212214
public virtual void SymbolicTtfCharEncodingsPdfA1Test01() {
213215
// encoding must not be specified
214-
CreateDocumentWithFont("symbolicTtfCharEncodingsPdfA1Test01.pdf", "Symbols1.ttf", "", PdfAConformanceLevel
215-
.PDF_A_1B, null);
216+
// Here we produced valid pdfa files in the past by silently removing not valid symbols
217+
// But right now we check for used glyphs which don't exist in the font and throw exception
218+
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => CreateDocumentWithFont(
219+
"symbolicTtfCharEncodingsPdfA1Test01.pdf", "Symbols1.ttf", "", PdfAConformanceLevel.PDF_A_1B));
220+
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.EMBEDDED_FONTS_SHALL_DEFINE_ALL_REFERENCED_GLYPHS
221+
, e.Message);
216222
}
217223

218224
[NUnit.Framework.Test]
219225
public virtual void SymbolicTtfCharEncodingsPdfA1Test02() {
220-
// TODO: DEVSIX-2975 Using only shipped fonts in font provider can result in pdf with no-def glyph and not conforming PDF/A document
221-
String expectedVeraPdfWarning = "VeraPDF verification failed. See verification results: " + UrlUtil.GetNormalizedFileUriString
222-
(DESTINATION_FOLDER + "symbolicTtfCharEncodingsPdfA1Test02.xml");
223226
// if you specify encoding, symbolic font is treated as non-symbolic
224-
CreateDocumentWithFont("symbolicTtfCharEncodingsPdfA1Test02.pdf", "Symbols1.ttf", PdfEncodings.MACROMAN, PdfAConformanceLevel
225-
.PDF_A_1B, expectedVeraPdfWarning);
227+
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => CreateDocumentWithFont(
228+
"symbolicTtfCharEncodingsPdfA1Test02.pdf", "Symbols1.ttf", PdfEncodings.MACROMAN, PdfAConformanceLevel
229+
.PDF_A_1B));
230+
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.EMBEDDED_FONTS_SHALL_DEFINE_ALL_REFERENCED_GLYPHS
231+
, e.Message);
226232
}
227233

228234
[NUnit.Framework.Test]
229235
public virtual void SymbolicTtfCharEncodingsPdfA1Test03() {
230236
// if you specify encoding, symbolic font is treated as non-symbolic
231237
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => CreateDocumentWithFont(
232238
"symbolicTtfCharEncodingsPdfA1Test03.pdf", "Symbols1.ttf", "ISO-8859-1", PdfAConformanceLevel.PDF_A_1B
233-
, null));
234-
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.ALL_NON_SYMBOLIC_TRUE_TYPE_FONT_SHALL_SPECIFY_MAC_ROMAN_OR_WIN_ANSI_ENCODING_AS_THE_ENCODING_ENTRY
239+
));
240+
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.EMBEDDED_FONTS_SHALL_DEFINE_ALL_REFERENCED_GLYPHS
235241
, e.Message);
236242
}
237243

238244
[NUnit.Framework.Test]
239245
public virtual void SymbolicTtfCharEncodingsPdfA1Test04() {
240-
// TODO: DEVSIX-2975 Using only shipped fonts in font provider can result in pdf with no-def glyph and not conforming PDF/A document
241-
String expectedVeraPdfWarning = "VeraPDF verification failed. See verification results: " + UrlUtil.GetNormalizedFileUriString
242-
(DESTINATION_FOLDER + "symbolicTtfCharEncodingsPdfA1Test04.xml");
243-
// emulate behaviour with default WinAnsi, which was present in 7.1
244-
CreateDocumentWithFont("symbolicTtfCharEncodingsPdfA1Test04.pdf", "Symbols1.ttf", PdfEncodings.WINANSI, PdfAConformanceLevel
245-
.PDF_A_1B, expectedVeraPdfWarning);
246+
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => CreateDocumentWithFont(
247+
"symbolicTtfCharEncodingsPdfA1Test04.pdf", "Symbols1.ttf", PdfEncodings.WINANSI, PdfAConformanceLevel.
248+
PDF_A_1B));
249+
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.EMBEDDED_FONTS_SHALL_DEFINE_ALL_REFERENCED_GLYPHS
250+
, e.Message);
246251
}
247252

248253
[NUnit.Framework.Test]
249254
public virtual void SymbolicTtfCharEncodingsPdfA1Test05() {
250255
// Identity-H behaviour should be the same as the default one, starting from 7.2
251-
CreateDocumentWithFont("symbolicTtfCharEncodingsPdfA1Test05.pdf", "Symbols1.ttf", PdfEncodings.IDENTITY_H,
252-
PdfAConformanceLevel.PDF_A_1B, null);
256+
// Here we produced valid pdfa files in the past by silently removing not valid symbols
257+
// But right now we check for used glyphs which don't exist in the font and throw exception
258+
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => CreateDocumentWithFont(
259+
"symbolicTtfCharEncodingsPdfA1Test05.pdf", "Symbols1.ttf", PdfEncodings.IDENTITY_H, PdfAConformanceLevel
260+
.PDF_A_1B));
261+
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.EMBEDDED_FONTS_SHALL_DEFINE_ALL_REFERENCED_GLYPHS
262+
, e.Message);
253263
}
254264

255265
[NUnit.Framework.Test]
256266
public virtual void NonSymbolicTtfCharEncodingsPdfA1Test01() {
257267
// encoding must be either winansi or macroman, by default winansi is used
258268
CreateDocumentWithFont("nonSymbolicTtfCharEncodingsPdfA1Test01.pdf", "FreeSans.ttf", PdfEncodings.WINANSI,
259-
PdfAConformanceLevel.PDF_A_1B, null);
269+
PdfAConformanceLevel.PDF_A_1B);
260270
}
261271

262272
[NUnit.Framework.Test]
263273
public virtual void NonSymbolicTtfCharEncodingsPdfA1Test02() {
264274
// encoding must be either winansi or macroman, by default winansi is used
265275
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => CreateDocumentWithFont(
266276
"nonSymbolicTtfCharEncodingsPdfA1Test02.pdf", "FreeSans.ttf", "ISO-8859-1", PdfAConformanceLevel.PDF_A_2B
267-
, null));
277+
));
268278
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.ALL_NON_SYMBOLIC_TRUE_TYPE_FONT_SHALL_SPECIFY_MAC_ROMAN_ENCODING_OR_WIN_ANSI_ENCODING
269279
, e.Message);
270280
}
@@ -280,24 +290,16 @@ public virtual void NotdefInTrueTypeFontTest() {
280290
PdfFont font = PdfFontFactory.CreateFont(SOURCE_FOLDER + "FreeSans.ttf", "# simple 32 0020 00C5 1987", PdfFontFactory.EmbeddingStrategy
281291
.PREFER_EMBEDDED);
282292
PdfCanvas canvas = new PdfCanvas(doc.AddNewPage());
283-
canvas.SaveState().BeginText().MoveText(36, 786).SetFontAndSize(font, 36).ShowText("\u00C5 \u1987").EndText
284-
().RestoreState();
285-
font = PdfFontFactory.CreateFont(SOURCE_FOLDER + "FreeSans.ttf", PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy
286-
.PREFER_EMBEDDED);
287-
canvas.SaveState().BeginText().MoveText(36, 756).SetFontAndSize(font, 36).ShowText("\u1987").EndText().RestoreState
288-
();
289-
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => doc.Close());
290-
NUnit.Framework.Assert.AreEqual(PdfAConformanceException.ALL_NON_SYMBOLIC_TRUE_TYPE_FONT_SHALL_SPECIFY_MAC_ROMAN_ENCODING_OR_WIN_ANSI_ENCODING
293+
canvas.SaveState().BeginText().MoveText(36, 786).SetFontAndSize(font, 36);
294+
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => canvas.ShowText("\u00C5 \u1987"
295+
));
296+
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.EMBEDDED_FONTS_SHALL_DEFINE_ALL_REFERENCED_GLYPHS
291297
, e.Message);
292298
}
293299

294300
[NUnit.Framework.Test]
295301
public virtual void NotdefFontTest2() {
296-
// TODO: DEVSIX-2975 Using only shipped fonts in font provider can result in pdf with no-def glyph and not conforming PDF/A document
297302
String outPdf = DESTINATION_FOLDER + "notdefFontTest2.pdf";
298-
String cmpPdf = SOURCE_FOLDER + "cmp/PdfAFontTest/notdefFontTest2.pdf";
299-
String expectedVeraPdfWarning = "VeraPDF verification failed. See verification results: " + UrlUtil.GetNormalizedFileUriString
300-
(DESTINATION_FOLDER + "notdefFontTest2.xml");
301303
PdfWriter writer = new PdfWriter(outPdf, new WriterProperties().SetPdfVersion(PdfVersion.PDF_2_0));
302304
Stream @is = new FileStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm", FileMode.Open, FileAccess.Read
303305
);
@@ -306,10 +308,50 @@ public virtual void NotdefFontTest2() {
306308
PdfFont font = PdfFontFactory.CreateFont(SOURCE_FOLDER + "NotoSans-Regular.ttf", "", PdfFontFactory.EmbeddingStrategy
307309
.PREFER_EMBEDDED);
308310
PdfCanvas canvas = new PdfCanvas(doc.AddNewPage());
309-
canvas.SaveState().BeginText().MoveText(36, 786).SetFontAndSize(font, 36).ShowText("\u898B\u7A4D\u3082\u308A"
310-
).EndText().RestoreState();
311-
doc.Close();
312-
CompareResult(outPdf, cmpPdf, expectedVeraPdfWarning);
311+
canvas.SaveState().BeginText().MoveText(36, 786).SetFontAndSize(font, 36);
312+
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => canvas.ShowText("\u898B\u7A4D\u3082\u308A"
313+
));
314+
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.EMBEDDED_FONTS_SHALL_DEFINE_ALL_REFERENCED_GLYPHS
315+
, e.Message);
316+
}
317+
318+
[NUnit.Framework.Test]
319+
public virtual void GlyphLineWithUndefinedGlyphsTest() {
320+
String outPdf = DESTINATION_FOLDER + "glyphLineWithUndefinedGlyphs.pdf";
321+
Stream icm = new FileStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm", FileMode.Open, FileAccess.Read
322+
);
323+
Document document = new Document(new PdfADocument(new PdfWriter(outPdf, new WriterProperties().SetPdfVersion
324+
(PdfVersion.PDF_2_0)), PdfAConformanceLevel.PDF_A_4, new PdfOutputIntent("Custom", "", "http://www.color.org"
325+
, "sRGB ICC preference", icm)));
326+
PdfFont font = PdfFontFactory.CreateFont(SOURCE_FOLDER + "NotoSans-Regular.ttf", "", PdfFontFactory.EmbeddingStrategy
327+
.PREFER_EMBEDDED);
328+
Paragraph p = new Paragraph("\u898B\u7A4D\u3082\u308A");
329+
p.SetFont(font);
330+
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => document.Add(p));
331+
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.EMBEDDED_FONTS_SHALL_DEFINE_ALL_REFERENCED_GLYPHS
332+
, e.Message);
333+
}
334+
335+
[NUnit.Framework.Test]
336+
public virtual void PdfArrayWithUndefinedGlyphsTest() {
337+
String outPdf = DESTINATION_FOLDER + "pdfArrayWithUndefinedGlyphs.pdf";
338+
PdfWriter writer = new PdfWriter(outPdf, new WriterProperties().SetPdfVersion(PdfVersion.PDF_2_0));
339+
Stream @is = new FileStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm", FileMode.Open, FileAccess.Read
340+
);
341+
PdfDocument doc = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_4, new PdfOutputIntent("Custom", "",
342+
"http://www.color.org", "sRGB IEC61966-2.1", @is));
343+
PdfFont font = PdfFontFactory.CreateFont(SOURCE_FOLDER + "NotoSans-Regular.ttf", "", PdfFontFactory.EmbeddingStrategy
344+
.PREFER_EMBEDDED);
345+
PdfCanvas canvas = new PdfCanvas(doc.AddNewPage());
346+
canvas.SaveState().BeginText().MoveText(36, 786).SetFontAndSize(font, 36);
347+
PdfArray pdfArray = new PdfArray();
348+
pdfArray.Add(new PdfString("ABC"));
349+
pdfArray.Add(new PdfNumber(1));
350+
pdfArray.Add(new PdfString("\u898B\u7A4D\u3082\u308A"));
351+
Exception e = NUnit.Framework.Assert.Catch(typeof(PdfAConformanceException), () => canvas.ShowText(pdfArray
352+
));
353+
NUnit.Framework.Assert.AreEqual(PdfaExceptionMessageConstant.EMBEDDED_FONTS_SHALL_DEFINE_ALL_REFERENCED_GLYPHS
354+
, e.Message);
313355
}
314356

315357
[NUnit.Framework.Test]
@@ -565,7 +607,7 @@ public virtual void CheckPdfA4WoffTest() {
565607
}
566608

567609
private void CreateDocumentWithFont(String outFileName, String fontFileName, String encoding, PdfAConformanceLevel
568-
conformanceLevel, String expectedVeraPdfWarning) {
610+
conformanceLevel) {
569611
String outPdf = DESTINATION_FOLDER + outFileName;
570612
String cmpPdf = SOURCE_FOLDER + "cmp/PdfAFontTest/cmp_" + outFileName;
571613
PdfWriter writer = new PdfWriter(outPdf);
@@ -580,7 +622,7 @@ private void CreateDocumentWithFont(String outFileName, String fontFileName, Str
580622
canvas.SaveState().BeginText().MoveText(36, 700).SetFontAndSize(font, 12).ShowText("Hello World").EndText(
581623
).RestoreState();
582624
doc.Close();
583-
CompareResult(outPdf, cmpPdf, expectedVeraPdfWarning);
625+
CompareResult(outPdf, cmpPdf, null);
584626
}
585627

586628
private void CompareResult(String outPdf, String cmpPdf, String expectedVeraPdfWarning) {

itext/itext.io/itext/io/font/PdfEncodings.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ public static byte[] ConvertToBytes(String text, String encoding) {
258258

259259
/// <summary>
260260
/// Converts a
261-
/// <c>String</c>
261+
/// <c>char</c>
262262
/// to a
263263
/// <c>byte</c>
264264
/// array according
@@ -276,7 +276,7 @@ public static byte[] ConvertToBytes(String text, String encoding) {
276276
/// representing the conversion according to the font's encoding
277277
/// </returns>
278278
public static byte[] ConvertToBytes(char ch, String encoding) {
279-
if (encoding == null || encoding.Length == 0) {
279+
if (encoding == null || encoding.Length == 0 || "symboltt".Equals(encoding)) {
280280
return new byte[] { (byte)ch };
281281
}
282282
IntHashtable hash = null;

itext/itext.kernel/itext/kernel/pdf/IsoKey.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public enum IsoKey {
3636
XREF_TABLE,
3737
SIGNATURE,
3838
SIGNATURE_TYPE,
39-
CRYPTO
39+
CRYPTO,
40+
FONT
4041
}
4142
}

0 commit comments

Comments
 (0)