mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-21 04:17:57 +08:00
#75 support vertical writing mode fonts
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
namespace UglyToad.PdfPig.Tests.Fonts.CidFonts
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using PdfPig.Fonts.CidFonts;
|
||||||
|
using PdfPig.Geometry;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class VerticalWritingMetricsTests
|
||||||
|
{
|
||||||
|
private readonly VerticalVectorComponents defaults = new VerticalVectorComponents(250, 600);
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void UsesDefaultWhenOverridesNull()
|
||||||
|
{
|
||||||
|
var data = new VerticalWritingMetrics(defaults, null, null);
|
||||||
|
|
||||||
|
Assert.Empty(data.IndividualVerticalWritingDisplacements);
|
||||||
|
Assert.Empty(data.IndividualVerticalWritingPositions);
|
||||||
|
|
||||||
|
var position = data.GetPositionVector(60, 250);
|
||||||
|
Assert.Equal(defaults.Position, position.Y);
|
||||||
|
|
||||||
|
var displacement = data.GetDisplacementVector(32);
|
||||||
|
Assert.Equal(defaults.Displacement, displacement.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DefaultXComponentsOfVectorsAreCorrect()
|
||||||
|
{
|
||||||
|
var data = new VerticalWritingMetrics(defaults, null, null);
|
||||||
|
|
||||||
|
var position = data.GetPositionVector(9, 120);
|
||||||
|
Assert.Equal(120 / 2m, position.X);
|
||||||
|
|
||||||
|
var displacement = data.GetDisplacementVector(10);
|
||||||
|
Assert.Equal(0m, displacement.X);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void UsesVectorOverridesWhenPresent()
|
||||||
|
{
|
||||||
|
var data = new VerticalWritingMetrics(defaults, new Dictionary<int, decimal> {{7, 120}},
|
||||||
|
new Dictionary<int, PdfVector> {{7, new PdfVector(25, 250)}});
|
||||||
|
|
||||||
|
var position = data.GetPositionVector(7, 360);
|
||||||
|
Assert.Equal(25, position.X);
|
||||||
|
Assert.Equal(250, position.Y);
|
||||||
|
|
||||||
|
var displacement = data.GetDisplacementVector(7);
|
||||||
|
Assert.Equal(0, displacement.X);
|
||||||
|
Assert.Equal(120, displacement.Y);
|
||||||
|
|
||||||
|
var defaultPosition = data.GetPositionVector(6, 100);
|
||||||
|
Assert.Equal(50, defaultPosition.X);
|
||||||
|
Assert.Equal(defaults.Position, defaultPosition.Y);
|
||||||
|
|
||||||
|
var defaultDisplacement = data.GetDisplacementVector(6);
|
||||||
|
Assert.Equal(0, defaultDisplacement.X);
|
||||||
|
Assert.Equal(defaults.Displacement, defaultDisplacement.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -45,5 +45,9 @@
|
|||||||
decimal GetWidthFromFont(int characterIdentifier);
|
decimal GetWidthFromFont(int characterIdentifier);
|
||||||
|
|
||||||
PdfRectangle GetBoundingBox(int characterIdentifier);
|
PdfRectangle GetBoundingBox(int characterIdentifier);
|
||||||
|
|
||||||
|
PdfVector GetPositionVector(int characterIdentifier);
|
||||||
|
|
||||||
|
PdfVector GetDisplacementVector(int characterIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -14,20 +14,30 @@
|
|||||||
internal class Type0CidFont : ICidFont
|
internal class Type0CidFont : ICidFont
|
||||||
{
|
{
|
||||||
private readonly ICidFontProgram fontProgram;
|
private readonly ICidFontProgram fontProgram;
|
||||||
|
private readonly VerticalWritingMetrics verticalWritingMetrics;
|
||||||
|
|
||||||
public NameToken Type { get; }
|
public NameToken Type { get; }
|
||||||
|
|
||||||
public NameToken SubType { get; }
|
public NameToken SubType { get; }
|
||||||
|
|
||||||
public NameToken BaseFont { get; }
|
public NameToken BaseFont { get; }
|
||||||
|
|
||||||
public CharacterIdentifierSystemInfo SystemInfo { get; }
|
public CharacterIdentifierSystemInfo SystemInfo { get; }
|
||||||
|
|
||||||
public TransformationMatrix FontMatrix { get; }
|
public TransformationMatrix FontMatrix { get; }
|
||||||
|
|
||||||
public CidFontType CidFontType => CidFontType.Type0;
|
public CidFontType CidFontType => CidFontType.Type0;
|
||||||
|
|
||||||
public FontDescriptor Descriptor { get; }
|
public FontDescriptor Descriptor { get; }
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, decimal> Widths { get; }
|
public IReadOnlyDictionary<int, decimal> Widths { get; }
|
||||||
|
|
||||||
public Type0CidFont(ICidFontProgram fontProgram, NameToken type, NameToken subType, NameToken baseFont,
|
public Type0CidFont(ICidFontProgram fontProgram, NameToken type, NameToken subType, NameToken baseFont,
|
||||||
CharacterIdentifierSystemInfo systemInfo,
|
CharacterIdentifierSystemInfo systemInfo,
|
||||||
FontDescriptor descriptor, IReadOnlyDictionary<int, decimal> widths)
|
FontDescriptor descriptor, VerticalWritingMetrics verticalWritingMetrics, IReadOnlyDictionary<int, decimal> widths)
|
||||||
{
|
{
|
||||||
this.fontProgram = fontProgram;
|
this.fontProgram = fontProgram;
|
||||||
|
this.verticalWritingMetrics = verticalWritingMetrics;
|
||||||
Type = type;
|
Type = type;
|
||||||
SubType = subType;
|
SubType = subType;
|
||||||
BaseFont = baseFont;
|
BaseFont = baseFont;
|
||||||
@@ -56,7 +66,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: correct values
|
// TODO: correct values
|
||||||
return 250;
|
if (Descriptor == null)
|
||||||
|
{
|
||||||
|
return 250;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Descriptor.MissingWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetBoundingBox(int characterIdentifier)
|
public PdfRectangle GetBoundingBox(int characterIdentifier)
|
||||||
@@ -79,5 +94,17 @@
|
|||||||
|
|
||||||
return new PdfRectangle(0, 0, 250, 0);
|
return new PdfRectangle(0, 0, 250, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PdfVector GetPositionVector(int characterIdentifier)
|
||||||
|
{
|
||||||
|
var width = GetWidthFromFont(characterIdentifier);
|
||||||
|
|
||||||
|
return verticalWritingMetrics.GetPositionVector(characterIdentifier, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PdfVector GetDisplacementVector(int characterIdentifier)
|
||||||
|
{
|
||||||
|
return verticalWritingMetrics.GetDisplacementVector(characterIdentifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,11 +18,17 @@
|
|||||||
private readonly CharacterIdentifierToGlyphIndexMap cidToGid;
|
private readonly CharacterIdentifierToGlyphIndexMap cidToGid;
|
||||||
|
|
||||||
public NameToken Type { get; }
|
public NameToken Type { get; }
|
||||||
|
|
||||||
public NameToken SubType { get; }
|
public NameToken SubType { get; }
|
||||||
|
|
||||||
public NameToken BaseFont { get; }
|
public NameToken BaseFont { get; }
|
||||||
|
|
||||||
public CharacterIdentifierSystemInfo SystemInfo { get; }
|
public CharacterIdentifierSystemInfo SystemInfo { get; }
|
||||||
|
|
||||||
public TransformationMatrix FontMatrix { get; }
|
public TransformationMatrix FontMatrix { get; }
|
||||||
|
|
||||||
public CidFontType CidFontType => CidFontType.Type2;
|
public CidFontType CidFontType => CidFontType.Type2;
|
||||||
|
|
||||||
public FontDescriptor Descriptor { get; }
|
public FontDescriptor Descriptor { get; }
|
||||||
|
|
||||||
public Type2CidFont(NameToken type, NameToken subType, NameToken baseFont, CharacterIdentifierSystemInfo systemInfo,
|
public Type2CidFont(NameToken type, NameToken subType, NameToken baseFont, CharacterIdentifierSystemInfo systemInfo,
|
||||||
@@ -85,5 +91,17 @@
|
|||||||
|
|
||||||
return Descriptor.BoundingBox;
|
return Descriptor.BoundingBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PdfVector GetPositionVector(int characterIdentifier)
|
||||||
|
{
|
||||||
|
var width = GetWidthFromFont(characterIdentifier);
|
||||||
|
|
||||||
|
return verticalWritingMetrics.GetPositionVector(characterIdentifier, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PdfVector GetDisplacementVector(int characterIdentifier)
|
||||||
|
{
|
||||||
|
return verticalWritingMetrics.GetDisplacementVector(characterIdentifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,20 +1,60 @@
|
|||||||
namespace UglyToad.PdfPig.Fonts.CidFonts
|
namespace UglyToad.PdfPig.Fonts.CidFonts
|
||||||
{
|
{
|
||||||
|
using Geometry;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to the DW2 array in the font dictionary for vertical fonts.
|
/// Defines the default position and displacement vector vertical components
|
||||||
|
/// for fonts which have vertical writing modes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal struct VerticalVectorComponents
|
internal struct VerticalVectorComponents
|
||||||
{
|
{
|
||||||
public decimal Position { get; }
|
/// <summary>
|
||||||
|
/// The default value of <see cref="VerticalVectorComponents"/> if not defined by a font.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly VerticalVectorComponents Default = new VerticalVectorComponents(800, -1000);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The vertical component of the position vector.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The full position vector unless overridden by the W2 array is:
|
||||||
|
/// (w0/2, Position)
|
||||||
|
/// Where w0 is the width of the given glyph.
|
||||||
|
/// </remarks>
|
||||||
|
public decimal Position { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The vertical component of the displacement vector.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The full displacement vector is:
|
||||||
|
/// (0, Displacement)
|
||||||
|
/// </remarks>
|
||||||
public decimal Displacement { get; }
|
public decimal Displacement { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="VerticalVectorComponents"/>.
|
||||||
|
/// </summary>
|
||||||
public VerticalVectorComponents(decimal position, decimal displacement)
|
public VerticalVectorComponents(decimal position, decimal displacement)
|
||||||
{
|
{
|
||||||
Position = position;
|
Position = position;
|
||||||
Displacement = displacement;
|
Displacement = displacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VerticalVectorComponents Default = new VerticalVectorComponents(800, -1000);
|
/// <summary>
|
||||||
|
/// Get the full position vector for a given glyph.
|
||||||
|
/// </summary>
|
||||||
|
public PdfVector GetPositionVector(decimal glyphWidth) => new PdfVector(glyphWidth / 2m, Position);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the full displacement vector.
|
||||||
|
/// </summary>
|
||||||
|
public PdfVector GetDisplacementVector() => new PdfVector(0, Displacement);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"Position: {Position}, Displacement: {Displacement}.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -2,20 +2,70 @@
|
|||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Geometry;
|
using Geometry;
|
||||||
|
using Util.JetBrains.Annotations;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Glyphs from fonts which support vertical writing mode define displacement and position vectors.
|
||||||
|
/// The position vector specifies how the horizontal writing origin is transformed into the vertical writing origin.
|
||||||
|
/// The displacement vector specifies how far to move vertically before drawing the next glyph.
|
||||||
|
/// </summary>
|
||||||
internal class VerticalWritingMetrics
|
internal class VerticalWritingMetrics
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The default position and displacement vectors where not overridden.
|
||||||
|
/// </summary>
|
||||||
public VerticalVectorComponents DefaultVerticalWritingMetrics { get; }
|
public VerticalVectorComponents DefaultVerticalWritingMetrics { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides displacement vector y components for glyphs specified by CID code.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
public IReadOnlyDictionary<int, decimal> IndividualVerticalWritingDisplacements { get; }
|
public IReadOnlyDictionary<int, decimal> IndividualVerticalWritingDisplacements { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides position vector (x and y) components for glyphs specified by CID code.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
public IReadOnlyDictionary<int, PdfVector> IndividualVerticalWritingPositions { get; }
|
public IReadOnlyDictionary<int, PdfVector> IndividualVerticalWritingPositions { get; }
|
||||||
|
|
||||||
public VerticalWritingMetrics(VerticalVectorComponents defaultVerticalWritingMetrics, IReadOnlyDictionary<int, decimal> individualVerticalWritingDisplacements, IReadOnlyDictionary<int, PdfVector> individualVerticalWritingPositions)
|
/// <summary>
|
||||||
|
/// Create new <see cref="VerticalWritingMetrics"/>.
|
||||||
|
/// </summary>
|
||||||
|
public VerticalWritingMetrics(VerticalVectorComponents defaultVerticalWritingMetrics,
|
||||||
|
[CanBeNull] IReadOnlyDictionary<int, decimal> individualVerticalWritingDisplacements,
|
||||||
|
[CanBeNull] IReadOnlyDictionary<int, PdfVector> individualVerticalWritingPositions)
|
||||||
{
|
{
|
||||||
DefaultVerticalWritingMetrics = defaultVerticalWritingMetrics;
|
DefaultVerticalWritingMetrics = defaultVerticalWritingMetrics;
|
||||||
IndividualVerticalWritingDisplacements = individualVerticalWritingDisplacements;
|
IndividualVerticalWritingDisplacements = individualVerticalWritingDisplacements
|
||||||
IndividualVerticalWritingPositions = individualVerticalWritingPositions;
|
?? new Dictionary<int, decimal>(0);
|
||||||
|
IndividualVerticalWritingPositions = individualVerticalWritingPositions
|
||||||
|
?? new Dictionary<int, PdfVector>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the position vector used to convert horizontal glyph origin to vertical origin.
|
||||||
|
/// </summary>
|
||||||
|
public PdfVector GetPositionVector(int characterIdentifier, decimal glyphWidth)
|
||||||
|
{
|
||||||
|
if (IndividualVerticalWritingPositions.TryGetValue(characterIdentifier, out var vector))
|
||||||
|
{
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefaultVerticalWritingMetrics.GetPositionVector(glyphWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the displacement vector used to move the origin to the next glyph location after drawing.
|
||||||
|
/// </summary>
|
||||||
|
public PdfVector GetDisplacementVector(int characterIdentifier)
|
||||||
|
{
|
||||||
|
if (IndividualVerticalWritingDisplacements.TryGetValue(characterIdentifier, out var displacementY))
|
||||||
|
{
|
||||||
|
return new PdfVector(0, displacementY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefaultVerticalWritingMetrics.GetDisplacementVector();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines glyphs using a CIDFont
|
/// Defines glyphs using a CIDFont
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class Type0Font : IFont
|
internal class Type0Font : IFont, IVerticalWritingSupported
|
||||||
{
|
{
|
||||||
public NameToken Name => BaseFont;
|
public NameToken Name => BaseFont;
|
||||||
|
|
||||||
@@ -97,5 +97,19 @@
|
|||||||
{
|
{
|
||||||
return CidFont.FontMatrix;
|
return CidFont.FontMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PdfVector GetPositionVector(int characterCode)
|
||||||
|
{
|
||||||
|
var characterIdentifier = CMap.ConvertToCid(characterCode);
|
||||||
|
|
||||||
|
return CidFont.GetPositionVector(characterIdentifier).Scale(-1 / 1000m);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PdfVector GetDisplacementVector(int characterCode)
|
||||||
|
{
|
||||||
|
var characterIdentifier = CMap.ConvertToCid(characterCode);
|
||||||
|
|
||||||
|
return CidFont.GetDisplacementVector(characterIdentifier).Scale(1 / 1000m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
src/UglyToad.PdfPig/Fonts/IVerticalWritingSupported.cs
Normal file
18
src/UglyToad.PdfPig/Fonts/IVerticalWritingSupported.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
namespace UglyToad.PdfPig.Fonts
|
||||||
|
{
|
||||||
|
using Geometry;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A font which supports a vertical writing mode in addition to the default horizontal writing mode.
|
||||||
|
/// </summary>
|
||||||
|
internal interface IVerticalWritingSupported
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// In vertical fonts the glyph position is described by a position vector from the origin used for horizontal writing.
|
||||||
|
/// The position vector is applied to the horizontal writing origin to give a new vertical writing origin.
|
||||||
|
/// </summary>
|
||||||
|
PdfVector GetPositionVector(int characterCode);
|
||||||
|
|
||||||
|
PdfVector GetDisplacementVector(int characterCode);
|
||||||
|
}
|
||||||
|
}
|
@@ -62,7 +62,7 @@
|
|||||||
var subType = dictionary.GetNameOrDefault(NameToken.Subtype);
|
var subType = dictionary.GetNameOrDefault(NameToken.Subtype);
|
||||||
if (NameToken.CidFontType0.Equals(subType))
|
if (NameToken.CidFontType0.Equals(subType))
|
||||||
{
|
{
|
||||||
return new Type0CidFont(fontProgram, type, subType, baseFont, systemInfo, descriptor, widths);
|
return new Type0CidFont(fontProgram, type, subType, baseFont, systemInfo, descriptor, verticalWritingMetrics, widths);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NameToken.CidFontType2.Equals(subType))
|
if (NameToken.CidFontType2.Equals(subType))
|
||||||
@@ -160,18 +160,18 @@
|
|||||||
return widths;
|
return widths;
|
||||||
}
|
}
|
||||||
|
|
||||||
int size = widthArray.Data.Count;
|
var size = widthArray.Data.Count;
|
||||||
int counter = 0;
|
var counter = 0;
|
||||||
while (counter < size)
|
while (counter < size)
|
||||||
{
|
{
|
||||||
var firstCode = (NumericToken)widthArray.Data[counter++];
|
var firstCode = (NumericToken)widthArray.Data[counter++];
|
||||||
var next = widthArray.Data[counter++];
|
var next = widthArray.Data[counter++];
|
||||||
if (DirectObjectFinder.TryGet(next, pdfScanner, out ArrayToken array))
|
if (DirectObjectFinder.TryGet(next, pdfScanner, out ArrayToken array))
|
||||||
{
|
{
|
||||||
int startRange = firstCode.Int;
|
var startRange = firstCode.Int;
|
||||||
int arraySize = array.Data.Count;
|
var arraySize = array.Data.Count;
|
||||||
|
|
||||||
for (int i = 0; i < arraySize; i++)
|
for (var i = 0; i < arraySize; i++)
|
||||||
{
|
{
|
||||||
var width = (NumericToken)array.Data[i];
|
var width = (NumericToken)array.Data[i];
|
||||||
widths[startRange + i] = width.Data;
|
widths[startRange + i] = width.Data;
|
||||||
@@ -181,8 +181,8 @@
|
|||||||
{
|
{
|
||||||
var secondCode = (NumericToken)next;
|
var secondCode = (NumericToken)next;
|
||||||
var rangeWidth = (NumericToken)widthArray.Data[counter++];
|
var rangeWidth = (NumericToken)widthArray.Data[counter++];
|
||||||
int startRange = firstCode.Int;
|
var startRange = firstCode.Int;
|
||||||
int endRange = secondCode.Int;
|
var endRange = secondCode.Int;
|
||||||
var width = rangeWidth.Data;
|
var width = rangeWidth.Data;
|
||||||
for (var i = startRange; i <= endRange; i++)
|
for (var i = startRange; i <= endRange; i++)
|
||||||
{
|
{
|
||||||
@@ -199,10 +199,11 @@
|
|||||||
var verticalDisplacements = new Dictionary<int, decimal>();
|
var verticalDisplacements = new Dictionary<int, decimal>();
|
||||||
var positionVectors = new Dictionary<int, PdfVector>();
|
var positionVectors = new Dictionary<int, PdfVector>();
|
||||||
|
|
||||||
|
// The default position vector and displacement vector are specified by the DW2 entry.
|
||||||
VerticalVectorComponents dw2;
|
VerticalVectorComponents dw2;
|
||||||
if (!dict.TryGet(NameToken.Dw2, out var dw2Token) || !(dw2Token is ArrayToken arrayVerticalComponents))
|
if (!dict.TryGet(NameToken.Dw2, out var dw2Token) || !(dw2Token is ArrayToken arrayVerticalComponents))
|
||||||
{
|
{
|
||||||
dw2 = new VerticalVectorComponents(880, -1000);
|
dw2 = VerticalVectorComponents.Default;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -222,9 +223,10 @@
|
|||||||
|
|
||||||
if (next is ArrayToken array)
|
if (next is ArrayToken array)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < array.Data.Count; j++)
|
for (var j = 0; j < array.Data.Count; j++)
|
||||||
{
|
{
|
||||||
int cid = c.Int + j;
|
var cid = c.Int + j;
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
var w1y = (NumericToken)array.Data[j];
|
var w1y = (NumericToken)array.Data[j];
|
||||||
var v1x = (NumericToken)array.Data[++j];
|
var v1x = (NumericToken)array.Data[++j];
|
||||||
var v1y = (NumericToken)array.Data[++j];
|
var v1y = (NumericToken)array.Data[++j];
|
||||||
@@ -236,11 +238,12 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int first = c.Int;
|
var first = c.Int;
|
||||||
int last = ((NumericToken)next).Int;
|
var last = ((NumericToken)next).Int;
|
||||||
var w1y = (NumericToken)w2.Data[++i];
|
var w1y = (NumericToken)w2.Data[++i];
|
||||||
var v1x = (NumericToken)w2.Data[++i];
|
var v1x = (NumericToken)w2.Data[++i];
|
||||||
var v1y = (NumericToken)w2.Data[++i];
|
var v1y = (NumericToken)w2.Data[++i];
|
||||||
|
// ReSharper restore InconsistentNaming
|
||||||
|
|
||||||
for (var cid = first; cid <= last; cid++)
|
for (var cid = first; cid <= last; cid++)
|
||||||
{
|
{
|
||||||
|
@@ -181,21 +181,31 @@
|
|||||||
wordSpacing += GetCurrentState().FontState.WordSpacing;
|
wordSpacing += GetCurrentState().FontState.WordSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var textMatrix = TextMatrices.TextMatrix;
|
||||||
|
|
||||||
if (font.IsVertical)
|
if (font.IsVertical)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Vertical fonts are currently unsupported, please submit a pull request or issue with an example file.");
|
if (!(font is IVerticalWritingSupported verticalFont))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Font {font.Name} was in vertical writing mode but did not implement {nameof(IVerticalWritingSupported)}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var positionVector = verticalFont.GetPositionVector(code);
|
||||||
|
|
||||||
|
textMatrix = textMatrix.Translate(positionVector.X, positionVector.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
var boundingBox = font.GetBoundingBox(code);
|
var boundingBox = font.GetBoundingBox(code);
|
||||||
|
|
||||||
var transformedGlyphBounds = rotation.Rotate(transformationMatrix)
|
var transformedGlyphBounds = rotation.Rotate(transformationMatrix)
|
||||||
.Transform(TextMatrices.TextMatrix
|
.Transform(textMatrix
|
||||||
.Transform(renderingMatrix
|
.Transform(renderingMatrix
|
||||||
.Transform(boundingBox.GlyphBounds)));
|
.Transform(boundingBox.GlyphBounds)));
|
||||||
|
|
||||||
var transformedPdfBounds = rotation.Rotate(transformationMatrix)
|
var transformedPdfBounds = rotation.Rotate(transformationMatrix)
|
||||||
.Transform(TextMatrices.TextMatrix
|
.Transform(textMatrix
|
||||||
.Transform(renderingMatrix.Transform(new PdfRectangle(0, 0, boundingBox.Width, 0))));
|
.Transform(renderingMatrix
|
||||||
|
.Transform(new PdfRectangle(0, 0, boundingBox.Width, 0))));
|
||||||
|
|
||||||
// If the text rendering mode calls for filling, the current nonstroking color in the graphics state is used;
|
// If the text rendering mode calls for filling, the current nonstroking color in the graphics state is used;
|
||||||
// if it calls for stroking, the current stroking color is used.
|
// if it calls for stroking, the current stroking color is used.
|
||||||
@@ -218,8 +228,10 @@
|
|||||||
decimal tx, ty;
|
decimal tx, ty;
|
||||||
if (font.IsVertical)
|
if (font.IsVertical)
|
||||||
{
|
{
|
||||||
|
var verticalFont = (IVerticalWritingSupported) font;
|
||||||
|
var displacement = verticalFont.GetDisplacementVector(code);
|
||||||
tx = 0;
|
tx = 0;
|
||||||
ty = boundingBox.GlyphBounds.Height * fontSize + characterSpacing + wordSpacing;
|
ty = (displacement.Y * fontSize) + characterSpacing + wordSpacing;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user