text:
/****************************************************************************
 *
 * cfftypes.h
 *
 *   Basic OpenType/CFF type definitions and interface (specification
 *   only).
 *
 * Copyright (C) 1996-2020 by
 * David Turner, Robert Wilhelm, and Werner Lemberg.
 *
 * This file is part of the FreeType project, and may only be used,
 * modified, and distributed under the terms of the FreeType project
 * license, LICENSE.TXT.  By continuing to use, modify, or distribute
 * this file you indicate that you have read the license and
 * understand and accept it fully.
 *
 */

#ifndef CFFTYPES_H_
#define CFFTYPES_H_

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TYPE1_TABLES_H
#include FT_INTERNAL_SERVICE_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
#include FT_INTERNAL_TYPE1_TYPES_H

FT_BEGIN_HEADER

  /**************************************************************************
   *
   * @struct:
   *   CFF_IndexRec
   *
   * @description:
   *   A structure used to model a CFF Index table.
   *
   * @fields:
   *   stream ::
   *     The source input stream.
   *
   *   start ::
   *     The position of the first index byte in the input stream.
   *
   *   count ::
   *     The number of elements in the index.
   *
   *   off_size ::
   *     The size in bytes of object offsets in index.
   *
   *   data_offset ::
   *     The position of first data byte in the index's bytes.
   *
   *   data_size ::
   *     The size of the data table in this index.
   *
   *   offsets ::
   *     A table of element offsets in the index.  Must be loaded explicitly.
   *
   *   bytes ::
   *     If the index is loaded in memory, its bytes.
   */
  typedef struct  CFF_IndexRec_
  {
    FT_Stream  stream;
    FT_ULong   start;
    FT_UInt    hdr_size;
    FT_UInt    count;
    FT_Byte    off_size;
    FT_ULong   data_offset;
    FT_ULong   data_size;

    FT_ULong*  offsets;
    FT_Byte*   bytes;

  } CFF_IndexRec, *CFF_Index;

  typedef struct  CFF_EncodingRec_
  {
    FT_UInt     format;
    FT_ULong    offset;

    FT_UInt     count;
    FT_UShort   sids [256];  /* avoid dynamic allocations */
    FT_UShort   codes[256];

  } CFF_EncodingRec, *CFF_Encoding;

  typedef struct  CFF_CharsetRec_
  {

    FT_UInt     format;
    FT_ULong    offset;

    FT_UShort*  sids;
    FT_UShort*  cids;       /* the inverse mapping of `sids'; only needed */
                            /* for CID-keyed fonts                        */
    FT_UInt     max_cid;
    FT_UInt     num_glyphs;

  } CFF_CharsetRec, *CFF_Charset;

  /* cf. similar fields in file `ttgxvar.h' from the `truetype' module */

  typedef struct  CFF_VarData_
  {
#if 0
    FT_UInt  itemCount;       /* not used; always zero */
    FT_UInt  shortDeltaCount; /* not used; always zero */
#endif

    FT_UInt   regionIdxCount; /* number of region indexes           */
    FT_UInt*  regionIndices;  /* array of `regionIdxCount' indices; */
                              /* these index `varRegionList'        */
  } CFF_VarData;

  /* contribution of one axis to a region */
  typedef struct  CFF_AxisCoords_
  {
    FT_Fixed  startCoord;
    FT_Fixed  peakCoord;      /* zero peak means no effect (factor = 1) */
    FT_Fixed  endCoord;

  } CFF_AxisCoords;

  typedef struct  CFF_VarRegion_
  {
    CFF_AxisCoords*  axisList;      /* array of axisCount records */

  } CFF_VarRegion;

  typedef struct  CFF_VStoreRec_
  {
    FT_UInt         dataCount;
    CFF_VarData*    varData;        /* array of dataCount records      */
                                    /* vsindex indexes this array      */
    FT_UShort       axisCount;
    FT_UInt         regionCount;    /* total number of regions defined */
    CFF_VarRegion*  varRegionList;

  } CFF_VStoreRec, *CFF_VStore;

  /* forward reference */
  typedef struct CFF_FontRec_*  CFF_Font;

  /* This object manages one cached blend vector.                  */
  /*                                                               */
  /* There is a BlendRec for Private DICT parsing in each subfont  */
  /* and a BlendRec for charstrings in CF2_Font instance data.     */
  /* A cached BV may be used across DICTs or Charstrings if inputs */
  /* have not changed.                                             */
  /*                                                               */
  /* `usedBV' is reset at the start of each parse or charstring.   */
  /* vsindex cannot be changed after a BV is used.                 */
  /*                                                               */
  /* Note: NDV is long (32/64 bit), while BV is 16.16 (FT_Int32).  */
  typedef struct  CFF_BlendRec_
  {
    FT_Bool    builtBV;        /* blendV has been built           */
    FT_Bool    usedBV;         /* blendV has been used            */
    CFF_Font   font;           /* top level font struct           */
    FT_UInt    lastVsindex;    /* last vsindex used               */
    FT_UInt    lenNDV;         /* normDV length (aka numAxes)     */
    FT_Fixed*  lastNDV;        /* last NDV used                   */
    FT_UInt    lenBV;          /* BlendV length (aka numMasters)  */
    FT_Int32*  BV;             /* current blendV (per DICT/glyph) */

  } CFF_BlendRec, *CFF_Blend;

  typedef struct  CFF_FontRecDictRec_
  {
    FT_UInt    version;
    FT_UInt    notice;
    FT_UInt    copyright;
    FT_UInt    full_name;
    FT_UInt    family_name;
    FT_UInt    weight;
    FT_Bool    is_fixed_pitch;
    FT_Fixed   italic_angle;
    FT_Fixed   underline_position;
    FT_Fixed   underline_thickness;
    FT_Int     paint_type;
    FT_Int     charstring_type;
    FT_Matrix  font_matrix;
    FT_Bool    has_font_matrix;
    FT_ULong   units_per_em;  /* temporarily used as scaling value also */
    FT_Vector  font_offset;
    FT_ULong   unique_id;
    FT_BBox    font_bbox;
    FT_Pos     stroke_width;
    FT_ULong   charset_offset;
    FT_ULong   encoding_offset;
    FT_ULong   charstrings_offset;
    FT_ULong   private_offset;
    FT_ULong   private_size;
    FT_Long    synthetic_base;
    FT_UInt    embedded_postscript;

    /* these should only be used for the top-level font dictionary */
    FT_UInt    cid_registry;
    FT_UInt    cid_ordering;
    FT_Long    cid_supplement;

    FT_Long    cid_font_version;
    FT_Long    cid_font_revision;
    FT_Long    cid_font_type;
    FT_ULong   cid_count;
    FT_ULong   cid_uid_base;
    FT_ULong   cid_fd_array_offset;
    FT_ULong   cid_fd_select_offset;
    FT_UInt    cid_font_name;

    /* the next fields come from the data of the deprecated          */
    /* `MultipleMaster' operator; they are needed to parse the (also */
    /* deprecated) `blend' operator in Type 2 charstrings            */
    FT_UShort  num_designs;
    FT_UShort  num_axes;

    /* fields for CFF2 */
    FT_ULong   vstore_offset;
    FT_UInt    maxstack;

  } CFF_FontRecDictRec, *CFF_FontRecDict;

  /* forward reference */
  typedef struct CFF_SubFontRec_*  CFF_SubFont;

  typedef struct  CFF_PrivateRec_
  {
    FT_Byte   num_blue_values;
    FT_Byte   num_other_blues;
    FT_Byte   num_family_blues;
    FT_Byte   num_family_other_blues;

    FT_Pos    blue_values[14];
    FT_Pos    other_blues[10];
    FT_Pos    family_blues[14];
    FT_Pos    family_other_blues[10];

    FT_Fixed  blue_scale;
    FT_Pos    blue_shift;
    FT_Pos    blue_fuzz;
    FT_Pos    standard_width;
    FT_Pos    standard_height;

    FT_Byte   num_snap_widths;
    FT_Byte   num_snap_heights;
    FT_Pos    snap_widths[13];
    FT_Pos    snap_heights[13];
    FT_Bool   force_bold;
    FT_Fixed  force_bold_threshold;
    FT_Int    lenIV;
    FT_Int    language_group;
    FT_Fixed  expansion_factor;
    FT_Long   initial_random_seed;
    FT_ULong  local_subrs_offset;
    FT_Pos    default_width;
    FT_Pos    nominal_width;

    /* fields for CFF2 */
    FT_UInt      vsindex;
    CFF_SubFont  subfont;

  } CFF_PrivateRec, *CFF_Private;

  typedef struct  CFF_FDSelectRec_
  {
    FT_Byte   format;
    FT_UInt   range_count;

    /* that's the table, taken from the file `as is' */
    FT_Byte*  data;
    FT_UInt   data_size;

    /* small cache for format 3 only */
    FT_UInt   cache_first;
    FT_UInt   cache_count;
    FT_Byte   cache_fd;

  } CFF_FDSelectRec, *CFF_FDSelect;

  /* A SubFont packs a font dict and a private dict together.  They are */
  /* needed to support CID-keyed CFF fonts.                             */
  typedef struct  CFF_SubFontRec_
  {
    CFF_FontRecDictRec  font_dict;
    CFF_PrivateRec      private_dict;

    /* fields for CFF2 */
    CFF_BlendRec  blend;      /* current blend vector       */
    FT_UInt       lenNDV;     /* current length NDV or zero */
    FT_Fixed*     NDV;        /* ptr to current NDV or NULL */

    /* `blend_stack' is a writable buffer to hold blend results.          */
    /* This buffer is to the side of the normal cff parser stack;         */
    /* `cff_parse_blend' and `cff_blend_doBlend' push blend results here. */
    /* The normal stack then points to these values instead of the DICT   */
    /* because all other operators in Private DICT clear the stack.       */
    /* `blend_stack' could be cleared at each operator other than blend.  */
    /* Blended values are stored as 5-byte fixed point values.            */

    FT_Byte*  blend_stack;    /* base of stack allocation     */
    FT_Byte*  blend_top;      /* first empty slot             */
    FT_UInt   blend_used;     /* number of bytes in use       */
    FT_UInt   blend_alloc;    /* number of bytes allocated    */

    CFF_IndexRec  local_subrs_index;
    FT_Byte**     local_subrs; /* array of pointers           */
                               /* into Local Subrs INDEX data */

    FT_UInt32  random;

  } CFF_SubFontRec;

