mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-07 16:04:34 +08:00
Add initial support to process CFF fonts contained inside a TrueType font
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Tables;
|
||||
using UglyToad.PdfPig.Fonts.CompactFontFormat;
|
||||
|
||||
/// <summary>
|
||||
/// Parses TrueType fonts.
|
||||
@@ -59,7 +60,36 @@
|
||||
|
||||
private static TrueTypeFont ParseTables(float version, IReadOnlyDictionary<string, TrueTypeHeaderTable> tables, TrueTypeDataBytes data)
|
||||
{
|
||||
var isPostScript = tables.ContainsKey(TrueTypeHeaderTable.Cff);
|
||||
bool isPostScript = false;
|
||||
CompactFontFormatFontCollection? cffFontCollection = null;
|
||||
|
||||
if (tables.TryGetValue(TrueTypeHeaderTable.Cff, out var cffTable))
|
||||
{
|
||||
isPostScript = true;
|
||||
try
|
||||
{
|
||||
/*
|
||||
* The presence of a CFF (Compact Font Format) table in a TrueType font creates a hybrid situation where the font
|
||||
* container uses TrueType structure but contains PostScript-based glyph descriptions. According to the OpenType
|
||||
* specification, when a TrueType font contains a CFF table instead of a traditional glyf table, it indicates
|
||||
* "an OpenType font with PostScript outlines". This creates what's known as an OpenType CFF font, which uses
|
||||
* PostScript Type 2 charstrings for glyph descriptions rather than TrueType quadratic curves.
|
||||
*
|
||||
* This is to fix P2P-33713919.pdf
|
||||
* See https://github.com/BobLd/PdfPig.Rendering.Skia/issues/46
|
||||
* TODO - Add test coverage and need to review if the logic belongs here
|
||||
*/
|
||||
|
||||
data.Seek(cffTable.Offset);
|
||||
var buffer = data.ReadByteArray((int)cffTable.Length);
|
||||
cffFontCollection = CompactFontFormatParser.Parse(new CompactFontFormatData(buffer));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(e);
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
var builder = new TableRegister.Builder();
|
||||
|
||||
@@ -102,7 +132,7 @@
|
||||
{
|
||||
builder.Os2Table = TableParser.Parse<Os2Table>(os2Table, data, builder);
|
||||
}
|
||||
|
||||
|
||||
if (!isPostScript)
|
||||
{
|
||||
if (!tables.TryGetValue(TrueTypeHeaderTable.Loca, out var indexToLocationHeaderTable))
|
||||
@@ -125,7 +155,7 @@
|
||||
|
||||
OptionallyParseTables(tables, data, builder);
|
||||
|
||||
return new TrueTypeFont(version, tables, builder.Build());
|
||||
return new TrueTypeFont(version, tables, builder.Build(), cffFontCollection);
|
||||
}
|
||||
|
||||
internal static NameTable GetNameTable(TrueTypeDataBytes data)
|
||||
@@ -134,7 +164,7 @@
|
||||
{
|
||||
throw new ArgumentNullException(nameof(data));
|
||||
}
|
||||
|
||||
|
||||
// Read these data points to move to the correct data location.
|
||||
data.Read32Fixed();
|
||||
int numberOfTables = data.ReadUnsignedShort();
|
||||
|
@@ -5,6 +5,7 @@
|
||||
using Core;
|
||||
using Parser;
|
||||
using Tables.CMapSubTables;
|
||||
using UglyToad.PdfPig.Fonts.CompactFontFormat;
|
||||
|
||||
/// <summary>
|
||||
/// A TrueType font.
|
||||
@@ -54,17 +55,33 @@
|
||||
/// </summary>
|
||||
public int NumberOfTables { get; }
|
||||
|
||||
// TODO - It would be better to use 'PdfCidCompactFontFormatFont' but the class is not accessible from here.
|
||||
private readonly CompactFontFormatFontCollection? cffFontCollection;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TrueTypeFont"/>.
|
||||
/// </summary>
|
||||
internal TrueTypeFont(float version, IReadOnlyDictionary<string, TrueTypeHeaderTable> tableHeaders, TableRegister tableRegister)
|
||||
internal TrueTypeFont(float version, IReadOnlyDictionary<string, TrueTypeHeaderTable> tableHeaders, TableRegister tableRegister, CompactFontFormatFontCollection? cffFontCollection)
|
||||
{
|
||||
Version = version;
|
||||
TableHeaders = tableHeaders ?? throw new ArgumentNullException(nameof(tableHeaders));
|
||||
TableRegister = tableRegister ?? throw new ArgumentNullException(nameof(tableRegister));
|
||||
NumberOfTables = tableHeaders.Count;
|
||||
|
||||
if (TableRegister.CMapTable != null)
|
||||
/*
|
||||
* The presence of a CFF (Compact Font Format) table in a TrueType font creates a hybrid situation where the font
|
||||
* container uses TrueType structure but contains PostScript-based glyph descriptions. According to the OpenType
|
||||
* specification, when a TrueType font contains a CFF table instead of a traditional glyf table, it indicates
|
||||
* "an OpenType font with PostScript outlines". This creates what's known as an OpenType CFF font, which uses
|
||||
* PostScript Type 2 charstrings for glyph descriptions rather than TrueType quadratic curves.
|
||||
*
|
||||
* This is to fix P2P-33713919.pdf
|
||||
* See https://github.com/BobLd/PdfPig.Rendering.Skia/issues/46
|
||||
* TODO - Add test coverage and need to review if the logic belongs here
|
||||
*/
|
||||
this.cffFontCollection = cffFontCollection;
|
||||
|
||||
if (TableRegister.CMapTable is not null)
|
||||
{
|
||||
const int encodingSymbol = 0;
|
||||
const int encodingUnicode = 1;
|
||||
@@ -72,19 +89,19 @@
|
||||
|
||||
foreach (var subTable in TableRegister.CMapTable.SubTables)
|
||||
{
|
||||
if (WindowsSymbolCMap == null
|
||||
if (WindowsSymbolCMap is null
|
||||
&& subTable.PlatformId == TrueTypeCMapPlatform.Windows
|
||||
&& subTable.EncodingId == encodingSymbol)
|
||||
{
|
||||
WindowsSymbolCMap = subTable;
|
||||
}
|
||||
else if (WindowsUnicodeCMap == null
|
||||
else if (WindowsUnicodeCMap is null
|
||||
&& subTable.PlatformId == TrueTypeCMapPlatform.Windows
|
||||
&& subTable.EncodingId == encodingUnicode)
|
||||
{
|
||||
WindowsUnicodeCMap = subTable;
|
||||
}
|
||||
else if (MacRomanCMap == null
|
||||
else if (MacRomanCMap is null
|
||||
&& subTable.PlatformId == TrueTypeCMapPlatform.Macintosh
|
||||
&& subTable.EncodingId == encodingMacRoman)
|
||||
{
|
||||
@@ -107,8 +124,36 @@
|
||||
{
|
||||
boundingBox = default(PdfRectangle);
|
||||
|
||||
if (TableRegister.GlyphTable == null)
|
||||
if (TableRegister.GlyphTable is null)
|
||||
{
|
||||
if (cffFontCollection is not null)
|
||||
{
|
||||
/*
|
||||
* The presence of a CFF (Compact Font Format) table in a TrueType font creates a hybrid situation where the font
|
||||
* container uses TrueType structure but contains PostScript-based glyph descriptions. According to the OpenType
|
||||
* specification, when a TrueType font contains a CFF table instead of a traditional glyf table, it indicates
|
||||
* "an OpenType font with PostScript outlines". This creates what's known as an OpenType CFF font, which uses
|
||||
* PostScript Type 2 charstrings for glyph descriptions rather than TrueType quadratic curves.
|
||||
*
|
||||
* This is to fix P2P-33713919.pdf
|
||||
* See https://github.com/BobLd/PdfPig.Rendering.Skia/issues/46
|
||||
* TODO - Add test coverage and need to review if the logic belongs here
|
||||
*/
|
||||
|
||||
var name = cffFontCollection.FirstFont.GetCharacterName(characterCode, true); // TODO cid?
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var bbox = cffFontCollection.FirstFont.GetCharacterBoundingBox(name);
|
||||
if (bbox.HasValue)
|
||||
{
|
||||
boundingBox = bbox.Value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -143,8 +188,30 @@
|
||||
{
|
||||
path = null;
|
||||
|
||||
if (TableRegister.GlyphTable == null)
|
||||
if (TableRegister.GlyphTable is null)
|
||||
{
|
||||
if (cffFontCollection is not null)
|
||||
{
|
||||
/*
|
||||
* The presence of a CFF (Compact Font Format) table in a TrueType font creates a hybrid situation where the font
|
||||
* container uses TrueType structure but contains PostScript-based glyph descriptions. According to the OpenType
|
||||
* specification, when a TrueType font contains a CFF table instead of a traditional glyf table, it indicates
|
||||
* "an OpenType font with PostScript outlines". This creates what's known as an OpenType CFF font, which uses
|
||||
* PostScript Type 2 charstrings for glyph descriptions rather than TrueType quadratic curves.
|
||||
*
|
||||
* This is to fix P2P-33713919.pdf
|
||||
* See https://github.com/BobLd/PdfPig.Rendering.Skia/issues/46
|
||||
* TODO - Add test coverage and need to review if the logic belongs here
|
||||
*/
|
||||
|
||||
var name = cffFontCollection.FirstFont.GetCharacterName(characterCode, true);
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return cffFontCollection.FirstFont.TryGetPath(name, out path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -188,7 +255,7 @@
|
||||
{
|
||||
width = 0;
|
||||
|
||||
if (TableRegister.HorizontalMetricsTable == null)
|
||||
if (TableRegister.HorizontalMetricsTable is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -210,7 +277,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TableRegister.CMapTable == null)
|
||||
if (TableRegister.CMapTable is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user