inline transformation code and cache afm strings

This commit is contained in:
Eliot Jones
2020-04-18 13:56:39 +01:00
parent db442194c3
commit b122bf0ca6
5 changed files with 106 additions and 83 deletions

View File

@@ -1,4 +1,6 @@
namespace UglyToad.PdfPig.Fonts.AdobeFontMetrics using System.Collections.Generic;
namespace UglyToad.PdfPig.Fonts.AdobeFontMetrics
{ {
using System; using System;
using System.Globalization; using System.Globalization;
@@ -11,6 +13,9 @@
/// </summary> /// </summary>
public static class AdobeFontMetricsParser public static class AdobeFontMetricsParser
{ {
private static readonly object Locker = new object();
private static readonly Dictionary<string, string> CharacterNames = new Dictionary<string, string>();
/// <summary> /// <summary>
/// This is a comment in a AFM file. /// This is a comment in a AFM file.
/// </summary> /// </summary>
@@ -603,7 +608,18 @@
} }
case CharmetricsN: case CharmetricsN:
{ {
metric.Name = parts[1]; lock (Locker)
{
var name = parts[1];
if (!CharacterNames.TryGetValue(name, out var cached))
{
cached = name;
CharacterNames[name] = cached;
}
metric.Name = cached;
}
break; break;
} }
case CharmetricsB: case CharmetricsB:

View File

@@ -3,7 +3,7 @@
/// <summary> /// <summary>
/// The meaning of the metric sets field. /// The meaning of the metric sets field.
/// </summary> /// </summary>
public enum AdobeFontMetricsWritingDirections public enum AdobeFontMetricsWritingDirections : byte
{ {
/// <summary> /// <summary>
/// Writing direction 0 only. /// Writing direction 0 only.

View File

@@ -33,8 +33,8 @@
{ {
private static readonly HashSet<string> Standard14Names = new HashSet<string>(); private static readonly HashSet<string> Standard14Names = new HashSet<string>();
private static readonly Dictionary<string, string> Standard14Mapping = new Dictionary<string, string>(34); private static readonly Dictionary<string, string> Standard14Mapping = new Dictionary<string, string>(34);
private static readonly Dictionary<string, AdobeFontMetrics> Standard14AfmMap = new Dictionary<string, AdobeFontMetrics>(34); private static readonly Dictionary<Standard14Font, string> BuilderTypesToNames = new Dictionary<Standard14Font, string>(14);
private static readonly Dictionary<Standard14Font, AdobeFontMetrics> Standard14AfmTypeMap = new Dictionary<Standard14Font, AdobeFontMetrics>(14); private static readonly Dictionary<string, AdobeFontMetrics> Standard14Cache = new Dictionary<string, AdobeFontMetrics>(34);
static Standard14() static Standard14()
{ {
@@ -88,9 +88,14 @@
Standard14Names.Add(fontName); Standard14Names.Add(fontName);
Standard14Mapping.Add(fontName, afmName); Standard14Mapping.Add(fontName, afmName);
if (Standard14AfmMap.TryGetValue(afmName, out var metrics)) if (type.HasValue)
{ {
Standard14AfmMap[fontName] = metrics; BuilderTypesToNames[type.Value] = afmName;
}
if (Standard14Cache.TryGetValue(afmName, out var metrics))
{
Standard14Cache[fontName] = metrics;
} }
try try
@@ -112,11 +117,7 @@
bytes = new ByteArrayInputBytes(memory.ToArray()); bytes = new ByteArrayInputBytes(memory.ToArray());
} }
Standard14AfmMap[fontName] = AdobeFontMetricsParser.Parse(bytes, true); Standard14Cache[fontName] = AdobeFontMetricsParser.Parse(bytes, true);
if (type.HasValue)
{
Standard14AfmTypeMap[type.Value] = Standard14AfmMap[fontName];
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -130,7 +131,7 @@
/// </summary> /// </summary>
public static AdobeFontMetrics GetAdobeFontMetrics(string baseName) public static AdobeFontMetrics GetAdobeFontMetrics(string baseName)
{ {
Standard14AfmMap.TryGetValue(baseName, out var metrics); Standard14Cache.TryGetValue(baseName, out var metrics);
return metrics; return metrics;
} }
@@ -140,7 +141,7 @@
/// </summary> /// </summary>
public static AdobeFontMetrics GetAdobeFontMetrics(Standard14Font fontType) public static AdobeFontMetrics GetAdobeFontMetrics(Standard14Font fontType)
{ {
return Standard14AfmTypeMap[fontType]; return Standard14Cache[BuilderTypesToNames[fontType]];
} }
/// <summary> /// <summary>

View File

@@ -3,31 +3,31 @@
/// <summary> /// <summary>
/// Direction of the text. /// Direction of the text.
/// </summary> /// </summary>
public enum TextDirection public enum TextDirection : byte
{ {
/// <summary> /// <summary>
/// Other text direction. /// Other text direction.
/// </summary> /// </summary>
Other, Other = 0,
/// <summary> /// <summary>
/// Usual text direction (Left to Right). /// Usual text direction (Left to Right).
/// </summary> /// </summary>
Horizontal, Horizontal = 1,
/// <summary> /// <summary>
/// Horizontal text, upside down. /// Horizontal text, upside down.
/// </summary> /// </summary>
Rotate180, Rotate180 = 2,
/// <summary> /// <summary>
/// Rotated text going down. /// Rotated text going down.
/// </summary> /// </summary>
Rotate90, Rotate90 = 3,
/// <summary> /// <summary>
/// Rotated text going up. /// Rotated text going up.
/// </summary> /// </summary>
Rotate270 Rotate270 = 4
} }
} }

View File

@@ -1,87 +1,93 @@
using UglyToad.PdfPig.Core; namespace UglyToad.PdfPig.Graphics
namespace UglyToad.PdfPig.Graphics
{ {
using PdfPig.Core;
internal static class PerformantRectangleTransformer internal static class PerformantRectangleTransformer
{ {
public static PdfRectangle Transform(TransformationMatrix first, TransformationMatrix second, TransformationMatrix third, PdfRectangle rectangle) public static PdfRectangle Transform(TransformationMatrix first, TransformationMatrix second, TransformationMatrix third, PdfRectangle rectangle)
{ {
var mutable = new MutableRectangle(rectangle); var tl = rectangle.TopLeft;
var tr = rectangle.TopRight;
var bl = rectangle.BottomLeft;
var br = rectangle.BottomRight;
mutable.Transform(first); var topLeftX = tl.X;
mutable.Transform(second); var topLeftY = tl.Y;
mutable.Transform(third);
return mutable.ToRectangle(); var topRightX = tr.X;
} var topRightY = tr.Y;
private struct MutableRectangle var bottomLeftX = bl.X;
{ var bottomLeftY = bl.Y;
private double topLeftX;
private double topLeftY;
private double topRightX; var bottomRightX = br.X;
private double topRightY; var bottomRightY = br.Y;
private double bottomLeftX; // First
private double bottomLeftY; var x = first.A * topLeftX + first.C * topLeftY + first.E;
var y = first.B * topLeftX + first.D * topLeftY + first.F;
topLeftX = x;
topLeftY = y;
private double bottomRightX; x = first.A * topRightX + first.C * topRightY + first.E;
private double bottomRightY; y = first.B * topRightX + first.D * topRightY + first.F;
topRightX = x;
topRightY = y;
public MutableRectangle(PdfRectangle rectangle) x = first.A * bottomLeftX + first.C * bottomLeftY + first.E;
{ y = first.B * bottomLeftX + first.D * bottomLeftY + first.F;
topLeftX = rectangle.TopLeft.X; bottomLeftX = x;
topLeftY = rectangle.TopLeft.Y; bottomLeftY = y;
topRightX = rectangle.TopRight.X; x = first.A * bottomRightX + first.C * bottomRightY + first.E;
topRightY = rectangle.TopRight.Y; y = first.B * bottomRightX + first.D * bottomRightY + first.F;
bottomRightX = x;
bottomRightY = y;
bottomLeftX = rectangle.BottomLeft.X; // Second
bottomLeftY = rectangle.BottomLeft.Y; x = second.A * topLeftX + second.C * topLeftY + second.E;
y = second.B * topLeftX + second.D * topLeftY + second.F;
topLeftX = x;
topLeftY = y;
bottomRightX = rectangle.BottomRight.X; x = second.A * topRightX + second.C * topRightY + second.E;
bottomRightY = rectangle.BottomRight.Y; y = second.B * topRightX + second.D * topRightY + second.F;
} topRightX = x;
topRightY = y;
public void Transform(TransformationMatrix matrix) x = second.A * bottomLeftX + second.C * bottomLeftY + second.E;
{ y = second.B * bottomLeftX + second.D * bottomLeftY + second.F;
/* bottomLeftX = x;
* TransformationMatrix.Transform(PdfPoint original) bottomLeftY = y;
* var x = A * original.X + C * original.Y + E;
* var y = B * original.X + D * original.Y + F;
* return new PdfPoint(x, y);
*
* For a rectangle runs on TopLeft, TopRight, BottomLeft and BottomRight
* and returns a new rectangle.
*/
var x = matrix.A * topLeftX + matrix.C * topLeftY + matrix.E; x = second.A * bottomRightX + second.C * bottomRightY + second.E;
var y = matrix.B * topLeftX + matrix.D * topLeftY + matrix.F; y = second.B * bottomRightX + second.D * bottomRightY + second.F;
topLeftX = x; bottomRightX = x;
topLeftY = y; bottomRightY = y;
x = matrix.A * topRightX + matrix.C * topRightY + matrix.E; // Third
y = matrix.B * topRightX + matrix.D * topRightY + matrix.F; x = third.A * topLeftX + third.C * topLeftY + third.E;
topRightX = x; y = third.B * topLeftX + third.D * topLeftY + third.F;
topRightY = y; topLeftX = x;
topLeftY = y;
x = matrix.A * bottomLeftX + matrix.C * bottomLeftY + matrix.E; x = third.A * topRightX + third.C * topRightY + third.E;
y = matrix.B * bottomLeftX + matrix.D * bottomLeftY + matrix.F; y = third.B * topRightX + third.D * topRightY + third.F;
bottomLeftX = x; topRightX = x;
bottomLeftY = y; topRightY = y;
x = matrix.A * bottomRightX + matrix.C * bottomRightY + matrix.E; x = third.A * bottomLeftX + third.C * bottomLeftY + third.E;
y = matrix.B * bottomRightX + matrix.D * bottomRightY + matrix.F; y = third.B * bottomLeftX + third.D * bottomLeftY + third.F;
bottomRightX = x; bottomLeftX = x;
bottomRightY = y; bottomLeftY = y;
}
public PdfRectangle ToRectangle() x = third.A * bottomRightX + third.C * bottomRightY + third.E;
{ y = third.B * bottomRightX + third.D * bottomRightY + third.F;
return new PdfRectangle(new PdfPoint(topLeftX, topLeftY), new PdfPoint(topRightX, topRightY), bottomRightX = x;
new PdfPoint(bottomLeftX, bottomLeftY), new PdfPoint(bottomRightX, bottomRightY)); bottomRightY = y;
}
return new PdfRectangle(new PdfPoint(topLeftX, topLeftY), new PdfPoint(topRightX, topRightY),
new PdfPoint(bottomLeftX, bottomLeftY), new PdfPoint(bottomRightX, bottomRightY));
} }
} }
} }