mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-15 03:34:52 +08:00
wire up cidtogid map for type2cid fonts
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
namespace UglyToad.PdfPig.Fonts.CidFonts
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies mapping from character identifiers to glyph indices.
|
||||
/// Can either be defined as a name in which case it must be Identity or a stream which defines the mapping.
|
||||
/// </summary>
|
||||
internal class CharacterIdentifierToGlyphIndexMap
|
||||
{
|
||||
private readonly bool isIdentity;
|
||||
private readonly int[] map;
|
||||
|
||||
public CharacterIdentifierToGlyphIndexMap()
|
||||
{
|
||||
isIdentity = true;
|
||||
map = null;
|
||||
}
|
||||
|
||||
public CharacterIdentifierToGlyphIndexMap(byte[] streamBytes)
|
||||
{
|
||||
var numberOfEntries = streamBytes.Length / 2;
|
||||
|
||||
map = new int[numberOfEntries];
|
||||
var offset = 0;
|
||||
|
||||
for (var i = 0; i < numberOfEntries; i++)
|
||||
{
|
||||
var glyphIndex = (streamBytes[offset] << 8) | streamBytes[offset + 1];
|
||||
map[i] = glyphIndex;
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
}
|
||||
|
||||
public int GetGlyphIndex(int characterIdentifier)
|
||||
{
|
||||
if (isIdentity)
|
||||
{
|
||||
return characterIdentifier;
|
||||
}
|
||||
|
||||
if (characterIdentifier >= map.Length || characterIdentifier < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return map[characterIdentifier];
|
||||
}
|
||||
}
|
||||
}
|
@@ -42,6 +42,6 @@
|
||||
|
||||
decimal GetWidthFromDictionary(int cid);
|
||||
|
||||
PdfRectangle GetBoundingBox(int characterCode);
|
||||
PdfRectangle GetBoundingBox(int characterIdentifier);
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
namespace UglyToad.PdfPig.Fonts.CidFonts
|
||||
{
|
||||
using System;
|
||||
using Geometry;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,5 +9,6 @@
|
||||
internal interface ICidFontProgram
|
||||
{
|
||||
bool TryGetBoundingBox(int characterCode, out PdfRectangle boundingBox);
|
||||
bool TryGetBoundingBox(int characterCode, Func<int, int> characterIdentifierToGlyphIndex, out PdfRectangle boundingBox);
|
||||
}
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public PdfRectangle GetBoundingBox(int characterCode)
|
||||
public PdfRectangle GetBoundingBox(int characterIdentifier)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@
|
||||
private readonly ICidFontProgram fontProgram;
|
||||
private readonly VerticalWritingMetrics verticalWritingMetrics;
|
||||
private readonly IReadOnlyDictionary<int, decimal> widths;
|
||||
private readonly CharacterIdentifierToGlyphIndexMap cidToGid;
|
||||
|
||||
public NameToken Type { get; }
|
||||
public NameToken SubType { get; }
|
||||
@@ -24,10 +25,11 @@
|
||||
public CidFontType CidFontType => CidFontType.Type2;
|
||||
public FontDescriptor Descriptor { get; }
|
||||
|
||||
public Type2CidFont(NameToken type, NameToken subType, NameToken baseFont, CharacterIdentifierSystemInfo systemInfo,
|
||||
public Type2CidFont(NameToken type, NameToken subType, NameToken baseFont, CharacterIdentifierSystemInfo systemInfo,
|
||||
FontDescriptor descriptor, ICidFontProgram fontProgram,
|
||||
VerticalWritingMetrics verticalWritingMetrics,
|
||||
IReadOnlyDictionary<int, decimal> widths)
|
||||
IReadOnlyDictionary<int, decimal> widths,
|
||||
CharacterIdentifierToGlyphIndexMap cidToGid)
|
||||
{
|
||||
Type = type;
|
||||
SubType = subType;
|
||||
@@ -37,6 +39,7 @@
|
||||
this.fontProgram = fontProgram;
|
||||
this.verticalWritingMetrics = verticalWritingMetrics;
|
||||
this.widths = widths;
|
||||
this.cidToGid = cidToGid;
|
||||
|
||||
// TODO: This should maybe take units per em into account?
|
||||
var scale = 1 / 1000m;
|
||||
@@ -49,9 +52,9 @@
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public decimal GetWidthFromDictionary(int cid)
|
||||
public decimal GetWidthFromDictionary(int characterIdentifier)
|
||||
{
|
||||
if (widths.TryGetValue(cid, out var width))
|
||||
if (widths.TryGetValue(characterIdentifier, out var width))
|
||||
{
|
||||
return width;
|
||||
}
|
||||
@@ -59,14 +62,14 @@
|
||||
return Descriptor.MissingWidth;
|
||||
}
|
||||
|
||||
public PdfRectangle GetBoundingBox(int characterCode)
|
||||
public PdfRectangle GetBoundingBox(int characterIdentifier)
|
||||
{
|
||||
if (fontProgram == null)
|
||||
{
|
||||
return Descriptor.BoundingBox;
|
||||
}
|
||||
|
||||
if (fontProgram.TryGetBoundingBox(characterCode, out var result))
|
||||
if (fontProgram.TryGetBoundingBox(characterIdentifier, cidToGid.GetGlyphIndex, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
@@ -90,7 +90,9 @@
|
||||
|
||||
public PdfRectangle GetBoundingBox(int characterCode)
|
||||
{
|
||||
return CidFont.GetBoundingBox(characterCode);
|
||||
var cid = CMap.ConvertToCid(characterCode);
|
||||
|
||||
return CidFont.GetBoundingBox(cid);
|
||||
}
|
||||
|
||||
public TransformationMatrix GetFontMatrix()
|
||||
|
@@ -52,7 +52,7 @@
|
||||
var baseFont = dictionary.GetNameOrDefault(NameToken.BaseFont);
|
||||
|
||||
var systemInfo = GetSystemInfo(dictionary);
|
||||
|
||||
|
||||
var subType = dictionary.GetNameOrDefault(NameToken.Subtype);
|
||||
if (NameToken.CidFontType0.Equals(subType))
|
||||
{
|
||||
@@ -61,12 +61,14 @@
|
||||
|
||||
if (NameToken.CidFontType2.Equals(subType))
|
||||
{
|
||||
return new Type2CidFont(type, subType, baseFont, systemInfo, descriptor, fontProgram, verticalWritingMetrics, widths);
|
||||
var cidToGid = GetCharacterIdentifierToGlyphIndexMap(dictionary, isLenientParsing);
|
||||
|
||||
return new Type2CidFont(type, subType, baseFont, systemInfo, descriptor, fontProgram, verticalWritingMetrics, widths, cidToGid);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private bool TryGetFontDescriptor(DictionaryToken dictionary, out DictionaryToken descriptorDictionary)
|
||||
{
|
||||
descriptorDictionary = null;
|
||||
@@ -152,7 +154,7 @@
|
||||
return widths;
|
||||
}
|
||||
|
||||
private VerticalWritingMetrics ReadVerticalDisplacements(DictionaryToken dict)
|
||||
private static VerticalWritingMetrics ReadVerticalDisplacements(DictionaryToken dict)
|
||||
{
|
||||
var verticalDisplacements = new Dictionary<int, decimal>();
|
||||
var positionVectors = new Dictionary<int, PdfVector>();
|
||||
@@ -237,6 +239,30 @@
|
||||
return new CharacterIdentifierSystemInfo(registry, ordering, supplement);
|
||||
}
|
||||
|
||||
private CharacterIdentifierToGlyphIndexMap GetCharacterIdentifierToGlyphIndexMap(DictionaryToken dictionary, bool isLenientParsing)
|
||||
{
|
||||
if (!dictionary.TryGet(NameToken.CidToGidMap, out var entry))
|
||||
{
|
||||
return new CharacterIdentifierToGlyphIndexMap();
|
||||
}
|
||||
|
||||
if (entry is NameToken name)
|
||||
{
|
||||
if (!name.Equals(NameToken.CidToGidMap) && !isLenientParsing)
|
||||
{
|
||||
throw new InvalidOperationException($"The CIDToGIDMap in a Type 0 font should have the value /Identity, instead got: {name}.");
|
||||
}
|
||||
|
||||
return new CharacterIdentifierToGlyphIndexMap();
|
||||
}
|
||||
|
||||
var stream = DirectObjectFinder.Get<StreamToken>(entry, pdfScanner);
|
||||
|
||||
var bytes = stream.Decode(filterProvider);
|
||||
|
||||
return new CharacterIdentifierToGlyphIndexMap(bytes);
|
||||
}
|
||||
|
||||
private string SafeKeyAccess(DictionaryToken dictionary, NameToken keyName)
|
||||
{
|
||||
if (!dictionary.TryGet(keyName, out var token))
|
||||
|
@@ -31,16 +31,23 @@
|
||||
GlyphTable = tableRegister.GlyphDataTable;
|
||||
}
|
||||
|
||||
public bool TryGetBoundingBox(int characterCode, out PdfRectangle boundingBox)
|
||||
public bool TryGetBoundingBox(int characterCode, out PdfRectangle boundingBox) => TryGetBoundingBox(characterCode, null, out boundingBox);
|
||||
public bool TryGetBoundingBox(int characterCode, Func<int, int> characterIdentifierToGlyphIndex, out PdfRectangle boundingBox)
|
||||
{
|
||||
boundingBox = default(PdfRectangle);
|
||||
|
||||
int index;
|
||||
|
||||
if (CMapTable == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (characterIdentifierToGlyphIndex == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CMapTable.TryGetGlyphIndex(characterCode, out var index))
|
||||
index = characterIdentifierToGlyphIndex(characterCode);
|
||||
}
|
||||
else if (!CMapTable.TryGetGlyphIndex(characterCode, out index))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user