text:
/* inftrees.c -- generate Huffman trees for efficient decoding
 * Copyright (C) 1995-2002 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "zutil.h"
#include "inftrees.h"

#if !defined(BUILDFIXED) && !defined(STDC)
#  define BUILDFIXED   /* non ANSI compilers may not accept inffixed.h */
#endif

#if 0
local const char inflate_copyright[] =
   " inflate 1.1.4 Copyright 1995-2002 Mark Adler ";
#endif
/*
  If you use the zlib library in a product, an acknowledgment is welcome
  in the documentation of your product. If for some reason you cannot
  include such an acknowledgment, I would appreciate that you keep this
  copyright string in the executable of your product.
 */

/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits

local int huft_build OF((
    uIntf *,            /* code lengths in bits */
    uInt,               /* number of codes */
    uInt,               /* number of "simple" codes */
    const uIntf *,      /* list of base values for non-simple codes */
    const uIntf *,      /* list of extra bits for non-simple codes */
    inflate_huft * FAR*,/* result: starting table */
    uIntf *,            /* maximum lookup bits (returns actual) */
    inflate_huft *,     /* space for trees */
    uInt *,             /* hufts used in space */
    uIntf * ));         /* space for values */

/* Tables for deflate from PKZIP's appnote.txt. */
local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
        /* see note #13 above about 258 */
local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
        8193, 12289, 16385, 24577};
local const uInt cpdext[30] = { /* Extra bits for distance codes */
        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
        12, 12, 13, 13};

/*
   Huffman code decoding is performed using a multi-level table lookup.
   The fastest way to decode is to simply build a lookup table whose
   size is determined by the longest code.  However, the time it takes
   to build this table can also be a factor if the data being decoded
   is not very long.  The most common codes are necessarily the
   shortest codes, so those codes dominate the decoding time, and hence
   the speed.  The idea is you can have a shorter table that decodes the
   shorter, more probable codes, and then point to subsidiary tables for
   the longer codes.  The time it costs to decode the longer codes is
   then traded against the time it takes to make longer tables.

   This results of this trade are in the variables lbits and dbits
   below.  lbits is the number of bits the first level table for literal/
   length codes can decode in one step, and dbits is the same thing for
   the distance codes.  Subsequent tables are also less than or equal to
   those sizes.  These values may be adjusted either when all of the
   codes are shorter than that, in which case the longest code length in
   bits is used, or when the shortest code is *longer* than the requested
   table size, in which case the length of the shortest code in bits is
   used.

   There are two different values for the two tables, since they code a
   different number of possibilities each.  The literal/length table
   codes 286 possible values, or in a flat code, a little over eight
   bits.  The distance table codes 30 possible values, or a little less
   than five bits, flat.  The optimum values for speed end up being
   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
   The optimum values may differ though from machine to machine, and
   possibly even between compilers.  Your mileage may vary.
 */

/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
#define BMAX 15         /* maximum bit length of any code */

local int huft_build( /* b, n, s, d, e, t, m, hp, hn, v) */
uIntf *b,               /* code lengths in bits (all assumed <= BMAX) */
uInt n,                 /* number of codes (assumed <= 288) */
uInt s,                 /* number of simple-valued codes (0..s-1) */
const uIntf *d,         /* list of base values for non-simple codes */
const uIntf *e,         /* list of extra bits for non-simple codes */
inflate_huft * FAR *t,  /* result: starting table */
uIntf *m,               /* maximum lookup bits, returns actual */
inflate_huft *hp,       /* space for trees */
uInt *hn,               /* hufts used in space */
uIntf *v                /* working area: values in order of bit length */
/* Given a list of code lengths and a maximum table size, make a set of
   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
   if the given code set is incomplete (the tables are still built in this
   case), or Z_DATA_ERROR if the input is invalid. */
)
{

  uInt a;                       /* counter for codes of length k */
  uInt c[BMAX+1];               /* bit length count table */
  uInt f;                       /* i repeats in table every f entries */
  int g;                        /* maximum code length */
  int h;                        /* table level */
  uInt i;                       /* counter, current code */
  uInt j;                       /* counter */
  int k;                        /* number of bits in current code */
  int l;                        /* bits per table (returned in m) */
  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
  uIntf *p;                     /* pointer into c[], b[], or v[] */
  inflate_huft *q;              /* points to current table */
  struct inflate_huft_s r;      /* table entry for structure assignment */
  inflate_huft *u[BMAX];        /* table stack */
  int w;                        /* bits before this table == (l * h) */
  uInt x[BMAX+1];               /* bit offsets, then code stack */
  uIntf *xp;                    /* pointer into x */
  int y;                        /* number of dummy codes added */
  uInt z;                       /* number of entries in current table */

  /* Make compiler happy */
  r.base = 0;

  /* Generate counts for each bit length */
  p = c;
#define C0 *p++ = 0;
#define C2 C0 C0 C0 C0
#define C4 C2 C2 C2 C2
  C4                            /* clear c[]--assume BMAX+1 is 16 */
  p = b;  i = n;
  do {
    c[*p++]++;                  /* assume all entries <= BMAX */
  } while (--i);
  if (c[0] == n)                /* null input--all zero length codes */
  {
    *t = (inflate_huft *)Z_NULL;
    *m = 0;
    return Z_OK;
  }

  /* Find minimum and maximum length, bound *m by those */
  l = *m;
  for (j = 1; j <= BMAX; j++)
    if (c[j])
      break;
  k = j;                        /* minimum code length */
  if ((uInt)l < j)
    l = j;
  for (i = BMAX; i; i--)
    if (c[i])
      break;
  g = i;                        /* maximum code length */
  if ((uInt)l > i)
    l = i;
  *m = l;

  /* Adjust last length count to fill out codes, if needed */
  for (y = 1 << j; j < i; j++, y <<= 1)
    if ((y -= c[j]) < 0)
      return Z_DATA_ERROR;
  if ((y -= c[i]) < 0)
    return Z_DATA_ERROR;
  c[i] += y;

  /* Generate starting offsets into the value table for each length */
  x[1] = j = 0;
  p = c + 1;  xp = x + 2;
  while (--i) {                 /* note that i == g from above */
    *xp++ = (j += *p++);
  }

  /* Make a table of values in order of bit lengths */
  p = b;  i = 0;
  do {
    if ((j = *p++) != 0)
      v[x[j]++] = i;
  } while (++i < n);
  n = x[g];                     /* set n to length of v */

  /* Generate the Huffman codes and for each, make the table entries */
  x[0] = i = 0;                 /* first Huffman code is zero */
  p = v;                        /* grab values in bit order */
  h = -1;                       /* no tables yet--level -1 */
  w = -l;                       /* bits decoded == (l * h) */
  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
  q = (inflate_huft *)Z_NULL;   /* ditto */
  z = 0;                        /* ditto */

  /* go through the bit lengths (k already is bits in shortest code) */
  for (; k <= g; k++)
  {
    a = c[k];
    while (a--)
    {
      /* here i is the Huffman code of length k bits for value *p */
      /* make tables up to required level */
      while (k > w + l)
      {
        h++;
        w += l;                 /* previous table always l bits */

        /* compute minimum size table less than or equal to l bits */
        z = g - w;
        z = z > (uInt)l ? (uInt)l : z;        /* table size upper limit */
        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
        {                       /* too few codes for k-w bit table */
          f -= a + 1;           /* deduct codes from patterns left */
          xp = c + k;
          if (j < z)
            while (++j < z)     /* try smaller tables up to z bits */
            {
              if ((f <<= 1) <= *++xp)
                break;          /* enough codes to use up j bits */
              f -= *xp;         /* else deduct codes from patterns */
            }
        }
        z = 1 << j;             /* table entries for j-bit table */

        /* allocate new table */
        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
          return Z_DATA_ERROR;  /* overflow of MANY */
        u[h] = q = hp + *hn;
        *hn += z;

        /* connect to last table, if there is one */
        if (h)
        {
          x[h] = i;             /* save pattern for backing up */
          r.bits = (Byte)l;     /* bits to dump before this table */
          r.exop = (Byte)j;     /* bits in this table */
          j = i >> (w - l);
          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
          u[h-1][j] = r;        /* connect to last table */
        }
        else
          *t = q;               /* first table is returned result */
      }

      /* set up table entry in r */
      r.bits = (Byte)(k - w);
      if (p >= v + n)
        r.exop = 128 + 64;      /* out of values--invalid code */
      else if (*p < s)
      {
        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
        r.base = *p++;          /* simple code is just the value */
      }
      else
      {
        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
        r.base = d[*p++ - s];
      }

      /* fill code-like entries with r */
      f = 1 << (k - w);
      for (j = i >> w; j < z; j += f)
        q[j] = r;

      /* backwards increment the k-bit code i */
      for (j = 1 << (k - 1); i & j; j >>= 1)
        i ^= j;
      i ^= j;

      /* backup over finished tables */
      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
      while ((i & mask) != x[h])
      {
        h--;                    /* don't need to update q */
        w -= l;
        mask = (1 << w) - 1;
      }
    }
  }

  /* Return Z_BUF_ERROR if we were given an incomplete table */
  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
}

local int inflate_trees_bits( /* c, bb, tb, hp, z) */
uIntf *c,               /* 19 code lengths */
uIntf *bb,              /* bits tree desired/actual depth */
inflate_huft * FAR *tb, /* bits tree result */
inflate_huft *hp,       /* space for trees */
z_streamp z             /* for messages */
)
{
  int r;
  uInt hn = 0;          /* hufts used in space */
  uIntf *v;             /* work area for huft_build */

  if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
    return Z_MEM_ERROR;
  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
                 tb, bb, hp, &hn, v);
  if (r == Z_DATA_ERROR)
    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
  else if (r == Z_BUF_ERROR || *bb == 0)
  {
    z->msg = (char*)"incomplete dynamic bit lengths tree";
    r = Z_DATA_ERROR;
  }
  ZFREE(z, v);
  return r;
}

local int inflate_trees_dynamic( /* nl, nd, c, bl, bd, tl, td, hp, z) */
uInt nl,                /* number of literal/length codes */
uInt nd,                /* number of distance codes */
uIntf *c,               /* that many (total) code lengths */
uIntf *bl,              /* literal desired/actual bit depth */
uIntf *bd,              /* distance desired/actual bit depth */
inflate_huft * FAR *tl, /* literal/length tree result */
inflate_huft * FAR *td, /* distance tree result */
inflate_huft *hp,       /* space for trees */
z_streamp z             /* for messages */
)
{
  int r;
  uInt hn = 0;          /* hufts used in space */
  uIntf *v;             /* work area for huft_build */

  /* allocate work area */
  if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
    return Z_MEM_ERROR;

  /* build literal/length tree */
  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
  if (r != Z_OK || *bl == 0)
  {
    if (r == Z_DATA_ERROR)
      z->msg = (char*)"oversubscribed literal/length tree";
    else if (r != Z_MEM_ERROR)
    {
      z->msg = (char*)"incomplete literal/length tree";
      r = Z_DATA_ERROR;
    }
    ZFREE(z, v);
    return r;
  }

  /* build distance tree */
  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
  if (r != Z_OK || (*bd == 0 && nl > 257))
  {
    if (r == Z_DATA_ERROR)
      z->msg = (char*)"oversubscribed distance tree";
    else if (r == Z_BUF_ERROR) {
#if 0
    {
#endif
#ifdef PKZIP_BUG_WORKAROUND
      r = Z_OK;
    }
#else
      z->msg = (char*)"incomplete distance tree";
      r = Z_DATA_ERROR;
    }
    else if (r != Z_MEM_ERROR)
    {
      z->msg = (char*)"empty distance tree with lengths";
      r = Z_DATA_ERROR;
    }
    ZFREE(z, v);
    return r;
#endif
  }

  /* done */
  ZFREE(z, v);
  return Z_OK;
}

