mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-15 19:54:52 +08:00
#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:
@@ -146,7 +146,7 @@ namespace UglyToad.PdfPig.Fonts
|
|||||||
var path = $"<path d='{glyph}' stroke='cyan' stroke-width='3'></path>";
|
var path = $"<path d='{glyph}' stroke='cyan' stroke-width='3'></path>";
|
||||||
var bboxRect = bbox.HasValue ? BboxToRect(bbox.Value, "yellow") : string.Empty;
|
var bboxRect = bbox.HasValue ? BboxToRect(bbox.Value, "yellow") : string.Empty;
|
||||||
var others = string.Join(" ", bboxes.Select(x => BboxToRect(x, "gray")));
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Charsets;
|
||||||
using Geometry;
|
using Geometry;
|
||||||
using Util;
|
using Util;
|
||||||
using Util.JetBrains.Annotations;
|
using Util.JetBrains.Annotations;
|
||||||
@@ -118,22 +119,25 @@
|
|||||||
*/
|
*/
|
||||||
var isOdd = ctx.Stack.Length % 2 != 0;
|
var isOdd = ctx.Stack.Length % 2 != 0;
|
||||||
|
|
||||||
|
var numberOfAdditionalLines = ctx.Stack.Length - (isOdd ? 1 : 0);
|
||||||
|
|
||||||
|
if (isOdd)
|
||||||
|
{
|
||||||
var dx1 = ctx.Stack.PopBottom();
|
var dx1 = ctx.Stack.PopBottom();
|
||||||
ctx.AddRelativeHorizontalLine(dx1);
|
ctx.AddRelativeHorizontalLine(dx1);
|
||||||
|
|
||||||
var numberOfAdditionalLines = ctx.Stack.Length;
|
for (var i = 0; i < numberOfAdditionalLines; i+= 2)
|
||||||
for (var i = 0; i < numberOfAdditionalLines; i++)
|
|
||||||
{
|
{
|
||||||
var isDeltaY = (isOdd && i % 2 == 0) || (!isOdd && i % 2 != 0);
|
ctx.AddRelativeVerticalLine(ctx.Stack.PopBottom());
|
||||||
if (isDeltaY)
|
ctx.AddRelativeHorizontalLine(ctx.Stack.PopBottom());
|
||||||
{
|
}
|
||||||
var dya = ctx.Stack.PopBottom();
|
|
||||||
ctx.AddRelativeVerticalLine(dya);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var dxa = ctx.Stack.PopBottom();
|
for (var i = 0; i < numberOfAdditionalLines; i+= 2)
|
||||||
ctx.AddRelativeHorizontalLine(dxa);
|
{
|
||||||
|
ctx.AddRelativeHorizontalLine(ctx.Stack.PopBottom());
|
||||||
|
ctx.AddRelativeVerticalLine(ctx.Stack.PopBottom());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,23 +149,25 @@
|
|||||||
{
|
{
|
||||||
var isOdd = ctx.Stack.Length % 2 != 0;
|
var isOdd = ctx.Stack.Length % 2 != 0;
|
||||||
|
|
||||||
|
var numberOfAdditionalLines = ctx.Stack.Length - (isOdd ? 1 : 0);
|
||||||
|
|
||||||
|
if (isOdd)
|
||||||
|
{
|
||||||
var dy1 = ctx.Stack.PopBottom();
|
var dy1 = ctx.Stack.PopBottom();
|
||||||
ctx.AddRelativeVerticalLine(dy1);
|
ctx.AddRelativeVerticalLine(dy1);
|
||||||
|
|
||||||
var numberOfAdditionalLines = ctx.Stack.Length;
|
for (var i = 0; i < numberOfAdditionalLines; i+=2)
|
||||||
for (var i = 0; i < numberOfAdditionalLines; i++)
|
|
||||||
{
|
{
|
||||||
var isDeltaY = (isOdd && i % 2 != 0) || (!isOdd && i % 2 == 0);
|
ctx.AddRelativeHorizontalLine(ctx.Stack.PopBottom());
|
||||||
|
ctx.AddRelativeVerticalLine(ctx.Stack.PopBottom());
|
||||||
if (isDeltaY)
|
}
|
||||||
{
|
|
||||||
var dya = ctx.Stack.PopBottom();
|
|
||||||
ctx.AddRelativeVerticalLine(dya);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var dxa = ctx.Stack.PopBottom();
|
for (var i = 0; i < numberOfAdditionalLines; i+=2)
|
||||||
ctx.AddRelativeHorizontalLine(dxa);
|
{
|
||||||
|
ctx.AddRelativeVerticalLine(ctx.Stack.PopBottom());
|
||||||
|
ctx.AddRelativeHorizontalLine(ctx.Stack.PopBottom());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,7 +679,7 @@
|
|||||||
|
|
||||||
public static Type2CharStrings Parse([NotNull] IReadOnlyList<IReadOnlyList<byte>> charStringBytes,
|
public static Type2CharStrings Parse([NotNull] IReadOnlyList<IReadOnlyList<byte>> charStringBytes,
|
||||||
[NotNull] CompactFontFormatIndex localSubroutines,
|
[NotNull] CompactFontFormatIndex localSubroutines,
|
||||||
[NotNull] CompactFontFormatIndex globalSubroutines)
|
[NotNull] CompactFontFormatIndex globalSubroutines, ICompactFontFormatCharset charset)
|
||||||
{
|
{
|
||||||
if (charStringBytes == null)
|
if (charStringBytes == null)
|
||||||
{
|
{
|
||||||
@@ -690,12 +696,12 @@
|
|||||||
throw new ArgumentNullException(nameof(globalSubroutines));
|
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++)
|
for (var i = 0; i < charStringBytes.Count; i++)
|
||||||
{
|
{
|
||||||
var charString = charStringBytes[i];
|
var charString = charStringBytes[i];
|
||||||
var sequence = ParseSingle(charString);
|
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>());
|
return new Type2CharStrings(charStrings, new Dictionary<int, Type2CharStrings.CommandSequence>());
|
||||||
|
@@ -10,11 +10,11 @@
|
|||||||
private readonly object locker = new object();
|
private readonly object locker = new object();
|
||||||
private readonly Dictionary<string, CharacterPath> glyphs = new Dictionary<string, CharacterPath>();
|
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 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));
|
CharStrings = charStrings ?? throw new ArgumentNullException(nameof(charStrings));
|
||||||
Subroutines = subroutines ?? throw new ArgumentNullException(nameof(subroutines));
|
Subroutines = subroutines ?? throw new ArgumentNullException(nameof(subroutines));
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
return result;
|
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.");
|
throw new InvalidOperationException($"No charstring sequence with the name /{name} in this font.");
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
public virtual string GetNameByGlyphId(int glyphId)
|
public virtual string GetNameByGlyphId(int glyphId)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return GlyphIdToStringIdAndName[glyphId].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual string GetNameByStringId(int stringId)
|
public virtual string GetNameByStringId(int stringId)
|
||||||
|
@@ -195,7 +195,7 @@
|
|||||||
|
|
||||||
public string GetNameByGlyphId(int glyphId)
|
public string GetNameByGlyphId(int glyphId)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
return characterIdToStringIdAndName[glyphId].Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetNameByStringId(int stringId)
|
public string GetNameByStringId(int stringId)
|
||||||
|
@@ -116,7 +116,7 @@
|
|||||||
|
|
||||||
public string GetNameByGlyphId(int glyphId)
|
public string GetNameByGlyphId(int glyphId)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
return characterIdToStringIdAndName[glyphId].Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetNameByStringId(int stringId)
|
public string GetNameByStringId(int stringId)
|
||||||
|
@@ -258,7 +258,7 @@
|
|||||||
|
|
||||||
public string GetNameByGlyphId(int glyphId)
|
public string GetNameByGlyphId(int glyphId)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
return characterIdToStringIdAndName[glyphId].Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetNameByStringId(int stringId)
|
public string GetNameByStringId(int stringId)
|
||||||
|
@@ -3,7 +3,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using Charsets;
|
using Charsets;
|
||||||
using CharStrings;
|
using CharStrings;
|
||||||
using Dictionaries;
|
using Dictionaries;
|
||||||
@@ -108,12 +110,11 @@
|
|||||||
var numberInRange = format == 1 ? data.ReadCard8() : data.ReadCard16();
|
var numberInRange = format == 1 ? data.ReadCard8() : data.ReadCard16();
|
||||||
|
|
||||||
glyphToNamesAndStringId.Add((glyphId, firstSid, ReadString(firstSid, stringIndex)));
|
glyphToNamesAndStringId.Add((glyphId, firstSid, ReadString(firstSid, stringIndex)));
|
||||||
glyphId++;
|
|
||||||
for (var i = 0; i < numberInRange; i++)
|
for (var i = 0; i < numberInRange; i++)
|
||||||
{
|
{
|
||||||
|
glyphId++;
|
||||||
var sid = firstSid + i + 1;
|
var sid = firstSid + i + 1;
|
||||||
glyphToNamesAndStringId.Add((glyphId, sid, ReadString(sid, stringIndex)));
|
glyphToNamesAndStringId.Add((glyphId, sid, ReadString(sid, stringIndex)));
|
||||||
glyphId++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +143,7 @@
|
|||||||
case CompactFontFormatCharStringType.Type1:
|
case CompactFontFormatCharStringType.Type1:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
case CompactFontFormatCharStringType.Type2:
|
case CompactFontFormatCharStringType.Type2:
|
||||||
charStrings = Type2CharStringParser.Parse(charStringIndex, localSubroutines, globalSubroutineIndex);
|
charStrings = Type2CharStringParser.Parse(charStringIndex, localSubroutines, globalSubroutineIndex, charset);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException($"Unexpected CharString type in CFF font: {topDictionary.CharStringType}.");
|
throw new ArgumentOutOfRangeException($"Unexpected CharString type in CFF font: {topDictionary.CharStringType}.");
|
||||||
@@ -150,11 +151,17 @@
|
|||||||
|
|
||||||
if (Debugger.IsAttached)
|
if (Debugger.IsAttached)
|
||||||
{
|
{
|
||||||
|
var builder = new StringBuilder("<!DOCTYPE html><html><head></head><body>");
|
||||||
foreach (var pair in charStrings.CharStrings)
|
foreach (var pair in charStrings.CharStrings)
|
||||||
{
|
{
|
||||||
var path = Type2CharStrings.Run(pair.Value);
|
var path = Type2CharStrings.Run(pair.Value);
|
||||||
var svg = path.ToFullSvg();
|
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));
|
return new CompactFontFormatFont(topDictionary, privateDictionary, charset, Union<Type1CharStrings, Type2CharStrings>.Two(charStrings));
|
||||||
|
Reference in New Issue
Block a user