Skip to content

Commit

Permalink
Properly handle ZapfDingbats font for Type1FontSimple and Type1Standa…
Browse files Browse the repository at this point in the history
…rd14Font and add tests
  • Loading branch information
BobLd committed Jan 5, 2025
1 parent 585e940 commit 4430a01
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 20 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
55 changes: 55 additions & 0 deletions src/UglyToad.PdfPig.Tests/Integration/ZapfDingbatsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
namespace UglyToad.PdfPig.Tests.Integration
{
using System.Linq;

public class ZapfDingbatsTests
{
[Fact]
public void Type1Standard14Font1()
{
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("TIKA-469-0")))
{
var page = document.GetPage(2);
Assert.Contains("●", page.Letters.Select(l => l.Value));
}
}

[Fact]
public void Type1Standard14Font2()
{
// This document does not actually contain circular references
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("MOZILLA-LINK-5251-1")))
{
var page = document.GetPage(1);
Assert.Contains("✁", page.Letters.Select(l => l.Value));
Assert.Contains("✂", page.Letters.Select(l => l.Value));
Assert.Contains("✄", page.Letters.Select(l => l.Value));
Assert.Contains("☎", page.Letters.Select(l => l.Value));
Assert.Contains("✆", page.Letters.Select(l => l.Value));
Assert.Contains("✇", page.Letters.Select(l => l.Value));
}
}

[Fact]
public void Type1FontSimple1()
{
// This document does not actually contain circular references
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("MOZILLA-2775-1")))
{
var page = document.GetPage(11);
Assert.Contains("●", page.Letters.Select(l => l.Value));
}
}

[Fact]
public void Type1FontSimple2()
{
// This document does not actually contain circular references
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("PDFBOX-492-4.jar-8")))
{
var page = document.GetPage(1);
Assert.Contains("\u25a0", page.Letters.Select(l => l.Value));
}
}
}
}
3 changes: 3 additions & 0 deletions src/UglyToad.PdfPig/PdfFonts/Simple/TrueTypeSimpleFont.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ public TrueTypeSimpleFont(

Details = descriptor?.ToDetails(Name?.Data)
?? FontDetails.GetDefault(Name?.Data);

// Assumption is ZapfDingbats is not possible here. We need to change the behaviour if not the case
System.Diagnostics.Debug.Assert(!(encoding is ZapfDingbatsEncoding || Details.Name.Contains("ZapfDingbats")));
}

public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public TrueTypeStandard14FallbackSimpleFont(NameToken name, AdobeFontMetrics fon
fontMetrics.Weight == "Bold",
fontMetrics.Weight == "Bold" ? 700 : FontDetails.DefaultWeight,
fontMetrics.ItalicAngle != 0);

// Assumption is ZapfDingbats is not possible here. We need to change the behaviour if not the case
System.Diagnostics.Debug.Assert(!(encoding is ZapfDingbatsEncoding || Details.Name.Contains("ZapfDingbats")));
}

public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
Expand Down
11 changes: 11 additions & 0 deletions src/UglyToad.PdfPig/PdfFonts/Simple/Type1FontSimple.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ internal sealed class Type1FontSimple : IFont

private readonly TransformationMatrix fontMatrix;

private readonly bool isZapfDingbats;

public NameToken Name { get; }

public bool IsVertical { get; } = false;
Expand Down Expand Up @@ -80,6 +82,7 @@ public Type1FontSimple(
Name = name;
Details = fontDescriptor?.ToDetails(name?.Data)
?? FontDetails.GetDefault(name?.Data);
isZapfDingbats = encoding is ZapfDingbatsEncoding || Details.Name.Contains("ZapfDingbats");
}

public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
Expand Down Expand Up @@ -124,6 +127,14 @@ public bool TryGetUnicode(int characterCode, [NotNullWhen(true)] out string? val

try
{
if (isZapfDingbats)
{
value = GlyphList.ZapfDingbats.NameToUnicode(name);
if (value is not null)
{
return true;
}
}
value = GlyphList.AdobeGlyphList.NameToUnicode(name);
}
catch
Expand Down
38 changes: 18 additions & 20 deletions src/UglyToad.PdfPig/PdfFonts/Simple/Type1Standard14Font.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ internal sealed class Type1Standard14Font : IFont
{
private readonly AdobeFontMetrics standardFontMetrics;
private readonly Encoding encoding;
private readonly bool isZapfDingbats;

public NameToken Name { get; }

Expand All @@ -39,6 +40,7 @@ public Type1Standard14Font(AdobeFontMetrics standardFontMetrics, Encoding? overr
standardFontMetrics.Weight == "Bold",
standardFontMetrics.Weight == "Bold" ? 700 : FontDetails.DefaultWeight,
standardFontMetrics.ItalicAngle != 0);
isZapfDingbats = encoding is ZapfDingbatsEncoding || Details.Name.Contains("ZapfDingbats");
}

public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
Expand All @@ -49,39 +51,35 @@ public int ReadCharacterCode(IInputBytes bytes, out int codeLength)

public bool TryGetUnicode(int characterCode, [NotNullWhen(true)] out string? value)
{
value = null;

var name = encoding.GetName(characterCode);

if (string.Equals(name, GlyphList.NotDefined, StringComparison.OrdinalIgnoreCase))
{
value = null;
return false;
}

if (encoding is ZapfDingbatsEncoding)
try
{
var listed = GlyphList.ZapfDingbats.NameToUnicode(name);
if (isZapfDingbats)
{
value = GlyphList.ZapfDingbats.NameToUnicode(name);

value = listed;
if (value is not null)
{
return true;
}
}

return true;
value = GlyphList.AdobeGlyphList.NameToUnicode(name);
}

if (encoding is StandardEncoding || encoding is SymbolEncoding)
catch
{
var listed = GlyphList.AdobeGlyphList.NameToUnicode(name);

value = listed;

return true;
return false;
}
else
{
Debug.WriteLine($"Warning: Type1Standard14Font with unexpected encoding: '{encoding.EncodingName}' Expected: 'ZapfDingbatsEncoding','SymbolEncoding' or 'StandardEncoding' . Font: '{standardFontMetrics.FontName}'");
var listed = GlyphList.AdobeGlyphList.NameToUnicode(name);

value = listed;

return true;
}
return value is not null;
}

public CharacterBoundingBox GetBoundingBox(int characterCode)
Expand Down
3 changes: 3 additions & 0 deletions src/UglyToad.PdfPig/PdfFonts/Simple/Type3Font.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public Type3Font(NameToken name, PdfRectangle boundingBox, TransformationMatrix
this.widths = widths;
this.toUnicodeCMap = new ToUnicodeCMap(toUnicodeCMap);
Details = FontDetails.GetDefault(name?.Data);

// Assumption is ZapfDingbats is not possible here. We need to change the behaviour if not the case
System.Diagnostics.Debug.Assert(!(encoding is ZapfDingbatsEncoding || Details.Name.Contains("ZapfDingbats")));
}

public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
Expand Down

0 comments on commit 4430a01

Please sign in to comment.