/* build fixed tables only once--keep them here */
#ifdef BUILDFIXED
local int fixed_built = 0;
#define FIXEDH 544      /* number of hufts used by fixed tables */
local inflate_huft fixed_mem[FIXEDH];
local uInt fixed_bl;
local uInt fixed_bd;
local inflate_huft *fixed_tl;
local inflate_huft *fixed_td;
#else
#include "inffixed.h"
#endif

local int inflate_trees_fixed( /* bl, bd, tl, td, z) */
uIntf *bl,                      /* literal desired/actual bit depth */
uIntf *bd,                      /* distance desired/actual bit depth */
const inflate_huft * FAR *tl,   /* literal/length tree result */
const inflate_huft * FAR *td,   /* distance tree result */
z_streamp z                     /* for memory allocation */
)
{
#ifdef BUILDFIXED
  /* build fixed tables if not already */
  if (!fixed_built)
  {
    int k;              /* temporary variable */
    uInt f = 0;         /* number of hufts used in fixed_mem */
    uIntf *c;           /* length list for huft_build */
    uIntf *v;           /* work area for huft_build */

    /* allocate memory */
    if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
      return Z_MEM_ERROR;
    if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
    {
      ZFREE(z, c);
      return Z_MEM_ERROR;
    }

    /* literal table */
    for (k = 0; k < 144; k++)
      c[k] = 8;
    for (; k < 256; k++)
      c[k] = 9;
    for (; k < 280; k++)
      c[k] = 7;
    for (; k < 288; k++)
      c[k] = 8;
    fixed_bl = 9;
    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
               fixed_mem, &f, v);

    /* distance table */
    for (k = 0; k < 30; k++)
      c[k] = 5;
    fixed_bd = 5;
    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
               fixed_mem, &f, v);

    /* done */
    ZFREE(z, v);
    ZFREE(z, c);
    fixed_built = 1;
  }
#else
  FT_UNUSED(z);
#endif
  *bl = fixed_bl;
  *bd = fixed_bd;
  *tl = fixed_tl;
  *td = fixed_td;
  return Z_OK;
}


text:
#
# FreeType 2 GZip support configuration rules
#

# Copyright (C) 2002-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.

# gzip driver directory
#
GZIP_DIR := $(SRC_DIR)/gzip

# compilation flags for the driver
#
ifeq ($(SYSTEM_ZLIB),)
  GZIP_COMPILE := $(CC) $(ANSIFLAGS)                             \
                        $I$(subst /,$(COMPILER_SEP),$(GZIP_DIR)) \
                        $(INCLUDE_FLAGS)                         \
                        $(FT_CFLAGS)
else
  GZIP_COMPILE := $(CC) $(ANSIFLAGS)     \
                        $(INCLUDE_FLAGS) \
                        $(FT_CFLAGS)
endif

# gzip support sources
#
# All source and header files get loaded by `ftgzip.c' only if SYSTEM_ZLIB
# is not defined (regardless whether we have a `single' or a `multi' build).
# However, it doesn't harm if we add everything as a dependency
# unconditionally.
#
GZIP_DRV_SRCS := $(GZIP_DIR)/adler32.c  \
                 $(GZIP_DIR)/ftzconf.h  \
                 $(GZIP_DIR)/infblock.c \
                 $(GZIP_DIR)/infblock.h \
                 $(GZIP_DIR)/infcodes.c \
                 $(GZIP_DIR)/infcodes.h \
                 $(GZIP_DIR)/inffixed.h \
                 $(GZIP_DIR)/inflate.c  \
                 $(GZIP_DIR)/inftrees.c \
                 $(GZIP_DIR)/inftrees.h \
                 $(GZIP_DIR)/infutil.c  \
                 $(GZIP_DIR)/infutil.h  \
                 $(GZIP_DIR)/zlib.h     \
                 $(GZIP_DIR)/zutil.c    \
                 $(GZIP_DIR)/zutil.h

# gzip driver object(s)
#
#   GZIP_DRV_OBJ is used during both `single' and `multi' builds
#
GZIP_DRV_OBJ := $(OBJ_DIR)/ftgzip.$O

# gzip main source file
#
GZIP_DRV_SRC := $(GZIP_DIR)/ftgzip.c

# gzip support - object
#
$(GZIP_DRV_OBJ): $(GZIP_DRV_SRC) $(GZIP_DRV_SRCS) $(FREETYPE_H)
	$(GZIP_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(GZIP_DRV_SRC))

# update main driver object lists
#
DRV_OBJS_S += $(GZIP_DRV_OBJ)
DRV_OBJS_M += $(GZIP_DRV_OBJ)

# EOF

repo_language: C

mime_type: text/x-c


text:
/***************************************************************************/
/*                                                                         */
/*  ftver.rc                                                               */
/*                                                                         */
/*    FreeType VERSIONINFO resource for Windows DLLs.                      */
/*                                                                         */
/*  Copyright (C) 2018-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.                                        */
/*                                                                         */
/***************************************************************************/

#include<windows.h>

#define FT_VERSION      2,10,2,0
#define FT_VERSION_STR  "2.10.2"

VS_VERSION_INFO      VERSIONINFO
FILEVERSION          FT_VERSION
PRODUCTVERSION       FT_VERSION
FILEFLAGSMASK        VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS            VS_FF_DEBUG
#endif
#ifdef DLL_EXPORT
FILETYPE             VFT_DLL
#define FT_FILENAME  "freetype.dll"
#else
FILETYPE             VFT_STATIC_LIB
#define FT_FILENAME  "freetype.lib"
#endif
BEGIN
  BLOCK "StringFileInfo"
  BEGIN
    BLOCK "040904E4"
    BEGIN
      VALUE "CompanyName",      "The FreeType Project"
      VALUE "FileDescription",  "Font Rendering Library"
      VALUE "FileVersion",      FT_VERSION_STR
      VALUE "ProductName",      "FreeType"
      VALUE "ProductVersion",   FT_VERSION_STR
      VALUE "LegalCopyright",   "\251 2000-2020 The FreeType Project www.freetype.org. All rights reserved."
      VALUE "InternalName",     "freetype"
      VALUE "OriginalFilename", FT_FILENAME
    END
  END

  BLOCK "VarFileInfo"
  BEGIN
    /* The following line should only be modified for localized versions.  */
    /* It consists of any number of WORD,WORD pairs, with each pair        */
    /* describing a "language,codepage" combination supported by the file. */
    VALUE "Translation", 0x409, 1252
  END
END


text:
/****************************************************************************
 *
 * ftcalc.c
 *
 *   Arithmetic computations (body).
 *
 * 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.
 *
 */

  /**************************************************************************
   *
   * Support for 1-complement arithmetic has been totally dropped in this
   * release.  You can still write your own code if you need it.
   *
   */

  /**************************************************************************
   *
   * Implementing basic computation routines.
   *
   * FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(),
   * and FT_FloorFix() are declared in freetype.h.
   *
   */

#include <ft2build.h>
#include FT_GLYPH_H
#include FT_TRIGONOMETRY_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H

#ifdef FT_MULFIX_ASSEMBLER
#undef FT_MulFix
#endif

/* we need to emulate a 64-bit data type if a real one isn't available */

#ifndef FT_LONG64

  typedef struct  FT_Int64_
  {
    FT_UInt32  lo;
    FT_UInt32  hi;

  } FT_Int64;

#endif /* !FT_LONG64 */

  /**************************************************************************
   *
   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
   * messages during execution.
   */
#undef  FT_COMPONENT
#define FT_COMPONENT  calc

  /* transfer sign, leaving a positive number;                        */
  /* we need an unsigned value to safely negate INT_MIN (or LONG_MIN) */
#define FT_MOVE_SIGN( x, x_unsigned, s ) \
  FT_BEGIN_STMNT                         \
    if ( x < 0 )                         \
    {                                    \
      x_unsigned = 0U - (x_unsigned);    \
      s          = -s;                   \
    }                                    \
  FT_END_STMNT

  /* The following three functions are available regardless of whether */
  /* FT_LONG64 is defined.                                             */

  /* documentation is in freetype.h */

  FT_EXPORT_DEF( FT_Fixed )
  FT_RoundFix( FT_Fixed  a )
  {
    return ( ADD_LONG( a, 0x8000L - ( a < 0 ) ) ) & ~0xFFFFL;
  }

  /* documentation is in freetype.h */

  FT_EXPORT_DEF( FT_Fixed )
  FT_CeilFix( FT_Fixed  a )
  {
    return ( ADD_LONG( a, 0xFFFFL ) ) & ~0xFFFFL;
  }

  /* documentation is in freetype.h */

  FT_EXPORT_DEF( FT_Fixed )
  FT_FloorFix( FT_Fixed  a )
  {
    return a & ~0xFFFFL;
  }

#ifndef FT_MSB

  FT_BASE_DEF ( FT_Int )
  FT_MSB( FT_UInt32 z )
  {
    FT_Int  shift = 0;

    /* determine msb bit index in `shift' */
    if ( z & 0xFFFF0000UL )
    {
      z     >>= 16;
      shift  += 16;
    }
    if ( z & 0x0000FF00UL )
    {
      z     >>= 8;
      shift  += 8;
    }
    if ( z & 0x000000F0UL )
    {
      z     >>= 4;
      shift  += 4;
    }
    if ( z & 0x0000000CUL )
    {
      z     >>= 2;
      shift  += 2;
    }
    if ( z & 0x00000002UL )
    {
   /* z     >>= 1; */
      shift  += 1;
    }

    return shift;
  }

#endif /* !FT_MSB */

  /* documentation is in ftcalc.h */

  FT_BASE_DEF( FT_Fixed )
  FT_Hypot( FT_Fixed  x,
            FT_Fixed  y )
  {
    FT_Vector  v;

    v.x = x;
    v.y = y;

    return FT_Vector_Length( &v );
  }