#define CFF_MAX_CID_FONTS  256

  typedef struct  CFF_FontRec_
  {
    FT_Library       library;
    FT_Stream        stream;
    FT_Memory        memory;        /* TODO: take this from stream->memory? */
    FT_ULong         base_offset;   /* offset to start of CFF */
    FT_UInt          num_faces;
    FT_UInt          num_glyphs;

    FT_Byte          version_major;
    FT_Byte          version_minor;
    FT_Byte          header_size;

    FT_UInt          top_dict_length;   /* cff2 only */

    FT_Bool          cff2;

    CFF_IndexRec     name_index;
    CFF_IndexRec     top_dict_index;
    CFF_IndexRec     global_subrs_index;

    CFF_EncodingRec  encoding;
    CFF_CharsetRec   charset;

    CFF_IndexRec     charstrings_index;
    CFF_IndexRec     font_dict_index;
    CFF_IndexRec     private_index;
    CFF_IndexRec     local_subrs_index;

    FT_String*       font_name;

    /* array of pointers into Global Subrs INDEX data */
    FT_Byte**        global_subrs;

    /* array of pointers into String INDEX data stored at string_pool */
    FT_UInt          num_strings;
    FT_Byte**        strings;
    FT_Byte*         string_pool;
    FT_ULong         string_pool_size;

    CFF_SubFontRec   top_font;
    FT_UInt          num_subfonts;
    CFF_SubFont      subfonts[CFF_MAX_CID_FONTS];

    CFF_FDSelectRec  fd_select;

    /* interface to PostScript hinter */
    PSHinter_Service  pshinter;

    /* interface to Postscript Names service */
    FT_Service_PsCMaps  psnames;

    /* interface to CFFLoad service */
    const void*  cffload;

    /* since version 2.3.0 */
    PS_FontInfoRec*  font_info;   /* font info dictionary */

    /* since version 2.3.6 */
    FT_String*       registry;
    FT_String*       ordering;

    /* since version 2.4.12 */
    FT_Generic       cf2_instance;

    /* since version 2.7.1 */
    CFF_VStoreRec    vstore;        /* parsed vstore structure */

    /* since version 2.9 */
    PS_FontExtraRec*  font_extra;

  } CFF_FontRec;

FT_END_HEADER

#endif /* CFFTYPES_H_ */

/* END */


text:
/****************************************************************************
 *
 * autohint.h
 *
 *   High-level 'autohint' module-specific interface (specification).
 *
 * Copyright (C) 1996-2020 by
 * David Turner, Robert Wilhelm, and Werner Lemberg.
 *
 * This file is part of the FreeType project, and may only be used,
 * modified, and distributed under the terms of the FreeType project
 * license, LICENSE.TXT.  By continuing to use, modify, or distribute
 * this file you indicate that you have read the license and
 * understand and accept it fully.
 *
 */

  /**************************************************************************
   *
   * The auto-hinter is used to load and automatically hint glyphs if a
   * format-specific hinter isn't available.
   *
   */

#ifndef AUTOHINT_H_
#define AUTOHINT_H_

  /**************************************************************************
   *
   * A small technical note regarding automatic hinting in order to clarify
   * this module interface.
   *
   * An automatic hinter might compute two kinds of data for a given face:
   *
   * - global hints: Usually some metrics that describe global properties
   *                 of the face.  It is computed by scanning more or less
   *                 aggressively the glyphs in the face, and thus can be
   *                 very slow to compute (even if the size of global hints
   *                 is really small).
   *
   * - glyph hints: These describe some important features of the glyph
   *                 outline, as well as how to align them.  They are
   *                 generally much faster to compute than global hints.
   *
   * The current FreeType auto-hinter does a pretty good job while performing
   * fast computations for both global and glyph hints.  However, we might be
   * interested in introducing more complex and powerful algorithms in the
   * future, like the one described in the John D. Hobby paper, which
   * unfortunately requires a lot more horsepower.
   *
   * Because a sufficiently sophisticated font management system would
   * typically implement an LRU cache of opened face objects to reduce memory
   * usage, it is a good idea to be able to avoid recomputing global hints
   * every time the same face is re-opened.
   *
   * We thus provide the ability to cache global hints outside of the face
   * object, in order to speed up font re-opening time.  Of course, this
   * feature is purely optional, so most client programs won't even notice
   * it.
   *
   * I initially thought that it would be a good idea to cache the glyph
   * hints too.  However, my general idea now is that if you really need to
   * cache these too, you are simply in need of a new font format, where all
   * this information could be stored within the font file and decoded on the
   * fly.
   *
   */

#include <ft2build.h>
#include FT_FREETYPE_H

FT_BEGIN_HEADER

  typedef struct FT_AutoHinterRec_  *FT_AutoHinter;

  /**************************************************************************
   *
   * @functype:
   *   FT_AutoHinter_GlobalGetFunc
   *
   * @description:
   *   Retrieve the global hints computed for a given face object.  The
   *   resulting data is dissociated from the face and will survive a call to
   *   FT_Done_Face().  It must be discarded through the API
   *   FT_AutoHinter_GlobalDoneFunc().
   *
   * @input:
   *   hinter ::
   *     A handle to the source auto-hinter.
   *
   *   face ::
   *     A handle to the source face object.
   *
   * @output:
   *   global_hints ::
   *     A typeless pointer to the global hints.
   *
   *   global_len ::
   *     The size in bytes of the global hints.
   */
  typedef void
  (*FT_AutoHinter_GlobalGetFunc)( FT_AutoHinter  hinter,
                                  FT_Face        face,
                                  void**         global_hints,
                                  long*          global_len );

  /**************************************************************************
   *
   * @functype:
   *   FT_AutoHinter_GlobalDoneFunc
   *
   * @description:
   *   Discard the global hints retrieved through
   *   FT_AutoHinter_GlobalGetFunc().  This is the only way these hints are
   *   freed from memory.
   *
   * @input:
   *   hinter ::
   *     A handle to the auto-hinter module.
   *
   *   global ::
   *     A pointer to retrieved global hints to discard.
   */
  typedef void
  (*FT_AutoHinter_GlobalDoneFunc)( FT_AutoHinter  hinter,
                                   void*          global );

  /**************************************************************************
   *
   * @functype:
   *   FT_AutoHinter_GlobalResetFunc
   *
   * @description:
   *   This function is used to recompute the global metrics in a given font.
   *   This is useful when global font data changes (e.g. Multiple Masters
   *   fonts where blend coordinates change).
   *
   * @input:
   *   hinter ::
   *     A handle to the source auto-hinter.
   *
   *   face ::
   *     A handle to the face.
   */
  typedef void
  (*FT_AutoHinter_GlobalResetFunc)( FT_AutoHinter  hinter,
                                    FT_Face        face );

  /**************************************************************************
   *
   * @functype:
   *   FT_AutoHinter_GlyphLoadFunc
   *
   * @description:
   *   This function is used to load, scale, and automatically hint a glyph
   *   from a given face.
   *
   * @input:
   *   face ::
   *     A handle to the face.
   *
   *   glyph_index ::
   *     The glyph index.
   *
   *   load_flags ::
   *     The load flags.
   *
   * @note:
   *   This function is capable of loading composite glyphs by hinting each
   *   sub-glyph independently (which improves quality).
   *
   *   It will call the font driver with @FT_Load_Glyph, with
   *   @FT_LOAD_NO_SCALE set.
   */
  typedef FT_Error
  (*FT_AutoHinter_GlyphLoadFunc)( FT_AutoHinter  hinter,
                                  FT_GlyphSlot   slot,
                                  FT_Size        size,
                                  FT_UInt        glyph_index,
                                  FT_Int32       load_flags );

  /**************************************************************************
   *
   * @struct:
   *   FT_AutoHinter_InterfaceRec
   *
   * @description:
   *   The auto-hinter module's interface.
   */
  typedef struct  FT_AutoHinter_InterfaceRec_
  {
    FT_AutoHinter_GlobalResetFunc  reset_face;
    FT_AutoHinter_GlobalGetFunc    get_global_hints;
    FT_AutoHinter_GlobalDoneFunc   done_global_hints;
    FT_AutoHinter_GlyphLoadFunc    load_glyph;

  } FT_AutoHinter_InterfaceRec, *FT_AutoHinter_Interface;

#define FT_DEFINE_AUTOHINTER_INTERFACE(       \
          class_,                             \
          reset_face_,                        \
          get_global_hints_,                  \
          done_global_hints_,                 \
          load_glyph_ )                       \
  FT_CALLBACK_TABLE_DEF                       \
  const FT_AutoHinter_InterfaceRec  class_ =  \
  {                                           \
    reset_face_,                              \
    get_global_hints_,                        \
    done_global_hints_,                       \
    load_glyph_                               \
  };

FT_END_HEADER

#endif /* AUTOHINT_H_ */

/* END */

repo_language: C

mime_type: text/x-c


text:
/****************************************************************************
 *
 * sfnt.h
 *
 *   High-level 'sfnt' driver interface (specification).
 *
 * Copyright (C) 1996-2020 by
 * David Turner, Robert Wilhelm, and Werner Lemberg.
 *
 * This file is part of the FreeType project, and may only be used,
 * modified, and distributed under the terms of the FreeType project
 * license, LICENSE.TXT.  By continuing to use, modify, or distribute
 * this file you indicate that you have read the license and
 * understand and accept it fully.
 *
 */

#ifndef SFNT_H_
#define SFNT_H_

#include <ft2build.h>
#include FT_INTERNAL_DRIVER_H
#include FT_INTERNAL_TRUETYPE_TYPES_H
#include FT_INTERNAL_WOFF_TYPES_H

