Skip to content

Commit

Permalink
#299 #241 add correct fallback cmap for korea1-3 and missing japan cmap
Browse files Browse the repository at this point in the history
  • Loading branch information
EliotJones committed Feb 28, 2021
1 parent 89ee5f5 commit 7c0fd48
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 24 deletions.
18 changes: 12 additions & 6 deletions src/UglyToad.PdfPig/PdfFonts/Cmap/CMapCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,26 @@ internal static class CMapCache

private static readonly CMapParser CMapParser = new CMapParser();

public static CMap Get(string name)
public static bool TryGet(string name, out CMap result)
{
result = null;

lock (Lock)
{
if (Cache.TryGetValue(name, out var result))
if (Cache.TryGetValue(name, out result))
{
return result;
return true;
}

result = CMapParser.ParseExternal(name);
if (CMapParser.TryParseExternal(name, out result))
{

Cache[name] = result;

Cache[name] = result;
return true;
}

return result;
return false;
}
}

Expand Down
27 changes: 18 additions & 9 deletions src/UglyToad.PdfPig/PdfFonts/Parser/CMapParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ public CMap Parse(IInputBytes inputBytes)
{
case "usecmap":
{
if (previousToken is NameToken name)
if (previousToken is NameToken name && TryParseExternal(name.Data, out var external))
{
var external = ParseExternal(name.Data);

builder.UseCMap(external);
}
else
Expand Down Expand Up @@ -120,28 +118,39 @@ public CMap Parse(IInputBytes inputBytes)
return builder.Build();
}

public CMap ParseExternal(string name)
public bool TryParseExternal(string name, out CMap result)
{
result = null;

var resources = typeof(CMapParser).Assembly.GetManifestResourceNames();

var resource = resources.FirstOrDefault(x =>
x.EndsWith("CMap." + name, StringComparison.InvariantCultureIgnoreCase));

if (resource == null)
{
throw new InvalidOperationException("Could not find the referenced CMap: " + name);
return false;
}

byte[] bytes;
using (var stream = typeof(CMapParser).Assembly.GetManifestResourceStream(resource))
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
if (stream == null)
{
return false;
}

bytes = memoryStream.ToArray();
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);

bytes = memoryStream.ToArray();
}
}

return Parse(new ByteArrayInputBytes(bytes));
result = Parse(new ByteArrayInputBytes(bytes));

return true;
}
}
}
33 changes: 24 additions & 9 deletions src/UglyToad.PdfPig/PdfFonts/Parser/Handlers/Type0FontHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ public IFont Generate(DictionaryToken dictionary)
toUnicodeCMap = CMapCache.Parse(new ByteArrayInputBytes(decodedUnicodeCMap));
}
}
else if (DirectObjectFinder.TryGet<NameToken>(toUnicodeValue, scanner, out var toUnicodeName))
else if (DirectObjectFinder.TryGet<NameToken>(toUnicodeValue, scanner, out var toUnicodeName)
&& CMapCache.TryGet(toUnicodeName.Data, out toUnicodeCMap))
{
toUnicodeCMap = CMapCache.Get(toUnicodeName.Data);
}
else
{
Expand Down Expand Up @@ -144,8 +144,11 @@ private CMap ReadEncoding(DictionaryToken dictionary, out bool isCMapPredefined)

if (dictionary.TryGet(NameToken.Encoding, scanner, out NameToken encodingName))
{
var cmap = CMapCache.Get(encodingName.Data);

if (!CMapCache.TryGet(encodingName.Data, out var cmap))
{
throw new InvalidOperationException($"Missing CMap named {encodingName.Data}.");
}

result = cmap ?? throw new InvalidOperationException($"Missing CMap named {encodingName.Data}.");

isCMapPredefined = true;
Expand Down Expand Up @@ -210,16 +213,28 @@ private static (CMap, bool isChineseJapaneseOrKorean) GetUcs2CMap(DictionaryToke
}

var fullCmapName = cidFont.SystemInfo.ToString();
var nonUnicodeCMap = CMapCache.Get(fullCmapName);

if (nonUnicodeCMap == null)
string registry;
string ordering;
if (CMapCache.TryGet(fullCmapName, out var nonUnicodeCMap))
{
registry = nonUnicodeCMap.Info.Registry;
ordering = nonUnicodeCMap.Info.Ordering;
}
else
{
return (null, true);
registry = cidFont.SystemInfo.Registry;
ordering = cidFont.SystemInfo.Ordering;
}

var unicodeCMapName = $"{registry}-{ordering}-UCS2";

var unicodeCMapName = $"{nonUnicodeCMap.Info.Registry}-{nonUnicodeCMap.Info.Ordering}-UCS2";
if (!CMapCache.TryGet(unicodeCMapName, out var unicodeCMap))
{
throw new InvalidFontFormatException($"Could not locate CMap by name: {nonUnicodeCMap}.");
}

return (CMapCache.Get(unicodeCMapName), true);
return (unicodeCMap, true);
}
}
}
166 changes: 166 additions & 0 deletions src/UglyToad.PdfPig/Resources/CMap/Adobe-Japan1-7
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (Identity)
%%Title: (Identity Adobe Japan1 7)
%%Version: 1.001
%%Copyright: -----------------------------------------------------------
%%Copyright: Copyright 1990-2019 Adobe. All rights reserved.
%%Copyright:
%%Copyright: Redistribution and use in source and binary forms, with or
%%Copyright: without modification, are permitted provided that the
%%Copyright: following conditions are met:
%%Copyright:
%%Copyright: Redistributions of source code must retain the above
%%Copyright: copyright notice, this list of conditions and the following
%%Copyright: disclaimer.
%%Copyright:
%%Copyright: Redistributions in binary form must reproduce the above
%%Copyright: copyright notice, this list of conditions and the following
%%Copyright: disclaimer in the documentation and/or other materials
%%Copyright: provided with the distribution.
%%Copyright:
%%Copyright: Neither the name of Adobe nor the names of its contributors
%%Copyright: may be used to endorse or promote products derived from
%%Copyright: this software without specific prior written permission.
%%Copyright:
%%Copyright: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
%%Copyright: CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
%%Copyright: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
%%Copyright: MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
%%Copyright: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
%%Copyright: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
%%Copyright: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
%%Copyright: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
%%Copyright: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
%%Copyright: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
%%Copyright: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
%%Copyright: OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
%%Copyright: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%%Copyright: -----------------------------------------------------------
%%EndComments