#ifdef FT_LONG64

  /* documentation is in freetype.h */

  FT_EXPORT_DEF( FT_Long )
  FT_MulDiv( FT_Long  a_,
             FT_Long  b_,
             FT_Long  c_ )
  {
    FT_Int     s = 1;
    FT_UInt64  a, b, c, d;
    FT_Long    d_;

    a = (FT_UInt64)a_;
    b = (FT_UInt64)b_;
    c = (FT_UInt64)c_;

    FT_MOVE_SIGN( a_, a, s );
    FT_MOVE_SIGN( b_, b, s );
    FT_MOVE_SIGN( c_, c, s );

    d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
              : 0x7FFFFFFFUL;

    d_ = (FT_Long)d;

    return s < 0 ? NEG_LONG( d_ ) : d_;
  }

  /* documentation is in ftcalc.h */

  FT_BASE_DEF( FT_Long )
  FT_MulDiv_No_Round( FT_Long  a_,
                      FT_Long  b_,
                      FT_Long  c_ )
  {
    FT_Int     s = 1;
    FT_UInt64  a, b, c, d;
    FT_Long    d_;

    a = (FT_UInt64)a_;
    b = (FT_UInt64)b_;
    c = (FT_UInt64)c_;

    FT_MOVE_SIGN( a_, a, s );
    FT_MOVE_SIGN( b_, b, s );
    FT_MOVE_SIGN( c_, c, s );

    d = c > 0 ? a * b / c
              : 0x7FFFFFFFUL;

    d_ = (FT_Long)d;

    return s < 0 ? NEG_LONG( d_ ) : d_;
  }

  /* documentation is in freetype.h */

  FT_EXPORT_DEF( FT_Long )
  FT_MulFix( FT_Long  a_,
             FT_Long  b_ )
  {
#ifdef FT_MULFIX_ASSEMBLER

    return FT_MULFIX_ASSEMBLER( (FT_Int32)a_, (FT_Int32)b_ );

#else

    FT_Int64  ab = (FT_Int64)a_ * (FT_Int64)b_;

    /* this requires arithmetic right shift of signed numbers */
    return (FT_Long)( ( ab + 0x8000L - ( ab < 0 ) ) >> 16 );

#endif /* FT_MULFIX_ASSEMBLER */
  }

  /* documentation is in freetype.h */

  FT_EXPORT_DEF( FT_Long )
  FT_DivFix( FT_Long  a_,
             FT_Long  b_ )
  {
    FT_Int     s = 1;
    FT_UInt64  a, b, q;
    FT_Long    q_;

    a = (FT_UInt64)a_;
    b = (FT_UInt64)b_;

    FT_MOVE_SIGN( a_, a, s );
    FT_MOVE_SIGN( b_, b, s );

    q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
              : 0x7FFFFFFFUL;

    q_ = (FT_Long)q;

    return s < 0 ? NEG_LONG( q_ ) : q_;
  }

#else /* !FT_LONG64 */

  static void
  ft_multo64( FT_UInt32  x,
              FT_UInt32  y,
              FT_Int64  *z )
  {
    FT_UInt32  lo1, hi1, lo2, hi2, lo, hi, i1, i2;

    lo1 = x & 0x0000FFFFU;  hi1 = x >> 16;
    lo2 = y & 0x0000FFFFU;  hi2 = y >> 16;

    lo = lo1 * lo2;
    i1 = lo1 * hi2;
    i2 = lo2 * hi1;
    hi = hi1 * hi2;

    /* Check carry overflow of i1 + i2 */
    i1 += i2;
    hi += (FT_UInt32)( i1 < i2 ) << 16;

    hi += i1 >> 16;
    i1  = i1 << 16;

    /* Check carry overflow of i1 + lo */
    lo += i1;
    hi += ( lo < i1 );

    z->lo = lo;
    z->hi = hi;
  }

  static FT_UInt32
  ft_div64by32( FT_UInt32  hi,
                FT_UInt32  lo,
                FT_UInt32  y )
  {
    FT_UInt32  r, q;
    FT_Int     i;

    if ( hi >= y )
      return (FT_UInt32)0x7FFFFFFFL;

    /* We shift as many bits as we can into the high register, perform     */
    /* 32-bit division with modulo there, then work through the remaining  */
    /* bits with long division. This optimization is especially noticeable */
    /* for smaller dividends that barely use the high register.            */

    i = 31 - FT_MSB( hi );
    r = ( hi << i ) | ( lo >> ( 32 - i ) ); lo <<= i; /* left 64-bit shift */
    q = r / y;
    r -= q * y;   /* remainder */

    i = 32 - i;   /* bits remaining in low register */
    do
    {
      q <<= 1;
      r   = ( r << 1 ) | ( lo >> 31 ); lo <<= 1;

      if ( r >= y )
      {
        r -= y;
        q |= 1;
      }
    } while ( --i );

    return q;
  }

  static void
  FT_Add64( FT_Int64*  x,
            FT_Int64*  y,
            FT_Int64  *z )
  {
    FT_UInt32  lo, hi;

    lo = x->lo + y->lo;
    hi = x->hi + y->hi + ( lo < x->lo );

    z->lo = lo;
    z->hi = hi;
  }

  /*  The FT_MulDiv function has been optimized thanks to ideas from     */
  /*  Graham Asher and Alexei Podtelezhnikov.  The trick is to optimize  */
  /*  a rather common case when everything fits within 32-bits.          */
  /*                                                                     */
  /*  We compute 'a*b+c/2', then divide it by 'c' (all positive values). */
  /*                                                                     */
  /*  The product of two positive numbers never exceeds the square of    */
  /*  its mean values.  Therefore, we always avoid the overflow by       */
  /*  imposing                                                           */
  /*                                                                     */
  /*    (a + b) / 2 <= sqrt(X - c/2)    ,                                */
  /*                                                                     */
  /*  where X = 2^32 - 1, the maximum unsigned 32-bit value, and using   */
  /*  unsigned arithmetic.  Now we replace `sqrt' with a linear function */
  /*  that is smaller or equal for all values of c in the interval       */
  /*  [0;X/2]; it should be equal to sqrt(X) and sqrt(3X/4) at the       */
  /*  endpoints.  Substituting the linear solution and explicit numbers  */
  /*  we get                                                             */
  /*                                                                     */
  /*    a + b <= 131071.99 - c / 122291.84    .                          */
  /*                                                                     */
  /*  In practice, we should use a faster and even stronger inequality   */
  /*                                                                     */
  /*    a + b <= 131071 - (c >> 16)                                      */
  /*                                                                     */
  /*  or, alternatively,                                                 */
  /*                                                                     */
  /*    a + b <= 129894 - (c >> 17)    .                                 */
  /*                                                                     */
  /*  FT_MulFix, on the other hand, is optimized for a small value of    */
  /*  the first argument, when the second argument can be much larger.   */
  /*  This can be achieved by scaling the second argument and the limit  */
  /*  in the above inequalities.  For example,                           */
  /*                                                                     */
  /*    a + (b >> 8) <= (131071 >> 4)                                    */
  /*                                                                     */
  /*  covers the practical range of use. The actual test below is a bit  */
  /*  tighter to avoid the border case overflows.                        */
  /*                                                                     */
  /*  In the case of FT_DivFix, the exact overflow check                 */
  /*                                                                     */
  /*    a << 16 <= X - c/2                                               */
  /*                                                                     */
  /*  is scaled down by 2^16 and we use                                  */
  /*                                                                     */
  /*    a <= 65535 - (c >> 17)    .                                      */

  /* documentation is in freetype.h */

  FT_EXPORT_DEF( FT_Long )
  FT_MulDiv( FT_Long  a_,
             FT_Long  b_,
             FT_Long  c_ )
  {
    FT_Int     s = 1;
    FT_UInt32  a, b, c;

    /* XXX: this function does not allow 64-bit arguments */

    a = (FT_UInt32)a_;
    b = (FT_UInt32)b_;
    c = (FT_UInt32)c_;

    FT_MOVE_SIGN( a_, a, s );
    FT_MOVE_SIGN( b_, b, s );
    FT_MOVE_SIGN( c_, c, s );

    if ( c == 0 )
      a = 0x7FFFFFFFUL;

    else if ( a + b <= 129894UL - ( c >> 17 ) )
      a = ( a * b + ( c >> 1 ) ) / c;

    else
    {
      FT_Int64  temp, temp2;

      ft_multo64( a, b, &temp );

      temp2.hi = 0;
      temp2.lo = c >> 1;

      FT_Add64( &temp, &temp2, &temp );

      /* last attempt to ditch long division */
      a = ( temp.hi == 0 ) ? temp.lo / c
                           : ft_div64by32( temp.hi, temp.lo, c );
    }

    a_ = (FT_Long)a;

    return s < 0 ? NEG_LONG( a_ ) : a_;
  }

  FT_BASE_DEF( FT_Long )
  FT_MulDiv_No_Round( FT_Long  a_,
                      FT_Long  b_,
                      FT_Long  c_ )
  {
    FT_Int     s = 1;
    FT_UInt32  a, b, c;

    /* XXX: this function does not allow 64-bit arguments */

    a = (FT_UInt32)a_;
    b = (FT_UInt32)b_;
    c = (FT_UInt32)c_;

    FT_MOVE_SIGN( a_, a, s );
    FT_MOVE_SIGN( b_, b, s );
    FT_MOVE_SIGN( c_, c, s );

    if ( c == 0 )
      a = 0x7FFFFFFFUL;

    else if ( a + b <= 131071UL )
      a = a * b / c;

    else
    {
      FT_Int64  temp;

      ft_multo64( a, b, &temp );

      /* last attempt to ditch long division */
      a = ( temp.hi == 0 ) ? temp.lo / c
                           : ft_div64by32( temp.hi, temp.lo, c );
    }

    a_ = (FT_Long)a;

    return s < 0 ? NEG_LONG( a_ ) : a_;
  }

  /* documentation is in freetype.h */

  FT_EXPORT_DEF( FT_Long )
  FT_MulFix( FT_Long  a_,
             FT_Long  b_ )
  {
#ifdef FT_MULFIX_ASSEMBLER

    return FT_MULFIX_ASSEMBLER( a_, b_ );

#elif 0

    /*
     * This code is nonportable.  See comment below.
     *
     * However, on a platform where right-shift of a signed quantity fills
     * the leftmost bits by copying the sign bit, it might be faster.
     */

    FT_Long    sa, sb;
    FT_UInt32  a, b;

    /*
     * This is a clever way of converting a signed number `a' into its
     * absolute value (stored back into `a') and its sign.  The sign is
     * stored in `sa'; 0 means `a' was positive or zero, and -1 means `a'
     * was negative.  (Similarly for `b' and `sb').
     *
     * Unfortunately, it doesn't work (at least not portably).
     *
     * It makes the assumption that right-shift on a negative signed value
     * fills the leftmost bits by copying the sign bit.  This is wrong.
     * According to K&R 2nd ed, section `A7.8 Shift Operators' on page 206,
     * the result of right-shift of a negative signed value is
     * implementation-defined.  At least one implementation fills the
     * leftmost bits with 0s (i.e., it is exactly the same as an unsigned
     * right shift).  This means that when `a' is negative, `sa' ends up
     * with the value 1 rather than -1.  After that, everything else goes
     * wrong.
     */
    sa = ( a_ >> ( sizeof ( a_ ) * 8 - 1 ) );
    a  = ( a_ ^ sa ) - sa;
    sb = ( b_ >> ( sizeof ( b_ ) * 8 - 1 ) );
    b  = ( b_ ^ sb ) - sb;

    a = (FT_UInt32)a_;
    b = (FT_UInt32)b_;

    if ( a + ( b >> 8 ) <= 8190UL )
      a = ( a * b + 0x8000U ) >> 16;
    else
    {
      FT_UInt32  al = a & 0xFFFFUL;

      a = ( a >> 16 ) * b + al * ( b >> 16 ) +
          ( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 );
    }

    sa ^= sb;
    a   = ( a ^ sa ) - sa;

    return (FT_Long)a;

#else /* 0 */

    FT_Int     s = 1;
    FT_UInt32  a, b;

    /* XXX: this function does not allow 64-bit arguments */

    a = (FT_UInt32)a_;
    b = (FT_UInt32)b_;

    FT_MOVE_SIGN( a_, a, s );
    FT_MOVE_SIGN( b_, b, s );

    if ( a + ( b >> 8 ) <= 8190UL )
      a = ( a * b + 0x8000UL ) >> 16;
    else
    {
      FT_UInt32  al = a & 0xFFFFUL;

      a = ( a >> 16 ) * b + al * ( b >> 16 ) +
          ( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 );
    }

    a_ = (FT_Long)a;

    return s < 0 ? NEG_LONG( a_ ) : a_;

#endif /* 0 */

  }

  /* documentation is in freetype.h */

  FT_EXPORT_DEF( FT_Long )
  FT_DivFix( FT_Long  a_,
             FT_Long  b_ )
  {
    FT_Int     s = 1;
    FT_UInt32  a, b, q;
    FT_Long    q_;

    /* XXX: this function does not allow 64-bit arguments */

    a = (FT_UInt32)a_;
    b = (FT_UInt32)b_;

    FT_MOVE_SIGN( a_, a, s );
    FT_MOVE_SIGN( b_, b, s );

    if ( b == 0 )
    {
      /* check for division by 0 */
      q = 0x7FFFFFFFUL;
    }
    else if ( a <= 65535UL - ( b >> 17 ) )
    {
      /* compute result directly */
      q = ( ( a << 16 ) + ( b >> 1 ) ) / b;
    }
    else
    {
      /* we need more bits; we have to do it by hand */
      FT_Int64  temp, temp2;

      temp.hi  = a >> 16;
      temp.lo  = a << 16;
      temp2.hi = 0;
      temp2.lo = b >> 1;

      FT_Add64( &temp, &temp2, &temp );
      q = ft_div64by32( temp.hi, temp.lo, b );
    }

    q_ = (FT_Long)q;

    return s < 0 ? NEG_LONG( q_ ) : q_;
  }