FT_BEGIN_HEADER

  /**************************************************************************
   *
   * @functype:
   *   TT_Init_Face_Func
   *
   * @description:
   *   First part of the SFNT face object initialization.  This finds the
   *   face in a SFNT file or collection, and load its format tag in
   *   face->format_tag.
   *
   * @input:
   *   stream ::
   *     The input stream.
   *
   *   face ::
   *     A handle to the target face object.
   *
   *   face_index ::
   *     The index of the TrueType font, if we are opening a collection, in
   *     bits 0-15.  The numbered instance index~+~1 of a GX (sub)font, if
   *     applicable, in bits 16-30.
   *
   *   num_params ::
   *     The number of additional parameters.
   *
   *   params ::
   *     Optional additional parameters.
   *
   * @return:
   *   FreeType error code.  0 means success.
   *
   * @note:
   *   The stream cursor must be at the font file's origin.
   *
   *   This function recognizes fonts embedded in a 'TrueType collection'.
   *
   *   Once the format tag has been validated by the font driver, it should
   *   then call the TT_Load_Face_Func() callback to read the rest of the
   *   SFNT tables in the object.
   */
  typedef FT_Error
  (*TT_Init_Face_Func)( FT_Stream      stream,
                        TT_Face        face,
                        FT_Int         face_index,
                        FT_Int         num_params,
                        FT_Parameter*  params );

  /**************************************************************************
   *
   * @functype:
   *   TT_Load_Face_Func
   *
   * @description:
   *   Second part of the SFNT face object initialization.  This loads the
   *   common SFNT tables (head, OS/2, maxp, metrics, etc.) in the face
   *   object.
   *
   * @input:
   *   stream ::
   *     The input stream.
   *
   *   face ::
   *     A handle to the target face object.
   *
   *   face_index ::
   *     The index of the TrueType font, if we are opening a collection, in
   *     bits 0-15.  The numbered instance index~+~1 of a GX (sub)font, if
   *     applicable, in bits 16-30.
   *
   *   num_params ::
   *     The number of additional parameters.
   *
   *   params ::
   *     Optional additional parameters.
   *
   * @return:
   *   FreeType error code.  0 means success.
   *
   * @note:
   *   This function must be called after TT_Init_Face_Func().
   */
  typedef FT_Error
  (*TT_Load_Face_Func)( FT_Stream      stream,
                        TT_Face        face,
                        FT_Int         face_index,
                        FT_Int         num_params,
                        FT_Parameter*  params );

  /**************************************************************************
   *
   * @functype:
   *   TT_Done_Face_Func
   *
   * @description:
   *   A callback used to delete the common SFNT data from a face.
   *
   * @input:
   *   face ::
   *     A handle to the target face object.
   *
   * @note:
   *   This function does NOT destroy the face object.
   */
  typedef void
  (*TT_Done_Face_Func)( TT_Face  face );

  /**************************************************************************
   *
   * @functype:
   *   TT_Load_Any_Func
   *
   * @description:
   *   Load any font table into client memory.
   *
   * @input:
   *   face ::
   *     The face object to look for.
   *
   *   tag ::
   *     The tag of table to load.  Use the value 0 if you want to access the
   *     whole font file, else set this parameter to a valid TrueType table
   *     tag that you can forge with the MAKE_TT_TAG macro.
   *
   *   offset ::
   *     The starting offset in the table (or the file if tag == 0).
   *
   *   length ::
   *     The address of the decision variable:
   *
   *     If `length == NULL`: Loads the whole table.  Returns an error if
   *     'offset' == 0!
   *
   *     If `*length == 0`: Exits immediately; returning the length of the
   *     given table or of the font file, depending on the value of 'tag'.
   *
   *     If `*length != 0`: Loads the next 'length' bytes of table or font,
   *     starting at offset 'offset' (in table or font too).
   *
   * @output:
   *   buffer ::
   *     The address of target buffer.
   *
   * @return:
   *   TrueType error code.  0 means success.
   */
  typedef FT_Error
  (*TT_Load_Any_Func)( TT_Face    face,
                       FT_ULong   tag,
                       FT_Long    offset,
                       FT_Byte   *buffer,
                       FT_ULong*  length );

  /**************************************************************************
   *
   * @functype:
   *   TT_Find_SBit_Image_Func
   *
   * @description:
   *   Check whether an embedded bitmap (an 'sbit') exists for a given glyph,
   *   at a given strike.
   *
   * @input:
   *   face ::
   *     The target face object.
   *
   *   glyph_index ::
   *     The glyph index.
   *
   *   strike_index ::
   *     The current strike index.
   *
   * @output:
   *   arange ::
   *     The SBit range containing the glyph index.
   *
   *   astrike ::
   *     The SBit strike containing the glyph index.
   *
   *   aglyph_offset ::
   *     The offset of the glyph data in 'EBDT' table.
   *
   * @return:
   *   FreeType error code.  0 means success.  Returns
   *   SFNT_Err_Invalid_Argument if no sbit exists for the requested glyph.
   */
  typedef FT_Error
  (*TT_Find_SBit_Image_Func)( TT_Face          face,
                              FT_UInt          glyph_index,
                              FT_ULong         strike_index,
                              TT_SBit_Range   *arange,
                              TT_SBit_Strike  *astrike,
                              FT_ULong        *aglyph_offset );

  /**************************************************************************
   *
   * @functype:
   *   TT_Load_SBit_Metrics_Func
   *
   * @description:
   *   Get the big metrics for a given embedded bitmap.
   *
   * @input:
   *   stream ::
   *     The input stream.
   *
   *   range ::
   *     The SBit range containing the glyph.
   *
   * @output:
   *   big_metrics ::
   *     A big SBit metrics structure for the glyph.
   *
   * @return:
   *   FreeType error code.  0 means success.
   *
   * @note:
   *   The stream cursor must be positioned at the glyph's offset within the
   *   'EBDT' table before the call.
   *
   *   If the image format uses variable metrics, the stream cursor is
   *   positioned just after the metrics header in the 'EBDT' table on
   *   function exit.
   */
  typedef FT_Error
  (*TT_Load_SBit_Metrics_Func)( FT_Stream        stream,
                                TT_SBit_Range    range,
                                TT_SBit_Metrics  metrics );

  /**************************************************************************
   *
   * @functype:
   *   TT_Load_SBit_Image_Func
   *
   * @description:
   *   Load a given glyph sbit image from the font resource.  This also
   *   returns its metrics.
   *
   * @input:
   *   face ::
   *     The target face object.
   *
   *   strike_index ::
   *     The strike index.
   *
   *   glyph_index ::
   *     The current glyph index.
   *
   *   load_flags ::
   *     The current load flags.
   *
   *   stream ::
   *     The input stream.
   *
   * @output:
   *   amap ::
   *     The target pixmap.
   *
   *   ametrics ::
   *     A big sbit metrics structure for the glyph image.
   *
   * @return:
   *   FreeType error code.  0 means success.  Returns an error if no glyph
   *   sbit exists for the index.
   *
   * @note:
   *   The `map.buffer` field is always freed before the glyph is loaded.
   */
  typedef FT_Error
  (*TT_Load_SBit_Image_Func)( TT_Face              face,
                              FT_ULong             strike_index,
                              FT_UInt              glyph_index,
                              FT_UInt              load_flags,
                              FT_Stream            stream,
                              FT_Bitmap           *amap,
                              TT_SBit_MetricsRec  *ametrics );

  /**************************************************************************
   *
   * @functype:
   *   TT_Set_SBit_Strike_Func
   *
   * @description:
   *   Select an sbit strike for a given size request.
   *
   * @input:
   *   face ::
   *     The target face object.
   *
   *   req ::
   *     The size request.
   *
   * @output:
   *   astrike_index ::
   *     The index of the sbit strike.
   *
   * @return:
   *   FreeType error code.  0 means success.  Returns an error if no sbit
   *   strike exists for the selected ppem values.
   */
  typedef FT_Error
  (*TT_Set_SBit_Strike_Func)( TT_Face          face,
                              FT_Size_Request  req,
                              FT_ULong*        astrike_index );

  /**************************************************************************
   *
   * @functype:
   *   TT_Load_Strike_Metrics_Func
   *
   * @description:
   *   Load the metrics of a given strike.
   *
   * @input:
   *   face ::
   *     The target face object.
   *
   *   strike_index ::
   *     The strike index.
   *
   * @output:
   *   metrics ::
   *     the metrics of the strike.
   *
   * @return:
   *   FreeType error code.  0 means success.  Returns an error if no such
   *   sbit strike exists.
   */
  typedef FT_Error
  (*TT_Load_Strike_Metrics_Func)( TT_Face           face,
                                  FT_ULong          strike_index,
                                  FT_Size_Metrics*  metrics );

  /**************************************************************************
   *
   * @functype:
   *   TT_Get_PS_Name_Func
   *
   * @description:
   *   Get the PostScript glyph name of a glyph.
   *
   * @input:
   *   idx ::
   *     The glyph index.
   *
   *   PSname ::
   *     The address of a string pointer.  Will be `NULL` in case of error,
   *     otherwise it is a pointer to the glyph name.
   *
   *     You must not modify the returned string!
   *
   * @output:
   *   FreeType error code.  0 means success.
   */
  typedef FT_Error
  (*TT_Get_PS_Name_Func)( TT_Face      face,
                          FT_UInt      idx,
                          FT_String**  PSname );

  /**************************************************************************
   *
   * @functype:
   *   TT_Load_Metrics_Func
   *
   * @description:
   *   Load a metrics table, which is a table with a horizontal and a
   *   vertical version.
   *
   * @input:
   *   face ::
   *     A handle to the target face object.
   *
   *   stream ::
   *     The input stream.
   *
   *   vertical ::
   *     A boolean flag.  If set, load the vertical one.
   *
   * @return:
   *   FreeType error code.  0 means success.
   */
  typedef FT_Error
  (*TT_Load_Metrics_Func)( TT_Face    face,
                           FT_Stream  stream,
                           FT_Bool    vertical );

  /**************************************************************************
   *
   * @functype:
   *   TT_Get_Metrics_Func
   *
   * @description:
   *   Load the horizontal or vertical header in a face object.
   *
   * @input:
   *   face ::
   *     A handle to the target face object.
   *
   *   vertical ::
   *     A boolean flag.  If set, load vertical metrics.
   *
   *   gindex ::
   *     The glyph index.
   *
   * @output:
   *   abearing ::
   *     The horizontal (or vertical) bearing.  Set to zero in case of error.
   *
   *   aadvance ::
   *     The horizontal (or vertical) advance.  Set to zero in case of error.
   */
  typedef void
  (*TT_Get_Metrics_Func)( TT_Face     face,
                          FT_Bool     vertical,
                          FT_UInt     gindex,
                          FT_Short*   abearing,
                          FT_UShort*  aadvance );

  /**************************************************************************
   *
   * @functype:
   *   TT_Set_Palette_Func
   *
   * @description:
   *   Load the colors into `face->palette` for a given palette index.
   *
   * @input:
   *   face ::
   *     The target face object.
   *
   *   idx ::
   *     The palette index.
   *
   * @return:
   *   FreeType error code.  0 means success.
   */
  typedef FT_Error
  (*TT_Set_Palette_Func)( TT_Face  face,
                          FT_UInt  idx );

  /**************************************************************************
   *
   * @functype:
   *   TT_Get_Colr_Layer_Func
   *
   * @description:
   *   Iteratively get the color layer data of a given glyph index.
   *
   * @input:
   *   face ::
   *     The target face object.
   *
   *   base_glyph ::
   *     The glyph index the colored glyph layers are associated with.
   *
   * @inout:
   *   iterator ::
   *     An @FT_LayerIterator object.  For the first call you should set
   *     `iterator->p` to `NULL`.  For all following calls, simply use the
   *     same object again.
   *
   * @output:
   *   aglyph_index ::
   *     The glyph index of the current layer.
   *
   *   acolor_index ::
   *     The color index into the font face's color palette of the current
   *     layer.  The value 0xFFFF is special; it doesn't reference a palette
   *     entry but indicates that the text foreground color should be used
   *     instead (to be set up by the application outside of FreeType).
   *
   * @return:
   *   Value~1 if everything is OK.  If there are no more layers (or if there
   *   are no layers at all), value~0 gets returned.  In case of an error,
   *   value~0 is returned also.
   */
  typedef FT_Bool
  (*TT_Get_Colr_Layer_Func)( TT_Face            face,
                             FT_UInt            base_glyph,
                             FT_UInt           *aglyph_index,
                             FT_UInt           *acolor_index,
                             FT_LayerIterator*  iterator );

  /**************************************************************************
   *
   * @functype:
   *   TT_Blend_Colr_Func
   *
   * @description:
   *   Blend the bitmap in `new_glyph` into `base_glyph` using the color
   *   specified by `color_index`.  If `color_index` is 0xFFFF, use
   *   `face->foreground_color` if `face->have_foreground_color` is set.
   *   Otherwise check `face->palette_data.palette_flags`: If present and
   *   @FT_PALETTE_FOR_DARK_BACKGROUND is set, use BGRA value 0xFFFFFFFF
   *   (white opaque).  Otherwise use BGRA value 0x000000FF (black opaque).
   *
   * @input:
   *   face ::
   *     The target face object.
   *
   *   color_index ::
   *     Color index from the COLR table.
   *
   *   base_glyph ::
   *     Slot for bitmap to be merged into.  The underlying bitmap may get
   *     reallocated.
   *
   *   new_glyph ::
   *     Slot to be incooperated into `base_glyph`.
   *
   * @return:
   *   FreeType error code.  0 means success.  Returns an error if
   *   color_index is invalid or reallocation fails.
   */
  typedef FT_Error
  (*TT_Blend_Colr_Func)( TT_Face       face,
                         FT_UInt       color_index,
                         FT_GlyphSlot  base_glyph,
                         FT_GlyphSlot  new_glyph );

  /**************************************************************************
   *
   * @functype:
   *   TT_Get_Name_Func
   *
   * @description:
   *   From the 'name' table, return a given ENGLISH name record in ASCII.
   *
   * @input:
   *   face ::
   *     A handle to the source face object.
   *
   *   nameid ::
   *     The name id of the name record to return.
   *
   * @inout:
   *   name ::
   *     The address of an allocated string pointer.  `NULL` if no name is
   *     present.
   *
   * @return:
   *   FreeType error code.  0 means success.
   */
  typedef FT_Error
  (*TT_Get_Name_Func)( TT_Face      face,
                       FT_UShort    nameid,
                       FT_String**  name );

  /**************************************************************************
   *
   * @functype:
   *   TT_Get_Name_ID_Func
   *
   * @description:
   *   Search whether an ENGLISH version for a given name ID is in the 'name'
   *   table.
   *
   * @input:
   *   face ::
   *     A handle to the source face object.
   *
   *   nameid ::
   *     The name id of the name record to return.
   *
   * @output:
   *   win ::
   *     If non-negative, an index into the 'name' table with the
   *     corresponding (3,1) or (3,0) Windows entry.
   *
   *   apple ::
   *     If non-negative, an index into the 'name' table with the
   *     corresponding (1,0) Apple entry.
   *
   * @return:
   *   1 if there is either a win or apple entry (or both), 0 otheriwse.
   */
  typedef FT_Bool
  (*TT_Get_Name_ID_Func)( TT_Face    face,
                          FT_UShort  nameid,
                          FT_Int    *win,
                          FT_Int    *apple );

  /**************************************************************************
   *
   * @functype:
   *   TT_Load_Table_Func
   *
   * @description:
   *   Load a given TrueType table.
   *
   * @input:
   *   face ::
   *     A handle to the target face object.
   *
   *   stream ::
   *     The input stream.
   *
   * @return:
   *   FreeType error code.  0 means success.
   *
   * @note:
   *   The function uses `face->goto_table` to seek the stream to the start
   *   of the table, except while loading the font directory.
   */
  typedef FT_Error
  (*TT_Load_Table_Func)( TT_Face    face,
                         FT_Stream  stream );

  /**************************************************************************
   *
   * @functype:
   *   TT_Free_Table_Func
   *
   * @description:
   *   Free a given TrueType table.
   *
   * @input:
   *   face ::
   *     A handle to the target face object.
   */
  typedef void
  (*TT_Free_Table_Func)( TT_Face  face );

  /*
   * @functype:
   *    TT_Face_GetKerningFunc
   *
   * @description:
   *    Return the horizontal kerning value between two glyphs.
   *
   * @input:
   *    face ::
   *      A handle to the source face object.
   *
   *    left_glyph ::
   *      The left glyph index.
   *
   *    right_glyph ::
   *      The right glyph index.
   *
   * @return:
   *    The kerning value in font units.
   */
  typedef FT_Int
  (*TT_Face_GetKerningFunc)( TT_Face  face,
                             FT_UInt  left_glyph,
                             FT_UInt  right_glyph );

  /**************************************************************************
   *
   * @struct:
   *   SFNT_Interface
   *
   * @description:
   *   This structure holds pointers to the functions used to load and free
   *   the basic tables that are required in a 'sfnt' font file.
   *
   * @fields:
   *   Check the various xxx_Func() descriptions for details.
   */
  typedef struct  SFNT_Interface_
  {
    TT_Loader_GotoTableFunc      goto_table;

    TT_Init_Face_Func            init_face;
    TT_Load_Face_Func            load_face;
    TT_Done_Face_Func            done_face;
    FT_Module_Requester          get_interface;

    TT_Load_Any_Func             load_any;

    /* these functions are called by `load_face' but they can also  */
    /* be called from external modules, if there is a need to do so */
    TT_Load_Table_Func           load_head;
    TT_Load_Metrics_Func         load_hhea;
    TT_Load_Table_Func           load_cmap;
    TT_Load_Table_Func           load_maxp;
    TT_Load_Table_Func           load_os2;
    TT_Load_Table_Func           load_post;

    TT_Load_Table_Func           load_name;
    TT_Free_Table_Func           free_name;

    /* this field was called `load_kerning' up to version 2.1.10 */
    TT_Load_Table_Func           load_kern;

    TT_Load_Table_Func           load_gasp;
    TT_Load_Table_Func           load_pclt;

    /* see `ttload.h'; this field was called `load_bitmap_header' up to */
    /* version 2.1.10                                                   */
    TT_Load_Table_Func           load_bhed;

    TT_Load_SBit_Image_Func      load_sbit_image;

    /* see `ttpost.h' */
    TT_Get_PS_Name_Func          get_psname;
    TT_Free_Table_Func           free_psnames;

    /* starting here, the structure differs from version 2.1.7 */

    /* this field was introduced in version 2.1.8, named `get_psname' */
    TT_Face_GetKerningFunc       get_kerning;

    /* new elements introduced after version 2.1.10 */

    /* load the font directory, i.e., the offset table and */
    /* the table directory                                 */
    TT_Load_Table_Func           load_font_dir;
    TT_Load_Metrics_Func         load_hmtx;

    TT_Load_Table_Func           load_eblc;
    TT_Free_Table_Func           free_eblc;

    TT_Set_SBit_Strike_Func      set_sbit_strike;
    TT_Load_Strike_Metrics_Func  load_strike_metrics;

    TT_Load_Table_Func           load_cpal;
    TT_Load_Table_Func           load_colr;
    TT_Free_Table_Func           free_cpal;
    TT_Free_Table_Func           free_colr;
    TT_Set_Palette_Func          set_palette;
    TT_Get_Colr_Layer_Func       get_colr_layer;
    TT_Blend_Colr_Func           colr_blend;

    TT_Get_Metrics_Func          get_metrics;

    TT_Get_Name_Func             get_name;
    TT_Get_Name_ID_Func          get_name_id;

  } SFNT_Interface;

  /* transitional */
  typedef SFNT_Interface*   SFNT_Service;

