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.Globalization;
@@ -11,6 +13,9 @@
/// </summary>
public static class AdobeFontMetricsParser
{
private static readonly object Locker = new object();
private static readonly Dictionary<string, string> CharacterNames = new Dictionary<string, string>();
/// <summary>
/// This is a comment in a AFM file.
/// </summary>
@@ -603,7 +608,18 @@
}
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;
}
case CharmetricsB:

View File

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

View File

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

View File

@@ -3,31 +3,31 @@
/// <summary>
/// Direction of the text.
/// </summary>
public enum TextDirection
public enum TextDirection : byte
{
/// <summary>
/// Other text direction.
/// </summary>
Other,
Other = 0,
/// <summary>
/// Usual text direction (Left to Right).
/// </summary>
Horizontal,
Horizontal = 1,
/// <summary>
/// Horizontal text, upside down.
/// </summary>
Rotate180,
Rotate180 = 2,
/// <summary>
/// Rotated text going down.
/// </summary>
Rotate90,
Rotate90 = 3,
/// <summary>
/// Rotated text going up.
/// </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
{
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);
mutable.Transform(second);
mutable.Transform(third);
var topLeftX = tl.X;
var topLeftY = tl.Y;
return mutable.ToRectangle();
}
var topRightX = tr.X;
var topRightY = tr.Y;
private struct MutableRectangle
{
private double topLeftX;
private double topLeftY;
var bottomLeftX = bl.X;
var bottomLeftY = bl.Y;
private double topRightX;
private double topRightY;
var bottomRightX = br.X;
var bottomRightY = br.Y;
private double bottomLeftX;
private double bottomLeftY;
private double bottomRightX;
private double bottomRightY;
public MutableRectangle(PdfRectangle rectangle)
{
topLeftX = rectangle.TopLeft.X;
topLeftY = rectangle.TopLeft.Y;
topRightX = rectangle.TopRight.X;
topRightY = rectangle.TopRight.Y;
bottomLeftX = rectangle.BottomLeft.X;
bottomLeftY = rectangle.BottomLeft.Y;
bottomRightX = rectangle.BottomRight.X;
bottomRightY = rectangle.BottomRight.Y;
}
public void Transform(TransformationMatrix matrix)
{
/*
* TransformationMatrix.Transform(PdfPoint original)
* 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;
var y = matrix.B * topLeftX + matrix.D * topLeftY + matrix.F;
// First
var x = first.A * topLeftX + first.C * topLeftY + first.E;
var y = first.B * topLeftX + first.D * topLeftY + first.F;
topLeftX = x;
topLeftY = y;
x = matrix.A * topRightX + matrix.C * topRightY + matrix.E;
y = matrix.B * topRightX + matrix.D * topRightY + matrix.F;
x = first.A * topRightX + first.C * topRightY + first.E;
y = first.B * topRightX + first.D * topRightY + first.F;
topRightX = x;
topRightY = y;
x = matrix.A * bottomLeftX + matrix.C * bottomLeftY + matrix.E;
y = matrix.B * bottomLeftX + matrix.D * bottomLeftY + matrix.F;
x = first.A * bottomLeftX + first.C * bottomLeftY + first.E;
y = first.B * bottomLeftX + first.D * bottomLeftY + first.F;
bottomLeftX = x;
bottomLeftY = y;
x = matrix.A * bottomRightX + matrix.C * bottomRightY + matrix.E;
y = matrix.B * bottomRightX + matrix.D * bottomRightY + matrix.F;
x = first.A * bottomRightX + first.C * bottomRightY + first.E;
y = first.B * bottomRightX + first.D * bottomRightY + first.F;
bottomRightX = x;
bottomRightY = y;
// Second
x = second.A * topLeftX + second.C * topLeftY + second.E;
y = second.B * topLeftX + second.D * topLeftY + second.F;
topLeftX = x;
topLeftY = y;
x = second.A * topRightX + second.C * topRightY + second.E;
y = second.B * topRightX + second.D * topRightY + second.F;
topRightX = x;
topRightY = y;
x = second.A * bottomLeftX + second.C * bottomLeftY + second.E;
y = second.B * bottomLeftX + second.D * bottomLeftY + second.F;
bottomLeftX = x;
bottomLeftY = y;
x = second.A * bottomRightX + second.C * bottomRightY + second.E;
y = second.B * bottomRightX + second.D * bottomRightY + second.F;
bottomRightX = x;
bottomRightY = y;
// Third
x = third.A * topLeftX + third.C * topLeftY + third.E;
y = third.B * topLeftX + third.D * topLeftY + third.F;
topLeftX = x;
topLeftY = y;
x = third.A * topRightX + third.C * topRightY + third.E;
y = third.B * topRightX + third.D * topRightY + third.F;
topRightX = x;
topRightY = y;
x = third.A * bottomLeftX + third.C * bottomLeftY + third.E;
y = third.B * bottomLeftX + third.D * bottomLeftY + third.F;
bottomLeftX = x;
bottomLeftY = y;
x = third.A * bottomRightX + third.C * bottomRightY + third.E;
y = third.B * bottomRightX + third.D * bottomRightY + third.F;
bottomRightX = x;
bottomRightY = y;
}
public PdfRectangle ToRectangle()
{
return new PdfRectangle(new PdfPoint(topLeftX, topLeftY), new PdfPoint(topRightX, topRightY),
new PdfPoint(bottomLeftX, bottomLeftY), new PdfPoint(bottomRightX, bottomRightY));
}
}
}
}