#endif /* !FT_LONG64 */

  /* documentation is in ftglyph.h */

  FT_EXPORT_DEF( void )
  FT_Matrix_Multiply( const FT_Matrix*  a,
                      FT_Matrix        *b )
  {
    FT_Fixed  xx, xy, yx, yy;

    if ( !a || !b )
      return;

    xx = ADD_LONG( FT_MulFix( a->xx, b->xx ),
                   FT_MulFix( a->xy, b->yx ) );
    xy = ADD_LONG( FT_MulFix( a->xx, b->xy ),
                   FT_MulFix( a->xy, b->yy ) );
    yx = ADD_LONG( FT_MulFix( a->yx, b->xx ),
                   FT_MulFix( a->yy, b->yx ) );
    yy = ADD_LONG( FT_MulFix( a->yx, b->xy ),
                   FT_MulFix( a->yy, b->yy ) );

    b->xx = xx;
    b->xy = xy;
    b->yx = yx;
    b->yy = yy;
  }

  /* documentation is in ftglyph.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Matrix_Invert( FT_Matrix*  matrix )
  {
    FT_Pos  delta, xx, yy;

    if ( !matrix )
      return FT_THROW( Invalid_Argument );

    /* compute discriminant */
    delta = FT_MulFix( matrix->xx, matrix->yy ) -
            FT_MulFix( matrix->xy, matrix->yx );

    if ( !delta )
      return FT_THROW( Invalid_Argument );  /* matrix can't be inverted */

    matrix->xy = -FT_DivFix( matrix->xy, delta );
    matrix->yx = -FT_DivFix( matrix->yx, delta );

    xx = matrix->xx;
    yy = matrix->yy;

    matrix->xx = FT_DivFix( yy, delta );
    matrix->yy = FT_DivFix( xx, delta );

    return FT_Err_Ok;
  }

  /* documentation is in ftcalc.h */

  FT_BASE_DEF( void )
  FT_Matrix_Multiply_Scaled( const FT_Matrix*  a,
                             FT_Matrix        *b,
                             FT_Long           scaling )
  {
    FT_Fixed  xx, xy, yx, yy;

    FT_Long   val = 0x10000L * scaling;

    if ( !a || !b )
      return;

    xx = ADD_LONG( FT_MulDiv( a->xx, b->xx, val ),
                   FT_MulDiv( a->xy, b->yx, val ) );
    xy = ADD_LONG( FT_MulDiv( a->xx, b->xy, val ),
                   FT_MulDiv( a->xy, b->yy, val ) );
    yx = ADD_LONG( FT_MulDiv( a->yx, b->xx, val ),
                   FT_MulDiv( a->yy, b->yx, val ) );
    yy = ADD_LONG( FT_MulDiv( a->yx, b->xy, val ),
                   FT_MulDiv( a->yy, b->yy, val ) );

    b->xx = xx;
    b->xy = xy;
    b->yx = yx;
    b->yy = yy;
  }

  /* documentation is in ftcalc.h */

  FT_BASE_DEF( FT_Bool )
  FT_Matrix_Check( const FT_Matrix*  matrix )
  {
    FT_Matrix  m;
    FT_Fixed   val[4];
    FT_Fixed   nonzero_minval, maxval;
    FT_Fixed   temp1, temp2;
    FT_UInt    i;

    if ( !matrix )
      return 0;

    val[0] = FT_ABS( matrix->xx );
    val[1] = FT_ABS( matrix->xy );
    val[2] = FT_ABS( matrix->yx );
    val[3] = FT_ABS( matrix->yy );

    /*
     * To avoid overflow, we ensure that each value is not larger than
     *
     *   int(sqrt(2^31 / 4)) = 23170  ;
     *
     * we also check that no value becomes zero if we have to scale.
     */

    maxval         = 0;
    nonzero_minval = FT_LONG_MAX;

    for ( i = 0; i < 4; i++ )
    {
      if ( val[i] > maxval )
        maxval = val[i];
      if ( val[i] && val[i] < nonzero_minval )
        nonzero_minval = val[i];
    }

    /* we only handle 32bit values */
    if ( maxval > 0x7FFFFFFFL )
      return 0;

    if ( maxval > 23170 )
    {
      FT_Fixed  scale = FT_DivFix( maxval, 23170 );

      if ( !FT_DivFix( nonzero_minval, scale ) )
        return 0;    /* value range too large */

      m.xx = FT_DivFix( matrix->xx, scale );
      m.xy = FT_DivFix( matrix->xy, scale );
      m.yx = FT_DivFix( matrix->yx, scale );
      m.yy = FT_DivFix( matrix->yy, scale );
    }
    else
      m = *matrix;

    temp1 = FT_ABS( m.xx * m.yy - m.xy * m.yx );
    temp2 = m.xx * m.xx + m.xy * m.xy + m.yx * m.yx + m.yy * m.yy;

    if ( temp1 == 0         ||
         temp2 / temp1 > 50 )
      return 0;

    return 1;
  }

  /* documentation is in ftcalc.h */

  FT_BASE_DEF( void )
  FT_Vector_Transform_Scaled( FT_Vector*        vector,
                              const FT_Matrix*  matrix,
                              FT_Long           scaling )
  {
    FT_Pos   xz, yz;

    FT_Long  val = 0x10000L * scaling;

    if ( !vector || !matrix )
      return;

    xz = ADD_LONG( FT_MulDiv( vector->x, matrix->xx, val ),
                   FT_MulDiv( vector->y, matrix->xy, val ) );
    yz = ADD_LONG( FT_MulDiv( vector->x, matrix->yx, val ),
                   FT_MulDiv( vector->y, matrix->yy, val ) );

    vector->x = xz;
    vector->y = yz;
  }

  /* documentation is in ftcalc.h */

  FT_BASE_DEF( FT_UInt32 )
  FT_Vector_NormLen( FT_Vector*  vector )
  {
    FT_Int32   x_ = vector->x;
    FT_Int32   y_ = vector->y;
    FT_Int32   b, z;
    FT_UInt32  x, y, u, v, l;
    FT_Int     sx = 1, sy = 1, shift;

    x = (FT_UInt32)x_;
    y = (FT_UInt32)y_;

    FT_MOVE_SIGN( x_, x, sx );
    FT_MOVE_SIGN( y_, y, sy );

    /* trivial cases */
    if ( x == 0 )
    {
      if ( y > 0 )
        vector->y = sy * 0x10000;
      return y;
    }
    else if ( y == 0 )
    {
      if ( x > 0 )
        vector->x = sx * 0x10000;
      return x;
    }

    /* Estimate length and prenormalize by shifting so that */
    /* the new approximate length is between 2/3 and 4/3.   */
    /* The magic constant 0xAAAAAAAAUL (2/3 of 2^32) helps  */
    /* achieve this in 16.16 fixed-point representation.    */
    l = x > y ? x + ( y >> 1 )
              : y + ( x >> 1 );

    shift  = 31 - FT_MSB( l );
    shift -= 15 + ( l >= ( 0xAAAAAAAAUL >> shift ) );

    if ( shift > 0 )
    {
      x <<= shift;
      y <<= shift;

      /* re-estimate length for tiny vectors */
      l = x > y ? x + ( y >> 1 )
                : y + ( x >> 1 );
    }
    else
    {
      x >>= -shift;
      y >>= -shift;
      l >>= -shift;
    }

    /* lower linear approximation for reciprocal length minus one */
    b = 0x10000 - (FT_Int32)l;

    x_ = (FT_Int32)x;
    y_ = (FT_Int32)y;

    /* Newton's iterations */
    do
    {
      u = (FT_UInt32)( x_ + ( x_ * b >> 16 ) );
      v = (FT_UInt32)( y_ + ( y_ * b >> 16 ) );

      /* Normalized squared length in the parentheses approaches 2^32. */
      /* On two's complement systems, converting to signed gives the   */
      /* difference with 2^32 even if the expression wraps around.     */
      z = -(FT_Int32)( u * u + v * v ) / 0x200;
      z = z * ( ( 0x10000 + b ) >> 8 ) / 0x10000;

      b += z;

    } while ( z > 0 );

    vector->x = sx < 0 ? -(FT_Pos)u : (FT_Pos)u;
    vector->y = sy < 0 ? -(FT_Pos)v : (FT_Pos)v;

    /* Conversion to signed helps to recover from likely wrap around */
    /* in calculating the prenormalized length, because it gives the */
    /* correct difference with 2^32 on two's complement systems.     */
    l = (FT_UInt32)( 0x10000 + (FT_Int32)( u * x + v * y ) / 0x10000 );
    if ( shift > 0 )
      l = ( l + ( 1 << ( shift - 1 ) ) ) >> shift;
    else
      l <<= -shift;

    return l;
  }