#define FT_DEFINE_SFNT_INTERFACE(        \
          class_,                        \
          goto_table_,                   \
          init_face_,                    \
          load_face_,                    \
          done_face_,                    \
          get_interface_,                \
          load_any_,                     \
          load_head_,                    \
          load_hhea_,                    \
          load_cmap_,                    \
          load_maxp_,                    \
          load_os2_,                     \
          load_post_,                    \
          load_name_,                    \
          free_name_,                    \
          load_kern_,                    \
          load_gasp_,                    \
          load_pclt_,                    \
          load_bhed_,                    \
          load_sbit_image_,              \
          get_psname_,                   \
          free_psnames_,                 \
          get_kerning_,                  \
          load_font_dir_,                \
          load_hmtx_,                    \
          load_eblc_,                    \
          free_eblc_,                    \
          set_sbit_strike_,              \
          load_strike_metrics_,          \
          load_cpal_,                    \
          load_colr_,                    \
          free_cpal_,                    \
          free_colr_,                    \
          set_palette_,                  \
          get_colr_layer_,               \
          colr_blend_,                   \
          get_metrics_,                  \
          get_name_,                     \
          get_name_id_ )                 \
  static const SFNT_Interface  class_ =  \
  {                                      \
    goto_table_,                         \
    init_face_,                          \
    load_face_,                          \
    done_face_,                          \
    get_interface_,                      \
    load_any_,                           \
    load_head_,                          \
    load_hhea_,                          \
    load_cmap_,                          \
    load_maxp_,                          \
    load_os2_,                           \
    load_post_,                          \
    load_name_,                          \
    free_name_,                          \
    load_kern_,                          \
    load_gasp_,                          \
    load_pclt_,                          \
    load_bhed_,                          \
    load_sbit_image_,                    \
    get_psname_,                         \
    free_psnames_,                       \
    get_kerning_,                        \
    load_font_dir_,                      \
    load_hmtx_,                          \
    load_eblc_,                          \
    free_eblc_,                          \
    set_sbit_strike_,                    \
    load_strike_metrics_,                \
    load_cpal_,                          \
    load_colr_,                          \
    free_cpal_,                          \
    free_colr_,                          \
    set_palette_,                        \
    get_colr_layer_,                     \
    colr_blend_,                         \
    get_metrics_,                        \
    get_name_,                           \
    get_name_id_                         \
  };

FT_END_HEADER

#endif /* SFNT_H_ */

/* END */


text:
/****************************************************************************
 *
 * ftrfork.h
 *
 *   Embedded resource forks accessor (specification).
 *
 * Copyright (C) 2004-2020 by
 * Masatake YAMATO and Redhat K.K.
 *
 * This file is part of the FreeType project, and may only be used,
 * modified, and distributed under the terms of the FreeType project
 * license, LICENSE.TXT.  By continuing to use, modify, or distribute
 * this file you indicate that you have read the license and
 * understand and accept it fully.
 *
 */

/****************************************************************************
 * Development of the code in this file is support of
 * Information-technology Promotion Agency, Japan.
 */

#ifndef FTRFORK_H_
#define FTRFORK_H_

#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H

FT_BEGIN_HEADER

  /* Number of guessing rules supported in `FT_Raccess_Guess'.            */
  /* Don't forget to increment the number if you add a new guessing rule. */
#define FT_RACCESS_N_RULES  9

  /* A structure to describe a reference in a resource by its resource ID */
  /* and internal offset.  The `POST' resource expects to be concatenated */
  /* by the order of resource IDs instead of its appearance in the file.  */

  typedef struct  FT_RFork_Ref_
  {
    FT_Short  res_id;
    FT_Long   offset;

  } FT_RFork_Ref;

#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
  typedef FT_Error
  (*ft_raccess_guess_func)( FT_Library  library,
                            FT_Stream   stream,
                            char       *base_file_name,
                            char      **result_file_name,
                            FT_Long    *result_offset );

  typedef enum  FT_RFork_Rule_ {
    FT_RFork_Rule_invalid = -2,
    FT_RFork_Rule_uknown, /* -1 */
    FT_RFork_Rule_apple_double,
    FT_RFork_Rule_apple_single,
    FT_RFork_Rule_darwin_ufs_export,
    FT_RFork_Rule_darwin_newvfs,
    FT_RFork_Rule_darwin_hfsplus,
    FT_RFork_Rule_vfat,
    FT_RFork_Rule_linux_cap,
    FT_RFork_Rule_linux_double,
    FT_RFork_Rule_linux_netatalk
  } FT_RFork_Rule;

  /* For fast translation between rule index and rule type,
   * the macros FT_RFORK_xxx should be kept consistent with the
   * raccess_guess_funcs table
   */
  typedef struct ft_raccess_guess_rec_ {
    ft_raccess_guess_func  func;
    FT_RFork_Rule          type;
  } ft_raccess_guess_rec;

