#6 fix bugs with vlineto and hlineto and decoding of charsets. dump results of type 2 path decoding to file for visual verification while debugging

This commit is contained in:
Eliot Jones
2018-11-17 20:21:59 +00:00
parent aa6f55c9ad
commit 8f5c0fc77b
8 changed files with 49 additions and 36 deletions

View File

@@ -146,7 +146,7 @@ namespace UglyToad.PdfPig.Fonts
var path = $"<path d='{glyph}' stroke='cyan' stroke-width='3'></path>";
var bboxRect = bbox.HasValue ? BboxToRect(bbox.Value, "yellow") : string.Empty;
var others = string.Join(" ", bboxes.Select(x => BboxToRect(x, "gray")));
var result = $"<svg transform='scale(1, -1)' width='2000' height='2000'>{path} {bboxRect} {others}</svg>";
var result = $"<svg transform='scale(0.2, -0.2)' width='500' height='500'>{path} {bboxRect} {others}</svg>";
return result;
}

View File

@@ -2,6 +2,7 @@
{
using System;
using System.Collections.Generic;
using Charsets;
using Geometry;
using Util;
using Util.JetBrains.Annotations;
@@ -118,22 +119,25 @@
*/
var isOdd = ctx.Stack.Length % 2 != 0;
var numberOfAdditionalLines = ctx.Stack.Length - (isOdd ? 1 : 0);
if (isOdd)
{
var dx1 = ctx.Stack.PopBottom();
ctx.AddRelativeHorizontalLine(dx1);
var numberOfAdditionalLines = ctx.Stack.Length;
for (var i = 0; i < numberOfAdditionalLines; i++)
for (var i = 0; i < numberOfAdditionalLines; i+= 2)
{
var isDeltaY = (isOdd && i % 2 == 0) || (!isOdd && i % 2 != 0);
if (isDeltaY)
{
var dya = ctx.Stack.PopBottom();
ctx.AddRelativeVerticalLine(dya);
ctx.AddRelativeVerticalLine(ctx.Stack.PopBottom());
ctx.AddRelativeHorizontalLine(ctx.Stack.PopBottom());
}
}
else
{
var dxa = ctx.Stack.PopBottom();
ctx.AddRelativeHorizontalLine(dxa);
for (var i = 0; i < numberOfAdditionalLines; i+= 2)
{
ctx.AddRelativeHorizontalLine(ctx.Stack.PopBottom());
ctx.AddRelativeVerticalLine(ctx.Stack.PopBottom());
}
}
@@ -145,23 +149,25 @@
{
var isOdd = ctx.Stack.Length % 2 != 0;
var numberOfAdditionalLines = ctx.Stack.Length - (isOdd ? 1 : 0);
if (isOdd)
{
var dy1 = ctx.Stack.PopBottom();
ctx.AddRelativeVerticalLine(dy1);
var numberOfAdditionalLines = ctx.Stack.Length;
for (var i = 0; i < numberOfAdditionalLines; i++)
for (var i = 0; i < numberOfAdditionalLines; i+=2)
{
var isDeltaY = (isOdd && i % 2 != 0) || (!isOdd && i % 2 == 0);
if (isDeltaY)
{
var dya = ctx.Stack.PopBottom();
ctx.AddRelativeVerticalLine(dya);
ctx.AddRelativeHorizontalLine(ctx.Stack.PopBottom());
ctx.AddRelativeVerticalLine(ctx.Stack.PopBottom());
}
}
else
{
var dxa = ctx.Stack.PopBottom();
ctx.AddRelativeHorizontalLine(dxa);
for (var i = 0; i < numberOfAdditionalLines; i+=2)
{
ctx.AddRelativeVerticalLine(ctx.Stack.PopBottom());
ctx.AddRelativeHorizontalLine(ctx.Stack.PopBottom());
}
}
@@ -673,7 +679,7 @@
public static Type2CharStrings Parse([NotNull] IReadOnlyList<IReadOnlyList<byte>> charStringBytes,
[NotNull] CompactFontFormatIndex localSubroutines,
[NotNull] CompactFontFormatIndex globalSubroutines)
[NotNull] CompactFontFormatIndex globalSubroutines, ICompactFontFormatCharset charset)
{
if (charStringBytes == null)
{
@@ -690,12 +696,12 @@
throw new ArgumentNullException(nameof(globalSubroutines));
}
var charStrings = new Dictionary<int, Type2CharStrings.CommandSequence>();
var charStrings = new Dictionary<string, Type2CharStrings.CommandSequence>();
for (var i = 0; i < charStringBytes.Count; i++)
{
var charString = charStringBytes[i];
var sequence = ParseSingle(charString);
charStrings[i] = new Type2CharStrings.CommandSequence(sequence);
charStrings[charset.GetNameByGlyphId(i)] = new Type2CharStrings.CommandSequence(sequence);
}
return new Type2CharStrings(charStrings, new Dictionary<int, Type2CharStrings.CommandSequence>());

View File

@@ -10,11 +10,11 @@
private readonly object locker = new object();
private readonly Dictionary<string, CharacterPath> glyphs = new Dictionary<string, CharacterPath>();
public IReadOnlyDictionary<int, CommandSequence> CharStrings { get; }
public IReadOnlyDictionary<string, CommandSequence> CharStrings { get; }
public IReadOnlyDictionary<int, CommandSequence> Subroutines { get; }
public Type2CharStrings(IReadOnlyDictionary<int, CommandSequence> charStrings, IReadOnlyDictionary<int, CommandSequence> subroutines)
public Type2CharStrings(IReadOnlyDictionary<string, CommandSequence> charStrings, IReadOnlyDictionary<int, CommandSequence> subroutines)
{
CharStrings = charStrings ?? throw new ArgumentNullException(nameof(charStrings));
Subroutines = subroutines ?? throw new ArgumentNullException(nameof(subroutines));
@@ -30,7 +30,7 @@
return result;
}
if (!CharStrings.TryGetValue(0, out var sequence))
if (!CharStrings.TryGetValue(name, out var sequence))
{
throw new InvalidOperationException($"No charstring sequence with the name /{name} in this font.");
}

View File

@@ -29,7 +29,7 @@
public virtual string GetNameByGlyphId(int glyphId)
{
throw new NotImplementedException();
return GlyphIdToStringIdAndName[glyphId].name;
}
public virtual string GetNameByStringId(int stringId)

View File

@@ -195,7 +195,7 @@
public string GetNameByGlyphId(int glyphId)
{
throw new System.NotImplementedException();
return characterIdToStringIdAndName[glyphId].Value;
}
public string GetNameByStringId(int stringId)

View File

@@ -116,7 +116,7 @@
public string GetNameByGlyphId(int glyphId)
{
throw new System.NotImplementedException();
return characterIdToStringIdAndName[glyphId].Value;
}
public string GetNameByStringId(int stringId)

View File

@@ -258,7 +258,7 @@
public string GetNameByGlyphId(int glyphId)
{
throw new System.NotImplementedException();
return characterIdToStringIdAndName[glyphId].Value;
}
public string GetNameByStringId(int stringId)

View File

@@ -3,7 +3,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Charsets;
using CharStrings;
using Dictionaries;
@@ -108,12 +110,11 @@
var numberInRange = format == 1 ? data.ReadCard8() : data.ReadCard16();
glyphToNamesAndStringId.Add((glyphId, firstSid, ReadString(firstSid, stringIndex)));
glyphId++;
for (var i = 0; i < numberInRange; i++)
{
glyphId++;
var sid = firstSid + i + 1;
glyphToNamesAndStringId.Add((glyphId, sid, ReadString(sid, stringIndex)));
glyphId++;
}
}
@@ -142,7 +143,7 @@
case CompactFontFormatCharStringType.Type1:
throw new NotImplementedException();
case CompactFontFormatCharStringType.Type2:
charStrings = Type2CharStringParser.Parse(charStringIndex, localSubroutines, globalSubroutineIndex);
charStrings = Type2CharStringParser.Parse(charStringIndex, localSubroutines, globalSubroutineIndex, charset);
break;
default:
throw new ArgumentOutOfRangeException($"Unexpected CharString type in CFF font: {topDictionary.CharStringType}.");
@@ -150,11 +151,17 @@
if (Debugger.IsAttached)
{
var builder = new StringBuilder("<!DOCTYPE html><html><head></head><body>");
foreach (var pair in charStrings.CharStrings)
{
var path = Type2CharStrings.Run(pair.Value);
var svg = path.ToFullSvg();
builder.AppendLine(svg);
}
builder.Append("</body></html>");
File.WriteAllText(@"C:\git\index.html", builder.ToString());
}
return new CompactFontFormatFont(topDictionary, privateDictionary, charset, Union<Type1CharStrings, Type2CharStrings>.Two(charStrings));