#if 0

  /* documentation is in ftcalc.h */

  FT_BASE_DEF( FT_Int32 )
  FT_SqrtFixed( FT_Int32  x )
  {
    FT_UInt32  root, rem_hi, rem_lo, test_div;
    FT_Int     count;

    root = 0;

    if ( x > 0 )
    {
      rem_hi = 0;
      rem_lo = (FT_UInt32)x;
      count  = 24;
      do
      {
        rem_hi   = ( rem_hi << 2 ) | ( rem_lo >> 30 );
        rem_lo <<= 2;
        root   <<= 1;
        test_div = ( root << 1 ) + 1;

        if ( rem_hi >= test_div )
        {
          rem_hi -= test_div;
          root   += 1;
        }
      } while ( --count );
    }

    return (FT_Int32)root;
  }

#endif /* 0 */

  /* documentation is in ftcalc.h */

  FT_BASE_DEF( FT_Int )
  ft_corner_orientation( FT_Pos  in_x,
                         FT_Pos  in_y,
                         FT_Pos  out_x,
                         FT_Pos  out_y )
  {
    /* we silently ignore overflow errors since such large values */
    /* lead to even more (harmless) rendering errors later on     */

#ifdef FT_LONG64

    FT_Int64  delta = SUB_INT64( MUL_INT64( in_x, out_y ),
                                 MUL_INT64( in_y, out_x ) );

    return ( delta > 0 ) - ( delta < 0 );

#else

    FT_Int  result;

    if ( ADD_LONG( FT_ABS( in_x ), FT_ABS( out_y ) ) <= 131071L &&
         ADD_LONG( FT_ABS( in_y ), FT_ABS( out_x ) ) <= 131071L )
    {
      FT_Long  z1 = MUL_LONG( in_x, out_y );
      FT_Long  z2 = MUL_LONG( in_y, out_x );

      if ( z1 > z2 )
        result = +1;
      else if ( z1 < z2 )
        result = -1;
      else
        result = 0;
    }
    else /* products might overflow 32 bits */
    {
      FT_Int64  z1, z2;

      /* XXX: this function does not allow 64-bit arguments */
      ft_multo64( (FT_UInt32)in_x, (FT_UInt32)out_y, &z1 );
      ft_multo64( (FT_UInt32)in_y, (FT_UInt32)out_x, &z2 );

      if ( z1.hi > z2.hi )
        result = +1;
      else if ( z1.hi < z2.hi )
        result = -1;
      else if ( z1.lo > z2.lo )
        result = +1;
      else if ( z1.lo < z2.lo )
        result = -1;
      else
        result = 0;
    }

    /* XXX: only the sign of return value, +1/0/-1 must be used */
    return result;

#endif
  }

  /* documentation is in ftcalc.h */

  FT_BASE_DEF( FT_Int )
  ft_corner_is_flat( FT_Pos  in_x,
                     FT_Pos  in_y,
                     FT_Pos  out_x,
                     FT_Pos  out_y )
  {
    FT_Pos  ax = in_x + out_x;
    FT_Pos  ay = in_y + out_y;

    FT_Pos  d_in, d_out, d_hypot;

    /* The idea of this function is to compare the length of the */
    /* hypotenuse with the `in' and `out' length.  The `corner'  */
    /* represented by `in' and `out' is flat if the hypotenuse's */
    /* length isn't too large.                                   */
    /*                                                           */
    /* This approach has the advantage that the angle between    */
    /* `in' and `out' is not checked.  In case one of the two    */
    /* vectors is `dominant', this is, much larger than the      */
    /* other vector, we thus always have a flat corner.          */
    /*                                                           */
    /*                hypotenuse                                 */
    /*       x---------------------------x                       */
    /*        \                      /                           */
    /*         \                /                                */
    /*      in  \          /  out                                */
    /*           \    /                                          */
    /*            o                                              */
    /*              Point                                        */

    d_in    = FT_HYPOT(  in_x,  in_y );
    d_out   = FT_HYPOT( out_x, out_y );
    d_hypot = FT_HYPOT(    ax,    ay );

    /* now do a simple length comparison: */
    /*                                    */
    /*   d_in + d_out < 17/16 d_hypot     */

    return ( d_in + d_out - d_hypot ) < ( d_hypot >> 4 );
  }

/* END */


text:
/*
 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
 * MD5 Message-Digest Algorithm (RFC 1321).
 *
 * Homepage:
 * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
 *
 * Author:
 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
 *
 * This software was written by Alexander Peslyak in 2001.  No copyright is
 * claimed, and the software is hereby placed in the public domain.
 * In case this attempt to disclaim copyright and place the software in the
 * public domain is deemed null and void, then the software is
 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
 * general public under the following terms:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted.
 *
 * There's ABSOLUTELY NO WARRANTY, express or implied.
 *
 * See md5.c for more information.
 */

#ifdef HAVE_OPENSSL
#include <openssl/md5.h>
#elif !defined(_MD5_H)
#define _MD5_H

/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;

typedef struct {
	MD5_u32plus lo, hi;
	MD5_u32plus a, b, c, d;
	unsigned char buffer[64];
	MD5_u32plus block[16];
} MD5_CTX;

extern void MD5_Init(MD5_CTX *ctx);
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);

#endif


text:
/*
 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
 * MD5 Message-Digest Algorithm (RFC 1321).
 *
 * Homepage:
 * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
 *
 * Author:
 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
 *
 * This software was written by Alexander Peslyak in 2001.  No copyright is
 * claimed, and the software is hereby placed in the public domain.
 * In case this attempt to disclaim copyright and place the software in the
 * public domain is deemed null and void, then the software is
 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
 * general public under the following terms:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted.
 *
 * There's ABSOLUTELY NO WARRANTY, express or implied.
 *
 * (This is a heavily cut-down "BSD license".)
 *
 * This differs from Colin Plumb's older public domain implementation in that
 * no exactly 32-bit integer data type is required (any 32-bit or wider
 * unsigned integer data type will do), there's no compile-time endianness
 * configuration, and the function prototypes match OpenSSL's.  No code from
 * Colin Plumb's implementation has been reused; this comment merely compares
 * the properties of the two independent implementations.
 *
 * The primary goals of this implementation are portability and ease of use.
 * It is meant to be fast, but not as fast as possible.  Some known
 * optimizations are not included to reduce source code size and avoid
 * compile-time configuration.
 */

#ifndef HAVE_OPENSSL

#include <string.h>

#include "md5.h"

/*
 * The basic MD5 functions.
 *
 * F and G are optimized compared to their RFC 1321 definitions for
 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
 * implementation.
 */
#define F(x, y, z)			((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z)			((y) ^ ((z) & ((x) ^ (y))))
#define H(x, y, z)			(((x) ^ (y)) ^ (z))
#define H2(x, y, z)			((x) ^ ((y) ^ (z)))
#define I(x, y, z)			((y) ^ ((x) | ~(z)))

/*
 * The MD5 transformation for all four rounds.
 */