#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type )  \
          static const type name[] = {
#define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix )  \
          { raccess_guess_ ## func_suffix,                           \
            FT_RFork_Rule_ ## type_suffix },
  /* this array is a storage, thus a final `;' is needed */
#define CONST_FT_RFORK_RULE_ARRAY_END  };

#endif /* FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */

  /**************************************************************************
   *
   * @function:
   *   FT_Raccess_Guess
   *
   * @description:
   *   Guess a file name and offset where the actual resource fork is stored.
   *   The macro FT_RACCESS_N_RULES holds the number of guessing rules; the
   *   guessed result for the Nth rule is represented as a triplet: a new
   *   file name (new_names[N]), a file offset (offsets[N]), and an error
   *   code (errors[N]).
   *
   * @input:
   *   library ::
   *     A FreeType library instance.
   *
   *   stream ::
   *     A file stream containing the resource fork.
   *
   *   base_name ::
   *     The (base) file name of the resource fork used for some guessing
   *     rules.
   *
   * @output:
   *   new_names ::
   *     An array of guessed file names in which the resource forks may
   *     exist.  If 'new_names[N]' is `NULL`, the guessed file name is equal
   *     to `base_name`.
   *
   *   offsets ::
   *     An array of guessed file offsets.  'offsets[N]' holds the file
   *     offset of the possible start of the resource fork in file
   *     'new_names[N]'.
   *
   *   errors ::
   *     An array of FreeType error codes.  'errors[N]' is the error code of
   *     Nth guessing rule function.  If 'errors[N]' is not FT_Err_Ok,
   *     'new_names[N]' and 'offsets[N]' are meaningless.
   */
  FT_BASE( void )
  FT_Raccess_Guess( FT_Library  library,
                    FT_Stream   stream,
                    char*       base_name,
                    char**      new_names,
                    FT_Long*    offsets,
                    FT_Error*   errors );

  /**************************************************************************
   *
   * @function:
   *   FT_Raccess_Get_HeaderInfo
   *
   * @description:
   *   Get the information from the header of resource fork.  The information
   *   includes the file offset where the resource map starts, and the file
   *   offset where the resource data starts.  `FT_Raccess_Get_DataOffsets`
   *   requires these two data.
   *
   * @input:
   *   library ::
   *     A FreeType library instance.
   *
   *   stream ::
   *     A file stream containing the resource fork.
   *
   *   rfork_offset ::
   *     The file offset where the resource fork starts.
   *
   * @output:
   *   map_offset ::
   *     The file offset where the resource map starts.
   *
   *   rdata_pos ::
   *     The file offset where the resource data starts.
   *
   * @return:
   *   FreeType error code.  FT_Err_Ok means success.
   */
  FT_BASE( FT_Error )
  FT_Raccess_Get_HeaderInfo( FT_Library  library,
                             FT_Stream   stream,
                             FT_Long     rfork_offset,
                             FT_Long    *map_offset,
                             FT_Long    *rdata_pos );

  /**************************************************************************
   *
   * @function:
   *   FT_Raccess_Get_DataOffsets
   *
   * @description:
   *   Get the data offsets for a tag in a resource fork.  Offsets are stored
   *   in an array because, in some cases, resources in a resource fork have
   *   the same tag.
   *
   * @input:
   *   library ::
   *     A FreeType library instance.
   *
   *   stream ::
   *     A file stream containing the resource fork.
   *
   *   map_offset ::
   *     The file offset where the resource map starts.
   *
   *   rdata_pos ::
   *     The file offset where the resource data starts.
   *
   *   tag ::
   *     The resource tag.
   *
   *   sort_by_res_id ::
   *     A Boolean to sort the fragmented resource by their ids.  The
   *     fragmented resources for 'POST' resource should be sorted to restore
   *     Type1 font properly.  For 'sfnt' resources, sorting may induce a
   *     different order of the faces in comparison to that by QuickDraw API.
   *
   * @output:
   *   offsets ::
   *     The stream offsets for the resource data specified by 'tag'.  This
   *     array is allocated by the function, so you have to call @ft_mem_free
   *     after use.
   *
   *   count ::
   *     The length of offsets array.
   *
   * @return:
   *   FreeType error code.  FT_Err_Ok means success.
   *
   * @note:
   *   Normally you should use `FT_Raccess_Get_HeaderInfo` to get the value
   *   for `map_offset` and `rdata_pos`.
   */
  FT_BASE( FT_Error )
  FT_Raccess_Get_DataOffsets( FT_Library  library,
                              FT_Stream   stream,
                              FT_Long     map_offset,
                              FT_Long     rdata_pos,
                              FT_Long     tag,
                              FT_Bool     sort_by_res_id,
                              FT_Long   **offsets,
                              FT_Long    *count );

FT_END_HEADER

#endif /* FTRFORK_H_ */

/* END */


text:
/****************************************************************************
 *
 * ftcalc.h
 *
 *   Arithmetic computations (specification).
 *
 * Copyright (C) 1996-2020 by
 * David Turner, Robert Wilhelm, and Werner Lemberg.
 *
 * This file is part of the FreeType project, and may only be used,
 * modified, and distributed under the terms of the FreeType project
 * license, LICENSE.TXT.  By continuing to use, modify, or distribute
 * this file you indicate that you have read the license and
 * understand and accept it fully.
 *
 */

#ifndef FTCALC_H_
#define FTCALC_H_

#include <ft2build.h>
#include FT_FREETYPE_H

FT_BEGIN_HEADER

  /**************************************************************************
   *
   * FT_MulDiv() and FT_MulFix() are declared in freetype.h.
   *
   */

#ifndef  FT_CONFIG_OPTION_NO_ASSEMBLER
  /* Provide assembler fragments for performance-critical functions. */
  /* These must be defined `static __inline__' with GCC.             */

#if defined( __CC_ARM ) || defined( __ARMCC__ )  /* RVCT */

#define FT_MULFIX_ASSEMBLER  FT_MulFix_arm

  /* documentation is in freetype.h */

  static __inline FT_Int32
  FT_MulFix_arm( FT_Int32  a,
                 FT_Int32  b )
  {
    FT_Int32  t, t2;

    __asm
    {
      smull t2, t,  b,  a           /* (lo=t2,hi=t) = a*b */
      mov   a,  t,  asr #31         /* a   = (hi >> 31) */
      add   a,  a,  #0x8000         /* a  += 0x8000 */
      adds  t2, t2, a               /* t2 += a */
      adc   t,  t,  #0              /* t  += carry */
      mov   a,  t2, lsr #16         /* a   = t2 >> 16 */
      orr   a,  a,  t,  lsl #16     /* a  |= t << 16 */
    }
    return a;
  }

#endif /* __CC_ARM || __ARMCC__ */

#ifdef __GNUC__

#if defined( __arm__ )                                 && \
    ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \
    !( defined( __CC_ARM ) || defined( __ARMCC__ ) )

#define FT_MULFIX_ASSEMBLER  FT_MulFix_arm

  /* documentation is in freetype.h */

  static __inline__ FT_Int32
  FT_MulFix_arm( FT_Int32  a,
                 FT_Int32  b )
  {
    FT_Int32  t, t2;

    __asm__ __volatile__ (
      "smull  %1, %2, %4, %3\n\t"       /* (lo=%1,hi=%2) = a*b */
      "mov    %0, %2, asr #31\n\t"      /* %0  = (hi >> 31) */
#if defined( __clang__ ) && defined( __thumb2__ )
      "add.w  %0, %0, #0x8000\n\t"      /* %0 += 0x8000 */
#else
      "add    %0, %0, #0x8000\n\t"      /* %0 += 0x8000 */
#endif
      "adds   %1, %1, %0\n\t"           /* %1 += %0 */
      "adc    %2, %2, #0\n\t"           /* %2 += carry */
      "mov    %0, %1, lsr #16\n\t"      /* %0  = %1 >> 16 */
      "orr    %0, %0, %2, lsl #16\n\t"  /* %0 |= %2 << 16 */
      : "=r"(a), "=&r"(t2), "=&r"(t)
      : "r"(a), "r"(b)
      : "cc" );
    return a;
  }

#endif /* __arm__                      && */
       /* ( __thumb2__ || !__thumb__ ) && */
       /* !( __CC_ARM || __ARMCC__ )      */

#if defined( __i386__ )

#define FT_MULFIX_ASSEMBLER  FT_MulFix_i386

  /* documentation is in freetype.h */

  static __inline__ FT_Int32
  FT_MulFix_i386( FT_Int32  a,
                  FT_Int32  b )
  {
    FT_Int32  result;

    __asm__ __volatile__ (
      "imul  %%edx\n"
      "movl  %%edx, %%ecx\n"
      "sarl  $31, %%ecx\n"
      "addl  $0x8000, %%ecx\n"
      "addl  %%ecx, %%eax\n"
      "adcl  $0, %%edx\n"
      "shrl  $16, %%eax\n"
      "shll  $16, %%edx\n"
      "addl  %%edx, %%eax\n"
      : "=a"(result), "=d"(b)
      : "a"(a), "d"(b)
      : "%ecx", "cc" );
    return result;
  }

#endif /* i386 */

#endif /* __GNUC__ */

#ifdef _MSC_VER /* Visual C++ */

#ifdef _M_IX86

#define FT_MULFIX_ASSEMBLER  FT_MulFix_i386

  /* documentation is in freetype.h */

  static __inline FT_Int32
  FT_MulFix_i386( FT_Int32  a,
                  FT_Int32  b )
  {
    FT_Int32  result;

    __asm
    {
      mov eax, a
      mov edx, b
      imul edx
      mov ecx, edx
      sar ecx, 31
      add ecx, 8000h
      add eax, ecx
      adc edx, 0
      shr eax, 16
      shl edx, 16
      add eax, edx
      mov result, eax
    }
    return result;
  }

#endif /* _M_IX86 */

#endif /* _MSC_VER */

#if defined( __GNUC__ ) && defined( __x86_64__ )

#define FT_MULFIX_ASSEMBLER  FT_MulFix_x86_64

  static __inline__ FT_Int32
  FT_MulFix_x86_64( FT_Int32  a,
                    FT_Int32  b )
  {
    /* Temporarily disable the warning that C90 doesn't support */
    /* `long long'.                                             */
#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlong-long"
#endif

#if 1
    /* Technically not an assembly fragment, but GCC does a really good */
    /* job at inlining it and generating good machine code for it.      */
    long long  ret, tmp;

    ret  = (long long)a * b;
    tmp  = ret >> 63;
    ret += 0x8000 + tmp;

    return (FT_Int32)( ret >> 16 );
#else

    /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine  */
    /* code from the lines below.  The main issue is that `wide_a' is not  */
    /* properly initialized by sign-extending `a'.  Instead, the generated */
    /* machine code assumes that the register that contains `a' on input   */
    /* can be used directly as a 64-bit value, which is wrong most of the  */
    /* time.                                                               */
    long long  wide_a = (long long)a;
    long long  wide_b = (long long)b;
    long long  result;

    __asm__ __volatile__ (
      "imul %2, %1\n"
      "mov %1, %0\n"
      "sar $63, %0\n"
      "lea 0x8000(%1, %0), %0\n"
      "sar $16, %0\n"
      : "=&r"(result), "=&r"(wide_a)
      : "r"(wide_b)
      : "cc" );

    return (FT_Int32)result;
#endif

#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 )
#pragma GCC diagnostic pop
#endif
  }

#endif /* __GNUC__ && __x86_64__ */

#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */

#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
#ifdef FT_MULFIX_ASSEMBLER
#define FT_MulFix( a, b )  FT_MULFIX_ASSEMBLER( (FT_Int32)(a), (FT_Int32)(b) )
#endif
#endif

  /**************************************************************************
   *
   * @function:
   *   FT_MulDiv_No_Round
   *
   * @description:
   *   A very simple function used to perform the computation '(a*b)/c'
   *   (without rounding) with maximum accuracy (it uses a 64-bit
   *   intermediate integer whenever necessary).
   *
   *   This function isn't necessarily as fast as some processor-specific
   *   operations, but is at least completely portable.
   *
   * @input:
   *   a ::
   *     The first multiplier.
   *   b ::
   *     The second multiplier.
   *   c ::
   *     The divisor.
   *
   * @return:
   *   The result of '(a*b)/c'.  This function never traps when trying to
   *   divide by zero; it simply returns 'MaxInt' or 'MinInt' depending on
   *   the signs of 'a' and 'b'.
   */
  FT_BASE( FT_Long )
  FT_MulDiv_No_Round( FT_Long  a,
                      FT_Long  b,
                      FT_Long  c );

  /*
   * A variant of FT_Matrix_Multiply which scales its result afterwards.  The
   * idea is that both `a' and `b' are scaled by factors of 10 so that the
   * values are as precise as possible to get a correct result during the
   * 64bit multiplication.  Let `sa' and `sb' be the scaling factors of `a'
   * and `b', respectively, then the scaling factor of the result is `sa*sb'.
   */
  FT_BASE( void )
  FT_Matrix_Multiply_Scaled( const FT_Matrix*  a,
                             FT_Matrix        *b,
                             FT_Long           scaling );

  /*
   * Check a matrix.  If the transformation would lead to extreme shear or
   * extreme scaling, for example, return 0.  If everything is OK, return 1.
   *
   * Based on geometric considerations we use the following inequality to
   * identify a degenerate matrix.
   *
   *   50 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2
   *
   * Value 50 is heuristic.
   */
  FT_BASE( FT_Bool )
  FT_Matrix_Check( const FT_Matrix*  matrix );

  /*
   * A variant of FT_Vector_Transform.  See comments for
   * FT_Matrix_Multiply_Scaled.
   */
  FT_BASE( void )
  FT_Vector_Transform_Scaled( FT_Vector*        vector,
                              const FT_Matrix*  matrix,
                              FT_Long           scaling );

  /*
   * This function normalizes a vector and returns its original length.  The
   * normalized vector is a 16.16 fixed-point unit vector with length close
   * to 0x10000.  The accuracy of the returned length is limited to 16 bits
   * also.  The function utilizes quick inverse square root approximation
   * without divisions and square roots relying on Newton's iterations
   * instead.
   */
  FT_BASE( FT_UInt32 )
  FT_Vector_NormLen( FT_Vector*  vector );

  /*
   * Return -1, 0, or +1, depending on the orientation of a given corner.  We
   * use the Cartesian coordinate system, with positive vertical values going
   * upwards.  The function returns +1 if the corner turns to the left, -1 to
   * the right, and 0 for undecidable cases.
   */
  FT_BASE( FT_Int )
  ft_corner_orientation( FT_Pos  in_x,
                         FT_Pos  in_y,
                         FT_Pos  out_x,
                         FT_Pos  out_y );

  /*
   * Return TRUE if a corner is flat or nearly flat.  This is equivalent to
   * saying that the corner point is close to its neighbors, or inside an
   * ellipse defined by the neighbor focal points to be more precise.
   */
  FT_BASE( FT_Int )
  ft_corner_is_flat( FT_Pos  in_x,
                     FT_Pos  in_y,
                     FT_Pos  out_x,
                     FT_Pos  out_y );

  /*
   * Return the most significant bit index.
   */

#ifndef  FT_CONFIG_OPTION_NO_ASSEMBLER

#if defined( __GNUC__ )                                          && \
    ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) )

