#region MIT License /*Copyright (c) 2012 Robert Rouhani SharpFont based on Tao.FreeType, Copyright (c) 2003-2007 Tao Framework Team 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.Collections.Generic; using System.Runtime.InteropServices; using SharpFont.Bdf; using SharpFont.Internal; using SharpFont.MultipleMasters; using SharpFont.PostScript; using SharpFont.TrueType; namespace SharpFont { /// /// FreeType root face class structure. A face object models a typeface in a font file. /// /// /// Fields may be changed after a call to or . /// public sealed class Face : IDisposable { #region Fields private IntPtr reference; private FaceRec rec; private bool disposed; private Library parentLibrary; private List childSizes; #endregion #region Constructors /// /// Initializes a new instance of the class with a default faceIndex of 0. /// /// The parent library. /// The path of the font file. public Face(Library library, string path) : this(library, path, 0) { } /// /// Initializes a new instance of the class. /// /// The parent library. /// The path of the font file. /// The index of the face to take from the file. public Face(Library library, string path, int faceIndex) : this() { IntPtr reference; Error err = FT.FT_New_Face(library.Reference, path, faceIndex, out reference); if (err != Error.Ok) throw new FreeTypeException(err); Reference = reference; parentLibrary = library; parentLibrary.AddChildFace(this); } //TODO make an overload with a FileStream instead of a byte[] /// /// Initializes a new instance of the class from a file that's already loaded into memory. /// /// The parent library. /// The loaded file. /// The index of the face to take from the file. public unsafe Face(Library library, byte[] file, int faceIndex) : this() { fixed (byte* ptr = file) { IntPtr reference; Error err = FT.FT_New_Memory_Face(library.Reference, (IntPtr)ptr, file.Length, faceIndex, out reference); if (err != Error.Ok) throw new FreeTypeException(err); Reference = reference; } parentLibrary = library; parentLibrary.AddChildFace(this); } /// /// Initializes a new instance of the Face class. /// /// A pointer to the unmanaged memory containing the Face. /// The parent . internal Face(IntPtr reference, Library parent) : this() { Reference = reference; if (parent != null) { parentLibrary = parent; parentLibrary.AddChildFace(this); } else { //if there's no parent, this is a marshalled duplicate. FT.FT_Reference_Face(Reference); } } private Face() { childSizes = new List(); } /// /// Finalizes an instance of the Face class. /// ~Face() { Dispose(false); } #endregion #region Properties /// /// Gets a value indicating whether the object has been disposed. /// public bool IsDisposed { get { return disposed; } } /// /// Gets the number of faces in the font file. Some font formats can have multiple faces in a font file. /// public int FaceCount { get { if (disposed) throw new ObjectDisposedException("FaceCount", "Cannot access a disposed object."); return (int)rec.num_faces; } } /// /// Gets the index of the face in the font file. It is set to 0 if there is only one face in the font file. /// public int FaceIndex { get { if (disposed) throw new ObjectDisposedException("FaceIndex", "Cannot access a disposed object."); return (int)rec.face_index; } } /// /// Gets a set of bit flags that give important information about the face. /// /// public FaceFlags FaceFlags { get { if (disposed) throw new ObjectDisposedException("FaceFlags", "Cannot access a disposed object."); return (FaceFlags)rec.face_flags; } } /// /// Gets a set of bit flags indicating the style of the face. /// /// public StyleFlags StyleFlags { get { if (disposed) throw new ObjectDisposedException("StyleFlags", "Cannot access a disposed object."); return (StyleFlags)rec.style_flags; } } /// /// Gets the number of glyphs in the face. If the face is scalable and has sbits (see ‘num_fixed_sizes’), it is /// set to the number of outline glyphs. /// /// For CID-keyed fonts, this value gives the highest CID used in the font. /// public int GlyphCount { get { if (disposed) throw new ObjectDisposedException("GlyphCount", "Cannot access a disposed object."); return (int)rec.num_glyphs; } } /// /// Gets the face's family name. This is an ASCII string, usually in English, which describes the typeface's /// family (like ‘Times New Roman’, ‘Bodoni’, ‘Garamond’, etc). This is a least common denominator used to list /// fonts. Some formats (TrueType & OpenType) provide localized and Unicode versions of this string. /// Applications should use the format specific interface to access them. Can be NULL (e.g., in fonts embedded /// in a PDF file). /// public string FamilyName { get { if (disposed) throw new ObjectDisposedException("FamilyName", "Cannot access a disposed object."); return rec.family_name; } } /// /// Gets the face's style name. This is an ASCII string, usually in English, which describes the typeface's /// style (like ‘Italic’, ‘Bold’, ‘Condensed’, etc). Not all font formats provide a style name, so this field /// is optional, and can be set to NULL. As for ‘family_name’, some formats provide localized and Unicode /// versions of this string. Applications should use the format specific interface to access them. /// public string StyleName { get { if (disposed) throw new ObjectDisposedException("StyleName", "Cannot access a disposed object."); return rec.style_name; } } /// /// Gets the number of bitmap strikes in the face. Even if the face is scalable, there might still be bitmap /// strikes, which are called ‘sbits’ in that case. /// public int FixedSizesCount { get { if (disposed) throw new ObjectDisposedException("FixedSizesCount", "Cannot access a disposed object."); return rec.num_fixed_sizes; } } /// /// Gets an array of FT_Bitmap_Size for all bitmap strikes in the face. It is set to NULL if there is no bitmap /// strike. /// public BitmapSize[] AvailableSizes { get { if (disposed) throw new ObjectDisposedException("AvailableSizes", "Cannot access a disposed object."); int count = FixedSizesCount; if (count == 0) return null; BitmapSize[] sizes = new BitmapSize[count]; IntPtr array = rec.available_sizes; for (int i = 0; i < count; i++) { sizes[i] = new BitmapSize(new IntPtr(array.ToInt64() + IntPtr.Size * i)); } return sizes; } } /// /// Gets the number of charmaps in the face. /// public int CharmapsCount { get { if (disposed) throw new ObjectDisposedException("CharmapsCount", "Cannot access a disposed object."); return rec.num_charmaps; } } /// /// Gets an array of the charmaps of the face. /// public CharMap[] CharMaps { get { if (disposed) throw new ObjectDisposedException("CharMaps", "Cannot access a disposed object."); int count = CharmapsCount; if (count == 0) return null; CharMap[] charmaps = new CharMap[count]; IntPtr array = rec.charmaps; for (int i = 0; i < count; i++) { charmaps[i] = new CharMap(new IntPtr(array.ToInt64() + IntPtr.Size * i), this); } return charmaps; } } /// /// Gets or sets a field reserved for client uses. /// /// public Generic Generic { get { if (disposed) throw new ObjectDisposedException("Generic", "Cannot access a disposed object."); return new Generic(rec.generic); } set { if (disposed) throw new ObjectDisposedException("Generic", "Cannot access a disposed object."); //rec.generic = value; value.WriteToUnmanagedMemory(new IntPtr(reference.ToInt64() + Marshal.OffsetOf(typeof(FaceRec), "generic").ToInt64())); Reference = reference; } } /// /// Gets the font bounding box. Coordinates are expressed in font units (see ‘units_per_EM’). The box is large /// enough to contain any glyph from the font. Thus, ‘bbox.yMax’ can be seen as the ‘maximal ascender’, and /// ‘bbox.yMin’ as the ‘minimal descender’. Only relevant for scalable formats. /// /// Note that the bounding box might be off by (at least) one pixel for hinted fonts. See FT_Size_Metrics for /// further discussion. /// public BBox BBox { get { if (disposed) throw new ObjectDisposedException("BBox", "Cannot access a disposed object."); return new BBox(rec.bbox); } } /// /// Gets the number of font units per EM square for this face. This is typically 2048 for TrueType fonts, and /// 1000 for Type 1 fonts. Only relevant for scalable formats. /// [CLSCompliant(false)] public ushort UnitsPerEM { get { if (disposed) throw new ObjectDisposedException("UnitsPerEM", "Cannot access a disposed object."); return rec.units_per_EM; } } /// /// Gets the typographic ascender of the face, expressed in font units. For font formats not having this /// information, it is set to ‘bbox.yMax’. Only relevant for scalable formats. /// public short Ascender { get { if (disposed) throw new ObjectDisposedException("Ascender", "Cannot access a disposed object."); return rec.ascender; } } /// /// Gets the typographic descender of the face, expressed in font units. For font formats not having this /// information, it is set to ‘bbox.yMin’.Note that this field is usually negative. Only relevant for scalable /// formats. /// public short Descender { get { if (disposed) throw new ObjectDisposedException("Descender", "Cannot access a disposed object."); return rec.descender; } } /// /// Gets the height is the vertical distance between two consecutive baselines, expressed in font units. It is /// always positive. Only relevant for scalable formats. /// public short Height { get { if (disposed) throw new ObjectDisposedException("Height", "Cannot access a disposed object."); return rec.height; } } /// /// Gets the maximal advance width, in font units, for all glyphs in this face. This can be used to make word /// wrapping computations faster. Only relevant for scalable formats. /// public short MaxAdvanceWidth { get { if (disposed) throw new ObjectDisposedException("MaxAdvanceWidth", "Cannot access a disposed object."); return rec.max_advance_width; } } /// /// Gets the maximal advance height, in font units, for all glyphs in this face. This is only relevant for /// vertical layouts, and is set to ‘height’ for fonts that do not provide vertical metrics. Only relevant for /// scalable formats. /// public short MaxAdvanceHeight { get { if (disposed) throw new ObjectDisposedException("MaxAdvanceHeight", "Cannot access a disposed object."); return rec.max_advance_height; } } /// /// Gets the position, in font units, of the underline line for this face. It is the center of the underlining /// stem. Only relevant for scalable formats. /// public short UnderlinePosition { get { if (disposed) throw new ObjectDisposedException("UnderlinePosition", "Cannot access a disposed object."); return rec.underline_position; } } /// /// Gets the thickness, in font units, of the underline for this face. Only relevant for scalable formats. /// public short UnderlineThickness { get { if (disposed) throw new ObjectDisposedException("UnderlineThickness", "Cannot access a disposed object."); return rec.underline_thickness; } } /// /// Gets the face's associated glyph slot(s). /// public GlyphSlot Glyph { get { if (disposed) throw new ObjectDisposedException("Glyph", "Cannot access a disposed object."); return new GlyphSlot(rec.glyph, this, parentLibrary); } } /// /// Gets the current active size for this face. /// public FTSize Size { get { if (disposed) throw new ObjectDisposedException("Size", "Cannot access a disposed object."); return new FTSize(rec.size, false, this); } } /// /// Gets the current active charmap for this face. /// public CharMap CharMap { get { if (disposed) throw new ObjectDisposedException("CharMap", "Cannot access a disposed object."); return new CharMap(rec.charmap, this); } } /// /// Gets a value indicating whether a face object contains horizontal metrics (this is true for all font /// formats though). /// public bool HasHoriziontal { get { return (FaceFlags & FaceFlags.Horizontal) == FaceFlags.Horizontal; } } /// /// Gets a value indicating whether a face object contains vertical metrics. /// public bool HasVertical { get { return (FaceFlags & FaceFlags.Vertical) == FaceFlags.Vertical; } } /// /// Gets a value indicating whether a face object contains kerning data that can be accessed with /// . /// public bool HasKerning { get { return (FaceFlags & FaceFlags.Kerning) == FaceFlags.Kerning; } } /// /// Gets a value indicating whether a face object contains a scalable font face (true for TrueType, Type 1, /// Type 42, CID, OpenType/CFF, and PFR font formats. /// public bool IsScalable { get { return (FaceFlags & FaceFlags.Scalable) == FaceFlags.Scalable; } } /// /// Gets a value indicating whether a face object contains a font whose format is based on the SFNT storage /// scheme. This usually means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded bitmap fonts. /// /// If this macro is true, all functions defined in FT_SFNT_NAMES_H and FT_TRUETYPE_TABLES_H are available. /// public bool IsSfnt { get { return (FaceFlags & FaceFlags.Sfnt) == FaceFlags.Sfnt; } } /// /// Gets a value indicating whether a face object contains a font face that contains fixed-width (or /// ‘monospace’, ‘fixed-pitch’, etc.) glyphs. /// public bool IsFixedWidth { get { return (FaceFlags & FaceFlags.FixedWidth) == FaceFlags.FixedWidth; } } /// /// Gets a value indicating whether a face object contains some embedded bitmaps. /// /// public bool HasFixedSizes { get { return (FaceFlags & FaceFlags.FixedSizes) == FaceFlags.FixedSizes; } } /// /// Gets a value indicating whether a face object contains some glyph names that can be accessed through /// . /// public bool HasGlyphNames { get { return (FaceFlags & FaceFlags.GlyphNames) == FaceFlags.GlyphNames; } } /// /// Gets a value indicating whether a face object contains some multiple masters. The functions provided by /// FT_MULTIPLE_MASTERS_H are then available to choose the exact design you want. /// public bool HasMultipleMasters { get { return (FaceFlags & FaceFlags.MultipleMasters) == FaceFlags.MultipleMasters; } } /// /// Gets a value indicating whether a face object contains a CID-keyed font. See the discussion of /// FT_FACE_FLAG_CID_KEYED for more details. /// /// If this macro is true, all functions defined in FT_CID_H are available. /// public bool IsCidKeyed { get { return (FaceFlags & FaceFlags.CidKeyed) == FaceFlags.CidKeyed; } } /// /// Gets a value indicating whether a face represents a ‘tricky’ font. See the discussion of /// FT_FACE_FLAG_TRICKY for more details. /// public bool IsTricky { get { return (FaceFlags & FaceFlags.Tricky) == FaceFlags.Tricky; } } internal IntPtr Reference { get { if (disposed) throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); return reference; } set { if (disposed) throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); reference = value; rec = PInvokeHelper.PtrToStructure(reference); } } #endregion #region Methods #region FreeType Version /// /// Parse all bytecode instructions of a TrueType font file to check whether any of the patented opcodes are /// used. This is only useful if you want to be able to use the unpatented hinter with fonts that do not use /// these opcodes. /// /// Note that this function parses all glyph instructions in the font file, which may be slow. /// /// /// Since May 2010, TrueType hinting is no longer patented. /// /// True if this is a TrueType font that uses one of the patented opcodes, false otherwise. public bool CheckTrueTypePatents() { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return FT.FT_Face_CheckTrueTypePatents(Reference); } /// /// Enable or disable the unpatented hinter for a given . Only enable it if you have /// determined that the face doesn't use any patented opcodes. /// /// /// Since May 2010, TrueType hinting is no longer patented. /// /// New boolean setting. /// /// The old setting value. This will always be false if this is not an SFNT font, or if the unpatented hinter /// is not compiled in this instance of the library. /// /// public bool SetUnpatentedHinting(bool value) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return FT.FT_Face_SetUnpatentedHinting(Reference, value); } #endregion #region Base Interface /// /// This function calls to attach a file. /// /// The pathname. public void AttachFile(string path) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); Error err = FT.FT_Attach_File(Reference, path); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// ‘Attach’ data to a face object. Normally, this is used to read additional information for the face object. /// For example, you can attach an AFM file that comes with a Type 1 font to get the kerning values and other /// metrics. /// /// /// The meaning of the ‘attach’ (i.e., what really happens when the new file is read) is not fixed by FreeType /// itself. It really depends on the font format (and thus the font driver). /// /// Client applications are expected to know what they are doing when invoking this function. Most drivers /// simply do not implement file attachments. /// /// A pointer to which must be filled by the caller. public void AttachStream(OpenArgs parameters) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); Error err = FT.FT_Attach_Stream(Reference, parameters.Reference); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// Select a bitmap strike. /// /// /// The index of the bitmap strike in the field of /// structure. /// public void SelectSize(int strikeIndex) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); Error err = FT.FT_Select_Size(Reference, strikeIndex); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// Resize the scale of the active object in a face. /// /// A pointer to a . public void RequestSize(SizeRequest request) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); Error err = FT.FT_Request_Size(Reference, request.Reference); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// This function calls to request the nominal size (in points). /// /// /// If either the character width or height is zero, it is set equal to the other value. /// /// If either the horizontal or vertical resolution is zero, it is set equal to the other value. /// /// A character width or height smaller than 1pt is set to 1pt; if both resolution values are zero, they are /// set to 72dpi. /// /// The nominal width, in 26.6 fractional points. /// The nominal height, in 26.6 fractional points. /// The horizontal resolution in dpi. /// The vertical resolution in dpi. [CLSCompliant(false)] public void SetCharSize(int width, int height, uint horizontalResolution, uint verticalResolution) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); Error err = FT.FT_Set_Char_Size(Reference, width, height, horizontalResolution, verticalResolution); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// This function calls to request the nominal size (in pixels). /// /// The nominal width, in pixels. /// The nominal height, in pixels [CLSCompliant(false)] public void SetPixelSizes(uint width, uint height) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); Error err = FT.FT_Set_Pixel_Sizes(Reference, width, height); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// A function used to load a single glyph into the glyph slot of a face object. /// /// /// The loaded glyph may be transformed. See for the details. /// /// For subsetted CID-keyed fonts, is returned for invalid CID values (this /// is, for CID values which don't have a corresponding glyph in the font). See the discussion of the /// flag for more details. /// /// /// The index of the glyph in the font file. For CID-keyed fonts (either in PS or in CFF format) this argument /// specifies the CID value. /// /// /// A flag indicating what to load for this glyph. The constants can be used to control /// the glyph loading process (e.g., whether the outline should be scaled, whether to load bitmaps or not, /// whether to hint the outline, etc). /// /// The target to OR with the flags. [CLSCompliant(false)] public void LoadGlyph(uint glyphIndex, LoadFlags flags, LoadTarget target) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); Error err = FT.FT_Load_Glyph(Reference, glyphIndex, (int)flags | (int)target); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// A function used to load a single glyph into the glyph slot of a face object, according to its character /// code. /// /// /// This function simply calls and /// /// /// The glyph's character code, according to the current charmap used in the face. /// /// /// A flag indicating what to load for this glyph. The constants can be used to control /// the glyph loading process (e.g., whether the outline should be scaled, whether to load bitmaps or not, /// whether to hint the outline, etc). /// /// The target to OR with the flags. [CLSCompliant(false)] public void LoadChar(uint charCode, LoadFlags flags, LoadTarget target) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); Error err = FT.FT_Load_Char(Reference, charCode, (int)flags | (int)target); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// A function used to set the transformation that is applied to glyph images when they are loaded into a glyph /// slot through . /// /// /// The transformation is only applied to scalable image formats after the glyph has been loaded. It means that /// hinting is unaltered by the transformation and is performed on the character size given in the last call to /// or . /// /// Note that this also transforms the ‘face.glyph.advance’ field, but not the values in ‘face.glyph.metrics’. /// /// A pointer to the transformation's 2x2 matrix. Use 0 for the identity matrix. /// A pointer to the translation vector. Use 0 for the null vector. public void SetTransform(FTMatrix matrix, FTVector delta) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); FT.FT_Set_Transform(Reference, ref matrix, ref delta); } /// /// Return the kerning vector between two glyphs of a same face. /// /// /// Only horizontal layouts (left-to-right & right-to-left) are supported by this method. Other layouts, or /// more sophisticated kernings, are out of the scope of this API function -- they can be implemented through /// format-specific interfaces. /// /// The index of the left glyph in the kern pair. /// The index of the right glyph in the kern pair. /// Determines the scale and dimension of the returned kerning vector. /// /// The kerning vector. This is either in font units or in pixels (26.6 format) for scalable formats, and in /// pixels for fixed-sizes formats. /// [CLSCompliant(false)] public FTVector GetKerning(uint leftGlyph, uint rightGlyph, KerningMode mode) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); FTVector kern; Error err = FT.FT_Get_Kerning(Reference, leftGlyph, rightGlyph, mode, out kern); if (err != Error.Ok) throw new FreeTypeException(err); return kern; } /// /// Return the track kerning for a given face object at a given size. /// /// The point size in 16.16 fractional points. /// The degree of tightness. /// The kerning in 16.16 fractional points. public int GetTrackKerning(int pointSize, int degree) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); int kerning; Error err = FT.FT_Get_Track_Kerning(Reference, pointSize, degree, out kerning); if (err != Error.Ok) throw new FreeTypeException(err); return kerning; } /// /// Retrieve the ASCII name of a given glyph in a face. This only works for those faces where /// returns 1. /// /// /// An error is returned if the face doesn't provide glyph names or if the glyph index is invalid. In all cases /// of failure, the first byte of ‘buffer’ is set to 0 to indicate an empty name. /// /// The glyph name is truncated to fit within the buffer if it is too long. The returned string is always /// zero-terminated. /// /// Be aware that FreeType reorders glyph indices internally so that glyph index 0 always corresponds to the /// ‘missing glyph’ (called ‘.notdef’). /// /// This function is not compiled within the library if the config macro ‘FT_CONFIG_OPTION_NO_GLYPH_NAMES’ is /// defined in ‘include/freetype/config/ftoptions.h’. /// /// The glyph index. /// The maximal number of bytes available in the buffer. /// The ASCII name of a given glyph in a face. [CLSCompliant(false)] public string GetGlyphName(uint glyphIndex, int bufferSize) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return GetGlyphName(glyphIndex, new byte[bufferSize]); } /// /// Retrieve the ASCII name of a given glyph in a face. This only works for those faces where /// returns 1. /// /// /// An error is returned if the face doesn't provide glyph names or if the glyph index is invalid. In all cases /// of failure, the first byte of ‘buffer’ is set to 0 to indicate an empty name. /// /// The glyph name is truncated to fit within the buffer if it is too long. The returned string is always /// zero-terminated. /// /// Be aware that FreeType reorders glyph indices internally so that glyph index 0 always corresponds to the /// ‘missing glyph’ (called ‘.notdef’). /// /// This function is not compiled within the library if the config macro ‘FT_CONFIG_OPTION_NO_GLYPH_NAMES’ is /// defined in ‘include/freetype/config/ftoptions.h’. /// /// The glyph index. /// The target buffer where the name is copied to. /// The ASCII name of a given glyph in a face. [CLSCompliant(false)] public unsafe string GetGlyphName(uint glyphIndex, byte[] buffer) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); fixed (byte* ptr = buffer) { IntPtr intptr = new IntPtr(ptr); Error err = FT.FT_Get_Glyph_Name(Reference, glyphIndex, intptr, (uint)buffer.Length); if (err != Error.Ok) throw new FreeTypeException(err); return Marshal.PtrToStringAnsi(intptr); } } /// /// Retrieve the ASCII Postscript name of a given face, if available. This only works with Postscript and /// TrueType fonts. /// /// /// The returned pointer is owned by the face and is destroyed with it. /// /// A pointer to the face's Postscript name. NULL if unavailable. public string GetPostscriptName() { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return Marshal.PtrToStringAnsi(FT.FT_Get_Postscript_Name(Reference)); } /// /// Select a given charmap by its encoding tag (as listed in ‘freetype.h’). /// /// /// This function returns an error if no charmap in the face corresponds to the encoding queried here. /// /// Because many fonts contain more than a single cmap for Unicode encoding, this function has some special /// code to select the one which covers Unicode best. It is thus preferable to in /// this case. /// /// A handle to the selected encoding. [CLSCompliant(false)] public void SelectCharmap(Encoding encoding) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); Error err = FT.FT_Select_Charmap(Reference, encoding); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// Select a given charmap for character code to glyph index mapping. /// /// /// This function returns an error if the charmap is not part of the face (i.e., if it is not listed in the /// ’ table). /// /// A handle to the selected charmap. public void SetCharmap(CharMap charmap) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); Error err = FT.FT_Set_Charmap(Reference, charmap.Reference); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// Return the glyph index of a given character code. This function uses a charmap object to do the mapping. /// /// /// If you use FreeType to manipulate the contents of font files directly, be aware that the glyph index /// returned by this function doesn't always correspond to the internal indices used within the file. This is /// done to ensure that value 0 always corresponds to the ‘missing glyph’. /// /// The character code. /// The glyph index. 0 means ‘undefined character code’. [CLSCompliant(false)] public uint GetCharIndex(uint charCode) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return FT.FT_Get_Char_Index(Reference, charCode); } /// /// This function is used to return the first character code in the current charmap of a given face. It also /// returns the corresponding glyph index. /// /// /// You should use this function with to be able to parse all character codes /// available in a given charmap. /// /// Note that ‘agindex’ is set to 0 if the charmap is empty. The result itself can be 0 in two cases: if the /// charmap is empty or when the value 0 is the first valid character code. /// /// Glyph index of first character code. 0 if charmap is empty. /// The charmap's first character code. [CLSCompliant(false)] public uint GetFirstChar(out uint glyphIndex) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return FT.FT_Get_First_Char(Reference, out glyphIndex); } /// /// This function is used to return the next character code in the current charmap of a given face following /// the value ‘charCode’, as well as the corresponding glyph index. /// /// /// You should use this function with to walk over all character codes available /// in a given charmap. See the note for this function for a simple code example. /// /// Note that ‘*agindex’ is set to 0 when there are no more codes in the charmap. /// /// The starting character code. /// Glyph index of first character code. 0 if charmap is empty. /// The charmap's next character code. [CLSCompliant(false)] public uint GetNextChar(uint charCode, out uint glyphIndex) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return FT.FT_Get_Next_Char(Reference, charCode, out glyphIndex); } /// /// Return the glyph index of a given glyph name. This function uses driver specific objects to do the /// translation. /// /// The glyph name. /// The glyph index. 0 means ‘undefined character code’. [CLSCompliant(false)] public uint GetNameIndex(string name) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return FT.FT_Get_Name_Index(Reference, Marshal.StringToHGlobalAuto(name)); } /// /// Return the flags for a font. /// /// /// Use this function rather than directly reading the ‘fs_type’ field in the /// structure which is only guaranteed to return the correct results for Type 1 fonts. /// /// The fsType flags, . [CLSCompliant(false)] public EmbeddingTypes GetFSTypeFlags() { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return FT.FT_Get_FSType_Flags(Reference); } #endregion #region Glyph Variants /// /// Return the glyph index of a given character code as modified by the variation selector. /// /// /// If you use FreeType to manipulate the contents of font files directly, be aware that the glyph index /// returned by this function doesn't always correspond to the internal indices used within the file. This is /// done to ensure that value 0 always corresponds to the ‘missing glyph’. /// /// This function is only meaningful if a) the font has a variation selector cmap sub table, and b) the current /// charmap has a Unicode encoding. /// /// The character code point in Unicode. /// The Unicode code point of the variation selector. /// /// The glyph index. 0 means either ‘undefined character code’, or ‘undefined selector code’, or ‘no variation /// selector cmap subtable’, or ‘current CharMap is not Unicode’. /// [CLSCompliant(false)] public uint GetCharVariantIndex(uint charCode, uint variantSelector) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return FT.FT_Face_GetCharVariantIndex(Reference, charCode, variantSelector); } /// /// Check whether this variant of this Unicode character is the one to be found in the ‘cmap’. /// /// /// This function is only meaningful if the font has a variation selector cmap subtable. /// /// The character codepoint in Unicode. /// The Unicode codepoint of the variation selector. /// /// 1 if found in the standard (Unicode) cmap, 0 if found in the variation selector cmap, or -1 if it is not a /// variant. /// [CLSCompliant(false)] public int GetCharVariantIsDefault(uint charCode, uint variantSelector) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); return FT.FT_Face_GetCharVariantIsDefault(Reference, charCode, variantSelector); } /// /// Return a zero-terminated list of Unicode variant selectors found in the font. /// /// /// The last item in the array is 0; the array is owned by the object but can be overwritten /// or released on the next call to a FreeType function. /// /// /// A pointer to an array of selector code points, or NULL if there is no valid variant selector cmap subtable. /// [CLSCompliant(false)] public uint[] GetVariantSelectors() { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); IntPtr ptr = FT.FT_Face_GetVariantSelectors(Reference); List list = new List(); //temporary non-zero value to prevent complaining about uninitialized variable. uint curValue = 1; for (int i = 0; curValue != 0; i++) { curValue = (uint)Marshal.ReadInt32(Reference, sizeof(uint) * i); list.Add(curValue); } return list.ToArray(); } /// /// Return a zero-terminated list of Unicode variant selectors found in the font. /// /// /// The last item in the array is 0; the array is owned by the object but can be overwritten /// or released on the next call to a FreeType function. /// /// The character codepoint in Unicode. /// /// A pointer to an array of variant selector code points which are active for the given character, or NULL if /// the corresponding list is empty. /// [CLSCompliant(false)] public uint[] GetVariantsOfChar(uint charCode) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); IntPtr ptr = FT.FT_Face_GetVariantsOfChar(Reference, charCode); List list = new List(); //temporary non-zero value to prevent complaining about uninitialized variable. uint curValue = 1; for (int i = 0; curValue != 0; i++) { curValue = (uint)Marshal.ReadInt32(Reference, sizeof(uint) * i); list.Add(curValue); } return list.ToArray(); } /// /// Return a zero-terminated list of Unicode character codes found for the specified variant selector. /// /// /// The last item in the array is 0; the array is owned by the object but can be overwritten /// or released on the next call to a FreeType function. /// /// The variant selector code point in Unicode. /// /// A list of all the code points which are specified by this selector (both default and non-default codes are /// returned) or NULL if there is no valid cmap or the variant selector is invalid. /// [CLSCompliant(false)] public uint[] GetCharsOfVariant(uint variantSelector) { if (disposed) throw new ObjectDisposedException("face", "Cannot access a disposed object."); IntPtr ptr = FT.FT_Face_GetCharsOfVariant(Reference, variantSelector); List list = new List(); //temporary non-zero value to prevent complaining about uninitialized variable. uint curValue = 1; for (int i = 0; curValue != 0; i++) { curValue = (uint)Marshal.ReadInt32(Reference, sizeof(uint) * i); list.Add(curValue); } return list.ToArray(); } #endregion #region Size Management /// /// Create a new size object from a given face object. /// /// /// You need to call in order to select the new size for upcoming calls to /// , , , , /// etc. /// /// A handle to a new size object. public FTSize NewSize() { return new FTSize(this); } #endregion #region Multiple Masters /// /// Retrieve the Multiple Master descriptor of a given font. /// /// This function can't be used with GX fonts. /// /// The Multiple Masters descriptor. public MultiMaster GetMultiMaster() { IntPtr masterRef; Error err = FT.FT_Get_Multi_Master(Reference, out masterRef); if (err != Error.Ok) throw new FreeTypeException(err); return new MultiMaster(masterRef); } /// /// Retrieve the Multiple Master/GX var descriptor of a given font. /// /// /// The Multiple Masters/GX var descriptor. Allocates a data structure, which the user must free (a single call /// to FT_FREE will do it). /// public MMVar GetMMVar() { IntPtr varRef; Error err = FT.FT_Get_MM_Var(Reference, out varRef); if (err != Error.Ok) throw new FreeTypeException(err); return new MMVar(varRef); } /// /// For Multiple Masters fonts, choose an interpolated font design through design coordinates. /// /// This function can't be used with GX fonts. /// /// An array of design coordinates. public unsafe void SetMMDesignCoordinates(long[] coords) { fixed (void* ptr = coords) { IntPtr coordsPtr = (IntPtr)ptr; Error err = FT.FT_Set_MM_Design_Coordinates(Reference, (uint)coords.Length, coordsPtr); if (err != Error.Ok) throw new FreeTypeException(err); } } /// /// For Multiple Master or GX Var fonts, choose an interpolated font design through design coordinates. /// /// An array of design coordinates. public unsafe void SetVarDesignCoordinates(long[] coords) { fixed (void* ptr = coords) { IntPtr coordsPtr = (IntPtr)ptr; Error err = FT.FT_Set_Var_Design_Coordinates(Reference, (uint)coords.Length, coordsPtr); if (err != Error.Ok) throw new FreeTypeException(err); } } /// /// For Multiple Masters and GX var fonts, choose an interpolated font design through normalized blend /// coordinates. /// /// The design coordinates array (each element must be between 0 and 1.0). public unsafe void SetMMBlendCoordinates(long[] coords) { fixed (void* ptr = coords) { IntPtr coordsPtr = (IntPtr)ptr; Error err = FT.FT_Set_MM_Blend_Coordinates(Reference, (uint)coords.Length, coordsPtr); if (err != Error.Ok) throw new FreeTypeException(err); } } /// /// This is another name of . /// /// The design coordinates array (each element must be between 0 and 1.0). public unsafe void SetVarBlendCoordinates(long[] coords) { fixed (void* ptr = coords) { IntPtr coordsPtr = (IntPtr)ptr; Error err = FT.FT_Set_Var_Blend_Coordinates(Reference, (uint)coords.Length, coordsPtr); if (err != Error.Ok) throw new FreeTypeException(err); } } #endregion #region TrueType Tables /// /// Return a pointer to a given SFNT table within a face. /// /// /// The table is owned by the face object and disappears with it. /// /// This function is only useful to access SFNT tables that are loaded by the sfnt, truetype, and opentype /// drivers. See for a list. /// /// The index of the SFNT table. /// /// A type-less pointer to the table. This will be 0 in case of error, or if the corresponding table was not /// found OR loaded from the file. /// /// Use a typecast according to ‘tag’ to access the structure elements. /// public object GetSfntTable(SfntTag tag) { IntPtr tableRef = FT.FT_Get_Sfnt_Table(Reference, tag); if (tableRef == IntPtr.Zero) return null; switch (tag) { case SfntTag.Header: return new Header(tableRef); case SfntTag.HorizontalHeader: return new HoriHeader(tableRef); case SfntTag.MaxProfile: return new MaxProfile(tableRef); case SfntTag.OS2: return new OS2(tableRef); case SfntTag.Pclt: return new Pclt(tableRef); case SfntTag.Postscript: return new Postscript(tableRef); case SfntTag.VertHeader: return new VertHeader(tableRef); default: return null; } } /// /// Load any font table into client memory. /// /// /// If you need to determine the table's length you should first call this function with ‘*length’ set to 0, as /// in the following example: /// /// FT_ULong length = 0; /// /// /// error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); /// if ( error ) { ... table does not exist ... } /// /// buffer = malloc( length ); /// if ( buffer == NULL ) { ... not enough memory ... } /// /// error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length ); /// if ( error ) { ... could not load table ... } /// /// /// /// The four-byte tag of the table to load. Use the value 0 if you want to access the whole font file. /// Otherwise, you can use one of the definitions found in the FT_TRUETYPE_TAGS_H file, or forge a new one with /// FT_MAKE_TAG. /// /// The starting offset in the table (or file if tag == 0). /// /// The target buffer address. The client must ensure that the memory array is big enough to hold the data. /// /// /// If the ‘length’ parameter is NULL, then try to load the whole table. Return an error code if it fails. /// /// Else, if ‘*length’ is 0, exit immediately while returning the table's (or file) full size in it. /// /// Else the number of bytes to read from the table or file, from the starting offset. /// [CLSCompliant(false)] public void LoadSfntTable(uint tag, int offset, IntPtr buffer, ref uint length) { Error err = FT.FT_Load_Sfnt_Table(Reference, tag, offset, buffer, ref length); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// Return information on an SFNT table. /// /// /// The index of an SFNT table. The function returns for an invalid value. /// /// /// The name tag of the SFNT table. If the value is NULL, ‘table_index’ is ignored, and ‘length’ returns the /// number of SFNT tables in the font. /// /// The length of the SFNT table (or the number of SFNT tables, depending on ‘tag’). [CLSCompliant(false)] public unsafe uint SfntTableInfo(uint tableIndex, SfntTag tag) { uint length; Error err = FT.FT_Sfnt_Table_Info(Reference, tableIndex, &tag, out length); if (err != Error.Ok) throw new FreeTypeException(err); return length; } /// /// Only gets the number of SFNT tables. /// /// The number of SFNT tables. [CLSCompliant(false)] public unsafe uint SfntTableInfo() { uint length; Error err = FT.FT_Sfnt_Table_Info(Reference, 0, null, out length); if (err != Error.Ok) throw new FreeTypeException(err); return length; } #endregion #region Type 1 Tables /// /// Return true if a given face provides reliable PostScript glyph names. This is similar to using the /// macro, except that certain fonts (mostly TrueType) contain incorrect /// glyph name tables. /// /// When this function returns true, the caller is sure that the glyph names returned by /// are reliable. /// /// Boolean. True if glyph names are reliable. public bool HasPSGlyphNames() { return FT.FT_Has_PS_Glyph_Names(Reference); } /// /// Retrieve the structure corresponding to a given PostScript font. /// /// /// The string pointers within the font info structure are owned by the face and don't need to be freed by the /// caller. /// /// If the font's format is not PostScript-based, this function will return the /// error code. /// /// Output font info structure pointer. public FontInfo GetPSFontInfo() { IntPtr fontInfoRef; Error err = FT.FT_Get_PS_Font_Info(Reference, out fontInfoRef); if (err != Error.Ok) throw new FreeTypeException(err); return new FontInfo(fontInfoRef); } /// /// Retrieve the structure corresponding to a given PostScript font. /// /// /// The string pointers within the structure are owned by the face and don't /// need to be freed by the caller. /// /// If the font's format is not PostScript-based, this function returns the /// error code. /// /// Output private dictionary structure pointer. public Private GetPSFontPrivate() { IntPtr privateRef; Error err = FT.FT_Get_PS_Font_Private(Reference, out privateRef); if (err != Error.Ok) throw new FreeTypeException(err); return new Private(privateRef); } /// /// Retrieve the value for the supplied key from a PostScript font. /// /// /// The values returned are not pointers into the internal structures of the face, but are ‘fresh’ copies, so /// that the memory containing them belongs to the calling application. This also enforces the ‘read-only’ /// nature of these values, i.e., this function cannot be used to manipulate the face. /// /// ‘value’ is a void pointer because the values returned can be of various types. /// /// If either ‘value’ is NULL or ‘value_len’ is too small, just the required memory size for the requested /// entry is returned. /// /// The ‘idx’ parameter is used, not only to retrieve elements of, for example, the FontMatrix or FontBBox, but /// also to retrieve name keys from the CharStrings dictionary, and the charstrings themselves. It is ignored /// for atomic values. /// /// returns a value that is scaled up by 1000. To get the /// value as in the font stream, you need to divide by 65536000.0 (to remove the FT_Fixed scale, and the x1000 /// scale). /// /// IMPORTANT: Only key/value pairs read by the FreeType interpreter can be retrieved. So, for example, /// PostScript procedures such as NP, ND, and RD are not available. Arbitrary keys are, obviously, not be /// available either. /// /// If the font's format is not PostScript-based, this function returns the /// error code. /// /// An enumeration value representing the dictionary key to retrieve. /// For array values, this specifies the index to be returned. /// A pointer to memory into which to write the value. /// The size, in bytes, of the memory supplied for the value. /// /// The amount of memory (in bytes) required to hold the requested value (if it exists, -1 otherwise). /// [CLSCompliant(false)] public int GetPSFontValue(DictionaryKeys key, uint idx, ref IntPtr value, int valueLength) { return FT.FT_Get_PS_Font_Value(Reference, key, idx, ref value, valueLength); } #endregion #region SFNT Names /// /// Retrieve the number of name strings in the SFNT ‘name’ table. /// /// The number of strings in the ‘name’ table. [CLSCompliant(false)] public uint GetSfntNameCount() { return FT.FT_Get_Sfnt_Name_Count(Reference); } /// /// Retrieve a string of the SFNT ‘name’ table for a given index. /// /// /// The ‘string’ array returned in the ‘aname’ structure is not null-terminated. The application should /// deallocate it if it is no longer in use. /// /// Use to get the total number of available ‘name’ table entries, then do a /// loop until you get the right platform, encoding, and name ID. /// /// The index of the ‘name’ string. /// The indexed structure. [CLSCompliant(false)] public SfntName GetSfntName(uint idx) { IntPtr nameRef; Error err = FT.FT_Get_Sfnt_Name(Reference, idx, out nameRef); if (err != Error.Ok) throw new FreeTypeException(err); return new SfntName(nameRef); } #endregion #region BDF and PCF Files /// /// Retrieve a BDF font character set identity, according to the BDF specification. /// /// /// This function only works with BDF faces, returning an error otherwise. /// /// Charset encoding, as a C string, owned by the face. /// Charset registry, as a C string, owned by the face. public void GetBdfCharsetId(out string encoding, out string registry) { Error err = FT.FT_Get_BDF_Charset_ID(Reference, out encoding, out registry); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// Retrieve a BDF property from a BDF or PCF font file. /// /// /// This function works with BDF and PCF fonts. It returns an error otherwise. It also returns an error if the /// property is not in the font. /// /// A ‘property’ is a either key-value pair within the STARTPROPERTIES ... ENDPROPERTIES block of a BDF font or /// a key-value pair from the ‘info->props’ array within a ‘FontRec’ structure of a PCF font. /// /// Integer properties are always stored as ‘signed’ within PCF fonts; consequently, /// is a possible return value for BDF fonts only. /// /// In case of error, ‘aproperty->type’ is always set to . /// /// The property name. /// The property. public Property GetBdfProperty(string propertyName) { IntPtr propertyRef; Error err = FT.FT_Get_BDF_Property(Reference, propertyName, out propertyRef); if (err != Error.Ok) throw new FreeTypeException(err); return new Property(propertyRef); } #endregion #region CID Fonts /// /// Retrieve the Registry/Ordering/Supplement triple (also known as the "R/O/S") from a CID-keyed font. /// /// /// This function only works with CID faces, returning an error otherwise. /// /// The registry, as a C string, owned by the face. /// The ordering, as a C string, owned by the face. /// The supplement. public void GetCidRegistryOrderingSupplement(out string registry, out string ordering, out int supplement) { Error err = FT.FT_Get_CID_Registry_Ordering_Supplement(Reference, out registry, out ordering, out supplement); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// Retrieve the type of the input face, CID keyed or not. In constrast to the /// macro this function returns successfully also for CID-keyed fonts in an /// SNFT wrapper. /// /// /// This function only works with CID faces and OpenType fonts, returning an error otherwise. /// /// The type of the face as an FT_Bool. public bool GetCidIsInternallyCidKeyed() { byte is_cid; Error err = FT.FT_Get_CID_Is_Internally_CID_Keyed(Reference, out is_cid); if (err != Error.Ok) throw new FreeTypeException(err); return is_cid == 1; } /// /// Retrieve the CID of the input glyph index. /// /// /// This function only works with CID faces and OpenType fonts, returning an error otherwise. /// /// The input glyph index. /// The CID as an uint. [CLSCompliant(false)] public uint GetCidFromGlyphIndex(uint glyphIndex) { uint cid; Error err = FT.FT_Get_CID_From_Glyph_Index(Reference, glyphIndex, out cid); if (err != Error.Ok) throw new FreeTypeException(err); return cid; } #endregion #region PFR Fonts /// /// Return the outline and metrics resolutions of a given PFR face. /// /// /// If the input face is not a PFR, this function will return an error. However, in all cases, it will return /// valid values. /// /// /// Outline resolution. This is equivalent to ‘face->units_per_EM’ for non-PFR fonts. Optional (parameter can /// be NULL). /// /// /// Metrics resolution. This is equivalent to ‘outline_resolution’ for non-PFR fonts. Optional (parameter can /// be NULL). /// /// /// A 16.16 fixed-point number used to scale distance expressed in metrics units to device sub-pixels. This is /// equivalent to ‘face->size->x_scale’, but for metrics only. Optional (parameter can be NULL). /// /// /// Same as ‘ametrics_x_scale’ but for the vertical direction. optional (parameter can be NULL). /// [CLSCompliant(false)] public void GetPfrMetrics(out uint outlineResolution, out uint metricsResolution, out int metricsXScale, out int metricsYScale) { Error err = FT.FT_Get_PFR_Metrics(Reference, out outlineResolution, out metricsResolution, out metricsXScale, out metricsYScale); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// Return the kerning pair corresponding to two glyphs in a PFR face. The distance is expressed in metrics /// units, unlike the result of . /// /// /// This function always return distances in original PFR metrics units. This is unlike /// with the mode, which always returns /// distances converted to outline units. /// /// You can use the value of the ‘x_scale’ and ‘y_scale’ parameters returned by to /// scale these to device sub-pixels. /// /// Index of the left glyph. /// Index of the right glyph. /// A kerning vector. [CLSCompliant(false)] public FTVector GetPfrKerning(uint left, uint right) { FTVector vector; Error err = FT.FT_Get_PFR_Kerning(Reference, left, right, out vector); if (err != Error.Ok) throw new FreeTypeException(err); return vector; } /// /// Return a given glyph advance, expressed in original metrics units, from a PFR font. /// /// /// You can use the ‘x_scale’ or ‘y_scale’ results of to convert the advance to /// device sub-pixels (i.e., 1/64th of pixels). /// /// The glyph index. /// The glyph advance in metrics units. [CLSCompliant(false)] public int GetPfrAdvance(uint glyphIndex) { int advance; Error err = FT.FT_Get_PFR_Advance(Reference, glyphIndex, out advance); if (err != Error.Ok) throw new FreeTypeException(err); return advance; } #endregion #region Windows FNT Files /// /// Retrieve a Windows FNT font info header. /// /// /// This function only works with Windows FNT faces, returning an error otherwise. /// /// The WinFNT header. public Fnt.Header GetWinFntHeader() { IntPtr headerRef; Error err = FT.FT_Get_WinFNT_Header(Reference, out headerRef); if (err != Error.Ok) throw new FreeTypeException(err); return new Fnt.Header(headerRef); } #endregion #region Font Formats /// /// Return a string describing the format of a given face, using values which can be used as an X11 /// FONT_PROPERTY. Possible values are ‘TrueType’, ‘Type 1’, ‘BDF’, ‘PCF’, ‘Type 42’, ‘CID Type 1’, ‘CFF’, /// ‘PFR’, and ‘Windows FNT’. /// /// Font format string. NULL in case of error. public string GetX11FontFormat() { return Marshal.PtrToStringAnsi(FT.FT_Get_X11_Font_Format(Reference)); } #endregion #region Gasp Table /// /// Read the ‘gasp’ table from a TrueType or OpenType font file and return the entry corresponding to a given /// character pixel size. /// /// The vertical character pixel size. /// /// Bit flags (see ), or if there is no ‘gasp’ table in the face. /// [CLSCompliant(false)] public Gasp GetGasp(uint ppem) { return FT.FT_Get_Gasp(Reference, ppem); } #endregion #region Quick retrieval of advance values /// /// Retrieve the advance value of a given glyph outline in a . By default, the unhinted /// advance is returned in font units. /// /// /// This function may fail if you use and if the corresponding font /// backend doesn't have a quick way to retrieve the advances. /// /// A scaled advance is returned in 16.16 format but isn't transformed by the affine transformation specified /// by . /// /// The glyph index. /// /// A set of bit flags similar to those used when calling , used to determine what kind /// of advances you need. /// /// /// The advance value, in either font units or 16.16 format. /// /// If is set, this is the vertical advance corresponding to a vertical /// layout. Otherwise, it is the horizontal advance in a horizontal layout. /// [CLSCompliant(false)] public int GetAdvance(uint glyphIndex, LoadFlags flags) { int padvance; Error err = FT.FT_Get_Advance(Reference, glyphIndex, flags, out padvance); if (err != Error.Ok) throw new FreeTypeException(err); return padvance; } /// /// Retrieve the advance values of several glyph outlines in an /// . By default, the unhinted advances are returned /// in font units. /// /// /// This function may fail if you use /// and if the /// corresponding font backend doesn't have a quick way to retrieve the /// advances. /// /// Scaled advances are returned in 16.16 format but aren't transformed /// by the affine transformation specified by /// . /// /// The first glyph index. /// The number of advance values you want to retrieve. /// A set of bit flags similar to those used when calling . /// The advances, in either font units or 16.16 format. This array must contain at least ‘count’ elements. /// /// If is set, these are the vertical advances corresponding to a vertical layout. Otherwise, they are the horizontal advances in a horizontal layout. [CLSCompliant(false)] public unsafe int[] GetAdvances(uint start, uint count, LoadFlags flags) { IntPtr advPtr; Error err = FT.FT_Get_Advances(Reference, start, count, flags, out advPtr); if (err != Error.Ok) throw new FreeTypeException(err); //create a new array and copy the data from the pointer over int[] advances = new int[count]; int* ptr = (int*)advPtr; for (int i = 0; i < count; i++) advances[i] = ptr[i]; return advances; } #endregion #region OpenType Validation /// /// Validate various OpenType tables to assure that all offsets and indices are valid. The idea is that a /// higher-level library which actually does the text layout can access those tables without error checking /// (which can be quite time consuming). /// /// /// This function only works with OpenType fonts, returning an error otherwise. /// /// After use, the application should deallocate the five tables with . A NULL value /// indicates that the table either doesn't exist in the font, or the application hasn't asked for validation. /// /// A bit field which specifies the tables to be validated. /// A pointer to the BASE table. /// A pointer to the GDEF table. /// A pointer to the GPOS table. /// A pointer to the GSUB table. /// A pointer to the JSTF table. [CLSCompliant(false)] public void OpenTypeValidate(OpenTypeValidationFlags flags, out IntPtr baseTable, out IntPtr gdefTable, out IntPtr gposTable, out IntPtr gsubTable, out IntPtr jstfTable) { Error err = FT.FT_OpenType_Validate(Reference, flags, out baseTable, out gdefTable, out gposTable, out gsubTable, out jstfTable); if (err != Error.Ok) throw new FreeTypeException(err); } /// /// Free the buffer allocated by OpenType validator. /// /// /// This function must be used to free the buffer allocated by only. /// /// The pointer to the buffer that is allocated by . public void OpenTypeFree(IntPtr table) { FT.FT_OpenType_Free(Reference, table); } #endregion #region TrueTypeGX/AAT Validation /// /// Validate various TrueTypeGX tables to assure that all offsets and indices are valid. The idea is that a /// higher-level library which actually does the text layout can access those tables without error checking /// (which can be quite time consuming). /// /// /// This function only works with TrueTypeGX fonts, returning an error otherwise. /// /// After use, the application should deallocate the buffers pointed to by each ‘tables’ element, by calling /// . A NULL value indicates that the table either doesn't exist in the font, the /// application hasn't asked for validation, or the validator doesn't have the ability to validate the sfnt /// table. /// /// A bit field which specifies the tables to be validated. /// /// The array where all validated sfnt tables are stored. The array itself must be allocated by a client. /// /// /// The size of the ‘tables’ array. Normally, FT_VALIDATE_GX_LENGTH should be passed. /// [CLSCompliant(false)] public void TrueTypeGXValidate(TrueTypeValidationFlags flags, byte[][] tables, uint tableLength) { FT.FT_TrueTypeGX_Validate(Reference, flags, tables, tableLength); } /// /// Free the buffer allocated by TrueTypeGX validator. /// /// /// This function must be used to free the buffer allocated by only. /// /// The pointer to the buffer allocated by . public void TrueTypeGXFree(IntPtr table) { FT.FT_TrueTypeGX_Free(Reference, table); } /// /// Validate classic (16-bit format) kern table to assure that the offsets and indices are valid. The idea is /// that a higher-level library which actually does the text layout can access those tables without error /// checking (which can be quite time consuming). /// /// The ‘kern’ table validator in deals with both the new 32-bit format and /// the classic 16-bit format, while only supports the classic 16-bit format. /// /// /// After use, the application should deallocate the buffers pointed to by ‘ckern_table’, by calling /// . A NULL value indicates that the table doesn't exist in the font. /// /// A bit field which specifies the dialect to be validated. /// A pointer to the kern table. [CLSCompliant(false)] public IntPtr ClassicKernValidate(ClassicKernValidationFlags flags) { IntPtr ckernRef; FT.FT_ClassicKern_Validate(Reference, flags, out ckernRef); return ckernRef; } /// /// Free the buffer allocated by classic Kern validator. /// /// /// This function must be used to free the buffer allocated by only. /// /// /// The pointer to the buffer that is allocated by . /// public void ClassicKernFree(IntPtr table) { FT.FT_ClassicKern_Free(Reference, table); } #endregion /// /// Disposes the Face. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } internal void AddChildSize(FTSize child) { childSizes.Add(child); } internal void RemoveChildSize(FTSize child) { childSizes.Remove(child); } private void Dispose(bool disposing) { if (!disposed) { disposed = true; foreach (FTSize s in childSizes) s.Dispose(); childSizes.Clear(); Error err = FT.FT_Done_Face(reference); if (err != Error.Ok) throw new FreeTypeException(err); // removes itself from the parent Library, with a check to prevent this from happening when Library is // being disposed (Library disposes all it's children with a foreach loop, this causes an // InvalidOperationException for modifying a collection during enumeration) if (!parentLibrary.IsDisposed) parentLibrary.RemoveChildFace(this); reference = IntPtr.Zero; rec = null; } } #endregion } }