mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-15 03:34:52 +08:00
tidy up truetype tables
* improves the naming of truetype related classes. * uses correct numeric type for the loca table. * makes a few related classes public.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
{
|
||||
using Tables;
|
||||
|
||||
internal interface ITrueTypeTableParser<out T> where T : ITable
|
||||
internal interface ITrueTypeTableParser<out T> where T : ITrueTypeTable
|
||||
{
|
||||
T Parse(TrueTypeHeaderTable header, TrueTypeDataBytes data, TableRegister.Builder register);
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@
|
||||
private static readonly NameTableParser NameTableParser = new NameTableParser();
|
||||
private static readonly Os2TableParser Os2TableParser = new Os2TableParser();
|
||||
|
||||
public static T Parse<T>(TrueTypeHeaderTable table, TrueTypeDataBytes data, TableRegister.Builder register) where T : ITable
|
||||
public static T Parse<T>(TrueTypeHeaderTable table, TrueTypeDataBytes data, TableRegister.Builder register) where T : ITrueTypeTable
|
||||
{
|
||||
if (typeof(T) == typeof(CMapTable))
|
||||
{
|
||||
|
@@ -7,7 +7,7 @@
|
||||
using IO;
|
||||
using Util;
|
||||
|
||||
internal class CMapTable : ITable, IWriteable
|
||||
internal class CMapTable : ITrueTypeTable, IWriteable
|
||||
{
|
||||
public IReadOnlyList<ICMapSubTable> SubTables { get; }
|
||||
|
||||
|
@@ -11,7 +11,7 @@
|
||||
/// The 'glyf' table contains the data that defines the appearance of the glyphs in the font.
|
||||
/// This includes specification of the points that describe the contours that make up a glyph outline and the instructions that grid-fit that glyph.
|
||||
/// </summary>
|
||||
internal class GlyphDataTable : ITable
|
||||
internal class GlyphDataTable : ITrueTypeTable
|
||||
{
|
||||
public string Tag => TrueTypeHeaderTable.Glyf;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
var offsets = indexToLocationTable.GlyphOffsets;
|
||||
|
||||
var entryCount = offsets.Length;
|
||||
var entryCount = offsets.Count;
|
||||
|
||||
var glyphCount = entryCount - 1;
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
/// The 'head' table contains global information about the font.
|
||||
/// It contains things like as the font version number, the creation and modification dates, revision number and basic typographic data that applies to the font as a whole.
|
||||
/// </summary>
|
||||
internal class HeaderTable : ITable
|
||||
internal class HeaderTable : ITrueTypeTable
|
||||
{
|
||||
public string Tag => TrueTypeHeaderTable.Head;
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
/// The 'hhea' table contains information needed to layout fonts whose characters are written horizontally, that is, either left to right or right to left.
|
||||
/// This table contains information that is general to the font as a whole.
|
||||
/// </summary>
|
||||
internal class HorizontalHeaderTable : ITable
|
||||
internal class HorizontalHeaderTable : ITrueTypeTable
|
||||
{
|
||||
public string Tag => TrueTypeHeaderTable.Hhea;
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
/// <summary>
|
||||
/// The 'hmtx' table contains metric information for the horizontal layout each of the glyphs in the font.
|
||||
/// </summary>
|
||||
internal class HorizontalMetricsTable : ITable, IWriteable
|
||||
internal class HorizontalMetricsTable : ITrueTypeTable, IWriteable
|
||||
{
|
||||
public string Tag => TrueTypeHeaderTable.Hmtx;
|
||||
|
||||
|
@@ -1,9 +0,0 @@
|
||||
namespace UglyToad.PdfPig.Fonts.TrueType.Tables
|
||||
{
|
||||
internal interface ITable
|
||||
{
|
||||
string Tag { get; }
|
||||
|
||||
TrueTypeHeaderTable DirectoryTable { get; }
|
||||
}
|
||||
}
|
18
src/UglyToad.PdfPig/Fonts/TrueType/Tables/ITrueTypeTable.cs
Normal file
18
src/UglyToad.PdfPig/Fonts/TrueType/Tables/ITrueTypeTable.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace UglyToad.PdfPig.Fonts.TrueType.Tables
|
||||
{
|
||||
/// <summary>
|
||||
/// A table in a TrueType font.
|
||||
/// </summary>
|
||||
public interface ITrueTypeTable
|
||||
{
|
||||
/// <summary>
|
||||
/// The tag, a 4 letter/byte code, used to identify this table in a TrueType font.
|
||||
/// </summary>
|
||||
string Tag { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The directory entry from the font's offset subtable which indicates the length, offset, type and checksum of a table.
|
||||
/// </summary>
|
||||
TrueTypeHeaderTable DirectoryTable { get; }
|
||||
}
|
||||
}
|
@@ -1,56 +1,95 @@
|
||||
namespace UglyToad.PdfPig.Fonts.TrueType.Tables
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Exceptions;
|
||||
using IO;
|
||||
using Parser;
|
||||
using Util;
|
||||
|
||||
/// <inheritdoc cref="ITrueTypeTable"/>
|
||||
/// <summary>
|
||||
/// Stores the offset to the glyph locations relative to the start of the glyph data table.
|
||||
/// Stores the offset to the glyph locations relative to the start of the <see cref="GlyphDataTable"/>.
|
||||
/// Index zero points to the "missing character" which is used for characters not provided by the font.
|
||||
/// The number of glpyhs in this table should match the maximum profile table.
|
||||
/// The number of glpyhs in this table should match the maximum profile table. The glyph offsets contains
|
||||
/// an extra entry at the last index which points to the end of the glyph data, this makes it possible to compute
|
||||
/// the length of the last glyph entry and supports empty glyphs.
|
||||
/// </summary>
|
||||
internal class IndexToLocationTable : ITable, IWriteable
|
||||
public class IndexToLocationTable : ITrueTypeTable, IWriteable
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string Tag => TrueTypeHeaderTable.Loca;
|
||||
|
||||
/// <inheritdoc />
|
||||
public TrueTypeHeaderTable DirectoryTable { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the format the offsets were stored in in the underlying file, for <see cref="EntryFormat.Short"/>
|
||||
/// the values are divided by 2. The values in <see cref="GlyphOffsets"/> are the real offsets, with any format
|
||||
/// changes removed.
|
||||
/// </summary>
|
||||
public EntryFormat Format { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The glyph offsets relative to the start of the glyph data table.
|
||||
/// </summary>
|
||||
public long[] GlyphOffsets { get; }
|
||||
public IReadOnlyList<uint> GlyphOffsets { get; }
|
||||
|
||||
public IndexToLocationTable(TrueTypeHeaderTable directoryTable, EntryFormat format, long[] glyphOffsets)
|
||||
/// <summary>
|
||||
/// Create a new <see cref="IndexToLocationTable"/>.
|
||||
/// </summary>
|
||||
public IndexToLocationTable(TrueTypeHeaderTable directoryTable, EntryFormat format, IReadOnlyList<uint> glyphOffsets)
|
||||
{
|
||||
DirectoryTable = directoryTable;
|
||||
Format = format;
|
||||
GlyphOffsets = glyphOffsets;
|
||||
GlyphOffsets = glyphOffsets ?? throw new ArgumentNullException(nameof(glyphOffsets));
|
||||
}
|
||||
|
||||
public static IndexToLocationTable Load(TrueTypeDataBytes data, TrueTypeHeaderTable table, TableRegister.Builder tableRegister)
|
||||
/// <summary>
|
||||
/// Load the index to location (loca) table from the TrueType font. Requires the maximum profile (maxp) and header (head) table
|
||||
/// to have been parsed.
|
||||
/// </summary>
|
||||
internal static IndexToLocationTable Load(TrueTypeDataBytes data, TrueTypeHeaderTable table, TableRegister.Builder tableRegister)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(data));
|
||||
}
|
||||
|
||||
if (tableRegister == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tableRegister));
|
||||
}
|
||||
|
||||
data.Seek(table.Offset);
|
||||
|
||||
var headerTable = tableRegister.HeaderTable;
|
||||
var maximumProfileTable = tableRegister.MaximumProfileTable;
|
||||
|
||||
if (headerTable == null)
|
||||
{
|
||||
throw new InvalidFontFormatException("No header (head) table was defined in this font.");
|
||||
}
|
||||
|
||||
if (maximumProfileTable == null)
|
||||
{
|
||||
throw new InvalidFontFormatException("No maximum profile (maxp) table was defined in this font.");
|
||||
}
|
||||
|
||||
var format = (EntryFormat)headerTable.IndexToLocFormat;
|
||||
|
||||
var glyphCount = maximumProfileTable.NumberOfGlyphs + 1;
|
||||
|
||||
var offsets = new long[glyphCount];
|
||||
var offsets = new uint[glyphCount];
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case EntryFormat.Short:
|
||||
{ // The local offset divided by 2 is stored.
|
||||
for (int i = 0; i < glyphCount; i++)
|
||||
for (var i = 0; i < glyphCount; i++)
|
||||
{
|
||||
offsets[i] = data.ReadUnsignedShort() * 2;
|
||||
offsets[i] = (uint)(data.ReadUnsignedShort() * 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -68,9 +107,10 @@
|
||||
return new IndexToLocationTable(table, format, offsets);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
for (var i = 0; i < GlyphOffsets.Length; i++)
|
||||
for (var i = 0; i < GlyphOffsets.Count; i++)
|
||||
{
|
||||
var offset = GlyphOffsets[i];
|
||||
switch (Format)
|
||||
@@ -87,6 +127,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The format of glyph offset entries stored in the raw TrueType data.
|
||||
/// </summary>
|
||||
public enum EntryFormat : short
|
||||
{
|
||||
/// <summary>
|
||||
|
@@ -5,7 +5,7 @@
|
||||
/// <summary>
|
||||
/// This table establishes the memory requirements for the font.
|
||||
/// </summary>
|
||||
internal class BasicMaximumProfileTable : ITable
|
||||
internal class BasicMaximumProfileTable : ITrueTypeTable
|
||||
{
|
||||
public string Tag => TrueTypeHeaderTable.Maxp;
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
using Names;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
internal class NameTable : ITable
|
||||
internal class NameTable : ITrueTypeTable
|
||||
{
|
||||
public string Tag => TrueTypeHeaderTable.Name;
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
/// <summary>
|
||||
/// The most basic format of the OS/2 table, excluding the fields not included in the Apple version of the specification.
|
||||
/// </summary>
|
||||
internal class Os2Table : ITable, IWriteable
|
||||
internal class Os2Table : ITrueTypeTable, IWriteable
|
||||
{
|
||||
public string Tag => TrueTypeHeaderTable.Os2;
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
/// This table contains information for TrueType fonts on PostScript printers.
|
||||
/// This includes data for the FontInfo dictionary and the PostScript glyph names.
|
||||
/// </summary>
|
||||
internal class PostScriptTable : ITable
|
||||
internal class PostScriptTable : ITrueTypeTable
|
||||
{
|
||||
public string Tag => TrueTypeHeaderTable.Post;
|
||||
|
||||
|
@@ -147,11 +147,11 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
public void ReadUnsignedIntArray(long[] offsets, int length)
|
||||
public void ReadUnsignedIntArray(uint[] offsets, int length)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
offsets[i] = ReadUnsignedInt();
|
||||
offsets[i] = (uint)ReadUnsignedInt();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,10 +6,12 @@
|
||||
using Util;
|
||||
using Util.JetBrains.Annotations;
|
||||
|
||||
/// <inheritdoc cref="IWriteable" />
|
||||
/// <summary>
|
||||
/// A table directory entry from the TrueType font file.
|
||||
/// A table directory entry from the TrueType font file. Indicates the position of the corresponding table
|
||||
/// data in the TrueType font.
|
||||
/// </summary>
|
||||
internal struct TrueTypeHeaderTable : IWriteable
|
||||
public struct TrueTypeHeaderTable : IWriteable
|
||||
{
|
||||
#region RequiredTableTags
|
||||
/// <summary>
|
||||
@@ -160,7 +162,11 @@
|
||||
#endregion
|
||||
|
||||
#region PostScriptTableTags
|
||||
|
||||
/// <summary>
|
||||
/// Compact font format table. The corresponding table contains a Compact Font Format font representation
|
||||
/// (also known as a PostScript Type 1, or CIDFont).
|
||||
/// </summary>
|
||||
/// <remarks>Optional</remarks>
|
||||
public const string Cff = "cff ";
|
||||
#endregion
|
||||
|
||||
@@ -176,18 +182,31 @@
|
||||
public uint CheckSum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Offset of the table from the beginning of the file.
|
||||
/// Offset of the table data from the beginning of the file in bytes.
|
||||
/// </summary>
|
||||
public uint Offset { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The length of the table.
|
||||
/// The length of the table data in bytes.
|
||||
/// </summary>
|
||||
public uint Length { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TrueTypeHeaderTable"/>.
|
||||
/// </summary>
|
||||
public TrueTypeHeaderTable(string tag, uint checkSum, uint offset, uint length)
|
||||
{
|
||||
Tag = tag ?? throw new ArgumentNullException(nameof(tag));
|
||||
if (tag == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tag));
|
||||
}
|
||||
|
||||
if (tag.Length != 4)
|
||||
{
|
||||
throw new ArgumentException($"A TrueType table tag must be a uint32, 4 bytes long, instead got: {tag}.", nameof(tag));
|
||||
}
|
||||
|
||||
Tag = tag;
|
||||
CheckSum = checkSum;
|
||||
Offset = offset;
|
||||
Length = length;
|
||||
@@ -201,11 +220,7 @@
|
||||
return new TrueTypeHeaderTable(tag, 0, 0, 0);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Tag} {Offset} {Length} {CheckSum}";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Write(Stream stream)
|
||||
{
|
||||
for (var i = 0; i < Tag.Length; i++)
|
||||
@@ -217,5 +232,11 @@
|
||||
stream.WriteUInt(Offset);
|
||||
stream.WriteUInt(Length);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Tag} - Offset: {Offset} Length: {Length} Checksum: {CheckSum}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -150,7 +150,7 @@
|
||||
{
|
||||
var indexToLocationTable = font.TableRegister.IndexToLocationTable;
|
||||
|
||||
var numGlyphs = indexToLocationTable.GlyphOffsets.Length - 1;
|
||||
var numGlyphs = indexToLocationTable.GlyphOffsets.Count - 1;
|
||||
|
||||
var glyphDirectory = font.TableRegister.GlyphTable.DirectoryTable;
|
||||
|
||||
|
@@ -3,7 +3,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using IO;
|
||||
using PdfPig.Fonts.Exceptions;
|
||||
using PdfPig.Fonts.TrueType;
|
||||
@@ -117,7 +116,7 @@
|
||||
else if (entry.Tag == TrueTypeHeaderTable.Loca)
|
||||
{
|
||||
var table = new IndexToLocationTable(entry.DummyHeader, IndexToLocationTable.EntryFormat.Long,
|
||||
trueTypeSubsetGlyphTable.GlyphOffsets.Select(x => (long)x).ToArray());
|
||||
trueTypeSubsetGlyphTable.GlyphOffsets);
|
||||
table.Write(stream);
|
||||
}
|
||||
else if (entry.Tag == TrueTypeHeaderTable.Head)
|
||||
|
Reference in New Issue
Block a user