mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-23 04:36:44 +08:00
#6 account for hintmask and cntrmask data when parsing a type 2 charstring
This commit is contained in:
@@ -17,6 +17,14 @@
|
||||
/// </remarks>
|
||||
internal class Type2CharStringParser
|
||||
{
|
||||
private static readonly HashSet<string> HintingCommandNames = new HashSet<string>
|
||||
{
|
||||
"hstem",
|
||||
"vstem",
|
||||
"hstemhm",
|
||||
"vstemhm"
|
||||
};
|
||||
|
||||
private static readonly IReadOnlyDictionary<int, LazyType2Command> SingleByteCommandStore = new Dictionary<int, LazyType2Command>
|
||||
{
|
||||
{ 1, new LazyType2Command("hstem", ctx =>
|
||||
@@ -701,7 +709,7 @@
|
||||
var b = bytes[i];
|
||||
if (b <= 31 && b != 28)
|
||||
{
|
||||
var command = GetCommand(b, bytes, ref i);
|
||||
var command = GetCommand(b, bytes, instructions, ref i);
|
||||
instructions.Add(Union<decimal, LazyType2Command>.Two(command));
|
||||
}
|
||||
else
|
||||
@@ -754,7 +762,8 @@
|
||||
return lead + (fractionalPart / 65535m);
|
||||
}
|
||||
|
||||
private static LazyType2Command GetCommand(byte b, IReadOnlyList<byte> bytes, ref int i)
|
||||
private static LazyType2Command GetCommand(byte b, IReadOnlyList<byte> bytes,
|
||||
IReadOnlyList<Union<decimal, LazyType2Command>> precedingCommands, ref int i)
|
||||
{
|
||||
if (b == 12)
|
||||
{
|
||||
@@ -767,6 +776,46 @@
|
||||
return new LazyType2Command($"unknown: {b} {b2}", x => { });
|
||||
}
|
||||
|
||||
// hintmask and cntrmask
|
||||
if (b == 19 || b == 20)
|
||||
{
|
||||
/*
|
||||
* The hintmask operator is followed by one or more data bytes that specify the stem hints which are to be active for the
|
||||
* subsequent path construction. The number of data bytes must be exactly the number needed to represent the number of
|
||||
* stems in the original stem list (those stems specified by the hstem, vstem, hstemhm, or vstemhm commands), using one bit
|
||||
* in the data bytes for each stem in the original stem list.
|
||||
*/
|
||||
var stemCount = 0;
|
||||
var precedingNumbers = 0;
|
||||
for (var j = 0; j < precedingCommands.Count; j++)
|
||||
{
|
||||
var item = precedingCommands[j];
|
||||
item.Match(x => precedingNumbers++,
|
||||
x =>
|
||||
{
|
||||
if (!HintingCommandNames.Contains(x.Name))
|
||||
{
|
||||
precedingNumbers = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
stemCount += precedingNumbers / 2;
|
||||
precedingNumbers = 0;
|
||||
});
|
||||
}
|
||||
|
||||
// The vstem command can be left out, e.g. for 12 20 hstemhm 4 6 hintmask, 4 and 6 act as the vertical hints
|
||||
if (precedingNumbers > 0)
|
||||
{
|
||||
stemCount += precedingNumbers / 2;
|
||||
}
|
||||
|
||||
var minimumFullBytes = Math.Ceiling(stemCount / 8d);
|
||||
// Skip the following hintmask or cntrmask data bytes
|
||||
i += (int)minimumFullBytes;
|
||||
}
|
||||
|
||||
if (SingleByteCommandStore.TryGetValue(b, out var command))
|
||||
{
|
||||
return command;
|
||||
|
Reference in New Issue
Block a user