mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-20 03:17:57 +08:00
inline transformation code and cache afm strings
This commit is contained in:
@@ -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:
|
||||
|
@@ -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.
|
||||
|
@@ -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>
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user