#if FT_SIZEOF_INT == 4

#define FT_MSB( x )  ( 31 - __builtin_clz( x ) )

#elif FT_SIZEOF_LONG == 4

#define FT_MSB( x )  ( 31 - __builtin_clzl( x ) )

#endif /* __GNUC__ */

#elif defined( _MSC_VER ) && ( _MSC_VER >= 1400 )

#if FT_SIZEOF_INT == 4

#include <intrin.h>
#pragma intrinsic( _BitScanReverse )

  static __inline FT_Int32
  FT_MSB_i386( FT_UInt32  x )
  {
    unsigned long  where;

    _BitScanReverse( &where, x );

    return (FT_Int32)where;
  }

#define FT_MSB( x )  ( FT_MSB_i386( x ) )

#endif

#endif /* _MSC_VER */

#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */

#ifndef FT_MSB

  FT_BASE( FT_Int )
  FT_MSB( FT_UInt32  z );

#endif

  /*
   * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
   * two fixed-point arguments instead.
   */
  FT_BASE( FT_Fixed )
  FT_Hypot( FT_Fixed  x,
            FT_Fixed  y );

#if 0

  /**************************************************************************
   *
   * @function:
   *   FT_SqrtFixed
   *
   * @description:
   *   Computes the square root of a 16.16 fixed-point value.
   *
   * @input:
   *   x ::
   *     The value to compute the root for.
   *
   * @return:
   *   The result of 'sqrt(x)'.
   *
   * @note:
   *   This function is not very fast.
   */
  FT_BASE( FT_Int32 )
  FT_SqrtFixed( FT_Int32  x );

#endif /* 0 */

#define INT_TO_F26DOT6( x )    ( (FT_Long)(x) * 64  )    /* << 6  */
#define INT_TO_F2DOT14( x )    ( (FT_Long)(x) * 16384 )  /* << 14 */
#define INT_TO_FIXED( x )      ( (FT_Long)(x) * 65536 )  /* << 16 */
#define F2DOT14_TO_FIXED( x )  ( (FT_Long)(x) * 4 )      /* << 2  */
#define FIXED_TO_INT( x )      ( FT_RoundFix( x ) >> 16 )

#define ROUND_F26DOT6( x )     ( x >= 0 ? (    ( (x) + 32 ) & -64 )     \
                                        : ( -( ( 32 - (x) ) & -64 ) ) )

  /*
   * The following macros have two purposes.
   *
   * - Tag places where overflow is expected and harmless.
   *
   * - Avoid run-time sanitizer errors.
   *
   * Use with care!
   */
#define ADD_INT( a, b )                           \
          (FT_Int)( (FT_UInt)(a) + (FT_UInt)(b) )
#define SUB_INT( a, b )                           \
          (FT_Int)( (FT_UInt)(a) - (FT_UInt)(b) )
#define MUL_INT( a, b )                           \
          (FT_Int)( (FT_UInt)(a) * (FT_UInt)(b) )
#define NEG_INT( a )                              \
          (FT_Int)( (FT_UInt)0 - (FT_UInt)(a) )

#define ADD_LONG( a, b )                             \
          (FT_Long)( (FT_ULong)(a) + (FT_ULong)(b) )
#define SUB_LONG( a, b )                             \
          (FT_Long)( (FT_ULong)(a) - (FT_ULong)(b) )
#define MUL_LONG( a, b )                             \
          (FT_Long)( (FT_ULong)(a) * (FT_ULong)(b) )
#define NEG_LONG( a )                                \
          (FT_Long)( (FT_ULong)0 - (FT_ULong)(a) )

#define ADD_INT32( a, b )                               \
          (FT_Int32)( (FT_UInt32)(a) + (FT_UInt32)(b) )
#define SUB_INT32( a, b )                               \
          (FT_Int32)( (FT_UInt32)(a) - (FT_UInt32)(b) )
#define MUL_INT32( a, b )                               \
          (FT_Int32)( (FT_UInt32)(a) * (FT_UInt32)(b) )
#define NEG_INT32( a )                                  \
          (FT_Int32)( (FT_UInt32)0 - (FT_UInt32)(a) )

#ifdef FT_LONG64

#define ADD_INT64( a, b )                               \
          (FT_Int64)( (FT_UInt64)(a) + (FT_UInt64)(b) )
#define SUB_INT64( a, b )                               \
          (FT_Int64)( (FT_UInt64)(a) - (FT_UInt64)(b) )
#define MUL_INT64( a, b )                               \
          (FT_Int64)( (FT_UInt64)(a) * (FT_UInt64)(b) )
#define NEG_INT64( a )                                  \
          (FT_Int64)( (FT_UInt64)0 - (FT_UInt64)(a) )

#endif /* FT_LONG64 */

FT_END_HEADER

#endif /* FTCALC_H_ */

/* END */


text:
/****************************************************************************
 *
 * ftserv.h
 *
 *   The FreeType services (specification only).
 *
 * Copyright (C) 2003-2020 by
 * David Turner, Robert Wilhelm, and Werner Lemberg.
 *
 * This file is part of the FreeType project, and may only be used,
 * modified, and distributed under the terms of the FreeType project
 * license, LICENSE.TXT.  By continuing to use, modify, or distribute
 * this file you indicate that you have read the license and
 * understand and accept it fully.
 *
 */

  /**************************************************************************
   *
   * Each module can export one or more 'services'.  Each service is
   * identified by a constant string and modeled by a pointer; the latter
   * generally corresponds to a structure containing function pointers.
   *
   * Note that a service's data cannot be a mere function pointer because in
   * C it is possible that function pointers might be implemented differently
   * than data pointers (e.g. 48 bits instead of 32).
   *
   */

#ifndef FTSERV_H_
#define FTSERV_H_

FT_BEGIN_HEADER

  /**************************************************************************
   *
   * @macro:
   *   FT_FACE_FIND_SERVICE
   *
   * @description:
   *   This macro is used to look up a service from a face's driver module.
   *
   * @input:
   *   face ::
   *     The source face handle.
   *
   *   id ::
   *     A string describing the service as defined in the service's header
   *     files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
   *     'multi-masters').  It is automatically prefixed with
   *     `FT_SERVICE_ID_`.
   *
   * @output:
   *   ptr ::
   *     A variable that receives the service pointer.  Will be `NULL` if not
   *     found.
   */
#ifdef __cplusplus

#define FT_FACE_FIND_SERVICE( face, ptr, id )                               \
  FT_BEGIN_STMNT                                                            \
    FT_Module    module = FT_MODULE( FT_FACE( face )->driver );             \
    FT_Pointer   _tmp_  = NULL;                                             \
    FT_Pointer*  _pptr_ = (FT_Pointer*)&(ptr);                              \
                                                                            \
                                                                            \
    if ( module->clazz->get_interface )                                     \
      _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
    *_pptr_ = _tmp_;                                                        \
  FT_END_STMNT

#else /* !C++ */

#define FT_FACE_FIND_SERVICE( face, ptr, id )                               \
  FT_BEGIN_STMNT                                                            \
    FT_Module   module = FT_MODULE( FT_FACE( face )->driver );              \
    FT_Pointer  _tmp_  = NULL;                                              \
                                                                            \
    if ( module->clazz->get_interface )                                     \
      _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
    ptr = _tmp_;                                                            \
  FT_END_STMNT

#endif /* !C++ */

  /**************************************************************************
   *
   * @macro:
   *   FT_FACE_FIND_GLOBAL_SERVICE
   *
   * @description:
   *   This macro is used to look up a service from all modules.
   *
   * @input:
   *   face ::
   *     The source face handle.
   *
   *   id ::
   *     A string describing the service as defined in the service's header
   *     files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to
   *     'multi-masters').  It is automatically prefixed with
   *     `FT_SERVICE_ID_`.
   *
   * @output:
   *   ptr ::
   *     A variable that receives the service pointer.  Will be `NULL` if not
   *     found.
   */
#ifdef __cplusplus

#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )                  \
  FT_BEGIN_STMNT                                                      \
    FT_Module    module = FT_MODULE( FT_FACE( face )->driver );       \
    FT_Pointer   _tmp_;                                               \
    FT_Pointer*  _pptr_ = (FT_Pointer*)&(ptr);                        \
                                                                      \
                                                                      \
    _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
    *_pptr_ = _tmp_;                                                  \
  FT_END_STMNT

#else /* !C++ */

#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )                  \
  FT_BEGIN_STMNT                                                      \
    FT_Module   module = FT_MODULE( FT_FACE( face )->driver );        \
    FT_Pointer  _tmp_;                                                \
                                                                      \
                                                                      \
    _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
    ptr   = _tmp_;                                                    \
  FT_END_STMNT

