First commit
Send all results
This commit is contained in:
398
PdfSharp/Fonts.OpenType/FontDescriptor.cs
Normal file
398
PdfSharp/Fonts.OpenType/FontDescriptor.cs
Normal file
@@ -0,0 +1,398 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if GDI
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
#endif
|
||||
#if WPF
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
using PdfSharp.Pdf.Internal;
|
||||
using PdfSharp.Fonts;
|
||||
#if !EDF_CORE
|
||||
using PdfSharp.Drawing;
|
||||
#endif
|
||||
|
||||
#pragma warning disable 0649
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
// TODO: Needs to be refactored #???
|
||||
/// <summary>
|
||||
/// Base class for all font descriptors.
|
||||
/// Currently only OpenTypeDescriptor is derived from this base class.
|
||||
/// </summary>
|
||||
internal class FontDescriptor
|
||||
{
|
||||
protected FontDescriptor(string key)
|
||||
{
|
||||
_key = key;
|
||||
}
|
||||
|
||||
public string Key
|
||||
{
|
||||
get { return _key; }
|
||||
}
|
||||
readonly string _key;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///// <summary>
|
||||
/////
|
||||
///// </summary>
|
||||
//public string FontFile
|
||||
//{
|
||||
// get { return _fontFile; }
|
||||
// private set { _fontFile = value; } // BUG: never set
|
||||
//}
|
||||
//string _fontFile;
|
||||
|
||||
///// <summary>
|
||||
/////
|
||||
///// </summary>
|
||||
//public string FontType
|
||||
//{
|
||||
// get { return _fontType; }
|
||||
// private set { _fontType = value; } // BUG: never set
|
||||
//}
|
||||
//string _fontType;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string FontName
|
||||
{
|
||||
get { return _fontName; }
|
||||
protected set { _fontName = value; }
|
||||
}
|
||||
string _fontName;
|
||||
|
||||
///// <summary>
|
||||
/////
|
||||
///// </summary>
|
||||
//public string FullName
|
||||
//{
|
||||
// get { return _fullName; }
|
||||
// private set { _fullName = value; } // BUG: never set
|
||||
//}
|
||||
//string _fullName;
|
||||
|
||||
///// <summary>
|
||||
/////
|
||||
///// </summary>
|
||||
//public string FamilyName
|
||||
//{
|
||||
// get { return _familyName; }
|
||||
// private set { _familyName = value; } // BUG: never set
|
||||
//}
|
||||
//string _familyName;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Weight
|
||||
{
|
||||
get { return _weight; }
|
||||
private set { _weight = value; } // BUG: never set
|
||||
}
|
||||
string _weight;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance belongs to a bold font.
|
||||
/// </summary>
|
||||
public virtual bool IsBoldFace
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float ItalicAngle
|
||||
{
|
||||
get { return _italicAngle; }
|
||||
protected set { _italicAngle = value; }
|
||||
}
|
||||
float _italicAngle;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance belongs to an italic font.
|
||||
/// </summary>
|
||||
public virtual bool IsItalicFace
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int XMin
|
||||
{
|
||||
get { return _xMin; }
|
||||
protected set { _xMin = value; }
|
||||
}
|
||||
int _xMin;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int YMin
|
||||
{
|
||||
get { return _yMin; }
|
||||
protected set { _yMin = value; }
|
||||
}
|
||||
int _yMin;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int XMax
|
||||
{
|
||||
get { return _xMax; }
|
||||
protected set { _xMax = value; }
|
||||
}
|
||||
int _xMax;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int YMax
|
||||
{
|
||||
get { return _yMax; }
|
||||
protected set { _yMax = value; }
|
||||
}
|
||||
int _yMax;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool IsFixedPitch
|
||||
{
|
||||
get { return _isFixedPitch; }
|
||||
private set { _isFixedPitch = value; } // BUG: never set
|
||||
}
|
||||
bool _isFixedPitch;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int UnderlinePosition
|
||||
{
|
||||
get { return _underlinePosition; }
|
||||
protected set { _underlinePosition = value; }
|
||||
}
|
||||
int _underlinePosition;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int UnderlineThickness
|
||||
{
|
||||
get { return _underlineThickness; }
|
||||
protected set { _underlineThickness = value; }
|
||||
}
|
||||
int _underlineThickness;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int StrikeoutPosition
|
||||
{
|
||||
get { return _strikeoutPosition; }
|
||||
protected set { _strikeoutPosition = value; }
|
||||
}
|
||||
int _strikeoutPosition;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int StrikeoutSize
|
||||
{
|
||||
get { return _strikeoutSize; }
|
||||
protected set { _strikeoutSize = value; }
|
||||
}
|
||||
int _strikeoutSize;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Version
|
||||
{
|
||||
get { return _version; }
|
||||
private set { _version = value; } // BUG: never set
|
||||
}
|
||||
string _version;
|
||||
|
||||
///// <summary>
|
||||
/////
|
||||
///// </summary>
|
||||
//public string Notice
|
||||
//{
|
||||
// get { return Notice; }
|
||||
//}
|
||||
//protected string notice;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string EncodingScheme
|
||||
{
|
||||
get { return _encodingScheme; }
|
||||
private set { _encodingScheme = value; } // BUG: never set
|
||||
}
|
||||
string _encodingScheme;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int UnitsPerEm
|
||||
{
|
||||
get { return _unitsPerEm; }
|
||||
protected set { _unitsPerEm = value; }
|
||||
}
|
||||
int _unitsPerEm;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int CapHeight
|
||||
{
|
||||
get { return _capHeight; }
|
||||
protected set { _capHeight = value; }
|
||||
}
|
||||
int _capHeight;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int XHeight
|
||||
{
|
||||
get { return _xHeight; }
|
||||
protected set { _xHeight = value; }
|
||||
}
|
||||
int _xHeight;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Ascender
|
||||
{
|
||||
get { return _ascender; }
|
||||
protected set { _ascender = value; }
|
||||
}
|
||||
int _ascender;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Descender
|
||||
{
|
||||
get { return _descender; }
|
||||
protected set { _descender = value; }
|
||||
}
|
||||
int _descender;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Leading
|
||||
{
|
||||
get { return _leading; }
|
||||
protected set { _leading = value; }
|
||||
}
|
||||
int _leading;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Flags
|
||||
{
|
||||
get { return _flags; }
|
||||
private set { _flags = value; } // BUG: never set
|
||||
}
|
||||
int _flags;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int StemV
|
||||
{
|
||||
get { return _stemV; }
|
||||
protected set { _stemV = value; }
|
||||
}
|
||||
int _stemV;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int LineSpacing
|
||||
{
|
||||
get { return _lineSpacing; }
|
||||
protected set { _lineSpacing = value; }
|
||||
}
|
||||
int _lineSpacing;
|
||||
|
||||
|
||||
internal static string ComputeKey(XFont font)
|
||||
{
|
||||
return font.GlyphTypeface.Key;
|
||||
//return ComputeKey(font.GlyphTypeface.Fontface.FullFaceName, font.Style);
|
||||
//XGlyphTypeface glyphTypeface = font.GlyphTypeface;
|
||||
//string key = glyphTypeface.Fontface.FullFaceName.ToLowerInvariant() +
|
||||
// (glyphTypeface.IsBold ? "/b" : "") + (glyphTypeface.IsItalic ? "/i" : "");
|
||||
//return key;
|
||||
}
|
||||
|
||||
internal static string ComputeKey(string name, XFontStyle style)
|
||||
{
|
||||
return ComputeKey(name,
|
||||
(style & XFontStyle.Bold) == XFontStyle.Bold,
|
||||
(style & XFontStyle.Italic) == XFontStyle.Italic);
|
||||
}
|
||||
|
||||
internal static string ComputeKey(string name, bool isBold, bool isItalic)
|
||||
{
|
||||
string key = name.ToLowerInvariant() + '/'
|
||||
+ (isBold ? "b" : "") + (isItalic ? "i" : "");
|
||||
return key;
|
||||
}
|
||||
|
||||
internal static string ComputeKey(string name)
|
||||
{
|
||||
string key = name.ToLowerInvariant();
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
70
PdfSharp/Fonts.OpenType/GenericFontTable.cs
Normal file
70
PdfSharp/Fonts.OpenType/GenericFontTable.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
//using Fixed = System.Int32;
|
||||
//using FWord = System.Int16;
|
||||
//using UFWord = System.UInt16;
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
#if true_
|
||||
/// <summary>
|
||||
/// Generic font table. Not yet used
|
||||
/// </summary>
|
||||
internal class GenericFontTable : OpenTypeFontTable
|
||||
{
|
||||
public GenericFontTable(OpenTypeFontTable fontTable)
|
||||
: base(null, "xxxx")
|
||||
{
|
||||
DirectoryEntry.Tag = fontTable.DirectoryEntry.Tag;
|
||||
int length = fontTable.DirectoryEntry.Length;
|
||||
if (length > 0)
|
||||
{
|
||||
_table = new byte[length];
|
||||
Buffer.BlockCopy(fontTable.FontData.Data, fontTable.DirectoryEntry.Offset, _table, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
public GenericFontTable(OpenTypeFontface fontData, string tag)
|
||||
: base(fontData, tag)
|
||||
{
|
||||
_fontData = fontData;
|
||||
}
|
||||
|
||||
protected override OpenTypeFontTable DeepCopy()
|
||||
{
|
||||
GenericFontTable fontTable = (GenericFontTable)base.DeepCopy();
|
||||
fontTable._table = (byte[])_table.Clone();
|
||||
return fontTable;
|
||||
}
|
||||
|
||||
byte[] _table;
|
||||
}
|
||||
#endif
|
||||
}
|
190
PdfSharp/Fonts.OpenType/GlyphDataTable.cs
Normal file
190
PdfSharp/Fonts.OpenType/GlyphDataTable.cs
Normal file
@@ -0,0 +1,190 @@
|
||||
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#define VERBOSE_
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
//using Fixed = System.Int32;
|
||||
//using FWord = System.Int16;
|
||||
//using UFWord = System.UInt16;
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// This table contains information that describes the glyphs in the font in the TrueType outline format.
|
||||
/// Information regarding the rasterizer (scaler) refers to the TrueType rasterizer.
|
||||
/// http://www.microsoft.com/typography/otspec/glyf.htm
|
||||
/// </summary>
|
||||
internal class GlyphDataTable : OpenTypeFontTable
|
||||
{
|
||||
public const string Tag = TableTagNames.Glyf;
|
||||
|
||||
internal byte[] GlyphTable;
|
||||
|
||||
public GlyphDataTable()
|
||||
: base(null, Tag)
|
||||
{
|
||||
DirectoryEntry.Tag = TableTagNames.Glyf;
|
||||
}
|
||||
|
||||
public GlyphDataTable(OpenTypeFontface fontData)
|
||||
: base(fontData, Tag)
|
||||
{
|
||||
DirectoryEntry.Tag = TableTagNames.Glyf;
|
||||
Read();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the bytes in a handy representation
|
||||
/// </summary>
|
||||
public void Read()
|
||||
{
|
||||
try
|
||||
{
|
||||
// not yet needed...
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data of the specified glyph.
|
||||
/// </summary>
|
||||
public byte[] GetGlyphData(int glyph)
|
||||
{
|
||||
IndexToLocationTable loca = _fontData.loca;
|
||||
int start = GetOffset(glyph);
|
||||
int next = GetOffset(glyph + 1);
|
||||
int count = next - start;
|
||||
byte[] bytes = new byte[count];
|
||||
Buffer.BlockCopy(_fontData.FontSource.Bytes, start, bytes, 0, count);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the byte array that defines the glyph.
|
||||
/// </summary>
|
||||
public int GetGlyphSize(int glyph)
|
||||
{
|
||||
IndexToLocationTable loca = _fontData.loca;
|
||||
return GetOffset(glyph + 1) - GetOffset(glyph);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the offset of the specified glyph relative to the first byte of the font image.
|
||||
/// </summary>
|
||||
public int GetOffset(int glyph)
|
||||
{
|
||||
return DirectoryEntry.Offset + _fontData.loca.LocaTable[glyph];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds for all composite glyphs the glyphs the composite one is made of.
|
||||
/// </summary>
|
||||
public void CompleteGlyphClosure(Dictionary<int, object> glyphs)
|
||||
{
|
||||
int count = glyphs.Count;
|
||||
int[] glyphArray = new int[glyphs.Count];
|
||||
glyphs.Keys.CopyTo(glyphArray, 0);
|
||||
if (!glyphs.ContainsKey(0))
|
||||
glyphs.Add(0, null);
|
||||
for (int idx = 0; idx < count; idx++)
|
||||
AddCompositeGlyphs(glyphs, glyphArray[idx]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the specified glyph is a composite glyph add the glyphs it is made of to the glyph table.
|
||||
/// </summary>
|
||||
void AddCompositeGlyphs(Dictionary<int, object> glyphs, int glyph)
|
||||
{
|
||||
//int start = fontData.loca.GetOffset(glyph);
|
||||
int start = GetOffset(glyph);
|
||||
// Has no contour?
|
||||
if (start == GetOffset(glyph + 1))
|
||||
return;
|
||||
_fontData.Position = start;
|
||||
int numContours = _fontData.ReadShort();
|
||||
// Is not a composite glyph?
|
||||
if (numContours >= 0)
|
||||
return;
|
||||
_fontData.SeekOffset(8);
|
||||
for (; ; )
|
||||
{
|
||||
int flags = _fontData.ReadUFWord();
|
||||
int cGlyph = _fontData.ReadUFWord();
|
||||
if (!glyphs.ContainsKey(cGlyph))
|
||||
glyphs.Add(cGlyph, null);
|
||||
if ((flags & MORE_COMPONENTS) == 0)
|
||||
return;
|
||||
int offset = (flags & ARG_1_AND_2_ARE_WORDS) == 0 ? 2 : 4;
|
||||
if ((flags & WE_HAVE_A_SCALE) != 0)
|
||||
offset += 2;
|
||||
else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0)
|
||||
offset += 4;
|
||||
if ((flags & WE_HAVE_A_TWO_BY_TWO) != 0)
|
||||
offset += 8;
|
||||
_fontData.SeekOffset(offset);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepares the font table to be compiled into its binary representation.
|
||||
/// </summary>
|
||||
public override void PrepareForCompilation()
|
||||
{
|
||||
base.PrepareForCompilation();
|
||||
|
||||
if (DirectoryEntry.Length == 0)
|
||||
DirectoryEntry.Length = GlyphTable.Length;
|
||||
DirectoryEntry.CheckSum = CalcChecksum(GlyphTable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the font into its binary representation.
|
||||
/// </summary>
|
||||
public override void Write(OpenTypeFontWriter writer)
|
||||
{
|
||||
writer.Write(GlyphTable, 0, DirectoryEntry.PaddedLength);
|
||||
}
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
// Constants from OpenType spec.
|
||||
const int ARG_1_AND_2_ARE_WORDS = 1;
|
||||
const int WE_HAVE_A_SCALE = 8;
|
||||
const int MORE_COMPONENTS = 32;
|
||||
const int WE_HAVE_AN_X_AND_Y_SCALE = 64;
|
||||
const int WE_HAVE_A_TWO_BY_TWO = 128;
|
||||
// ReSharper restore InconsistentNaming
|
||||
}
|
||||
}
|
116
PdfSharp/Fonts.OpenType/GlyphTypefaceCache.cs
Normal file
116
PdfSharp/Fonts.OpenType/GlyphTypefaceCache.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using PdfSharp.Drawing;
|
||||
using PdfSharp.Internal;
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// Global table of all glyph typefaces.
|
||||
/// </summary>
|
||||
internal class GlyphTypefaceCache
|
||||
{
|
||||
GlyphTypefaceCache()
|
||||
{
|
||||
_glyphTypefacesByKey = new Dictionary<string, XGlyphTypeface>();
|
||||
}
|
||||
|
||||
public static bool TryGetGlyphTypeface(string key, out XGlyphTypeface glyphTypeface)
|
||||
{
|
||||
try
|
||||
{
|
||||
Lock.EnterFontFactory();
|
||||
bool result = Singleton._glyphTypefacesByKey.TryGetValue(key, out glyphTypeface);
|
||||
return result;
|
||||
}
|
||||
finally { Lock.ExitFontFactory(); }
|
||||
}
|
||||
|
||||
public static void AddGlyphTypeface(XGlyphTypeface glyphTypeface)
|
||||
{
|
||||
try
|
||||
{
|
||||
Lock.EnterFontFactory();
|
||||
GlyphTypefaceCache cache = Singleton;
|
||||
Debug.Assert(!cache._glyphTypefacesByKey.ContainsKey(glyphTypeface.Key));
|
||||
cache._glyphTypefacesByKey.Add(glyphTypeface.Key, glyphTypeface);
|
||||
}
|
||||
finally { Lock.ExitFontFactory(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the singleton.
|
||||
/// </summary>
|
||||
static GlyphTypefaceCache Singleton
|
||||
{
|
||||
get
|
||||
{
|
||||
// ReSharper disable once InvertIf
|
||||
if (_singleton == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Lock.EnterFontFactory();
|
||||
if (_singleton == null)
|
||||
_singleton = new GlyphTypefaceCache();
|
||||
}
|
||||
finally { Lock.ExitFontFactory(); }
|
||||
}
|
||||
return _singleton;
|
||||
}
|
||||
}
|
||||
static volatile GlyphTypefaceCache _singleton;
|
||||
|
||||
internal static string GetCacheState()
|
||||
{
|
||||
StringBuilder state = new StringBuilder();
|
||||
state.Append("====================\n");
|
||||
state.Append("Glyph typefaces by name\n");
|
||||
Dictionary<string, XGlyphTypeface>.KeyCollection familyKeys = Singleton._glyphTypefacesByKey.Keys;
|
||||
int count = familyKeys.Count;
|
||||
string[] keys = new string[count];
|
||||
familyKeys.CopyTo(keys, 0);
|
||||
Array.Sort(keys, StringComparer.OrdinalIgnoreCase);
|
||||
foreach (string key in keys)
|
||||
state.AppendFormat(" {0}: {1}\n", key, Singleton._glyphTypefacesByKey[key].DebuggerDisplay);
|
||||
state.Append("\n");
|
||||
return state.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps typeface key to glyph typeface.
|
||||
/// </summary>
|
||||
readonly Dictionary<string, XGlyphTypeface> _glyphTypefacesByKey;
|
||||
}
|
||||
}
|
83
PdfSharp/Fonts.OpenType/IRefFontTable.cs
Normal file
83
PdfSharp/Fonts.OpenType/IRefFontTable.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using Fixed = System.Int32;
|
||||
using FWord = System.Int16;
|
||||
using UFWord = System.UInt16;
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an indirect reference to an existing font table in a font image.
|
||||
/// Used to create binary copies of an existing font table that is not modified.
|
||||
/// </summary>
|
||||
// ReSharper disable once InconsistentNaming - "I" stands for "indirect", not "interface".
|
||||
internal class IRefFontTable : OpenTypeFontTable
|
||||
{
|
||||
public IRefFontTable(OpenTypeFontface fontData, OpenTypeFontTable fontTable)
|
||||
: base(null, fontTable.DirectoryEntry.Tag)
|
||||
{
|
||||
_fontData = fontData;
|
||||
_irefDirectoryEntry = fontTable.DirectoryEntry;
|
||||
}
|
||||
|
||||
readonly TableDirectoryEntry _irefDirectoryEntry;
|
||||
|
||||
/// <summary>
|
||||
/// Prepares the font table to be compiled into its binary representation.
|
||||
/// </summary>
|
||||
public override void PrepareForCompilation()
|
||||
{
|
||||
base.PrepareForCompilation();
|
||||
DirectoryEntry.Length = _irefDirectoryEntry.Length;
|
||||
DirectoryEntry.CheckSum = _irefDirectoryEntry.CheckSum;
|
||||
#if DEBUG
|
||||
// Check the checksum algorithm
|
||||
if (DirectoryEntry.Tag != TableTagNames.Head)
|
||||
{
|
||||
byte[] bytes = new byte[DirectoryEntry.PaddedLength];
|
||||
Buffer.BlockCopy(_irefDirectoryEntry.FontTable._fontData.FontSource.Bytes, _irefDirectoryEntry.Offset, bytes, 0, DirectoryEntry.PaddedLength);
|
||||
uint checkSum1 = DirectoryEntry.CheckSum;
|
||||
uint checkSum2 = CalcChecksum(bytes);
|
||||
// TODO: Sometimes this Assert fails,
|
||||
//Debug.Assert(checkSum1 == checkSum2, "Bug in checksum algorithm.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the font into its binary representation.
|
||||
/// </summary>
|
||||
public override void Write(OpenTypeFontWriter writer)
|
||||
{
|
||||
writer.Write(_irefDirectoryEntry.FontTable._fontData.FontSource.Bytes, _irefDirectoryEntry.Offset, _irefDirectoryEntry.PaddedLength);
|
||||
}
|
||||
}
|
||||
}
|
149
PdfSharp/Fonts.OpenType/IndexToLocationTable.cs
Normal file
149
PdfSharp/Fonts.OpenType/IndexToLocationTable.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#define VERBOSE_
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
//using Fixed = System.Int32;
|
||||
//using FWord = System.Int16;
|
||||
//using UFWord = System.UInt16;
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// The indexToLoc table stores the offsets to the locations of the glyphs in the font,
|
||||
/// relative to the beginning of the glyphData table. In order to compute the length of
|
||||
/// the last glyph element, there is an extra entry after the last valid index.
|
||||
/// </summary>
|
||||
internal class IndexToLocationTable : OpenTypeFontTable
|
||||
{
|
||||
public const string Tag = TableTagNames.Loca;
|
||||
|
||||
internal int[] LocaTable;
|
||||
|
||||
public IndexToLocationTable()
|
||||
: base(null, Tag)
|
||||
{
|
||||
DirectoryEntry.Tag = TableTagNames.Loca;
|
||||
}
|
||||
|
||||
public IndexToLocationTable(OpenTypeFontface fontData)
|
||||
: base(fontData, Tag)
|
||||
{
|
||||
DirectoryEntry = _fontData.TableDictionary[TableTagNames.Loca];
|
||||
Read();
|
||||
}
|
||||
|
||||
public bool ShortIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Converts the bytes in a handy representation
|
||||
/// </summary>
|
||||
public void Read()
|
||||
{
|
||||
try
|
||||
{
|
||||
ShortIndex = _fontData.head.indexToLocFormat == 0;
|
||||
_fontData.Position = DirectoryEntry.Offset;
|
||||
if (ShortIndex)
|
||||
{
|
||||
int entries = DirectoryEntry.Length / 2;
|
||||
Debug.Assert(_fontData.maxp.numGlyphs + 1 == entries,
|
||||
"For your information only: Number of glyphs mismatch in font. You can ignore this assertion.");
|
||||
LocaTable = new int[entries];
|
||||
for (int idx = 0; idx < entries; idx++)
|
||||
LocaTable[idx] = 2 * _fontData.ReadUFWord();
|
||||
}
|
||||
else
|
||||
{
|
||||
int entries = DirectoryEntry.Length / 4;
|
||||
Debug.Assert(_fontData.maxp.numGlyphs + 1 == entries,
|
||||
"For your information only: Number of glyphs mismatch in font. You can ignore this assertion.");
|
||||
LocaTable = new int[entries];
|
||||
for (int idx = 0; idx < entries; idx++)
|
||||
LocaTable[idx] = _fontData.ReadLong();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
GetType();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepares the font table to be compiled into its binary representation.
|
||||
/// </summary>
|
||||
public override void PrepareForCompilation()
|
||||
{
|
||||
DirectoryEntry.Offset = 0;
|
||||
if (ShortIndex)
|
||||
DirectoryEntry.Length = LocaTable.Length * 2;
|
||||
else
|
||||
DirectoryEntry.Length = LocaTable.Length * 4;
|
||||
|
||||
_bytes = new byte[DirectoryEntry.PaddedLength];
|
||||
int length = LocaTable.Length;
|
||||
int byteIdx = 0;
|
||||
if (ShortIndex)
|
||||
{
|
||||
for (int idx = 0; idx < length; idx++)
|
||||
{
|
||||
int value = LocaTable[idx] / 2;
|
||||
_bytes[byteIdx++] = (byte)(value >> 8);
|
||||
_bytes[byteIdx++] = (byte)(value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int idx = 0; idx < length; idx++)
|
||||
{
|
||||
int value = LocaTable[idx];
|
||||
_bytes[byteIdx++] = (byte)(value >> 24);
|
||||
_bytes[byteIdx++] = (byte)(value >> 16);
|
||||
_bytes[byteIdx++] = (byte)(value >> 8);
|
||||
_bytes[byteIdx++] = (byte)value;
|
||||
}
|
||||
}
|
||||
DirectoryEntry.CheckSum = CalcChecksum(_bytes);
|
||||
}
|
||||
byte[] _bytes;
|
||||
|
||||
/// <summary>
|
||||
/// Converts the font into its binary representation.
|
||||
/// </summary>
|
||||
public override void Write(OpenTypeFontWriter writer)
|
||||
{
|
||||
writer.Write(_bytes, 0, DirectoryEntry.PaddedLength);
|
||||
}
|
||||
}
|
||||
}
|
425
PdfSharp/Fonts.OpenType/OpenTypeDescriptor.cs
Normal file
425
PdfSharp/Fonts.OpenType/OpenTypeDescriptor.cs
Normal file
@@ -0,0 +1,425 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
#if GDI
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
#endif
|
||||
#if WPF
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
using PdfSharp.Pdf.Internal;
|
||||
#if !EDF_CORE
|
||||
using PdfSharp.Drawing;
|
||||
#endif
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// The OpenType font descriptor.
|
||||
/// Currently the only font type PDFsharp supports.
|
||||
/// </summary>
|
||||
internal sealed class OpenTypeDescriptor : FontDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// New...
|
||||
/// </summary>
|
||||
public OpenTypeDescriptor(string fontDescriptorKey, string name, XFontStyle stlye, OpenTypeFontface fontface, XPdfFontOptions options)
|
||||
: base(fontDescriptorKey)
|
||||
{
|
||||
FontFace = fontface;
|
||||
FontName = name;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public OpenTypeDescriptor(string fontDescriptorKey, XFont font)
|
||||
: base(fontDescriptorKey)
|
||||
{
|
||||
try
|
||||
{
|
||||
FontFace = font.GlyphTypeface.Fontface;
|
||||
FontName = font.Name;
|
||||
Initialize();
|
||||
}
|
||||
catch
|
||||
{
|
||||
GetType();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
internal OpenTypeDescriptor(string fontDescriptorKey, string idName, byte[] fontData)
|
||||
: base(fontDescriptorKey)
|
||||
{
|
||||
try
|
||||
{
|
||||
FontFace = new OpenTypeFontface(fontData, idName);
|
||||
// Try to get real name form name table
|
||||
if (idName.Contains("XPS-Font-") && FontFace.name != null && FontFace.name.Name.Length != 0)
|
||||
{
|
||||
string tag = String.Empty;
|
||||
if (idName.IndexOf('+') == 6)
|
||||
tag = idName.Substring(0, 6);
|
||||
idName = tag + "+" + FontFace.name.Name;
|
||||
if (FontFace.name.Style.Length != 0)
|
||||
idName += "," + FontFace.name.Style;
|
||||
//idName = idName.Replace(" ", "");
|
||||
}
|
||||
FontName = idName;
|
||||
Initialize();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
GetType();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
internal OpenTypeFontface FontFace;
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
// TODO: Respect embedding restrictions.
|
||||
//bool embeddingRestricted = fontData.os2.fsType == 0x0002;
|
||||
|
||||
//fontName = image.n
|
||||
ItalicAngle = FontFace.post.italicAngle;
|
||||
|
||||
XMin = FontFace.head.xMin;
|
||||
YMin = FontFace.head.yMin;
|
||||
XMax = FontFace.head.xMax;
|
||||
YMax = FontFace.head.yMax;
|
||||
|
||||
UnderlinePosition = FontFace.post.underlinePosition;
|
||||
UnderlineThickness = FontFace.post.underlineThickness;
|
||||
|
||||
// PDFlib states that some Apple fonts miss the OS/2 table.
|
||||
Debug.Assert(FontFace.os2 != null, "TrueType font has no OS/2 table.");
|
||||
|
||||
StrikeoutPosition = FontFace.os2.yStrikeoutPosition;
|
||||
StrikeoutSize = FontFace.os2.yStrikeoutSize;
|
||||
|
||||
// No documentation found how to get the set vertical stems width from the
|
||||
// TrueType tables.
|
||||
// The following formula comes from PDFlib Lite source code. Acrobat 5.0 sets
|
||||
// /StemV to 0 always. I think the value doesn't matter.
|
||||
//float weight = (float)(image.os2.usWeightClass / 65.0f);
|
||||
//stemV = (int)(50 + weight * weight); // MAGIC
|
||||
StemV = 0;
|
||||
|
||||
UnitsPerEm = FontFace.head.unitsPerEm;
|
||||
|
||||
// Calculate Ascent, Descent, Leading and LineSpacing like in WPF Source Code (see FontDriver.ReadBasicMetrics)
|
||||
|
||||
// OS/2 is an optional table, but we can't determine if it is existing in this font.
|
||||
bool os2SeemsToBeEmpty = FontFace.os2.sTypoAscender == 0 && FontFace.os2.sTypoDescender == 0 && FontFace.os2.sTypoLineGap == 0;
|
||||
//Debug.Assert(!os2SeemsToBeEmpty); // Are there fonts without OS/2 table?
|
||||
|
||||
bool dontUseWinLineMetrics = (FontFace.os2.fsSelection & 128) != 0;
|
||||
if (!os2SeemsToBeEmpty && dontUseWinLineMetrics)
|
||||
{
|
||||
// Comment from WPF: The font specifies that the sTypoAscender, sTypoDescender, and sTypoLineGap fields are valid and
|
||||
// should be used instead of winAscent and winDescent.
|
||||
int typoAscender = FontFace.os2.sTypoAscender;
|
||||
int typoDescender = FontFace.os2.sTypoDescender;
|
||||
int typoLineGap = FontFace.os2.sTypoLineGap;
|
||||
|
||||
// Comment from WPF: We include the line gap in the ascent so that white space is distributed above the line. (Note that
|
||||
// the typo line gap is a different concept than "external leading".)
|
||||
Ascender = typoAscender + typoLineGap;
|
||||
// Comment from WPF: Typo descent is a signed value where the positive direction is up. It is therefore typically negative.
|
||||
// A signed typo descent would be quite unusual as it would indicate the descender was above the baseline
|
||||
Descender = -typoDescender;
|
||||
LineSpacing = typoAscender + typoLineGap - typoDescender;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Comment from WPF: get the ascender field
|
||||
int ascender = FontFace.hhea.ascender;
|
||||
// Comment from WPF: get the descender field; this is measured in the same direction as ascender and is therefore
|
||||
// normally negative whereas we want a positive value; however some fonts get the sign wrong
|
||||
// so instead of just negating we take the absolute value.
|
||||
int descender = Math.Abs(FontFace.hhea.descender);
|
||||
// Comment from WPF: get the lineGap field and make sure it's >= 0
|
||||
int lineGap = Math.Max((short)0, FontFace.hhea.lineGap);
|
||||
|
||||
if (!os2SeemsToBeEmpty)
|
||||
{
|
||||
// Comment from WPF: we could use sTypoAscender, sTypoDescender, and sTypoLineGap which are supposed to represent
|
||||
// optimal typographic values not constrained by backwards compatibility; however, many fonts get
|
||||
// these fields wrong or get them right only for Latin text; therefore we use the more reliable
|
||||
// platform-specific Windows values. We take the absolute value of the win32descent in case some
|
||||
// fonts get the sign wrong.
|
||||
int winAscent = FontFace.os2.usWinAscent;
|
||||
int winDescent = Math.Abs(FontFace.os2.usWinDescent);
|
||||
|
||||
Ascender = winAscent;
|
||||
Descender = winDescent;
|
||||
// Comment from WPF: The following calculation for designLineSpacing is per [....]. The default line spacing
|
||||
// should be the sum of the Mac ascender, descender, and lineGap unless the resulting value would
|
||||
// be less than the cell height (winAscent + winDescent) in which case we use the cell height.
|
||||
// See also http://www.microsoft.com/typography/otspec/recom.htm.
|
||||
// Note that in theory it's valid for the baseline-to-baseline distance to be less than the cell
|
||||
// height. However, Windows has never allowed this for Truetype fonts, and fonts built for Windows
|
||||
// sometimes rely on this behavior and get the hha values wrong or set them all to zero.
|
||||
LineSpacing = Math.Max(lineGap + ascender + descender, winAscent + winDescent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ascender = ascender;
|
||||
Descender = descender;
|
||||
LineSpacing = ascender + descender + lineGap;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Assert(Descender >= 0);
|
||||
|
||||
int cellHeight = Ascender + Descender;
|
||||
int internalLeading = cellHeight - UnitsPerEm; // Not used, only for debugging.
|
||||
int externalLeading = LineSpacing - cellHeight;
|
||||
Leading = externalLeading;
|
||||
|
||||
// sCapHeight and sxHeight are only valid if Version >= 2
|
||||
if (FontFace.os2.version >= 2 && FontFace.os2.sCapHeight != 0)
|
||||
CapHeight = FontFace.os2.sCapHeight;
|
||||
else
|
||||
CapHeight = Ascender;
|
||||
|
||||
if (FontFace.os2.version >= 2 && FontFace.os2.sxHeight != 0)
|
||||
XHeight = FontFace.os2.sxHeight;
|
||||
else
|
||||
XHeight = (int)(0.66 * Ascender);
|
||||
|
||||
//flags = image.
|
||||
|
||||
#if !EDF_CORE
|
||||
Encoding ansi = PdfEncoders.WinAnsiEncoding; // System.Text.Encoding.Default;
|
||||
#else
|
||||
Encoding ansi = null; //$$$ PdfEncoders.WinAnsiEncoding; // System.Text.Encoding.Default;
|
||||
#endif
|
||||
|
||||
Encoding unicode = Encoding.Unicode;
|
||||
byte[] bytes = new byte[256];
|
||||
|
||||
bool symbol = FontFace.cmap.symbol;
|
||||
Widths = new int[256];
|
||||
for (int idx = 0; idx < 256; idx++)
|
||||
{
|
||||
bytes[idx] = (byte)idx;
|
||||
// PDFlib handles some font flaws here...
|
||||
// We wait for bug reports.
|
||||
|
||||
char ch = (char)idx;
|
||||
string s = ansi.GetString(bytes, idx, 1);
|
||||
if (s.Length != 0)
|
||||
{
|
||||
if (s[0] != ch)
|
||||
ch = s[0];
|
||||
}
|
||||
|
||||
//Debug.Assert(ch == idx);
|
||||
|
||||
//int glyphIndex;
|
||||
//if (symbol)
|
||||
//{
|
||||
// glyphIndex = idx + (FontFace.os2. usFirstCharIndex & 0xFF00);
|
||||
// glyphIndex = CharCodeToGlyphIndex((char)glyphIndex);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// //Debug.Assert(idx + (fontData.os2.usFirstCharIndex & 0xFF00) == idx);
|
||||
// //glyphIndex = CharCodeToGlyphIndex((char)idx);
|
||||
// glyphIndex = CharCodeToGlyphIndex(ch);
|
||||
//}
|
||||
|
||||
if (symbol)
|
||||
{
|
||||
// Remap ch for symbol fonts.
|
||||
ch = (char)(ch | (FontFace.os2.usFirstCharIndex & 0xFF00)); // @@@ refactor
|
||||
}
|
||||
int glyphIndex = CharCodeToGlyphIndex(ch);
|
||||
Widths[idx] = GlyphIndexToPdfWidth(glyphIndex);
|
||||
}
|
||||
}
|
||||
public int[] Widths;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance belongs to a bold font.
|
||||
/// </summary>
|
||||
public override bool IsBoldFace
|
||||
{
|
||||
get
|
||||
{
|
||||
// usWeightClass 700 is Bold
|
||||
//Debug.Assert((fontData.os2.usWeightClass >= 700) == ((fontData.os2.fsSelection & (ushort)OS2Table.FontSelectionFlags.Bold) != 0));
|
||||
return FontFace.os2.IsBold;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance belongs to an italic font.
|
||||
/// </summary>
|
||||
public override bool IsItalicFace
|
||||
{
|
||||
get { return FontFace.os2.IsItalic; }
|
||||
}
|
||||
|
||||
internal int DesignUnitsToPdf(double value)
|
||||
{
|
||||
return (int)Math.Round(value * 1000.0 / FontFace.head.unitsPerEm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a unicode to the index of the corresponding glyph.
|
||||
/// See OpenType spec "cmap - Character To Glyph Index Mapping Table / Format 4: Segment mapping to delta values"
|
||||
/// for details about this a little bit strange looking algorithm.
|
||||
/// </summary>
|
||||
public int CharCodeToGlyphIndex(char value)
|
||||
{
|
||||
try
|
||||
{
|
||||
CMap4 cmap = FontFace.cmap.cmap4;
|
||||
int segCount = cmap.segCountX2 / 2;
|
||||
int seg;
|
||||
for (seg = 0; seg < segCount; seg++)
|
||||
{
|
||||
if (value <= cmap.endCount[seg])
|
||||
break;
|
||||
}
|
||||
Debug.Assert(seg < segCount);
|
||||
|
||||
if (value < cmap.startCount[seg])
|
||||
return 0;
|
||||
|
||||
if (cmap.idRangeOffs[seg] == 0)
|
||||
return (value + cmap.idDelta[seg]) & 0xFFFF;
|
||||
|
||||
int idx = cmap.idRangeOffs[seg] / 2 + (value - cmap.startCount[seg]) - (segCount - seg);
|
||||
Debug.Assert(idx >= 0 && idx < cmap.glyphCount);
|
||||
|
||||
if (cmap.glyphIdArray[idx] == 0)
|
||||
return 0;
|
||||
|
||||
return (cmap.glyphIdArray[idx] + cmap.idDelta[seg]) & 0xFFFF;
|
||||
}
|
||||
catch
|
||||
{
|
||||
GetType();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the width of a glyph identified by its index to PDF design units.
|
||||
/// </summary>
|
||||
public int GlyphIndexToPdfWidth(int glyphIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
int numberOfHMetrics = FontFace.hhea.numberOfHMetrics;
|
||||
int unitsPerEm = FontFace.head.unitsPerEm;
|
||||
|
||||
// glyphIndex >= numberOfHMetrics means the font is mono-spaced and all glyphs have the same width
|
||||
if (glyphIndex >= numberOfHMetrics)
|
||||
glyphIndex = numberOfHMetrics - 1;
|
||||
|
||||
int width = FontFace.hmtx.Metrics[glyphIndex].advanceWidth;
|
||||
|
||||
// Sometimes the unitsPerEm is 1000, sometimes a power of 2.
|
||||
if (unitsPerEm == 1000)
|
||||
return width;
|
||||
return width * 1000 / unitsPerEm; // normalize
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
GetType();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public int PdfWidthFromCharCode(char ch)
|
||||
{
|
||||
int idx = CharCodeToGlyphIndex(ch);
|
||||
int width = GlyphIndexToPdfWidth(idx);
|
||||
return width;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// //Converts the width of a glyph identified by its index to PDF design units.
|
||||
/// </summary>
|
||||
public double GlyphIndexToEmfWidth(int glyphIndex, double emSize)
|
||||
{
|
||||
try
|
||||
{
|
||||
int numberOfHMetrics = FontFace.hhea.numberOfHMetrics;
|
||||
int unitsPerEm = FontFace.head.unitsPerEm;
|
||||
|
||||
// glyphIndex >= numberOfHMetrics means the font is mono-spaced and all glyphs have the same width
|
||||
if (glyphIndex >= numberOfHMetrics)
|
||||
glyphIndex = numberOfHMetrics - 1;
|
||||
|
||||
int width = FontFace.hmtx.Metrics[glyphIndex].advanceWidth;
|
||||
|
||||
return width * emSize / unitsPerEm; // normalize
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
GetType();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// //Converts the width of a glyph identified by its index to PDF design units.
|
||||
/// </summary>
|
||||
public int GlyphIndexToWidth(int glyphIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
int numberOfHMetrics = FontFace.hhea.numberOfHMetrics;
|
||||
|
||||
// glyphIndex >= numberOfHMetrics means the font is mono-spaced and all glyphs have the same width
|
||||
if (glyphIndex >= numberOfHMetrics)
|
||||
glyphIndex = numberOfHMetrics - 1;
|
||||
|
||||
int width = FontFace.hmtx.Metrics[glyphIndex].advanceWidth;
|
||||
return width;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
GetType();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
118
PdfSharp/Fonts.OpenType/OpenTypeFontTable.cs
Normal file
118
PdfSharp/Fonts.OpenType/OpenTypeFontTable.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
//using Fixed = System.Int32;
|
||||
//using FWord = System.Int16;
|
||||
//using UFWord = System.UInt16;
|
||||
#if SILVERLIGHT
|
||||
using PdfSharp;
|
||||
#endif
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
// TODO: Create a font driver for reading and writing OpenType font files.
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all OpenType tables used in PDFsharp.
|
||||
/// </summary>
|
||||
internal class OpenTypeFontTable : ICloneable
|
||||
{
|
||||
public OpenTypeFontTable(OpenTypeFontface fontData, string tag)
|
||||
{
|
||||
_fontData = fontData;
|
||||
if (fontData != null && fontData.TableDictionary.ContainsKey(tag))
|
||||
DirectoryEntry = fontData.TableDictionary[tag];
|
||||
else
|
||||
DirectoryEntry = new TableDirectoryEntry(tag);
|
||||
DirectoryEntry.FontTable = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep copy of the current instance.
|
||||
/// </summary>
|
||||
public object Clone()
|
||||
{
|
||||
return DeepCopy();
|
||||
}
|
||||
|
||||
protected virtual OpenTypeFontTable DeepCopy()
|
||||
{
|
||||
OpenTypeFontTable fontTable = (OpenTypeFontTable)MemberwiseClone();
|
||||
fontTable.DirectoryEntry.Offset = 0;
|
||||
fontTable.DirectoryEntry.FontTable = fontTable;
|
||||
return fontTable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the font image the table belongs to.
|
||||
/// </summary>
|
||||
public OpenTypeFontface FontData
|
||||
{
|
||||
get { return _fontData; }
|
||||
}
|
||||
internal OpenTypeFontface _fontData;
|
||||
|
||||
public TableDirectoryEntry DirectoryEntry;
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, prepares the font table to be compiled into its binary representation.
|
||||
/// </summary>
|
||||
public virtual void PrepareForCompilation()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, converts the font into its binary representation.
|
||||
/// </summary>
|
||||
public virtual void Write(OpenTypeFontWriter writer)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the checksum of a table represented by its bytes.
|
||||
/// </summary>
|
||||
public static uint CalcChecksum(byte[] bytes)
|
||||
{
|
||||
Debug.Assert((bytes.Length & 3) == 0);
|
||||
// Cannot use Buffer.BlockCopy because 32-bit values are Big-endian in fonts.
|
||||
uint byte3, byte2, byte1, byte0;
|
||||
byte3 = byte2 = byte1 = byte0 = 0;
|
||||
int length = bytes.Length;
|
||||
for (int idx = 0; idx < length;)
|
||||
{
|
||||
byte3 += bytes[idx++];
|
||||
byte2 += bytes[idx++];
|
||||
byte1 += bytes[idx++];
|
||||
byte0 += bytes[idx++];
|
||||
}
|
||||
return (byte3 << 24) + (byte2 << 16) + (byte1 << 8) + byte0;
|
||||
}
|
||||
}
|
||||
}
|
1051
PdfSharp/Fonts.OpenType/OpenTypeFontTables.cs
Normal file
1051
PdfSharp/Fonts.OpenType/OpenTypeFontTables.cs
Normal file
File diff suppressed because it is too large
Load Diff
59
PdfSharp/Fonts.OpenType/OpenTypeFontWriter.cs
Normal file
59
PdfSharp/Fonts.OpenType/OpenTypeFontWriter.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a writer for True Type font files.
|
||||
/// </summary>
|
||||
internal class OpenTypeFontWriter : FontWriter
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OpenTypeFontWriter"/> class.
|
||||
/// </summary>
|
||||
public OpenTypeFontWriter(Stream stream)
|
||||
: base(stream)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Writes a table name.
|
||||
/// </summary>
|
||||
public void WriteTag(string tag)
|
||||
{
|
||||
Debug.Assert(tag.Length == 4);
|
||||
WriteByte((byte)(tag[0]));
|
||||
WriteByte((byte)(tag[1]));
|
||||
WriteByte((byte)(tag[2]));
|
||||
WriteByte((byte)(tag[3]));
|
||||
}
|
||||
}
|
||||
}
|
746
PdfSharp/Fonts.OpenType/OpenTypeFontface.cs
Normal file
746
PdfSharp/Fonts.OpenType/OpenTypeFontface.cs
Normal file
@@ -0,0 +1,746 @@
|
||||
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#define VERBOSE_
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
#if GDI
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using GdiFontFamily = System.Drawing.FontFamily;
|
||||
using GdiFont = System.Drawing.Font;
|
||||
using GdiFontStyle = System.Drawing.FontStyle;
|
||||
#endif
|
||||
#if WPF
|
||||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using WpfFontFamily = System.Windows.Media.FontFamily;
|
||||
using WpfTypeface = System.Windows.Media.Typeface;
|
||||
using WpfGlyphTypeface = System.Windows.Media.GlyphTypeface;
|
||||
#endif
|
||||
using PdfSharp.Fonts;
|
||||
#if !EDF_CORE
|
||||
using PdfSharp.Drawing;
|
||||
using PdfSharp.Internal;
|
||||
#endif
|
||||
|
||||
using Fixed = System.Int32;
|
||||
using FWord = System.Int16;
|
||||
using UFWord = System.UInt16;
|
||||
|
||||
#pragma warning disable 0649
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an OpenType fontface in memory.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{DebuggerDisplay}")]
|
||||
internal sealed class OpenTypeFontface
|
||||
{
|
||||
// Implementation Notes
|
||||
// OpenTypeFontface represents a 'decompiled' font file in memory.
|
||||
//
|
||||
// * An OpenTypeFontface can belong to more than one
|
||||
// XGlyphTypeface because of StyleSimulations.
|
||||
//
|
||||
// * Currently there is a one to one relationship to XFontSource.
|
||||
//
|
||||
// * Consider OpenTypeFontface as an decompiled XFontSource.
|
||||
//
|
||||
// http://www.microsoft.com/typography/otspec/
|
||||
|
||||
/// <summary>
|
||||
/// Shallow copy for font subset.
|
||||
/// </summary>
|
||||
OpenTypeFontface(OpenTypeFontface fontface)
|
||||
{
|
||||
_offsetTable = fontface._offsetTable;
|
||||
_fullFaceName = fontface._fullFaceName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OpenTypeFontface"/> class.
|
||||
/// </summary>
|
||||
public OpenTypeFontface(byte[] data, string faceName)
|
||||
{
|
||||
_fullFaceName = faceName;
|
||||
// Always save a copy of the font bytes.
|
||||
int length = data.Length;
|
||||
//FontSource = new XFontSource(faceName, new byte[length]);
|
||||
Array.Copy(data, FontSource.Bytes, length);
|
||||
Read();
|
||||
}
|
||||
|
||||
public OpenTypeFontface(XFontSource fontSource)
|
||||
{
|
||||
FontSource = fontSource;
|
||||
Read();
|
||||
_fullFaceName = name.FullFontName;
|
||||
}
|
||||
|
||||
public static OpenTypeFontface CetOrCreateFrom(XFontSource fontSource)
|
||||
{
|
||||
OpenTypeFontface fontface;
|
||||
if (OpenTypeFontfaceCache.TryGetFontface(fontSource.Key, out fontface))
|
||||
{
|
||||
return fontface;
|
||||
}
|
||||
// Each font source already contains its OpenTypeFontface.
|
||||
Debug.Assert(fontSource.Fontface != null);
|
||||
fontface = OpenTypeFontfaceCache.AddFontface(fontSource.Fontface);
|
||||
Debug.Assert(ReferenceEquals(fontSource.Fontface, fontface));
|
||||
return fontface;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full face name from the name table.
|
||||
/// Name is also used as the key.
|
||||
/// </summary>
|
||||
public string FullFaceName
|
||||
{
|
||||
get { return _fullFaceName; }
|
||||
}
|
||||
readonly string _fullFaceName;
|
||||
|
||||
public ulong CheckSum
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_checkSum == 0)
|
||||
_checkSum = FontHelper.CalcChecksum(FontSource.Bytes);
|
||||
return _checkSum;
|
||||
}
|
||||
}
|
||||
ulong _checkSum;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bytes that represents the font data.
|
||||
/// </summary>
|
||||
public XFontSource FontSource
|
||||
{
|
||||
get { return _fontSource; }
|
||||
private set
|
||||
{
|
||||
// Stop working if font was not found.
|
||||
if (value == null)
|
||||
throw new InvalidOperationException("Font cannot be resolved.");
|
||||
_fontSource = value;
|
||||
}
|
||||
}
|
||||
XFontSource _fontSource;
|
||||
|
||||
internal FontTechnology _fontTechnology;
|
||||
|
||||
internal OffsetTable _offsetTable;
|
||||
|
||||
/// <summary>
|
||||
/// The dictionary of all font tables.
|
||||
/// </summary>
|
||||
internal Dictionary<string, TableDirectoryEntry> TableDictionary = new Dictionary<string, TableDirectoryEntry>();
|
||||
|
||||
// Keep names identical to OpenType spec.
|
||||
// ReSharper disable InconsistentNaming
|
||||
internal CMapTable cmap;
|
||||
internal ControlValueTable cvt;
|
||||
internal FontProgram fpgm;
|
||||
internal MaximumProfileTable maxp;
|
||||
internal NameTable name;
|
||||
internal ControlValueProgram prep;
|
||||
internal FontHeaderTable head;
|
||||
internal HorizontalHeaderTable hhea;
|
||||
internal HorizontalMetricsTable hmtx;
|
||||
internal OS2Table os2;
|
||||
internal PostScriptTable post;
|
||||
internal GlyphDataTable glyf;
|
||||
internal IndexToLocationTable loca;
|
||||
internal GlyphSubstitutionTable gsub;
|
||||
internal VerticalHeaderTable vhea; // TODO
|
||||
internal VerticalMetricsTable vmtx; // TODO
|
||||
// ReSharper restore InconsistentNaming
|
||||
|
||||
public bool CanRead
|
||||
{
|
||||
get { return FontSource != null; }
|
||||
}
|
||||
|
||||
public bool CanWrite
|
||||
{
|
||||
get { return FontSource == null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified table to this font image.
|
||||
/// </summary>
|
||||
public void AddTable(OpenTypeFontTable fontTable)
|
||||
{
|
||||
if (!CanWrite)
|
||||
throw new InvalidOperationException("Font image cannot be modified.");
|
||||
|
||||
if (fontTable == null)
|
||||
throw new ArgumentNullException("fontTable");
|
||||
|
||||
if (fontTable._fontData == null)
|
||||
{
|
||||
fontTable._fontData = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(fontTable._fontData.CanRead);
|
||||
// Create a reference to this font table
|
||||
fontTable = new IRefFontTable(this, fontTable);
|
||||
}
|
||||
|
||||
//Debug.Assert(fontTable.FontData == null);
|
||||
//fontTable.fontData = this;
|
||||
|
||||
TableDictionary[fontTable.DirectoryEntry.Tag] = fontTable.DirectoryEntry;
|
||||
switch (fontTable.DirectoryEntry.Tag)
|
||||
{
|
||||
case TableTagNames.CMap:
|
||||
cmap = fontTable as CMapTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.Cvt:
|
||||
cvt = fontTable as ControlValueTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.Fpgm:
|
||||
fpgm = fontTable as FontProgram;
|
||||
break;
|
||||
|
||||
case TableTagNames.MaxP:
|
||||
maxp = fontTable as MaximumProfileTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.Name:
|
||||
name = fontTable as NameTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.Head:
|
||||
head = fontTable as FontHeaderTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.HHea:
|
||||
hhea = fontTable as HorizontalHeaderTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.HMtx:
|
||||
hmtx = fontTable as HorizontalMetricsTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.OS2:
|
||||
os2 = fontTable as OS2Table;
|
||||
break;
|
||||
|
||||
case TableTagNames.Post:
|
||||
post = fontTable as PostScriptTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.Glyf:
|
||||
glyf = fontTable as GlyphDataTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.Loca:
|
||||
loca = fontTable as IndexToLocationTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.GSUB:
|
||||
gsub = fontTable as GlyphSubstitutionTable;
|
||||
break;
|
||||
|
||||
case TableTagNames.Prep:
|
||||
prep = fontTable as ControlValueProgram;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads all required tables from the font data.
|
||||
/// </summary>
|
||||
internal void Read()
|
||||
{
|
||||
// Determine font technology
|
||||
// ReSharper disable InconsistentNaming
|
||||
const uint OTTO = 0x4f54544f; // Adobe OpenType CFF data, tag: 'OTTO'
|
||||
const uint TTCF = 0x74746366; // TrueType Collection tag: 'ttcf'
|
||||
// ReSharper restore InconsistentNaming
|
||||
try
|
||||
{
|
||||
#if DEBUG_
|
||||
if (Name == "Cambria")
|
||||
Debug-Break.Break();
|
||||
#endif
|
||||
|
||||
// Check if data is a TrueType collection font.
|
||||
uint startTag = ReadULong();
|
||||
if (startTag == TTCF)
|
||||
{
|
||||
_fontTechnology = FontTechnology.TrueTypeCollection;
|
||||
throw new InvalidOperationException("TrueType collection fonts are not yet supported by PDFsharp.");
|
||||
}
|
||||
|
||||
// Read offset table
|
||||
_offsetTable.Version = startTag;
|
||||
_offsetTable.TableCount = ReadUShort();
|
||||
_offsetTable.SearchRange = ReadUShort();
|
||||
_offsetTable.EntrySelector = ReadUShort();
|
||||
_offsetTable.RangeShift = ReadUShort();
|
||||
|
||||
// Move to table dictionary at position 12
|
||||
Debug.Assert(_pos == 12);
|
||||
//tableDictionary = (offsetTable.TableCount);
|
||||
|
||||
if (_offsetTable.Version == OTTO)
|
||||
_fontTechnology = FontTechnology.PostscriptOutlines;
|
||||
else
|
||||
_fontTechnology = FontTechnology.TrueTypeOutlines;
|
||||
|
||||
for (int idx = 0; idx < _offsetTable.TableCount; idx++)
|
||||
{
|
||||
TableDirectoryEntry entry = TableDirectoryEntry.ReadFrom(this);
|
||||
TableDictionary.Add(entry.Tag, entry);
|
||||
#if VERBOSE
|
||||
Debug.WriteLine(String.Format("Font table: {0}", entry.Tag));
|
||||
#endif
|
||||
}
|
||||
|
||||
// PDFlib checks this, but it is not part of the OpenType spec anymore
|
||||
if (TableDictionary.ContainsKey("bhed"))
|
||||
throw new NotSupportedException("Bitmap fonts are not supported by PDFsharp.");
|
||||
|
||||
// Read required tables
|
||||
if (Seek(CMapTable.Tag) != -1)
|
||||
cmap = new CMapTable(this);
|
||||
|
||||
if (Seek(ControlValueTable.Tag) != -1)
|
||||
cvt = new ControlValueTable(this);
|
||||
|
||||
if (Seek(FontProgram.Tag) != -1)
|
||||
fpgm = new FontProgram(this);
|
||||
|
||||
if (Seek(MaximumProfileTable.Tag) != -1)
|
||||
maxp = new MaximumProfileTable(this);
|
||||
|
||||
if (Seek(NameTable.Tag) != -1)
|
||||
name = new NameTable(this);
|
||||
|
||||
if (Seek(FontHeaderTable.Tag) != -1)
|
||||
head = new FontHeaderTable(this);
|
||||
|
||||
if (Seek(HorizontalHeaderTable.Tag) != -1)
|
||||
hhea = new HorizontalHeaderTable(this);
|
||||
|
||||
if (Seek(HorizontalMetricsTable.Tag) != -1)
|
||||
hmtx = new HorizontalMetricsTable(this);
|
||||
|
||||
if (Seek(OS2Table.Tag) != -1)
|
||||
os2 = new OS2Table(this);
|
||||
|
||||
if (Seek(PostScriptTable.Tag) != -1)
|
||||
post = new PostScriptTable(this);
|
||||
|
||||
if (Seek(GlyphDataTable.Tag) != -1)
|
||||
glyf = new GlyphDataTable(this);
|
||||
|
||||
if (Seek(IndexToLocationTable.Tag) != -1)
|
||||
loca = new IndexToLocationTable(this);
|
||||
|
||||
if (Seek(GlyphSubstitutionTable.Tag) != -1)
|
||||
gsub = new GlyphSubstitutionTable(this);
|
||||
|
||||
if (Seek(ControlValueProgram.Tag) != -1)
|
||||
prep = new ControlValueProgram(this);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
GetType();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new font image that is a subset of this font image containing only the specified glyphs.
|
||||
/// </summary>
|
||||
public OpenTypeFontface CreateFontSubSet(Dictionary<int, object> glyphs, bool cidFont)
|
||||
{
|
||||
// Create new font image
|
||||
OpenTypeFontface fontData = new OpenTypeFontface(this);
|
||||
|
||||
// Create new loca and glyf table
|
||||
IndexToLocationTable locaNew = new IndexToLocationTable();
|
||||
locaNew.ShortIndex = loca.ShortIndex;
|
||||
GlyphDataTable glyfNew = new GlyphDataTable();
|
||||
|
||||
// Add all required tables
|
||||
//fontData.AddTable(os2);
|
||||
if (!cidFont)
|
||||
fontData.AddTable(cmap);
|
||||
if (cvt != null)
|
||||
fontData.AddTable(cvt);
|
||||
if (fpgm != null)
|
||||
fontData.AddTable(fpgm);
|
||||
fontData.AddTable(glyfNew);
|
||||
fontData.AddTable(head);
|
||||
fontData.AddTable(hhea);
|
||||
fontData.AddTable(hmtx);
|
||||
fontData.AddTable(locaNew);
|
||||
if (maxp != null)
|
||||
fontData.AddTable(maxp);
|
||||
//fontData.AddTable(name);
|
||||
if (prep != null)
|
||||
fontData.AddTable(prep);
|
||||
|
||||
// Get closure of used glyphs.
|
||||
glyf.CompleteGlyphClosure(glyphs);
|
||||
|
||||
// Create a sorted array of all used glyphs.
|
||||
int glyphCount = glyphs.Count;
|
||||
int[] glyphArray = new int[glyphCount];
|
||||
glyphs.Keys.CopyTo(glyphArray, 0);
|
||||
Array.Sort(glyphArray);
|
||||
|
||||
// Calculate new size of glyph table.
|
||||
int size = 0;
|
||||
for (int idx = 0; idx < glyphCount; idx++)
|
||||
size += glyf.GetGlyphSize(glyphArray[idx]);
|
||||
glyfNew.DirectoryEntry.Length = size;
|
||||
|
||||
// Create new loca table
|
||||
int numGlyphs = maxp.numGlyphs;
|
||||
locaNew.LocaTable = new int[numGlyphs + 1];
|
||||
|
||||
// Create new glyf table
|
||||
glyfNew.GlyphTable = new byte[glyfNew.DirectoryEntry.PaddedLength];
|
||||
|
||||
// Fill new glyf and loca table
|
||||
int glyphOffset = 0;
|
||||
int glyphIndex = 0;
|
||||
for (int idx = 0; idx < numGlyphs; idx++)
|
||||
{
|
||||
locaNew.LocaTable[idx] = glyphOffset;
|
||||
if (glyphIndex < glyphCount && glyphArray[glyphIndex] == idx)
|
||||
{
|
||||
glyphIndex++;
|
||||
byte[] bytes = glyf.GetGlyphData(idx);
|
||||
int length = bytes.Length;
|
||||
if (length > 0)
|
||||
{
|
||||
Buffer.BlockCopy(bytes, 0, glyfNew.GlyphTable, glyphOffset, length);
|
||||
glyphOffset += length;
|
||||
}
|
||||
}
|
||||
}
|
||||
locaNew.LocaTable[numGlyphs] = glyphOffset;
|
||||
|
||||
// Compile font tables into byte array
|
||||
fontData.Compile();
|
||||
|
||||
return fontData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compiles the font to its binary representation.
|
||||
/// </summary>
|
||||
void Compile()
|
||||
{
|
||||
MemoryStream stream = new MemoryStream();
|
||||
OpenTypeFontWriter writer = new OpenTypeFontWriter(stream);
|
||||
|
||||
int tableCount = TableDictionary.Count;
|
||||
int selector = _entrySelectors[tableCount];
|
||||
|
||||
_offsetTable.Version = 0x00010000;
|
||||
_offsetTable.TableCount = tableCount;
|
||||
_offsetTable.SearchRange = (ushort)((1 << selector) * 16);
|
||||
_offsetTable.EntrySelector = (ushort)selector;
|
||||
_offsetTable.RangeShift = (ushort)((tableCount - (1 << selector)) * 16);
|
||||
_offsetTable.Write(writer);
|
||||
|
||||
// Sort tables by tag name
|
||||
string[] tags = new string[tableCount];
|
||||
TableDictionary.Keys.CopyTo(tags, 0);
|
||||
Array.Sort(tags, StringComparer.Ordinal);
|
||||
|
||||
#if VERBOSE
|
||||
Debug.WriteLine("Start Compile");
|
||||
#endif
|
||||
// Write tables in alphabetical order
|
||||
int tablePosition = 12 + 16 * tableCount;
|
||||
for (int idx = 0; idx < tableCount; idx++)
|
||||
{
|
||||
TableDirectoryEntry entry = TableDictionary[tags[idx]];
|
||||
#if DEBUG
|
||||
if (entry.Tag == "glyf" || entry.Tag == "loca")
|
||||
GetType();
|
||||
#endif
|
||||
entry.FontTable.PrepareForCompilation();
|
||||
entry.Offset = tablePosition;
|
||||
writer.Position = tablePosition;
|
||||
entry.FontTable.Write(writer);
|
||||
int endPosition = writer.Position;
|
||||
tablePosition = endPosition;
|
||||
writer.Position = 12 + 16 * idx;
|
||||
entry.Write(writer);
|
||||
#if VERBOSE
|
||||
Debug.WriteLine(String.Format(" Write Table '{0}', offset={1}, length={2}, checksum={3}, ", entry.Tag, entry.Offset, entry.Length, entry.CheckSum));
|
||||
#endif
|
||||
}
|
||||
#if VERBOSE
|
||||
Debug.WriteLine("End Compile");
|
||||
#endif
|
||||
writer.Stream.Flush();
|
||||
int l = (int)writer.Stream.Length;
|
||||
FontSource = XFontSource.CreateCompiledFont(stream.ToArray());
|
||||
}
|
||||
// 2^entrySelector[n] <= n
|
||||
static readonly int[] _entrySelectors = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
|
||||
|
||||
public int Position
|
||||
{
|
||||
get { return _pos; }
|
||||
set { _pos = value; }
|
||||
}
|
||||
int _pos;
|
||||
|
||||
public int Seek(string tag)
|
||||
{
|
||||
if (TableDictionary.ContainsKey(tag))
|
||||
{
|
||||
_pos = TableDictionary[tag].Offset;
|
||||
return _pos;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int SeekOffset(int offset)
|
||||
{
|
||||
_pos += offset;
|
||||
return _pos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.Byte.
|
||||
/// </summary>
|
||||
public byte ReadByte()
|
||||
{
|
||||
return _fontSource.Bytes[_pos++];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.Int16.
|
||||
/// </summary>
|
||||
public short ReadShort()
|
||||
{
|
||||
int pos = _pos;
|
||||
_pos += 2;
|
||||
return (short)((_fontSource.Bytes[pos] << 8) | (_fontSource.Bytes[pos + 1]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.UInt16.
|
||||
/// </summary>
|
||||
public ushort ReadUShort()
|
||||
{
|
||||
int pos = _pos;
|
||||
_pos += 2;
|
||||
return (ushort)((_fontSource.Bytes[pos] << 8) | (_fontSource.Bytes[pos + 1]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.Int32.
|
||||
/// </summary>
|
||||
public int ReadLong()
|
||||
{
|
||||
int pos = _pos;
|
||||
_pos += 4;
|
||||
return (_fontSource.Bytes[pos] << 24) | (_fontSource.Bytes[pos + 1] << 16) | (_fontSource.Bytes[pos + 2] << 8) | (_fontSource.Bytes[pos + 3]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.UInt32.
|
||||
/// </summary>
|
||||
public uint ReadULong()
|
||||
{
|
||||
int pos = _pos;
|
||||
_pos += 4;
|
||||
return (uint)((_fontSource.Bytes[pos] << 24) | (_fontSource.Bytes[pos + 1] << 16) | (_fontSource.Bytes[pos + 2] << 8) | (_fontSource.Bytes[pos + 3]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.Int32.
|
||||
/// </summary>
|
||||
public Fixed ReadFixed()
|
||||
{
|
||||
int pos = _pos;
|
||||
_pos += 4;
|
||||
return (_fontSource.Bytes[pos] << 24) | (_fontSource.Bytes[pos + 1] << 16) | (_fontSource.Bytes[pos + 2] << 8) | (_fontSource.Bytes[pos + 3]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.Int16.
|
||||
/// </summary>
|
||||
public short ReadFWord()
|
||||
{
|
||||
int pos = _pos;
|
||||
_pos += 2;
|
||||
return (short)((_fontSource.Bytes[pos] << 8) | (_fontSource.Bytes[pos + 1]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.UInt16.
|
||||
/// </summary>
|
||||
public ushort ReadUFWord()
|
||||
{
|
||||
int pos = _pos;
|
||||
_pos += 2;
|
||||
return (ushort)((_fontSource.Bytes[pos] << 8) | (_fontSource.Bytes[pos + 1]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.Int64.
|
||||
/// </summary>
|
||||
public long ReadLongDate()
|
||||
{
|
||||
int pos = _pos;
|
||||
_pos += 8;
|
||||
byte[] bytes = _fontSource.Bytes;
|
||||
return (((long)bytes[pos]) << 56) | (((long)bytes[pos + 1]) << 48) | (((long)bytes[pos + 2]) << 40) | (((long)bytes[pos + 3]) << 32) |
|
||||
(((long)bytes[pos + 4]) << 24) | (((long)bytes[pos + 5]) << 16) | (((long)bytes[pos + 6]) << 8) | bytes[pos + 7];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.String with the specified size.
|
||||
/// </summary>
|
||||
public string ReadString(int size)
|
||||
{
|
||||
char[] chars = new char[size];
|
||||
for (int idx = 0; idx < size; idx++)
|
||||
chars[idx] = (char)_fontSource.Bytes[_pos++];
|
||||
return new string(chars);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.Byte[] with the specified size.
|
||||
/// </summary>
|
||||
public byte[] ReadBytes(int size)
|
||||
{
|
||||
byte[] bytes = new byte[size];
|
||||
for (int idx = 0; idx < size; idx++)
|
||||
bytes[idx] = _fontSource.Bytes[_pos++];
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the specified buffer.
|
||||
/// </summary>
|
||||
public void Read(byte[] buffer)
|
||||
{
|
||||
Read(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the specified buffer.
|
||||
/// </summary>
|
||||
public void Read(byte[] buffer, int offset, int length)
|
||||
{
|
||||
Buffer.BlockCopy(_fontSource.Bytes, _pos, buffer, offset, length);
|
||||
_pos += length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a System.Char[4] as System.String.
|
||||
/// </summary>
|
||||
public string ReadTag()
|
||||
{
|
||||
return ReadString(4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DebuggerDisplayAttribute text.
|
||||
/// </summary>
|
||||
// ReSharper disable UnusedMember.Local
|
||||
internal string DebuggerDisplay
|
||||
// ReSharper restore UnusedMember.Local
|
||||
{
|
||||
get { return string.Format(CultureInfo.InvariantCulture, "OpenType fontfaces: {0}", _fullFaceName); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the font offset table.
|
||||
/// </summary>
|
||||
internal struct OffsetTable
|
||||
{
|
||||
/// <summary>
|
||||
/// 0x00010000 for Version 1.0.
|
||||
/// </summary>
|
||||
public uint Version;
|
||||
|
||||
/// <summary>
|
||||
/// Number of tables.
|
||||
/// </summary>
|
||||
public int TableCount;
|
||||
|
||||
/// <summary>
|
||||
/// (Maximum power of 2 ≤ numTables) x 16.
|
||||
/// </summary>
|
||||
public ushort SearchRange;
|
||||
|
||||
/// <summary>
|
||||
/// Log2(maximum power of 2 ≤ numTables).
|
||||
/// </summary>
|
||||
public ushort EntrySelector;
|
||||
|
||||
/// <summary>
|
||||
/// NumTables x 16-searchRange.
|
||||
/// </summary>
|
||||
public ushort RangeShift;
|
||||
|
||||
/// <summary>
|
||||
/// Writes the offset table.
|
||||
/// </summary>
|
||||
public void Write(OpenTypeFontWriter writer)
|
||||
{
|
||||
writer.WriteUInt(Version);
|
||||
writer.WriteShort(TableCount);
|
||||
writer.WriteUShort(SearchRange);
|
||||
writer.WriteUShort(EntrySelector);
|
||||
writer.WriteUShort(RangeShift);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
157
PdfSharp/Fonts.OpenType/OpenTypeFontfaceCache.cs
Normal file
157
PdfSharp/Fonts.OpenType/OpenTypeFontfaceCache.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using PdfSharp.Internal;
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// Global table of all OpenType fontfaces cached by their face name and check sum.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{DebuggerDisplay}")]
|
||||
internal class OpenTypeFontfaceCache
|
||||
{
|
||||
OpenTypeFontfaceCache()
|
||||
{
|
||||
_fontfaceCache = new Dictionary<string, OpenTypeFontface>(StringComparer.OrdinalIgnoreCase);
|
||||
_fontfacesByCheckSum = new Dictionary<ulong, OpenTypeFontface>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get fontface by its key.
|
||||
/// </summary>
|
||||
public static bool TryGetFontface(string key, out OpenTypeFontface fontface)
|
||||
{
|
||||
try
|
||||
{
|
||||
Lock.EnterFontFactory();
|
||||
bool result = Singleton._fontfaceCache.TryGetValue(key, out fontface);
|
||||
return result;
|
||||
}
|
||||
finally { Lock.ExitFontFactory(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get fontface by its check sum.
|
||||
/// </summary>
|
||||
public static bool TryGetFontface(ulong checkSum, out OpenTypeFontface fontface)
|
||||
{
|
||||
try
|
||||
{
|
||||
Lock.EnterFontFactory();
|
||||
bool result = Singleton._fontfacesByCheckSum.TryGetValue(checkSum, out fontface);
|
||||
return result;
|
||||
}
|
||||
finally { Lock.ExitFontFactory(); }
|
||||
}
|
||||
|
||||
public static OpenTypeFontface AddFontface(OpenTypeFontface fontface)
|
||||
{
|
||||
try
|
||||
{
|
||||
Lock.EnterFontFactory();
|
||||
OpenTypeFontface fontfaceCheck;
|
||||
if (TryGetFontface(fontface.FullFaceName, out fontfaceCheck))
|
||||
{
|
||||
if (fontfaceCheck.CheckSum != fontface.CheckSum)
|
||||
throw new InvalidOperationException("OpenTypeFontface with same signature but different bytes.");
|
||||
return fontfaceCheck;
|
||||
}
|
||||
Singleton._fontfaceCache.Add(fontface.FullFaceName, fontface);
|
||||
Singleton._fontfacesByCheckSum.Add(fontface.CheckSum, fontface);
|
||||
return fontface;
|
||||
}
|
||||
finally { Lock.ExitFontFactory(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the singleton.
|
||||
/// </summary>
|
||||
static OpenTypeFontfaceCache Singleton
|
||||
{
|
||||
get
|
||||
{
|
||||
// ReSharper disable once InvertIf
|
||||
if (_singleton == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Lock.EnterFontFactory();
|
||||
if (_singleton == null)
|
||||
_singleton = new OpenTypeFontfaceCache();
|
||||
}
|
||||
finally { Lock.ExitFontFactory(); }
|
||||
}
|
||||
return _singleton;
|
||||
}
|
||||
}
|
||||
static volatile OpenTypeFontfaceCache _singleton;
|
||||
|
||||
internal static string GetCacheState()
|
||||
{
|
||||
StringBuilder state = new StringBuilder();
|
||||
state.Append("====================\n");
|
||||
state.Append("OpenType fontfaces by name\n");
|
||||
Dictionary<string, OpenTypeFontface>.KeyCollection familyKeys = Singleton._fontfaceCache.Keys;
|
||||
int count = familyKeys.Count;
|
||||
string[] keys = new string[count];
|
||||
familyKeys.CopyTo(keys, 0);
|
||||
Array.Sort(keys, StringComparer.OrdinalIgnoreCase);
|
||||
foreach (string key in keys)
|
||||
state.AppendFormat(" {0}: {1}\n", key, Singleton._fontfaceCache[key].DebuggerDisplay);
|
||||
state.Append("\n");
|
||||
return state.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps face name to OpenType fontface.
|
||||
/// </summary>
|
||||
readonly Dictionary<string, OpenTypeFontface> _fontfaceCache;
|
||||
|
||||
/// <summary>
|
||||
/// Maps font source key to OpenType fontface.
|
||||
/// </summary>
|
||||
readonly Dictionary<ulong, OpenTypeFontface> _fontfacesByCheckSum;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DebuggerDisplayAttribute text.
|
||||
/// </summary>
|
||||
// ReSharper disable UnusedMember.Local
|
||||
string DebuggerDisplay
|
||||
// ReSharper restore UnusedMember.Local
|
||||
{
|
||||
get { return string.Format(CultureInfo.InvariantCulture, "Fontfaces: {0}", _fontfaceCache.Count); }
|
||||
}
|
||||
}
|
||||
}
|
130
PdfSharp/Fonts.OpenType/TableDirectoryEntry.cs
Normal file
130
PdfSharp/Fonts.OpenType/TableDirectoryEntry.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#define VERBOSE_
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
//using Fixed = System.Int32;
|
||||
//using FWord = System.Int16;
|
||||
//using UFWord = System.UInt16;
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an entry in the fonts table dictionary.
|
||||
/// </summary>
|
||||
internal class TableDirectoryEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableDirectoryEntry"/> class.
|
||||
/// </summary>
|
||||
public TableDirectoryEntry()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableDirectoryEntry"/> class.
|
||||
/// </summary>
|
||||
public TableDirectoryEntry(string tag)
|
||||
{
|
||||
Debug.Assert(tag.Length == 4);
|
||||
Tag = tag;
|
||||
//CheckSum = 0;
|
||||
//Offset = 0;
|
||||
//Length = 0;
|
||||
//FontTable = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 4 -byte identifier.
|
||||
/// </summary>
|
||||
public string Tag;
|
||||
|
||||
/// <summary>
|
||||
/// CheckSum for this table.
|
||||
/// </summary>
|
||||
public uint CheckSum;
|
||||
|
||||
/// <summary>
|
||||
/// Offset from beginning of TrueType font file.
|
||||
/// </summary>
|
||||
public int Offset;
|
||||
|
||||
/// <summary>
|
||||
/// Actual length of this table in bytes.
|
||||
/// </summary>
|
||||
public int Length;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length rounded up to a multiple of four bytes.
|
||||
/// </summary>
|
||||
public int PaddedLength
|
||||
{
|
||||
get { return (Length + 3) & ~3; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Associated font table.
|
||||
/// </summary>
|
||||
public OpenTypeFontTable FontTable;
|
||||
|
||||
/// <summary>
|
||||
/// Creates and reads a TableDirectoryEntry from the font image.
|
||||
/// </summary>
|
||||
public static TableDirectoryEntry ReadFrom(OpenTypeFontface fontData)
|
||||
{
|
||||
TableDirectoryEntry entry = new TableDirectoryEntry();
|
||||
entry.Tag = fontData.ReadTag();
|
||||
entry.CheckSum = fontData.ReadULong();
|
||||
entry.Offset = fontData.ReadLong();
|
||||
entry.Length = (int)fontData.ReadULong();
|
||||
return entry;
|
||||
}
|
||||
|
||||
public void Read(OpenTypeFontface fontData)
|
||||
{
|
||||
Tag = fontData.ReadTag();
|
||||
CheckSum = fontData.ReadULong();
|
||||
Offset = fontData.ReadLong();
|
||||
Length = (int)fontData.ReadULong();
|
||||
}
|
||||
|
||||
public void Write(OpenTypeFontWriter writer)
|
||||
{
|
||||
Debug.Assert(Tag.Length == 4);
|
||||
Debug.Assert(Offset != 0);
|
||||
Debug.Assert(Length != 0);
|
||||
writer.WriteTag(Tag);
|
||||
writer.WriteUInt(CheckSum);
|
||||
writer.WriteInt(Offset);
|
||||
writer.WriteUInt((uint)Length);
|
||||
}
|
||||
}
|
||||
}
|
52
PdfSharp/Fonts.OpenType/enums/FontTechnology.cs
Normal file
52
PdfSharp/Fonts.OpenType/enums/FontTechnology.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifies the technology of an OpenType font file.
|
||||
/// </summary>
|
||||
enum FontTechnology
|
||||
{
|
||||
/// <summary>
|
||||
/// Font is Adobe Postscript font in CFF.
|
||||
/// </summary>
|
||||
PostscriptOutlines,
|
||||
|
||||
/// <summary>
|
||||
/// Font is a TrueType font.
|
||||
/// </summary>
|
||||
TrueTypeOutlines,
|
||||
|
||||
/// <summary>
|
||||
/// Font is a TrueType font collection.
|
||||
/// </summary>
|
||||
TrueTypeCollection
|
||||
}
|
||||
}
|
211
PdfSharp/Fonts.OpenType/enums/TableTagNames.cs
Normal file
211
PdfSharp/Fonts.OpenType/enums/TableTagNames.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace PdfSharp.Fonts.OpenType
|
||||
{
|
||||
/// <summary>
|
||||
/// TrueType font table names.
|
||||
/// </summary>
|
||||
static class TableTagNames
|
||||
{
|
||||
// --- Required Tables ---
|
||||
|
||||
/// <summary>
|
||||
/// Character to glyph mapping.
|
||||
/// </summary>
|
||||
public const string CMap = "cmap";
|
||||
|
||||
/// <summary>
|
||||
/// Font header .
|
||||
/// </summary>
|
||||
public const string Head = "head";
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal header.
|
||||
/// </summary>
|
||||
public const string HHea = "hhea";
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal Metrics.
|
||||
/// </summary>
|
||||
public const string HMtx = "hmtx";
|
||||
|
||||
/// <summary>
|
||||
/// Maximum profile.
|
||||
/// </summary>
|
||||
public const string MaxP = "maxp";
|
||||
|
||||
/// <summary>
|
||||
/// Naming table.
|
||||
/// </summary>
|
||||
public const string Name = "name";
|
||||
|
||||
/// <summary>
|
||||
/// OS/2 and Windows specific Metrics.
|
||||
/// </summary>
|
||||
public const string OS2 = "OS/2";
|
||||
|
||||
/// <summary>
|
||||
/// PostScript information.
|
||||
/// </summary>
|
||||
public const string Post = "post";
|
||||
|
||||
// --- Tables Related to TrueType Outlines ---
|
||||
|
||||
/// <summary>
|
||||
/// Control Value Table.
|
||||
/// </summary>
|
||||
public const string Cvt = "cvt ";
|
||||
|
||||
/// <summary>
|
||||
/// Font program.
|
||||
/// </summary>
|
||||
public const string Fpgm = "fpgm";
|
||||
|
||||
/// <summary>
|
||||
/// Glyph data.
|
||||
/// </summary>
|
||||
public const string Glyf = "glyf";
|
||||
|
||||
/// <summary>
|
||||
/// Index to location.
|
||||
/// </summary>
|
||||
public const string Loca = "loca";
|
||||
|
||||
/// <summary>
|
||||
/// CVT Program.
|
||||
/// </summary>
|
||||
public const string Prep = "prep";
|
||||
|
||||
// --- Tables Related to PostScript Outlines ---
|
||||
|
||||
/// <summary>
|
||||
/// PostScript font program (compact font format).
|
||||
/// </summary>
|
||||
public const string Cff = "CFF";
|
||||
|
||||
/// <summary>
|
||||
/// Vertical Origin.
|
||||
/// </summary>
|
||||
public const string VOrg = "VORG";
|
||||
|
||||
// --- Tables Related to Bitmap Glyphs ---
|
||||
|
||||
/// <summary>
|
||||
/// Embedded bitmap data.
|
||||
/// </summary>
|
||||
public const string EBDT = "EBDT";
|
||||
|
||||
/// <summary>
|
||||
/// Embedded bitmap location data.
|
||||
/// </summary>
|
||||
public const string EBLC = "EBLC";
|
||||
|
||||
/// <summary>
|
||||
/// Embedded bitmap scaling data.
|
||||
/// </summary>
|
||||
public const string EBSC = "EBSC";
|
||||
|
||||
// --- Advanced Typographic Tables ---
|
||||
|
||||
/// <summary>
|
||||
/// Baseline data.
|
||||
/// </summary>
|
||||
public const string BASE = "BASE";
|
||||
|
||||
/// <summary>
|
||||
/// Glyph definition data.
|
||||
/// </summary>
|
||||
public const string GDEF = "GDEF";
|
||||
|
||||
/// <summary>
|
||||
/// Glyph positioning data.
|
||||
/// </summary>
|
||||
public const string GPOS = "GPOS";
|
||||
|
||||
/// <summary>
|
||||
/// Glyph substitution data.
|
||||
/// </summary>
|
||||
public const string GSUB = "GSUB";
|
||||
|
||||
/// <summary>
|
||||
/// Justification data.
|
||||
/// </summary>
|
||||
public const string JSTF = "JSTF";
|
||||
|
||||
// --- Other OpenType Tables ---
|
||||
|
||||
/// <summary>
|
||||
/// Digital signature.
|
||||
/// </summary>
|
||||
public const string DSIG = "DSIG";
|
||||
|
||||
/// <summary>
|
||||
/// Grid-fitting/Scan-conversion.
|
||||
/// </summary>
|
||||
public const string Gasp = "gasp";
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal device Metrics.
|
||||
/// </summary>
|
||||
public const string Hdmx = "hdmx";
|
||||
|
||||
/// <summary>
|
||||
/// Kerning.
|
||||
/// </summary>
|
||||
public const string Kern = "kern";
|
||||
|
||||
/// <summary>
|
||||
/// Linear threshold data.
|
||||
/// </summary>
|
||||
public const string LTSH = "LTSH";
|
||||
|
||||
/// <summary>
|
||||
/// PCL 5 data.
|
||||
/// </summary>
|
||||
public const string PCLT = "PCLT";
|
||||
|
||||
/// <summary>
|
||||
/// Vertical device Metrics.
|
||||
/// </summary>
|
||||
public const string VDMX = "VDMX";
|
||||
|
||||
/// <summary>
|
||||
/// Vertical Header.
|
||||
/// </summary>
|
||||
public const string VHea = "vhea";
|
||||
|
||||
/// <summary>
|
||||
/// Vertical Metrics.
|
||||
/// </summary>
|
||||
public const string VMtx = "vmtx";
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user