move getting the bounding box from a truetype font to the cid font program interface so it can be used from the type 0 and truetype font. comment the pfb parsing logic in type1 fonts

This commit is contained in:
Eliot Jones
2018-04-12 23:11:09 +01:00
parent e063ac45fe
commit a7c8efa6f7
8 changed files with 69 additions and 10 deletions

View File

@@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Fonts.CidFonts
{
using Core;
using Geometry;
using Tokenization.Tokens;
/// <summary>
@@ -39,8 +40,8 @@
FontDescriptor Descriptor { get; }
decimal GetWidthFromFont(int characterCode);
decimal GetWidthFromDictionary(int cid);
PdfRectangle GetBoundingBox(int characterCode);
}
}

View File

@@ -1,10 +1,12 @@
namespace UglyToad.PdfPig.Fonts.CidFonts
{
using Geometry;
/// <summary>
/// Represents either an Adobe Type 1 or TrueType font program for a CIDFont.
/// </summary>
internal interface ICidFontProgram
{
bool TryGetBoundingBox(int characterCode, out PdfRectangle boundingBox);
}
}

View File

@@ -1,6 +1,7 @@
namespace UglyToad.PdfPig.Fonts.CidFonts
{
using Core;
using Geometry;
using Tokenization.Tokens;
/// <inheritdoc/>
@@ -32,5 +33,10 @@
{
throw new System.NotImplementedException();
}
public PdfRectangle GetBoundingBox(int characterCode)
{
throw new System.NotImplementedException();
}
}
}

View File

@@ -2,6 +2,7 @@
{
using System.Collections.Generic;
using Core;
using Geometry;
using Tokenization.Tokens;
/// <inheritdoc />
@@ -57,5 +58,20 @@
return Descriptor.MissingWidth;
}
public PdfRectangle GetBoundingBox(int characterCode)
{
if (fontProgram == null)
{
return Descriptor.BoundingBox;
}
if (fontProgram.TryGetBoundingBox(characterCode, out var result))
{
return result;
}
return Descriptor.BoundingBox;
}
}
}

View File

@@ -88,7 +88,7 @@
public PdfRectangle GetBoundingBox(int characterCode)
{
throw new NotImplementedException();
return CidFont.GetBoundingBox(characterCode);
}
public TransformationMatrix GetFontMatrix()

View File

@@ -107,19 +107,17 @@
public PdfRectangle GetBoundingBox(int characterCode)
{
if (font?.CMapTable == null)
if (font == null)
{
return descriptor.BoundingBox;
}
if (!font.CMapTable.TryGetGlyphIndex(characterCode, out var index))
if (font.TryGetBoundingBox(characterCode, out var bounds))
{
return descriptor.BoundingBox;
return bounds;
}
var glyph = font.GlyphTable.Glyphs[index];
return glyph?.GlyphBounds ?? descriptor.BoundingBox;
return descriptor.BoundingBox;
}
public TransformationMatrix GetFontMatrix()

View File

@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using CidFonts;
using Geometry;
using Parser;
using Tables;
@@ -29,5 +30,31 @@
CMapTable = tableRegister.CMapTable;
GlyphTable = tableRegister.GlyphDataTable;
}
public bool TryGetBoundingBox(int characterCode, out PdfRectangle boundingBox)
{
boundingBox = default(PdfRectangle);
if (CMapTable == null)
{
return false;
}
if (!CMapTable.TryGetGlyphIndex(characterCode, out var index))
{
return false;
}
var glyph = GlyphTable.Glyphs[index];
if (glyph?.GlyphBounds == null)
{
return false;
}
boundingBox = glyph.GlyphBounds;
return true;
}
}
}

View File

@@ -31,6 +31,7 @@
/// <returns>The parsed type 1 font.</returns>
public Type1Font Parse(IInputBytes inputBytes, int length1, int length2)
{
// Sometimes the entire PFB file including the header bytes can be included which prevents parsing in the normal way.
var isEntirePfbFile = inputBytes.Peek() == PfbFileIndicator;
IReadOnlyList<byte> eexecPortion = new byte[0];
@@ -155,6 +156,14 @@
/// </summary>
private static (byte[] ascii, byte[] binary) ReadPfbHeader(IInputBytes bytes)
{
/*
* The header is a 6 byte sequence. The first byte is 0x80 followed by 0x01 for the ASCII record indicator.
* The following 4 bytes determine the size/length of the ASCII part of the PFB file.
* After the ASCII part another 6 byte sequence is present, this time 0x80 0x02 for the Binary part length.
* A 3rd sequence is present at the end re-stating the ASCII length but this is surplus to requirements.
*/
// ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
int ReadSize(byte recordType)
{
bytes.MoveNext();