#endif /* !C++ */

  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****         S E R V I C E   D E S C R I P T O R S                 *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /*
   * The following structure is used to _describe_ a given service to the
   * library.  This is useful to build simple static service lists.
   */
  typedef struct  FT_ServiceDescRec_
  {
    const char*  serv_id;     /* service name         */
    const void*  serv_data;   /* service pointer/data */

  } FT_ServiceDescRec;

  typedef const FT_ServiceDescRec*  FT_ServiceDesc;

  /**************************************************************************
   *
   * @macro:
   *   FT_DEFINE_SERVICEDESCREC1
   *   FT_DEFINE_SERVICEDESCREC2
   *   FT_DEFINE_SERVICEDESCREC3
   *   FT_DEFINE_SERVICEDESCREC4
   *   FT_DEFINE_SERVICEDESCREC5
   *   FT_DEFINE_SERVICEDESCREC6
   *   FT_DEFINE_SERVICEDESCREC7
   *   FT_DEFINE_SERVICEDESCREC8
   *   FT_DEFINE_SERVICEDESCREC9
   *   FT_DEFINE_SERVICEDESCREC10
   *
   * @description:
   *   Used to initialize an array of FT_ServiceDescRec structures.
   *
   *   The array will be allocated in the global scope (or the scope where
   *   the macro is used).
   */
#define FT_DEFINE_SERVICEDESCREC1( class_,                                  \
                                   serv_id_1, serv_data_1 )                 \
  static const FT_ServiceDescRec  class_[] =                                \
  {                                                                         \
    { serv_id_1, serv_data_1 },                                             \
    { NULL, NULL }                                                          \
  };

#define FT_DEFINE_SERVICEDESCREC2( class_,                                  \
                                   serv_id_1, serv_data_1,                  \
                                   serv_id_2, serv_data_2 )                 \
  static const FT_ServiceDescRec  class_[] =                                \
  {                                                                         \
    { serv_id_1, serv_data_1 },                                             \
    { serv_id_2, serv_data_2 },                                             \
    { NULL, NULL }                                                          \
  };

#define FT_DEFINE_SERVICEDESCREC3( class_,                                  \
                                   serv_id_1, serv_data_1,                  \
                                   serv_id_2, serv_data_2,                  \
                                   serv_id_3, serv_data_3 )                 \
  static const FT_ServiceDescRec  class_[] =                                \
  {                                                                         \
    { serv_id_1, serv_data_1 },                                             \
    { serv_id_2, serv_data_2 },                                             \
    { serv_id_3, serv_data_3 },                                             \
    { NULL, NULL }                                                          \
  };

#define FT_DEFINE_SERVICEDESCREC4( class_,                                  \
                                   serv_id_1, serv_data_1,                  \
                                   serv_id_2, serv_data_2,                  \
                                   serv_id_3, serv_data_3,                  \
                                   serv_id_4, serv_data_4 )                 \
  static const FT_ServiceDescRec  class_[] =                                \
  {                                                                         \
    { serv_id_1, serv_data_1 },                                             \
    { serv_id_2, serv_data_2 },                                             \
    { serv_id_3, serv_data_3 },                                             \
    { serv_id_4, serv_data_4 },                                             \
    { NULL, NULL }                                                          \
  };

#define FT_DEFINE_SERVICEDESCREC5( class_,                                  \
                                   serv_id_1, serv_data_1,                  \
                                   serv_id_2, serv_data_2,                  \
                                   serv_id_3, serv_data_3,                  \
                                   serv_id_4, serv_data_4,                  \
                                   serv_id_5, serv_data_5 )                 \
  static const FT_ServiceDescRec  class_[] =                                \
  {                                                                         \
    { serv_id_1, serv_data_1 },                                             \
    { serv_id_2, serv_data_2 },                                             \
    { serv_id_3, serv_data_3 },                                             \
    { serv_id_4, serv_data_4 },                                             \
    { serv_id_5, serv_data_5 },                                             \
    { NULL, NULL }                                                          \
  };

#define FT_DEFINE_SERVICEDESCREC6( class_,                                  \
                                   serv_id_1, serv_data_1,                  \
                                   serv_id_2, serv_data_2,                  \
                                   serv_id_3, serv_data_3,                  \
                                   serv_id_4, serv_data_4,                  \
                                   serv_id_5, serv_data_5,                  \
                                   serv_id_6, serv_data_6 )                 \
  static const FT_ServiceDescRec  class_[] =                                \
  {                                                                         \
    { serv_id_1, serv_data_1 },                                             \
    { serv_id_2, serv_data_2 },                                             \
    { serv_id_3, serv_data_3 },                                             \
    { serv_id_4, serv_data_4 },                                             \
    { serv_id_5, serv_data_5 },                                             \
    { serv_id_6, serv_data_6 },                                             \
    { NULL, NULL }                                                          \
  };

#define FT_DEFINE_SERVICEDESCREC7( class_,                                  \
                                   serv_id_1, serv_data_1,                  \
                                   serv_id_2, serv_data_2,                  \
                                   serv_id_3, serv_data_3,                  \
                                   serv_id_4, serv_data_4,                  \
                                   serv_id_5, serv_data_5,                  \
                                   serv_id_6, serv_data_6,                  \
                                   serv_id_7, serv_data_7 )                 \
  static const FT_ServiceDescRec  class_[] =                                \
  {                                                                         \
    { serv_id_1, serv_data_1 },                                             \
    { serv_id_2, serv_data_2 },                                             \
    { serv_id_3, serv_data_3 },                                             \
    { serv_id_4, serv_data_4 },                                             \
    { serv_id_5, serv_data_5 },                                             \
    { serv_id_6, serv_data_6 },                                             \
    { serv_id_7, serv_data_7 },                                             \
    { NULL, NULL }                                                          \
  };

#define FT_DEFINE_SERVICEDESCREC8( class_,                                  \
                                   serv_id_1, serv_data_1,                  \
                                   serv_id_2, serv_data_2,                  \
                                   serv_id_3, serv_data_3,                  \
                                   serv_id_4, serv_data_4,                  \
                                   serv_id_5, serv_data_5,                  \
                                   serv_id_6, serv_data_6,                  \
                                   serv_id_7, serv_data_7,                  \
                                   serv_id_8, serv_data_8 )                 \
  static const FT_ServiceDescRec  class_[] =                                \
  {                                                                         \
    { serv_id_1, serv_data_1 },                                             \
    { serv_id_2, serv_data_2 },                                             \
    { serv_id_3, serv_data_3 },                                             \
    { serv_id_4, serv_data_4 },                                             \
    { serv_id_5, serv_data_5 },                                             \
    { serv_id_6, serv_data_6 },                                             \
    { serv_id_7, serv_data_7 },                                             \
    { serv_id_8, serv_data_8 },                                             \
    { NULL, NULL }                                                          \
  };

#define FT_DEFINE_SERVICEDESCREC9( class_,                                  \
                                   serv_id_1, serv_data_1,                  \
                                   serv_id_2, serv_data_2,                  \
                                   serv_id_3, serv_data_3,                  \
                                   serv_id_4, serv_data_4,                  \
                                   serv_id_5, serv_data_5,                  \
                                   serv_id_6, serv_data_6,                  \
                                   serv_id_7, serv_data_7,                  \
                                   serv_id_8, serv_data_8,                  \
                                   serv_id_9, serv_data_9 )                 \
  static const FT_ServiceDescRec  class_[] =                                \
  {                                                                         \
    { serv_id_1, serv_data_1 },                                             \
    { serv_id_2, serv_data_2 },                                             \
    { serv_id_3, serv_data_3 },                                             \
    { serv_id_4, serv_data_4 },                                             \
    { serv_id_5, serv_data_5 },                                             \
    { serv_id_6, serv_data_6 },                                             \
    { serv_id_7, serv_data_7 },                                             \
    { serv_id_8, serv_data_8 },                                             \
    { serv_id_9, serv_data_9 },                                             \
    { NULL, NULL }                                                          \
  };

#define FT_DEFINE_SERVICEDESCREC10( class_,                                 \
                                    serv_id_1, serv_data_1,                 \
                                    serv_id_2, serv_data_2,                 \
                                    serv_id_3, serv_data_3,                 \
                                    serv_id_4, serv_data_4,                 \
                                    serv_id_5, serv_data_5,                 \
                                    serv_id_6, serv_data_6,                 \
                                    serv_id_7, serv_data_7,                 \
                                    serv_id_8, serv_data_8,                 \
                                    serv_id_9, serv_data_9,                 \
                                    serv_id_10, serv_data_10 )              \
  static const FT_ServiceDescRec  class_[] =                                \
  {                                                                         \
    { serv_id_1, serv_data_1 },                                             \
    { serv_id_2, serv_data_2 },                                             \
    { serv_id_3, serv_data_3 },                                             \
    { serv_id_4, serv_data_4 },                                             \
    { serv_id_5, serv_data_5 },                                             \
    { serv_id_6, serv_data_6 },                                             \
    { serv_id_7, serv_data_7 },                                             \
    { serv_id_8, serv_data_8 },                                             \
    { serv_id_9, serv_data_9 },                                             \
    { serv_id_10, serv_data_10 },                                           \
    { NULL, NULL }                                                          \
  };

  /*
   * Parse a list of FT_ServiceDescRec descriptors and look for a specific
   * service by ID.  Note that the last element in the array must be { NULL,
   * NULL }, and that the function should return NULL if the service isn't
   * available.
   *
   * This function can be used by modules to implement their `get_service'
   * method.
   */
  FT_BASE( FT_Pointer )
  ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
                          const char*     service_id );

  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****             S E R V I C E S   C A C H E                       *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /*
   * This structure is used to store a cache for several frequently used
   * services.  It is the type of `face->internal->services'.  You should
   * only use FT_FACE_LOOKUP_SERVICE to access it.
   *
   * All fields should have the type FT_Pointer to relax compilation
   * dependencies.  We assume the developer isn't completely stupid.
   *
   * Each field must be named `service_XXXX' where `XXX' corresponds to the
   * correct FT_SERVICE_ID_XXXX macro.  See the definition of
   * FT_FACE_LOOKUP_SERVICE below how this is implemented.
   *
   */
  typedef struct  FT_ServiceCacheRec_
  {
    FT_Pointer  service_POSTSCRIPT_FONT_NAME;
    FT_Pointer  service_MULTI_MASTERS;
    FT_Pointer  service_METRICS_VARIATIONS;
    FT_Pointer  service_GLYPH_DICT;
    FT_Pointer  service_PFR_METRICS;
    FT_Pointer  service_WINFNT;

  } FT_ServiceCacheRec, *FT_ServiceCache;

  /*
   * A magic number used within the services cache.
   */

  /* ensure that value `1' has the same width as a pointer */
#define FT_SERVICE_UNAVAILABLE  ((FT_Pointer)~(FT_PtrDist)1)

  /**************************************************************************
   *
   * @macro:
   *   FT_FACE_LOOKUP_SERVICE
   *
   * @description:
   *   This macro is used to look up a service from a face's driver module
   *   using its cache.
   *
   * @input:
   *   face ::
   *     The source face handle containing the cache.
   *
   *   field ::
   *     The field name in the cache.
   *
   *   id ::
   *     The service ID.
   *
   * @output:
   *   ptr ::
   *     A variable receiving the service data.  `NULL` if not available.
   */
#ifdef __cplusplus

