mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-15 11:44:51 +08:00
fixed coordinate space transformations
This commit is contained in:
@@ -106,10 +106,10 @@
|
|||||||
public PdfRectangle Transform(PdfRectangle original)
|
public PdfRectangle Transform(PdfRectangle original)
|
||||||
{
|
{
|
||||||
return new PdfRectangle(
|
return new PdfRectangle(
|
||||||
|
Transform(original.TopLeft.ToVector()),
|
||||||
|
Transform(original.TopRight.ToVector()),
|
||||||
Transform(original.BottomLeft.ToVector()),
|
Transform(original.BottomLeft.ToVector()),
|
||||||
Transform(original.BottomLeft.ToVector()),
|
Transform(original.BottomRight.ToVector())
|
||||||
Transform(original.BottomLeft.ToVector()),
|
|
||||||
Transform(original.BottomLeft.ToVector())
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -71,12 +71,12 @@
|
|||||||
return ToUnicode.TryGet(characterCode, out value);
|
return ToUnicode.TryGet(characterCode, out value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetDisplacement(int characterCode)
|
public PdfRectangle GetBoundingBox(int characterCode)
|
||||||
{
|
{
|
||||||
return fontMatrix.Transform(GetRectangle(characterCode));
|
return fontMatrix.Transform(GetBoundingBoxInGlyphSpace(characterCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetRectangle(int characterCode)
|
private PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode)
|
||||||
{
|
{
|
||||||
var cid = CMap.ConvertToCid(characterCode);
|
var cid = CMap.ConvertToCid(characterCode);
|
||||||
|
|
||||||
@@ -85,11 +85,6 @@
|
|||||||
return new PdfRectangle(0, 0, fromFont, 0);
|
return new PdfRectangle(0, 0, fromFont, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetBoundingBox(int characterCode)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransformationMatrix GetFontMatrix()
|
public TransformationMatrix GetFontMatrix()
|
||||||
{
|
{
|
||||||
return CidFont.FontMatrix;
|
return CidFont.FontMatrix;
|
||||||
|
@@ -15,8 +15,6 @@
|
|||||||
|
|
||||||
bool TryGetUnicode(int characterCode, out string value);
|
bool TryGetUnicode(int characterCode, out string value);
|
||||||
|
|
||||||
PdfRectangle GetDisplacement(int characterCode);
|
|
||||||
|
|
||||||
PdfRectangle GetBoundingBox(int characterCode);
|
PdfRectangle GetBoundingBox(int characterCode);
|
||||||
|
|
||||||
TransformationMatrix GetFontMatrix();
|
TransformationMatrix GetFontMatrix();
|
||||||
|
@@ -42,12 +42,6 @@
|
|||||||
|
|
||||||
public IFont Generate(DictionaryToken dictionary, bool isLenientParsing)
|
public IFont Generate(DictionaryToken dictionary, bool isLenientParsing)
|
||||||
{
|
{
|
||||||
var firstCharacter = FontDictionaryAccessHelper.GetFirstCharacter(dictionary);
|
|
||||||
|
|
||||||
var lastCharacter = FontDictionaryAccessHelper.GetLastCharacter(dictionary);
|
|
||||||
|
|
||||||
var widths = FontDictionaryAccessHelper.GetWidths(pdfScanner, dictionary, isLenientParsing);
|
|
||||||
|
|
||||||
var descriptor = FontDictionaryAccessHelper.GetFontDescriptor(pdfScanner, fontDescriptorFactory, dictionary, isLenientParsing);
|
var descriptor = FontDictionaryAccessHelper.GetFontDescriptor(pdfScanner, fontDescriptorFactory, dictionary, isLenientParsing);
|
||||||
|
|
||||||
// TODO: use the parsed font fully.
|
// TODO: use the parsed font fully.
|
||||||
@@ -70,7 +64,7 @@
|
|||||||
|
|
||||||
Encoding encoding = encodingReader.Read(dictionary, isLenientParsing, descriptor);
|
Encoding encoding = encodingReader.Read(dictionary, isLenientParsing, descriptor);
|
||||||
|
|
||||||
return new TrueTypeSimpleFont(name, firstCharacter, lastCharacter, widths, descriptor, toUnicodeCMap, encoding, font);
|
return new TrueTypeSimpleFont(name, descriptor, toUnicodeCMap, encoding, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TrueTypeFont ParseTrueTypeFont(FontDescriptor descriptor)
|
private TrueTypeFont ParseTrueTypeFont(FontDescriptor descriptor)
|
||||||
|
@@ -12,16 +12,11 @@
|
|||||||
|
|
||||||
internal class TrueTypeSimpleFont : IFont
|
internal class TrueTypeSimpleFont : IFont
|
||||||
{
|
{
|
||||||
private readonly int firstCharacterCode;
|
|
||||||
|
|
||||||
private readonly int lastCharacterCode;
|
|
||||||
|
|
||||||
private readonly decimal[] widths;
|
|
||||||
|
|
||||||
private readonly FontDescriptor descriptor;
|
private readonly FontDescriptor descriptor;
|
||||||
|
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
private readonly Encoding encoding;
|
private readonly Encoding encoding;
|
||||||
|
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
private readonly TrueTypeFont font;
|
private readonly TrueTypeFont font;
|
||||||
|
|
||||||
@@ -34,15 +29,12 @@
|
|||||||
|
|
||||||
private readonly TransformationMatrix fontMatrix = TransformationMatrix.FromValues(0.001m, 0, 0, 0.001m, 0, 0);
|
private readonly TransformationMatrix fontMatrix = TransformationMatrix.FromValues(0.001m, 0, 0, 0.001m, 0, 0);
|
||||||
|
|
||||||
public TrueTypeSimpleFont(NameToken name, int firstCharacterCode, int lastCharacterCode, decimal[] widths,
|
public TrueTypeSimpleFont(NameToken name,
|
||||||
FontDescriptor descriptor,
|
FontDescriptor descriptor,
|
||||||
[CanBeNull] CMap toUnicodeCMap,
|
[CanBeNull] CMap toUnicodeCMap,
|
||||||
[CanBeNull] Encoding encoding,
|
[CanBeNull] Encoding encoding,
|
||||||
[CanBeNull]TrueTypeFont font)
|
[CanBeNull] TrueTypeFont font)
|
||||||
{
|
{
|
||||||
this.firstCharacterCode = firstCharacterCode;
|
|
||||||
this.lastCharacterCode = lastCharacterCode;
|
|
||||||
this.widths = widths;
|
|
||||||
this.descriptor = descriptor;
|
this.descriptor = descriptor;
|
||||||
this.encoding = encoding;
|
this.encoding = encoding;
|
||||||
this.font = font;
|
this.font = font;
|
||||||
@@ -88,24 +80,12 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetDisplacement(int characterCode)
|
|
||||||
{
|
|
||||||
return fontMatrix.Transform(GetRectangle(characterCode));
|
|
||||||
}
|
|
||||||
|
|
||||||
public PdfRectangle GetRectangle(int characterCode)
|
|
||||||
{
|
|
||||||
var index = characterCode - firstCharacterCode;
|
|
||||||
|
|
||||||
if (index < 0 || index >= widths.Length)
|
|
||||||
{
|
|
||||||
return new PdfRectangle(0, 0, descriptor.MissingWidth, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PdfRectangle(0, 0, widths[index], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PdfRectangle GetBoundingBox(int characterCode)
|
public PdfRectangle GetBoundingBox(int characterCode)
|
||||||
|
{
|
||||||
|
return fontMatrix.Transform(GetBoundingBoxInGlyphSpace(characterCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
private PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode)
|
||||||
{
|
{
|
||||||
if (font?.CMapTable == null)
|
if (font?.CMapTable == null)
|
||||||
{
|
{
|
||||||
|
@@ -14,10 +14,15 @@
|
|||||||
internal class Type1FontSimple : IFont
|
internal class Type1FontSimple : IFont
|
||||||
{
|
{
|
||||||
private readonly int firstChar;
|
private readonly int firstChar;
|
||||||
|
|
||||||
private readonly int lastChar;
|
private readonly int lastChar;
|
||||||
|
|
||||||
private readonly decimal[] widths;
|
private readonly decimal[] widths;
|
||||||
|
|
||||||
private readonly FontDescriptor fontDescriptor;
|
private readonly FontDescriptor fontDescriptor;
|
||||||
|
|
||||||
private readonly Encoding encoding;
|
private readonly Encoding encoding;
|
||||||
|
|
||||||
private readonly ToUnicodeCMap toUnicodeCMap;
|
private readonly ToUnicodeCMap toUnicodeCMap;
|
||||||
|
|
||||||
private readonly TransformationMatrix fontMatrix = TransformationMatrix.FromValues(0.001m, 0, 0, 0.001m, 0, 0);
|
private readonly TransformationMatrix fontMatrix = TransformationMatrix.FromValues(0.001m, 0, 0, 0.001m, 0, 0);
|
||||||
@@ -81,12 +86,12 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetDisplacement(int characterCode)
|
public PdfRectangle GetBoundingBox(int characterCode)
|
||||||
{
|
{
|
||||||
return fontMatrix.Transform(GetRectangle(characterCode));
|
return fontMatrix.Transform(GetBoundingBoxInGlyphSpace(characterCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetRectangle(int characterCode)
|
private PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode)
|
||||||
{
|
{
|
||||||
if (characterCode < firstChar || characterCode > lastChar)
|
if (characterCode < firstChar || characterCode > lastChar)
|
||||||
{
|
{
|
||||||
@@ -96,11 +101,6 @@
|
|||||||
return new PdfRectangle(0, 0, widths[characterCode - firstChar], 0);
|
return new PdfRectangle(0, 0, widths[characterCode - firstChar], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetBoundingBox(int characterCode)
|
|
||||||
{
|
|
||||||
throw new System.NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransformationMatrix GetFontMatrix()
|
public TransformationMatrix GetFontMatrix()
|
||||||
{
|
{
|
||||||
return fontMatrix;
|
return fontMatrix;
|
||||||
|
@@ -44,12 +44,12 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetDisplacement(int characterCode)
|
public PdfRectangle GetBoundingBox(int characterCode)
|
||||||
{
|
{
|
||||||
return fontMatrix.Transform(GetRectangle(characterCode));
|
return fontMatrix.Transform(GetBoundingBoxInGlyphSpace(characterCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetRectangle(int characterCode)
|
private PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode)
|
||||||
{
|
{
|
||||||
var name = encoding.GetName(characterCode);
|
var name = encoding.GetName(characterCode);
|
||||||
|
|
||||||
@@ -61,11 +61,6 @@
|
|||||||
return new PdfRectangle(0, 0, metrics.WidthX, 0);
|
return new PdfRectangle(0, 0, metrics.WidthX, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetBoundingBox(int characterCode)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransformationMatrix GetFontMatrix()
|
public TransformationMatrix GetFontMatrix()
|
||||||
{
|
{
|
||||||
return fontMatrix;
|
return fontMatrix;
|
||||||
|
@@ -63,12 +63,12 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetDisplacement(int characterCode)
|
public PdfRectangle GetBoundingBox(int characterCode)
|
||||||
{
|
{
|
||||||
return fontMatrix.Transform(GetRectangle(characterCode));
|
return fontMatrix.Transform(GetBoundingBoxInGlyphSpace(characterCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetRectangle(int characterCode)
|
private PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode)
|
||||||
{
|
{
|
||||||
if (characterCode < firstChar || characterCode > lastChar)
|
if (characterCode < firstChar || characterCode > lastChar)
|
||||||
{
|
{
|
||||||
@@ -78,11 +78,6 @@
|
|||||||
return new PdfRectangle(0, 0, widths[characterCode - firstChar], 0); ;
|
return new PdfRectangle(0, 0, widths[characterCode - firstChar], 0); ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PdfRectangle GetBoundingBox(int characterCode)
|
|
||||||
{
|
|
||||||
throw new System.NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransformationMatrix GetFontMatrix()
|
public TransformationMatrix GetFontMatrix()
|
||||||
{
|
{
|
||||||
return fontMatrix;
|
return fontMatrix;
|
||||||
|
@@ -93,9 +93,13 @@
|
|||||||
var fontSize = currentState.FontState.FontSize;
|
var fontSize = currentState.FontState.FontSize;
|
||||||
var horizontalScaling = currentState.FontState.HorizontalScaling / 100m;
|
var horizontalScaling = currentState.FontState.HorizontalScaling / 100m;
|
||||||
var characterSpacing = currentState.FontState.CharacterSpacing;
|
var characterSpacing = currentState.FontState.CharacterSpacing;
|
||||||
|
var rise = currentState.FontState.Rise;
|
||||||
|
|
||||||
var transformationMatrix = currentState.CurrentTransformationMatrix;
|
var transformationMatrix = currentState.CurrentTransformationMatrix;
|
||||||
|
|
||||||
|
var renderingMatrix =
|
||||||
|
TransformationMatrix.FromValues(fontSize * horizontalScaling, 0, 0, fontSize, 0, rise);
|
||||||
|
|
||||||
// TODO: this does not seem correct, produces the correct result for now but we need to revisit.
|
// TODO: this does not seem correct, produces the correct result for now but we need to revisit.
|
||||||
// see: https://stackoverflow.com/questions/48010235/pdf-specification-get-font-size-in-points
|
// see: https://stackoverflow.com/questions/48010235/pdf-specification-get-font-size-in-points
|
||||||
var pointSize = decimal.Round(fontSize * transformationMatrix.A, 2);
|
var pointSize = decimal.Round(fontSize * transformationMatrix.A, 2);
|
||||||
@@ -119,17 +123,15 @@
|
|||||||
|
|
||||||
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.");
|
throw new NotImplementedException("Vertical fonts are currently unsupported, please submit a pull request or issue with an example file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var displacement = font.GetDisplacement(code);
|
var boundingBox = font.GetBoundingBox(code);
|
||||||
|
|
||||||
var fontScaling = TransformationMatrix.Identity.Multiply(fontSize);
|
|
||||||
|
|
||||||
var transformedDisplacement = transformationMatrix
|
var transformedDisplacement = transformationMatrix
|
||||||
.Transform(TextMatrices.TextMatrix
|
.Transform(TextMatrices.TextMatrix
|
||||||
.Transform(fontScaling
|
.Transform(renderingMatrix
|
||||||
.Transform(displacement)));
|
.Transform(boundingBox)));
|
||||||
|
|
||||||
ShowGlyph(font, transformedDisplacement, unicode, fontSize, pointSize);
|
ShowGlyph(font, transformedDisplacement, unicode, fontSize, pointSize);
|
||||||
|
|
||||||
@@ -137,11 +139,11 @@
|
|||||||
if (font.IsVertical)
|
if (font.IsVertical)
|
||||||
{
|
{
|
||||||
tx = 0;
|
tx = 0;
|
||||||
ty = displacement.Height * fontSize + characterSpacing + wordSpacing;
|
ty = boundingBox.Height * fontSize + characterSpacing + wordSpacing;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tx = (displacement.Width * fontSize + characterSpacing + wordSpacing) * horizontalScaling;
|
tx = (boundingBox.Width * fontSize + characterSpacing + wordSpacing) * horizontalScaling;
|
||||||
ty = 0;
|
ty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,39 +10,5 @@
|
|||||||
public TransformationMatrix TextMatrix { get; set; }
|
public TransformationMatrix TextMatrix { get; set; }
|
||||||
|
|
||||||
public TransformationMatrix TextLineMatrix { get; set; }
|
public TransformationMatrix TextLineMatrix { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the Text Rendering Matrix (Trm) which maps from text space to device space.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>The rendering matrix is temporary and is calculated for each glyph in a text showing operation.</para>
|
|
||||||
/// <para>
|
|
||||||
/// The rendering matrix is calculated as follows:<br/>
|
|
||||||
/// | (Tfs * Th) 0 0 |<br/>
|
|
||||||
/// | 0 Tfs 0 | * Tm * CTM<br/>
|
|
||||||
/// | 0 Trise 1 |<br/>
|
|
||||||
/// Where Tfs is the font size, Th is the horizontal scaling, Trise is the text rise, Tm is the current <see cref="TextMatrix"/> and CTM is the
|
|
||||||
/// <see cref="CurrentGraphicsState.CurrentTransformationMatrix"/>.
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
|
||||||
public TransformationMatrix GetRenderingMatrix(CurrentGraphicsState currentGraphicsState)
|
|
||||||
{
|
|
||||||
var fontSize = currentGraphicsState.FontState.FontSize;
|
|
||||||
var horizontalScaling = currentGraphicsState.FontState.HorizontalScaling;
|
|
||||||
var rise = currentGraphicsState.FontState.Rise;
|
|
||||||
|
|
||||||
var initialMatrix = TransformationMatrix.FromArray(new[]
|
|
||||||
{
|
|
||||||
(fontSize * horizontalScaling), 0, 0,
|
|
||||||
0, fontSize, 0,
|
|
||||||
0, rise, 1
|
|
||||||
});
|
|
||||||
|
|
||||||
var multipledByTextMatrix = initialMatrix.Multiply(TextMatrix);
|
|
||||||
|
|
||||||
var result = multipledByTextMatrix.Multiply(currentGraphicsState.CurrentTransformationMatrix);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user