fixed coordinate space transformations

This commit is contained in:
modest-as
2018-04-11 23:18:24 +01:00
parent 1da3975325
commit d65f50dfd1
10 changed files with 39 additions and 114 deletions

View File

@@ -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())
);
}

View File

@@ -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;

View File

@@ -15,8 +15,6 @@
bool TryGetUnicode(int characterCode, out string value);
PdfRectangle GetDisplacement(int characterCode);
PdfRectangle GetBoundingBox(int characterCode);
TransformationMatrix GetFontMatrix();

View File

@@ -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)

View File

@@ -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)
{
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)
{

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}
}
}