/CIDInit /ProcSet findresource begin

12 dict begin

begincmap

/CIDSystemInfo 3 dict dup begin
/Registry (Adobe) def
/Ordering (Japan1) def
/Supplement 7 def
end def

/CMapName /Adobe-Japan1-7 def
/CMapVersion 1.001 def
/CMapType 1 def

/WMode 0 def

/CIDCount 23060 def

1 begincodespacerange
<0000> <5AFF>
endcodespacerange

91 begincidrange
<0000> <00ff> 0
<0100> <01ff> 256
<0200> <02ff> 512
<0300> <03ff> 768
<0400> <04ff> 1024
<0500> <05ff> 1280
<0600> <06ff> 1536
<0700> <07ff> 1792
<0800> <08ff> 2048
<0900> <09ff> 2304
<0a00> <0aff> 2560
<0b00> <0bff> 2816
<0c00> <0cff> 3072
<0d00> <0dff> 3328
<0e00> <0eff> 3584
<0f00> <0fff> 3840
<1000> <10ff> 4096
<1100> <11ff> 4352
<1200> <12ff> 4608
<1300> <13ff> 4864
<1400> <14ff> 5120
<1500> <15ff> 5376
<1600> <16ff> 5632
<1700> <17ff> 5888
<1800> <18ff> 6144
<1900> <19ff> 6400
<1a00> <1aff> 6656
<1b00> <1bff> 6912
<1c00> <1cff> 7168
<1d00> <1dff> 7424
<1e00> <1eff> 7680
<1f00> <1fff> 7936
<2000> <20ff> 8192
<2100> <21ff> 8448
<2200> <22ff> 8704
<2300> <23ff> 8960
<2400> <24ff> 9216
<2500> <25ff> 9472
<2600> <26ff> 9728
<2700> <27ff> 9984
<2800> <28ff> 10240
<2900> <29ff> 10496
<2a00> <2aff> 10752
<2b00> <2bff> 11008
<2c00> <2cff> 11264
<2d00> <2dff> 11520
<2e00> <2eff> 11776
<2f00> <2fff> 12032
<3000> <30ff> 12288
<3100> <31ff> 12544
<3200> <32ff> 12800
<3300> <33ff> 13056
<3400> <34ff> 13312
<3500> <35ff> 13568
<3600> <36ff> 13824
<3700> <37ff> 14080
<3800> <38ff> 14336
<3900> <39ff> 14592
<3a00> <3aff> 14848
<3b00> <3bff> 15104
<3c00> <3cff> 15360
<3d00> <3dff> 15616
<3e00> <3eff> 15872
<3f00> <3fff> 16128
<4000> <40ff> 16384
<4100> <41ff> 16640
<4200> <42ff> 16896
<4300> <43ff> 17152
<4400> <44ff> 17408
<4500> <45ff> 17664
<4600> <46ff> 17920
<4700> <47ff> 18176
<4800> <48ff> 18432
<4900> <49ff> 18688
<4a00> <4aff> 18944
<4b00> <4bff> 19200
<4c00> <4cff> 19456
<4d00> <4dff> 19712
<4e00> <4eff> 19968
<4f00> <4fff> 20224
<5000> <50ff> 20480
<5100> <51ff> 20736
<5200> <52ff> 20992
<5300> <53ff> 21248
<5400> <54ff> 21504
<5500> <55ff> 21760
<5600> <56ff> 22016
<5700> <57ff> 22272
<5800> <58ff> 22528
<5900> <59ff> 22784
<5a00> <5a13> 23040
endcidrange
endcmap
CMapName currentdict /CMap defineresource pop
end
end

%%EndResource
%%EOF

0 comments on commit 7c0fd48

Please sign in to comment.