#define STEP(f, a, b, c, d, x, t, s) \
	(a) += f((b), (c), (d)) + (x) + (t); \
	(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
	(a) += (b);

/*
 * SET reads 4 input bytes in little-endian byte order and stores them in a
 * properly aligned word in host byte order.
 *
 * The check for little-endian architectures that tolerate unaligned memory
 * accesses is just an optimization.  Nothing will break if it fails to detect
 * a suitable architecture.
 *
 * Unfortunately, this optimization may be a C strict aliasing rules violation
 * if the caller's data buffer has effective type that cannot be aliased by
 * MD5_u32plus.  In practice, this problem may occur if these MD5 routines are
 * inlined into a calling function, or with future and dangerously advanced
 * link-time optimizations.  For the time being, keeping these MD5 routines in
 * their own translation unit avoids the problem.
 */
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
	(*(MD5_u32plus *)&ptr[(n) * 4])
#define GET(n) \
	SET(n)
#else
#define SET(n) \
	(ctx->block[(n)] = \
	(MD5_u32plus)ptr[(n) * 4] | \
	((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
	((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
	((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
	(ctx->block[(n)])
#endif

/*
 * This processes one or more 64-byte data blocks, but does NOT update the bit
 * counters.  There are no alignment requirements.
 */
static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
{
	const unsigned char *ptr;
	MD5_u32plus a, b, c, d;
	MD5_u32plus saved_a, saved_b, saved_c, saved_d;

	ptr = (const unsigned char *)data;

	a = ctx->a;
	b = ctx->b;
	c = ctx->c;
	d = ctx->d;

	do {
		saved_a = a;
		saved_b = b;
		saved_c = c;
		saved_d = d;

/* Round 1 */
		STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
		STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
		STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
		STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
		STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
		STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
		STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
		STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
		STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
		STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
		STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
		STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
		STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
		STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
		STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
		STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)

/* Round 2 */
		STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
		STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
		STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
		STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
		STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
		STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
		STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
		STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
		STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
		STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
		STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
		STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
		STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
		STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
		STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
		STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)

/* Round 3 */
		STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
		STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
		STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
		STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
		STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
		STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
		STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
		STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
		STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
		STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
		STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
		STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
		STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
		STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
		STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
		STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)

/* Round 4 */
		STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
		STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
		STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
		STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
		STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
		STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
		STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
		STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
		STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
		STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
		STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
		STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
		STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
		STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
		STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
		STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)

		a += saved_a;
		b += saved_b;
		c += saved_c;
		d += saved_d;

		ptr += 64;
	} while (size -= 64);

	ctx->a = a;
	ctx->b = b;
	ctx->c = c;
	ctx->d = d;

	return ptr;
}

void MD5_Init(MD5_CTX *ctx)
{
	ctx->a = 0x67452301;
	ctx->b = 0xefcdab89;
	ctx->c = 0x98badcfe;
	ctx->d = 0x10325476;

	ctx->lo = 0;
	ctx->hi = 0;
}

void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
{
	MD5_u32plus saved_lo;
	unsigned long used, available;

	saved_lo = ctx->lo;
	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
		ctx->hi++;
	ctx->hi += size >> 29;

	used = saved_lo & 0x3f;

	if (used) {
		available = 64 - used;

		if (size < available) {
			memcpy(&ctx->buffer[used], data, size);
			return;
		}

		memcpy(&ctx->buffer[used], data, available);
		data = (const unsigned char *)data + available;
		size -= available;
		body(ctx, ctx->buffer, 64);
	}

	if (size >= 64) {
		data = body(ctx, data, size & ~(unsigned long)0x3f);
		size &= 0x3f;
	}

	memcpy(ctx->buffer, data, size);
}

#define OUT(dst, src) \
	(dst)[0] = (unsigned char)(src); \
	(dst)[1] = (unsigned char)((src) >> 8); \
	(dst)[2] = (unsigned char)((src) >> 16); \
	(dst)[3] = (unsigned char)((src) >> 24);

void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
	unsigned long used, available;

	used = ctx->lo & 0x3f;

	ctx->buffer[used++] = 0x80;

	available = 64 - used;

	if (available < 8) {
		memset(&ctx->buffer[used], 0, available);
		body(ctx, ctx->buffer, 64);
		used = 0;
		available = 64;
	}

	memset(&ctx->buffer[used], 0, available - 8);

	ctx->lo <<= 3;
	OUT(&ctx->buffer[56], ctx->lo)
	OUT(&ctx->buffer[60], ctx->hi)

	body(ctx, ctx->buffer, 64);

	OUT(&result[0], ctx->a)
	OUT(&result[4], ctx->b)
	OUT(&result[8], ctx->c)
	OUT(&result[12], ctx->d)

	memset(ctx, 0, sizeof(*ctx));
}

#endif


text:
/****************************************************************************
 *
 * ftbitmap.c
 *
 *   FreeType utility functions for bitmaps (body).
 *
 * Copyright (C) 2004-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.
 *
 */

#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H

#include FT_BITMAP_H
#include FT_IMAGE_H
#include FT_INTERNAL_OBJECTS_H

  /**************************************************************************
   *
   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
   * messages during execution.
   */
#undef  FT_COMPONENT
#define FT_COMPONENT  bitmap

  static
  const FT_Bitmap  null_bitmap = { 0, 0, 0, NULL, 0, 0, 0, NULL };

  /* documentation is in ftbitmap.h */

  FT_EXPORT_DEF( void )
  FT_Bitmap_Init( FT_Bitmap  *abitmap )
  {
    if ( abitmap )
      *abitmap = null_bitmap;
  }

  /* deprecated function name; retained for ABI compatibility */

  FT_EXPORT_DEF( void )
  FT_Bitmap_New( FT_Bitmap  *abitmap )
  {
    if ( abitmap )
      *abitmap = null_bitmap;
  }

  /* documentation is in ftbitmap.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Bitmap_Copy( FT_Library        library,
                  const FT_Bitmap  *source,
                  FT_Bitmap        *target)
  {
    FT_Memory  memory;
    FT_Error   error  = FT_Err_Ok;

    FT_Int    pitch;
    FT_ULong  size;

    FT_Int  source_pitch_sign, target_pitch_sign;

    if ( !library )
      return FT_THROW( Invalid_Library_Handle );

    if ( !source || !target )
      return FT_THROW( Invalid_Argument );

    if ( source == target )
      return FT_Err_Ok;

    source_pitch_sign = source->pitch < 0 ? -1 : 1;
    target_pitch_sign = target->pitch < 0 ? -1 : 1;

    if ( !source->buffer )
    {
      *target = *source;
      if ( source_pitch_sign != target_pitch_sign )
        target->pitch = -target->pitch;

      return FT_Err_Ok;
    }

    memory = library->memory;
    pitch  = source->pitch;

    if ( pitch < 0 )
      pitch = -pitch;
    size = (FT_ULong)pitch * source->rows;

    if ( target->buffer )
    {
      FT_Int    target_pitch = target->pitch;
      FT_ULong  target_size;

      if ( target_pitch < 0 )
        target_pitch = -target_pitch;
      target_size = (FT_ULong)target_pitch * target->rows;

      if ( target_size != size )
        (void)FT_QREALLOC( target->buffer, target_size, size );
    }
    else
      (void)FT_QALLOC( target->buffer, size );

    if ( !error )
    {
      unsigned char *p;

      p = target->buffer;
      *target = *source;
      target->buffer = p;

      if ( source_pitch_sign == target_pitch_sign )
        FT_MEM_COPY( target->buffer, source->buffer, size );
      else
      {
        /* take care of bitmap flow */
        FT_UInt   i;
        FT_Byte*  s = source->buffer;
        FT_Byte*  t = target->buffer;

        t += (FT_ULong)pitch * ( target->rows - 1 );

        for ( i = target->rows; i > 0; i-- )
        {
          FT_ARRAY_COPY( t, s, pitch );

          s += pitch;
          t -= pitch;
        }
      }
    }

    return error;
  }

  /* Enlarge `bitmap' horizontally and vertically by `xpixels' */
  /* and `ypixels', respectively.                              */

  static FT_Error
  ft_bitmap_assure_buffer( FT_Memory   memory,
                           FT_Bitmap*  bitmap,
                           FT_UInt     xpixels,
                           FT_UInt     ypixels )
  {
    FT_Error        error;
    unsigned int    pitch;
    unsigned int    new_pitch;
    FT_UInt         bpp;
    FT_UInt         width, height;
    unsigned char*  buffer = NULL;

    width  = bitmap->width;
    height = bitmap->rows;
    pitch  = (unsigned int)FT_ABS( bitmap->pitch );

    switch ( bitmap->pixel_mode )
    {
    case FT_PIXEL_MODE_MONO:
      bpp       = 1;
      new_pitch = ( width + xpixels + 7 ) >> 3;
      break;
    case FT_PIXEL_MODE_GRAY2:
      bpp       = 2;
      new_pitch = ( width + xpixels + 3 ) >> 2;
      break;
    case FT_PIXEL_MODE_GRAY4:
      bpp       = 4;
      new_pitch = ( width + xpixels + 1 ) >> 1;
      break;
    case FT_PIXEL_MODE_GRAY:
    case FT_PIXEL_MODE_LCD:
    case FT_PIXEL_MODE_LCD_V:
      bpp       = 8;
      new_pitch = width + xpixels;
      break;
    default:
      return FT_THROW( Invalid_Glyph_Format );
    }

    /* if no need to allocate memory */
    if ( ypixels == 0 && new_pitch <= pitch )
    {
      /* zero the padding */
      FT_UInt  bit_width = pitch * 8;
      FT_UInt  bit_last  = ( width + xpixels ) * bpp;

      if ( bit_last < bit_width )
      {
        FT_Byte*  line  = bitmap->buffer + ( bit_last >> 3 );
        FT_Byte*  end   = bitmap->buffer + pitch;
        FT_UInt   shift = bit_last & 7;
        FT_UInt   mask  = 0xFF00U >> shift;
        FT_UInt   count = height;

        for ( ; count > 0; count--, line += pitch, end += pitch )
        {
          FT_Byte*  write = line;

          if ( shift > 0 )
          {
            write[0] = (FT_Byte)( write[0] & mask );
            write++;
          }
          if ( write < end )
            FT_MEM_ZERO( write, end - write );
        }
      }

      return FT_Err_Ok;
    }

    /* otherwise allocate new buffer */
    if ( FT_QALLOC_MULT( buffer, bitmap->rows + ypixels, new_pitch ) )
      return error;

    /* new rows get added at the top of the bitmap, */
    /* thus take care of the flow direction         */
    if ( bitmap->pitch > 0 )
    {
      FT_UInt  len = ( width * bpp + 7 ) >> 3;

      unsigned char*  in  = bitmap->buffer;
      unsigned char*  out = buffer;

      unsigned char*  limit = bitmap->buffer + pitch * bitmap->rows;
      unsigned int    delta = new_pitch - len;

      FT_MEM_ZERO( out, new_pitch * ypixels );
      out += new_pitch * ypixels;

      while ( in < limit )
      {
        FT_MEM_COPY( out, in, len );
        in  += pitch;
        out += len;

        /* we use FT_QALLOC_MULT, which doesn't zero out the buffer;      */
        /* consequently, we have to manually zero out the remaining bytes */
        FT_MEM_ZERO( out, delta );
        out += delta;
      }
    }
    else
    {
      FT_UInt  len = ( width * bpp + 7 ) >> 3;

      unsigned char*  in  = bitmap->buffer;
      unsigned char*  out = buffer;

      unsigned char*  limit = bitmap->buffer + pitch * bitmap->rows;
      unsigned int    delta = new_pitch - len;

      while ( in < limit )
      {
        FT_MEM_COPY( out, in, len );
        in  += pitch;
        out += len;

        FT_MEM_ZERO( out, delta );
        out += delta;
      }

      FT_MEM_ZERO( out, new_pitch * ypixels );
    }

    FT_FREE( bitmap->buffer );
    bitmap->buffer = buffer;

    /* set pitch only, width and height are left untouched */
    if ( bitmap->pitch < 0 )
      bitmap->pitch = -(int)new_pitch;
    else
      bitmap->pitch = (int)new_pitch;

    return FT_Err_Ok;
  }

  /* documentation is in ftbitmap.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Bitmap_Embolden( FT_Library  library,
                      FT_Bitmap*  bitmap,
                      FT_Pos      xStrength,
                      FT_Pos      yStrength )
  {
    FT_Error        error;
    unsigned char*  p;
    FT_Int          i, x, pitch;
    FT_UInt         y;
    FT_Int          xstr, ystr;

    if ( !library )
      return FT_THROW( Invalid_Library_Handle );

    if ( !bitmap || !bitmap->buffer )
      return FT_THROW( Invalid_Argument );

    if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
         ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
      return FT_THROW( Invalid_Argument );

    xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;
    ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;

    if ( xstr == 0 && ystr == 0 )
      return FT_Err_Ok;
    else if ( xstr < 0 || ystr < 0 )
      return FT_THROW( Invalid_Argument );

    switch ( bitmap->pixel_mode )
    {
    case FT_PIXEL_MODE_GRAY2:
    case FT_PIXEL_MODE_GRAY4:
      {
        FT_Bitmap  tmp;

        /* convert to 8bpp */
        FT_Bitmap_Init( &tmp );
        error = FT_Bitmap_Convert( library, bitmap, &tmp, 1 );
        if ( error )
          return error;

        FT_Bitmap_Done( library, bitmap );
        *bitmap = tmp;
      }
      break;

    case FT_PIXEL_MODE_MONO:
      if ( xstr > 8 )
        xstr = 8;
      break;

    case FT_PIXEL_MODE_LCD:
      xstr *= 3;
      break;

    case FT_PIXEL_MODE_LCD_V:
      ystr *= 3;
      break;

    case FT_PIXEL_MODE_BGRA:
      /* We don't embolden color glyphs. */
      return FT_Err_Ok;
    }

    error = ft_bitmap_assure_buffer( library->memory, bitmap,
                                     (FT_UInt)xstr, (FT_UInt)ystr );
    if ( error )
      return error;

    /* take care of bitmap flow */
    pitch = bitmap->pitch;
    if ( pitch > 0 )
      p = bitmap->buffer + pitch * ystr;
    else
    {
      pitch = -pitch;
      p = bitmap->buffer + (FT_UInt)pitch * ( bitmap->rows - 1 );
    }

    /* for each row */
    for ( y = 0; y < bitmap->rows; y++ )
    {
      /*
       * Horizontally:
       *
       * From the last pixel on, make each pixel or'ed with the
       * `xstr' pixels before it.
       */
      for ( x = pitch - 1; x >= 0; x-- )
      {
        unsigned char  tmp;

        tmp = p[x];
        for ( i = 1; i <= xstr; i++ )
        {
          if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )
          {
            p[x] |= tmp >> i;

            /* the maximum value of 8 for `xstr' comes from here */
            if ( x > 0 )
              p[x] |= p[x - 1] << ( 8 - i );

#if 0
            if ( p[x] == 0xFF )
              break;
#endif
          }
          else
          {
            if ( x - i >= 0 )
            {
              if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
              {
                p[x] = (unsigned char)( bitmap->num_grays - 1 );
                break;
              }
              else
              {
                p[x] = (unsigned char)( p[x] + p[x - i] );
                if ( p[x] == bitmap->num_grays - 1 )
                  break;
              }
            }
            else
              break;
          }
        }
      }

      /*
       * Vertically:
       *
       * Make the above `ystr' rows or'ed with it.
       */
      for ( x = 1; x <= ystr; x++ )
      {
        unsigned char*  q;

        q = p - bitmap->pitch * x;
        for ( i = 0; i < pitch; i++ )
          q[i] |= p[i];
      }

      p += bitmap->pitch;
    }

    bitmap->width += (FT_UInt)xstr;
    bitmap->rows += (FT_UInt)ystr;

    return FT_Err_Ok;
  }

  static FT_Byte
  ft_gray_for_premultiplied_srgb_bgra( const FT_Byte*  bgra )
  {
    FT_UInt  a = bgra[3];
    FT_UInt  l;

    /* Short-circuit transparent color to avoid division by zero. */
    if ( !a )
      return 0;

    /*
     * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722
     * coefficients for RGB channels *on the linear colors*.
     * A gamma of 2.2 is fair to assume.  And then, we need to
     * undo the premultiplication too.
     *
     *   https://accessibility.kde.org/hsl-adjusted.php
     *
     * We do the computation with integers only, applying a gamma of 2.0.
     * We guarantee 32-bit arithmetic to avoid overflow but the resulting
     * luminosity fits into 16 bits.
     *
     */

    l = (  4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] +
          46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] +
          13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16;

    /*
     * Final transparency can be determined as follows.
     *
     * - If alpha is zero, we want 0.
     * - If alpha is zero and luminosity is zero, we want 255.
     * - If alpha is zero and luminosity is one, we want 0.
     *
     * So the formula is a * (1 - l) = a - l * a.
     *
     * We still need to undo premultiplication by dividing l by a*a.
     *
     */

    return (FT_Byte)( a - l / a );
  }

  /* documentation is in ftbitmap.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Bitmap_Convert( FT_Library        library,
                     const FT_Bitmap  *source,
                     FT_Bitmap        *target,
                     FT_Int            alignment )
  {
    FT_Error   error = FT_Err_Ok;
    FT_Memory  memory;

    FT_Byte*  s;
    FT_Byte*  t;

    if ( !library )
      return FT_THROW( Invalid_Library_Handle );

    if ( !source || !target )
      return FT_THROW( Invalid_Argument );

    memory = library->memory;

    switch ( source->pixel_mode )
    {
    case FT_PIXEL_MODE_MONO:
    case FT_PIXEL_MODE_GRAY:
    case FT_PIXEL_MODE_GRAY2:
    case FT_PIXEL_MODE_GRAY4:
    case FT_PIXEL_MODE_LCD:
    case FT_PIXEL_MODE_LCD_V:
    case FT_PIXEL_MODE_BGRA:
      {
        FT_Int    pad, old_target_pitch, target_pitch;
        FT_ULong  old_size;

        old_target_pitch = target->pitch;
        if ( old_target_pitch < 0 )
          old_target_pitch = -old_target_pitch;

        old_size = target->rows * (FT_UInt)old_target_pitch;

        target->pixel_mode = FT_PIXEL_MODE_GRAY;
        target->rows       = source->rows;
        target->width      = source->width;

        pad = 0;
        if ( alignment > 0 )
        {
          pad = (FT_Int)source->width % alignment;
          if ( pad != 0 )
            pad = alignment - pad;
        }

        target_pitch = (FT_Int)source->width + pad;

        if ( target_pitch > 0                                               &&
             (FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch )
          return FT_THROW( Invalid_Argument );

        if ( FT_QREALLOC( target->buffer,
                          old_size, target->rows * (FT_UInt)target_pitch ) )
          return error;

        target->pitch = target->pitch < 0 ? -target_pitch : target_pitch;
      }
      break;

    default:
      error = FT_THROW( Invalid_Argument );
    }

    s = source->buffer;
    t = target->buffer;

    /* take care of bitmap flow */
    if ( source->pitch < 0 )
      s -= source->pitch * (FT_Int)( source->rows - 1 );
    if ( target->pitch < 0 )
      t -= target->pitch * (FT_Int)( target->rows - 1 );

    switch ( source->pixel_mode )
    {
    case FT_PIXEL_MODE_MONO:
      {
        FT_UInt  i;

        target->num_grays = 2;

        for ( i = source->rows; i > 0; i-- )
        {
          FT_Byte*  ss = s;
          FT_Byte*  tt = t;
          FT_UInt   j;

          /* get the full bytes */
          for ( j = source->width >> 3; j > 0; j-- )
          {
            FT_Int  val = ss[0]; /* avoid a byte->int cast on each line */

            tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
            tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
            tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
            tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
            tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
            tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
            tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
            tt[7] = (FT_Byte)(   val & 0x01 );

            tt += 8;
            ss += 1;
          }

          /* get remaining pixels (if any) */
          j = source->width & 7;
          if ( j > 0 )
          {
            FT_Int  val = *ss;

            for ( ; j > 0; j-- )
            {
              tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
              val <<= 1;
              tt   += 1;
            }
          }

          s += source->pitch;
          t += target->pitch;
        }
      }
      break;

    case FT_PIXEL_MODE_GRAY:
    case FT_PIXEL_MODE_LCD:
    case FT_PIXEL_MODE_LCD_V:
      {
        FT_UInt  width = source->width;
        FT_UInt  i;

        target->num_grays = 256;

        for ( i = source->rows; i > 0; i-- )
        {
          FT_ARRAY_COPY( t, s, width );

          s += source->pitch;
          t += target->pitch;
        }
      }
      break;

    case FT_PIXEL_MODE_GRAY2:
      {
        FT_UInt  i;

        target->num_grays = 4;

        for ( i = source->rows; i > 0; i-- )
        {
          FT_Byte*  ss = s;
          FT_Byte*  tt = t;
          FT_UInt   j;

          /* get the full bytes */
          for ( j = source->width >> 2; j > 0; j-- )
          {
            FT_Int  val = ss[0];

            tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
            tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
            tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
            tt[3] = (FT_Byte)( ( val & 0x03 ) );

            ss += 1;
            tt += 4;
          }

          j = source->width & 3;
          if ( j > 0 )
          {
            FT_Int  val = ss[0];

            for ( ; j > 0; j-- )
            {
              tt[0]  = (FT_Byte)( ( val & 0xC0 ) >> 6 );
              val  <<= 2;
              tt    += 1;
            }
          }

          s += source->pitch;
          t += target->pitch;
        }
      }
      break;

    case FT_PIXEL_MODE_GRAY4:
      {
        FT_UInt  i;

        target->num_grays = 16;

        for ( i = source->rows; i > 0; i-- )
        {
          FT_Byte*  ss = s;
          FT_Byte*  tt = t;
          FT_UInt   j;

          /* get the full bytes */
          for ( j = source->width >> 1; j > 0; j-- )
          {
            FT_Int  val = ss[0];

            tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
            tt[1] = (FT_Byte)( ( val & 0x0F ) );

            ss += 1;
            tt += 2;
          }

          if ( source->width & 1 )
            tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );

          s += source->pitch;
          t += target->pitch;
        }
      }
      break;

    case FT_PIXEL_MODE_BGRA:
      {
        FT_UInt  i;

        target->num_grays = 256;

        for ( i = source->rows; i > 0; i-- )
        {
          FT_Byte*  ss = s;
          FT_Byte*  tt = t;
          FT_UInt   j;

          for ( j = source->width; j > 0; j-- )
          {
            tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss );

            ss += 4;
            tt += 1;
          }

          s += source->pitch;
          t += target->pitch;
        }
      }
      break;

    default:
      ;
    }

    return error;
  }

  /* documentation is in ftbitmap.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Bitmap_Blend( FT_Library        library,
                   const FT_Bitmap*  source_,
                   const FT_Vector   source_offset_,
                   FT_Bitmap*        target,
                   FT_Vector        *atarget_offset,
                   FT_Color          color )
  {
    FT_Error   error = FT_Err_Ok;
    FT_Memory  memory;

    FT_Bitmap         source_bitmap;
    const FT_Bitmap*  source;

    FT_Vector  source_offset;
    FT_Vector  target_offset;

    FT_Bool  free_source_bitmap          = 0;
    FT_Bool  free_target_bitmap_on_error = 0;

    FT_Pos  source_llx, source_lly, source_urx, source_ury;
    FT_Pos  target_llx, target_lly, target_urx, target_ury;
    FT_Pos  final_llx, final_lly, final_urx, final_ury;

    unsigned int  final_rows, final_width;
    long          x, y;

    if ( !library || !target || !source_ || !atarget_offset )
      return FT_THROW( Invalid_Argument );

    memory = library->memory;

    if ( !( target->pixel_mode == FT_PIXEL_MODE_NONE     ||
            ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
              target->buffer                           ) ) )
      return FT_THROW( Invalid_Argument );

    if ( source_->pixel_mode == FT_PIXEL_MODE_NONE )
      return FT_Err_Ok;               /* nothing to do */

    /* pitches must have the same sign */
    if ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
         ( source_->pitch ^ target->pitch ) < 0   )
      return FT_THROW( Invalid_Argument );

    if ( !( source_->width && source_->rows ) )
      return FT_Err_Ok;               /* nothing to do */

    /* assure integer pixel offsets */
    source_offset.x = FT_PIX_FLOOR( source_offset_.x );
    source_offset.y = FT_PIX_FLOOR( source_offset_.y );
    target_offset.x = FT_PIX_FLOOR( atarget_offset->x );
    target_offset.y = FT_PIX_FLOOR( atarget_offset->y );

    /* get source bitmap dimensions */
    source_llx = source_offset.x;
    if ( FT_LONG_MIN + (FT_Pos)( source_->rows << 6 ) + 64 > source_offset.y )
    {
      FT_TRACE5((
        "FT_Bitmap_Blend: y coordinate overflow in source bitmap\n" ));
      return FT_THROW( Invalid_Argument );
    }
    source_lly = source_offset.y - ( source_->rows << 6 );

    if ( FT_LONG_MAX - (FT_Pos)( source_->width << 6 ) - 64 < source_llx )
    {
      FT_TRACE5((
        "FT_Bitmap_Blend: x coordinate overflow in source bitmap\n" ));
      return FT_THROW( Invalid_Argument );
    }
    source_urx = source_llx + ( source_->width << 6 );
    source_ury = source_offset.y;

    /* get target bitmap dimensions */
    if ( target->width && target->rows )
    {
      target_llx = target_offset.x;
      if ( FT_LONG_MIN + (FT_Pos)( target->rows << 6 ) > target_offset.y )
      {
        FT_TRACE5((
          "FT_Bitmap_Blend: y coordinate overflow in target bitmap\n" ));
        return FT_THROW( Invalid_Argument );
      }
      target_lly = target_offset.y - ( target->rows << 6 );

      if ( FT_LONG_MAX - (FT_Pos)( target->width << 6 ) < target_llx )
      {
        FT_TRACE5((
          "FT_Bitmap_Blend: x coordinate overflow in target bitmap\n" ));
        return FT_THROW( Invalid_Argument );
      }
      target_urx = target_llx + ( target->width << 6 );
      target_ury = target_offset.y;
    }
    else
    {
      target_llx = FT_LONG_MAX;
      target_lly = FT_LONG_MAX;
      target_urx = FT_LONG_MIN;
      target_ury = FT_LONG_MIN;
    }

    /* compute final bitmap dimensions */
    final_llx = FT_MIN( source_llx, target_llx );
    final_lly = FT_MIN( source_lly, target_lly );
    final_urx = FT_MAX( source_urx, target_urx );
    final_ury = FT_MAX( source_ury, target_ury );

    final_width = ( final_urx - final_llx ) >> 6;
    final_rows  = ( final_ury - final_lly ) >> 6;

