mirror of
https://github.com/UglyToad/PdfPig.git
synced 2026-03-10 00:23:29 +08:00
Fix CID / CFF font glyphs and add tests
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
/// as the local (per font) and global (per font set) subroutines.
|
||||
/// The CharStrings are lazily evaluated.
|
||||
/// </summary>
|
||||
internal class Type2CharStrings
|
||||
internal sealed class Type2CharStrings
|
||||
{
|
||||
private readonly object locker = new object();
|
||||
private readonly Dictionary<string, Type2Glyph> glyphs = new Dictionary<string, Type2Glyph>();
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
if (!CharStrings.TryGetValue(name, out var sequence))
|
||||
{
|
||||
if (!CharStrings.TryGetValue(".notdef", out sequence))
|
||||
if (!CharStrings.TryGetValue(GlyphList.NotDefined, out sequence))
|
||||
{
|
||||
throw new InvalidOperationException($"No charstring sequence with the name /{name} in this font.");
|
||||
}
|
||||
@@ -149,7 +149,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
public class CommandSequence
|
||||
public sealed class CommandSequence
|
||||
{
|
||||
public IReadOnlyList<float> Values { get; }
|
||||
public IReadOnlyList<CommandIdentifier> CommandIdentifiers { get; }
|
||||
@@ -157,7 +157,6 @@
|
||||
/// <summary>
|
||||
/// The ordered list of numbers and commands for a Type 2 charstring or subroutine.
|
||||
/// </summary>
|
||||
|
||||
public CommandSequence(IReadOnlyList<float> values, IReadOnlyList<CommandIdentifier> commandIdentifiers)
|
||||
{
|
||||
Values = values;
|
||||
@@ -218,7 +217,7 @@
|
||||
/// Since Type 2 CharStrings may define their width as the first argument (as a delta from the font's nominal width X)
|
||||
/// we can retrieve both details for the Type 2 glyph.
|
||||
/// </summary>
|
||||
internal class Type2Glyph
|
||||
internal sealed class Type2Glyph
|
||||
{
|
||||
/// <summary>
|
||||
/// The path of the glyph.
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
public virtual string GetNameByStringId(int stringId)
|
||||
{
|
||||
return GlyphIdToStringIdAndName.Single(x => x.Value.stringId == stringId).Value.name;
|
||||
return GlyphIdToStringIdAndName.SingleOrDefault(x => x.Value.stringId == stringId).Value.name;
|
||||
}
|
||||
|
||||
public virtual int GetStringIdByGlyphId(int glyphId)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
{
|
||||
if (!codeToNameMap.TryGetValue(code, out var name))
|
||||
{
|
||||
return ".notdef";
|
||||
return NotDefined;
|
||||
}
|
||||
|
||||
return name;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
/// <summary>
|
||||
/// The font matrix for this font.
|
||||
/// </summary>
|
||||
public TransformationMatrix FontMatrix => TopDictionary.FontMatrix;
|
||||
public TransformationMatrix FontMatrix => TopDictionary.FontMatrix.HasValue ? TopDictionary.FontMatrix.Value : TransformationMatrix.FromValues(0.001, 0, 0, 0.001, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// The value of Weight from the top dictionary or <see langword="null"/>.
|
||||
@@ -50,6 +50,32 @@
|
||||
Encoding = fontEncoding;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the character name. Returns <c>null</c> if cannot be processed.
|
||||
/// </summary>
|
||||
public string GetCharacterName(int characterCode, bool isCid)
|
||||
{
|
||||
if (Encoding != null)
|
||||
{
|
||||
return Encoding.GetName(characterCode);
|
||||
}
|
||||
|
||||
if (Charset.IsCidCharset || isCid)
|
||||
{
|
||||
return Charset?.GetNameByStringId(characterCode);
|
||||
}
|
||||
|
||||
string characterName = GlyphList.AdobeGlyphList.UnicodeCodePointToName(characterCode);
|
||||
|
||||
if (characterName.Equals(GlyphList.NotDefined, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// BobLD: Not tested
|
||||
return Charset?.GetNameByStringId(characterCode);
|
||||
}
|
||||
|
||||
return characterName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the bounding box for the character with the given name.
|
||||
/// </summary>
|
||||
@@ -143,9 +169,17 @@
|
||||
{
|
||||
return PrivateDictionary.NominalWidthX;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Font Matrix for the corresponding character name, if available. Return <c>null</c> if not.
|
||||
/// </summary>
|
||||
public virtual TransformationMatrix? GetFontMatrix(string characterName)
|
||||
{
|
||||
return TopDictionary.FontMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
internal class CompactFontFormatCidFont : CompactFontFormatFont
|
||||
internal sealed class CompactFontFormatCidFont : CompactFontFormatFont
|
||||
{
|
||||
public IReadOnlyList<CompactFontFormatTopLevelDictionary> FontDictionaries { get; }
|
||||
public IReadOnlyList<CompactFontFormatPrivateDictionary> PrivateDictionaries { get; }
|
||||
@@ -183,6 +217,26 @@
|
||||
return dictionary.NominalWidthX;
|
||||
}
|
||||
|
||||
public override TransformationMatrix? GetFontMatrix(string characterName)
|
||||
{
|
||||
// BobLd: It seems PdfBox just returns TopDictionary.FontMatrix
|
||||
// But see https://bugs.ghostscript.com/show_bug.cgi?id=690724
|
||||
// and https://github.com/veraPDF/veraPDF-library/issues/1010
|
||||
// TODO - We might need to multiply both matrices together
|
||||
|
||||
if (TopDictionary.FontMatrix is not null)
|
||||
{
|
||||
return TopDictionary.FontMatrix;
|
||||
}
|
||||
|
||||
if (!TryGetFontDictionaryForCharacter(characterName, out var dictionary))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return dictionary.FontMatrix;
|
||||
}
|
||||
|
||||
private bool TryGetPrivateDictionaryForCharacter(string characterName, out CompactFontFormatPrivateDictionary dictionary)
|
||||
{
|
||||
dictionary = null;
|
||||
@@ -199,5 +253,22 @@
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetFontDictionaryForCharacter(string characterName, out CompactFontFormatTopLevelDictionary dictionary)
|
||||
{
|
||||
dictionary = null;
|
||||
|
||||
var glyphId = Charset.GetGlyphIdByName(characterName);
|
||||
|
||||
var fd = FdSelect.GetFontDictionaryIndex(glyphId);
|
||||
if (fd == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dictionary = FontDictionaries[fd];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,16 +65,11 @@
|
||||
/// <summary>
|
||||
/// Get the name for the character with the given character code from the font.
|
||||
/// </summary>
|
||||
public string GetCharacterName(int characterCode)
|
||||
public string GetCharacterName(int characterCode, bool isCid)
|
||||
{
|
||||
var font = FirstFont;
|
||||
var name = FirstFont.GetCharacterName(characterCode, isCid);
|
||||
|
||||
if (font.Encoding != null)
|
||||
{
|
||||
return font.Encoding.GetName(characterCode);
|
||||
}
|
||||
|
||||
return ".notdef";
|
||||
return name ?? GlyphList.NotDefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
internal class CompactFontFormatFormat0Encoding : CompactFontFormatBuiltInEncoding
|
||||
internal sealed class CompactFontFormatFormat0Encoding : CompactFontFormatBuiltInEncoding
|
||||
{
|
||||
public CompactFontFormatFormat0Encoding(IReadOnlyList<(int code, int sid, string str)> values,
|
||||
IReadOnlyList<Supplement> supplements) : base(supplements)
|
||||
{
|
||||
Add(0, 0, ".notdef");
|
||||
Add(0, 0, NotDefined);
|
||||
|
||||
foreach (var value in values)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
internal class CompactFontFormatFormat1Encoding : CompactFontFormatBuiltInEncoding
|
||||
internal sealed class CompactFontFormatFormat1Encoding : CompactFontFormatBuiltInEncoding
|
||||
{
|
||||
public int NumberOfRanges { get; set; }
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
{
|
||||
NumberOfRanges = numberOfRanges;
|
||||
|
||||
Add(0, 0, ".notdef");
|
||||
Add(0, 0, NotDefined);
|
||||
|
||||
foreach (var value in values)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
using Core;
|
||||
|
||||
internal class CompactFontFormatTopLevelDictionary
|
||||
internal sealed class CompactFontFormatTopLevelDictionary
|
||||
{
|
||||
public const int UnsetOffset = -1;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
public CompactFontFormatCharStringType CharStringType { get; set; } = CompactFontFormatCharStringType.Type2;
|
||||
|
||||
public TransformationMatrix FontMatrix { get; set; } = TransformationMatrix.FromValues(0.001, 0, 0, 0.001, 0, 0);
|
||||
public TransformationMatrix? FontMatrix { get; set; }
|
||||
|
||||
public decimal StrokeWidth { get; set; }
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
internal class CidFontOperators
|
||||
internal sealed class CidFontOperators
|
||||
{
|
||||
public RegistryOrderingSupplement Ros { get; set; }
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
public string FontName { get; set; }
|
||||
}
|
||||
|
||||
internal class RegistryOrderingSupplement
|
||||
internal sealed class RegistryOrderingSupplement
|
||||
{
|
||||
public string Registry { get; set; }
|
||||
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
/// </summary>
|
||||
public abstract class Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// <c>.notdef</c>.
|
||||
/// </summary>
|
||||
protected internal const string NotDefined = ".notdef";
|
||||
|
||||
/// <summary>
|
||||
/// Mutable code to name map.
|
||||
/// </summary>
|
||||
@@ -24,7 +29,7 @@
|
||||
protected readonly Dictionary<string, int> NameToCode = new Dictionary<string, int>(250);
|
||||
|
||||
/// <summary>
|
||||
/// Maps from names to character cocdes.
|
||||
/// Maps from names to character codes.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, int> NameToCodeMap => NameToCode;
|
||||
|
||||
@@ -48,7 +53,7 @@
|
||||
{
|
||||
return CodeToName.ContainsKey(code);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the character name corresponding to the given code.
|
||||
/// </summary>
|
||||
@@ -56,17 +61,16 @@
|
||||
{
|
||||
if (!CodeToName.TryGetValue(code, out var name))
|
||||
{
|
||||
return ".notdef";
|
||||
return NotDefined;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the character code from name
|
||||
/// Get the character code from name
|
||||
/// </summary>
|
||||
/// <param name="name">Character name (eg. euro, ampersand, A, space)</param>
|
||||
/// <param name="name">Character name (e.g. euro, ampersand, A, space)</param>
|
||||
/// <returns>-1 if not found otherwise the character code</returns>
|
||||
public virtual int GetCode(string name)
|
||||
{
|
||||
@@ -90,7 +94,7 @@
|
||||
NameToCode[name] = code;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a known encoding instance with the given name.
|
||||
/// </summary>
|
||||
|
||||
@@ -11,7 +11,10 @@
|
||||
/// </summary>
|
||||
public class GlyphList
|
||||
{
|
||||
private const string NotDefined = ".notdef";
|
||||
/// <summary>
|
||||
/// <c>.notdef</c>.
|
||||
/// </summary>
|
||||
public const string NotDefined = ".notdef";
|
||||
|
||||
private readonly IReadOnlyDictionary<string, string> nameToUnicode;
|
||||
private readonly IReadOnlyDictionary<string, string> unicodeToName;
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
/// </summary>
|
||||
public bool TryGetPath(int characterCode, Func<int, int?> characterCodeToGlyphId, out IReadOnlyList<PdfSubpath> path)
|
||||
{
|
||||
path = EmptyArray<PdfSubpath>.Instance;
|
||||
path = null;
|
||||
|
||||
if (!TryGetGlyphIndex(characterCode, characterCodeToGlyphId, out var index)
|
||||
|| TableRegister.GlyphTable == null)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
internal class Type1CharstringDecryptedBytes
|
||||
internal sealed class Type1CharstringDecryptedBytes
|
||||
{
|
||||
public IReadOnlyList<byte> Bytes { get; }
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
{
|
||||
Bytes = bytes ?? throw new ArgumentNullException(nameof(bytes));
|
||||
Index = index;
|
||||
Name = ".notdef";
|
||||
Name = GlyphList.NotDefined;
|
||||
Source = SourceType.Subroutine;
|
||||
}
|
||||
|
||||
|
||||
BIN
src/UglyToad.PdfPig.Tests/Integration/Documents/FontMatrix-1.pdf
Normal file
BIN
src/UglyToad.PdfPig.Tests/Integration/Documents/FontMatrix-1.pdf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,13 +1,17 @@
|
||||
namespace UglyToad.PdfPig.Tests.Integration.VisualVerification
|
||||
{
|
||||
using PdfPig.Core;
|
||||
using SkiaSharp;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UglyToad.PdfPig.Tests.Integration.VisualVerification.SkiaHelpers;
|
||||
using Xunit;
|
||||
|
||||
public class GenerateLetterGlyphImages
|
||||
{
|
||||
private const bool RenderGlyphRectangle = true;
|
||||
|
||||
private const string NonLatinAcrobatDistiller = "Single Page Non Latin - from acrobat distiller";
|
||||
private const string SingleGoogleDrivePage = "Single Page Simple - from google drive";
|
||||
private const string SinglePageFormattedType0Content = "Type0 Font";
|
||||
@@ -23,10 +27,12 @@
|
||||
|
||||
private const string OutputPath = "ImagesGlyphs";
|
||||
|
||||
private const float Scale = 2f;
|
||||
private const float Scale = 2.5f;
|
||||
|
||||
private static readonly SKMatrix ScaleMatrix = SKMatrix.CreateScale(Scale, Scale);
|
||||
|
||||
private static readonly SKPaint redPaint = new SKPaint() { Color = SKColors.Crimson, StrokeWidth = 1 };
|
||||
|
||||
public GenerateLetterGlyphImages()
|
||||
{
|
||||
if (!Directory.Exists(OutputPath))
|
||||
@@ -56,17 +62,28 @@
|
||||
document.AddPageFactory<SKPicture, SkiaGlyphPageFactory>();
|
||||
|
||||
var page = document.GetPage(pageNo);
|
||||
var size = new SKSizeI((int)(page.Width * Scale), (int)(page.Height * Scale));
|
||||
|
||||
using (var picture = document.GetPage<SKPicture>(pageNo))
|
||||
using (var image = SKImage.FromPicture(picture, size, ScaleMatrix))
|
||||
using (var bmp = SKBitmap.FromImage(image))
|
||||
using (var canvas = new SKCanvas(bmp))
|
||||
{
|
||||
Assert.NotNull(picture);
|
||||
|
||||
if (RenderGlyphRectangle)
|
||||
{
|
||||
foreach (var letter in page.Letters)
|
||||
{
|
||||
DrawRectangle(letter.GlyphRectangle, canvas, redPaint, size.Height, Scale);
|
||||
}
|
||||
}
|
||||
|
||||
var imageName = $"{file}_{pageNo}.png";
|
||||
var savePath = Path.Combine(OutputPath, imageName);
|
||||
|
||||
using (var fs = new FileStream(savePath, FileMode.Create))
|
||||
using (var image = SKImage.FromPicture(picture, new SKSizeI((int)(page.Width * Scale), (int)(page.Height * Scale)), ScaleMatrix))
|
||||
using (SKData d = image.Encode(SKEncodedImageFormat.Png, 100))
|
||||
using (var d = bmp.Encode(SKEncodedImageFormat.Png, 100))
|
||||
{
|
||||
d.SaveTo(fs);
|
||||
}
|
||||
@@ -74,6 +91,174 @@
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawRectangle(PdfRectangle rectangle, SKCanvas graphics, SKPaint pen, int imageHeight, double scale)
|
||||
{
|
||||
int GetY(PdfPoint p)
|
||||
{
|
||||
return imageHeight - (int)(p.Y * scale);
|
||||
}
|
||||
|
||||
SKPoint GetPoint(PdfPoint p)
|
||||
{
|
||||
return new SKPoint((int)(p.X * scale), GetY(p));
|
||||
}
|
||||
|
||||
graphics.DrawLine(GetPoint(rectangle.BottomLeft), GetPoint(rectangle.BottomRight), pen);
|
||||
graphics.DrawLine(GetPoint(rectangle.BottomRight), GetPoint(rectangle.TopRight), pen);
|
||||
graphics.DrawLine(GetPoint(rectangle.TopRight), GetPoint(rectangle.TopLeft), pen);
|
||||
graphics.DrawLine(GetPoint(rectangle.TopLeft), GetPoint(rectangle.BottomLeft), pen);
|
||||
}
|
||||
|
||||
// veraPDF_Issue1010_x -> https://github.com/veraPDF/veraPDF-library/issues/1010
|
||||
[Fact(Skip = "Text is in annotations")]
|
||||
public void veraPDF_Issue1010_1()
|
||||
{
|
||||
Run("FontMatrix-1");
|
||||
}
|
||||
|
||||
[Fact(Skip = "Skipping for the moment")]
|
||||
public void veraPDF_Issue1010_2()
|
||||
{
|
||||
Run("FontMatrix-otf");
|
||||
}
|
||||
|
||||
[Fact(Skip = "Skipping for the moment")]
|
||||
public void veraPDF_Issue1010_3()
|
||||
{
|
||||
Run("FontMatrix-raw");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void veraPDF_Issue1010_4()
|
||||
{
|
||||
Run("felltypes-test");
|
||||
}
|
||||
|
||||
[Fact(Skip = "Skipping for the moment")]
|
||||
public void veraPDF_Issue1010_5()
|
||||
{
|
||||
Run("FontMatrix-otf-bad-hmtx");
|
||||
}
|
||||
|
||||
[Fact(Skip = "Text is in annotations")]
|
||||
public void veraPDF_Issue1010_6()
|
||||
{
|
||||
Run("FontMatrix-concat");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmbeddedCidFont_1()
|
||||
{
|
||||
Run("GHOSTSCRIPT-696547-0.zip-7");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmbeddedCidFont_2()
|
||||
{
|
||||
Run("GHOSTSCRIPT-696547-0.zip-9");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmbeddedCidFont_Music_1()
|
||||
{
|
||||
Run("GHOSTSCRIPT-696171-0");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void pdf995_1()
|
||||
{
|
||||
Run("GHOSTSCRIPT-699035-0");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void pdf995_3()
|
||||
{
|
||||
Run("GHOSTSCRIPT-699035-0", 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmbeddedType1Cid_1()
|
||||
{
|
||||
Run("GHOSTSCRIPT-697507-0");
|
||||
}
|
||||
|
||||
[Fact(Skip = "Glyphs cannot be rendered")]
|
||||
public void EmbeddedType1Cid_MatrixIssue()
|
||||
{
|
||||
// It seems it's correct that the glyphs cannot be rendered
|
||||
// Leaving it there just in case
|
||||
Run("GHOSTSCRIPT-698168-0");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmbeddedType1Cid_2()
|
||||
{
|
||||
Run("GHOSTSCRIPT-698721-0.zip-6");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmbeddedType1Cid_3()
|
||||
{
|
||||
Run("GHOSTSCRIPT-699554-0.zip-4");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmbeddedType1Cid_4()
|
||||
{
|
||||
Run("GHOSTSCRIPT-700931-0.7z-5");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmbeddedType1_PatternColor_1()
|
||||
{
|
||||
Run("GHOSTSCRIPT-698721-1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RepresentativeWindEnergyDeals()
|
||||
{
|
||||
// Colors look wrong but they are correct as we do not support ICC profile color space.
|
||||
// The colors are the same as when the document is opened in pdf.js (Firefox).
|
||||
Run("GHOSTSCRIPT-702013-1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Psion()
|
||||
{
|
||||
Run("GHOSTSCRIPT-700236-1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RabobankWestland()
|
||||
{
|
||||
Run("GHOSTSCRIPT-700125-1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MammaMia()
|
||||
{
|
||||
Run("GHOSTSCRIPT-699375-5");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InstallingMuAndPygameZero()
|
||||
{
|
||||
// Still an issue with some of the glyphs
|
||||
Run("GHOSTSCRIPT-700139-0");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FolhaDeLondrina()
|
||||
{
|
||||
Run("GHOSTSCRIPT-699488-0");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LithgowHighSchool()
|
||||
{
|
||||
Run("GHOSTSCRIPT-700370-2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TIKA_1552_0_4()
|
||||
{
|
||||
@@ -83,7 +268,7 @@
|
||||
[Fact]
|
||||
public void TIKA_1552_0_3()
|
||||
{
|
||||
Run("TIKA-1552-0",3);
|
||||
Run("TIKA-1552-0", 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -119,6 +304,7 @@
|
||||
[Fact]
|
||||
public void SinglePageSimpleFromInkscape()
|
||||
{
|
||||
// Issue with Glyph related to Bézier curves in PdfPig
|
||||
Run(SingleInkscapePage);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,19 +8,20 @@
|
||||
|
||||
internal static class SkiaExtensions
|
||||
{
|
||||
public static SKMatrix ToSkMatrix(this TransformationMatrix transformationMatrix)
|
||||
public static SKMatrix ToSKMatrix(this TransformationMatrix transformationMatrix)
|
||||
{
|
||||
return new SKMatrix((float)transformationMatrix.A, (float)transformationMatrix.C, (float)transformationMatrix.E,
|
||||
(float)transformationMatrix.B, (float)transformationMatrix.D, (float)transformationMatrix.F,
|
||||
0, 0, 1);
|
||||
}
|
||||
|
||||
public static SKColor ToSKColor(this IColor? pdfColor, decimal alpha)
|
||||
public static SKColor ToSKColor(this IColor pdfColor, decimal alpha)
|
||||
{
|
||||
var color = SKColors.Black;
|
||||
if (pdfColor != null)
|
||||
if (pdfColor != null && pdfColor is not PatternColor)
|
||||
{
|
||||
var (r, g, b) = pdfColor.ToRGBValues();
|
||||
|
||||
color = new SKColor(Convert.ToByte(r * 255), Convert.ToByte(g * 255), Convert.ToByte(b * 255));
|
||||
}
|
||||
|
||||
|
||||
@@ -103,9 +103,9 @@
|
||||
TransformationMatrix textMatrix,
|
||||
TransformationMatrix transformationMatrix)
|
||||
{
|
||||
var transformMatrix = renderingMatrix.ToSkMatrix()
|
||||
.PostConcat(textMatrix.ToSkMatrix())
|
||||
.PostConcat(transformationMatrix.ToSkMatrix())
|
||||
var transformMatrix = renderingMatrix.ToSKMatrix()
|
||||
.PostConcat(textMatrix.ToSKMatrix())
|
||||
.PostConcat(transformationMatrix.ToSKMatrix())
|
||||
.PostConcat(yAxisFlipMatrix);
|
||||
|
||||
var style = textRenderingMode.ToSKPaintStyle();
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
|
||||
PdfVector GetDisplacementVector(int characterIdentifier);
|
||||
|
||||
TransformationMatrix GetFontMatrix(int characterIdentifier);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the glyph path for the given character code.
|
||||
/// </summary>
|
||||
|
||||
@@ -19,10 +19,15 @@
|
||||
|
||||
bool TryGetBoundingAdvancedWidth(int characterIdentifier, out double width);
|
||||
|
||||
bool TryGetPath(int characterName, out IReadOnlyList<PdfSubpath> path);
|
||||
bool TryGetPath(int characterCode, out IReadOnlyList<PdfSubpath> path);
|
||||
|
||||
bool TryGetPath(int characterCode, Func<int, int?> characterCodeToGlyphId, out IReadOnlyList<PdfSubpath> path);
|
||||
|
||||
int GetFontMatrixMultiplier();
|
||||
|
||||
/// <summary>
|
||||
/// Try to get the font matrix if available.
|
||||
/// </summary>
|
||||
bool TryGetFontMatrix(int characterCode, out TransformationMatrix? matrix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Core;
|
||||
using Fonts;
|
||||
using Fonts.CompactFontFormat;
|
||||
|
||||
internal class PdfCidCompactFontFormatFont : ICidFontProgram
|
||||
internal sealed class PdfCidCompactFontFormatFont : ICidFontProgram
|
||||
{
|
||||
private readonly CompactFontFormatFontCollection fontCollection;
|
||||
|
||||
@@ -51,13 +52,13 @@
|
||||
|
||||
var font = GetFont();
|
||||
|
||||
if (font.Encoding == null)
|
||||
var characterName = GetCharacterName(characterIdentifier);
|
||||
|
||||
if (string.Equals(characterName, GlyphList.NotDefined, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var characterName = GetCharacterName(characterIdentifier);
|
||||
|
||||
boundingBox = font.GetCharacterBoundingBox(characterName) ?? new PdfRectangle(0, 0, 500, 0);
|
||||
|
||||
return true;
|
||||
@@ -83,16 +84,26 @@
|
||||
return 1000;
|
||||
}
|
||||
|
||||
public bool TryGetFontMatrix(int characterCode, out TransformationMatrix? matrix)
|
||||
{
|
||||
var font = GetFont();
|
||||
var name = font.GetCharacterName(characterCode, true);
|
||||
if (name == null)
|
||||
{
|
||||
matrix = null;
|
||||
return false;
|
||||
}
|
||||
matrix = font.GetFontMatrix(name);
|
||||
return matrix.HasValue;
|
||||
}
|
||||
|
||||
public string GetCharacterName(int characterCode)
|
||||
{
|
||||
var font = GetFont();
|
||||
|
||||
if (font.Encoding != null)
|
||||
{
|
||||
return font.Encoding.GetName(characterCode);
|
||||
}
|
||||
var name = font.GetCharacterName(characterCode, true);
|
||||
|
||||
return ".notdef";
|
||||
return name ?? GlyphList.NotDefined;
|
||||
}
|
||||
|
||||
private CompactFontFormatFont GetFont()
|
||||
@@ -109,17 +120,17 @@
|
||||
|
||||
public bool TryGetPath(int characterCode, out IReadOnlyList<PdfSubpath> path)
|
||||
{
|
||||
path = EmptyArray<PdfSubpath>.Instance;
|
||||
path = null;
|
||||
|
||||
var font = GetFont();
|
||||
|
||||
if (font.Encoding == null)
|
||||
var characterName = GetCharacterName(characterCode);
|
||||
|
||||
if (string.Equals(characterName, GlyphList.NotDefined, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var characterName = GetCharacterName(characterCode);
|
||||
|
||||
if (font.TryGetPath(characterName, out path))
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
using Fonts.TrueType;
|
||||
using Fonts.TrueType.Tables;
|
||||
|
||||
internal class PdfCidTrueTypeFont : ICidFontProgram
|
||||
internal sealed class PdfCidTrueTypeFont : ICidFontProgram
|
||||
{
|
||||
private readonly TrueTypeFont font;
|
||||
|
||||
@@ -35,6 +35,13 @@
|
||||
|
||||
public int GetFontMatrixMultiplier() => font.GetUnitsPerEm();
|
||||
|
||||
public bool TryGetFontMatrix(int characterCode, out TransformationMatrix? matrix)
|
||||
{
|
||||
// We don't have a matrix here
|
||||
matrix = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetPath(int characterCode, out IReadOnlyList<PdfSubpath> path) => font.TryGetPath(characterCode, out path);
|
||||
|
||||
public bool TryGetPath(int characterCode, Func<int, int?> characterCodeToGlyphId, out IReadOnlyList<PdfSubpath> path)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Core;
|
||||
using Geometry;
|
||||
using Tokens;
|
||||
@@ -11,7 +12,7 @@
|
||||
/// Type 0 CID fonts contain glyph descriptions based on the
|
||||
/// Adobe Type 1 font format.
|
||||
/// </summary>
|
||||
internal class Type0CidFont : ICidFont
|
||||
internal sealed class Type0CidFont : ICidFont
|
||||
{
|
||||
private readonly ICidFontProgram fontProgram;
|
||||
private readonly VerticalWritingMetrics verticalWritingMetrics;
|
||||
@@ -26,8 +27,8 @@
|
||||
|
||||
public CharacterIdentifierSystemInfo SystemInfo { get; }
|
||||
|
||||
public FontDetails Details => fontProgram?.Details ?? Descriptor?.ToDetails(BaseFont?.Data)
|
||||
?? FontDetails.GetDefault(BaseFont?.Data);
|
||||
public FontDetails Details => fontProgram?.Details ?? Descriptor?.ToDetails(BaseFont?.Data)
|
||||
?? FontDetails.GetDefault(BaseFont?.Data);
|
||||
|
||||
public TransformationMatrix FontMatrix { get; }
|
||||
|
||||
@@ -37,10 +38,13 @@
|
||||
|
||||
public IReadOnlyDictionary<int, double> Widths { get; }
|
||||
|
||||
public Type0CidFont(ICidFontProgram fontProgram, NameToken type, NameToken subType, NameToken baseFont,
|
||||
public Type0CidFont(ICidFontProgram fontProgram,
|
||||
NameToken type,
|
||||
NameToken subType,
|
||||
NameToken baseFont,
|
||||
CharacterIdentifierSystemInfo systemInfo,
|
||||
FontDescriptor descriptor,
|
||||
VerticalWritingMetrics verticalWritingMetrics,
|
||||
FontDescriptor descriptor,
|
||||
VerticalWritingMetrics verticalWritingMetrics,
|
||||
IReadOnlyDictionary<int, double> widths,
|
||||
double? defaultWidth)
|
||||
{
|
||||
@@ -80,7 +84,7 @@
|
||||
{
|
||||
return defaultWidth.Value;
|
||||
}
|
||||
|
||||
|
||||
if (Descriptor == null)
|
||||
{
|
||||
return 1000;
|
||||
@@ -132,6 +136,16 @@
|
||||
return verticalWritingMetrics.GetDisplacementVector(characterIdentifier);
|
||||
}
|
||||
|
||||
public TransformationMatrix GetFontMatrix(int characterIdentifier)
|
||||
{
|
||||
if (fontProgram == null)
|
||||
{
|
||||
return FontMatrix;
|
||||
}
|
||||
|
||||
return fontProgram.TryGetFontMatrix(characterIdentifier, out var m) ? m.Value : FontMatrix;
|
||||
}
|
||||
|
||||
public bool TryGetPath(int characterCode, out IReadOnlyList<PdfSubpath> path)
|
||||
{
|
||||
path = null;
|
||||
@@ -142,7 +156,7 @@
|
||||
|
||||
return fontProgram.TryGetPath(characterCode, out path);
|
||||
}
|
||||
|
||||
|
||||
public bool TryGetPath(int characterCode, Func<int, int?> characterCodeToGlyphId, out IReadOnlyList<PdfSubpath> path)
|
||||
{
|
||||
path = null;
|
||||
@@ -156,12 +170,36 @@
|
||||
|
||||
public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList<PdfSubpath> path)
|
||||
{
|
||||
return TryGetPath(characterCode, out path);
|
||||
path = null;
|
||||
if (fontProgram == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fontProgram.TryGetPath(characterCode, out path))
|
||||
{
|
||||
path = GetFontMatrix(characterCode).Transform(path).ToArray();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetNormalisedPath(int characterCode, Func<int, int?> characterCodeToGlyphId, out IReadOnlyList<PdfSubpath> path)
|
||||
{
|
||||
return TryGetPath(characterCode, characterCodeToGlyphId, out path);
|
||||
path = null;
|
||||
if (fontProgram == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fontProgram.TryGetPath(characterCode, characterCodeToGlyphId, out path))
|
||||
{
|
||||
path = GetFontMatrix(characterCode).Transform(path).ToArray();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
/// Type 2 CID fonts contains glyph descriptions based on
|
||||
/// the TrueType font format.
|
||||
/// </summary>
|
||||
internal class Type2CidFont : ICidFont
|
||||
internal sealed class Type2CidFont : ICidFont
|
||||
{
|
||||
private readonly ICidFontProgram fontProgram;
|
||||
private readonly VerticalWritingMetrics verticalWritingMetrics;
|
||||
@@ -35,10 +35,14 @@
|
||||
public FontDescriptor Descriptor { get; }
|
||||
|
||||
public FontDetails Details => fontProgram?.Details ?? Descriptor?.ToDetails(BaseFont?.Data)
|
||||
?? FontDetails.GetDefault(BaseFont?.Data);
|
||||
?? FontDetails.GetDefault(BaseFont?.Data);
|
||||
|
||||
public Type2CidFont(NameToken type, NameToken subType, NameToken baseFont, CharacterIdentifierSystemInfo systemInfo,
|
||||
FontDescriptor descriptor, ICidFontProgram fontProgram,
|
||||
public Type2CidFont(NameToken type,
|
||||
NameToken subType,
|
||||
NameToken baseFont,
|
||||
CharacterIdentifierSystemInfo systemInfo,
|
||||
FontDescriptor descriptor,
|
||||
ICidFontProgram fontProgram,
|
||||
VerticalWritingMetrics verticalWritingMetrics,
|
||||
IReadOnlyDictionary<int, double> widths,
|
||||
double? defaultWidth,
|
||||
@@ -71,6 +75,7 @@
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
// TODO: Read the font width from the font program.
|
||||
return GetWidthFromDictionary(characterIdentifier);
|
||||
}
|
||||
@@ -117,6 +122,11 @@
|
||||
return verticalWritingMetrics.GetDisplacementVector(characterIdentifier);
|
||||
}
|
||||
|
||||
public TransformationMatrix GetFontMatrix(int characterIdentifier)
|
||||
{
|
||||
return FontMatrix;
|
||||
}
|
||||
|
||||
public bool TryGetPath(int characterCode, out IReadOnlyList<PdfSubpath> path) => TryGetPath(characterCode, cidToGid.GetGlyphIndex, out path);
|
||||
|
||||
public bool TryGetPath(int characterCode, Func<int, int?> characterCodeToGlyphId, out IReadOnlyList<PdfSubpath> path)
|
||||
@@ -132,18 +142,24 @@
|
||||
|
||||
public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList<PdfSubpath> path)
|
||||
{
|
||||
if (!TryGetPath(characterCode, out path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
path = FontMatrix.Transform(path).ToList();
|
||||
return true;
|
||||
return TryGetNormalisedPath(characterCode, cidToGid.GetGlyphIndex, out path);
|
||||
}
|
||||
|
||||
public bool TryGetNormalisedPath(int characterCode, Func<int, int?> characterCodeToGlyphId, out IReadOnlyList<PdfSubpath> path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
path = null;
|
||||
if (fontProgram == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fontProgram.TryGetPath(characterCode, characterCodeToGlyphId, out path))
|
||||
{
|
||||
path = GetFontMatrix(characterCode).Transform(path).ToArray();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
/// <summary>
|
||||
/// Defines glyphs using a CIDFont
|
||||
/// </summary>
|
||||
internal class Type0Font : IFont, IVerticalWritingSupported
|
||||
internal sealed class Type0Font : IFont, IVerticalWritingSupported
|
||||
{
|
||||
private readonly CMap ucs2CMap;
|
||||
// ReSharper disable once NotAccessedField.Local
|
||||
@@ -117,17 +117,18 @@
|
||||
return cached;
|
||||
}
|
||||
|
||||
var matrix = GetFontMatrix();
|
||||
|
||||
var boundingBox = GetBoundingBoxInGlyphSpace(characterCode);
|
||||
|
||||
boundingBox = matrix.Transform(boundingBox);
|
||||
|
||||
var characterIdentifier = CMap.ConvertToCid(characterCode);
|
||||
|
||||
// Get the bounding box in glyph space
|
||||
var boundingBox = CidFont.GetBoundingBox(characterIdentifier);
|
||||
|
||||
boundingBox = CidFont.GetFontMatrix(characterIdentifier).Transform(boundingBox);
|
||||
|
||||
var width = CidFont.GetWidthFromFont(characterIdentifier);
|
||||
|
||||
var advanceWidth = matrix.TransformX(width);
|
||||
var advanceWidth = GetFontMatrix().TransformX(width);
|
||||
// BobLD: Not sure why we don't need CidFont.GetFontMatrix(characterCode)
|
||||
// Might be related to https://github.com/veraPDF/veraPDF-library/issues/1010
|
||||
|
||||
var result = new CharacterBoundingBox(boundingBox, advanceWidth);
|
||||
|
||||
@@ -136,13 +137,6 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
public PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode)
|
||||
{
|
||||
var characterIdentifier = CMap.ConvertToCid(characterCode);
|
||||
|
||||
return CidFont.GetBoundingBox(characterIdentifier);
|
||||
}
|
||||
|
||||
public TransformationMatrix GetFontMatrix()
|
||||
{
|
||||
return CidFont.FontMatrix;
|
||||
@@ -165,13 +159,17 @@
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetPath(int characterCode, out IReadOnlyList<PdfSubpath> path)
|
||||
{
|
||||
return CidFont.TryGetPath(characterCode, out path);
|
||||
var characterIdentifier = CMap.ConvertToCid(characterCode);
|
||||
|
||||
return CidFont.TryGetPath(characterIdentifier, out path);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetNormalisedPath(int characterCode, out IReadOnlyList<PdfSubpath> path)
|
||||
{
|
||||
return CidFont.TryGetNormalisedPath(characterCode, out path);
|
||||
var characterIdentifier = CMap.ConvertToCid(characterCode);
|
||||
|
||||
return CidFont.TryGetNormalisedPath(characterIdentifier, out path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
using Tokens;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
internal class TrueTypeSimpleFont : IFont
|
||||
internal sealed class TrueTypeSimpleFont : IFont
|
||||
{
|
||||
private static readonly TransformationMatrix DefaultTransformation =
|
||||
TransformationMatrix.FromValues(1 / 1000.0, 0, 0, 1 / 1000.0, 0, 0);
|
||||
@@ -230,7 +230,7 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.Equals(name, ".notdef", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(name, GlyphList.NotDefined, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -328,7 +328,7 @@
|
||||
{
|
||||
if (font == null)
|
||||
{
|
||||
path = EmptyArray<PdfSubpath>.Instance;
|
||||
path = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
path = GetFontMatrix().Transform(path).ToList();
|
||||
path = GetFontMatrix().Transform(path).ToArray();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/// <summary>
|
||||
/// Some TrueType fonts use both the Standard 14 descriptor and the TrueType font from disk.
|
||||
/// </summary>
|
||||
internal class TrueTypeStandard14FallbackSimpleFont : IFont
|
||||
internal sealed class TrueTypeStandard14FallbackSimpleFont : IFont
|
||||
{
|
||||
private static readonly TransformationMatrix DefaultTransformation =
|
||||
TransformationMatrix.FromValues(1 / 1000.0, 0, 0, 1 / 1000.0, 0, 0);
|
||||
@@ -152,7 +152,7 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
path = GetFontMatrix().Transform(path).ToList();
|
||||
path = GetFontMatrix().Transform(path).ToArray();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
/// <summary>
|
||||
/// A font based on the Adobe Type 1 font format.
|
||||
/// </summary>
|
||||
internal class Type1FontSimple : IFont
|
||||
internal sealed class Type1FontSimple : IFont
|
||||
{
|
||||
private static readonly TransformationMatrix DefaultTransformationMatrix = TransformationMatrix.FromValues(0.001, 0, 0, 0.001, 0, 0);
|
||||
|
||||
@@ -197,7 +197,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
characterName = cffFont.GetCharacterName(characterCode);
|
||||
characterName = cffFont.GetCharacterName(characterCode, false);
|
||||
}
|
||||
|
||||
rect = first.GetCharacterBoundingBox(characterName);
|
||||
@@ -247,7 +247,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
characterName = cffFont.GetCharacterName(characterCode);
|
||||
characterName = cffFont.GetCharacterName(characterCode, false);
|
||||
}
|
||||
|
||||
tempPath = first.GetCharacterPath(characterName);
|
||||
@@ -267,7 +267,7 @@
|
||||
{
|
||||
if (TryGetPath(characterCode, out path))
|
||||
{
|
||||
path = fontMatrix.Transform(path).ToList();
|
||||
path = fontMatrix.Transform(path).ToArray();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace UglyToad.PdfPig.PdfFonts.Simple
|
||||
/// <summary>
|
||||
/// A font using one of the Adobe Standard 14 fonts. Can use a custom encoding.
|
||||
/// </summary>
|
||||
internal class Type1Standard14Font : IFont
|
||||
internal sealed class Type1Standard14Font : IFont
|
||||
{
|
||||
private readonly AdobeFontMetrics standardFontMetrics;
|
||||
private readonly Encoding encoding;
|
||||
@@ -49,7 +49,7 @@ namespace UglyToad.PdfPig.PdfFonts.Simple
|
||||
public bool TryGetUnicode(int characterCode, out string value)
|
||||
{
|
||||
var name = encoding.GetName(characterCode);
|
||||
if (string.Equals(name, ".notdef", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(name, GlyphList.NotDefined, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
using PdfPig.Fonts.Encodings;
|
||||
using Tokens;
|
||||
|
||||
internal class Standard14WritingFont : IWritingFont
|
||||
internal sealed class Standard14WritingFont : IWritingFont
|
||||
{
|
||||
private readonly AdobeFontMetrics metrics;
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
public bool TryGetBoundingBox(char character, out PdfRectangle boundingBox)
|
||||
{
|
||||
|
||||
boundingBox = default(PdfRectangle);
|
||||
|
||||
int code = CodeMapIfUnicode(character);
|
||||
@@ -118,7 +117,7 @@
|
||||
private int UnicodeToSymbolCode(char character)
|
||||
{
|
||||
var name = GlyphList.AdobeGlyphList.UnicodeCodePointToName(character);
|
||||
if (string.Equals(name, ".notdef", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(name, GlyphList.NotDefined, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -134,7 +133,7 @@
|
||||
private int UnicodeToZapfDingbats(char character)
|
||||
{
|
||||
var name = GlyphList.ZapfDingbats.UnicodeCodePointToName(character);
|
||||
if (string.Equals(name, ".notdef", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(name, GlyphList.NotDefined, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Debug.WriteLine($"Failed to find Unicode character '{character}' (0x{(int)character:X}).");
|
||||
return -1;
|
||||
@@ -147,13 +146,12 @@
|
||||
Debug.WriteLine($"Found Unicode point '{character}' (0x{(int)character:X}) but glphy name '{name}' not found in font '{metrics.FontName}' (font specific encoding: ZapfDingbats).");
|
||||
}
|
||||
return code;
|
||||
|
||||
}
|
||||
|
||||
private int UnicodeToStandardEncoding(char character)
|
||||
{
|
||||
var name = GlyphList.AdobeGlyphList.UnicodeCodePointToName(character);
|
||||
if (string.Equals(name, ".notdef", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(name, GlyphList.NotDefined, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Debug.WriteLine($"Failed to find Unicode character '{character}' (0x{(int)character:X}).");
|
||||
return -1;
|
||||
@@ -167,7 +165,7 @@
|
||||
code = standardEncoding.GetCode(nameCapitalisedChange);
|
||||
if (code == -1)
|
||||
{
|
||||
Debug.WriteLine($"Found Unicode point '{character}' (0x{(int)character:X}) but glphy name '{name}' not found in font '{metrics.FontName}' (StandardEncoding).");
|
||||
Debug.WriteLine($"Found Unicode point '{character}' (0x{(int)character:X}) but glyph name '{name}' not found in font '{metrics.FontName}' (StandardEncoding).");
|
||||
}
|
||||
}
|
||||
return code;
|
||||
|
||||
Reference in New Issue
Block a user