mirror of
https://github.com/UglyToad/PdfPig.git
synced 2026-03-10 00:23:29 +08:00
support format 6 cmap sub tables for truetype fonts. pass the truetypefont to the ifont implementation so we can use it to access font data
This commit is contained in:
@@ -122,7 +122,7 @@
|
||||
name = "cvt ";
|
||||
}
|
||||
|
||||
var match = font.Tables[name];
|
||||
var match = font.TableHeaders[name];
|
||||
|
||||
var offset = long.Parse(parts[1]);
|
||||
var length = long.Parse(parts[2]);
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
Encoding encoding = encodingReader.Read(dictionary, isLenientParsing, descriptor);
|
||||
|
||||
return new TrueTypeSimpleFont(name, firstCharacter, lastCharacter, widths, descriptor, toUnicodeCMap, encoding);
|
||||
return new TrueTypeSimpleFont(name, firstCharacter, lastCharacter, widths, descriptor, toUnicodeCMap, encoding, font);
|
||||
}
|
||||
|
||||
private TrueTypeFont ParseTrueTypeFont(FontDescriptor descriptor)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
using Geometry;
|
||||
using IO;
|
||||
using Tokenization.Tokens;
|
||||
using TrueType;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
internal class TrueTypeSimpleFont : IFont
|
||||
@@ -19,6 +20,8 @@
|
||||
private readonly FontDescriptor descriptor;
|
||||
[CanBeNull]
|
||||
private readonly Encoding encoding;
|
||||
[CanBeNull]
|
||||
private readonly TrueTypeFont font;
|
||||
|
||||
public NameToken Name { get; }
|
||||
|
||||
@@ -27,16 +30,18 @@
|
||||
[NotNull]
|
||||
public ToUnicodeCMap ToUnicode { get; set; }
|
||||
|
||||
public TrueTypeSimpleFont(NameToken name, int firstCharacterCode, int lastCharacterCode, decimal[] widths,
|
||||
public TrueTypeSimpleFont(NameToken name, int firstCharacterCode, int lastCharacterCode, decimal[] widths,
|
||||
FontDescriptor descriptor,
|
||||
[CanBeNull]CMap toUnicodeCMap,
|
||||
[CanBeNull]Encoding encoding)
|
||||
[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;
|
||||
|
||||
Name = name;
|
||||
IsVertical = false;
|
||||
|
||||
@@ -11,9 +11,13 @@
|
||||
{
|
||||
var version = (decimal)data.Read32Fixed();
|
||||
int numberOfTables = data.ReadUnsignedShort();
|
||||
|
||||
// Read these data points to move to the correct data location.
|
||||
// ReSharper disable UnusedVariable
|
||||
int searchRange = data.ReadUnsignedShort();
|
||||
int entrySelector = data.ReadUnsignedShort();
|
||||
int rangeShift = data.ReadUnsignedShort();
|
||||
// ReSharper restore UnusedVariable
|
||||
|
||||
var tables = new Dictionary<string, TrueTypeHeaderTable>();
|
||||
|
||||
@@ -80,7 +84,6 @@
|
||||
tableRegister.MaximumProfileTable = BasicMaximumProfileTable.Load(data, maxHeaderTable);
|
||||
|
||||
// post
|
||||
var postScriptTable = default(PostScriptTable);
|
||||
if (tables.TryGetValue(TrueTypeHeaderTable.Post, out var postscriptHeaderTable))
|
||||
{
|
||||
tableRegister.PostScriptTable = PostScriptTable.Load(data, table, tableRegister.MaximumProfileTable);
|
||||
@@ -108,7 +111,7 @@
|
||||
OptionallyParseTables(tables, data, tableRegister);
|
||||
}
|
||||
|
||||
return new TrueTypeFont(version, tables, tableRegister.HeaderTable);
|
||||
return new TrueTypeFont(version, tables, tableRegister);
|
||||
}
|
||||
|
||||
private static void OptionallyParseTables(IReadOnlyDictionary<string, TrueTypeHeaderTable> tables, TrueTypeDataBytes data, TableRegister tableRegister)
|
||||
|
||||
@@ -69,10 +69,11 @@ namespace UglyToad.PdfPig.Fonts.TrueType.Tables.CMapSubTables
|
||||
|
||||
var idRangeOffsets = data.ReadUnsignedShortArray(segmentCount);
|
||||
|
||||
const int singleIntsRead = 16;
|
||||
const int singleIntsRead = 8;
|
||||
const int intArraysRead = 8;
|
||||
|
||||
var remainingBytes = length - (singleIntsRead + intArraysRead * segmentCount);
|
||||
// ReSharper disable once ArrangeRedundantParentheses
|
||||
var remainingBytes = length - ((singleIntsRead * 2) + intArraysRead * segmentCount);
|
||||
|
||||
var remainingInts = remainingBytes / 2;
|
||||
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
/// </summary>
|
||||
int EncodingId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Maps from a character code to the array index of the glyph in the font data.
|
||||
/// </summary>
|
||||
/// <param name="characterCode">The character code.</param>
|
||||
/// <returns>The index of the glyph information for this character.</returns>
|
||||
int CharacterCodeToGlyphIndex(int characterCode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// ReSharper disable UnusedVariable
|
||||
namespace UglyToad.PdfPig.Fonts.TrueType.Tables.CMapSubTables
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// A format 6 CMap sub-table which uses 2 bytes to map a contiguous range of character codes to glyph indices.
|
||||
/// </summary>
|
||||
internal class TrimmedTableMappingCMapTable : ICMapSubTable
|
||||
{
|
||||
private readonly int firstCharacterCode;
|
||||
private readonly int entryCount;
|
||||
private readonly int[] glyphIndices;
|
||||
|
||||
public int PlatformId { get; }
|
||||
public int EncodingId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TrimmedTableMappingCMapTable"/>.
|
||||
/// </summary>
|
||||
public TrimmedTableMappingCMapTable(int platformId, int encodingId, int firstCharacterCode, int entryCount, int[] glyphIndices)
|
||||
{
|
||||
this.firstCharacterCode = firstCharacterCode;
|
||||
this.entryCount = entryCount;
|
||||
this.glyphIndices = glyphIndices ?? throw new ArgumentNullException(nameof(glyphIndices));
|
||||
|
||||
PlatformId = platformId;
|
||||
EncodingId = encodingId;
|
||||
}
|
||||
|
||||
public int CharacterCodeToGlyphIndex(int characterCode)
|
||||
{
|
||||
if (characterCode < firstCharacterCode || characterCode > firstCharacterCode + entryCount)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var offset = characterCode - firstCharacterCode;
|
||||
|
||||
return glyphIndices[offset];
|
||||
}
|
||||
|
||||
public static TrimmedTableMappingCMapTable Load(TrueTypeDataBytes data, int platformId, int encodingId)
|
||||
{
|
||||
var length = data.ReadUnsignedShort();
|
||||
var language = data.ReadUnsignedShort();
|
||||
|
||||
// First character code in the range.
|
||||
var firstCode = data.ReadUnsignedShort();
|
||||
|
||||
// Number of character codes in the range.
|
||||
var entryCount = data.ReadUnsignedShort();
|
||||
|
||||
var glyphIndices = data.ReadUnsignedShortArray(entryCount);
|
||||
|
||||
return new TrimmedTableMappingCMapTable(platformId, encodingId, firstCode, entryCount, glyphIndices);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,12 +88,12 @@
|
||||
// Microsoft's standard mapping table.
|
||||
var item = Format4CMapTable.Load(data, header.PlatformId, header.EncodingId);
|
||||
tables.Add(item);
|
||||
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
// TODO: support format 6 for modern fonts.
|
||||
var item = TrimmedTableMappingCMapTable.Load(data, header.PlatformId, header.EncodingId);
|
||||
tables.Add(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,33 @@
|
||||
namespace UglyToad.PdfPig.Fonts.TrueType
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CidFonts;
|
||||
using Parser;
|
||||
using Tables;
|
||||
|
||||
internal class TrueTypeFont : ICidFontProgram
|
||||
{
|
||||
public decimal Version { get; }
|
||||
|
||||
public IReadOnlyDictionary<string, TrueTypeHeaderTable> Tables { get; }
|
||||
public IReadOnlyDictionary<string, TrueTypeHeaderTable> TableHeaders { get; }
|
||||
|
||||
public HeaderTable HeaderTable { get; }
|
||||
public CMapTable CMapTable { get; }
|
||||
public GlyphDataTable GlyphTable { get; }
|
||||
|
||||
public TrueTypeFont(decimal version, IReadOnlyDictionary<string, TrueTypeHeaderTable> tables, HeaderTable headerTable)
|
||||
public TrueTypeFont(decimal version, IReadOnlyDictionary<string, TrueTypeHeaderTable> tableHeaders, TableRegister tableRegister)
|
||||
{
|
||||
if (tableRegister == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tableRegister));
|
||||
}
|
||||
|
||||
Version = version;
|
||||
Tables = tables;
|
||||
HeaderTable = headerTable;
|
||||
TableHeaders = tableHeaders;
|
||||
HeaderTable = tableRegister.HeaderTable;
|
||||
CMapTable = tableRegister.CMapTable;
|
||||
GlyphTable = tableRegister.GlyphDataTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user