#ifdef FT_DEBUG_LEVEL_TRACE
    FT_TRACE5(( "FT_Bitmap_Blend:\n"
                "  source bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
      source_llx / 64, source_lly / 64,
      source_urx / 64, source_ury / 64,
      source_->width, source_->rows ));

    if ( target->width && target->rows )
      FT_TRACE5(( "  target bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
        target_llx / 64, target_lly / 64,
        target_urx / 64, target_ury / 64,
        target->width, target->rows ));
    else
      FT_TRACE5(( "  target bitmap: empty\n" ));

    if ( final_width && final_rows )
      FT_TRACE5(( "  final bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
        final_llx / 64, final_lly / 64,
        final_urx / 64, final_ury / 64,
        final_width, final_rows ));
    else
      FT_TRACE5(( "  final bitmap: empty\n" ));
#endif /* FT_DEBUG_LEVEL_TRACE */

    if ( !( final_width && final_rows ) )
      return FT_Err_Ok;               /* nothing to do */

    /* for blending, set offset vector of final bitmap */
    /* temporarily to (0,0)                            */
    source_llx -= final_llx;
    source_lly -= final_lly;

    if ( target->width && target->rows )
    {
      target_llx -= final_llx;
      target_lly -= final_lly;
    }

    /* set up target bitmap */
    if ( target->pixel_mode == FT_PIXEL_MODE_NONE )
    {
      /* create new empty bitmap */
      target->width      = final_width;
      target->rows       = final_rows;
      target->pixel_mode = FT_PIXEL_MODE_BGRA;
      target->pitch      = (int)final_width * 4;
      target->num_grays  = 256;

      if ( FT_LONG_MAX / target->pitch < (int)target->rows )
      {
        FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
                     final_width, final_rows ));
        return FT_THROW( Invalid_Argument );
      }

      if ( FT_ALLOC( target->buffer, target->pitch * (int)target->rows ) )
        return error;

      free_target_bitmap_on_error = 1;
    }
    else if ( target->width != final_width ||
              target->rows  != final_rows  )
    {
      /* adjust old bitmap to enlarged size */
      int  pitch, new_pitch;

      unsigned char*  buffer = NULL;

      pitch = target->pitch;

      if ( pitch < 0 )
        pitch = -pitch;

      new_pitch = (int)final_width * 4;

      if ( FT_LONG_MAX / new_pitch < (int)final_rows )
      {
        FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
                     final_width, final_rows ));
        return FT_THROW( Invalid_Argument );
      }

      /* TODO: provide an in-buffer solution for large bitmaps */
      /*       to avoid allocation of a new buffer             */
      if ( FT_ALLOC( buffer, new_pitch * (int)final_rows ) )
        goto Error;

      /* copy data to new buffer */
      x = target_llx >> 6;
      y = target_lly >> 6;

      /* the bitmap flow is from top to bottom, */
      /* but y is measured from bottom to top   */
      if ( target->pitch < 0 )
      {
        /* XXX */
      }
      else
      {
        unsigned char*  p =
          target->buffer;
        unsigned char*  q =
          buffer +
          ( final_rows - y - target->rows ) * new_pitch +
          x * 4;
        unsigned char*  limit_p =
          p + pitch * (int)target->rows;

        while ( p < limit_p )
        {
          FT_MEM_COPY( q, p, pitch );

          p += pitch;
          q += new_pitch;
        }
      }

      FT_FREE( target->buffer );

      target->width = final_width;
      target->rows  = final_rows;

      if ( target->pitch < 0 )
        target->pitch = -new_pitch;
      else
        target->pitch = new_pitch;

      target->buffer = buffer;
    }

    /* adjust source bitmap if necessary */
    if ( source_->pixel_mode != FT_PIXEL_MODE_GRAY )
    {
      FT_Bitmap_Init( &source_bitmap );
      error = FT_Bitmap_Convert( library, source_, &source_bitmap, 1 );
      if ( error )
        goto Error;

      source             = &source_bitmap;
      free_source_bitmap = 1;
    }
    else
      source = source_;

    /* do blending; the code below returns pre-multiplied channels, */
    /* similar to what FreeType gets from `CBDT' tables             */
    x = source_llx >> 6;
    y = source_lly >> 6;

    /* the bitmap flow is from top to bottom, */
    /* but y is measured from bottom to top   */
    if ( target->pitch < 0 )
    {
      /* XXX */
    }
    else
    {
      unsigned char*  p =
        source->buffer;
      unsigned char*  q =
        target->buffer +
        ( target->rows - y - source->rows ) * target->pitch +
        x * 4;
      unsigned char*  limit_p =
        p + source->pitch * (int)source->rows;

      while ( p < limit_p )
      {
        unsigned char*  r       = p;
        unsigned char*  s       = q;
        unsigned char*  limit_r = r + source->width;

        while ( r < limit_r )
        {
          int  aa = *r++;
          int  fa = color.alpha * aa / 255;

          int  fb = color.blue * fa / 255;
          int  fg = color.green * fa / 255;
          int  fr = color.red * fa / 255;

          int  ba2 = 255 - fa;

          int  bb = s[0];
          int  bg = s[1];
          int  br = s[2];
          int  ba = s[3];

          *s++ = (unsigned char)( bb * ba2 / 255 + fb );
          *s++ = (unsigned char)( bg * ba2 / 255 + fg );
          *s++ = (unsigned char)( br * ba2 / 255 + fr );
          *s++ = (unsigned char)( ba * ba2 / 255 + fa );
        }

        p += source->pitch;
        q += target->pitch;
      }
    }

    atarget_offset->x = final_llx;
    atarget_offset->y = final_lly + ( final_rows << 6 );

  Error:
    if ( error && free_target_bitmap_on_error )
      FT_Bitmap_Done( library, target );

    if ( free_source_bitmap )
      FT_Bitmap_Done( library, &source_bitmap );

    return error;
  }

  /* documentation is in ftbitmap.h */

  FT_EXPORT_DEF( FT_Error )
  FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot  slot )
  {
    if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP   &&
         !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
    {
      FT_Bitmap  bitmap;
      FT_Error   error;

      FT_Bitmap_Init( &bitmap );
      error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
      if ( error )
        return error;

      slot->bitmap = bitmap;
      slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
    }

    return FT_Err_Ok;
  }

  /* documentation is in ftbitmap.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Bitmap_Done( FT_Library  library,
                  FT_Bitmap  *bitmap )
  {
    FT_Memory  memory;

    if ( !library )
      return FT_THROW( Invalid_Library_Handle );

    if ( !bitmap )
      return FT_THROW( Invalid_Argument );

    memory = library->memory;

    FT_FREE( bitmap->buffer );
    *bitmap = null_bitmap;

    return FT_Err_Ok;
  }

/* END */


