mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-07 07:34:36 +08:00
Add GetDescent() and GetAscent() methods to IFont, improve font matrix for TrueTypeSimpleFont and TrueTypeStandard14FallbackSimpleFont and add loose bounding box to Letter
Some checks failed
Build, test and publish draft / build (push) Has been cancelled
Build and test [MacOS] / build (push) Has been cancelled
Run Common Crawl Tests / build (0000-0001) (push) Has been cancelled
Run Common Crawl Tests / build (0002-0003) (push) Has been cancelled
Run Common Crawl Tests / build (0004-0005) (push) Has been cancelled
Run Common Crawl Tests / build (0006-0007) (push) Has been cancelled
Run Integration Tests / build (push) Has been cancelled
Nightly Release / Check if this commit has already been published (push) Has been cancelled
Nightly Release / tests (push) Has been cancelled
Nightly Release / build_and_publish_nightly (push) Has been cancelled
Some checks failed
Build, test and publish draft / build (push) Has been cancelled
Build and test [MacOS] / build (push) Has been cancelled
Run Common Crawl Tests / build (0000-0001) (push) Has been cancelled
Run Common Crawl Tests / build (0002-0003) (push) Has been cancelled
Run Common Crawl Tests / build (0004-0005) (push) Has been cancelled
Run Common Crawl Tests / build (0006-0007) (push) Has been cancelled
Run Integration Tests / build (push) Has been cancelled
Nightly Release / Check if this commit has already been published (push) Has been cancelled
Nightly Release / tests (push) Has been cancelled
Nightly Release / build_and_publish_nightly (push) Has been cancelled
This commit is contained in:
@@ -224,9 +224,18 @@
|
||||
[Pure]
|
||||
public double TransformX(double x)
|
||||
{
|
||||
var xt = A * x + C * 0 + E;
|
||||
return A * x + E; // + C * 0
|
||||
}
|
||||
|
||||
return xt;
|
||||
|
||||
/// <summary>
|
||||
/// Transform an Y coordinate using this transformation matrix.
|
||||
/// </summary>
|
||||
/// <param name="y">The Y coordinate.</param>
|
||||
/// <returns>The transformed Y coordinate.</returns>
|
||||
public double TransformY(double y)
|
||||
{
|
||||
return D * y + F;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -60,6 +60,7 @@
|
||||
letter = new Letter(
|
||||
" ",
|
||||
letter.GlyphRectangle,
|
||||
letter.GlyphRectangleLoose,
|
||||
letter.StartBaseLine,
|
||||
letter.EndBaseLine,
|
||||
letter.Width,
|
||||
|
@@ -60,6 +60,7 @@
|
||||
private static TextBlock CreateFakeTextBlock(PdfRectangle boundingBox)
|
||||
{
|
||||
var letter = new Letter("a",
|
||||
boundingBox,
|
||||
boundingBox,
|
||||
boundingBox.BottomLeft,
|
||||
boundingBox.BottomRight,
|
||||
|
@@ -4,6 +4,7 @@ using UglyToad.PdfPig.Tests.Dla;
|
||||
namespace UglyToad.PdfPig.Tests.Fonts.SystemFonts
|
||||
{
|
||||
using PdfPig.Core;
|
||||
using PdfPig.Geometry;
|
||||
|
||||
public class Linux
|
||||
{
|
||||
@@ -68,7 +69,10 @@ namespace UglyToad.PdfPig.Tests.Fonts.SystemFonts
|
||||
Assert.Equal(expectedData.TopLeft.Y, current.GlyphRectangle.TopLeft.Y, 6);
|
||||
Assert.Equal(expectedData.Width, current.GlyphRectangle.Width, 6);
|
||||
Assert.Equal(expectedData.Height, current.GlyphRectangle.Height, 6);
|
||||
Assert.Equal(expectedData.Rotation, current.GlyphRectangle.Rotation, 3);
|
||||
Assert.Equal(expectedData.Rotation, current.GlyphRectangle.Rotation, 3);
|
||||
|
||||
Assert.True(current.GlyphRectangle.IntersectsWith(current.GlyphRectangleLoose));
|
||||
Assert.Equal(current.GlyphRectangle.Rotation, current.GlyphRectangleLoose.Rotation, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
namespace UglyToad.PdfPig.Tests.Integration
|
||||
{
|
||||
using PdfPig.Geometry;
|
||||
|
||||
public class IntegrationDocumentTests
|
||||
{
|
||||
private static readonly Lazy<string> DocumentFolder = new Lazy<string>(() => Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "Integration", "Documents")));
|
||||
@@ -11,6 +13,36 @@
|
||||
"cmap-parsing-exception.pdf"
|
||||
];
|
||||
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetAllDocuments))]
|
||||
public void CheckGlyphLooseBoundingBoxes(string documentName)
|
||||
{
|
||||
// Add the full path back on, we removed it so we could see it in the test explorer.
|
||||
documentName = Path.Combine(DocumentFolder.Value, documentName);
|
||||
|
||||
using (var document = PdfDocument.Open(documentName, new ParsingOptions { UseLenientParsing = true }))
|
||||
{
|
||||
for (var i = 0; i < document.NumberOfPages; i++)
|
||||
{
|
||||
var page = document.GetPage(i + 1);
|
||||
foreach (var letter in page.Letters)
|
||||
{
|
||||
var bbox = letter.GlyphRectangle;
|
||||
if (bbox.Height > 0)
|
||||
{
|
||||
if (letter.GlyphRectangleLoose.Height <= 0)
|
||||
{
|
||||
_ = letter.GetFont().GetAscent();
|
||||
}
|
||||
|
||||
Assert.True(letter.GlyphRectangleLoose.Height > 0, $"Page {i + 1}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetAllDocuments))]
|
||||
public void CanReadAllPages(string documentName)
|
||||
|
@@ -53,6 +53,8 @@ namespace UglyToad.PdfPig.Tests.Integration
|
||||
|
||||
Assert.Contains(page.Letters, x => x.GlyphRectangle.Width != 0);
|
||||
Assert.Contains(page.Letters, x => x.GlyphRectangle.Height != 0);
|
||||
Assert.Contains(page.Letters, x => x.GlyphRectangleLoose.Width != 0);
|
||||
Assert.Contains(page.Letters, x => x.GlyphRectangleLoose.Height != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -193,6 +193,32 @@
|
||||
d.SaveTo(fs);
|
||||
}
|
||||
}
|
||||
|
||||
using (var bitmap = SKBitmap.FromImage(image))
|
||||
using (var graphics = new SKCanvas(bitmap))
|
||||
{
|
||||
foreach (var letter in page.Letters)
|
||||
{
|
||||
DrawRectangle(letter.GlyphRectangleLoose, graphics, violetPen, imageHeight, scale);
|
||||
}
|
||||
|
||||
graphics.Flush();
|
||||
|
||||
var imageName = $"{file}_loose.jpg";
|
||||
|
||||
if (!Directory.Exists(OutputPath))
|
||||
{
|
||||
Directory.CreateDirectory(OutputPath);
|
||||
}
|
||||
|
||||
var savePath = Path.Combine(OutputPath, imageName);
|
||||
|
||||
using (var fs = new FileStream(savePath, FileMode.Create))
|
||||
using (SKData d = bitmap.Encode(SKEncodedImageFormat.Jpeg, 100))
|
||||
{
|
||||
d.SaveTo(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -85,6 +85,31 @@
|
||||
d.SaveTo(fs);
|
||||
}
|
||||
}
|
||||
|
||||
using (var picture = document.GetPage<SKPicture>(pageNo))
|
||||
using (var image = SKImage.FromPicture(picture, size, ScaleMatrix))
|
||||
using (var bmp = SKBitmap.FromImage(image))
|
||||
using (var canvas = new SKCanvas(bmp))
|
||||
{
|
||||
Assert.NotNull(picture);
|
||||
|
||||
if (RenderGlyphRectangle)
|
||||
{
|
||||
foreach (var letter in page.Letters)
|
||||
{
|
||||
DrawRectangle(letter.GlyphRectangleLoose, canvas, redPaint, size.Height, Scale);
|
||||
}
|
||||
}
|
||||
|
||||
var imageName = $"{file}_{pageNo}_loose.png";
|
||||
var savePath = Path.Combine(OutputPath, imageName);
|
||||
|
||||
using (var fs = new FileStream(savePath, FileMode.Create))
|
||||
using (var d = bmp.Encode(SKEncodedImageFormat.Png, 100))
|
||||
{
|
||||
d.SaveTo(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -46,6 +46,12 @@
|
||||
/// </summary>
|
||||
public PdfRectangle GlyphRectangle { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The loose bounding box for the glyph. Contrary to the <see cref="GlyphRectangle"/>, the loose bounding box will be the same across all glyphes of the same font.
|
||||
/// It takes in account the font Ascent and Descent.
|
||||
/// </summary>
|
||||
public PdfRectangle GlyphRectangleLoose { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Size as defined in the PDF file. This is not equivalent to font size in points but is relative to other font sizes on the page.
|
||||
/// </summary>
|
||||
@@ -60,7 +66,7 @@
|
||||
/// Details about the font for this letter.
|
||||
/// </summary>
|
||||
public FontDetails FontDetails { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Details about the font for this letter.
|
||||
/// </summary>
|
||||
@@ -103,13 +109,14 @@
|
||||
/// <summary>
|
||||
/// Sequence number of the ShowText operation that printed this letter.
|
||||
/// </summary>
|
||||
public int TextSequence { get; }
|
||||
public int TextSequence { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new letter to represent some text drawn by the Tj operator.
|
||||
/// </summary>
|
||||
public Letter(string value,
|
||||
PdfRectangle glyphRectangle,
|
||||
PdfRectangle glyphRectangle,
|
||||
PdfRectangle glyphRectangleLoose,
|
||||
PdfPoint startBaseLine,
|
||||
PdfPoint endBaseLine,
|
||||
double width,
|
||||
@@ -120,7 +127,7 @@
|
||||
IColor fillColor,
|
||||
double pointSize,
|
||||
int textSequence) :
|
||||
this(value, glyphRectangle,
|
||||
this(value, glyphRectangle, glyphRectangleLoose,
|
||||
startBaseLine, endBaseLine,
|
||||
width, fontSize, font.Details, font,
|
||||
renderingMode, strokeColor, fillColor,
|
||||
@@ -131,7 +138,8 @@
|
||||
/// Create a new letter to represent some text drawn by the Tj operator.
|
||||
/// </summary>
|
||||
public Letter(string value,
|
||||
PdfRectangle glyphRectangle,
|
||||
PdfRectangle glyphRectangle,
|
||||
PdfRectangle glyphRectangleLoose,
|
||||
PdfPoint startBaseLine,
|
||||
PdfPoint endBaseLine,
|
||||
double width,
|
||||
@@ -142,14 +150,16 @@
|
||||
IColor fillColor,
|
||||
double pointSize,
|
||||
int textSequence):
|
||||
this(value, glyphRectangle,
|
||||
this(value, glyphRectangle, glyphRectangleLoose,
|
||||
startBaseLine, endBaseLine,
|
||||
width, fontSize, fontDetails, null,
|
||||
renderingMode, strokeColor, fillColor,
|
||||
pointSize, textSequence)
|
||||
{ }
|
||||
|
||||
private Letter(string value, PdfRectangle glyphRectangle,
|
||||
private Letter(string value,
|
||||
PdfRectangle glyphRectangle,
|
||||
PdfRectangle glyphRectangleLoose,
|
||||
PdfPoint startBaseLine,
|
||||
PdfPoint endBaseLine,
|
||||
double width,
|
||||
@@ -164,6 +174,7 @@
|
||||
{
|
||||
Value = value;
|
||||
GlyphRectangle = glyphRectangle;
|
||||
GlyphRectangleLoose = glyphRectangleLoose;
|
||||
StartBaseLine = startBaseLine;
|
||||
EndBaseLine = endBaseLine;
|
||||
Width = width;
|
||||
@@ -196,7 +207,8 @@
|
||||
public Letter AsBold()
|
||||
{
|
||||
return new Letter(Value,
|
||||
GlyphRectangle,
|
||||
GlyphRectangle,
|
||||
GlyphRectangleLoose,
|
||||
StartBaseLine,
|
||||
EndBaseLine,
|
||||
Width,
|
||||
|
@@ -100,12 +100,6 @@ namespace UglyToad.PdfPig.Graphics
|
||||
var transformedGlyphBounds = PerformantRectangleTransformer
|
||||
.Transform(renderingMatrix, textMatrix, transformationMatrix, characterBoundingBox.GlyphBounds);
|
||||
|
||||
var transformedPdfBounds = PerformantRectangleTransformer
|
||||
.Transform(renderingMatrix,
|
||||
textMatrix,
|
||||
transformationMatrix,
|
||||
new PdfRectangle(0, 0, characterBoundingBox.Width, UserSpaceUnit.PointMultiples));
|
||||
|
||||
if (ParsingOptions.ClipPaths)
|
||||
{
|
||||
var currentClipping = currentState.CurrentClippingPath;
|
||||
@@ -129,6 +123,7 @@ namespace UglyToad.PdfPig.Graphics
|
||||
letter = new Letter(
|
||||
newLetter,
|
||||
attachTo.GlyphRectangle,
|
||||
attachTo.GlyphRectangleLoose,
|
||||
attachTo.StartBaseLine,
|
||||
attachTo.EndBaseLine,
|
||||
attachTo.Width,
|
||||
@@ -151,9 +146,25 @@ namespace UglyToad.PdfPig.Graphics
|
||||
// If we did not create a letter for a combined diacritic, create one here.
|
||||
if (letter is null)
|
||||
{
|
||||
var transformedPdfBounds = PerformantRectangleTransformer
|
||||
.Transform(renderingMatrix,
|
||||
textMatrix,
|
||||
transformationMatrix,
|
||||
new PdfRectangle(0, 0, characterBoundingBox.Width, UserSpaceUnit.PointMultiples));
|
||||
|
||||
var looseBox = PerformantRectangleTransformer
|
||||
.Transform(renderingMatrix,
|
||||
textMatrix,
|
||||
transformationMatrix,
|
||||
new PdfRectangle(0,
|
||||
font.GetDescent(),
|
||||
characterBoundingBox.Width,
|
||||
font.GetAscent()));
|
||||
|
||||
letter = new Letter(
|
||||
unicode,
|
||||
isBboxValid ? transformedGlyphBounds : transformedPdfBounds,
|
||||
looseBox,
|
||||
transformedPdfBounds.BottomLeft,
|
||||
transformedPdfBounds.BottomRight,
|
||||
transformedPdfBounds.Width,
|
||||
@@ -167,7 +178,6 @@ namespace UglyToad.PdfPig.Graphics
|
||||
}
|
||||
|
||||
letters.Add(letter);
|
||||
|
||||
markedContentStack.AddLetter(letter);
|
||||
}
|
||||
|
||||
|
@@ -57,6 +57,10 @@
|
||||
|
||||
TransformationMatrix GetFontMatrix(int characterIdentifier);
|
||||
|
||||
double GetDescent();
|
||||
|
||||
double GetAscent();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the glyph path for the given character code.
|
||||
/// </summary>
|
||||
|
@@ -20,6 +20,10 @@
|
||||
|
||||
bool TryGetBoundingAdvancedWidth(int characterIdentifier, out double width);
|
||||
|
||||
double? GetDescent();
|
||||
|
||||
double? GetAscent();
|
||||
|
||||
bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList<PdfSubpath>? path);
|
||||
|
||||
bool TryGetPath(int characterCode, Func<int, int?> characterCodeToGlyphId, [NotNullWhen(true)] out IReadOnlyList<PdfSubpath>? path);
|
||||
|
@@ -42,6 +42,18 @@
|
||||
|
||||
public PdfRectangle? GetCharacterBoundingBox(string characterName) => fontCollection.GetCharacterBoundingBox(characterName);
|
||||
|
||||
public double? GetDescent()
|
||||
{
|
||||
// BobLd: we don't support ascent / descent for cff for the moment
|
||||
return null;
|
||||
}
|
||||
|
||||
public double? GetAscent()
|
||||
{
|
||||
// BobLd: we don't support ascent / descent for cff for the moment
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool TryGetBoundingBox(int characterIdentifier, out PdfRectangle boundingBox)
|
||||
{
|
||||
boundingBox = new PdfRectangle(0, 0, 500, 0);
|
||||
|
@@ -36,6 +36,16 @@
|
||||
|
||||
public int GetFontMatrixMultiplier() => font.GetUnitsPerEm();
|
||||
|
||||
public double? GetDescent()
|
||||
{
|
||||
return font.TableRegister.HorizontalHeaderTable.Descent;
|
||||
}
|
||||
|
||||
public double? GetAscent()
|
||||
{
|
||||
return font.TableRegister.HorizontalHeaderTable.Ascent;
|
||||
}
|
||||
|
||||
public bool TryGetFontMatrix(int characterCode, [NotNullWhen(true)] out TransformationMatrix? matrix)
|
||||
{
|
||||
// We don't have a matrix here
|
||||
|
@@ -148,6 +148,38 @@
|
||||
return fontProgram.TryGetFontMatrix(characterIdentifier, out var m) ? m.Value : FontMatrix;
|
||||
}
|
||||
|
||||
public double GetDescent()
|
||||
{
|
||||
if (fontProgram is null)
|
||||
{
|
||||
return Descriptor.Descent;
|
||||
}
|
||||
|
||||
double? descent = fontProgram.GetDescent();
|
||||
if (descent.HasValue)
|
||||
{
|
||||
return descent.Value;
|
||||
}
|
||||
|
||||
return Descriptor.Descent;
|
||||
}
|
||||
|
||||
public double GetAscent()
|
||||
{
|
||||
if (fontProgram is null)
|
||||
{
|
||||
return Descriptor.Ascent;
|
||||
}
|
||||
|
||||
double? ascent = fontProgram.GetAscent();
|
||||
if (ascent.HasValue)
|
||||
{
|
||||
return ascent.Value;
|
||||
}
|
||||
|
||||
return Descriptor.Ascent;
|
||||
}
|
||||
|
||||
public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList<PdfSubpath>? path)
|
||||
{
|
||||
path = null;
|
||||
|
@@ -132,6 +132,38 @@
|
||||
return FontMatrix;
|
||||
}
|
||||
|
||||
public double GetDescent()
|
||||
{
|
||||
if (fontProgram is null)
|
||||
{
|
||||
return Descriptor.Descent;
|
||||
}
|
||||
|
||||
double? descent = fontProgram.GetDescent();
|
||||
if (descent.HasValue)
|
||||
{
|
||||
return descent.Value;
|
||||
}
|
||||
|
||||
return Descriptor.Descent;
|
||||
}
|
||||
|
||||
public double GetAscent()
|
||||
{
|
||||
if (fontProgram is null)
|
||||
{
|
||||
return Descriptor.Ascent;
|
||||
}
|
||||
|
||||
double? ascent = fontProgram.GetAscent();
|
||||
if (ascent.HasValue)
|
||||
{
|
||||
return ascent.Value;
|
||||
}
|
||||
|
||||
return Descriptor.Ascent;
|
||||
}
|
||||
|
||||
public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList<PdfSubpath>? path) => TryGetPath(characterCode, cidToGid.GetGlyphIndex, out path);
|
||||
|
||||
public bool TryGetPath(int characterCode, Func<int, int?> characterCodeToGlyphId, [NotNullWhen(true)] out IReadOnlyList<PdfSubpath>? path)
|
||||
|
@@ -22,6 +22,8 @@
|
||||
= new Dictionary<int, CharacterBoundingBox>();
|
||||
|
||||
private readonly bool useLenientParsing;
|
||||
private readonly double ascent;
|
||||
private readonly double descent;
|
||||
|
||||
public NameToken Name => BaseFont;
|
||||
|
||||
@@ -57,6 +59,30 @@
|
||||
?? FontDetails.GetDefault(Name.Data);
|
||||
|
||||
useLenientParsing = parsingOptions.UseLenientParsing;
|
||||
ascent = ComputeAscent();
|
||||
descent = ComputeDescent();
|
||||
}
|
||||
|
||||
private double ComputeDescent()
|
||||
{
|
||||
double d = CidFont.GetDescent();
|
||||
if (Math.Abs(d) > double.Epsilon)
|
||||
{
|
||||
return GetFontMatrix().TransformY(d);
|
||||
}
|
||||
|
||||
return -0.25;
|
||||
}
|
||||
|
||||
private double ComputeAscent()
|
||||
{
|
||||
double a = CidFont.GetAscent();
|
||||
if (Math.Abs(a) > double.Epsilon)
|
||||
{
|
||||
return GetFontMatrix().TransformY(a);
|
||||
}
|
||||
|
||||
return 0.75;
|
||||
}
|
||||
|
||||
public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
|
||||
@@ -144,6 +170,16 @@
|
||||
return CidFont.FontMatrix;
|
||||
}
|
||||
|
||||
public double GetDescent()
|
||||
{
|
||||
return descent;
|
||||
}
|
||||
|
||||
public double GetAscent()
|
||||
{
|
||||
return ascent;
|
||||
}
|
||||
|
||||
public PdfVector GetPositionVector(int characterCode)
|
||||
{
|
||||
var characterIdentifier = CMap.ConvertToCid(characterCode);
|
||||
|
@@ -45,6 +45,24 @@
|
||||
/// </summary>
|
||||
TransformationMatrix GetFontMatrix();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the descent value of the font, adjusted by the font matrix.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="double"/> representing the descent of the font,
|
||||
/// which is the distance from the baseline to the lowest point of the font's glyphs.
|
||||
/// </returns>
|
||||
double GetDescent();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the ascent value of the font, adjusted byt the font matrix.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="double"/> representing the ascent of the font,
|
||||
/// which is the distance from the baseline to the highest point of the font's glyphs.
|
||||
/// </returns>
|
||||
double GetAscent();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the glyph path for the given character code.
|
||||
/// </summary>
|
||||
|
@@ -33,6 +33,10 @@
|
||||
|
||||
private readonly bool isZapfDingbats;
|
||||
|
||||
private readonly TransformationMatrix fontMatrix;
|
||||
private readonly double descent;
|
||||
private readonly double ascent;
|
||||
|
||||
#nullable disable
|
||||
public NameToken Name { get; }
|
||||
#nullable enable
|
||||
@@ -66,6 +70,37 @@
|
||||
?? FontDetails.GetDefault(Name?.Data);
|
||||
|
||||
isZapfDingbats = encoding is ZapfDingbatsEncoding || Details.Name.Contains("ZapfDingbats");
|
||||
|
||||
// Set font matrix
|
||||
double scale = 1000.0;
|
||||
if (this.font?.TableRegister.HeaderTable is not null)
|
||||
{
|
||||
scale = this.font.GetUnitsPerEm();
|
||||
}
|
||||
|
||||
fontMatrix = TransformationMatrix.FromValues(1.0 / scale, 0, 0, 1.0 / scale, 0, 0);
|
||||
descent = ComputeDescent();
|
||||
ascent = ComputeAscent();
|
||||
}
|
||||
|
||||
private double ComputeDescent()
|
||||
{
|
||||
if (font is null)
|
||||
{
|
||||
return DefaultTransformation.TransformY(descriptor!.Descent);
|
||||
}
|
||||
|
||||
return GetFontMatrix().TransformY(font.TableRegister.HorizontalHeaderTable.Descent);
|
||||
}
|
||||
|
||||
private double ComputeAscent()
|
||||
{
|
||||
if (font is null)
|
||||
{
|
||||
return DefaultTransformation.TransformY(descriptor!.Ascent);
|
||||
}
|
||||
|
||||
return GetFontMatrix().TransformY(font.TableRegister.HorizontalHeaderTable.Ascent);
|
||||
}
|
||||
|
||||
public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
|
||||
@@ -195,14 +230,7 @@
|
||||
|
||||
public TransformationMatrix GetFontMatrix()
|
||||
{
|
||||
var scale = 1000.0;
|
||||
|
||||
if (font?.TableRegister.HeaderTable != null)
|
||||
{
|
||||
scale = font.GetUnitsPerEm();
|
||||
}
|
||||
|
||||
return TransformationMatrix.FromValues(1 / scale, 0, 0, 1 / scale, 0, 0);
|
||||
return fontMatrix;
|
||||
}
|
||||
|
||||
private PdfRectangle GetBoundingBoxInGlyphSpace(int characterCode, out bool fromFont)
|
||||
@@ -338,6 +366,16 @@
|
||||
return widths[index];
|
||||
}
|
||||
|
||||
public double GetDescent()
|
||||
{
|
||||
return descent;
|
||||
}
|
||||
|
||||
public double GetAscent()
|
||||
{
|
||||
return ascent;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList<PdfSubpath>? path)
|
||||
{
|
||||
|
@@ -19,6 +19,9 @@
|
||||
private static readonly TransformationMatrix DefaultTransformation =
|
||||
TransformationMatrix.FromValues(1 / 1000.0, 0, 0, 1 / 1000.0, 0, 0);
|
||||
|
||||
private readonly TransformationMatrix fontMatrix;
|
||||
private readonly double ascent;
|
||||
private readonly double descent;
|
||||
private readonly AdobeFontMetrics fontMetrics;
|
||||
private readonly Encoding encoding;
|
||||
private readonly TrueTypeFont font;
|
||||
@@ -45,8 +48,42 @@
|
||||
|
||||
// Assumption is ZapfDingbats is not possible here. We need to change the behaviour if not the case
|
||||
System.Diagnostics.Debug.Assert(!(encoding is ZapfDingbatsEncoding || Details.Name.Contains("ZapfDingbats")));
|
||||
|
||||
// Set font matrix
|
||||
if (this.font?.TableRegister.HeaderTable is not null)
|
||||
{
|
||||
var scale = (double)this.font.GetUnitsPerEm();
|
||||
fontMatrix = TransformationMatrix.FromValues(1.0 / scale, 0, 0, 1.0 / scale, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fontMatrix = DefaultTransformation;
|
||||
}
|
||||
|
||||
descent = ComputeDescent();
|
||||
ascent = ComputeAscent();
|
||||
}
|
||||
|
||||
private double ComputeDescent()
|
||||
{
|
||||
if (fontMetrics is not null)
|
||||
{
|
||||
return GetFontMatrix().TransformY(fontMetrics.Descender);
|
||||
}
|
||||
|
||||
return GetFontMatrix().TransformY(font.TableRegister.HorizontalHeaderTable.Descent);
|
||||
}
|
||||
|
||||
private double ComputeAscent()
|
||||
{
|
||||
if (fontMetrics is not null)
|
||||
{
|
||||
return GetFontMatrix().TransformY(fontMetrics.Ascender);
|
||||
}
|
||||
|
||||
return GetFontMatrix().TransformY(font.TableRegister.HorizontalHeaderTable.Ascent);
|
||||
}
|
||||
|
||||
public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
|
||||
{
|
||||
codeLength = 1;
|
||||
@@ -127,14 +164,17 @@
|
||||
|
||||
public TransformationMatrix GetFontMatrix()
|
||||
{
|
||||
if (font?.TableRegister.HeaderTable != null)
|
||||
{
|
||||
var scale = (double)font.GetUnitsPerEm();
|
||||
return fontMatrix;
|
||||
}
|
||||
|
||||
return TransformationMatrix.FromValues(1 / scale, 0, 0, 1 / scale, 0, 0);
|
||||
}
|
||||
public double GetDescent()
|
||||
{
|
||||
return descent;
|
||||
}
|
||||
|
||||
return DefaultTransformation;
|
||||
public double GetAscent()
|
||||
{
|
||||
return ascent;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@@ -36,7 +36,9 @@
|
||||
private readonly ToUnicodeCMap toUnicodeCMap;
|
||||
|
||||
private readonly TransformationMatrix fontMatrix;
|
||||
|
||||
private readonly double ascent;
|
||||
private readonly double descent;
|
||||
|
||||
private readonly bool isZapfDingbats;
|
||||
|
||||
public NameToken Name { get; }
|
||||
@@ -83,6 +85,60 @@
|
||||
Details = fontDescriptor?.ToDetails(name?.Data)
|
||||
?? FontDetails.GetDefault(name?.Data);
|
||||
isZapfDingbats = encoding is ZapfDingbatsEncoding || Details.Name.Contains("ZapfDingbats");
|
||||
descent = ComputeDescent();
|
||||
ascent = ComputeAscent();
|
||||
}
|
||||
|
||||
private double ComputeDescent()
|
||||
{
|
||||
if (Math.Abs(fontDescriptor.Descent) > double.Epsilon)
|
||||
{
|
||||
return fontMatrix.TransformY(fontDescriptor.Descent);
|
||||
}
|
||||
|
||||
/*
|
||||
// BobLd: Should 'fontProgram' be used
|
||||
if (fontProgram is not null)
|
||||
{
|
||||
if (fontProgram.TryGetFirst(out var t1))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (fontProgram.TryGetSecond(out var cffCol))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return -0.25;
|
||||
}
|
||||
|
||||
private double ComputeAscent()
|
||||
{
|
||||
if (Math.Abs(fontDescriptor.Ascent) > double.Epsilon)
|
||||
{
|
||||
return fontMatrix.TransformY(fontDescriptor.Ascent);
|
||||
}
|
||||
|
||||
/*
|
||||
// BobLd: Should 'fontProgram' be used
|
||||
if (fontProgram is not null)
|
||||
{
|
||||
if (fontProgram.TryGetFirst(out var t1))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (fontProgram.TryGetSecond(out var cffCol))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return 0.75;
|
||||
}
|
||||
|
||||
public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
|
||||
@@ -206,7 +262,7 @@
|
||||
{
|
||||
var first = cffFont.FirstFont;
|
||||
string characterName;
|
||||
if (encoding != null)
|
||||
if (encoding is not null)
|
||||
{
|
||||
characterName = encoding.GetName(characterCode);
|
||||
}
|
||||
@@ -232,6 +288,16 @@
|
||||
return fontMatrix;
|
||||
}
|
||||
|
||||
public double GetDescent()
|
||||
{
|
||||
return descent;
|
||||
}
|
||||
|
||||
public double GetAscent()
|
||||
{
|
||||
return ascent;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetPath(int characterCode, [NotNullWhen(true)] out IReadOnlyList<PdfSubpath>? path)
|
||||
{
|
||||
|
@@ -26,6 +26,8 @@ namespace UglyToad.PdfPig.PdfFonts.Simple
|
||||
public FontDetails Details { get; }
|
||||
|
||||
private readonly TransformationMatrix fontMatrix = TransformationMatrix.FromValues(0.001, 0, 0, 0.001, 0, 0);
|
||||
private readonly double ascent;
|
||||
private readonly double descent;
|
||||
|
||||
public Type1Standard14Font(AdobeFontMetrics standardFontMetrics, Encoding? overrideEncoding = null)
|
||||
{
|
||||
@@ -40,6 +42,28 @@ namespace UglyToad.PdfPig.PdfFonts.Simple
|
||||
standardFontMetrics.Weight == "Bold" ? 700 : FontDetails.DefaultWeight,
|
||||
standardFontMetrics.ItalicAngle != 0);
|
||||
isZapfDingbats = encoding is ZapfDingbatsEncoding || Details.Name.Contains("ZapfDingbats");
|
||||
descent = ComputeDescent();
|
||||
ascent = ComputeAscent();
|
||||
}
|
||||
|
||||
private double ComputeDescent()
|
||||
{
|
||||
if (Math.Abs(standardFontMetrics.Descender) < double.Epsilon)
|
||||
{
|
||||
return -0.25;
|
||||
}
|
||||
|
||||
return fontMatrix.TransformY(standardFontMetrics.Descender);
|
||||
}
|
||||
|
||||
private double ComputeAscent()
|
||||
{
|
||||
if (Math.Abs(standardFontMetrics.Ascender) < double.Epsilon)
|
||||
{
|
||||
return 0.75;
|
||||
}
|
||||
|
||||
return fontMatrix.TransformY(standardFontMetrics.Ascender);
|
||||
}
|
||||
|
||||
public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
|
||||
@@ -115,6 +139,16 @@ namespace UglyToad.PdfPig.PdfFonts.Simple
|
||||
return fontMatrix;
|
||||
}
|
||||
|
||||
public double GetDescent()
|
||||
{
|
||||
return descent;
|
||||
}
|
||||
|
||||
public double GetAscent()
|
||||
{
|
||||
return ascent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// <para>Not implemented.</para>
|
||||
|
@@ -13,6 +13,8 @@
|
||||
{
|
||||
private readonly PdfRectangle boundingBox;
|
||||
private readonly TransformationMatrix fontMatrix;
|
||||
private readonly double ascent;
|
||||
private readonly double descent;
|
||||
private readonly Encoding encoding;
|
||||
private readonly int firstChar;
|
||||
private readonly int lastChar;
|
||||
@@ -45,6 +47,18 @@
|
||||
|
||||
// Assumption is ZapfDingbats is not possible here. We need to change the behaviour if not the case
|
||||
System.Diagnostics.Debug.Assert(!(encoding is ZapfDingbatsEncoding || Details.Name.Contains("ZapfDingbats")));
|
||||
descent = ComputeDescent();
|
||||
ascent = ComputeAscent();
|
||||
}
|
||||
|
||||
private double ComputeDescent()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
private double ComputeAscent()
|
||||
{
|
||||
return fontMatrix.TransformY(boundingBox.Height);
|
||||
}
|
||||
|
||||
public int ReadCharacterCode(IInputBytes bytes, out int codeLength)
|
||||
@@ -106,6 +120,16 @@
|
||||
return fontMatrix;
|
||||
}
|
||||
|
||||
public double GetDescent()
|
||||
{
|
||||
return descent;
|
||||
}
|
||||
|
||||
public double GetAscent()
|
||||
{
|
||||
return ascent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// <para>Type 3 fonts do not use vector paths. Always returns <c>false</c>.</para>
|
||||
|
@@ -1069,6 +1069,7 @@
|
||||
var letter = new Letter(
|
||||
c.ToString(),
|
||||
documentSpace,
|
||||
documentSpace,
|
||||
advanceRect.BottomLeft,
|
||||
advanceRect.BottomRight,
|
||||
width,
|
||||
|
Reference in New Issue
Block a user