mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-15 03:34:52 +08:00
fixed coordinate space transformations
This commit is contained in:
@@ -106,10 +106,10 @@
|
||||
public PdfRectangle Transform(PdfRectangle original)
|
||||
{
|
||||
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.BottomLeft.ToVector())
|
||||
Transform(original.BottomRight.ToVector())
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -71,12 +71,12 @@
|
||||
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);
|
||||
|
||||
@@ -85,11 +85,6 @@
|
||||
return new PdfRectangle(0, 0, fromFont, 0);
|
||||
}
|
||||
|
||||
public PdfRectangle GetBoundingBox(int characterCode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TransformationMatrix GetFontMatrix()
|
||||
{
|
||||
return CidFont.FontMatrix;
|
||||
|
@@ -15,8 +15,6 @@
|
||||
|
||||
bool TryGetUnicode(int characterCode, out string value);
|
||||
|
||||
PdfRectangle GetDisplacement(int characterCode);
|
||||
|
||||
PdfRectangle GetBoundingBox(int characterCode);
|
||||
|
||||
TransformationMatrix GetFontMatrix();
|
||||
|
@@ -42,12 +42,6 @@
|
||||
|
||||
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);
|
||||
|
||||
// TODO: use the parsed font fully.
|
||||
@@ -70,7 +64,7 @@
|
||||
|
||||
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)
|
||||
|
@@ -12,16 +12,11 @@
|
||||
|
||||
internal class TrueTypeSimpleFont : IFont
|
||||
{
|
||||
private readonly int firstCharacterCode;
|
||||
|
||||
private readonly int lastCharacterCode;
|
||||
|
||||
private readonly decimal[] widths;
|
||||
|
||||
private readonly FontDescriptor descriptor;
|
||||
|
||||
[CanBeNull]
|
||||
private readonly Encoding encoding;
|
||||
|
||||
[CanBeNull]
|
||||
private readonly TrueTypeFont font;
|
||||
|
||||
@@ -34,15 +29,12 @@
|
||||
|
||||
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,
|
||||
[CanBeNull] CMap toUnicodeCMap,
|
||||
[CanBeNull] Encoding encoding,
|
||||
[CanBeNull]TrueTypeFont font)
|
||||
[CanBeNull] TrueTypeFont font)
|
||||
{
|
||||
this.firstCharacterCode = firstCharacterCode;
|
||||
this.lastCharacterCode = lastCharacterCode;
|
||||
this.widths = widths;
|
||||
this.descriptor = descriptor;
|
||||
this.encoding = encoding;
|
||||
this.font = font;
|
||||
@@ -88,24 +80,12 @@
|
||||
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)
|
||||
{
|
||||
return fontMatrix.Transform(GetBoundingBoxInGlyphSpace(characterCode));
|
||||
}
|
||||
|
||||
private PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode)
|
||||
{
|
||||
if (font?.CMapTable == null)
|
||||
{
|
||||
|
@@ -14,10 +14,15 @@
|
||||
internal class Type1FontSimple : IFont
|
||||
{
|
||||
private readonly int firstChar;
|
||||
|
||||
private readonly int lastChar;
|
||||
|
||||
private readonly decimal[] widths;
|
||||
|
||||
private readonly FontDescriptor fontDescriptor;
|
||||
|
||||
private readonly Encoding encoding;
|
||||
|
||||
private readonly ToUnicodeCMap toUnicodeCMap;
|
||||
|
||||
private readonly TransformationMatrix fontMatrix = TransformationMatrix.FromValues(0.001m, 0, 0, 0.001m, 0, 0);
|
||||
@@ -81,12 +86,12 @@
|
||||
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)
|
||||
{
|
||||
@@ -96,11 +101,6 @@
|
||||
return new PdfRectangle(0, 0, widths[characterCode - firstChar], 0);
|
||||
}
|
||||
|
||||
public PdfRectangle GetBoundingBox(int characterCode)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public TransformationMatrix GetFontMatrix()
|
||||
{
|
||||
return fontMatrix;
|
||||
|
@@ -44,12 +44,12 @@
|
||||
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);
|
||||
|
||||
@@ -61,11 +61,6 @@
|
||||
return new PdfRectangle(0, 0, metrics.WidthX, 0);
|
||||
}
|
||||
|
||||
public PdfRectangle GetBoundingBox(int characterCode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TransformationMatrix GetFontMatrix()
|
||||
{
|
||||
return fontMatrix;
|
||||
|
@@ -63,12 +63,12 @@
|
||||
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)
|
||||
{
|
||||
@@ -78,11 +78,6 @@
|
||||
return new PdfRectangle(0, 0, widths[characterCode - firstChar], 0); ;
|
||||
}
|
||||
|
||||
public PdfRectangle GetBoundingBox(int characterCode)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public TransformationMatrix GetFontMatrix()
|
||||
{
|
||||
return fontMatrix;
|
||||
|
@@ -93,9 +93,13 @@
|
||||
var fontSize = currentState.FontState.FontSize;
|
||||
var horizontalScaling = currentState.FontState.HorizontalScaling / 100m;
|
||||
var characterSpacing = currentState.FontState.CharacterSpacing;
|
||||
var rise = currentState.FontState.Rise;
|
||||
|
||||
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.
|
||||
// see: https://stackoverflow.com/questions/48010235/pdf-specification-get-font-size-in-points
|
||||
var pointSize = decimal.Round(fontSize * transformationMatrix.A, 2);
|
||||
@@ -119,17 +123,15 @@
|
||||
|
||||
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 fontScaling = TransformationMatrix.Identity.Multiply(fontSize);
|
||||
var boundingBox = font.GetBoundingBox(code);
|
||||
|
||||
var transformedDisplacement = transformationMatrix
|
||||
.Transform(TextMatrices.TextMatrix
|
||||
.Transform(fontScaling
|
||||
.Transform(displacement)));
|
||||
.Transform(renderingMatrix
|
||||
.Transform(boundingBox)));
|
||||
|
||||
ShowGlyph(font, transformedDisplacement, unicode, fontSize, pointSize);
|
||||
|
||||
@@ -137,11 +139,11 @@
|
||||
if (font.IsVertical)
|
||||
{
|
||||
tx = 0;
|
||||
ty = displacement.Height * fontSize + characterSpacing + wordSpacing;
|
||||
ty = boundingBox.Height * fontSize + characterSpacing + wordSpacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
tx = (displacement.Width * fontSize + characterSpacing + wordSpacing) * horizontalScaling;
|
||||
tx = (boundingBox.Width * fontSize + characterSpacing + wordSpacing) * horizontalScaling;
|
||||
ty = 0;
|
||||
}
|
||||
|
||||
|
@@ -10,39 +10,5 @@
|
||||
public TransformationMatrix TextMatrix { 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