text:
/****************************************************************************
 *
 * ftsynth.c
 *
 *   FreeType synthesizing code for emboldening and slanting (body).
 *
 * Copyright (C) 2000-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.
 *
 */

#include <ft2build.h>
#include FT_SYNTHESIS_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
#include FT_OUTLINE_H
#include FT_BITMAP_H

  /**************************************************************************
   *
   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
   * messages during execution.
   */
#undef  FT_COMPONENT
#define FT_COMPONENT  synth

  /*************************************************************************/
  /*************************************************************************/
  /****                                                                 ****/
  /****   EXPERIMENTAL OBLIQUING SUPPORT                                ****/
  /****                                                                 ****/
  /*************************************************************************/
  /*************************************************************************/

  /* documentation is in ftsynth.h */

  FT_EXPORT_DEF( void )
  FT_GlyphSlot_Oblique( FT_GlyphSlot  slot )
  {
    FT_Matrix    transform;
    FT_Outline*  outline;

    if ( !slot )
      return;

    outline = &slot->outline;

    /* only oblique outline glyphs */
    if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
      return;

    /* we don't touch the advance width */

    /* For italic, simply apply a shear transform, with an angle */
    /* of about 12 degrees.                                      */

    transform.xx = 0x10000L;
    transform.yx = 0x00000L;

    transform.xy = 0x0366AL;
    transform.yy = 0x10000L;

    FT_Outline_Transform( outline, &transform );
  }

  /*************************************************************************/
  /*************************************************************************/
  /****                                                                 ****/
  /****   EXPERIMENTAL EMBOLDENING SUPPORT                              ****/
  /****                                                                 ****/
  /*************************************************************************/
  /*************************************************************************/

  /* documentation is in ftsynth.h */

  FT_EXPORT_DEF( void )
  FT_GlyphSlot_Embolden( FT_GlyphSlot  slot )
  {
    FT_Library  library;
    FT_Face     face;
    FT_Error    error;
    FT_Pos      xstr, ystr;

    if ( !slot )
      return;

    library = slot->library;
    face    = slot->face;

    if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
         slot->format != FT_GLYPH_FORMAT_BITMAP  )
      return;

    /* some reasonable strength */
    xstr = FT_MulFix( face->units_per_EM,
                      face->size->metrics.y_scale ) / 24;
    ystr = xstr;

    if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
      FT_Outline_EmboldenXY( &slot->outline, xstr, ystr );

    else /* slot->format == FT_GLYPH_FORMAT_BITMAP */
    {
      /* round to full pixels */
      xstr &= ~63;
      if ( xstr == 0 )
        xstr = 1 << 6;
      ystr &= ~63;

      /*
       * XXX: overflow check for 16-bit system, for compatibility
       *      with FT_GlyphSlot_Embolden() since FreeType 2.1.10.
       *      unfortunately, this function return no informations
       *      about the cause of error.
       */
      if ( ( ystr >> 6 ) > FT_INT_MAX || ( ystr >> 6 ) < FT_INT_MIN )
      {
        FT_TRACE1(( "FT_GlyphSlot_Embolden:" ));
        FT_TRACE1(( "too strong emboldening parameter ystr=%d\n", ystr ));
        return;
      }
      error = FT_GlyphSlot_Own_Bitmap( slot );
      if ( error )
        return;

      error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr );
      if ( error )
        return;
    }

    if ( slot->advance.x )
      slot->advance.x += xstr;

    if ( slot->advance.y )
      slot->advance.y += ystr;

    slot->metrics.width        += xstr;
    slot->metrics.height       += ystr;
    slot->metrics.horiAdvance  += xstr;
    slot->metrics.vertAdvance  += ystr;
    slot->metrics.horiBearingY += ystr;

    /* XXX: 16-bit overflow case must be excluded before here */
    if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
      slot->bitmap_top += (FT_Int)( ystr >> 6 );
  }

/* END */