finish reading the encoding cmap for the type 0 font

This commit is contained in:
Eliot Jones 2017-12-21 22:45:18 +00:00
parent a0205ab637
commit 206eb91ff1
2 changed files with 52 additions and 12 deletions

View File

@ -13,11 +13,13 @@
{ {
private readonly CidFontFactory cidFontFactory; private readonly CidFontFactory cidFontFactory;
private readonly CMapCache cMapCache; private readonly CMapCache cMapCache;
private readonly IFilterProvider filterProvider;
public Type0FontHandler(CidFontFactory cidFontFactory, CMapCache cMapCache) public Type0FontHandler(CidFontFactory cidFontFactory, CMapCache cMapCache, IFilterProvider filterProvider)
{ {
this.cidFontFactory = cidFontFactory; this.cidFontFactory = cidFontFactory;
this.cMapCache = cMapCache; this.cMapCache = cMapCache;
this.filterProvider = filterProvider;
} }
public IFont Generate(PdfDictionary dictionary, ParsingArguments arguments) public IFont Generate(PdfDictionary dictionary, ParsingArguments arguments)
@ -26,7 +28,7 @@
var baseFont = dictionary.GetName(CosName.BASE_FONT); var baseFont = dictionary.GetName(CosName.BASE_FONT);
ReadEncoding(dictionary); var cMap = ReadEncoding(dictionary, out var isCMapPredefined);
if (TryGetFirstDescendant(dictionary, out var descendantObject)) if (TryGetFirstDescendant(dictionary, out var descendantObject))
{ {
@ -38,6 +40,8 @@
} }
} }
var ucs2CMap = GetUcs2CMap(dictionary, isCMapPredefined, false);
CMap toUnicodeCMap = null; CMap toUnicodeCMap = null;
if (dictionary.ContainsKey(CosName.TO_UNICODE)) if (dictionary.ContainsKey(CosName.TO_UNICODE))
{ {
@ -45,12 +49,11 @@
var toUnicode = dynamicParser.Parse(arguments, toUnicodeValue as CosObject, false) as RawCosStream; var toUnicode = dynamicParser.Parse(arguments, toUnicodeValue as CosObject, false) as RawCosStream;
var decodedUnicodeCMap = toUnicode?.Decode(arguments.Container.Get<IFilterProvider>()); var decodedUnicodeCMap = toUnicode?.Decode(filterProvider);
if (decodedUnicodeCMap != null) if (decodedUnicodeCMap != null)
{ {
toUnicodeCMap = arguments.Container.Get<CMapParser>() toUnicodeCMap = cMapCache.Parse(new ByteArrayInputBytes(decodedUnicodeCMap), arguments.IsLenientParsing);
.Parse(new ByteArrayInputBytes(decodedUnicodeCMap), arguments.IsLenientParsing);
} }
} }
@ -99,28 +102,65 @@
cidFontFactory.Generate(dictionary, arguments, arguments.IsLenientParsing); cidFontFactory.Generate(dictionary, arguments, arguments.IsLenientParsing);
} }
private void ReadEncoding(PdfDictionary dictionary) private CMap ReadEncoding(PdfDictionary dictionary, out bool isCMapPredefined)
{ {
isCMapPredefined = false;
CMap result = default(CMap);
if (dictionary.TryGetValue(CosName.ENCODING, out var value)) if (dictionary.TryGetValue(CosName.ENCODING, out var value))
{ {
if (value is CosName encodingName) if (value is CosName encodingName)
{ {
var cmap = cMapCache.Get(encodingName.Name); var cmap = cMapCache.Get(encodingName.Name);
if (cmap == null) result = cmap ?? throw new InvalidOperationException("Missing CMap for " + encodingName.Name);
{
throw new InvalidOperationException("Missing CMap for " + encodingName.Name); isCMapPredefined = true;
}
} }
else if (value is RawCosStream stream) else if (value is RawCosStream stream)
{ {
var decoded = stream.Decode(filterProvider);
var cmap = cMapCache.Parse(new ByteArrayInputBytes(decoded), false);
result = cmap ?? throw new InvalidOperationException("Could not read CMap for " + dictionary);
} }
else else
{ {
throw new InvalidOperationException("Could not read the encoding, expected a name or a stream but got a: " + value.GetType().Name); throw new InvalidOperationException("Could not read the encoding, expected a name or a stream but got a: " + value.GetType().Name);
} }
} }
return result;
}
private static CMap GetUcs2CMap(PdfDictionary dictionary, bool isCMapPredefined, bool usesDescendantAdobeFont)
{
if (!isCMapPredefined)
{
return null;
}
/*
* If the font is a composite font that uses one of the predefined CMaps except IdentityH and IdentityV or whose descendant
* CIDFont uses the Adobe-GB1, Adobe-CNS1, Adobe-Japan1, or Adobe-Korea1 character collection use a UCS2 CMap.
*/
var encodingName = dictionary.GetName(CosName.ENCODING);
if (encodingName == null)
{
return null;
}
var isPredefinedIdentityMap = encodingName.Equals(CosName.IDENTITY_H) || encodingName.Equals(CosName.IDENTITY_V);
if (isPredefinedIdentityMap && !usesDescendantAdobeFont)
{
return null;
}
throw new NotSupportedException("Support for UCS2 CMaps are not implemented yet. Please raise an issue.");
} }
} }
} }

View File

@ -59,7 +59,7 @@
var cmapParser = new CMapParser(); var cmapParser = new CMapParser();
var afmParser = new AdobeFontMetricsParser(); var afmParser = new AdobeFontMetricsParser();
var type0FontFactory = new Type0FontHandler(new CidFontFactory(new FontDescriptorFactory(), new TrueTypeFontParser()), new CMapCache(cmapParser)); var type0FontFactory = new Type0FontHandler(new CidFontFactory(new FontDescriptorFactory(), new TrueTypeFontParser()), new CMapCache(cmapParser), filterProvider);
var fontFactory = new FontFactory(type0FontFactory); var fontFactory = new FontFactory(type0FontFactory);
var container = new Container(); var container = new Container();