#define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
  FT_BEGIN_STMNT                                               \
    FT_Pointer   svc;                                          \
    FT_Pointer*  Pptr = (FT_Pointer*)&(ptr);                   \
                                                               \
                                                               \
    svc = FT_FACE( face )->internal->services. service_ ## id; \
    if ( svc == FT_SERVICE_UNAVAILABLE )                       \
      svc = NULL;                                              \
    else if ( svc == NULL )                                    \
    {                                                          \
      FT_FACE_FIND_SERVICE( face, svc, id );                   \
                                                               \
      FT_FACE( face )->internal->services. service_ ## id =    \
        (FT_Pointer)( svc != NULL ? svc                        \
                                  : FT_SERVICE_UNAVAILABLE );  \
    }                                                          \
    *Pptr = svc;                                               \
  FT_END_STMNT

#else /* !C++ */

#define FT_FACE_LOOKUP_SERVICE( face, ptr, id )                \
  FT_BEGIN_STMNT                                               \
    FT_Pointer  svc;                                           \
                                                               \
                                                               \
    svc = FT_FACE( face )->internal->services. service_ ## id; \
    if ( svc == FT_SERVICE_UNAVAILABLE )                       \
      svc = NULL;                                              \
    else if ( svc == NULL )                                    \
    {                                                          \
      FT_FACE_FIND_SERVICE( face, svc, id );                   \
                                                               \
      FT_FACE( face )->internal->services. service_ ## id =    \
        (FT_Pointer)( svc != NULL ? svc                        \
                                  : FT_SERVICE_UNAVAILABLE );  \
    }                                                          \
    ptr = svc;                                                 \
  FT_END_STMNT

#endif /* !C++ */

  /*
   * A macro used to define new service structure types.
   */

#define FT_DEFINE_SERVICE( name )            \
  typedef struct FT_Service_ ## name ## Rec_ \
    FT_Service_ ## name ## Rec ;             \
  typedef struct FT_Service_ ## name ## Rec_ \
    const * FT_Service_ ## name ;            \
  struct FT_Service_ ## name ## Rec_

  /* */

  /*
   * The header files containing the services.
   */

#define FT_SERVICE_BDF_H                <freetype/internal/services/svbdf.h>
#define FT_SERVICE_CFF_TABLE_LOAD_H     <freetype/internal/services/svcfftl.h>
#define FT_SERVICE_CID_H                <freetype/internal/services/svcid.h>
#define FT_SERVICE_FONT_FORMAT_H        <freetype/internal/services/svfntfmt.h>
#define FT_SERVICE_GLYPH_DICT_H         <freetype/internal/services/svgldict.h>
#define FT_SERVICE_GX_VALIDATE_H        <freetype/internal/services/svgxval.h>
#define FT_SERVICE_KERNING_H            <freetype/internal/services/svkern.h>
#define FT_SERVICE_METRICS_VARIATIONS_H <freetype/internal/services/svmetric.h>
#define FT_SERVICE_MULTIPLE_MASTERS_H   <freetype/internal/services/svmm.h>
#define FT_SERVICE_OPENTYPE_VALIDATE_H  <freetype/internal/services/svotval.h>
#define FT_SERVICE_PFR_H                <freetype/internal/services/svpfr.h>
#define FT_SERVICE_POSTSCRIPT_CMAPS_H   <freetype/internal/services/svpscmap.h>
#define FT_SERVICE_POSTSCRIPT_INFO_H    <freetype/internal/services/svpsinfo.h>
#define FT_SERVICE_POSTSCRIPT_NAME_H    <freetype/internal/services/svpostnm.h>
#define FT_SERVICE_PROPERTIES_H         <freetype/internal/services/svprop.h>
#define FT_SERVICE_SFNT_H               <freetype/internal/services/svsfnt.h>
#define FT_SERVICE_TRUETYPE_ENGINE_H    <freetype/internal/services/svtteng.h>
#define FT_SERVICE_TRUETYPE_GLYF_H      <freetype/internal/services/svttglyf.h>
#define FT_SERVICE_TT_CMAP_H            <freetype/internal/services/svttcmap.h>
#define FT_SERVICE_WINFNT_H             <freetype/internal/services/svwinfnt.h>

 /* */

FT_END_HEADER

#endif /* FTSERV_H_ */

/* END */


text:
/****************************************************************************
 *
 * ftdebug.h
 *
 *   Debugging and logging component (specification).
 *
 * Copyright (C) 1996-2020 by
 * David Turner, Robert Wilhelm, and Werner Lemberg.
 *
 * This file is part of the FreeType project, and may only be used,
 * modified, and distributed under the terms of the FreeType project
 * license, LICENSE.TXT.  By continuing to use, modify, or distribute
 * this file you indicate that you have read the license and
 * understand and accept it fully.
 *
 *
 * IMPORTANT: A description of FreeType's debugging support can be
 *             found in 'docs/DEBUG.TXT'.  Read it if you need to use or
 *             understand this code.
 *
 */

#ifndef FTDEBUG_H_
#define FTDEBUG_H_

#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include FT_FREETYPE_H

FT_BEGIN_HEADER

  /* force the definition of FT_DEBUG_LEVEL_ERROR if FT_DEBUG_LEVEL_TRACE */
  /* is already defined; this simplifies the following #ifdefs            */
  /*                                                                      */
#ifdef FT_DEBUG_LEVEL_TRACE
#undef  FT_DEBUG_LEVEL_ERROR
#define FT_DEBUG_LEVEL_ERROR
#endif

  /**************************************************************************
   *
   * Define the trace enums as well as the trace levels array when they are
   * needed.
   *
   */

#ifdef FT_DEBUG_LEVEL_TRACE

#define FT_TRACE_DEF( x )  trace_ ## x ,

  /* defining the enumeration */
  typedef enum  FT_Trace_
  {
#include FT_INTERNAL_TRACE_H
    trace_count

  } FT_Trace;

  /* a pointer to the array of trace levels, */
  /* provided by `src/base/ftdebug.c'        */
  extern int*  ft_trace_levels;

#undef FT_TRACE_DEF

#endif /* FT_DEBUG_LEVEL_TRACE */

  /**************************************************************************
   *
   * Define the FT_TRACE macro
   *
   * IMPORTANT!
   *
   * Each component must define the macro FT_COMPONENT to a valid FT_Trace
   * value before using any TRACE macro.
   *
   */

#ifdef FT_DEBUG_LEVEL_TRACE

  /* we need two macros here to make cpp expand `FT_COMPONENT' */
#define FT_TRACE_COMP( x )   FT_TRACE_COMP_( x )
#define FT_TRACE_COMP_( x )  trace_ ## x

#define FT_TRACE( level, varformat )                                       \
          do                                                               \
          {                                                                \
            if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] >= level ) \
              FT_Message varformat;                                        \
          } while ( 0 )

#else /* !FT_DEBUG_LEVEL_TRACE */

#define FT_TRACE( level, varformat )  do { } while ( 0 )      /* nothing */

#endif /* !FT_DEBUG_LEVEL_TRACE */

  /**************************************************************************
   *
   * @function:
   *   FT_Trace_Get_Count
   *
   * @description:
   *   Return the number of available trace components.
   *
   * @return:
   *   The number of trace components.  0 if FreeType 2 is not built with
   *   FT_DEBUG_LEVEL_TRACE definition.
   *
   * @note:
   *   This function may be useful if you want to access elements of the
   *   internal trace levels array by an index.
   */
  FT_BASE( FT_Int )
  FT_Trace_Get_Count( void );

  /**************************************************************************
   *
   * @function:
   *   FT_Trace_Get_Name
   *
   * @description:
   *   Return the name of a trace component.
   *
   * @input:
   *   The index of the trace component.
   *
   * @return:
   *   The name of the trace component.  This is a statically allocated
   *   C~string, so do not free it after use.  `NULL` if FreeType is not
   *   built with FT_DEBUG_LEVEL_TRACE definition.
   *
   * @note:
   *   Use @FT_Trace_Get_Count to get the number of available trace
   *   components.
   */
  FT_BASE( const char* )
  FT_Trace_Get_Name( FT_Int  idx );

  /**************************************************************************
   *
   * @function:
   *   FT_Trace_Disable
   *
   * @description:
   *   Switch off tracing temporarily.  It can be activated again with
   *   @FT_Trace_Enable.
   */
  FT_BASE( void )
  FT_Trace_Disable( void );

  /**************************************************************************
   *
   * @function:
   *   FT_Trace_Enable
   *
   * @description:
   *   Activate tracing.  Use it after tracing has been switched off with
   *   @FT_Trace_Disable.
   */
  FT_BASE( void )
  FT_Trace_Enable( void );

  /**************************************************************************
   *
   * You need two opening and closing parentheses!
   *
   * Example: FT_TRACE0(( "Value is %i", foo ))
   *
   * Output of the FT_TRACEX macros is sent to stderr.
   *
   */

#define FT_TRACE0( varformat )  FT_TRACE( 0, varformat )
#define FT_TRACE1( varformat )  FT_TRACE( 1, varformat )
#define FT_TRACE2( varformat )  FT_TRACE( 2, varformat )
#define FT_TRACE3( varformat )  FT_TRACE( 3, varformat )
#define FT_TRACE4( varformat )  FT_TRACE( 4, varformat )
#define FT_TRACE5( varformat )  FT_TRACE( 5, varformat )
#define FT_TRACE6( varformat )  FT_TRACE( 6, varformat )
#define FT_TRACE7( varformat )  FT_TRACE( 7, varformat )

  /**************************************************************************
   *
   * Define the FT_ERROR macro.
   *
   * Output of this macro is sent to stderr.
   *
   */

#ifdef FT_DEBUG_LEVEL_ERROR

#define FT_ERROR( varformat )  FT_Message  varformat

#else  /* !FT_DEBUG_LEVEL_ERROR */

#define FT_ERROR( varformat )  do { } while ( 0 )      /* nothing */

#endif /* !FT_DEBUG_LEVEL_ERROR */

  /**************************************************************************
   *
   * Define the FT_ASSERT and FT_THROW macros.  The call to `FT_Throw` makes
   * it possible to easily set a breakpoint at this function.
   *
   */

#ifdef FT_DEBUG_LEVEL_ERROR

#define FT_ASSERT( condition )                                      \
          do                                                        \
          {                                                         \
            if ( !( condition ) )                                   \
              FT_Panic( "assertion failed on line %d of file %s\n", \
                        __LINE__, __FILE__ );                       \
          } while ( 0 )

#define FT_THROW( e )                                   \
          ( FT_Throw( FT_ERR_CAT( FT_ERR_PREFIX, e ),   \
                      __LINE__,                         \
                      __FILE__ )                      | \
            FT_ERR_CAT( FT_ERR_PREFIX, e )            )

#else /* !FT_DEBUG_LEVEL_ERROR */

#define FT_ASSERT( condition )  do { } while ( 0 )

#define FT_THROW( e )  FT_ERR_CAT( FT_ERR_PREFIX, e )

#endif /* !FT_DEBUG_LEVEL_ERROR */

  /**************************************************************************
   *
   * Define `FT_Message` and `FT_Panic` when needed.
   *
   */

#ifdef FT_DEBUG_LEVEL_ERROR

#include "stdio.h"  /* for vfprintf() */

  /* print a message */
  FT_BASE( void )
  FT_Message( const char*  fmt,
              ... );

  /* print a message and exit */
  FT_BASE( void )
  FT_Panic( const char*  fmt,
            ... );

  /* report file name and line number of an error */
  FT_BASE( int )
  FT_Throw( FT_Error     error,
            int          line,
            const char*  file );

#endif /* FT_DEBUG_LEVEL_ERROR */

  FT_BASE( void )
  ft_debug_init( void );

FT_END_HEADER

#endif /* FTDEBUG_H_ */

/* END */