[FREETYPE] Update to v2.6.4. CORE-11553 CORE-11543
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 8 Jul 2016 21:07:25 +0000 (21:07 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 8 Jul 2016 21:07:25 +0000 (21:07 +0000)
svn path=/trunk/; revision=71866

99 files changed:
reactos/media/doc/3rd Party Files.txt
reactos/sdk/lib/3rdparty/freetype/ChangeLog
reactos/sdk/lib/3rdparty/freetype/README
reactos/sdk/lib/3rdparty/freetype/devel/ftoption.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/config/ftoption.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/config/ftstdlib.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/freetype.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftautoh.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftcache.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftcffdrv.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftcid.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftgzip.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftimage.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftotval.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftsystem.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftttdrv.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/ftdriver.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/ftmemory.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/ftobjs.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/ftrfork.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/internal.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/tttypes.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/tttables.h
reactos/sdk/lib/3rdparty/freetype/src/autofit/afblue.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/afblue.dat
reactos/sdk/lib/3rdparty/freetype/src/autofit/afblue.h
reactos/sdk/lib/3rdparty/freetype/src/autofit/afcjk.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/afhints.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/afhints.h
reactos/sdk/lib/3rdparty/freetype/src/autofit/aflatin.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/aflatin2.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/aflatin2.h
reactos/sdk/lib/3rdparty/freetype/src/autofit/afranges.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/afscript.h
reactos/sdk/lib/3rdparty/freetype/src/autofit/afstyles.h
reactos/sdk/lib/3rdparty/freetype/src/autofit/aftypes.h
reactos/sdk/lib/3rdparty/freetype/src/base/ftadvanc.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftbitmap.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftmac.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftobjs.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftoutln.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftrfork.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftstream.c
reactos/sdk/lib/3rdparty/freetype/src/base/md5.c
reactos/sdk/lib/3rdparty/freetype/src/bdf/bdflib.c
reactos/sdk/lib/3rdparty/freetype/src/cache/ftccache.h
reactos/sdk/lib/3rdparty/freetype/src/cache/ftccmap.c
reactos/sdk/lib/3rdparty/freetype/src/cache/ftcmanag.c
reactos/sdk/lib/3rdparty/freetype/src/cache/ftcmru.h
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2error.h
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2hints.h
reactos/sdk/lib/3rdparty/freetype/src/cff/cffdrivr.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cffgload.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cffgload.h
reactos/sdk/lib/3rdparty/freetype/src/cff/cffload.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cffobjs.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cffparse.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cffparse.h
reactos/sdk/lib/3rdparty/freetype/src/cff/cfftoken.h
reactos/sdk/lib/3rdparty/freetype/src/cff/cfftypes.h
reactos/sdk/lib/3rdparty/freetype/src/cid/cidparse.c
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvcommn.c
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvcommn.h
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvjust.c
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvkern.c
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvlcar.c
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvmort1.c
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvtrak.c
reactos/sdk/lib/3rdparty/freetype/src/gzip/ftgzip.c
reactos/sdk/lib/3rdparty/freetype/src/gzip/zlib.h
reactos/sdk/lib/3rdparty/freetype/src/otvalid/otvmath.c
reactos/sdk/lib/3rdparty/freetype/src/pcf/pcfread.c
reactos/sdk/lib/3rdparty/freetype/src/pfr/pfrgload.c
reactos/sdk/lib/3rdparty/freetype/src/pfr/pfrload.c
reactos/sdk/lib/3rdparty/freetype/src/pfr/pfrobjs.c
reactos/sdk/lib/3rdparty/freetype/src/pfr/pfrsbit.c
reactos/sdk/lib/3rdparty/freetype/src/pfr/pfrtypes.h
reactos/sdk/lib/3rdparty/freetype/src/psaux/psobjs.c
reactos/sdk/lib/3rdparty/freetype/src/pshinter/pshalgo.c
reactos/sdk/lib/3rdparty/freetype/src/pshinter/pshglob.c
reactos/sdk/lib/3rdparty/freetype/src/raster/ftraster.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/sfobjs.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/ttcmap.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/ttpost.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/ttpost.h
reactos/sdk/lib/3rdparty/freetype/src/smooth/ftgrays.c
reactos/sdk/lib/3rdparty/freetype/src/tools/docmaker/tohtml.py
reactos/sdk/lib/3rdparty/freetype/src/truetype/ttdriver.c
reactos/sdk/lib/3rdparty/freetype/src/truetype/ttgload.c
reactos/sdk/lib/3rdparty/freetype/src/truetype/ttgxvar.c
reactos/sdk/lib/3rdparty/freetype/src/truetype/ttinterp.c
reactos/sdk/lib/3rdparty/freetype/src/truetype/ttinterp.h
reactos/sdk/lib/3rdparty/freetype/src/truetype/ttobjs.c
reactos/sdk/lib/3rdparty/freetype/src/truetype/ttsubpix.c
reactos/sdk/lib/3rdparty/freetype/src/truetype/ttsubpix.h
reactos/sdk/lib/3rdparty/freetype/src/type1/t1afm.c
reactos/sdk/lib/3rdparty/freetype/src/type1/t1load.c
reactos/sdk/lib/3rdparty/freetype/src/type1/t1objs.c
reactos/sdk/lib/3rdparty/freetype/src/type42/t42parse.c

index fdb71b0..87fe9bf 100644 (file)
@@ -23,7 +23,7 @@ Used Version: 1.1
 Website: http://www.geocities.com/dborca/opengl/tc.html
 
 Title: FreeType
-Used Version: 2.6.3
+Used Version: 2.6.4
 Website: http://www.freetype.org
 
 Title: Mesa3D
index a19b4de..2e3ff02 100644 (file)
+2016-07-05  Werner Lemberg  <wl@gnu.org>
+
+       * Version 2.6.4 released.
+       =========================
+
+
+       Tag sources with `VER-2-6-4'.
+
+       * docs/VERSION.TXT: Update documentation and bump version number to
+       2.6.4.
+
+       * README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj,
+       builds/windows/vc2005/index.html,
+       builds/windows/vc2008/freetype.vcproj,
+       builds/windows/vc2008/index.html,
+       builds/windows/vc2010/freetype.vcxproj,
+       builds/windows/vc2010/index.html,
+       builds/windows/visualc/freetype.dsp,
+       builds/windows/visualc/freetype.vcproj,
+       builds/windows/visualc/index.html,
+       builds/windows/visualce/freetype.dsp,
+       builds/windows/visualce/freetype.vcproj,
+       builds/windows/visualce/index.html,
+       builds/wince/vc2005-ce/freetype.vcproj,
+       builds/wince/vc2005-ce/index.html,
+       builds/wince/vc2008-ce/freetype.vcproj,
+       builds/wince/vc2008-ce/index.html: s/2.6.3/2.6.4/, s/263/264/.
+
+       * include/freetype/freetype.h (FREETYPE_PATCH): Set to 4.
+
+       * builds/unix/configure.raw (version_info): Set to 18:4:12.
+       * CMakeLists.txt (VERSION_PATCH): Set to 4.
+
+       * docs/CHANGES: Updated.
+
+2016-07-05  Werner Lemberg  <wl@gnu.org>
+
+       * src/pfr/pfrsbit.c (pfr_lookup_bitmap_data): Fix compiler warning.
+
+2016-07-04  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Variable type revision (part 2).
+
+       * src/smooth/ftgrays.c (TArea): Restore original definition as `int'.
+       (gray_render_line) [FT_LONG64]: Updated.
+       (gray_convert_glyph): 32-bit band bisection stack should be 32 bands.
+       (gray_convert_glyph_inner): Trace successes and failures.
+
+2016-07-04  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Handle single-point contours as segments.
+
+       Doing so allows us to link them to edges \96 some fonts like
+       `NotoSansGurmukhi-Regular' have such isolated points sitting exactly
+       on other outlines.
+
+       * src/autofit/aflatin.c (af_latin_hints_compute_segments): Don't
+       ignore one-point contours but handle them specially as one-point
+       segments.
+       (af_latin_hints_compute_edges): Append one-point segments to edges
+       if possible.
+
+2016-07-02  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Remove unused structure members.
+
+       * src/autofit/afhints.h (AF_SegmentRec, AF_EdgeRec): Remove
+       `num_linked'.
+
+       * src/autofit/afcjk.c (af_cjk_hints_link_segments): Updated.
+
+2016-07-02  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Update to Unicode 9.0.0.
+
+       * src/autofit/afranges.c (af_arab_nonbase_uniranges,
+       af_cyrl_uniranges): Add new data.
+
+2016-07-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Variable type revision (part 1).
+
+       This patch restores original `TCoord' definition as `int' so that the
+       rendering pool is used more efficiently on LP64 platforms (unix).
+
+       * src/smooth/ftgrays.c (gray_TWorker, TCell, gray_TBand): Switch some
+       fields to `TCoord'.
+       (gray_find_cell, gray_render_scanline, gray_render_line, gray_hline,
+       gray_sweep, gray_convert_glyph): Updated.
+
+2016-06-28  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Minor clean-ups.
+
+       * src/smooth/ftgrays.c (gray_TWorker): Remove redundant `ycount'.
+       (gray_sweep, gray_convert_glyph, gray_dump_cells): Updated.
+
+2016-06-27  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Minor clean-ups.
+
+       * src/smooth/ftgrays.c (gray_convert_glyph): Do not use volatile
+       qualifier.
+       (gray_raster_render): Move span initializations from here.
+       (gray_sweep): ... to here and remove unused `target' argument.
+
+2016-06-26  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [pcf] Fix handling of very large fonts (#47708).
+
+       * src/pcf/pcfread.c (pcf_get_encodings): Make `encodingOffset' an
+       unsigned short.
+       Only reject `0xFFFF' as an invalid encoding offset.
+
+2016-06-25  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Really fix deallocation in case of error (#47726).
+
+       * src/truetype/ttgload.c (load_truetype_glyph): Thinko; initialize
+       `outline.points' also.
+
+2016-06-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Consolidate memory management.
+
+       * src/smooth/ftgrays.c (gray_init_cells): Remove function.
+       (gray_TWorker): Remove fields that become local variables.
+       (gray_raster_render): Move rendering buffer declaration from here.
+       (gray_convert_glyph): ... to here and update accordingly.
+
+2016-06-22  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Consolidate boundary checks.
+
+       Removing the checks from `gray_hline' shaves 1% off rendering speed.
+
+       * src/smooth/ftgrays.c [STANDALONE_]: Duplicate `FT_MIN' and `FT_MAX'.
+       (gray_TWorker): No need to store `clip_box'.
+       (gray_hline): Remove unnecessary boundary checks.
+       (gray_convert_glyph): Move boundary checks from here.
+       (gray_raster_render): ... to here and consolidate.
+
+2016-06-21  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Use `FT_Outline_Get_CBox'.
+
+       * src/smooth/ftgrays.c [STANDALONE_]: Duplicate `FT_Outline_Get_CBox'.
+       (gray_compute_cbox): Remove this function.
+       (gray_convert_glyph): Update to use `FT_Outline_Get_CBox'.
+
+2016-06-20  Werner Lemberg  <wl@gnu.org>
+
+       [smooth] Remove compiler warnings.
+
+       * src/smooth/ftgrays.c (gray_convert_glyph): Fix reports from clang.
+
+2016-06-20  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Sanitize memory managenent.
+
+       * src/smooth/ftgrays.c (gray_convert_glyph): Cleaned up.
+
+2016-06-18  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Remove `band_shoot' that never worked.
+
+       * src/smooth/ftgrays.c (gray_TWorker): Remove `band_shoot'.
+       (gray_convert_glyph): Updated.
+
+2016-06-17  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [raster, smooth] Handle FT_RENDER_POOL_SIZE better.
+
+       * src/raster/ftraster.c (FT_MAX_BLACK_POOL): New macro.
+       (ft_black_render): Updated.
+       * src/smooth/ftgrays.c (FT_MAX_GRAY_POOL): New macro.
+       (gray_raster_render): Updated.
+
+2016-06-16  Werner Lemberg  <wl@gnu.org>
+
+       * src/base/md5.c: Updated to recent version.
+
+2016-06-14  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       * src/smooth/ftgrays.c (gray_hline): Optimize if-condition.
+
+2016-06-13  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Add support for Cherokee script.
+
+       * src/autofit/afblue.dat: Add blue zone data for Cherokee.
+
+       * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+       * src/autofit/afscript.h: Add Cherokee standard characters.
+
+       * src/autofit/afranges.c: Add Cherokee data.
+
+       * src/autofit/afstyles.h: Add Cherokee data.
+
+2016-06-09  David Capello  <davidcapello@gmail.com>
+
+       [cmake] Avoid modifying `ftconfig.h' and `ftoption.h' files.
+
+       * CMakeLists.txt: Each time cmake is run those files are
+       modified and the whole FreeType library is recompiled.  With this
+       change we change the files only if there are real modifications, so
+       we can avoid recompilations.
+
+2016-06-09  Werner Lemberg  <wl@gnu.org>
+
+       [bdf] Check number of properties (#48166).
+
+       * src/bdf/bdflib.c (_bdf_parse_start): Implement.
+
+2016-06-08  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Re-enable new line renderer on 64-bit archs.
+
+       * src/smooth/ftgrays.c (gray_render_line): Conditionally re-enable new
+       implementation, where it is safe from overflows.
+
+2016-06-08  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Minor clean-ups.
+
+       * src/smooth/ftgrays.c (gray_dump_cells): Move out of the way.
+       (gray_render_span): Remove spurious casts and streamline.
+
+2016-06-07  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Add support for Ethiopic script.
+
+       * src/autofit/afblue.dat: Add blue zone data for Ethiopic.
+
+       * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+       * src/autofit/afscript.h: Add Ethiopic standard characters.
+
+       * src/autofit/afranges.c: Add Ethiopic data.
+
+       * src/autofit/afstyles.h: Add Ethiopic data.
+
+2016-06-07  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Fix compilation with VS2016 (#48126).
+
+       This compiler doesn't recognize the end-of-comment sequence `*/' if
+       it immediately follows non-ASCII characters.
+
+       * src/autofit/afscript.h: Ensure whitespace before `*/'.
+
+2016-06-04  Werner Lemberg  <wl@gnu.org>
+
+       Fix a test for named instances (#48122).
+
+       This was missed while giving negative face indices an extended
+       meaning.
+
+       * src/base/ftobjs.c (Mac_Read_sfnt_Resource): Implement.
+
+2016-05-31  Nikolaus Waxweiler  <madigens@gmail.com>
+
+       [truetype] Let SHPIX move points in the twilight zone in v40.
+
+       * src/truetype/ttinterp.c (Ins_SHPIX): Allow SHPIX to move points in
+       the twilight zone.  Otherwise, treat SHPIX the same as DELTAP.
+       Unbreaks various fonts such as older versions of Rokkitt and DTL
+       Argo T Light that would glitch severly after calling ALIGNRP after a
+       blocked SHPIX.
+
+2016-05-30  Werner Lemberg  <wl@gnu.org>
+
+       [type42] Support `CharStrings' entry format as created by LilyPond.
+
+       * src/type42/t42parse.c (t42_parse_charstrings): Handle entries
+       having the format
+
+         (foo) cvn 12345 def
+
+2016-05-28  Werner Lemberg  <wl@gnu.org>
+
+       * src/autofit/afranges.c: Remove `UL' postfix from hex numbers.
+
+       Suggested by Alexei.  `UL' is only needed for 16bit compilers, but
+       it seems noone is using this anymore (and we no longer test whether
+       FreeType compiles in such an environment).  Otherwise, it is easy to
+       add the postfix to the `AF_UNICODE_RANGE' macro.
+
+2016-05-26  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Shrink bisection stack.
+
+       The convergence of Bézier flatteners is fast with the deviation
+       from straight line being assymptotically cut 4-fold on each bisection.
+       This justifies smaller bisection stack size.
+
+       * src/smooth/ftgrays.c (gray_TWorker): Remove common `bez_stack'.
+       (gray_render_conic): Create and use conic `bez_stack'. Move back the
+       band analysis from...
+       (gray_conic_to): ... here.
+       (gray_render_cubic): Create and use cubic `bez_stack'. Move back the
+       band analysis from...
+       (gray_cubic_to): ... here.
+       (gray_move_to): Updated.
+
+2016-05-25  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Fixes for Armenian and Gujarati ranges.
+
+       * src/autofit/afranges.c (af_armn_uniranges): Corrected.
+       (af_guru_nonbase_uniranges): Make U+0A3E a base character.
+
+2016-05-24  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Add support for Armenian script.
+
+       * src/autofit/afblue.dat: Add blue zone data for Armenian.
+
+       * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+       * src/autofit/afscript.h: Add Armenian standard characters.
+
+       * src/autofit/afranges.c: Add Armenian data.
+
+       * src/autofit/afstyles.h: Add Armenian data.
+
+2016-05-23  Werner Lemberg  <wl@gnu.org>
+
+       * builds/unix/unix-cc.in (LINK_LIBRARY): Use `-export-symbols'.
+
+       This was commented about 10 years ago \96 I think the reason then to
+       disable libtool's `-export-symbols' option was to give some badly
+       programmed applications access to internal FreeType functions.
+
+       I believe that we should no longer take care of such programs; the
+       number of symbols exported should be rather restricted as much as
+       possible.
+
+2016-05-22  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Add blue-zone support for Gurmukhi script.
+
+       This essentially moves the Gurmukhi script from the `Indic' hinter to
+       the `Latin' hinter.
+
+       * src/autofit/afblue.dat: Add blue zone data for Gurmukhi.
+
+       * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+       * src/autofit/afscript.h: Add Gurmukhi standard characters and move
+       data out of AF_CONFIG_OPTION_INDIC block.
+
+       * src/autofit/afranges.c: Move Gurmukhi data out of
+       AF_CONFIG_OPTION_INDIC block.
+
+       * src/autofit/afstyles.h: Update Gurmukhi data; in particular, use
+       AF_WRITING_SYSTEM_LATIN.
+
+2016-05-21  Werner Lemberg  <wl@gnu.org>
+
+       Minor clang++ fixes.
+
+       * src/base/ftobjs.c (FT_Add_Module), src/psaux/psobjs.c
+       (ps_parser_load_field), src/type1/t1load.c (parse_subrs): Add
+       initializer.
+
+       * src/cache/ftccache.h (FTC_CACHE_TRYLOOP_END): Avoid implicit
+       conversion from NULL to boolean.
+
+2016-05-21  Werner Lemberg  <wl@gnu.org>
+
+       Work around a bug of the C 8.0.0.1 compiler on AIX 5.3 (#47955).
+
+       * include/freetype/internal/ftmemory.h (cplusplus_typeof): Use
+       braces for `extern "C++"'.
+
+2016-05-17  Nikolaus Waxweiler  <madigens@gmail.com>
+
+       [truetype] Make TT_LOADER_SET_PP support subpixel hinting [3/3].
+
+       * src/truetype/ttgload.c (TT_LOADER_SET_PP): Replace macro with...
+       (tt_loader_set_pp): ... this new function.
+       Update all callers.
+
+2016-05-17  Nikolaus Waxweiler  <madigens@gmail.com>
+
+       [truetype] New implementation of v38 bytecode interpreter [2/3].
+
+       This patch actually modifies the bytecode interpreter.
+
+       See added comments in `ttinterp.h' for more information on this and
+       the following commit in the series.
+
+       * src/truetype/ttinterp.c (SUBPIXEL_HINTING): Replaced by...
+       (NO_SUBPIXEL_HINTING, SUBPIXEL_HINTING_INFINALITY,
+       SUBPIXEL_HINTING_MINIMAL): ...new macros.
+       (Direct_Move, Direct_Move_X, Direct_Move_Y): Handle backwards
+       compatibility.
+       Updated.
+       (Ins_RS, Ins_FDEF, Ins_ENDF, Ins_CALL, Ins_LOOPCALL, Ins_MD):
+       Updated.
+       (Ins_INSTCTRL): Handle native ClearType mode flag.
+       Updated.
+       (Ins_FLIPPT, Ins_FLIPRGON, Ins_FLIPRGOFF): Handle backwards
+       compatibility.
+       (Move_Zp2_Point): Ditto.
+       (Ins_SHP): Updated.
+       (Ins_SHPIX): Handle backwards compatibility.
+       Updated.
+       (Ins_MSIRP, Ins_MDAP, Ins_MIAP, Ins_MDRP, Ins_MIRP): Updated.
+       (Ins_ALIGNRP): Updated.
+       (Ins_IUP, Ins_DELTAP): Handle backwards compatibility.
+       Updated.
+       (Ins_GETINFO): Handle v38 flags.
+       Updated.
+       (TT_RunIns): Handle backwards compatibility mode.
+       Updated.
+
+2016-05-17  Nikolaus Waxweiler  <madigens@gmail.com>
+
+       [truetype] New implementation of v38 bytecode interpreter [1/3].
+
+       This patch prepares data structures and the like.
+
+       See added comments in `ttinterp.h' for more information on this and
+       the following commits in the series.
+
+       * devel/ftoption.h, include/freetype/config/ftoption.h
+       (TT_CONFIG_OPTION_SUBPIXEL_HINTING): Assign values to differentiate
+       between subpixel versions.
+       (TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY,
+       TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL): New macros.
+
+       * include/freetype/ftttdrv.h (TT_INTERPRETER_VERSION_40): New macro.
+
+       * include/freetype/internal/tttypes.h (TT_FaceRec): Updated.
+
+       * src/truetype/ttinterp.h (TT_ExecContextRec): Define new fields
+       `subpixel_hinting_lean', `vertical_lcd_lean',
+       `backwards_compatibility', `iupx_called', iupy_called', and
+       `grayscale_cleartype' for new hinting mode.
+
+       * src/truetype/ttdriver.c (tt_property_set): Handle v38 and v40
+       interpreters conditionally.
+
+       * src/truetype/ttgload.c (TT_Hint_Glyph): Save phantom points unless
+       in v38 backwards compatibility mode.
+       Updated.
+       (compute_glyph_metrics): Add v38 backwards compatibility mode
+       constraint for adjusting advance widths.
+       Updated.
+       (tt_loader_init): Handle new flags `subpixel_hinting_lean',
+       `grayscale_cleartype', and `vertical_lcd_lean'.
+       Updated.
+       (tt_get_metrics, TT_Process_Simple_Glyph, TT_LOADER_SET_PP):
+       Updated.
+
+       * src/truetype/ttobjs.c (tt_driver_init): Conditionally set
+       default interpreter version number.
+
+       * src/truetype/ttsubpix.c, src/truetype/ttsubpix.h: Updated.
+
+2016-05-17  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Fix matrix scaling (#47848).
+
+       * include/freetype/config/ftstdlib.h (FT_LONG_MIN): New macro.
+
+       * src/cff/cffparse.c (cff_parse_font_matrix): Use largest scaling
+       value of all matrix coefficients to scale matrix.
+
+       * src/cff/cffobjs.c (cff_face_init): Use `matrix->yx' member for
+       matrix normalization if `matrix->yy' is zero.
+
+2016-05-16  Werner Lemberg  <wl@gnu.org>
+
+       [base] Reject invalid sfnt Mac resource (#47891).
+
+       * src/base/ftobjs.c (open_face_PS_from_sfnt_stream): Check validity
+       of `CID ' and `TYPE1' table offset and length.
+
+2016-05-16  Werner Lemberg  <wl@gnu.org>
+
+       [cid] Fix scanning for `StartData' and `/sfnts' (#47892).
+
+       * src/cid/cidparse.c (STARTDATA, STARTDATA_LEN, SFNTS, SFNTS_LEN):
+       New macros.
+       (cid_parser_new): Fix and document algorithm.
+
+2016-05-16  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
+
+       [truetype] Improve the recursive reference detector.
+
+       The previous fix for #46372 misunderstood a composite glyph referring
+       same component twice as a recursive reference.  See the discussion
+
+         http://lists.gnu.org/archive/html/freetype/2016-05/msg00000.html
+
+       Thanks to Khaled Hosny for finding this issue.
+
+       * src/truetype/ttgload.c (ft_list_get_node_at): A function to get
+       the i-th node from FT_List.
+       (load_truetype_glyph): In the traversal scan of the reference tree
+       in the composite glyph, we clear the nodes filled by previous
+       sibling chain.
+
+2016-05-07  Werner Lemberg  <wl@gnu.org>
+
+       [cache] Allow value 0 for face ID.
+
+       We never dereference `face_id', and some implementations might use a
+       running number instead of a pointer.  Additionally, disallowing
+       value zero was undocumented.
+
+       * src/cache/ftccmap.c (FTC_CMapCache_Lookup), src/cache/ftcmanag.c
+       (FTC_Manager_LookupFace, FTC_Manager_RemoveFaceID): Remove test for
+       `face_id'.
+
+2016-05-05  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] More efficient accounting of conic splits and draws.
+
+       A single decrement counter of segments to draw, instead of an array,
+       contains all the information necessary to decide when to split and
+       when to draw a conic segment. The number of splits before each draw is
+       equal to the number of trailing zeros in the counter.
+
+       * src/smooth/ftgrays.c (gray_TWorker): Remove `lev_stack'.
+       (gray_render_conic): Updated to use decrement counter of segments.
+
+2016-05-05  Werner Lemberg  <wl@gnu.org>
+
+       [cff, truetype] Fix logic for `FT_Property_Set'.
+
+       Otherwise some properties could be set to arbitrary values, which is
+       harmless, but querying could give wrong positive results.
+
+       * src/cff/cffdrivr.c (cff_property_set) [hinting-engine],
+       * src/truetype/ttdriver.c (tt_property_set) [interpreter-version]:
+       Only allow defined values.
+
+2016-04-25  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Add blue-zone support for Gujarati script.
+
+       This essentially moves the Gujarati script from the `Indic' hinter to
+       the `Latin' hinter.
+
+       * src/autofit/afblue.dat: Add blue zone data for Gujarati.
+
+       * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+       * src/autofit/afscript.h: Add Gujarati standard characters and move
+       data out of AF_CONFIG_OPTION_INDIC block.
+
+       * src/autofit/afranges.c: Move Gujarati data out of
+       AF_CONFIG_OPTION_INDIC block.
+
+       * src/autofit/afstyles.h: Update Gujarati data; in particular, use
+       AF_WRITING_SYSTEM_LATIN.
+
+2016-04-24  Werner Lemberg  <wl@gnu.org>
+
+       Minor.
+
+       * include/freetype/freetype.h (FT_HAS_*, FT_IS_*): Protect macro
+       argument with parentheses.
+
+2016-04-24  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Fix deallocation in case of error (#47726).
+
+       * src/truetype/ttgload.c (load_truetype_glyph): Initialize fields in
+       `outline' that are going to be deallocated in case of error.
+
+2016-04-23  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Improve Georgian blue zone characters.
+
+       Suggested by Akaki Razmadze <razmadzekoko@gmail.com>.
+
+       * src/autofit/afblue.dat (AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM):
+       Updated.
+
+       * src/autofit/afblue.c: Regenerated.
+
+2016-04-16  David Capello  <davidcapello@gmail.com>
+
+       [cmake] Honor SKIP_INSTALL_* settings (as used in zlib).
+
+       As FreeType depends on zlib, if we don't install zlib (e.g., because
+       we defined SKIP_INSTALL_ALL), FreeType cannot be installed, too
+       (cmake triggers an error saying that FreeType cannot be installed
+       because zlib target isn't in the export set).
+
+       * CMakeLists.txt: Honor `SKIP_INSTALL_HEADERS',
+       `SKIP_INSTALL_LIBRARIES', and `SKIP_INSTALL_ALL' settings.
+
+2016-04-16  Behdad Esfahbod  <behdad@behdad.org>
+
+       [truetype] Another fix for non-intermediate GX tuples.
+
+       * src/truetype/ttgxvar.c (ft_var_apply_tuple): Add some missing
+       cases.
+
+2016-04-12  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       Remove forgotten macro.
+
+       * include/freetype/internal/internal.h
+       [FT_INTERNAL_POSTSCRIPT_GLOBALS_H]: Remove.
+
+2016-04-09  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Add support for Georgian scripts.
+
+       Georgian is problematic, since `uppercase' forms of Mkhedruli
+       (called Mtavruli) are not yet defined in Unicode, which means that
+       proper blue zones can't be defined.  However, there is already a
+       proposal submitted to Unicode; see
+
+         http://www.unicode.org/L2/L2016/16034-n4707-georgian.pdf
+
+       Additionally, due to historical reasons, Unicode treats Khutsuri as
+       the same script as Mkhedruli, and so does OpenType.  However, since
+       the two scripts have completely different shapes it can happen that
+       blue zones differ considerably.  The tag `geok' used here (derived
+       from ISO 15924) to differentiate the two scripts is not an OpenType
+       tag in use.  If we now have a font that contains both glyphs for
+       Mkhedruli and Khutsuri, and it uses OpenType features for both also,
+       HarfBuzz unavoidably treats all glyphs as `geor'.  As a consequence,
+       blue zones for `geok' are not used for glyphs involved in the
+       OpenType features.
+
+       An issue not yet resolved is which OpenType feature should be used
+       to access Mtavruli glyph shapes; right now, FreeType doesn't set up
+       support for them, but it is easy to add them later on as soon as
+       more information is available.
+
+       * src/autofit/afblue.dat: Add blue zone data for Georgian.
+
+       * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+       * src/autofit/afscript.h: Add Georgian standard characters.
+
+       * src/autofit/afranges.c: Add Georgian data.
+
+       * src/autofit/afstyles.h: Add Georgian data.
+
+2016-04-05  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Provide dummy blue zone for pseudo script `none'.
+
+       Even if the dummy hinter is used as the handler for `none' (which
+       doesn't use blue zones), it is more consistent than the old value
+       (which was 0), pointing to Arabic...
+
+       * src/autofit/afblue.dat: Add `AF_BLUE_STRINGSET_NONE'.
+       * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+       * src/autofit/afstyles.h (none_dflt): Use AF_BLUE_STRINGSET_NONE.
+
+2016-03-30  Werner Lemberg  <wl@gnu.org>
+
+       * src/pfr/pfrload.c (pfr_aux_name_load): Thinko (#47567).
+
+2016-03-30  Werner Lemberg  <wl@gnu.org>
+
+       * src/pfr/pfrload.c (pfr_log_font_count): Better font size estimate.
+
+2016-03-30  Werner Lemberg  <wl@gnu.org>
+
+       * src/pfr/pfrload.c (pfr_aux_name_load): Fix memory leak (#47567).
+
+2016-03-29  Werner Lemberg  <wl@gnu.org>
+
+       * src/base/ftadvanc.c (FT_Get_Advances): Fix invalid left shift.
+
+2016-03-29  Werner Lemberg  <wl@gnu.org>
+
+       [pfr] Fix binary search (#47514).
+
+       * src/pfr/pfrsbit.c (pfr_lookup_bitmap_data): Handle border
+       conditions correctly.
+
+2016-03-29  Werner Lemberg  <wl@gnu.org>
+
+       [pfr] Minor.
+
+       * src/pfr/pfrsbit.c (pfr_lookup_bitmap_data): Replace `left',
+       `right', and `middle' with `min', `max', and `mid' as used in other
+       FreeType binary search code.
+       (pfr_load_bitmap_metrics): Fix invalid left shift.
+
+2016-03-29  Werner Lemberg  <wl@gnu.org>
+
+       * src/pfr/pfrtypes.h: Replace all enums with macros.
+
+       We need `~FOO' to unset bits, and only with unsigned values (which
+       `enum' isn't normally) this works cleanly.
+
+2016-03-26  Werner Lemberg  <wl@gnu.org>
+
+       [pfr] Robustify bitmap strike handling (#47514).
+
+       We did a binary search for a charcode without ensuring that the
+       searched data is ordered.  Validating the order is now done lazily,
+       this is, the first access to a bitmap glyph triggers the order check
+       in the corresponding bitmap strike.
+
+       * src/pfr/pfrtypes.h (PFR_BitmapFlags): New values
+       `PFR_BITMAP_VALID_CHARCODES' and `PFR_BITMAP_CHARCODES_VALIDATED'.
+
+       * src/pfr/pfrsbit.c (pfr_lookup_bitmap_data): Make `flags' argument
+       a pointer.  Handle new PFR_BITMAP_XXX flags.
+       (pfr_slot_load_bitmap): Updated.
+
+2016-03-26  Werner Lemberg  <wl@gnu.org>
+
+       [pfr] Fix handling of compound glyphs.
+
+       Extra items are indicated with different bit positions.
+
+       * src/pfr/pfrtypes.h (PFR_GlyphFlags): Replace
+       `PFR_GLYPH_EXTRA_ITEMS' with `PFR_GLYPH_SIMPLE_EXTRA_ITEMS' and
+       `PFR_GLYPH_COMPOUND_EXTRA_ITEMS'.
+
+       * src/pfr/pfrgload.c (pfr_glyph_load_simple,
+       pfr_glyph_load_compound): Use them.
+
+2016-03-25  Werner Lemberg  <wl@gnu.org>
+
+       [pfr] Minor.
+
+       * src/pfr/pfrsbit.c, src/pfr/pfrobjs.c: Use flag names instead of
+       bare numbers.
+
+2016-03-25  Werner Lemberg  <wl@gnu.org>
+
+       [pfr] Various clang sanitizer fixes.
+
+       * src/pfr/pfrsbit.c (pfr_load_bitmap_metrics): Correctly handle
+       signed nibbles.
+       (pfr_slot_load_bitmap): Correctly exit frame in case of error.
+       Fix invalid left shifts.
+
+2016-03-23  Werner Lemberg  <wl@gnu.org>
+
+       Rename `VERSION.DLL' (#47472).
+
+       * docs/VERSION.DLL: Renamed to...
+       * docs/VERSIONS.TXT: ...this.
+
+2016-03-23  Werner Lemberg  <wl@gnu.org>
+
+       [raster, smooth] Directly test outline size (#47500).
+
+       This improves stand-alone compilation.
+
+       * src/base/ftoutln.c (FT_Outline_Render): Move cbox size test to...
+
+       * src/raster/ftraster.c (ft_black_render), src/smooth/ftgrays.c
+       (gray_raster_render): ...these functions.
+
+2016-03-23  Werner Lemberg  <wl@gnu.org>
+
+       [raster, smooth] Fix some clang sanitizer runtime issues.
+
+       * src/raster/ftraster.c (ft_black_reset, ft_black_set_mode,
+       ft_black_render): Harmonize signatures with `ftimage.h'.
+
+       * src/smooth/ftgrays.c (gray_raster_render, gray_raster_reset):
+       Ditto.
+
+2016-03-22  Werner Lemberg  <wl@gnu.org>
+
+       * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Minor.
+
+       This fixes an AddressSanitizer issue:
+
+         ttgload.c:430:7: runtime error: null pointer passed as argument 1,
+                          which is declared to never be null
+
+2016-03-21  Werner Lemberg  <wl@gnu.org>
+
+       * src/autofit/afhints.c (af_glyph_hints_reload): Thinko.
+
+       This fixes the previous commit to this file.
+
+2016-03-21  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Partly revert recent changes.
+
+       * src/smooth/ftgrays.c (gray_conic_to, gray_cubic_to): Rework
+       conditions to fix rendering issues.
+
+2016-03-20  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Show `near' points in tracing.
+
+       * src/autofit/afhints.h (AF_FLAG_NEAR): New macro.
+
+       * src/autofit/afhints.c (af_glyph_hints_dump_points): Implement it.
+       (af_glyph_hints_reload): Handle AF_FLAG_NEAR.
+
+2016-03-18  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Minor refactoring and microoptimizations.
+
+       * src/smooth/ftgrays.c (gray_render_conic, gray_render_cubic): Move
+       band clipping from here.
+       (gray_conic_to, gray_cubic_to): ... to here.
+       (gray_rander_line, gray_render_scanline): Initialize variables closer
+       to their use.
+
+2016-03-17  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Minor refactoring.
+
+       * src/smooth/ftgrays.c (gray_render_conic, gray_render_cubic): Move
+       upscaling from here.
+       (gray_conic_to, gray_cubic_to): ... to here.
+
+2016-03-15  Werner Lemberg  <wl@gnu.org>
+
+       * src/autofit/aflatin.c (af_latin_compute_stem_width): Optimize.
+
+2016-03-14  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Temporarily revert 6eb6158dd787 (#47114).
+
+       * src/smooth/ftgrays.c (gray_render_line): Old implementation.
+
+2016-03-12  Werner Lemberg  <wl@gnu.org>
+
+       [ftfuzzer] Improve coverage of rasterfuzzer.
+
+       * src/tools/ftfuzzer/rasterfuzzer.cc (LLVMFuzzerTestOneInput): Use
+       input data for `tags' array also.
+       Trim input data to get more positive hits.
+
+2016-03-11  Pavlo Denysov  <paul.kiev+savannah@gmail.com>
+
+       Fix CMake issues for iOS (patch #8941).
+
+       * CMakeLists.txt (CMAKE_TOOLCHAIN_FILE): Fix directory.
+       * builds/cmake/iOS.cmake: No longer enforce gcc.
+
+2016-03-09  Behdad Esfahbod  <behdad@behdad.org>
+
+       [truetype] Fix handling of non-intermediate GX tuples.
+
+       We probably did not notice this as all fonts we tested had only
+       tuple_coords[i] be +1 or -1 for non-intermediate tuples.
+
+       * src/truetype/ttgxvar.c (ft_var_apply_tuple): Implement it.
+
+2016-03-06  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [base] Refuse to render enormous outlines (#47114).
+
+       The goal is to avoid integer overflows in the rendering algorithms.
+       The limit is chosen arbitrarily at some 2^18 pixels, which should be
+       enough for modern devices including printers.
+
+       * src/base/ftoutln.c (FT_Outline_Render): Check CBox and reject
+       enormous outlines.
+
+2016-03-06  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Replace left shifts with multiplications (#47114).
+
+       * src/smooth/ftgrays.c (SUBPIXELS, UPSCALE, DOWNSCALE): Do it.
+
+2016-03-05  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Avoid excessive stem length rounding (#25392).
+
+       * src/autofit/aflatin.c (af_latin_compute_stem_width): Add argument
+       to pass difference between hinted and unhinted position of base
+       point; use this to adjust the stem width depending on the PPEM so
+       that it doesn't become too large under certain circumstances.
+       Update all callers using value 0 for this argument except...
+       (af_latin_align_linked_edge): Pass position delta of base point to
+       `af_latin_compute_stem_width'.
+
+2016-03-05  J Raynor  <jxraynor@gmail.com>
+
+       Make FreeType compile on AIX out of the box.
+
+       * builds/unix/configure.raw (XX_ANSIFLAGS): Don't use `-ansi' on
+       AIX.
+
+2016-03-01  Werner Lemberg  <wl@gnu.org>
+           Kostya Serebryany  <kcc@google.com>
+
+       [ftfuzzer] Add unit for testing smooth and black rasterizers.
+
+       * src/tools/ftfuzzer/rasterfuzzer.cc: New file.
+
+2016-03-01  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Fix reallocation error introduced in 2016-02-27 (#47310).
+
+       * src/autofit/aflatin.c (af_latin_hints_compute_segments): Reassign
+       `prev_segment' after reallocation.
+
+2016-03-01  Werner Lemberg  <wl@gnu.org>
+
+       Fix clang warnings.
+
+       * src/autofit/aflatin.c (af_latin_hints_compute_segments): Use
+       FT_UShort for `min_flags' and `max_flags'.
+       Initialize `prev_*' variables.
+
+       * src/cff/cffobjs.c (cff_face_init) [FT_DEBUG_LEVEL_TRACE]: Fix
+       types of local variables.
+
+       * src/smooth/ftgrays.c (gray_dump_cells) [FT_DEBUG_LEVEL_TRACE]:
+       Update `printf' format string.
+
+       * src/tools/ftfuzzer/ftfuzzer.cc (setIntermediateAxis): Add cast.
+       (LLVMFuzzerTestOneInput): Fix loop type.
+
+2016-02-29  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Add blue-zone support for Sinhala script.
+
+       This essentially moves the Sinhala script from the `Indic' hinter to
+       the `Latin' hinter.
+
+       * src/autofit/afblue.dat: Add blue zone data for Sinhala.
+
+       * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+       * src/autofit/afscript.h: Add Sinhala standard character and move data
+       out of AF_CONFIG_OPTION_INDIC block.
+
+       * src/autofit/afranges.c: Move Sinhala data out of
+       AF_CONFIG_OPTION_INDIC block.
+
+       * src/autofit/afstyles.h: Update Sinhala data; in particular, use
+       AF_WRITING_SYSTEM_LATIN.
+
+2016-02-27  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Properly handle spikes pointing to the x-axis.
+
+       An example that gets better rendered is glyph `uusignTaml' (glyph
+       index 2286) in font `FreeSerif.ttf' (Version 0412.2263) at 22ppem.
+
+       * src/autofit/aflatin.c (af_latin_hints_compute_segments): Properly
+       handle segments where the last point of the first segment is
+       identical to the first point in the second one.  This can happen for
+       malformed fonts or spikes.  We either merge the new segment with the
+       previous one (both segments point into the same direction), or we
+       discard the shorter segment if they point into different directions.
+
+2016-02-27  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Minor code clean-up.
+
+       * src/autofit/aflatin.c (af_latin_hints_compute_segments): Change
+       some local variable names to better differentiate between values
+       along a segment and values orthogonal to it.
+
+2016-02-26  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Improve BOUND action.
+
+       In complex glyph shapes, the original logic was too simple to cater
+       for situations that would actually need something similar to PS Hint
+       masks.  This fix should alleviate the worst cases.
+
+       * src/autofit/aflatin.c (af_latin_hint_edges): Don't allow
+       complete disappearance of stems.
+
+2016-02-25  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Add blue-zone support for Tamil script.
+
+       This essentially moves the Tamil script from the `Indic' hinter to
+       the `Latin' hinter.
+
+       * src/autofit/afblue.dat: Add blue zone data for Tamil.
+
+       * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+       * src/autofit/afscript.h: Add Tamil standard character and move data
+       out of AF_CONFIG_OPTION_INDIC block.
+
+       * src/autofit/afranges.c: Move Tamil data out of
+       AF_CONFIG_OPTION_INDIC block.
+
+       * src/autofit/afstyles.h: Update Tamil data; in particular, use
+       AF_WRITING_SYSTEM_LATIN.
+
+2016-02-18  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Add blue-zone support for Malayalam script.
+
+       This essentially moves the Malayalam script from the `Indic' hinter
+       to the `Latin' hinter.
+
+       * src/autofit/afblue.dat: Add blue zone data for Malayalam.
+
+       * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+       * src/autofit/afscript.h: Add Malayalam standard characters and move
+       data out of AF_CONFIG_OPTION_INDIC block.
+
+       * src/autofit/afranges.c: Move Malayalam data out of
+       AF_CONFIG_OPTION_INDIC block.
+
+       * src/autofit/afstyles.h: Update Malayalam data; in particular, use
+       AF_WRITING_SYSTEM_LATIN.
+
+2016-02-16  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Fix integer overflow (#47114).
+
+       * src/smooth/ftgrays.c (TArea): Make it unconditionally `long'.
+
+2016-02-15  Werner Lemberg  <wl@gnu.org>
+
+       * src/cff/cffparse.c (cff_parse_multiple_master): Improve tracing.
+
+2016-02-15  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Handle T2 operator only with old CFF engine (#47157).
+
+       * src/cff/cffparse.c (cff_parser_run) <opcode 31>: Enclose with
+       #ifdef CFF_CONFIG_OPTION_OLD_ENGINE...#endif.
+
+2016-02-15  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Partially handle `load' and `store' ops in old CFF engine.
+
+       Now all glyphs of MM CFFs like `ITCGaramondMM-It.otf' can be
+       displayed.
+
+       * src/cff/cffgload.c (cff_decoder_parse_charstrings) <cff_op_store,
+       cff_op_load>: Partially implement it.
+
+       * src/cff/cffparse.c (cff_parser_init): Add new parameter to pass
+       the number of Multiple Master axes.
+       Update all callers.
+       (cff_parse_multiple_master): Get number of axes.
+       (cff_parser_run) <opcode 31>: Updated.
+       * src/cff/cffparse.h: Updated.
+       (CFF_ParserRec): Add `num_axes' field.
+
+       * src/cff/cffload.c: Updated.
+
+       * src/cff/cfftypes.h (CFF_FontRecDictRec): Add `num_axes' field.
+
+2016-02-15  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Correctly trace SIDs that contain NULL bytes.
+
+       We need this to properly trace Multiple Master CFFs, which contain
+       two SIDs that are charstrings.
+
+       This commit makes FreeType also show the last SID, omitted
+       previously due to a bug.
+
+       * src/cff/cfftypes.h (CFF_FontRec): Add `string_pool_size' field.
+
+       * src/cff/cffload.c (cff_index_get_pointers): Add argument to return
+       the pool size.
+       Update all callers.
+
+       * src/cff/cffobjs.c (cff_face_init) [FT_DEBUG_LEVEL_TRACE]: Directly
+       access `cff->strings' to display the non-default strings.
+
+2016-02-14  Werner Lemberg  <wl@gnu.org>
+
+       * src/base/fthash.c: Include FT_INTERNAL_MEMORY_H.
+
+2016-02-14  Werner Lemberg  <wl@gnu.org>
+
+       * src/cff/cffparse.c: Include `cffgload.h'.
+
+       Problem reported by Colin Walters <walters@verbum.org>.
+
+2016-02-14  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Make old CFF engine show MM CFFs (without variations).
+
+       The new code only displays the first master in the font.
+
+       * src/cff/cffgload.c (cff_decode_parse_charstrings): Add new
+       parameter to allow function calls from dictionaries also.
+       <cff_op_blend>: Partially implement it.
+       Update all callers.
+       * src/cff/cffgload.h: Updated.
+
+       * src/cff/cffparse.c (cff_parser_init): Add new parameter to pass the
+       number of Multiple Master designs.
+       Update all callers.
+       (cff_parse_multiple_master): New function to rudimentarily parse
+       operator.
+       (cff_parser_run): Handle `T2' operator.
+       * src/cff/cffparse.h: Updated.
+       (CFF_ParserRec): Add `num_designs' field.
+
+       * src/cff/cffload.c: Updated.
+
+       * src/cff/cfftoken.h: Handle `MultipleMaster' operator.
+
+       * src/cff/cfftypes.h (CFF_FontRecDictRec): Add `num_designs' field.
+
+       * src/sfnt/sfobjs.c (sfnt_init_face): Don't handle `fvar' table for
+       MM CFFs.
+
+2016-02-09  Werner Lemberg  <wl@gnu.org>
+
+       [docmaker] Don't emit trailing newlines.
+
+       * src/tools/docmaker/tohtml.py (HtmlFormatter::make_html_code):
+       Use `rstrip'.
+
 2016-02-07  Werner Lemberg  <wl@gnu.org>
 
        * Version 2.6.3 released.
        * include/freetype/freetype.h (FREETYPE_PATCH): Set to 3.
 
        * builds/unix/configure.raw (version_info): Set to 18:3:12.
-       * CMakeLists.txt (VERSION_PATCH): Set to 2.
+       * CMakeLists.txt (VERSION_PATCH): Set to 3.
 
        * docs/CHANGES: Updated.
 
        * src/autofit/afscript.h: Add another parameter to `SCRIPT',
        specifying hinting direction.
 
-       * src/autofit/afglobal.c, scr/autofit/afglobal.h,
+       * src/autofit/afglobal.c, src/autofit/afglobal.h,
        src/autofit/afpic.c, src/autofit/afranges.h, src/autofit/afshaper.c,
        src/autofit/aftypes.h: Extend `SCRIPT' definitions.
 
        [bdf] Remove dead code (#46625).
 
        The BDF specification only allows decimal numbers, no octal or
-       hexidecimal decoding is needed.
+       hexadecimal decoding is needed.
 
        * src/bdf/bdflib.c (_bdf_atoul, _bdf_atol, _bdf_atous,
        _bdf_atos): Remove unused code and parameters.
        * src/base/ftobjs.c (Mac_Read_sfnt_Resource, FT_Open_Face): Set
        `error'.
 
-2015-12-14  Ben Wagner <bungeman@gmail.com>
+2015-12-14  Ben Wagner  <bungeman@gmail.com>
 
        [base] Check error when seeking to data supplied offset (#46635).
 
        * src/base/ftobjs.c (open_face_PS_from_sfnt_stream):
-       `ft_lookup_PS_in_sfnt_stream' returns offset and and length from
+       `ft_lookup_PS_in_sfnt_stream' returns offset and length from
        user supplied data.  Use of this these values must be checked.
 
 2015-12-13  Werner Lemberg  <wl@gnu.org>
        * src/autofit/afglobal.c: s/hbshim.h/afshaper.h/.
        (af_face_globals_compute_style_coverage): Updated.
 
-       * src/autofit/afglocal.h: s/hbshim.h/afshaper.h/.
+       * src/autofit/afglobal.h: s/hbshim.h/afshaper.h/.
 
        * src/autofit/autofit.c: s/hbshim.c/afshaper.c/.
 
 
 2015-11-27  Tamas Kenez  <tamas.kenez@adasworks.com>
 
-       [cmake] Make `FindHarfbuzz' observe the REQUIRED option.
+       [cmake] Make `FindHarfBuzz' observe the REQUIRED option.
 
        * builds/cmake/FindHarfBuzz.cmake: Implement it.
 
 
 2015-10-04  Werner Lemberg  <wl@gnu.org>
 
-       [bzip2, gzip] Avoid access of unitialized memory (#46109).
+       [bzip2, gzip] Avoid access of uninitialized memory (#46109).
 
        * src/bzip2/ftbzip2.c (ft_bzip2_file_fill_input), src/gzip/ftgzip.c
        (ft_gzip_file_fill_input): In case of an error, adjust the limit to
 
 2015-10-03  Werner Lemberg  <wl@gnu.org>
 
-       [bzip2, gzip] Avoid access of unitialized memory (#46109).
+       [bzip2, gzip] Avoid access of uninitialized memory (#46109).
 
        * src/bzip2/ftbzip2.c (ft_bzip2_file_fill_output), src/gzip/ftgzip.c
        (ft_gzip_file_fill_output): In case of an error, adjust the limit to
        [raster,smooth] Microoptimizations.
 
        * src/raster/ftraster.c (Insert_Y_Turn, Finalize_Profile_Table,
-       Beziier_Up, ): Use do-while loops.
+       Bezier_Up, ): Use do-while loops.
 
        * src/smooth/ftgrays.c (gray_render_scanline, gray_render_line,
        gray_convert_glyph): Ditto.
        [base] Improve emboldener (#45596).
 
        * src/base/ftoutln.c (FT_Outline_EmboldenXY): Correct displacement
-       of zero-lenght segments.
+       of zero-length segments.
 
 2015-08-16  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        * src/type1/t1gload.c (T1_Load_Glyph): Directly modify advances only
        if font matrix is not trivial.
        * src/cff/cffgload.c (cff_slot_load): Ditto.
-       * sff/cid/cidgload.c (cid_slot_load_glyph): Ditto for advances and the
+       * src/cid/cidgload.c (cid_slot_load_glyph): Ditto for advances and the
        entire outline.
 
 2015-08-11  Werner Lemberg  <wl@gnu.org>
        * src/autofit/aftypes.h [FT_DEBUG_AUTOFIT]: Include
        FT_CONFIG_STANDARD_LIBRARY_H earlier.
 
-       * src/truetype/ttpic.h: Include FT_INTERNL_PIC_H.
+       * src/truetype/ttpic.h: Include FT_INTERNAL_PIC_H.
 
 2015-07-07  Werner Lemberg  <wl@gnu.org>
 
        (load_truetype_glyph), src/truetype/ttgxvar.c (tt_handle_deltas),
        src/truetype/ttinterp.c (Ins_INSTCTRL): Fix signedness issues.
 
-2015-06-29  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-06-29  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        [truetype] Speed up bytecode interpreter.
 
        * src/truetype/ttinterp.c (Normalize): Use `FT_Vector_NormLen'.
 
-2015-06-29  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-06-29  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        [base] Speed up emboldening.
 
        * src/base/ftoutln.c (FT_Outline_EmboldenXY): Use
        `FT_Vector_NormLen'.
 
-2015-06-29  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-06-29  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        [base] Implement fast vector normalization.
 
 
        * docs/*: Updated.
 
-2015-06-24  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-06-24  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        * src/bdf/bdflib.c (_bdf_parse_start): Disallow 0 bpp.
 
-2015-06-24  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-06-24  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        * src/bdf/bdflib.c (_bdf_parse_start): Simplify bpp parsing.
 
        incremental interface callback to apply the encoding to raw
        character index (as it was in the previous code).
 
-2015-04-29  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-04-29  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        [autofit] Speed up IUP.
 
        * src/cff/cffdrivr.c (cff_get_ps_name): Use the `sfnt' service if we
        have an SFNT.
 
-2015-04-27  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-04-27  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        [truetype] Speed up IUP.
 
 
        * src/autofit/afhints.h (AF_HINTS_DO_WARP): New macro.
 
-       * src/autofi/aflatin.c (af_latin_hints_apply)
+       * src/autofit/aflatin.c (af_latin_hints_apply)
        [AF_CONFIG_OPTION_USE_WARPER]: Use `AF_HINTS_DO_WARP' to control use
        of warper.
 
        * src/cff/cffgload.c (cff_slot_load): Use advance width and side
        bearing values from `hmtx' table if present.
 
-2015-04-03  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-04-03  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        * src/autofit/afhints.c (af_glyph_hints_reload): Use do-while loop.
 
-2015-04-02  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-04-02  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        * src/autofit/aflatin.c (af_latin_hint_edges): Reduce logic.
 
-2015-04-01  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-04-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        [autofit] Finish the thought.
 
        * src/cff/cffgload.c (cff_decoder_parse_charstrings)
        <cff_op_callsubr, cff_op_callgsubr, cff_op_return>: Ditto.
 
-2015-03-21  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-03-21  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        [base] Optimize `FT_Angle_Diff'.
 
        single-element runs.  Cf. glyph `Q' in Skia.ttf with weights larger
        than the default.
 
-2015-03-20  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-03-20  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        * src/base/fttrigon.c (FT_Vector_Rotate): Minor refactoring.
 
-2015-03-17  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-03-17  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        Fix Savannah bug #44412 (part 2).
 
        include/config/ftheader.h, include/ftfntfmt.h, modules.cfg,
        src/base/ftfntfmt.c, vms_make.com: Updated.
 
-2015-03-10  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-03-10  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        Fix Savannah bug #44412 (part 1).
 
 
        Found by Alexei.
 
-2015-03-05  Alexei Podtelezhnikov <apodtele@gmail.com>
+2015-03-05  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
        * src/base/ftstroke.c: Simplify.
 
        * src/pfr/pfrload.c (pfr_extra_item_load_font_id): Ditto.
        * src/psaux/psobjs.c (ps_table_add), src/psaux/psobjs.h: Ditto.
        * src/type1/t1load.c (parse_blend_axis_types, parse_encoding,
-       parse_chharstrings, parse_dict): Ditto.
+       parse_charstrings, parse_dict): Ditto.
        * src/type42/t42parse.c (t42_parse_encoding, t42_parse_charstrings,
        t42_parse_dict): Ditto.
 
        * include/internal/ftstream.h (FT_Stream_Pos): Return `FT_ULong'.
 
        * src/base/ftoutln.c, src/base/ftrfork.c, src/base/ftstream.c:
-       Signedess fixes.
+       Signedness fixes.
 
 2015-02-16  Werner Lemberg  <wl@gnu.org>
 
 
 2015-01-11  Werner Lemberg  <wl@gnu.org>
 
-       [truetype] Prettyfing.
+       [truetype] Prettifying.
 
        * src/truetype/ttinterp.c (project, dualproj, fast_project,
        fast_dualproj): Rename to...
        [truetype] More macro expansions.
 
        * src/truetype/ttinterp.c (INS_ARG): Remove macro by expansion,
-       adjusting funtion calls where necessary.
+       adjusting function calls where necessary.
        (FT_UNUSED_ARG): Removed, no longer needed.
 
 2015-01-10  Werner Lemberg  <wl@gnu.org>
index ff81cdf..09a203a 100644 (file)
@@ -1,4 +1,4 @@
-  FreeType 2.6.3
+  FreeType 2.6.4
   ==============
 
   Homepage: http://www.freetype.org
@@ -24,9 +24,9 @@
 
   and download one of the following files.
 
-    freetype-doc-2.6.3.tar.bz2
-    freetype-doc-2.6.3.tar.gz
-    ftdoc263.zip
+    freetype-doc-2.6.4.tar.bz2
+    freetype-doc-2.6.4.tar.gz
+    ftdoc264.zip
 
   To view the documentation online, go to
 
index b354efd..d20df81 100644 (file)
@@ -586,23 +586,53 @@ FT_BEGIN_HEADER
   /*************************************************************************/
   /*                                                                       */
   /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile       */
-  /* EXPERIMENTAL subpixel hinting support into the TrueType driver.  This */
-  /* replaces the native TrueType hinting mechanism when anything but      */
-  /* FT_RENDER_MODE_MONO is requested.                                     */
+  /* subpixel hinting support into the TrueType driver.  This modifies the */
+  /* TrueType hinting mechanism when anything but FT_RENDER_MODE_MONO is   */
+  /* requested.                                                            */
   /*                                                                       */
-  /* Enabling this causes the TrueType driver to ignore instructions under */
-  /* certain conditions.  This is done in accordance with the guide here,  */
-  /* with some minor differences:                                          */
+  /* In particular, it modifies the bytecode interpreter to interpret (or  */
+  /* not) instructions in a certain way so that all TrueType fonts look    */
+  /* like they do in a Windows ClearType (DirectWrite) environment.  See   */
+  /* [1] for a technical overview on what this means.  See `ttinterp.h'    */
+  /* for more details on the LEAN option.                                  */
   /*                                                                       */
-  /*  http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
+  /* There are three options.                                              */
   /*                                                                       */
-  /* By undefining this, you only compile the code necessary to hint       */
-  /* TrueType glyphs with native TT hinting.                               */
+  /* 1. This option is associated with the `Infinality' moniker.           */
+  /*    Contributed by an individual nicknamed Infinality with the goal of */
+  /*    making TrueType fonts render better than on Windows.  A high       */
+  /*    amount of configurability and flexibility, down to rules for       */
+  /*    single glyphs in fonts, but also very slow.  Its experimental and  */
+  /*    slow nature and the original developer losing interest meant that  */
+  /*    this option was never enabled in default builds.                   */
   /*                                                                       */
-  /*   This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be    */
-  /*   defined.                                                            */
+  /* 2. The new default mode for the TrueType driver.  The Infinality code */
+  /*    base was stripped to the bare minimum and all configurability      */
+  /*    removed in the name of speed and simplicity.  The configurability  */
+  /*    was mainly aimed at legacy fonts like Arial, Times New Roman, or   */
+  /*    Courier.  Legacy fonts are fonts that modify vertical stems to     */
+  /*    achieve clean black-and-white bitmaps.  The new mode focuses on    */
+  /*    applying a minimal set of rules to all fonts indiscriminately so   */
+  /*    that modern and web fonts render well while legacy fonts render    */
+  /*    okay.                                                              */
   /*                                                                       */
-#define TT_CONFIG_OPTION_SUBPIXEL_HINTING
+  /* 3. Compile both.                                                      */
+  /*                                                                       */
+  /* By undefining these, you get rendering behavior like on Windows       */
+  /* without ClearType, i.e., Windows XP without ClearType enabled and     */
+  /* Win9x (interpreter version v35).  Or not, depending on how much       */
+  /* hinting blood and testing tears the font designer put into a given    */
+  /* font.  If you define one or both subpixel hinting options, you can    */
+  /* switch between between v35 and the ones you define.                   */
+  /*                                                                       */
+  /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be      */
+  /* defined.                                                              */
+  /*                                                                       */
+  /* [1] http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
+  /*                                                                       */
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING  1     */
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING  2     */
+#define TT_CONFIG_OPTION_SUBPIXEL_HINTING     ( 1 | 2 )
 
 
   /*************************************************************************/
@@ -811,6 +841,14 @@ FT_BEGIN_HEADER
    */
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 #define  TT_USE_BYTECODE_INTERPRETER
+
+#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1
+#define  TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+#endif
+
+#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2
+#define  TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+#endif
 #endif
 
 
index a8097fe..7dd3f55 100644 (file)
@@ -586,23 +586,53 @@ FT_BEGIN_HEADER
   /*************************************************************************/
   /*                                                                       */
   /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile       */
-  /* EXPERIMENTAL subpixel hinting support into the TrueType driver.  This */
-  /* replaces the native TrueType hinting mechanism when anything but      */
-  /* FT_RENDER_MODE_MONO is requested.                                     */
+  /* subpixel hinting support into the TrueType driver.  This modifies the */
+  /* TrueType hinting mechanism when anything but FT_RENDER_MODE_MONO is   */
+  /* requested.                                                            */
   /*                                                                       */
-  /* Enabling this causes the TrueType driver to ignore instructions under */
-  /* certain conditions.  This is done in accordance with the guide here,  */
-  /* with some minor differences:                                          */
+  /* In particular, it modifies the bytecode interpreter to interpret (or  */
+  /* not) instructions in a certain way so that all TrueType fonts look    */
+  /* like they do in a Windows ClearType (DirectWrite) environment.  See   */
+  /* [1] for a technical overview on what this means.  See `ttinterp.h'    */
+  /* for more details on the LEAN option.                                  */
   /*                                                                       */
-  /*  http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
+  /* There are three options.                                              */
   /*                                                                       */
-  /* By undefining this, you only compile the code necessary to hint       */
-  /* TrueType glyphs with native TT hinting.                               */
+  /* 1. This option is associated with the `Infinality' moniker.           */
+  /*    Contributed by an individual nicknamed Infinality with the goal of */
+  /*    making TrueType fonts render better than on Windows.  A high       */
+  /*    amount of configurability and flexibility, down to rules for       */
+  /*    single glyphs in fonts, but also very slow.  Its experimental and  */
+  /*    slow nature and the original developer losing interest meant that  */
+  /*    this option was never enabled in default builds.                   */
   /*                                                                       */
-  /*   This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be    */
-  /*   defined.                                                            */
+  /* 2. The new default mode for the TrueType driver.  The Infinality code */
+  /*    base was stripped to the bare minimum and all configurability      */
+  /*    removed in the name of speed and simplicity.  The configurability  */
+  /*    was mainly aimed at legacy fonts like Arial, Times New Roman, or   */
+  /*    Courier.  Legacy fonts are fonts that modify vertical stems to     */
+  /*    achieve clean black-and-white bitmaps.  The new mode focuses on    */
+  /*    applying a minimal set of rules to all fonts indiscriminately so   */
+  /*    that modern and web fonts render well while legacy fonts render    */
+  /*    okay.                                                              */
   /*                                                                       */
-/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+  /* 3. Compile both.                                                      */
+  /*                                                                       */
+  /* By undefining these, you get rendering behavior like on Windows       */
+  /* without ClearType, i.e., Windows XP without ClearType enabled and     */
+  /* Win9x (interpreter version v35).  Or not, depending on how much       */
+  /* hinting blood and testing tears the font designer put into a given    */
+  /* font.  If you define one or both subpixel hinting options, you can    */
+  /* switch between between v35 and the ones you define.                   */
+  /*                                                                       */
+  /* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be      */
+  /* defined.                                                              */
+  /*                                                                       */
+  /* [1] http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
+  /*                                                                       */
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING  1     */
+#define TT_CONFIG_OPTION_SUBPIXEL_HINTING     2
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING  ( 1 | 2 ) */
 
 
   /*************************************************************************/
@@ -811,6 +841,14 @@ FT_BEGIN_HEADER
    */
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 #define  TT_USE_BYTECODE_INTERPRETER
+
+#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1
+#define  TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+#endif
+
+#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2
+#define  TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+#endif
 #endif
 
 
index 9daea56..562e255 100644 (file)
@@ -63,6 +63,7 @@
 #define FT_INT_MAX     INT_MAX
 #define FT_INT_MIN     INT_MIN
 #define FT_UINT_MAX    UINT_MAX
+#define FT_LONG_MIN    LONG_MIN
 #define FT_LONG_MAX    LONG_MAX
 #define FT_ULONG_MAX   ULONG_MAX
 
index 4666d48..7baf185 100644 (file)
@@ -651,11 +651,11 @@ FT_BEGIN_HEADER
   /*                                                                       */
   /*    FT_ENCODING_SJIS ::                                                */
   /*      Corresponds to Japanese SJIS encoding.  More info at             */
-  /*      at `http://en.wikipedia.org/wiki/Shift_JIS'.                     */
+  /*      `http://en.wikipedia.org/wiki/Shift_JIS'.                        */
   /*      See note on multi-byte encodings below.                          */
   /*                                                                       */
   /*    FT_ENCODING_GB2312 ::                                              */
-  /*      Corresponds to an encoding system for Simplified Chinese as used */
+  /*      Corresponds to an encoding system for Simplified Chinese as      */
   /*      used in mainland China.                                          */
   /*                                                                       */
   /*    FT_ENCODING_BIG5 ::                                                */
@@ -1103,7 +1103,7 @@ FT_BEGIN_HEADER
   /*    FT_FACE_FLAG_SCALABLE ::                                           */
   /*      Indicates that the face contains outline glyphs.  This doesn't   */
   /*      prevent bitmap strikes, i.e., a face can have both this and      */
-  /*      and @FT_FACE_FLAG_FIXED_SIZES set.                               */
+  /*      @FT_FACE_FLAG_FIXED_SIZES set.                                   */
   /*                                                                       */
   /*    FT_FACE_FLAG_FIXED_SIZES ::                                        */
   /*      Indicates that the face contains bitmap strikes.  See also the   */
@@ -1222,7 +1222,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_HAS_HORIZONTAL( face ) \
-          ( face->face_flags & FT_FACE_FLAG_HORIZONTAL )
+          ( (face)->face_flags & FT_FACE_FLAG_HORIZONTAL )
 
 
   /*************************************************************************
@@ -1236,7 +1236,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_HAS_VERTICAL( face ) \
-          ( face->face_flags & FT_FACE_FLAG_VERTICAL )
+          ( (face)->face_flags & FT_FACE_FLAG_VERTICAL )
 
 
   /*************************************************************************
@@ -1250,7 +1250,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_HAS_KERNING( face ) \
-          ( face->face_flags & FT_FACE_FLAG_KERNING )
+          ( (face)->face_flags & FT_FACE_FLAG_KERNING )
 
 
   /*************************************************************************
@@ -1265,7 +1265,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_IS_SCALABLE( face ) \
-          ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+          ( (face)->face_flags & FT_FACE_FLAG_SCALABLE )
 
 
   /*************************************************************************
@@ -1284,7 +1284,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_IS_SFNT( face ) \
-          ( face->face_flags & FT_FACE_FLAG_SFNT )
+          ( (face)->face_flags & FT_FACE_FLAG_SFNT )
 
 
   /*************************************************************************
@@ -1299,7 +1299,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_IS_FIXED_WIDTH( face ) \
-          ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH )
+          ( (face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH )
 
 
   /*************************************************************************
@@ -1314,7 +1314,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_HAS_FIXED_SIZES( face ) \
-          ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
+          ( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES )
 
 
   /*************************************************************************
@@ -1340,7 +1340,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_HAS_GLYPH_NAMES( face ) \
-          ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
+          ( (face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
 
 
   /*************************************************************************
@@ -1355,7 +1355,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_HAS_MULTIPLE_MASTERS( face ) \
-          ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )
+          ( (face)->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )
 
 
   /*************************************************************************
@@ -1373,7 +1373,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_IS_CID_KEYED( face ) \
-          ( face->face_flags & FT_FACE_FLAG_CID_KEYED )
+          ( (face)->face_flags & FT_FACE_FLAG_CID_KEYED )
 
 
   /*************************************************************************
@@ -1387,7 +1387,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_IS_TRICKY( face ) \
-          ( face->face_flags & FT_FACE_FLAG_TRICKY )
+          ( (face)->face_flags & FT_FACE_FLAG_TRICKY )
 
 
   /*************************************************************************
@@ -1401,7 +1401,7 @@ FT_BEGIN_HEADER
    *
    */
 #define FT_HAS_COLOR( face ) \
-          ( face->face_flags & FT_FACE_FLAG_COLOR )
+          ( (face)->face_flags & FT_FACE_FLAG_COLOR )
 
 
   /*************************************************************************/
@@ -1941,7 +1941,7 @@ FT_BEGIN_HEADER
   /*                                                                       */
   /*    If the @FT_OPEN_MEMORY bit is set, assume that this is a           */
   /*    memory file of `memory_size' bytes, located at `memory_address'.   */
-  /*    The data are are not copied, and the client is responsible for     */
+  /*    The data are not copied, and the client is responsible for         */
   /*    releasing and destroying them _after_ the corresponding call to    */
   /*    @FT_Done_Face.                                                     */
   /*                                                                       */
@@ -2339,9 +2339,9 @@ FT_BEGIN_HEADER
   /*      used to determine both scaling values.                           */
   /*                                                                       */
   /*    FT_SIZE_REQUEST_TYPE_REAL_DIM ::                                   */
-  /*      The real dimension.  The sum of the the `ascender' and (minus    */
-  /*      of) the `descender' fields of @FT_FaceRec are used to determine  */
-  /*      both scaling values.                                             */
+  /*      The real dimension.  The sum of the `ascender' and (minus of)    */
+  /*      the `descender' fields of @FT_FaceRec are used to determine both */
+  /*      scaling values.                                                  */
   /*                                                                       */
   /*    FT_SIZE_REQUEST_TYPE_BBOX ::                                       */
   /*      The font bounding box.  The width and height of the `bbox' field */
@@ -2578,6 +2578,10 @@ FT_BEGIN_HEADER
   /*    don't have a corresponding glyph in the font).  See the discussion */
   /*    of the @FT_FACE_FLAG_CID_KEYED flag for more details.              */
   /*                                                                       */
+  /*    If you receive `FT_Err_Glyph_Too_Big', try getting the glyph       */
+  /*    outline at EM size, then scale it manually and fill it as a        */
+  /*    graphics operation.                                                */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Load_Glyph( FT_Face   face,
                  FT_UInt   glyph_index,
@@ -2855,7 +2859,7 @@ FT_BEGIN_HEADER
    *
    *   If @FT_LOAD_RENDER is also set, the glyph is rendered in the
    *   corresponding mode (i.e., the mode that matches the used algorithm
-   *   best).  An exeption is FT_LOAD_TARGET_MONO since it implies
+   *   best).  An exception is FT_LOAD_TARGET_MONO since it implies
    *   @FT_LOAD_MONOCHROME.
    *
    *   You can use a hinting algorithm that doesn't correspond to the same
@@ -3273,7 +3277,7 @@ FT_BEGIN_HEADER
   /*    `.notdef').                                                        */
   /*                                                                       */
   /*    This function always returns an error if the config macro          */
-  /*    `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is not defined in `ftoptions.h'. */
+  /*    `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is not defined in `ftoption.h'.  */
   /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Get_Glyph_Name( FT_Face     face,
@@ -4172,7 +4176,7 @@ FT_BEGIN_HEADER
    */
 #define FREETYPE_MAJOR  2
 #define FREETYPE_MINOR  6
-#define FREETYPE_PATCH  3
+#define FREETYPE_PATCH  4
 
 
   /*************************************************************************/
index 8052dd2..40c8003 100644 (file)
@@ -219,8 +219,8 @@ FT_BEGIN_HEADER
    *       U+0F00 - U+0FFF  // Tibetan
    *       U+1900 - U+194F  // Limbu
    *       U+1B80 - U+1BBF  // Sundanese
-   *       U+1C80 - U+1CDF  // Meetei Mayak
    *       U+A800 - U+A82F  // Syloti Nagri
+   *       U+ABC0 - U+ABFF  // Meetei Mayek
    *      U+11800 - U+118DF // Sharada
    *     }
    *
index 6c9f2c4..883c88d 100644 (file)
@@ -749,7 +749,7 @@ FT_BEGIN_HEADER
   /*    aglyph :: The corresponding @FT_Glyph object.  0~in case of        */
   /*              failure.                                                 */
   /*                                                                       */
-  /*    anode  :: Used to return the address of of the corresponding cache */
+  /*    anode  :: Used to return the address of the corresponding cache    */
   /*              node after incrementing its reference count (see note    */
   /*              below).                                                  */
   /*                                                                       */
@@ -802,7 +802,7 @@ FT_BEGIN_HEADER
   /*    aglyph     :: The corresponding @FT_Glyph object.  0~in case of    */
   /*                  failure.                                             */
   /*                                                                       */
-  /*    anode      :: Used to return the address of of the corresponding   */
+  /*    anode      :: Used to return the address of the corresponding      */
   /*                  cache node after incrementing its reference count    */
   /*                  (see note below).                                    */
   /*                                                                       */
@@ -957,7 +957,7 @@ FT_BEGIN_HEADER
   /* <Output>                                                              */
   /*    sbit   :: A handle to a small bitmap descriptor.                   */
   /*                                                                       */
-  /*    anode  :: Used to return the address of of the corresponding cache */
+  /*    anode  :: Used to return the address of the corresponding cache    */
   /*              node after incrementing its reference count (see note    */
   /*              below).                                                  */
   /*                                                                       */
@@ -1012,7 +1012,7 @@ FT_BEGIN_HEADER
   /* <Output>                                                              */
   /*    sbit       :: A handle to a small bitmap descriptor.               */
   /*                                                                       */
-  /*    anode      :: Used to return the address of of the corresponding   */
+  /*    anode      :: Used to return the address of the corresponding      */
   /*                  cache node after incrementing its reference count    */
   /*                  (see note below).                                    */
   /*                                                                       */
index 9dea980..ad34541 100644 (file)
@@ -89,7 +89,7 @@ FT_BEGIN_HEADER
    *   features preserve the design's weight and spacing much better than
    *   aliased type would.
    *
-   *   2) Aligment in the vertical direction: Weights and spacing along the
+   *   2) Alignment in the vertical direction: Weights and spacing along the
    *   y~axis are less critical; what is much more important is the visual
    *   alignment of related features (like cap-height and x-height).  The
    *   sense of alignment for these is enhanced by the sharpness of grid-fit
@@ -110,7 +110,7 @@ FT_BEGIN_HEADER
    *   to minimize distortion.
    *
    * @order:
-   *   hinting-engine
+   *   hinting-engine[cff]
    *   no-stem-darkening[cff]
    *   darkening-parameters[cff]
    *
@@ -120,7 +120,7 @@ FT_BEGIN_HEADER
   /**************************************************************************
    *
    * @property:
-   *   hinting-engine
+   *   hinting-engine[cff]
    *
    * @description:
    *   Thanks to Adobe, which contributed a new hinting (and parsing)
@@ -157,8 +157,8 @@ FT_BEGIN_HEADER
    *   FT_CFF_HINTING_XXX
    *
    * @description:
-   *   A list of constants used for the @hinting-engine property to select
-   *   the hinting engine for CFF fonts.
+   *   A list of constants used for the @hinting-engine[cff] property to
+   *   select the hinting engine for CFF fonts.
    *
    * @values:
    *   FT_CFF_HINTING_FREETYPE ::
index 140f2f8..e1bc9fe 100644 (file)
@@ -97,8 +97,8 @@ FT_BEGIN_HEADER
    *
    * @description:
    *    Retrieve the type of the input face, CID keyed or not.  In
-   *    constrast to the @FT_IS_CID_KEYED macro this function returns
-   *    successfully also for CID-keyed fonts in an SNFT wrapper.
+   *    contrast to the @FT_IS_CID_KEYED macro this function returns
+   *    successfully also for CID-keyed fonts in an SFNT wrapper.
    *
    * @input:
    *    face ::
index 9e658b0..3932ce6 100644 (file)
@@ -117,11 +117,11 @@ FT_BEGIN_HEADER
   *
   * @inout:
   *   output_len ::
-  *     Before calling the function, this is the the total size of the
-  *     output buffer, which must be large enough to hold the entire
-  *     uncompressed data (so the size of the uncompressed data must be
-  *     known in advance).  After calling the function, `output_len' is the
-  *     size of the used data in `output'.
+  *     Before calling the function, this is the total size of the output
+  *     buffer, which must be large enough to hold the entire uncompressed
+  *     data (so the size of the uncompressed data must be known in
+  *     advance).  After calling the function, `output_len' is the size of
+  *     the used data in `output'.
   *
   * @return:
   *   FreeType error code.  0~means success.
index 1d557c9..28b2704 100644 (file)
@@ -747,7 +747,7 @@ FT_BEGIN_HEADER
   /*************************************************************************/
   /*                                                                       */
   /* A raster is a scan converter, in charge of rendering an outline into  */
-  /* a a bitmap.  This section contains the public API for rasters.        */
+  /* a bitmap.  This section contains the public API for rasters.          */
   /*                                                                       */
   /* Note that in FreeType 2, all rasters are now encapsulated within      */
   /* specific modules called `renderers'.  See `ftrender.h' for more       */
index c678ef3..3e6e18d 100644 (file)
@@ -106,12 +106,12 @@ FT_BEGIN_HEADER
 #define FT_VALIDATE_JSTF  0x1000
 #define FT_VALIDATE_MATH  0x2000
 
-#define FT_VALIDATE_OT  FT_VALIDATE_BASE | \
-                        FT_VALIDATE_GDEF | \
-                        FT_VALIDATE_GPOS | \
-                        FT_VALIDATE_GSUB | \
-                        FT_VALIDATE_JSTF | \
-                        FT_VALIDATE_MATH
+#define FT_VALIDATE_OT  FT_VALIDATE_BASE | \
+                          FT_VALIDATE_GDEF | \
+                          FT_VALIDATE_GPOS | \
+                          FT_VALIDATE_GSUB | \
+                          FT_VALIDATE_JSTF | \
+                          FT_VALIDATE_MATH )
 
  /**********************************************************************
   *
index 908ae07..a75f958 100644 (file)
@@ -290,7 +290,7 @@ FT_BEGIN_HEADER
    *     The stream size in bytes.
    *
    *     In case of compressed streams where the size is unknown before
-   *     actually doing the decompression, the value is set to 0x7FFFFFFF. 
+   *     actually doing the decompression, the value is set to 0x7FFFFFFF.
    *     (Note that this size value can occur for normal streams also; it is
    *     thus just a hint.)
    *
index 6c02e65..0d868bc 100644 (file)
@@ -138,31 +138,37 @@ FT_BEGIN_HEADER
    *   interpreter-version
    *
    * @description:
-   *   Currently, two versions are available, representing the bytecode
-   *   interpreter with and without subpixel hinting support,
-   *   respectively.  The default is subpixel support if
-   *   TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel
-   *   support otherwise (since it isn't available then).
+
+   *   Currently, three versions are available, two representing the
+   *   bytecode interpreter with subpixel hinting support (old `Infinality'
+   *   code and new stripped-down and higher performance `minimal' code) and
+   *   one without, respectively.  The default is subpixel support if
+   *   TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel support
+   *   otherwise (since it isn't available then).
    *
    *   If subpixel hinting is on, many TrueType bytecode instructions behave
    *   differently compared to B/W or grayscale rendering (except if `native
-   *   ClearType' is selected by the font).  The main idea is to render at a
-   *   much increased horizontal resolution, then sampling down the created
-   *   output to subpixel precision.  However, many older fonts are not
-   *   suited to this and must be specially taken care of by applying
-   *   (hardcoded) font-specific tweaks.
+   *   ClearType' is selected by the font).  Microsoft's main idea is to
+   *   render at a much increased horizontal resolution, then sampling down
+   *   the created output to subpixel precision.  However, many older fonts
+   *   are not suited to this and must be specially taken care of by
+   *   applying (hardcoded) tweaks in Microsoft's interpreter.
    *
    *   Details on subpixel hinting and some of the necessary tweaks can be
    *   found in Greg Hitchcock's whitepaper at
-   *   `http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'.
+   *   `http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'. 
+   *   Note that FreeType currently doesn't really `subpixel hint' (6x1, 6x2,
+   *   or 6x5 supersampling) like discussed in the paper.  Depending on the
+   *   chosen interpreter, it simply ignores instructions on vertical stems
+   *   to arrive at very similar results.
    *
-   *   The following example code demonstrates how to activate subpixel
+   *   The following example code demonstrates how to deactivate subpixel
    *   hinting (omitting the error handling).
    *
    *   {
    *     FT_Library  library;
    *     FT_Face     face;
-   *     FT_UInt     interpreter_version = TT_INTERPRETER_VERSION_38;
+   *     FT_UInt     interpreter_version = TT_INTERPRETER_VERSION_35;
    *
    *
    *     FT_Init_FreeType( &library );
@@ -197,9 +203,19 @@ FT_BEGIN_HEADER
    *
    *   TT_INTERPRETER_VERSION_38 ::
    *     Version~38 corresponds to MS rasterizer v.1.9; it is roughly
-   *     equivalent to the hinting provided by DirectWrite ClearType (as
-   *     can be found, for example, in the Internet Explorer~9 running on
-   *     Windows~7).
+   *     equivalent to the hinting provided by DirectWrite ClearType (as can
+   *     be found, for example, in the Internet Explorer~9 running on
+   *     Windows~7).  It is used in FreeType to select the `Infinality'
+   *     subpixel hinting code.  The code may be removed in a future
+   *     version.
+   *
+   *   TT_INTERPRETER_VERSION_40 ::
+   *     Version~40 corresponds to MS rasterizer v.2.1; it is roughly
+   *     equivalent to the hinting provided by DirectWrite ClearType (as can
+   *     be found, for example, in Microsoft's Edge Browser on Windows~10). 
+   *     It is used in FreeType to select the `minimal' subpixel hinting
+   *     code, a stripped-down and higher performance version of the
+   *     `Infinality' code.
    *
    * @note:
    *   This property controls the behaviour of the bytecode interpreter
@@ -207,9 +223,9 @@ FT_BEGIN_HEADER
    *   get rasterized!  In particular, it does not control subpixel color
    *   filtering.
    *
-   *   If FreeType has not been compiled with configuration option
-   *   FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 causes an
-   *   `FT_Err_Unimplemented_Feature' error.
+   *   If FreeType has not been compiled with the configuration option
+   *   FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 or~40 causes
+   *   an `FT_Err_Unimplemented_Feature' error.
    *
    *   Depending on the graphics framework, Microsoft uses different
    *   bytecode and rendering engines.  As a consequence, the version
@@ -290,13 +306,14 @@ FT_BEGIN_HEADER
    *   the version~1 gasp table exclusively (like Color ClearType), while
    *   v1.6 only respects the values of version~0 (bits 0 and~1).
    *
-   *   FreeType doesn't provide all capabilities of the most recent
-   *   ClearType incarnation, thus we identify our subpixel support as
-   *   version~38.
+   *   Keep in mind that the features of the above interpreter versions
+   *   might not map exactly to FreeType features or behavior because it is
+   *   a fundamentally different library with different internals.
    *
    */
 #define TT_INTERPRETER_VERSION_35  35
 #define TT_INTERPRETER_VERSION_38  38
+#define TT_INTERPRETER_VERSION_40  40
 
  /* */
 
index 4b28e6a..3e1e66e 100644 (file)
@@ -213,7 +213,7 @@ FT_BEGIN_HEADER
   /*    And when it is no longer needed a `destroy' function needs to be   */
   /*    called to release that allocation.                                 */
   /*                                                                       */
-  /*    `fcinit.c' (ft_create_default_module_classes) already contains a   */
+  /*    `ftinit.c' (ft_create_default_module_classes) already contains a   */
   /*    mechanism to call these functions for the default modules          */
   /*    described in `ftmodule.h'.                                         */
   /*                                                                       */
index 3157daf..8c06fc2 100644 (file)
@@ -65,13 +65,15 @@ FT_BEGIN_HEADER
 
 #ifdef __cplusplus
 
-  extern "C++"
+extern "C++"
+{
   template <typename T> inline T*
   cplusplus_typeof(        T*,
                     void  *v )
   {
     return static_cast <T*> ( v );
   }
+}
 
 #define FT_ASSIGNP( p, val )  (p) = cplusplus_typeof( (p), (val) )
 
index c37c07e..e3fa320 100644 (file)
@@ -833,7 +833,7 @@ FT_BEGIN_HEADER
   /*                        filtering callback function.                   */
   /*                                                                       */
   /*    pic_container    :: Contains global structs and tables, instead    */
-  /*                        of defining them globallly.                    */
+  /*                        of defining them globally.                     */
   /*                                                                       */
   /*    refcount         :: A counter initialized to~1 at the time an      */
   /*                        @FT_Library structure is created.              */
@@ -971,8 +971,8 @@ FT_BEGIN_HEADER
   /*                                                                       */
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Outline_Funcs struct.         */
-  /*    When FT_CONFIG_OPTION_PIC is defined an init funtion will need to  */
-  /*    be called with a pre-allocated structure to be filled.             */
+  /*    When FT_CONFIG_OPTION_PIC is defined an init function will need    */
+  /*    to be called with a pre-allocated structure to be filled.          */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
   /*    is used).                                                          */
@@ -1030,8 +1030,8 @@ FT_BEGIN_HEADER
   /*                                                                       */
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Raster_Funcs struct.          */
-  /*    When FT_CONFIG_OPTION_PIC is defined an init funtion will need to  */
-  /*    be called with a pre-allocated structure to be filled.             */
+  /*    When FT_CONFIG_OPTION_PIC is defined an init function will need    */
+  /*    to be called with a pre-allocated structure to be filled.          */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
   /*    is used).                                                          */
@@ -1090,8 +1090,8 @@ FT_BEGIN_HEADER
   /*                                                                       */
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Glyph_Class struct.           */
-  /*    When FT_CONFIG_OPTION_PIC is defined an init funtion will need to  */
-  /*    be called with a pre-allocated stcture to be filled.               */
+  /*    When FT_CONFIG_OPTION_PIC is defined an init function will need    */
+  /*    to be called with a pre-allocated structure to be filled.          */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
   /*    is used).                                                          */
@@ -1164,11 +1164,11 @@ FT_BEGIN_HEADER
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Renderer_Class struct.        */
   /*                                                                       */
-  /*    When FT_CONFIG_OPTION_PIC is defined a `create' funtion will need  */
-  /*    to be called with a pointer where the allocated structure is       */
+  /*    When FT_CONFIG_OPTION_PIC is defined a `create' function will      */
+  /*    need to be called with a pointer where the allocated structure is  */
   /*    returned.  And when it is no longer needed a `destroy' function    */
   /*    needs to be called to release that allocation.                     */
-  /*    `fcinit.c' (ft_create_default_module_classes) already contains     */
+  /*    `ftinit.c' (ft_create_default_module_classes) already contains     */
   /*    a mechanism to call these functions for the default modules        */
   /*    described in `ftmodule.h'.                                         */
   /*                                                                       */
@@ -1368,11 +1368,11 @@ FT_BEGIN_HEADER
   /* <Description>                                                         */
   /*    Used to initialize an instance of an FT_Module_Class struct.       */
   /*                                                                       */
-  /*    When FT_CONFIG_OPTION_PIC is defined a `create' funtion needs to   */
-  /*    be called with a pointer where the allocated structure is          */
+  /*    When FT_CONFIG_OPTION_PIC is defined a `create' function needs     */
+  /*    to be called with a pointer where the allocated structure is       */
   /*    returned.  And when it is no longer needed a `destroy' function    */
   /*    needs to be called to release that allocation.                     */
-  /*    `fcinit.c' (ft_create_default_module_classes) already contains     */
+  /*    `ftinit.c' (ft_create_default_module_classes) already contains     */
   /*    a mechanism to call these functions for the default modules        */
   /*    described in `ftmodule.h'.                                         */
   /*                                                                       */
index 13a68fe..b923401 100644 (file)
@@ -227,7 +227,7 @@ FT_BEGIN_HEADER
   /*    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 `snft' resources, sorting   */
+  /*      to restore Type1 font properly.  For `sfnt' resources, sorting   */
   /*      may induce a different order of the faces in comparison to that  */
   /*      by QuickDraw API.                                                */
   /*                                                                       */
index 689afa9..8c3c14c 100644 (file)
@@ -44,7 +44,6 @@
 
 #define FT_INTERNAL_POSTSCRIPT_AUX_H      <freetype/internal/psaux.h>
 #define FT_INTERNAL_POSTSCRIPT_HINTS_H    <freetype/internal/pshints.h>
-#define FT_INTERNAL_POSTSCRIPT_GLOBALS_H  <freetype/internal/psglobal.h>
 
 #define FT_INTERNAL_AUTOHINT_H            <freetype/internal/autohint.h>
 
index 8643775..4110d50 100644 (file)
@@ -185,7 +185,7 @@ FT_BEGIN_HEADER
   /*                                                                       */
   /*    CompLength :: Compressed table length (in bytes).                  */
   /*                                                                       */
-  /*    OrigLength :: Unompressed table length (in bytes).                 */
+  /*    OrigLength :: Uncompressed table length (in bytes).                */
   /*                                                                       */
   /*    CheckSum   :: The table checksum.  This value can be ignored.      */
   /*                                                                       */
@@ -1386,12 +1386,12 @@ FT_BEGIN_HEADER
     FT_ULong              horz_metrics_offset;
     FT_ULong              vert_metrics_offset;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* since 2.4.12 */
     FT_ULong              sph_found_func_flags; /* special functions found */
                                                 /* for this face           */
     FT_Bool               sph_compatibility_mode;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
   } TT_FaceRec;
 
index dfe3bcb..1c075dc 100644 (file)
@@ -587,7 +587,7 @@ FT_BEGIN_HEADER
   /*                                                                       */
   /*    FT_SFNT_HHEA :: To access the font's @TT_HoriHeader structure.     */
   /*                                                                       */
-  /*    FT_SFNT_VHEA :: To access the font's @TT_VertHeader struture.      */
+  /*    FT_SFNT_VHEA :: To access the font's @TT_VertHeader structure.     */
   /*                                                                       */
   /*    FT_SFNT_POST :: To access the font's @TT_Postscript structure.     */
   /*                                                                       */
index 7d9646c..95786ed 100644 (file)
     '\0',
     '\xD9', '\x80',  /* ـ */
     '\0',
+    '\xD4', '\xB1', ' ', '\xD5', '\x84', ' ', '\xD5', '\x92', ' ', '\xD5', '\x93', ' ', '\xD4', '\xB2', ' ', '\xD4', '\xB3', ' ', '\xD4', '\xB4', ' ', '\xD5', '\x95',  /* Ա Մ Ւ Փ Բ Գ Դ Օ */
+    '\0',
+    '\xD5', '\x92', ' ', '\xD5', '\x88', ' ', '\xD5', '\x93', ' ', '\xD5', '\x83', ' ', '\xD5', '\x87', ' ', '\xD5', '\x8D', ' ', '\xD5', '\x8F', ' ', '\xD5', '\x95',  /* Ւ Ո Փ Ճ Շ Ս Տ Օ */
+    '\0',
+    '\xD5', '\xA5', ' ', '\xD5', '\xA7', ' ', '\xD5', '\xAB', ' ', '\xD5', '\xB4', ' ', '\xD5', '\xBE', ' ', '\xD6', '\x83', ' ', '\xD6', '\x86', ' ', '\xD6', '\x83',  /* ե է ի մ վ փ ֆ փ */
+    '\0',
+    '\xD5', '\xA1', ' ', '\xD5', '\xB5', ' ', '\xD6', '\x82', ' ', '\xD5', '\xBD', ' ', '\xD5', '\xA3', ' ', '\xD5', '\xBB', ' ', '\xD6', '\x80', ' ', '\xD6', '\x85',  /* ա յ ւ ս գ ջ ր օ */
+    '\0',
+    '\xD5', '\xB0', ' ', '\xD5', '\xB8', ' ', '\xD5', '\xB3', ' ', '\xD5', '\xA1', ' ', '\xD5', '\xA5', ' ', '\xD5', '\xAE', ' ', '\xD5', '\xBD', ' ', '\xD6', '\x85',  /* հ ո ճ ա ե ծ ս օ */
+    '\0',
+    '\xD5', '\xA2', ' ', '\xD5', '\xA8', ' ', '\xD5', '\xAB', ' ', '\xD5', '\xAC', ' ', '\xD5', '\xB2', ' ', '\xD5', '\xBA', ' ', '\xD6', '\x83', ' ', '\xD6', '\x81',  /* բ ը ի լ ղ պ փ ց */
+    '\0',
     '\xE0', '\xA6', '\x85', ' ', '\xE0', '\xA6', '\xA1', ' ', '\xE0', '\xA6', '\xA4', ' ', '\xE0', '\xA6', '\xA8', ' ', '\xE0', '\xA6', '\xAC', ' ', '\xE0', '\xA6', '\xAD', ' ', '\xE0', '\xA6', '\xB2', ' ', '\xE0', '\xA6', '\x95',  /* অ ড ত ন ব ভ ল ক */
     '\0',
     '\xE0', '\xA6', '\x87', ' ', '\xE0', '\xA6', '\x9F', ' ', '\xE0', '\xA6', '\xA0', ' ', '\xE0', '\xA6', '\xBF', ' ', '\xE0', '\xA7', '\x80', ' ', '\xE0', '\xA7', '\x88', ' ', '\xE0', '\xA7', '\x97',  /* ই ট ঠ ি ী ৈ ৗ */
     '\0',
     '\xE0', '\xA6', '\x93', ' ', '\xE0', '\xA6', '\x8F', ' ', '\xE0', '\xA6', '\xA1', ' ', '\xE0', '\xA6', '\xA4', ' ', '\xE0', '\xA6', '\xA8', ' ', '\xE0', '\xA6', '\xAC', ' ', '\xE0', '\xA6', '\xB2', ' ', '\xE0', '\xA6', '\x95',  /* ও এ ড ত ন ব ল ক */
     '\0',
+    '\xE1', '\x8F', '\x86', ' ', '\xE1', '\x8E', '\xBB', ' ', '\xE1', '\x8E', '\xAC', ' ', '\xE1', '\x8F', '\x83', ' ', '\xE1', '\x8E', '\xA4', ' ', '\xE1', '\x8F', '\xA3', ' ', '\xE1', '\x8E', '\xA6', ' ', '\xE1', '\x8F', '\x95',  /* Ꮖ Ꮋ Ꭼ Ꮓ Ꭴ Ꮳ Ꭶ Ꮥ */
+    '\0',
+    '\xEA', '\xAE', '\x92', ' ', '\xEA', '\xAE', '\xA4', ' ', '\xEA', '\xAE', '\xB6', ' ', '\xEA', '\xAD', '\xB4', ' ', '\xEA', '\xAD', '\xBE', ' ', '\xEA', '\xAE', '\x97', ' ', '\xEA', '\xAE', '\x9D', ' ', '\xEA', '\xAE', '\xBF',  /* ꮒ ꮤ ꮶ ꭴ ꭾ ꮗ ꮝ ꮿ */
+    '\0',
+    '\xEA', '\xAE', '\x96', ' ', '\xEA', '\xAD', '\xBC', ' ', '\xEA', '\xAE', '\x93', ' ', '\xEA', '\xAE', '\xA0', ' ', '\xEA', '\xAE', '\xB3', ' ', '\xEA', '\xAD', '\xB6', ' ', '\xEA', '\xAE', '\xA5', ' ', '\xEA', '\xAE', '\xBB',  /* ꮖ ꭼ ꮓ ꮠ ꮳ ꭶ ꮥ ꮻ */
+    '\0',
+    '\xE1', '\x8F', '\xB8', ' ', '\xEA', '\xAE', '\x90', ' ', '\xEA', '\xAD', '\xB9', ' ', '\xEA', '\xAD', '\xBB',  /* ᏸ ꮐ ꭹ ꭻ */
+    '\0',
     '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\x9F', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD',  /* Б В Е П З О С Э */
     '\0',
     '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\xA8', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD',  /* Б В Е Ш З О С Э */
     '\0',
     '\xE0', '\xA5', '\x81', ' ', '\xE0', '\xA5', '\x83',  /* ु ृ */
     '\0',
+    '\xE1', '\x88', '\x80', ' ', '\xE1', '\x88', '\x83', ' ', '\xE1', '\x8B', '\x98', ' ', '\xE1', '\x8D', '\x90', ' ', '\xE1', '\x88', '\x9B', ' ', '\xE1', '\x89', '\xA0', ' ', '\xE1', '\x8B', '\x8B', ' ', '\xE1', '\x8B', '\x90',  /* ሀ ሃ ዘ ፐ ማ በ ዋ ዐ */
+    '\0',
+    '\xE1', '\x88', '\x88', ' ', '\xE1', '\x88', '\x90', ' ', '\xE1', '\x89', '\xA0', ' ', '\xE1', '\x8B', '\x98', ' ', '\xE1', '\x88', '\x80', ' ', '\xE1', '\x88', '\xAA', ' ', '\xE1', '\x8B', '\x90', ' ', '\xE1', '\x8C', '\xA8',  /* ለ ሐ በ ዘ ሀ ሪ ዐ ጨ */
+    '\0',
+    '\xE1', '\x83', '\x92', ' ', '\xE1', '\x83', '\x93', ' ', '\xE1', '\x83', '\x94', ' ', '\xE1', '\x83', '\x95', ' ', '\xE1', '\x83', '\x97', ' ', '\xE1', '\x83', '\x98', ' ', '\xE1', '\x83', '\x9D', ' ', '\xE1', '\x83', '\xA6',  /* გ დ ე ვ თ ი ო ღ */
+    '\0',
+    '\xE1', '\x83', '\x90', ' ', '\xE1', '\x83', '\x96', ' ', '\xE1', '\x83', '\x9B', ' ', '\xE1', '\x83', '\xA1', ' ', '\xE1', '\x83', '\xA8', ' ', '\xE1', '\x83', '\xAB', ' ', '\xE1', '\x83', '\xAE', ' ', '\xE1', '\x83', '\x9E',  /* ა ზ მ ს შ ძ ხ პ */
+    '\0',
+    '\xE1', '\x83', '\xA1', ' ', '\xE1', '\x83', '\xAE', ' ', '\xE1', '\x83', '\xA5', ' ', '\xE1', '\x83', '\x96', ' ', '\xE1', '\x83', '\x9B', ' ', '\xE1', '\x83', '\xA8', ' ', '\xE1', '\x83', '\xA9', ' ', '\xE1', '\x83', '\xAC',  /* ს ხ ქ ზ მ შ ჩ წ */
+    '\0',
+    '\xE1', '\x83', '\x94', ' ', '\xE1', '\x83', '\x95', ' ', '\xE1', '\x83', '\x9F', ' ', '\xE1', '\x83', '\xA2', ' ', '\xE1', '\x83', '\xA3', ' ', '\xE1', '\x83', '\xA4', ' ', '\xE1', '\x83', '\xA5', ' ', '\xE1', '\x83', '\xA7',  /* ე ვ ჟ ტ უ ფ ქ ყ */
+    '\0',
+    '\xE1', '\x82', '\xB1', ' ', '\xE1', '\x82', '\xA7', ' ', '\xE1', '\x82', '\xB9', ' ', '\xE1', '\x82', '\xBC', ' ', '\xE1', '\x82', '\xA4', ' ', '\xE1', '\x82', '\xA5', ' ', '\xE1', '\x82', '\xB3', ' ', '\xE1', '\x82', '\xBA',  /* Ⴑ Ⴇ Ⴙ Ⴜ Ⴄ Ⴅ Ⴓ Ⴚ */
+    '\0',
+    '\xE1', '\x82', '\xA4', ' ', '\xE1', '\x82', '\xA5', ' ', '\xE1', '\x82', '\xA7', ' ', '\xE1', '\x82', '\xA8', ' ', '\xE1', '\x82', '\xA6', ' ', '\xE1', '\x82', '\xB1', ' ', '\xE1', '\x82', '\xAA', ' ', '\xE1', '\x82', '\xAB',  /* Ⴄ Ⴅ Ⴇ Ⴈ Ⴆ Ⴑ Ⴊ Ⴋ */
+    '\0',
+    '\xE2', '\xB4', '\x81', ' ', '\xE2', '\xB4', '\x97', ' ', '\xE2', '\xB4', '\x82', ' ', '\xE2', '\xB4', '\x84', ' ', '\xE2', '\xB4', '\x85', ' ', '\xE2', '\xB4', '\x87', ' ', '\xE2', '\xB4', '\x94', ' ', '\xE2', '\xB4', '\x96',  /* ⴁ ⴗ ⴂ ⴄ ⴅ ⴇ ⴔ ⴖ */
+    '\0',
+    '\xE2', '\xB4', '\x88', ' ', '\xE2', '\xB4', '\x8C', ' ', '\xE2', '\xB4', '\x96', ' ', '\xE2', '\xB4', '\x8E', ' ', '\xE2', '\xB4', '\x83', ' ', '\xE2', '\xB4', '\x86', ' ', '\xE2', '\xB4', '\x8B', ' ', '\xE2', '\xB4', '\xA2',  /* ⴈ ⴌ ⴖ ⴎ ⴃ ⴆ ⴋ ⴢ */
+    '\0',
+    '\xE2', '\xB4', '\x90', ' ', '\xE2', '\xB4', '\x91', ' ', '\xE2', '\xB4', '\x93', ' ', '\xE2', '\xB4', '\x95', ' ', '\xE2', '\xB4', '\x99', ' ', '\xE2', '\xB4', '\x9B', ' ', '\xE2', '\xB4', '\xA1', ' ', '\xE2', '\xB4', '\xA3',  /* ⴐ ⴑ ⴓ ⴕ ⴙ ⴛ ⴡ ⴣ */
+    '\0',
+    '\xE2', '\xB4', '\x84', ' ', '\xE2', '\xB4', '\x85', ' ', '\xE2', '\xB4', '\x94', ' ', '\xE2', '\xB4', '\x95', ' ', '\xE2', '\xB4', '\x81', ' ', '\xE2', '\xB4', '\x82', ' ', '\xE2', '\xB4', '\x98', ' ', '\xE2', '\xB4', '\x9D',  /* ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ */
+    '\0',
     '\xCE', '\x93', ' ', '\xCE', '\x92', ' ', '\xCE', '\x95', ' ', '\xCE', '\x96', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', ' ', '\xCE', '\xA9',  /* Γ Β Ε Ζ Θ Ο Ω */
     '\0',
     '\xCE', '\x92', ' ', '\xCE', '\x94', ' ', '\xCE', '\x96', ' ', '\xCE', '\x9E', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F',  /* Β Δ Ζ Ξ Θ Ο */
     '\0',
     '\xCE', '\xB2', ' ', '\xCE', '\xB3', ' ', '\xCE', '\xB7', ' ', '\xCE', '\xBC', ' ', '\xCF', '\x81', ' ', '\xCF', '\x86', ' ', '\xCF', '\x87', ' ', '\xCF', '\x88',  /* β γ η μ ρ φ χ ψ */
     '\0',
+    '\xE0', '\xAA', '\xA4', ' ', '\xE0', '\xAA', '\xA8', ' ', '\xE0', '\xAA', '\x8B', ' ', '\xE0', '\xAA', '\x8C', ' ', '\xE0', '\xAA', '\x9B', ' ', '\xE0', '\xAA', '\x9F', ' ', '\xE0', '\xAA', '\xB0', ' ', '\xE0', '\xAB', '\xA6',  /* ત ન ઋ ઌ છ ટ ર ૦ */
+    '\0',
+    '\xE0', '\xAA', '\x96', ' ', '\xE0', '\xAA', '\x97', ' ', '\xE0', '\xAA', '\x98', ' ', '\xE0', '\xAA', '\x9E', ' ', '\xE0', '\xAA', '\x87', ' ', '\xE0', '\xAA', '\x88', ' ', '\xE0', '\xAA', '\xA0', ' ', '\xE0', '\xAA', '\x9C',  /* ખ ગ ઘ ઞ ઇ ઈ ઠ જ */
+    '\0',
+    '\xE0', '\xAA', '\x88', ' ', '\xE0', '\xAA', '\x8A', ' ', '\xE0', '\xAA', '\xBF', ' ', '\xE0', '\xAB', '\x80', ' ', '\xE0', '\xAA', '\xB2', '\xE0', '\xAB', '\x80', ' ', '\xE0', '\xAA', '\xB6', '\xE0', '\xAB', '\x8D', '\xE0', '\xAA', '\x9A', '\xE0', '\xAA', '\xBF', ' ', '\xE0', '\xAA', '\x9C', '\xE0', '\xAA', '\xBF', ' ', '\xE0', '\xAA', '\xB8', '\xE0', '\xAB', '\x80',  /* ઈ ઊ િ ી લી શ્ચિ જિ સી */
+    '\0',
+    '\xE0', '\xAB', '\x81', ' ', '\xE0', '\xAB', '\x83', ' ', '\xE0', '\xAB', '\x84', ' ', '\xE0', '\xAA', '\x96', '\xE0', '\xAB', '\x81', ' ', '\xE0', '\xAA', '\x9B', '\xE0', '\xAB', '\x83', ' ', '\xE0', '\xAA', '\x9B', '\xE0', '\xAB', '\x84',  /* ુ ૃ ૄ ખુ છૃ છૄ */
+    '\0',
+    '\xE0', '\xAB', '\xA6', ' ', '\xE0', '\xAB', '\xA7', ' ', '\xE0', '\xAB', '\xA8', ' ', '\xE0', '\xAB', '\xA9', ' ', '\xE0', '\xAB', '\xAD',  /* ૦ ૧ ૨ ૩ ૭ */
+    '\0',
+    '\xE0', '\xA8', '\x95', ' ', '\xE0', '\xA8', '\x97', ' ', '\xE0', '\xA8', '\x99', ' ', '\xE0', '\xA8', '\x9A', ' ', '\xE0', '\xA8', '\x9C', ' ', '\xE0', '\xA8', '\xA4', ' ', '\xE0', '\xA8', '\xA7', ' ', '\xE0', '\xA8', '\xB8',  /* ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ */
+    '\0',
+    '\xE0', '\xA8', '\x95', ' ', '\xE0', '\xA8', '\x97', ' ', '\xE0', '\xA8', '\x99', ' ', '\xE0', '\xA8', '\x9A', ' ', '\xE0', '\xA8', '\x9C', ' ', '\xE0', '\xA8', '\xA4', ' ', '\xE0', '\xA8', '\xA7', ' ', '\xE0', '\xA8', '\xB8',  /* ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ */
+    '\0',
+    '\xE0', '\xA8', '\x87', ' ', '\xE0', '\xA8', '\x88', ' ', '\xE0', '\xA8', '\x89', ' ', '\xE0', '\xA8', '\x8F', ' ', '\xE0', '\xA8', '\x93', ' ', '\xE0', '\xA9', '\xB3', ' ', '\xE0', '\xA8', '\xBF', ' ', '\xE0', '\xA9', '\x80',  /* ਇ ਈ ਉ ਏ ਓ ੳ ਿ ੀ */
+    '\0',
+    '\xE0', '\xA8', '\x85', ' ', '\xE0', '\xA8', '\x8F', ' ', '\xE0', '\xA8', '\x93', ' ', '\xE0', '\xA8', '\x97', ' ', '\xE0', '\xA8', '\x9C', ' ', '\xE0', '\xA8', '\xA0', ' ', '\xE0', '\xA8', '\xB0', ' ', '\xE0', '\xA8', '\xB8',  /* ਅ ਏ ਓ ਗ ਜ ਠ ਰ ਸ */
+    '\0',
+    '\xE0', '\xA9', '\xA6', ' ', '\xE0', '\xA9', '\xA7', ' ', '\xE0', '\xA9', '\xA8', ' ', '\xE0', '\xA9', '\xA9', ' ', '\xE0', '\xA9', '\xAD',  /* ੦ ੧ ੨ ੩ ੭ */
+    '\0',
     '\xD7', '\x91', ' ', '\xD7', '\x93', ' ', '\xD7', '\x94', ' ', '\xD7', '\x97', ' ', '\xD7', '\x9A', ' ', '\xD7', '\x9B', ' ', '\xD7', '\x9D', ' ', '\xD7', '\xA1',  /* ב ד ה ח ך כ ם ס */
     '\0',
     '\xD7', '\x91', ' ', '\xD7', '\x98', ' ', '\xD7', '\x9B', ' ', '\xD7', '\x9D', ' ', '\xD7', '\xA1', ' ', '\xD7', '\xA6',  /* ב ט כ ם ס צ */
     '\0',
     '\xE1', '\xB5', '\x96', ' ', '\xCA', '\xB8', ' ', '\xE1', '\xB5', '\x8D',  /* ᵖ ʸ ᵍ */
     '\0',
+    '\xE0', '\xB4', '\x92', ' ', '\xE0', '\xB4', '\x9F', ' ', '\xE0', '\xB4', '\xA0', ' ', '\xE0', '\xB4', '\xB1', ' ', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xAA', ' ', '\xE0', '\xB4', '\x9A', '\xE0', '\xB5', '\x8D', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xAA', '\xE0', '\xB5', '\x8D', '\xE0', '\xB4', '\xAA',  /* ഒ ട ഠ റ ച പ ച്ച പ്പ */
+    '\0',
+    '\xE0', '\xB4', '\x9F', ' ', '\xE0', '\xB4', '\xA0', ' ', '\xE0', '\xB4', '\xA7', ' ', '\xE0', '\xB4', '\xB6', ' ', '\xE0', '\xB4', '\x98', ' ', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xA5', ' ', '\xE0', '\xB4', '\xB2',  /* ട ഠ ധ ശ ഘ ച ഥ ല */
+    '\0',
     '\xE1', '\x80', '\x81', ' ', '\xE1', '\x80', '\x82', ' ', '\xE1', '\x80', '\x84', ' ', '\xE1', '\x80', '\x92', ' ', '\xE1', '\x80', '\x9D', ' ', '\xE1', '\x81', '\xA5', ' ', '\xE1', '\x81', '\x8A', ' ', '\xE1', '\x81', '\x8B',  /* ခ ဂ င ဒ ဝ ၥ ၊ ။ */
     '\0',
     '\xE1', '\x80', '\x84', ' ', '\xE1', '\x80', '\x8E', ' ', '\xE1', '\x80', '\x92', ' ', '\xE1', '\x80', '\x95', ' ', '\xE1', '\x80', '\x97', ' ', '\xE1', '\x80', '\x9D', ' ', '\xE1', '\x81', '\x8A', ' ', '\xE1', '\x81', '\x8B',  /* င ဎ ဒ ပ ဗ ဝ ၊ ။ */
     '\0',
     '\xE1', '\x80', '\x89', ' ', '\xE1', '\x80', '\x8A', ' ', '\xE1', '\x80', '\xA5', ' ', '\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xA8', ' ', '\xE1', '\x81', '\x82', ' ', '\xE1', '\x81', '\x85', ' ', '\xE1', '\x81', '\x89',  /* ဉ ည ဥ ဩ ဨ ၂ ၅ ၉ */
     '\0',
+    '\xE0', '\xB6', '\x89', ' ', '\xE0', '\xB6', '\x9A', ' ', '\xE0', '\xB6', '\x9D', ' ', '\xE0', '\xB6', '\xB3', ' ', '\xE0', '\xB6', '\xB4', ' ', '\xE0', '\xB6', '\xBA', ' ', '\xE0', '\xB6', '\xBD', ' ', '\xE0', '\xB7', '\x86',  /* ඉ ක ඝ ඳ ප ය ල ෆ */
+    '\0',
+    '\xE0', '\xB6', '\x91', ' ', '\xE0', '\xB6', '\x94', ' ', '\xE0', '\xB6', '\x9D', ' ', '\xE0', '\xB6', '\xA2', ' ', '\xE0', '\xB6', '\xA7', ' ', '\xE0', '\xB6', '\xAE', ' ', '\xE0', '\xB6', '\xB0', ' ', '\xE0', '\xB6', '\xBB',  /* එ ඔ ඝ ජ ට ථ ධ ර */
+    '\0',
+    '\xE0', '\xB6', '\xAF', ' ', '\xE0', '\xB6', '\xB3', ' ', '\xE0', '\xB6', '\x8B', ' ', '\xE0', '\xB6', '\xBD', ' ', '\xE0', '\xB6', '\xAD', '\xE0', '\xB7', '\x96', ' ', '\xE0', '\xB6', '\xAD', '\xE0', '\xB7', '\x94', ' ', '\xE0', '\xB6', '\xB6', '\xE0', '\xB7', '\x94', ' ', '\xE0', '\xB6', '\xAF', '\xE0', '\xB7', '\x94',  /* ද ඳ උ ල තූ තු බු දු */
+    '\0',
+    '\xE0', '\xAE', '\x89', ' ', '\xE0', '\xAE', '\x92', ' ', '\xE0', '\xAE', '\x93', ' ', '\xE0', '\xAE', '\xB1', ' ', '\xE0', '\xAE', '\x88', ' ', '\xE0', '\xAE', '\x95', ' ', '\xE0', '\xAE', '\x99', ' ', '\xE0', '\xAE', '\x9A',  /* உ ஒ ஓ ற ஈ க ங ச */
+    '\0',
+    '\xE0', '\xAE', '\x95', ' ', '\xE0', '\xAE', '\x9A', ' ', '\xE0', '\xAE', '\xB2', ' ', '\xE0', '\xAE', '\xB6', ' ', '\xE0', '\xAE', '\x89', ' ', '\xE0', '\xAE', '\x99', ' ', '\xE0', '\xAE', '\x9F', ' ', '\xE0', '\xAE', '\xAA',  /* க ச ல ஶ உ ங ட ப */
+    '\0',
     '\xE0', '\xB0', '\x87', ' ', '\xE0', '\xB0', '\x8C', ' ', '\xE0', '\xB0', '\x99', ' ', '\xE0', '\xB0', '\x9E', ' ', '\xE0', '\xB0', '\xA3', ' ', '\xE0', '\xB0', '\xB1', ' ', '\xE0', '\xB1', '\xAF',  /* ఇ ఌ ఙ ఞ ణ ఱ ౯ */
     '\0',
     '\xE0', '\xB0', '\x85', ' ', '\xE0', '\xB0', '\x95', ' ', '\xE0', '\xB0', '\x9A', ' ', '\xE0', '\xB0', '\xB0', ' ', '\xE0', '\xB0', '\xBD', ' ', '\xE0', '\xB1', '\xA8', ' ', '\xE0', '\xB1', '\xAC',  /* అ క చ ర ఽ ౨ ౬ */
     { AF_BLUE_STRING_ARABIC_BOTTOM, 0                              },
     { AF_BLUE_STRING_ARABIC_JOIN,   AF_BLUE_PROPERTY_LATIN_NEUTRAL },
     { AF_BLUE_STRING_MAX,           0                              },
-    { AF_BLUE_STRING_BENGALI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        },
-    { AF_BLUE_STRING_BENGALI_HEAD,   AF_BLUE_PROPERTY_LATIN_TOP        },
-    { AF_BLUE_STRING_BENGALI_BASE,   AF_BLUE_PROPERTY_LATIN_TOP      |
-                                     AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
-                                     AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
-    { AF_BLUE_STRING_BENGALI_BASE,   0                                 },
-    { AF_BLUE_STRING_MAX,            0                                 },
+    { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM,  0                                 },
+    { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_ARMENIAN_SMALL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                      0                                 },
+    { AF_BLUE_STRING_BENGALI_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_BENGALI_BASE, AF_BLUE_PROPERTY_LATIN_TOP      |
+                                   AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_BENGALI_BASE, 0                                 },
+    { AF_BLUE_STRING_MAX,          0                                 },
+    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         0                                 },
+    { AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_CHEROKEE_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_CHEROKEE_SMALL,           0                                 },
+    { AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                      0                                 },
     { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
     { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM,  0                                 },
     { AF_BLUE_STRING_CYRILLIC_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
     { AF_BLUE_STRING_DEVANAGARI_BASE,   0                                 },
     { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0                                 },
     { AF_BLUE_STRING_MAX,               0                                 },
+    { AF_BLUE_STRING_ETHIOPIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP },
+    { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0                          },
+    { AF_BLUE_STRING_MAX,             0                          },
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                          0                                 },
+    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM, 0                                 },
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_MAX,                         0                                 },
     { AF_BLUE_STRING_GREEK_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
     { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM,  0                                 },
     { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        },
     { AF_BLUE_STRING_GREEK_SMALL,           0                                 },
     { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0                                 },
     { AF_BLUE_STRING_MAX,                   0                                 },
+    { AF_BLUE_STRING_GUJARATI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_GUJARATI_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_GUJARATI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GUJARATI_DESCENDER, 0                                 },
+    { AF_BLUE_STRING_GUJARATI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_MAX,                0                                 },
+    { AF_BLUE_STRING_GURMUKHI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GURMUKHI_HEAD,      AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_GURMUKHI_BASE,      AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_GURMUKHI_BOTTOM,    0                                 },
+    { AF_BLUE_STRING_GURMUKHI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_MAX,                0                                 },
     { AF_BLUE_STRING_HEBREW_TOP,       AF_BLUE_PROPERTY_LATIN_TOP  |
                                        AF_BLUE_PROPERTY_LATIN_LONG   },
     { AF_BLUE_STRING_HEBREW_BOTTOM,    0                             },
                                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
     { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0                                 },
     { AF_BLUE_STRING_MAX,                         0                                 },
-    { AF_BLUE_STRING_LAO_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
-                                          AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
-    { AF_BLUE_STRING_LAO_BOTTOM,          0                                 },
-    { AF_BLUE_STRING_LAO_ASCENDER,        AF_BLUE_PROPERTY_LATIN_TOP        },
-    { AF_BLUE_STRING_LAO_LARGE_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
-    { AF_BLUE_STRING_LAO_DESCENDER,       0                                 },
-    { AF_BLUE_STRING_MAX,                 0                                 },
+    { AF_BLUE_STRING_LAO_TOP,            AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_LAO_BOTTOM,         0                                 },
+    { AF_BLUE_STRING_LAO_ASCENDER,       AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP        },
+    { AF_BLUE_STRING_LAO_DESCENDER,      0                                 },
+    { AF_BLUE_STRING_MAX,                0                                 },
     { AF_BLUE_STRING_LATIN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
     { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM,  0                                 },
     { AF_BLUE_STRING_LATIN_SMALL_F_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        },
     { AF_BLUE_STRING_LATIN_SUPS_SMALL,           0                                 },
     { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0                                 },
     { AF_BLUE_STRING_MAX,                        0                                 },
+    { AF_BLUE_STRING_MALAYALAM_TOP,    AF_BLUE_PROPERTY_LATIN_TOP },
+    { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0                          },
+    { AF_BLUE_STRING_MAX,              0                          },
     { AF_BLUE_STRING_MYANMAR_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
     { AF_BLUE_STRING_MYANMAR_BOTTOM,    0                                 },
     { AF_BLUE_STRING_MYANMAR_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        },
     { AF_BLUE_STRING_MYANMAR_DESCENDER, 0                                 },
     { AF_BLUE_STRING_MAX,               0                                 },
+    { AF_BLUE_STRING_MAX, 0 },
+    { AF_BLUE_STRING_SINHALA_TOP,       AF_BLUE_PROPERTY_LATIN_TOP },
+    { AF_BLUE_STRING_SINHALA_BOTTOM,    0                          },
+    { AF_BLUE_STRING_SINHALA_DESCENDER, 0                          },
+    { AF_BLUE_STRING_MAX,               0                          },
+    { AF_BLUE_STRING_TAMIL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP },
+    { AF_BLUE_STRING_TAMIL_BOTTOM, 0                          },
+    { AF_BLUE_STRING_MAX,          0                          },
     { AF_BLUE_STRING_TELUGU_TOP,    AF_BLUE_PROPERTY_LATIN_TOP },
     { AF_BLUE_STRING_TELUGU_BOTTOM, 0                          },
     { AF_BLUE_STRING_MAX,           0                          },
index 9a7757c..0734ec7 100644 (file)
@@ -65,8 +65,8 @@
 // values; this essentially means that the maximum values can easily be too
 // large.  Given that the purpose of those values is to create local
 // fixed-size arrays at compile time for further processing of the blue zone
-// data, this isn't a problem.  Note the the final zero byte of a string is
-// not counted.  Note also that the count holds the number of UTF-8 encoded
+// data, this isn't a problem.  Note the final zero byte of a string is not
+// counted.  Note also that the count holds the number of UTF-8 encoded
 // characters, not bytes.
 
 
@@ -86,6 +86,19 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
   AF_BLUE_STRING_ARABIC_JOIN
     "ـ"
 
+  AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP
+    "Ա Մ Ւ Փ Բ Գ Դ Օ"
+  AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM
+    "Ւ Ո Փ Ճ Շ Ս Տ Օ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER
+    "ե է ի մ վ փ ֆ փ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_TOP
+    "ա յ ւ ս գ ջ ր օ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM
+    "հ ո ճ ա ե ծ ս օ"
+  AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER
+    "բ ը ի լ ղ պ փ ց"
+
   AF_BLUE_STRING_BENGALI_BASE
     "অ ড ত ন ব ভ ল ক"
   AF_BLUE_STRING_BENGALI_TOP
@@ -93,6 +106,15 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
   AF_BLUE_STRING_BENGALI_HEAD
     "ও এ ড ত ন ব ল ক"
 
+  AF_BLUE_STRING_CHEROKEE_CAPITAL
+    "Ꮖ Ꮋ Ꭼ Ꮓ Ꭴ Ꮳ Ꭶ Ꮥ"
+  AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER
+    "ꮒ ꮤ ꮶ ꭴ ꭾ ꮗ ꮝ ꮿ"
+  AF_BLUE_STRING_CHEROKEE_SMALL
+    "ꮖ ꭼ ꮓ ꮠ ꮳ ꭶ ꮥ ꮻ"
+  AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER
+    "ᏸ ꮐ ꭹ ꭻ"
+
   AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP
     "Б В Е П З О С Э"
   AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM
@@ -114,6 +136,34 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
   AF_BLUE_STRING_DEVANAGARI_BOTTOM
     "ु ृ"
 
+  AF_BLUE_STRING_ETHIOPIC_TOP
+    "ሀ ሃ ዘ ፐ ማ በ ዋ ዐ"
+  AF_BLUE_STRING_ETHIOPIC_BOTTOM
+    "ለ ሐ በ ዘ ሀ ሪ ዐ ጨ"
+
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP
+    "გ დ ე ვ თ ი ო ღ"
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM
+    "ა ზ მ ს შ ძ ხ პ"
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER
+    "ს ხ ქ ზ მ შ ჩ წ"
+  AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER
+    "ე ვ ჟ ტ უ ფ ქ ყ"
+
+  AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP
+    "Ⴑ Ⴇ Ⴙ Ⴜ Ⴄ Ⴅ Ⴓ Ⴚ"
+  AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM
+    "Ⴄ Ⴅ Ⴇ Ⴈ Ⴆ Ⴑ Ⴊ Ⴋ"
+
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP
+    "ⴁ ⴗ ⴂ ⴄ ⴅ ⴇ ⴔ ⴖ"
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM
+    "ⴈ ⴌ ⴖ ⴎ ⴃ ⴆ ⴋ ⴢ"
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER
+    "ⴐ ⴑ ⴓ ⴕ ⴙ ⴛ ⴡ ⴣ"
+  AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER
+    "ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ"
+
   AF_BLUE_STRING_GREEK_CAPITAL_TOP
     "Γ Β Ε Ζ Θ Ο Ω"
   AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM
@@ -125,6 +175,28 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
   AF_BLUE_STRING_GREEK_SMALL_DESCENDER
     "β γ η μ ρ φ χ ψ"
 
+  AF_BLUE_STRING_GUJARATI_TOP
+    "ત ન ઋ ઌ છ ટ ર ૦"
+  AF_BLUE_STRING_GUJARATI_BOTTOM
+    "ખ ગ ઘ ઞ ઇ ઈ ઠ જ"
+  AF_BLUE_STRING_GUJARATI_ASCENDER
+    "ઈ ઊ િ ી લી શ્ચિ જિ સી"
+  AF_BLUE_STRING_GUJARATI_DESCENDER
+    "ુ ૃ ૄ ખુ છૃ છૄ"
+  AF_BLUE_STRING_GUJARATI_DIGIT_TOP
+    "૦ ૧ ૨ ૩ ૭"
+
+  AF_BLUE_STRING_GURMUKHI_BASE
+    "ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ"
+  AF_BLUE_STRING_GURMUKHI_HEAD
+    "ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ"
+  AF_BLUE_STRING_GURMUKHI_TOP
+    "ਇ ਈ ਉ ਏ ਓ ੳ ਿ ੀ"
+  AF_BLUE_STRING_GURMUKHI_BOTTOM
+    "ਅ ਏ ਓ ਗ ਜ ਠ ਰ ਸ"
+  AF_BLUE_STRING_GURMUKHI_DIGIT_TOP
+    "੦ ੧ ੨ ੩ ੭"
+
   AF_BLUE_STRING_HEBREW_TOP
     "ב ד ה ח ך כ ם ס"
   AF_BLUE_STRING_HEBREW_BOTTOM
@@ -200,6 +272,11 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
   AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER
     "ᵖ ʸ ᵍ"
 
+  AF_BLUE_STRING_MALAYALAM_TOP
+    "ഒ ട ഠ റ ച പ ച്ച പ്പ"
+  AF_BLUE_STRING_MALAYALAM_BOTTOM
+    "ട ഠ ധ ശ ഘ ച ഥ ല"
+
   AF_BLUE_STRING_MYANMAR_TOP
     "ခ ဂ င ဒ ဝ ၥ ၊ ။"
   AF_BLUE_STRING_MYANMAR_BOTTOM
@@ -209,6 +286,18 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
   AF_BLUE_STRING_MYANMAR_DESCENDER
     "ဉ ည ဥ ဩ ဨ ၂ ၅ ၉"
 
+  AF_BLUE_STRING_SINHALA_TOP
+    "ඉ ක ඝ ඳ ප ය ල ෆ"
+  AF_BLUE_STRING_SINHALA_BOTTOM
+    "එ ඔ ඝ ජ ට ථ ධ ර"
+  AF_BLUE_STRING_SINHALA_DESCENDER
+    "ද ඳ උ ල තූ තු බු දු"
+
+  AF_BLUE_STRING_TAMIL_TOP
+    "உ ஒ ஓ ற ஈ க ங ச"
+  AF_BLUE_STRING_TAMIL_BOTTOM
+    "க ச ல ஶ உ ங ட ப"
+
   AF_BLUE_STRING_TELUGU_TOP
     "ఇ ఌ ఙ ఞ ణ ఱ ౯"
   AF_BLUE_STRING_TELUGU_BOTTOM
@@ -400,14 +489,34 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
     { AF_BLUE_STRING_ARABIC_JOIN,   AF_BLUE_PROPERTY_LATIN_NEUTRAL }
     { AF_BLUE_STRING_MAX,           0                              }
 
+  AF_BLUE_STRINGSET_ARMN
+    { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM,  0                                 }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                      0                                 }
+
   AF_BLUE_STRINGSET_BENG
-    { AF_BLUE_STRING_BENGALI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_BENGALI_HEAD,   AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_BENGALI_BASE,   AF_BLUE_PROPERTY_LATIN_TOP      |
-                                     AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
-                                     AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_BENGALI_BASE,   0                                 }
-    { AF_BLUE_STRING_MAX,            0                                 }
+    { AF_BLUE_STRING_BENGALI_TOP,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_BENGALI_BASE, AF_BLUE_PROPERTY_LATIN_TOP      |
+                                   AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_BENGALI_BASE, 0                                 }
+    { AF_BLUE_STRING_MAX,          0                                 }
+
+  AF_BLUE_STRINGSET_CHER
+    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_CHEROKEE_CAPITAL,         0                                 }
+    { AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_CHEROKEE_SMALL,           AF_BLUE_PROPERTY_LATIN_TOP      |
+                                               AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_CHEROKEE_SMALL,           0                                 }
+    { AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                      0                                 }
 
   AF_BLUE_STRINGSET_CYRL
     { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
@@ -428,6 +537,30 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
     { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0                                 }
     { AF_BLUE_STRING_MAX,               0                                 }
 
+  AF_BLUE_STRINGSET_ETHI
+    { AF_BLUE_STRING_ETHIOPIC_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,             0                          }
+
+  // blue zones for Mtavruli are missing (not yet defined in Unicode)
+  AF_BLUE_STRINGSET_GEOR
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                   AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                          0                                 }
+
+  AF_BLUE_STRINGSET_GEOK
+    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP,    AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM, 0                                 }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                                  AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_MAX,                         0                                 }
+
   AF_BLUE_STRINGSET_GREK
     { AF_BLUE_STRING_GREEK_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
     { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM,  0                                 }
@@ -438,6 +571,25 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
     { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0                                 }
     { AF_BLUE_STRING_MAX,                   0                                 }
 
+  AF_BLUE_STRINGSET_GUJR
+    { AF_BLUE_STRING_GUJARATI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GUJARATI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GUJARATI_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GUJARATI_DESCENDER, 0                                 }
+    { AF_BLUE_STRING_GUJARATI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MAX,                0                                 }
+
+  AF_BLUE_STRINGSET_GURU
+    { AF_BLUE_STRING_GURMUKHI_TOP,       AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GURMUKHI_HEAD,      AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_GURMUKHI_BASE,      AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_NEUTRAL  |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_GURMUKHI_BOTTOM,    0                                 }
+    { AF_BLUE_STRING_GURMUKHI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_MAX,                0                                 }
+
   AF_BLUE_STRINGSET_HEBR
     { AF_BLUE_STRING_HEBREW_TOP,       AF_BLUE_PROPERTY_LATIN_TOP  |
                                        AF_BLUE_PROPERTY_LATIN_LONG   }
@@ -466,13 +618,13 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
     { AF_BLUE_STRING_MAX,                         0                                 }
 
   AF_BLUE_STRINGSET_LAO
-    { AF_BLUE_STRING_LAO_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
-                                          AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
-    { AF_BLUE_STRING_LAO_BOTTOM,          0                                 }
-    { AF_BLUE_STRING_LAO_ASCENDER,        AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_LAO_LARGE_ASCENDER,  AF_BLUE_PROPERTY_LATIN_TOP        }
-    { AF_BLUE_STRING_LAO_DESCENDER,       0                                 }
-    { AF_BLUE_STRING_MAX,                 0                                 }
+    { AF_BLUE_STRING_LAO_TOP,            AF_BLUE_PROPERTY_LATIN_TOP      |
+                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_LAO_BOTTOM,         0                                 }
+    { AF_BLUE_STRING_LAO_ASCENDER,       AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP        }
+    { AF_BLUE_STRING_LAO_DESCENDER,      0                                 }
+    { AF_BLUE_STRING_MAX,                0                                 }
 
   AF_BLUE_STRINGSET_LATN
     { AF_BLUE_STRING_LATIN_CAPITAL_TOP,     AF_BLUE_PROPERTY_LATIN_TOP        }
@@ -504,6 +656,11 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
     { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0                                 }
     { AF_BLUE_STRING_MAX,                        0                                 }
 
+  AF_BLUE_STRINGSET_MLYM
+    { AF_BLUE_STRING_MALAYALAM_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,              0                          }
+
   AF_BLUE_STRINGSET_MYMR
     { AF_BLUE_STRING_MYANMAR_TOP,       AF_BLUE_PROPERTY_LATIN_TOP      |
                                         AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
@@ -512,6 +669,20 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
     { AF_BLUE_STRING_MYANMAR_DESCENDER, 0                                 }
     { AF_BLUE_STRING_MAX,               0                                 }
 
+  AF_BLUE_STRINGSET_NONE
+    { AF_BLUE_STRING_MAX, 0 }
+
+  AF_BLUE_STRINGSET_SINH
+    { AF_BLUE_STRING_SINHALA_TOP,       AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_SINHALA_BOTTOM,    0                          }
+    { AF_BLUE_STRING_SINHALA_DESCENDER, 0                          }
+    { AF_BLUE_STRING_MAX,               0                          }
+
+  AF_BLUE_STRINGSET_TAML
+    { AF_BLUE_STRING_TAMIL_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
+    { AF_BLUE_STRING_TAMIL_BOTTOM, 0                          }
+    { AF_BLUE_STRING_MAX,          0                          }
+
   AF_BLUE_STRINGSET_TELU
     { AF_BLUE_STRING_TELUGU_TOP,    AF_BLUE_PROPERTY_LATIN_TOP }
     { AF_BLUE_STRING_TELUGU_BOTTOM, 0                          }
index 75cd6c3..41f838e 100644 (file)
@@ -80,68 +80,107 @@ FT_BEGIN_HEADER
     AF_BLUE_STRING_ARABIC_TOP = 0,
     AF_BLUE_STRING_ARABIC_BOTTOM = 18,
     AF_BLUE_STRING_ARABIC_JOIN = 33,
-    AF_BLUE_STRING_BENGALI_BASE = 36,
-    AF_BLUE_STRING_BENGALI_TOP = 68,
-    AF_BLUE_STRING_BENGALI_HEAD = 96,
-    AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 128,
-    AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 152,
-    AF_BLUE_STRING_CYRILLIC_SMALL = 176,
-    AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 200,
-    AF_BLUE_STRING_DEVANAGARI_BASE = 209,
-    AF_BLUE_STRING_DEVANAGARI_TOP = 241,
-    AF_BLUE_STRING_DEVANAGARI_HEAD = 273,
-    AF_BLUE_STRING_DEVANAGARI_BOTTOM = 305,
-    AF_BLUE_STRING_GREEK_CAPITAL_TOP = 313,
-    AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 334,
-    AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 352,
-    AF_BLUE_STRING_GREEK_SMALL = 370,
-    AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 394,
-    AF_BLUE_STRING_HEBREW_TOP = 418,
-    AF_BLUE_STRING_HEBREW_BOTTOM = 442,
-    AF_BLUE_STRING_HEBREW_DESCENDER = 460,
-    AF_BLUE_STRING_KANNADA_TOP = 475,
-    AF_BLUE_STRING_KANNADA_BOTTOM = 519,
-    AF_BLUE_STRING_KHMER_TOP = 551,
-    AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 575,
-    AF_BLUE_STRING_KHMER_BOTTOM = 615,
-    AF_BLUE_STRING_KHMER_DESCENDER = 647,
-    AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 681,
-    AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 768,
-    AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 776,
-    AF_BLUE_STRING_LAO_TOP = 784,
-    AF_BLUE_STRING_LAO_BOTTOM = 816,
-    AF_BLUE_STRING_LAO_ASCENDER = 848,
-    AF_BLUE_STRING_LAO_LARGE_ASCENDER = 864,
-    AF_BLUE_STRING_LAO_DESCENDER = 876,
-    AF_BLUE_STRING_LATIN_CAPITAL_TOP = 900,
-    AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 916,
-    AF_BLUE_STRING_LATIN_SMALL_F_TOP = 932,
-    AF_BLUE_STRING_LATIN_SMALL = 946,
-    AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 960,
-    AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 970,
-    AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 990,
-    AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 1010,
-    AF_BLUE_STRING_LATIN_SUBS_SMALL = 1030,
-    AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 1066,
-    AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 1086,
-    AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 1117,
-    AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 1146,
-    AF_BLUE_STRING_LATIN_SUPS_SMALL = 1172,
-    AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 1197,
-    AF_BLUE_STRING_MYANMAR_TOP = 1208,
-    AF_BLUE_STRING_MYANMAR_BOTTOM = 1240,
-    AF_BLUE_STRING_MYANMAR_ASCENDER = 1272,
-    AF_BLUE_STRING_MYANMAR_DESCENDER = 1300,
-    AF_BLUE_STRING_TELUGU_TOP = 1332,
-    AF_BLUE_STRING_TELUGU_BOTTOM = 1360,
-    AF_BLUE_STRING_THAI_TOP = 1388,
-    AF_BLUE_STRING_THAI_BOTTOM = 1412,
-    AF_BLUE_STRING_THAI_ASCENDER = 1440,
-    AF_BLUE_STRING_THAI_LARGE_ASCENDER = 1452,
-    AF_BLUE_STRING_THAI_DESCENDER = 1464,
-    AF_BLUE_STRING_THAI_LARGE_DESCENDER = 1480,
-    AF_BLUE_STRING_THAI_DIGIT_TOP = 1488,
-    af_blue_1_1 = 1499,
+    AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP = 36,
+    AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM = 60,
+    AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER = 84,
+    AF_BLUE_STRING_ARMENIAN_SMALL_TOP = 108,
+    AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM = 132,
+    AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER = 156,
+    AF_BLUE_STRING_BENGALI_BASE = 180,
+    AF_BLUE_STRING_BENGALI_TOP = 212,
+    AF_BLUE_STRING_BENGALI_HEAD = 240,
+    AF_BLUE_STRING_CHEROKEE_CAPITAL = 272,
+    AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER = 304,
+    AF_BLUE_STRING_CHEROKEE_SMALL = 336,
+    AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER = 368,
+    AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 384,
+    AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 408,
+    AF_BLUE_STRING_CYRILLIC_SMALL = 432,
+    AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 456,
+    AF_BLUE_STRING_DEVANAGARI_BASE = 465,
+    AF_BLUE_STRING_DEVANAGARI_TOP = 497,
+    AF_BLUE_STRING_DEVANAGARI_HEAD = 529,
+    AF_BLUE_STRING_DEVANAGARI_BOTTOM = 561,
+    AF_BLUE_STRING_ETHIOPIC_TOP = 569,
+    AF_BLUE_STRING_ETHIOPIC_BOTTOM = 601,
+    AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP = 633,
+    AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM = 665,
+    AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER = 697,
+    AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER = 729,
+    AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP = 761,
+    AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM = 793,
+    AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP = 825,
+    AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM = 857,
+    AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER = 889,
+    AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER = 921,
+    AF_BLUE_STRING_GREEK_CAPITAL_TOP = 953,
+    AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 974,
+    AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 992,
+    AF_BLUE_STRING_GREEK_SMALL = 1010,
+    AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 1034,
+    AF_BLUE_STRING_GUJARATI_TOP = 1058,
+    AF_BLUE_STRING_GUJARATI_BOTTOM = 1090,
+    AF_BLUE_STRING_GUJARATI_ASCENDER = 1122,
+    AF_BLUE_STRING_GUJARATI_DESCENDER = 1172,
+    AF_BLUE_STRING_GUJARATI_DIGIT_TOP = 1205,
+    AF_BLUE_STRING_GURMUKHI_BASE = 1225,
+    AF_BLUE_STRING_GURMUKHI_HEAD = 1257,
+    AF_BLUE_STRING_GURMUKHI_TOP = 1289,
+    AF_BLUE_STRING_GURMUKHI_BOTTOM = 1321,
+    AF_BLUE_STRING_GURMUKHI_DIGIT_TOP = 1353,
+    AF_BLUE_STRING_HEBREW_TOP = 1373,
+    AF_BLUE_STRING_HEBREW_BOTTOM = 1397,
+    AF_BLUE_STRING_HEBREW_DESCENDER = 1415,
+    AF_BLUE_STRING_KANNADA_TOP = 1430,
+    AF_BLUE_STRING_KANNADA_BOTTOM = 1474,
+    AF_BLUE_STRING_KHMER_TOP = 1506,
+    AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 1530,
+    AF_BLUE_STRING_KHMER_BOTTOM = 1570,
+    AF_BLUE_STRING_KHMER_DESCENDER = 1602,
+    AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 1636,
+    AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 1723,
+    AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 1731,
+    AF_BLUE_STRING_LAO_TOP = 1739,
+    AF_BLUE_STRING_LAO_BOTTOM = 1771,
+    AF_BLUE_STRING_LAO_ASCENDER = 1803,
+    AF_BLUE_STRING_LAO_LARGE_ASCENDER = 1819,
+    AF_BLUE_STRING_LAO_DESCENDER = 1831,
+    AF_BLUE_STRING_LATIN_CAPITAL_TOP = 1855,
+    AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 1871,
+    AF_BLUE_STRING_LATIN_SMALL_F_TOP = 1887,
+    AF_BLUE_STRING_LATIN_SMALL = 1901,
+    AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 1915,
+    AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 1925,
+    AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 1945,
+    AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 1965,
+    AF_BLUE_STRING_LATIN_SUBS_SMALL = 1985,
+    AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 2021,
+    AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 2041,
+    AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 2072,
+    AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 2101,
+    AF_BLUE_STRING_LATIN_SUPS_SMALL = 2127,
+    AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 2152,
+    AF_BLUE_STRING_MALAYALAM_TOP = 2163,
+    AF_BLUE_STRING_MALAYALAM_BOTTOM = 2207,
+    AF_BLUE_STRING_MYANMAR_TOP = 2239,
+    AF_BLUE_STRING_MYANMAR_BOTTOM = 2271,
+    AF_BLUE_STRING_MYANMAR_ASCENDER = 2303,
+    AF_BLUE_STRING_MYANMAR_DESCENDER = 2331,
+    AF_BLUE_STRING_SINHALA_TOP = 2363,
+    AF_BLUE_STRING_SINHALA_BOTTOM = 2395,
+    AF_BLUE_STRING_SINHALA_DESCENDER = 2427,
+    AF_BLUE_STRING_TAMIL_TOP = 2471,
+    AF_BLUE_STRING_TAMIL_BOTTOM = 2503,
+    AF_BLUE_STRING_TELUGU_TOP = 2535,
+    AF_BLUE_STRING_TELUGU_BOTTOM = 2563,
+    AF_BLUE_STRING_THAI_TOP = 2591,
+    AF_BLUE_STRING_THAI_BOTTOM = 2615,
+    AF_BLUE_STRING_THAI_ASCENDER = 2643,
+    AF_BLUE_STRING_THAI_LARGE_ASCENDER = 2655,
+    AF_BLUE_STRING_THAI_DESCENDER = 2667,
+    AF_BLUE_STRING_THAI_LARGE_DESCENDER = 2683,
+    AF_BLUE_STRING_THAI_DIGIT_TOP = 2691,
+    af_blue_1_1 = 2702,
 #ifdef AF_CONFIG_OPTION_CJK
     AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1,
     AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203,
@@ -201,22 +240,33 @@ FT_BEGIN_HEADER
   typedef enum  AF_Blue_Stringset_
   {
     AF_BLUE_STRINGSET_ARAB = 0,
-    AF_BLUE_STRINGSET_BENG = 4,
-    AF_BLUE_STRINGSET_CYRL = 9,
-    AF_BLUE_STRINGSET_DEVA = 15,
-    AF_BLUE_STRINGSET_GREK = 21,
-    AF_BLUE_STRINGSET_HEBR = 28,
-    AF_BLUE_STRINGSET_KNDA = 32,
-    AF_BLUE_STRINGSET_KHMR = 35,
-    AF_BLUE_STRINGSET_KHMS = 41,
-    AF_BLUE_STRINGSET_LAO = 44,
-    AF_BLUE_STRINGSET_LATN = 50,
-    AF_BLUE_STRINGSET_LATB = 57,
-    AF_BLUE_STRINGSET_LATP = 64,
-    AF_BLUE_STRINGSET_MYMR = 71,
-    AF_BLUE_STRINGSET_TELU = 76,
-    AF_BLUE_STRINGSET_THAI = 79,
-    af_blue_2_1 = 87,
+    AF_BLUE_STRINGSET_ARMN = 4,
+    AF_BLUE_STRINGSET_BENG = 11,
+    AF_BLUE_STRINGSET_CHER = 16,
+    AF_BLUE_STRINGSET_CYRL = 23,
+    AF_BLUE_STRINGSET_DEVA = 29,
+    AF_BLUE_STRINGSET_ETHI = 35,
+    AF_BLUE_STRINGSET_GEOR = 38,
+    AF_BLUE_STRINGSET_GEOK = 43,
+    AF_BLUE_STRINGSET_GREK = 50,
+    AF_BLUE_STRINGSET_GUJR = 57,
+    AF_BLUE_STRINGSET_GURU = 63,
+    AF_BLUE_STRINGSET_HEBR = 69,
+    AF_BLUE_STRINGSET_KNDA = 73,
+    AF_BLUE_STRINGSET_KHMR = 76,
+    AF_BLUE_STRINGSET_KHMS = 82,
+    AF_BLUE_STRINGSET_LAO = 85,
+    AF_BLUE_STRINGSET_LATN = 91,
+    AF_BLUE_STRINGSET_LATB = 98,
+    AF_BLUE_STRINGSET_LATP = 105,
+    AF_BLUE_STRINGSET_MLYM = 112,
+    AF_BLUE_STRINGSET_MYMR = 115,
+    AF_BLUE_STRINGSET_NONE = 120,
+    AF_BLUE_STRINGSET_SINH = 121,
+    AF_BLUE_STRINGSET_TAML = 125,
+    AF_BLUE_STRINGSET_TELU = 128,
+    AF_BLUE_STRINGSET_THAI = 131,
+    af_blue_2_1 = 139,
 #ifdef AF_CONFIG_OPTION_CJK
     AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0,
     af_blue_2_1_1 = af_blue_2_1 + 2,
index e813777..f21ae3a 100644 (file)
 
       if ( seg2 )
       {
-        seg2->num_linked++;
         if ( seg2->link != seg1 )
         {
           seg1->link = NULL;
 
           if ( seg2->score < dist_threshold || seg1->score < seg2->score * 4 )
             seg1->serif = seg2->link;
-          else
-            seg2->num_linked--;
         }
       }
     }
       }
 
       if ( dist < 54 )
-        dist += ( 54 - dist ) / 2 ;
+        dist += ( 54 - dist ) / 2;
       else if ( dist < 3 * 64 )
       {
         FT_Pos  delta;
index 9ed058f..6c3d032 100644 (file)
     AF_DUMP(( "Table of points:\n" ));
 
     if ( hints->num_points )
-      AF_DUMP(( "  index  hedge  hseg  vedge  vseg  flags"
+      AF_DUMP(( "  index  hedge  hseg  vedge  vseg  flags "
                 "  xorg  yorg  xscale  yscale   xfit    yfit" ));
     else
       AF_DUMP(( "  (none)\n" ));
         contour++;
       }
 
-      AF_DUMP(( "  %5d  %5s %5s  %5s %5s  %s "
+      AF_DUMP(( "  %5d  %5s %5s  %5s %5s  %s"
                 " %5d %5d %7.2f %7.2f %7.2f %7.2f\n",
                 point_idx,
                 af_print_idx( buf1,
                 af_print_idx( buf3,
                               af_get_edge_index( hints, segment_idx_0, 0 ) ),
                 af_print_idx( buf4, segment_idx_0 ),
-                ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? "weak"
-                                                              : " -- ",
+                ( point->flags & AF_FLAG_NEAR )
+                  ? " near "
+                  : ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
+                    ? " weak "
+                    : "strong",
 
                 point->fx,
                 point->fy,
       AF_Point  point;
       AF_Point  point_limit = points + hints->num_points;
 
+      /* value 20 in `near_limit' is heuristic */
+      FT_UInt  units_per_em = hints->metrics->scaler.face->units_per_EM;
+      FT_Int   near_limit   = 20 * units_per_em / 2048;
+
 
       /* compute coordinates & Bezier flags, next and prev */
       {
         FT_Vector*  vec           = outline->points;
         char*       tag           = outline->tags;
-        AF_Point    end           = points + outline->contours[0];
+        FT_Short    endpoint      = outline->contours[0];
+        AF_Point    end           = points + endpoint;
         AF_Point    prev          = end;
         FT_Int      contour_index = 0;
 
 
         for ( point = points; point < point_limit; point++, vec++, tag++ )
         {
+          FT_Pos  out_x, out_y;
+
+
           point->in_dir  = (FT_Char)AF_DIR_NONE;
           point->out_dir = (FT_Char)AF_DIR_NONE;
 
           point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
           point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
 
+          end->fx = (FT_Short)outline->points[endpoint].x;
+          end->fy = (FT_Short)outline->points[endpoint].y;
+
           switch ( FT_CURVE_TAG( *tag ) )
           {
           case FT_CURVE_TAG_CONIC:
             point->flags = AF_FLAG_NONE;
           }
 
+          out_x = point->fx - prev->fx;
+          out_y = point->fy - prev->fy;
+
+          if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit )
+            prev->flags |= AF_FLAG_NEAR;
+
           point->prev = prev;
           prev->next  = point;
           prev        = point;
           {
             if ( ++contour_index < outline->n_contours )
             {
-              end  = points + outline->contours[contour_index];
-              prev = end;
+              endpoint = outline->contours[contour_index];
+              end      = points + endpoint;
+              prev     = end;
             }
           }
         }
          *  Compute directions of `in' and `out' vectors.
          *
          *  Note that distances between points that are very near to each
-         *  other are accumulated.  In other words, the auto-hinter
+         *  other are accumulated.  In other words, the auto-hinter either
          *  prepends the small vectors between near points to the first
-         *  non-near vector.  All intermediate points are tagged as
-         *  weak; the directions are adjusted also to be equal to the
-         *  accumulated one.
+         *  non-near vector, or the sum of small vector lengths exceeds a
+         *  threshold, thus `grouping' the small vectors.  All intermediate
+         *  points are tagged as weak; the directions are adjusted also to
+         *  be equal to the accumulated one.
          */
 
-        /* value 20 in `near_limit' is heuristic */
-        FT_UInt  units_per_em = hints->metrics->scaler.face->units_per_EM;
-        FT_Int   near_limit   = 20 * units_per_em / 2048;
-        FT_Int   near_limit2  = 2 * near_limit - 1;
+        FT_Int  near_limit2 = 2 * near_limit - 1;
 
         AF_Point*  contour;
         AF_Point*  contour_limit = hints->contours + hints->num_contours;
           /* now loop over all points of the contour to get */
           /* `in' and `out' vector directions               */
 
-          curr  = first;
+          curr = first;
 
           /*
            *  We abuse the `u' and `v' fields to store index deltas to the
 
 
             point = next;
-            next = point->next;
+            next  = point->next;
 
             out_x += next->fx - point->fx;
             out_y += next->fy - point->fy;
index 4563565..5142e6e 100644 (file)
@@ -221,6 +221,9 @@ FT_BEGIN_HEADER
   /* candidates for weak interpolation have this flag set */
 #define AF_FLAG_WEAK_INTERPOLATION  ( 1U << 4 )
 
+  /* the distance to the next point is very small */
+#define AF_FLAG_NEAR  ( 1U << 5 )
+
 
   /* edge hint flags */
 #define AF_EDGE_NORMAL  0
@@ -266,7 +269,6 @@ FT_BEGIN_HEADER
 
     AF_Segment  link;        /* (stem) link segment        */
     AF_Segment  serif;       /* primary segment for serifs */
-    FT_Pos      num_linked;  /* number of linked segments  */
     FT_Pos      score;       /* used during stem matching  */
     FT_Pos      len;         /* used during stem matching  */
 
@@ -289,7 +291,6 @@ FT_BEGIN_HEADER
     AF_Width    blue_edge;  /* non-NULL if this is a blue edge */
     AF_Edge     link;       /* link edge                       */
     AF_Edge     serif;      /* primary edge for serifs         */
-    FT_Short    num_linked; /* number of linked edges          */
     FT_Int      score;      /* used during stem matching       */
 
     AF_Segment  first;      /* first segment in edge */
index 40646e3..18559fc 100644 (file)
     /* do each contour separately */
     for ( ; contour < contour_limit; contour++ )
     {
-      AF_Point  point      =  contour[0];
-      AF_Point  last       =  point->prev;
-      int       on_edge    =  0;
-      FT_Pos    min_pos    =  32000;  /* minimum segment pos != min_coord */
-      FT_Pos    max_pos    = -32000;  /* maximum segment pos != max_coord */
-      FT_Pos    min_on_pos =  32000;
-      FT_Pos    max_on_pos = -32000;
-      FT_Bool   passed;
+      AF_Point  point   = contour[0];
+      AF_Point  last    = point->prev;
+      int       on_edge = 0;
+
+      /* we call values measured along a segment (point->v)    */
+      /* `coordinates', and values orthogonal to it (point->u) */
+      /* `positions'                                           */
+      FT_Pos     min_pos      =  32000;
+      FT_Pos     max_pos      = -32000;
+      FT_Pos     min_coord    =  32000;
+      FT_Pos     max_coord    = -32000;
+      FT_UShort  min_flags    =  AF_FLAG_NONE;
+      FT_UShort  max_flags    =  AF_FLAG_NONE;
+      FT_Pos     min_on_coord =  32000;
+      FT_Pos     max_on_coord = -32000;
+
+      FT_Bool  passed;
+
+      AF_Segment  prev_segment = NULL;
+
+      FT_Pos     prev_min_pos      = min_pos;
+      FT_Pos     prev_max_pos      = max_pos;
+      FT_Pos     prev_min_coord    = min_coord;
+      FT_Pos     prev_max_coord    = max_coord;
+      FT_UShort  prev_min_flags    = min_flags;
+      FT_UShort  prev_max_flags    = max_flags;
+      FT_Pos     prev_min_on_coord = min_on_coord;
+      FT_Pos     prev_max_on_coord = max_on_coord;
 
 
-      if ( point == last )  /* skip singletons -- just in case */
-        continue;
-
       if ( FT_ABS( last->out_dir )  == major_dir &&
            FT_ABS( point->out_dir ) == major_dir )
       {
 
         if ( on_edge )
         {
+          /* get minimum and maximum position */
           u = point->u;
           if ( u < min_pos )
             min_pos = u;
           if ( u > max_pos )
             max_pos = u;
 
-          /* get minimum and maximum coordinate of on points */
+          /* get minimum and maximum coordinate together with flags */
+          v = point->v;
+          if ( v < min_coord )
+          {
+            min_coord = v;
+            min_flags = point->flags;
+          }
+          if ( v > max_coord )
+          {
+            max_coord = v;
+            max_flags = point->flags;
+          }
+
+          /* get minimum and maximum coordinate of `on' points */
           if ( !( point->flags & AF_FLAG_CONTROL ) )
           {
             v = point->v;
-            if ( v < min_on_pos )
-              min_on_pos = v;
-            if ( v > max_on_pos )
-              max_on_pos = v;
+            if ( v < min_on_coord )
+              min_on_coord = v;
+            if ( v > max_on_coord )
+              max_on_coord = v;
           }
 
           if ( point->out_dir != segment_dir || point == last )
           {
-            /* we are just leaving an edge; record a new segment! */
-            segment->last = point;
-            segment->pos  = (FT_Short)( ( min_pos + max_pos ) >> 1 );
-
-            /* a segment is round if either its first or last point */
-            /* is a control point, and the length of the on points  */
-            /* inbetween doesn't exceed a heuristic limit           */
-            if ( ( segment->first->flags | point->flags ) & AF_FLAG_CONTROL &&
-                 ( max_on_pos - min_on_pos ) < flat_threshold               )
-              segment->flags |= AF_EDGE_ROUND;
+            /* check whether the new segment's start point is identical to */
+            /* the previous segment's end point; for example, this might   */
+            /* happen for spikes                                           */
 
-            /* compute segment size */
-            min_pos = max_pos = point->v;
+            if ( !prev_segment || segment->first != prev_segment->last )
+            {
+              /* points are different: we are just leaving an edge, thus */
+              /* record a new segment                                    */
+
+              segment->last = point;
+              segment->pos  = (FT_Short)( ( min_pos + max_pos ) >> 1 );
+
+              /* a segment is round if either its first or last point */
+              /* is a control point, and the length of the on points  */
+              /* inbetween doesn't exceed a heuristic limit           */
+              if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL      &&
+                   ( max_on_coord - min_on_coord ) < flat_threshold )
+                segment->flags |= AF_EDGE_ROUND;
+
+              segment->min_coord = (FT_Short)min_coord;
+              segment->max_coord = (FT_Short)max_coord;
+              segment->height    = segment->max_coord - segment->min_coord;
+
+              prev_segment      = segment;
+              prev_min_pos      = min_pos;
+              prev_max_pos      = max_pos;
+              prev_min_coord    = min_coord;
+              prev_max_coord    = max_coord;
+              prev_min_flags    = min_flags;
+              prev_max_flags    = max_flags;
+              prev_min_on_coord = min_on_coord;
+              prev_max_on_coord = max_on_coord;
+            }
+            else
+            {
+              /* points are the same: we don't create a new segment but */
+              /* merge the current segment with the previous one        */
 
-            v = segment->first->v;
-            if ( v < min_pos )
-              min_pos = v;
-            if ( v > max_pos )
-              max_pos = v;
+              if ( prev_segment->last->in_dir == point->in_dir )
+              {
+                /* we have identical directions (this can happen for       */
+                /* degenerate outlines that move zig-zag along the main    */
+                /* axis without changing the coordinate value of the other */
+                /* axis, and where the segments have just been merged):    */
+                /* unify segments                                          */
 
-            segment->min_coord = (FT_Short)min_pos;
-            segment->max_coord = (FT_Short)max_pos;
-            segment->height    = (FT_Short)( segment->max_coord -
-                                             segment->min_coord );
+                /* update constraints */
+
+                if ( prev_min_pos < min_pos )
+                  min_pos = prev_min_pos;
+                if ( prev_max_pos > max_pos )
+                  max_pos = prev_max_pos;
+
+                if ( prev_min_coord < min_coord )
+                {
+                  min_coord = prev_min_coord;
+                  min_flags = prev_min_flags;
+                }
+                if ( prev_max_coord > max_coord )
+                {
+                  max_coord = prev_max_coord;
+                  max_flags = prev_max_flags;
+                }
+
+                if ( prev_min_on_coord < min_on_coord )
+                  min_on_coord = prev_min_on_coord;
+                if ( prev_max_on_coord > max_on_coord )
+                  max_on_coord = prev_max_on_coord;
+
+                prev_segment->last = point;
+                prev_segment->pos  = (FT_Short)( ( min_pos +
+                                                   max_pos ) >> 1 );
+
+                if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL      &&
+                     ( max_on_coord - min_on_coord ) < flat_threshold )
+                  prev_segment->flags |= AF_EDGE_ROUND;
+                else
+                  prev_segment->flags &= ~AF_EDGE_ROUND;
+
+                prev_segment->min_coord = (FT_Short)min_coord;
+                prev_segment->max_coord = (FT_Short)max_coord;
+                prev_segment->height    = prev_segment->max_coord -
+                                          prev_segment->min_coord;
+              }
+              else
+              {
+                /* we have different directions; use the properties of the */
+                /* longer segment and discard the other one                */
+
+                if ( FT_ABS( prev_max_coord - prev_min_coord ) >
+                     FT_ABS( max_coord - min_coord ) )
+                {
+                  /* discard current segment */
+
+                  if ( min_pos < prev_min_pos )
+                    prev_min_pos = min_pos;
+                  if ( max_pos > prev_max_pos )
+                    prev_max_pos = max_pos;
+
+                  prev_segment->last = point;
+                  prev_segment->pos  = (FT_Short)( ( prev_min_pos +
+                                                     prev_max_pos ) >> 1 );
+                }
+                else
+                {
+                  /* discard previous segment */
+
+                  if ( prev_min_pos < min_pos )
+                    min_pos = prev_min_pos;
+                  if ( prev_max_pos > max_pos )
+                    max_pos = prev_max_pos;
+
+                  segment->last = point;
+                  segment->pos  = (FT_Short)( ( min_pos + max_pos ) >> 1 );
+
+                  if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL      &&
+                       ( max_on_coord - min_on_coord ) < flat_threshold )
+                    segment->flags |= AF_EDGE_ROUND;
+
+                  segment->min_coord = (FT_Short)min_coord;
+                  segment->max_coord = (FT_Short)max_coord;
+                  segment->height    = segment->max_coord -
+                                       segment->min_coord;
+
+                  *prev_segment = *segment;
+
+                  prev_min_pos      = min_pos;
+                  prev_max_pos      = max_pos;
+                  prev_min_coord    = min_coord;
+                  prev_max_coord    = max_coord;
+                  prev_min_flags    = min_flags;
+                  prev_max_flags    = max_flags;
+                  prev_min_on_coord = min_on_coord;
+                  prev_max_on_coord = max_on_coord;
+                }
+              }
+
+              axis->num_segments--;
+            }
 
             on_edge = 0;
             segment = NULL;
+
             /* fall through */
           }
         }
           passed = 1;
         }
 
-        if ( !on_edge && FT_ABS( point->out_dir ) == major_dir )
+        /* if we are not on an edge, check whether the major direction */
+        /* coincides with the current point's `out' direction, or      */
+        /* whether we have a single-point contour                      */
+        if ( !on_edge                                  &&
+             ( FT_ABS( point->out_dir ) == major_dir ||
+               point == point->prev                  ) )
         {
           /* this is the start of a new segment! */
           segment_dir = (AF_Direction)point->out_dir;
           segment->first = point;
           segment->last  = point;
 
-          min_pos = max_pos = point->u;
+          /* `af_axis_hints_new_segment' reallocates memory,    */
+          /* thus we have to refresh the `prev_segment' pointer */
+          if ( prev_segment )
+            prev_segment = segment - 1;
+
+          min_pos   = max_pos   = point->u;
+          min_coord = max_coord = point->v;
+          min_flags = max_flags = point->flags;
 
           if ( point->flags & AF_FLAG_CONTROL )
           {
-            min_on_pos =  32000;
-            max_on_pos = -32000;
+            min_on_coord =  32000;
+            max_on_coord = -32000;
           }
           else
-            min_on_pos = max_on_pos = point->v;
+            min_on_coord = max_on_coord = point->v;
 
           on_edge = 1;
+
+          if ( point == point->prev )
+          {
+            /* we have a one-point segment: this is a one-point */
+            /* contour with `in' and `out' direction set to     */
+            /* AF_DIR_NONE                                      */
+            segment->pos = (FT_Short)min_pos;
+
+            if (point->flags & AF_FLAG_CONTROL)
+              segment->flags |= AF_EDGE_ROUND;
+
+            segment->min_coord = (FT_Short)point->v;
+            segment->max_coord = (FT_Short)point->v;
+            segment->height = 0;
+
+            on_edge = 0;
+            segment = NULL;
+          }
         }
 
         point = point->next;
       FT_Int   ee;
 
 
-      if ( seg->height < segment_length_threshold )
+      /* ignore too short segments and, in this loop, */
+      /* one-point segments without a direction       */
+      if ( seg->height < segment_length_threshold ||
+           seg->dir == AF_DIR_NONE                )
         continue;
 
       /* A special case for serif edges: If they are smaller than */
       }
     }
 
+    /* we loop again over all segments to catch one-point segments   */
+    /* without a direction: if possible, link them to existing edges */
+    for ( seg = segments; seg < segment_limit; seg++ )
+    {
+      AF_Edge  found = NULL;
+      FT_Int   ee;
+
+
+      if ( seg->dir != AF_DIR_NONE )
+        continue;
+
+      /* look for an edge corresponding to the segment */
+      for ( ee = 0; ee < axis->num_edges; ee++ )
+      {
+        AF_Edge  edge = axis->edges + ee;
+        FT_Pos   dist;
+
+
+        dist = seg->pos - edge->fpos;
+        if ( dist < 0 )
+          dist = -dist;
+
+        if ( dist < edge_distance_threshold )
+        {
+          found = edge;
+          break;
+        }
+      }
+
+      /* one-point segments without a match are ignored */
+      if ( found )
+      {
+        seg->edge_next         = found->first;
+        found->last->edge_next = seg;
+        found->last            = seg;
+      }
+    }
+
 
     /******************************************************************/
     /*                                                                */
   af_latin_compute_stem_width( AF_GlyphHints  hints,
                                AF_Dimension   dim,
                                FT_Pos         width,
+                               FT_Pos         base_delta,
                                FT_UInt        base_flags,
                                FT_UInt        stem_flags )
   {
             dist += delta;
         }
         else
-          dist = ( dist + 32 ) & ~63;
+        {
+          /* A stem's end position depends on two values: the start        */
+          /* position and the stem length.  The former gets usually        */
+          /* rounded to the grid, while the latter gets rounded also if it */
+          /* exceeds a certain length (see below in this function).  This  */
+          /* `double rounding' can lead to a great difference to the       */
+          /* original, unhinted position; this normally doesn't matter for */
+          /* large PPEM values, but for small sizes it can easily make     */
+          /* outlines collide.  For this reason, we adjust the stem length */
+          /* by a small amount depending on the PPEM value in case the     */
+          /* former and latter rounding both point into the same           */
+          /* direction.                                                    */
+
+          FT_Pos  bdelta = 0;
+
+
+          if ( ( ( width > 0 ) && ( base_delta > 0 ) ) ||
+               ( ( width < 0 ) && ( base_delta < 0 ) ) )
+          {
+            FT_UInt  ppem = metrics->root.scaler.face->size->metrics.x_ppem;
+
+
+            if ( ppem < 10 )
+              bdelta = base_delta;
+            else if ( ppem < 30 )
+              bdelta = ( base_delta * (FT_Pos)( 30 - ppem ) ) / 20;
+
+            if ( bdelta < 0 )
+              bdelta = -bdelta;
+          }
+
+          dist = ( dist - bdelta + 32 ) & ~63;
+        }
       }
     }
     else
                               AF_Edge        base_edge,
                               AF_Edge        stem_edge )
   {
-    FT_Pos  dist = stem_edge->opos - base_edge->opos;
+    FT_Pos  dist, base_delta;
+    FT_Pos  fitted_width;
+
+
+    dist       = stem_edge->opos - base_edge->opos;
+    base_delta = base_edge->pos - base_edge->opos;
 
-    FT_Pos  fitted_width = af_latin_compute_stem_width( hints, dim, dist,
-                                                        base_edge->flags,
-                                                        stem_edge->flags );
+    fitted_width = af_latin_compute_stem_width( hints, dim,
+                                                dist, base_delta,
+                                                base_edge->flags,
+                                                stem_edge->flags );
 
 
     stem_edge->pos = base_edge->pos + fitted_width;
 
 
         org_len = edge2->opos - edge->opos;
-        cur_len = af_latin_compute_stem_width( hints, dim, org_len,
+        cur_len = af_latin_compute_stem_width( hints, dim,
+                                               org_len, 0,
                                                edge->flags,
                                                edge2->flags );
 
         org_len    = edge2->opos - edge->opos;
         org_center = org_pos + ( org_len >> 1 );
 
-        cur_len = af_latin_compute_stem_width( hints, dim, org_len,
+        cur_len = af_latin_compute_stem_width( hints, dim,
+                                               org_len, 0,
                                                edge->flags,
                                                edge2->flags );
 
           org_len    = edge2->opos - edge->opos;
           org_center = org_pos + ( org_len >> 1 );
 
-          cur_len    = af_latin_compute_stem_width( hints, dim, org_len,
+          cur_len    = af_latin_compute_stem_width( hints, dim,
+                                                    org_len, 0,
                                                     edge->flags,
                                                     edge2->flags );
 
              ( top_to_bottom_hinting ? ( edge->pos > edge[-1].pos )
                                      : ( edge->pos < edge[-1].pos ) ) )
         {
+          /* don't move if stem would (almost) disappear otherwise; */
+          /* the ad-hoc value 16 corresponds to 1/4px               */
+          if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
+          {
 #ifdef FT_DEBUG_LEVEL_TRACE
-          FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
-                      edge - edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+            FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
+                        edge - edges,
+                        edge->pos / 64.0,
+                        edge[-1].pos / 64.0 ));
 
-          num_actions++;
+            num_actions++;
 #endif
 
-          edge->pos = edge[-1].pos;
+            edge->pos = edge[-1].pos;
+          }
         }
       }
     }
              ( top_to_bottom_hinting ? ( edge->pos > edge[-1].pos )
                                      : ( edge->pos < edge[-1].pos ) ) )
         {
+          /* don't move if stem would (almost) disappear otherwise; */
+          /* the ad-hoc value 16 corresponds to 1/4px               */
+          if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
+          {
 #ifdef FT_DEBUG_LEVEL_TRACE
-          FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
-                      edge - edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+            FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
+                        edge - edges,
+                        edge->pos / 64.0,
+                        edge[-1].pos / 64.0 ));
 
-          num_actions++;
+            num_actions++;
 #endif
-          edge->pos = edge[-1].pos;
+            edge->pos = edge[-1].pos;
+          }
         }
 
         if ( edge + 1 < edge_limit                                   &&
              ( top_to_bottom_hinting ? ( edge->pos < edge[1].pos )
                                      : ( edge->pos > edge[1].pos ) ) )
         {
+          /* don't move if stem would (almost) disappear otherwise; */
+          /* the ad-hoc value 16 corresponds to 1/4px               */
+          if ( edge->link && FT_ABS( edge->link->pos - edge[-1].pos ) > 16 )
+          {
 #ifdef FT_DEBUG_LEVEL_TRACE
-          FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
-                      edge - edges, edge->pos / 64.0, edge[1].pos / 64.0 ));
+            FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
+                        edge - edges,
+                        edge->pos / 64.0,
+                        edge[1].pos / 64.0 ));
 
-          num_actions++;
+            num_actions++;
 #endif
 
-          edge->pos = edge[1].pos;
+            edge->pos = edge[1].pos;
+          }
         }
       }
     }
index 1fab85e..5db4a41 100644 (file)
@@ -1,3 +1,8 @@
+/* ATTENTION: This file doesn't compile.  It is only here as a reference */
+/*            of an alternative latin hinting algorithm that was always  */
+/*            marked as experimental.                                    */
+
+
 /***************************************************************************/
 /*                                                                         */
 /*  aflatin2.c                                                             */
index c17a6a2..f83f704 100644 (file)
@@ -1,3 +1,8 @@
+/* ATTENTION: This file doesn't compile.  It is only here as a reference */
+/*            of an alternative latin hinting algorithm that was always  */
+/*            marked as experimental.                                    */
+
+
 /***************************************************************************/
 /*                                                                         */
 /*  aflatin2.h                                                             */
index 4e81e78..732f3d1 100644 (file)
 
   const AF_Script_UniRangeRec  af_arab_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0600UL,  0x06FFUL ),  /* Arabic                                 */
-    AF_UNIRANGE_REC(  0x0750UL,  0x07FFUL ),  /* Arabic Supplement                      */
-    AF_UNIRANGE_REC(  0x08A0UL,  0x08FFUL ),  /* Arabic Extended-A                      */
-    AF_UNIRANGE_REC(  0xFB50UL,  0xFDFFUL ),  /* Arabic Presentation Forms-A            */
-    AF_UNIRANGE_REC(  0xFE70UL,  0xFEFFUL ),  /* Arabic Presentation Forms-B            */
-    AF_UNIRANGE_REC( 0x1EE00UL, 0x1EEFFUL ),  /* Arabic Mathematical Alphabetic Symbols */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0600,  0x06FF ),  /* Arabic                                 */
+    AF_UNIRANGE_REC(  0x0750,  0x07FF ),  /* Arabic Supplement                      */
+    AF_UNIRANGE_REC(  0x08A0,  0x08FF ),  /* Arabic Extended-A                      */
+    AF_UNIRANGE_REC(  0xFB50,  0xFDFF ),  /* Arabic Presentation Forms-A            */
+    AF_UNIRANGE_REC(  0xFE70,  0xFEFF ),  /* Arabic Presentation Forms-B            */
+    AF_UNIRANGE_REC( 0x1EE00, 0x1EEFF ),  /* Arabic Mathematical Alphabetic Symbols */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_arab_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0600UL,  0x0605UL ),
-    AF_UNIRANGE_REC(  0x0610UL,  0x061AUL ),
-    AF_UNIRANGE_REC(  0x064BUL,  0x065FUL ),
-    AF_UNIRANGE_REC(  0x0670UL,  0x0670UL ),
-    AF_UNIRANGE_REC(  0x06D6UL,  0x06DCUL ),
-    AF_UNIRANGE_REC(  0x06DFUL,  0x06E4UL ),
-    AF_UNIRANGE_REC(  0x06E7UL,  0x06E8UL ),
-    AF_UNIRANGE_REC(  0x06EAUL,  0x06EDUL ),
-    AF_UNIRANGE_REC(  0x08E3UL,  0x08FFUL ),
-    AF_UNIRANGE_REC(  0xFBB2UL,  0xFBC1UL ),
-    AF_UNIRANGE_REC(  0xFE70UL,  0xFE70UL ),
-    AF_UNIRANGE_REC(  0xFE72UL,  0xFE72UL ),
-    AF_UNIRANGE_REC(  0xFE74UL,  0xFE74UL ),
-    AF_UNIRANGE_REC(  0xFE76UL,  0xFE76UL ),
-    AF_UNIRANGE_REC(  0xFE78UL,  0xFE78UL ),
-    AF_UNIRANGE_REC(  0xFE7AUL,  0xFE7AUL ),
-    AF_UNIRANGE_REC(  0xFE7CUL,  0xFE7CUL ),
-    AF_UNIRANGE_REC(  0xFE7EUL,  0xFE7EUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0600,  0x0605 ),
+    AF_UNIRANGE_REC(  0x0610,  0x061A ),
+    AF_UNIRANGE_REC(  0x064B,  0x065F ),
+    AF_UNIRANGE_REC(  0x0670,  0x0670 ),
+    AF_UNIRANGE_REC(  0x06D6,  0x06DC ),
+    AF_UNIRANGE_REC(  0x06DF,  0x06E4 ),
+    AF_UNIRANGE_REC(  0x06E7,  0x06E8 ),
+    AF_UNIRANGE_REC(  0x06EA,  0x06ED ),
+    AF_UNIRANGE_REC(  0x08D4,  0x08E1 ),
+    AF_UNIRANGE_REC(  0x08E3,  0x08FF ),
+    AF_UNIRANGE_REC(  0xFBB2,  0xFBC1 ),
+    AF_UNIRANGE_REC(  0xFE70,  0xFE70 ),
+    AF_UNIRANGE_REC(  0xFE72,  0xFE72 ),
+    AF_UNIRANGE_REC(  0xFE74,  0xFE74 ),
+    AF_UNIRANGE_REC(  0xFE76,  0xFE76 ),
+    AF_UNIRANGE_REC(  0xFE78,  0xFE78 ),
+    AF_UNIRANGE_REC(  0xFE7A,  0xFE7A ),
+    AF_UNIRANGE_REC(  0xFE7C,  0xFE7C ),
+    AF_UNIRANGE_REC(  0xFE7E,  0xFE7E ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_armn_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0530,  0x058F ),  /* Armenian                          */
+    AF_UNIRANGE_REC(  0xFB13,  0xFB17 ),  /* Alphab. Present. Forms (Armenian) */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_armn_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0559,  0x055F ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_beng_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0980UL,  0x09FFUL ),  /* Bengali */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0980,  0x09FF ),  /* Bengali */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_beng_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0981UL,  0x0981UL ),
-    AF_UNIRANGE_REC(  0x09BCUL,  0x09BCUL ),
-    AF_UNIRANGE_REC(  0x09C1UL,  0x09C4UL ),
-    AF_UNIRANGE_REC(  0x09CDUL,  0x09CDUL ),
-    AF_UNIRANGE_REC(  0x09E2UL,  0x09E3UL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0981,  0x0981 ),
+    AF_UNIRANGE_REC(  0x09BC,  0x09BC ),
+    AF_UNIRANGE_REC(  0x09C1,  0x09C4 ),
+    AF_UNIRANGE_REC(  0x09CD,  0x09CD ),
+    AF_UNIRANGE_REC(  0x09E2,  0x09E3 ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_cher_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x13A0,  0x13FF ),  /* Cherokee            */
+    AF_UNIRANGE_REC(  0xAB70,  0xABBF ),  /* Cherokee Supplement */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_cher_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
   };
 
 
   const AF_Script_UniRangeRec  af_cyrl_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0400UL,  0x04FFUL ),  /* Cyrillic            */
-    AF_UNIRANGE_REC(  0x0500UL,  0x052FUL ),  /* Cyrillic Supplement */
-    AF_UNIRANGE_REC(  0x2DE0UL,  0x2DFFUL ),  /* Cyrillic Extended-A */
-    AF_UNIRANGE_REC(  0xA640UL,  0xA69FUL ),  /* Cyrillic Extended-B */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0400,  0x04FF ),  /* Cyrillic            */
+    AF_UNIRANGE_REC(  0x0500,  0x052F ),  /* Cyrillic Supplement */
+    AF_UNIRANGE_REC(  0x2DE0,  0x2DFF ),  /* Cyrillic Extended-A */
+    AF_UNIRANGE_REC(  0xA640,  0xA69F ),  /* Cyrillic Extended-B */
+    AF_UNIRANGE_REC(  0x1C80,  0x1C8F ),  /* Cyrillic Extended-C */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_cyrl_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0483UL,  0x0489UL ),
-    AF_UNIRANGE_REC(  0x2DE0UL,  0x2DFFUL ),
-    AF_UNIRANGE_REC(  0xA66FUL,  0xA67FUL ),
-    AF_UNIRANGE_REC(  0xA69EUL,  0xA69FUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0483,  0x0489 ),
+    AF_UNIRANGE_REC(  0x2DE0,  0x2DFF ),
+    AF_UNIRANGE_REC(  0xA66F,  0xA67F ),
+    AF_UNIRANGE_REC(  0xA69E,  0xA69F ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
 
   const AF_Script_UniRangeRec  af_deva_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0900UL,  0x093BUL ),  /* Devanagari          */
+    AF_UNIRANGE_REC(  0x0900,  0x093B ),  /* Devanagari          */
     /* omitting U+093C nukta */
-    AF_UNIRANGE_REC(  0x093DUL,  0x0950UL ),  /* ... continued       */
+    AF_UNIRANGE_REC(  0x093D,  0x0950 ),  /* ... continued       */
     /* omitting U+0951 udatta, U+0952 anudatta */
-    AF_UNIRANGE_REC(  0x0953UL,  0x0963UL ),  /* ... continued       */
+    AF_UNIRANGE_REC(  0x0953,  0x0963 ),  /* ... continued       */
     /* omitting U+0964 danda, U+0965 double danda */
-    AF_UNIRANGE_REC(  0x0966UL,  0x097FUL ),  /* ... continued       */
-    AF_UNIRANGE_REC(  0x20B9UL,  0x20B9UL ),  /* (new) Rupee sign    */
-    AF_UNIRANGE_REC(  0xA8E0UL,  0xA8FFUL ),  /* Devanagari Extended */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0966,  0x097F ),  /* ... continued       */
+    AF_UNIRANGE_REC(  0x20B9,  0x20B9 ),  /* (new) Rupee sign    */
+    AF_UNIRANGE_REC(  0xA8E0,  0xA8FF ),  /* Devanagari Extended */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_deva_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0900UL,  0x0902UL ),
-    AF_UNIRANGE_REC(  0x093AUL,  0x093AUL ),
-    AF_UNIRANGE_REC(  0x0941UL,  0x0948UL ),
-    AF_UNIRANGE_REC(  0x094DUL,  0x094DUL ),
-    AF_UNIRANGE_REC(  0x0953UL,  0x0957UL ),
-    AF_UNIRANGE_REC(  0x0962UL,  0x0963UL ),
-    AF_UNIRANGE_REC(  0xA8E0UL,  0xA8F1UL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0900,  0x0902 ),
+    AF_UNIRANGE_REC(  0x093A,  0x093A ),
+    AF_UNIRANGE_REC(  0x0941,  0x0948 ),
+    AF_UNIRANGE_REC(  0x094D,  0x094D ),
+    AF_UNIRANGE_REC(  0x0953,  0x0957 ),
+    AF_UNIRANGE_REC(  0x0962,  0x0963 ),
+    AF_UNIRANGE_REC(  0xA8E0,  0xA8F1 ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_ethi_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x1200,  0x137F ),  /* Ethiopic            */
+    AF_UNIRANGE_REC(  0x1380,  0x139F ),  /* Ethiopic Supplement */
+    AF_UNIRANGE_REC(  0x2D80,  0x2DDF ),  /* Ethiopic Extended   */
+    AF_UNIRANGE_REC(  0xAB00,  0xAB2F ),  /* Ethiopic Extended-A */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_ethi_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x135D,  0x135F ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_geor_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x10D0,  0x10FF ),  /* Georgian (Mkhedruli) */
+#if 0
+    /* the following range is proposed for inclusion in Unicode */
+    AF_UNIRANGE_REC(  0x1C90,  0x1CBF ),  /* Georgian (Mtavruli)  */
+#endif
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_geor_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_geok_uniranges[] =
+  {
+    /* Khutsuri */
+    AF_UNIRANGE_REC(  0x10A0,  0x10CD ),  /* Georgian (Asomtavruli) */
+    AF_UNIRANGE_REC(  0x2D00,  0x2D2D ),  /* Georgian (Nuskhuri)    */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_geok_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC( 0, 0 )
   };
 
 
   const AF_Script_UniRangeRec  af_grek_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0370UL,  0x03FFUL ),  /* Greek and Coptic */
-    AF_UNIRANGE_REC(  0x1F00UL,  0x1FFFUL ),  /* Greek Extended   */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0370,  0x03FF ),  /* Greek and Coptic */
+    AF_UNIRANGE_REC(  0x1F00,  0x1FFF ),  /* Greek Extended   */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_grek_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x037AUL,  0x037AUL ),
-    AF_UNIRANGE_REC(  0x0384UL,  0x0385UL ),
-    AF_UNIRANGE_REC(  0x1FBDUL,  0x1FC1UL ),
-    AF_UNIRANGE_REC(  0x1FCDUL,  0x1FCFUL ),
-    AF_UNIRANGE_REC(  0x1FDDUL,  0x1FDFUL ),
-    AF_UNIRANGE_REC(  0x1FEDUL,  0x1FEFUL ),
-    AF_UNIRANGE_REC(  0x1FFDUL,  0x1FFEUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x037A,  0x037A ),
+    AF_UNIRANGE_REC(  0x0384,  0x0385 ),
+    AF_UNIRANGE_REC(  0x1FBD,  0x1FC1 ),
+    AF_UNIRANGE_REC(  0x1FCD,  0x1FCF ),
+    AF_UNIRANGE_REC(  0x1FDD,  0x1FDF ),
+    AF_UNIRANGE_REC(  0x1FED,  0x1FEF ),
+    AF_UNIRANGE_REC(  0x1FFD,  0x1FFE ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_gujr_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0A80,  0x0AFF ),  /* Gujarati */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_gujr_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0A81,  0x0A82 ),
+    AF_UNIRANGE_REC(  0x0ABC,  0x0ABC ),
+    AF_UNIRANGE_REC(  0x0AC1,  0x0AC8 ),
+    AF_UNIRANGE_REC(  0x0ACD,  0x0ACD ),
+    AF_UNIRANGE_REC(  0x0AE2,  0x0AE3 ),
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+
+  const AF_Script_UniRangeRec  af_guru_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0A00,  0x0A7F ),  /* Gurmukhi */
+    AF_UNIRANGE_REC(       0,       0 )
+  };
+
+  const AF_Script_UniRangeRec  af_guru_nonbase_uniranges[] =
+  {
+    AF_UNIRANGE_REC(  0x0A01,  0x0A02 ),
+    AF_UNIRANGE_REC(  0x0A3C,  0x0A3C ),
+    AF_UNIRANGE_REC(  0x0A41,  0x0A51 ),
+    AF_UNIRANGE_REC(  0x0A70,  0x0A71 ),
+    AF_UNIRANGE_REC(  0x0A75,  0x0A75 ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_hebr_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0590UL,  0x05FFUL ),  /* Hebrew                          */
-    AF_UNIRANGE_REC(  0xFB1DUL,  0xFB4FUL ),  /* Alphab. Present. Forms (Hebrew) */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0590,  0x05FF ),  /* Hebrew                          */
+    AF_UNIRANGE_REC(  0xFB1D,  0xFB4F ),  /* Alphab. Present. Forms (Hebrew) */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_hebr_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0591UL,  0x05BFUL ),
-    AF_UNIRANGE_REC(  0x05C1UL,  0x05C2UL ),
-    AF_UNIRANGE_REC(  0x05C4UL,  0x05C5UL ),
-    AF_UNIRANGE_REC(  0x05C7UL,  0x05C7UL ),
-    AF_UNIRANGE_REC(  0xFB1EUL,  0xFB1EUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0591,  0x05BF ),
+    AF_UNIRANGE_REC(  0x05C1,  0x05C2 ),
+    AF_UNIRANGE_REC(  0x05C4,  0x05C5 ),
+    AF_UNIRANGE_REC(  0x05C7,  0x05C7 ),
+    AF_UNIRANGE_REC(  0xFB1E,  0xFB1E ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_knda_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0C80UL,  0x0CFFUL ),  /* Kannada */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0C80,  0x0CFF ),  /* Kannada */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_knda_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0C81UL,  0x0C81UL ),
-    AF_UNIRANGE_REC(  0x0CBCUL,  0x0CBCUL ),
-    AF_UNIRANGE_REC(  0x0CBFUL,  0x0CBFUL ),
-    AF_UNIRANGE_REC(  0x0CC6UL,  0x0CC6UL ),
-    AF_UNIRANGE_REC(  0x0CCCUL,  0x0CCDUL ),
-    AF_UNIRANGE_REC(  0x0CE2UL,  0x0CE3UL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0C81,  0x0C81 ),
+    AF_UNIRANGE_REC(  0x0CBC,  0x0CBC ),
+    AF_UNIRANGE_REC(  0x0CBF,  0x0CBF ),
+    AF_UNIRANGE_REC(  0x0CC6,  0x0CC6 ),
+    AF_UNIRANGE_REC(  0x0CCC,  0x0CCD ),
+    AF_UNIRANGE_REC(  0x0CE2,  0x0CE3 ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_khmr_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x1780UL,  0x17FFUL ),  /* Khmer */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x1780,  0x17FF ),  /* Khmer */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_khmr_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x17B7UL,  0x17BDUL ),
-    AF_UNIRANGE_REC(  0x17C6UL,  0x17C6UL ),
-    AF_UNIRANGE_REC(  0x17C9UL,  0x17D3UL ),
-    AF_UNIRANGE_REC(  0x17DDUL,  0x17DDUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x17B7,  0x17BD ),
+    AF_UNIRANGE_REC(  0x17C6,  0x17C6 ),
+    AF_UNIRANGE_REC(  0x17C9,  0x17D3 ),
+    AF_UNIRANGE_REC(  0x17DD,  0x17DD ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_khms_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x19E0UL,  0x19FFUL ),  /* Khmer Symbols */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x19E0,  0x19FF ),  /* Khmer Symbols */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_khms_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC( 0UL, 0UL )
+    AF_UNIRANGE_REC( 0, 0 )
   };
 
 
   const AF_Script_UniRangeRec  af_lao_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0E80UL,  0x0EFFUL ),  /* Lao */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0E80,  0x0EFF ),  /* Lao */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_lao_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0EB1UL,  0x0EB1UL ),
-    AF_UNIRANGE_REC(  0x0EB4UL,  0x0EBCUL ),
-    AF_UNIRANGE_REC(  0x0EC8UL,  0x0ECDUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0EB1,  0x0EB1 ),
+    AF_UNIRANGE_REC(  0x0EB4,  0x0EBC ),
+    AF_UNIRANGE_REC(  0x0EC8,  0x0ECD ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_latn_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0020UL,  0x007FUL ),  /* Basic Latin (no control chars)         */
-    AF_UNIRANGE_REC(  0x00A0UL,  0x00A9UL ),  /* Latin-1 Supplement (no control chars)  */
-    AF_UNIRANGE_REC(  0x00ABUL,  0x00B1UL ),  /* ... continued                          */
-    AF_UNIRANGE_REC(  0x00B4UL,  0x00B8UL ),  /* ... continued                          */
-    AF_UNIRANGE_REC(  0x00BBUL,  0x00FFUL ),  /* ... continued                          */
-    AF_UNIRANGE_REC(  0x0100UL,  0x017FUL ),  /* Latin Extended-A                       */
-    AF_UNIRANGE_REC(  0x0180UL,  0x024FUL ),  /* Latin Extended-B                       */
-    AF_UNIRANGE_REC(  0x0250UL,  0x02AFUL ),  /* IPA Extensions                         */
-    AF_UNIRANGE_REC(  0x02B9UL,  0x02DFUL ),  /* Spacing Modifier Letters               */
-    AF_UNIRANGE_REC(  0x02E5UL,  0x02FFUL ),  /* ... continued                          */
-    AF_UNIRANGE_REC(  0x0300UL,  0x036FUL ),  /* Combining Diacritical Marks            */
-    AF_UNIRANGE_REC(  0x1AB0UL,  0x1ABEUL ),  /* Combining Diacritical Marks Extended   */
-    AF_UNIRANGE_REC(  0x1D00UL,  0x1D2BUL ),  /* Phonetic Extensions                    */
-    AF_UNIRANGE_REC(  0x1D6BUL,  0x1D77UL ),  /* ... continued                          */
-    AF_UNIRANGE_REC(  0x1D79UL,  0x1D7FUL ),  /* ... continued                          */
-    AF_UNIRANGE_REC(  0x1D80UL,  0x1D9AUL ),  /* Phonetic Extensions Supplement         */
-    AF_UNIRANGE_REC(  0x1DC0UL,  0x1DFFUL ),  /* Combining Diacritical Marks Supplement */
-    AF_UNIRANGE_REC(  0x1E00UL,  0x1EFFUL ),  /* Latin Extended Additional              */
-    AF_UNIRANGE_REC(  0x2000UL,  0x206FUL ),  /* General Punctuation                    */
-    AF_UNIRANGE_REC(  0x20A0UL,  0x20B8UL ),  /* Currency Symbols ...                   */
-    AF_UNIRANGE_REC(  0x20BAUL,  0x20CFUL ),  /* ... except new Rupee sign              */
-    AF_UNIRANGE_REC(  0x2150UL,  0x218FUL ),  /* Number Forms                           */
-    AF_UNIRANGE_REC(  0x2C60UL,  0x2C7BUL ),  /* Latin Extended-C                       */
-    AF_UNIRANGE_REC(  0x2C7EUL,  0x2C7FUL ),  /* ... continued                          */
-    AF_UNIRANGE_REC(  0x2E00UL,  0x2E7FUL ),  /* Supplemental Punctuation               */
-    AF_UNIRANGE_REC(  0xA720UL,  0xA76FUL ),  /* Latin Extended-D                       */
-    AF_UNIRANGE_REC(  0xA771UL,  0xA7F7UL ),  /* ... continued                          */
-    AF_UNIRANGE_REC(  0xA7FAUL,  0xA7FFUL ),  /* ... continued                          */
-    AF_UNIRANGE_REC(  0xAB30UL,  0xAB5BUL ),  /* Latin Extended-E                       */
-    AF_UNIRANGE_REC(  0xAB60UL,  0xAB6FUL ),  /* ... continued                          */
-    AF_UNIRANGE_REC(  0xFB00UL,  0xFB06UL ),  /* Alphab. Present. Forms (Latin Ligs)    */
-    AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ),  /* Mathematical Alphanumeric Symbols      */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0020,  0x007F ),  /* Basic Latin (no control chars)         */
+    AF_UNIRANGE_REC(  0x00A0,  0x00A9 ),  /* Latin-1 Supplement (no control chars)  */
+    AF_UNIRANGE_REC(  0x00AB,  0x00B1 ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x00B4,  0x00B8 ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x00BB,  0x00FF ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x0100,  0x017F ),  /* Latin Extended-A                       */
+    AF_UNIRANGE_REC(  0x0180,  0x024F ),  /* Latin Extended-B                       */
+    AF_UNIRANGE_REC(  0x0250,  0x02AF ),  /* IPA Extensions                         */
+    AF_UNIRANGE_REC(  0x02B9,  0x02DF ),  /* Spacing Modifier Letters               */
+    AF_UNIRANGE_REC(  0x02E5,  0x02FF ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x0300,  0x036F ),  /* Combining Diacritical Marks            */
+    AF_UNIRANGE_REC(  0x1AB0,  0x1ABE ),  /* Combining Diacritical Marks Extended   */
+    AF_UNIRANGE_REC(  0x1D00,  0x1D2B ),  /* Phonetic Extensions                    */
+    AF_UNIRANGE_REC(  0x1D6B,  0x1D77 ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x1D79,  0x1D7F ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x1D80,  0x1D9A ),  /* Phonetic Extensions Supplement         */
+    AF_UNIRANGE_REC(  0x1DC0,  0x1DFF ),  /* Combining Diacritical Marks Supplement */
+    AF_UNIRANGE_REC(  0x1E00,  0x1EFF ),  /* Latin Extended Additional              */
+    AF_UNIRANGE_REC(  0x2000,  0x206F ),  /* General Punctuation                    */
+    AF_UNIRANGE_REC(  0x20A0,  0x20B8 ),  /* Currency Symbols ...                   */
+    AF_UNIRANGE_REC(  0x20BA,  0x20CF ),  /* ... except new Rupee sign              */
+    AF_UNIRANGE_REC(  0x2150,  0x218F ),  /* Number Forms                           */
+    AF_UNIRANGE_REC(  0x2C60,  0x2C7B ),  /* Latin Extended-C                       */
+    AF_UNIRANGE_REC(  0x2C7E,  0x2C7F ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0x2E00,  0x2E7F ),  /* Supplemental Punctuation               */
+    AF_UNIRANGE_REC(  0xA720,  0xA76F ),  /* Latin Extended-D                       */
+    AF_UNIRANGE_REC(  0xA771,  0xA7F7 ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0xA7FA,  0xA7FF ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0xAB30,  0xAB5B ),  /* Latin Extended-E                       */
+    AF_UNIRANGE_REC(  0xAB60,  0xAB6F ),  /* ... continued                          */
+    AF_UNIRANGE_REC(  0xFB00,  0xFB06 ),  /* Alphab. Present. Forms (Latin Ligs)    */
+    AF_UNIRANGE_REC( 0x1D400, 0x1D7FF ),  /* Mathematical Alphanumeric Symbols      */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_latn_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x005EUL,  0x0060UL ),
-    AF_UNIRANGE_REC(  0x007EUL,  0x007EUL ),
-    AF_UNIRANGE_REC(  0x00A8UL,  0x00A9UL ),
-    AF_UNIRANGE_REC(  0x00AEUL,  0x00B0UL ),
-    AF_UNIRANGE_REC(  0x00B4UL,  0x00B4UL ),
-    AF_UNIRANGE_REC(  0x00B8UL,  0x00B8UL ),
-    AF_UNIRANGE_REC(  0x00BCUL,  0x00BEUL ),
-    AF_UNIRANGE_REC(  0x02B9UL,  0x02DFUL ),
-    AF_UNIRANGE_REC(  0x02E5UL,  0x02FFUL ),
-    AF_UNIRANGE_REC(  0x0300UL,  0x036FUL ),
-    AF_UNIRANGE_REC(  0x1AB0UL,  0x1ABEUL ),
-    AF_UNIRANGE_REC(  0x1DC0UL,  0x1DFFUL ),
-    AF_UNIRANGE_REC(  0x2017UL,  0x2017UL ),
-    AF_UNIRANGE_REC(  0x203EUL,  0x203EUL ),
-    AF_UNIRANGE_REC(  0xA788UL,  0xA788UL ),
-    AF_UNIRANGE_REC(  0xA7F8UL,  0xA7FAUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x005E,  0x0060 ),
+    AF_UNIRANGE_REC(  0x007E,  0x007E ),
+    AF_UNIRANGE_REC(  0x00A8,  0x00A9 ),
+    AF_UNIRANGE_REC(  0x00AE,  0x00B0 ),
+    AF_UNIRANGE_REC(  0x00B4,  0x00B4 ),
+    AF_UNIRANGE_REC(  0x00B8,  0x00B8 ),
+    AF_UNIRANGE_REC(  0x00BC,  0x00BE ),
+    AF_UNIRANGE_REC(  0x02B9,  0x02DF ),
+    AF_UNIRANGE_REC(  0x02E5,  0x02FF ),
+    AF_UNIRANGE_REC(  0x0300,  0x036F ),
+    AF_UNIRANGE_REC(  0x1AB0,  0x1ABE ),
+    AF_UNIRANGE_REC(  0x1DC0,  0x1DFF ),
+    AF_UNIRANGE_REC(  0x2017,  0x2017 ),
+    AF_UNIRANGE_REC(  0x203E,  0x203E ),
+    AF_UNIRANGE_REC(  0xA788,  0xA788 ),
+    AF_UNIRANGE_REC(  0xA7F8,  0xA7FA ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_latb_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x1D62UL,  0x1D6AUL ),  /* some small subscript letters   */
-    AF_UNIRANGE_REC(  0x2080UL,  0x209CUL ),  /* subscript digits and letters   */
-    AF_UNIRANGE_REC(  0x2C7CUL,  0x2C7CUL ),  /* latin subscript small letter j */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x1D62,  0x1D6A ),  /* some small subscript letters   */
+    AF_UNIRANGE_REC(  0x2080,  0x209C ),  /* subscript digits and letters   */
+    AF_UNIRANGE_REC(  0x2C7C,  0x2C7C ),  /* latin subscript small letter j */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_latb_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC( 0UL, 0UL )
+    AF_UNIRANGE_REC( 0, 0 )
   };
 
 
   const AF_Script_UniRangeRec  af_latp_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x00AAUL,  0x00AAUL ),  /* feminine ordinal indicator          */
-    AF_UNIRANGE_REC(  0x00B2UL,  0x00B3UL ),  /* superscript two and three           */
-    AF_UNIRANGE_REC(  0x00B9UL,  0x00BAUL ),  /* superscript one, masc. ord. indic.  */
-    AF_UNIRANGE_REC(  0x02B0UL,  0x02B8UL ),  /* some latin superscript mod. letters */
-    AF_UNIRANGE_REC(  0x02E0UL,  0x02E4UL ),  /* some IPA modifier letters           */
-    AF_UNIRANGE_REC(  0x1D2CUL,  0x1D61UL ),  /* latin superscript modifier letters  */
-    AF_UNIRANGE_REC(  0x1D78UL,  0x1D78UL ),  /* modifier letter cyrillic en         */
-    AF_UNIRANGE_REC(  0x1D9BUL,  0x1DBFUL ),  /* more modifier letters               */
-    AF_UNIRANGE_REC(  0x2070UL,  0x207FUL ),  /* superscript digits and letters      */
-    AF_UNIRANGE_REC(  0x2C7DUL,  0x2C7DUL ),  /* modifier letter capital v           */
-    AF_UNIRANGE_REC(  0xA770UL,  0xA770UL ),  /* modifier letter us                  */
-    AF_UNIRANGE_REC(  0xA7F8UL,  0xA7F9UL ),  /* more modifier letters               */
-    AF_UNIRANGE_REC(  0xAB5CUL,  0xAB5FUL ),  /* more modifier letters               */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x00AA,  0x00AA ),  /* feminine ordinal indicator          */
+    AF_UNIRANGE_REC(  0x00B2,  0x00B3 ),  /* superscript two and three           */
+    AF_UNIRANGE_REC(  0x00B9,  0x00BA ),  /* superscript one, masc. ord. indic.  */
+    AF_UNIRANGE_REC(  0x02B0,  0x02B8 ),  /* some latin superscript mod. letters */
+    AF_UNIRANGE_REC(  0x02E0,  0x02E4 ),  /* some IPA modifier letters           */
+    AF_UNIRANGE_REC(  0x1D2C,  0x1D61 ),  /* latin superscript modifier letters  */
+    AF_UNIRANGE_REC(  0x1D78,  0x1D78 ),  /* modifier letter cyrillic en         */
+    AF_UNIRANGE_REC(  0x1D9B,  0x1DBF ),  /* more modifier letters               */
+    AF_UNIRANGE_REC(  0x2070,  0x207F ),  /* superscript digits and letters      */
+    AF_UNIRANGE_REC(  0x2C7D,  0x2C7D ),  /* modifier letter capital v           */
+    AF_UNIRANGE_REC(  0xA770,  0xA770 ),  /* modifier letter us                  */
+    AF_UNIRANGE_REC(  0xA7F8,  0xA7F9 ),  /* more modifier letters               */
+    AF_UNIRANGE_REC(  0xAB5C,  0xAB5F ),  /* more modifier letters               */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_latp_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC( 0UL, 0UL )
+    AF_UNIRANGE_REC( 0, 0 )
   };
 
 
-  const AF_Script_UniRangeRec  af_mymr_uniranges[] =
+  const AF_Script_UniRangeRec  af_mlym_uniranges[] =
   {
-    AF_UNIRANGE_REC( 0x1000UL, 0x109FUL ),    /* Myanmar            */
-    AF_UNIRANGE_REC( 0xA9E0UL, 0xA9FFUL ),    /* Myanmar Extended-B */
-    AF_UNIRANGE_REC( 0xAA60UL, 0xAA7FUL ),    /* Myanmar Extended-A */
-    AF_UNIRANGE_REC(      0UL,      0UL )
+    AF_UNIRANGE_REC(  0x0D00,  0x0D7F ),  /* Malayalam */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_mymr_nonbase_uniranges[] =
+  const AF_Script_UniRangeRec  af_mlym_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC( 0x102DUL, 0x1030UL ),
-    AF_UNIRANGE_REC( 0x1032UL, 0x1037UL ),
-    AF_UNIRANGE_REC( 0x103AUL, 0x103AUL ),
-    AF_UNIRANGE_REC( 0x103DUL, 0x103EUL ),
-    AF_UNIRANGE_REC( 0x1058UL, 0x1059UL ),
-    AF_UNIRANGE_REC( 0x105EUL, 0x1060UL ),
-    AF_UNIRANGE_REC( 0x1071UL, 0x1074UL ),
-    AF_UNIRANGE_REC( 0x1082UL, 0x1082UL ),
-    AF_UNIRANGE_REC( 0x1085UL, 0x1086UL ),
-    AF_UNIRANGE_REC( 0x108DUL, 0x108DUL ),
-    AF_UNIRANGE_REC( 0xA9E5UL, 0xA9E5UL ),
-    AF_UNIRANGE_REC( 0xAA7CUL, 0xAA7CUL ),
-    AF_UNIRANGE_REC(      0UL,      0UL )
+    AF_UNIRANGE_REC(  0x0D01,  0x0D01 ),
+    AF_UNIRANGE_REC(  0x0D4D,  0x0D4E ),
+    AF_UNIRANGE_REC(  0x0D62,  0x0D63 ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
-  const AF_Script_UniRangeRec  af_none_uniranges[] =
+  const AF_Script_UniRangeRec  af_mymr_uniranges[] =
   {
-    AF_UNIRANGE_REC( 0UL, 0UL )
+    AF_UNIRANGE_REC( 0x1000, 0x109F ),    /* Myanmar            */
+    AF_UNIRANGE_REC( 0xA9E0, 0xA9FF ),    /* Myanmar Extended-B */
+    AF_UNIRANGE_REC( 0xAA60, 0xAA7F ),    /* Myanmar Extended-A */
+    AF_UNIRANGE_REC(      0,      0 )
   };
 
-  const AF_Script_UniRangeRec  af_none_nonbase_uniranges[] =
+  const AF_Script_UniRangeRec  af_mymr_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC( 0UL, 0UL )
+    AF_UNIRANGE_REC( 0x102D, 0x1030 ),
+    AF_UNIRANGE_REC( 0x1032, 0x1037 ),
+    AF_UNIRANGE_REC( 0x103A, 0x103A ),
+    AF_UNIRANGE_REC( 0x103D, 0x103E ),
+    AF_UNIRANGE_REC( 0x1058, 0x1059 ),
+    AF_UNIRANGE_REC( 0x105E, 0x1060 ),
+    AF_UNIRANGE_REC( 0x1071, 0x1074 ),
+    AF_UNIRANGE_REC( 0x1082, 0x1082 ),
+    AF_UNIRANGE_REC( 0x1085, 0x1086 ),
+    AF_UNIRANGE_REC( 0x108D, 0x108D ),
+    AF_UNIRANGE_REC( 0xA9E5, 0xA9E5 ),
+    AF_UNIRANGE_REC( 0xAA7C, 0xAA7C ),
+    AF_UNIRANGE_REC(      0,      0 )
   };
 
 
-  const AF_Script_UniRangeRec  af_telu_uniranges[] =
+  const AF_Script_UniRangeRec  af_none_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0C00UL,  0x0C7FUL ),  /* Telugu */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC( 0, 0 )
   };
 
-  const AF_Script_UniRangeRec  af_telu_nonbase_uniranges[] =
+  const AF_Script_UniRangeRec  af_none_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0C00UL,  0x0C00UL ),
-    AF_UNIRANGE_REC(  0x0C3EUL,  0x0C40UL ),
-    AF_UNIRANGE_REC(  0x0C46UL,  0x0C56UL ),
-    AF_UNIRANGE_REC(  0x0C62UL,  0x0C63UL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC( 0, 0 )
   };
 
 
-  const AF_Script_UniRangeRec  af_thai_uniranges[] =
+  const AF_Script_UniRangeRec  af_sinh_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0E00UL,  0x0E7FUL ),  /* Thai */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0D80,  0x0DFF ),  /* Sinhala */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_thai_nonbase_uniranges[] =
+  const AF_Script_UniRangeRec  af_sinh_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0E31UL,  0x0E31UL ),
-    AF_UNIRANGE_REC(  0x0E34UL,  0x0E3AUL ),
-    AF_UNIRANGE_REC(  0x0E47UL,  0x0E4EUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0DCA,  0x0DCA ),
+    AF_UNIRANGE_REC(  0x0DD2,  0x0DD6 ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
-#ifdef AF_CONFIG_OPTION_INDIC
-
-  const AF_Script_UniRangeRec  af_gujr_uniranges[] =
+  const AF_Script_UniRangeRec  af_taml_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0A80UL,  0x0AFFUL ),  /* Gujarati */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0B80,  0x0BFF ),  /* Tamil */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_gujr_nonbase_uniranges[] =
+  const AF_Script_UniRangeRec  af_taml_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0A81UL,  0x0A82UL ),
-    AF_UNIRANGE_REC(  0x0ABCUL,  0x0ABCUL ),
-    AF_UNIRANGE_REC(  0x0AC1UL,  0x0AC8UL ),
-    AF_UNIRANGE_REC(  0x0ACDUL,  0x0ACDUL ),
-    AF_UNIRANGE_REC(  0x0AE2UL,  0x0AE3UL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0B82,  0x0B82 ),
+    AF_UNIRANGE_REC(  0x0BC0,  0x0BC2 ),
+    AF_UNIRANGE_REC(  0x0BCD,  0x0BCD ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
-  const AF_Script_UniRangeRec  af_guru_uniranges[] =
+  const AF_Script_UniRangeRec  af_telu_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0A00UL,  0x0A7FUL ),  /* Gurmukhi */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0C00,  0x0C7F ),  /* Telugu */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_guru_nonbase_uniranges[] =
+  const AF_Script_UniRangeRec  af_telu_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0A01UL,  0x0A02UL ),
-    AF_UNIRANGE_REC(  0x0A3CUL,  0x0A3EUL ),
-    AF_UNIRANGE_REC(  0x0A41UL,  0x0A51UL ),
-    AF_UNIRANGE_REC(  0x0A70UL,  0x0A71UL ),
-    AF_UNIRANGE_REC(  0x0A75UL,  0x0A75UL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0C00,  0x0C00 ),
+    AF_UNIRANGE_REC(  0x0C3E,  0x0C40 ),
+    AF_UNIRANGE_REC(  0x0C46,  0x0C56 ),
+    AF_UNIRANGE_REC(  0x0C62,  0x0C63 ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
-  const AF_Script_UniRangeRec  af_limb_uniranges[] =
+  const AF_Script_UniRangeRec  af_thai_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x1900UL,  0x194FUL ),  /* Limbu */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0E00,  0x0E7F ),  /* Thai */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_limb_nonbase_uniranges[] =
+  const AF_Script_UniRangeRec  af_thai_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x1920UL,  0x1922UL ),
-    AF_UNIRANGE_REC(  0x1927UL,  0x1934UL ),
-    AF_UNIRANGE_REC(  0x1937UL,  0x193BUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0E31,  0x0E31 ),
+    AF_UNIRANGE_REC(  0x0E34,  0x0E3A ),
+    AF_UNIRANGE_REC(  0x0E47,  0x0E4E ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
-  const AF_Script_UniRangeRec  af_mlym_uniranges[] =
+#ifdef AF_CONFIG_OPTION_INDIC
+
+  const AF_Script_UniRangeRec  af_limb_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0D00UL,  0x0D7FUL ),  /* Malayalam */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x1900,  0x194F ),  /* Limbu */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
-  const AF_Script_UniRangeRec  af_mlym_nonbase_uniranges[] =
+  const AF_Script_UniRangeRec  af_limb_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0D01UL,  0x0D01UL ),
-    AF_UNIRANGE_REC(  0x0D4DUL,  0x0D4EUL ),
-    AF_UNIRANGE_REC(  0x0D62UL,  0x0D63UL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x1920,  0x1922 ),
+    AF_UNIRANGE_REC(  0x1927,  0x1934 ),
+    AF_UNIRANGE_REC(  0x1937,  0x193B ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_orya_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0B00UL,  0x0B7FUL ),  /* Oriya */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0B00,  0x0B7F ),  /* Oriya */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_orya_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0B01UL,  0x0B02UL ),
-    AF_UNIRANGE_REC(  0x0B3CUL,  0x0B3CUL ),
-    AF_UNIRANGE_REC(  0x0B3FUL,  0x0B3FUL ),
-    AF_UNIRANGE_REC(  0x0B41UL,  0x0B44UL ),
-    AF_UNIRANGE_REC(  0x0B4DUL,  0x0B56UL ),
-    AF_UNIRANGE_REC(  0x0B62UL,  0x0B63UL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
-  };
-
-
-  const AF_Script_UniRangeRec  af_sinh_uniranges[] =
-  {
-    AF_UNIRANGE_REC(  0x0D80UL,  0x0DFFUL ),  /* Sinhala */
-    AF_UNIRANGE_REC(       0UL,       0UL )
-  };
-
-  const AF_Script_UniRangeRec  af_sinh_nonbase_uniranges[] =
-  {
-    AF_UNIRANGE_REC(  0x0DCAUL,  0x0DCAUL ),
-    AF_UNIRANGE_REC(  0x0DD2UL,  0x0DD6UL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0B01,  0x0B02 ),
+    AF_UNIRANGE_REC(  0x0B3C,  0x0B3C ),
+    AF_UNIRANGE_REC(  0x0B3F,  0x0B3F ),
+    AF_UNIRANGE_REC(  0x0B41,  0x0B44 ),
+    AF_UNIRANGE_REC(  0x0B4D,  0x0B56 ),
+    AF_UNIRANGE_REC(  0x0B62,  0x0B63 ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_sund_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x1B80UL,  0x1BBFUL ),  /* Sundanese            */
-    AF_UNIRANGE_REC(  0x1CC0UL,  0x1CCFUL ),  /* Sundanese Supplement */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x1B80,  0x1BBF ),  /* Sundanese            */
+    AF_UNIRANGE_REC(  0x1CC0,  0x1CCF ),  /* Sundanese Supplement */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_sund_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x1B80UL,  0x1B82UL ),
-    AF_UNIRANGE_REC(  0x1BA1UL,  0x1BADUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x1B80,  0x1B82 ),
+    AF_UNIRANGE_REC(  0x1BA1,  0x1BAD ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_sylo_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0xA800UL,  0xA82FUL ),  /* Syloti Nagri */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0xA800,  0xA82F ),  /* Syloti Nagri */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_sylo_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0xA802UL,  0xA802UL ),
-    AF_UNIRANGE_REC(  0xA806UL,  0xA806UL ),
-    AF_UNIRANGE_REC(  0xA80BUL,  0xA80BUL ),
-    AF_UNIRANGE_REC(  0xA825UL,  0xA826UL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
-  };
-
-
-  const AF_Script_UniRangeRec  af_taml_uniranges[] =
-  {
-    AF_UNIRANGE_REC(  0x0B80UL,  0x0BFFUL ),  /* Tamil */
-    AF_UNIRANGE_REC(       0UL,       0UL )
-  };
-
-  const AF_Script_UniRangeRec  af_taml_nonbase_uniranges[] =
-  {
-    AF_UNIRANGE_REC(  0x0B82UL,  0x0B82UL ),
-    AF_UNIRANGE_REC(  0x0BC0UL,  0x0BC2UL ),
-    AF_UNIRANGE_REC(  0x0BCDUL,  0x0BCDUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0xA802,  0xA802 ),
+    AF_UNIRANGE_REC(  0xA806,  0xA806 ),
+    AF_UNIRANGE_REC(  0xA80B,  0xA80B ),
+    AF_UNIRANGE_REC(  0xA825,  0xA826 ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 
   const AF_Script_UniRangeRec  af_tibt_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0F00UL,  0x0FFFUL ),  /* Tibetan */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0F00,  0x0FFF ),  /* Tibetan */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_tibt_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x0F18UL,  0x0F19UL ),
-    AF_UNIRANGE_REC(  0x0F35UL,  0x0F35UL ),
-    AF_UNIRANGE_REC(  0x0F37UL,  0x0F37UL ),
-    AF_UNIRANGE_REC(  0x0F39UL,  0x0F39UL ),
-    AF_UNIRANGE_REC(  0x0F3EUL,  0x0F3FUL ),
-    AF_UNIRANGE_REC(  0x0F71UL,  0x0F7EUL ),
-    AF_UNIRANGE_REC(  0x0F80UL,  0x0F84UL ),
-    AF_UNIRANGE_REC(  0x0F86UL,  0x0F87UL ),
-    AF_UNIRANGE_REC(  0x0F8DUL,  0x0FBCUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x0F18,  0x0F19 ),
+    AF_UNIRANGE_REC(  0x0F35,  0x0F35 ),
+    AF_UNIRANGE_REC(  0x0F37,  0x0F37 ),
+    AF_UNIRANGE_REC(  0x0F39,  0x0F39 ),
+    AF_UNIRANGE_REC(  0x0F3E,  0x0F3F ),
+    AF_UNIRANGE_REC(  0x0F71,  0x0F7E ),
+    AF_UNIRANGE_REC(  0x0F80,  0x0F84 ),
+    AF_UNIRANGE_REC(  0x0F86,  0x0F87 ),
+    AF_UNIRANGE_REC(  0x0F8D,  0x0FBC ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 #endif /* !AF_CONFIG_OPTION_INDIC */
 
   const AF_Script_UniRangeRec  af_hani_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x1100UL,  0x11FFUL ),  /* Hangul Jamo                             */
-    AF_UNIRANGE_REC(  0x2E80UL,  0x2EFFUL ),  /* CJK Radicals Supplement                 */
-    AF_UNIRANGE_REC(  0x2F00UL,  0x2FDFUL ),  /* Kangxi Radicals                         */
-    AF_UNIRANGE_REC(  0x2FF0UL,  0x2FFFUL ),  /* Ideographic Description Characters      */
-    AF_UNIRANGE_REC(  0x3000UL,  0x303FUL ),  /* CJK Symbols and Punctuation             */
-    AF_UNIRANGE_REC(  0x3040UL,  0x309FUL ),  /* Hiragana                                */
-    AF_UNIRANGE_REC(  0x30A0UL,  0x30FFUL ),  /* Katakana                                */
-    AF_UNIRANGE_REC(  0x3100UL,  0x312FUL ),  /* Bopomofo                                */
-    AF_UNIRANGE_REC(  0x3130UL,  0x318FUL ),  /* Hangul Compatibility Jamo               */
-    AF_UNIRANGE_REC(  0x3190UL,  0x319FUL ),  /* Kanbun                                  */
-    AF_UNIRANGE_REC(  0x31A0UL,  0x31BFUL ),  /* Bopomofo Extended                       */
-    AF_UNIRANGE_REC(  0x31C0UL,  0x31EFUL ),  /* CJK Strokes                             */
-    AF_UNIRANGE_REC(  0x31F0UL,  0x31FFUL ),  /* Katakana Phonetic Extensions            */
-    AF_UNIRANGE_REC(  0x3300UL,  0x33FFUL ),  /* CJK Compatibility                       */
-    AF_UNIRANGE_REC(  0x3400UL,  0x4DBFUL ),  /* CJK Unified Ideographs Extension A      */
-    AF_UNIRANGE_REC(  0x4DC0UL,  0x4DFFUL ),  /* Yijing Hexagram Symbols                 */
-    AF_UNIRANGE_REC(  0x4E00UL,  0x9FFFUL ),  /* CJK Unified Ideographs                  */
-    AF_UNIRANGE_REC(  0xA960UL,  0xA97FUL ),  /* Hangul Jamo Extended-A                  */
-    AF_UNIRANGE_REC(  0xAC00UL,  0xD7AFUL ),  /* Hangul Syllables                        */
-    AF_UNIRANGE_REC(  0xD7B0UL,  0xD7FFUL ),  /* Hangul Jamo Extended-B                  */
-    AF_UNIRANGE_REC(  0xF900UL,  0xFAFFUL ),  /* CJK Compatibility Ideographs            */
-    AF_UNIRANGE_REC(  0xFE10UL,  0xFE1FUL ),  /* Vertical forms                          */
-    AF_UNIRANGE_REC(  0xFE30UL,  0xFE4FUL ),  /* CJK Compatibility Forms                 */
-    AF_UNIRANGE_REC(  0xFF00UL,  0xFFEFUL ),  /* Halfwidth and Fullwidth Forms           */
-    AF_UNIRANGE_REC( 0x1B000UL, 0x1B0FFUL ),  /* Kana Supplement                         */
-    AF_UNIRANGE_REC( 0x1D300UL, 0x1D35FUL ),  /* Tai Xuan Hing Symbols                   */
-    AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ),  /* CJK Unified Ideographs Extension B      */
-    AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ),  /* CJK Unified Ideographs Extension C      */
-    AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ),  /* CJK Unified Ideographs Extension D      */
-    AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ),  /* CJK Compatibility Ideographs Supplement */
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x1100,  0x11FF ),  /* Hangul Jamo                             */
+    AF_UNIRANGE_REC(  0x2E80,  0x2EFF ),  /* CJK Radicals Supplement                 */
+    AF_UNIRANGE_REC(  0x2F00,  0x2FDF ),  /* Kangxi Radicals                         */
+    AF_UNIRANGE_REC(  0x2FF0,  0x2FFF ),  /* Ideographic Description Characters      */
+    AF_UNIRANGE_REC(  0x3000,  0x303F ),  /* CJK Symbols and Punctuation             */
+    AF_UNIRANGE_REC(  0x3040,  0x309F ),  /* Hiragana                                */
+    AF_UNIRANGE_REC(  0x30A0,  0x30FF ),  /* Katakana                                */
+    AF_UNIRANGE_REC(  0x3100,  0x312F ),  /* Bopomofo                                */
+    AF_UNIRANGE_REC(  0x3130,  0x318F ),  /* Hangul Compatibility Jamo               */
+    AF_UNIRANGE_REC(  0x3190,  0x319F ),  /* Kanbun                                  */
+    AF_UNIRANGE_REC(  0x31A0,  0x31BF ),  /* Bopomofo Extended                       */
+    AF_UNIRANGE_REC(  0x31C0,  0x31EF ),  /* CJK Strokes                             */
+    AF_UNIRANGE_REC(  0x31F0,  0x31FF ),  /* Katakana Phonetic Extensions            */
+    AF_UNIRANGE_REC(  0x3300,  0x33FF ),  /* CJK Compatibility                       */
+    AF_UNIRANGE_REC(  0x3400,  0x4DBF ),  /* CJK Unified Ideographs Extension A      */
+    AF_UNIRANGE_REC(  0x4DC0,  0x4DFF ),  /* Yijing Hexagram Symbols                 */
+    AF_UNIRANGE_REC(  0x4E00,  0x9FFF ),  /* CJK Unified Ideographs                  */
+    AF_UNIRANGE_REC(  0xA960,  0xA97F ),  /* Hangul Jamo Extended-A                  */
+    AF_UNIRANGE_REC(  0xAC00,  0xD7AF ),  /* Hangul Syllables                        */
+    AF_UNIRANGE_REC(  0xD7B0,  0xD7FF ),  /* Hangul Jamo Extended-B                  */
+    AF_UNIRANGE_REC(  0xF900,  0xFAFF ),  /* CJK Compatibility Ideographs            */
+    AF_UNIRANGE_REC(  0xFE10,  0xFE1F ),  /* Vertical forms                          */
+    AF_UNIRANGE_REC(  0xFE30,  0xFE4F ),  /* CJK Compatibility Forms                 */
+    AF_UNIRANGE_REC(  0xFF00,  0xFFEF ),  /* Halfwidth and Fullwidth Forms           */
+    AF_UNIRANGE_REC( 0x1B000, 0x1B0FF ),  /* Kana Supplement                         */
+    AF_UNIRANGE_REC( 0x1D300, 0x1D35F ),  /* Tai Xuan Hing Symbols                   */
+    AF_UNIRANGE_REC( 0x20000, 0x2A6DF ),  /* CJK Unified Ideographs Extension B      */
+    AF_UNIRANGE_REC( 0x2A700, 0x2B73F ),  /* CJK Unified Ideographs Extension C      */
+    AF_UNIRANGE_REC( 0x2B740, 0x2B81F ),  /* CJK Unified Ideographs Extension D      */
+    AF_UNIRANGE_REC( 0x2F800, 0x2FA1F ),  /* CJK Compatibility Ideographs Supplement */
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
   const AF_Script_UniRangeRec  af_hani_nonbase_uniranges[] =
   {
-    AF_UNIRANGE_REC(  0x302AUL,  0x302FUL ),
-    AF_UNIRANGE_REC(  0x3190UL,  0x319FUL ),
-    AF_UNIRANGE_REC(       0UL,       0UL )
+    AF_UNIRANGE_REC(  0x302A,  0x302F ),
+    AF_UNIRANGE_REC(  0x3190,  0x319F ),
+    AF_UNIRANGE_REC(       0,       0 )
   };
 
 #endif /* !AF_CONFIG_OPTION_CJK */
index 9bbb6f3..33c3012 100644 (file)
           HINTING_BOTTOM_TO_TOP,
           "\xD9\x84 \xD8\xAD \xD9\x80" ) /* ل ح ـ */
 
+  SCRIPT( armn, ARMN,
+          "Armenian",
+          HB_SCRIPT_ARMENIAN,
+          HINTING_BOTTOM_TO_TOP,
+          "\xD6\x85 \xD5\x95" ) /* օ Օ */
+
   /* there are no simple forms for letters; we thus use two digit shapes */
   SCRIPT( beng, BENG,
           "Bengali",
           HB_SCRIPT_BENGALI,
           HINTING_TOP_TO_BOTTOM,
-          "\xE0\xA7\xA6 \xE0\xA7\xAA" ) /* ০ ৪*/
+          "\xE0\xA7\xA6 \xE0\xA7\xAA" ) /* ০ ৪ */
+
+  SCRIPT( cher, CHER,
+          "Cherokee",
+          HB_SCRIPT_CHEROKEE,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\x8E\xA4 \xE1\x8F\x85 \xEA\xAE\x95" ) /* Ꭴ Ꮕ ꮕ */
 
   SCRIPT( cyrl, CYRL,
           "Cyrillic",
           HINTING_TOP_TO_BOTTOM,
           "\xE0\xA4\xA0 \xE0\xA4\xB5 \xE0\xA4\x9F" ) /* ठ व ट */
 
+  SCRIPT( ethi, ETHI,
+          "Ethiopic",
+          HB_SCRIPT_ETHIOPIC,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\x8B\x90" ) /* ዐ */
+
+  SCRIPT( geor, GEOR,
+          "Georgian (Mkhedruli)",
+          HB_SCRIPT_GEORGIAN,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\x83\x98 \xE1\x83\x94 \xE1\x83\x90" ) /* ი ე ა */
+
+  SCRIPT( geok, GEOK,
+          "Georgian (Khutsuri)",
+          HB_SCRIPT_INVALID,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE1\x82\xB6 \xE1\x82\xB1 \xE2\xB4\x99" ) /* Ⴖ Ⴑ ⴙ */
+
   SCRIPT( grek, GREK,
           "Greek",
           HB_SCRIPT_GREEK,
           HINTING_BOTTOM_TO_TOP,
           "\xCE\xBF \xCE\x9F" ) /* ο Ο */
 
+  SCRIPT( gujr, GUJR,
+          "Gujarati",
+          HB_SCRIPT_GUJARATI,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xAA\x9F \xE0\xAB\xA6" ) /* ટ ૦ */
+
+  SCRIPT( guru, GURU,
+          "Gurmukhi",
+          HB_SCRIPT_GURMUKHI,
+          HINTING_TOP_TO_BOTTOM,
+          "\xE0\xA8\xA0 \xE0\xA8\xB0 \xE0\xA9\xA6" ) /* ਠ ਰ ੦ */
+
   SCRIPT( hebr, HEBR,
           "Hebrew",
           HB_SCRIPT_HEBREW,
           HINTING_BOTTOM_TO_TOP,
           "\xE1\xB5\x92 \xE1\xB4\xBC \xE2\x81\xB0" ) /* ᵒ ᴼ ⁰ */
 
+  SCRIPT( mlym, MLYM,
+          "Malayalam",
+          HB_SCRIPT_MALAYALAM,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB4\xA0 \xE0\xB4\xB1" ) /* ഠ റ */
+
   SCRIPT( mymr, MYMR,
           "Myanmar",
           HB_SCRIPT_MYANMAR,
           HINTING_BOTTOM_TO_TOP,
           "" )
 
+  SCRIPT( sinh, SINH,
+          "Sinhala",
+          HB_SCRIPT_SINHALA,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xB6\xA7" ) /* ට */
+
+  /* only digit zero has a simple (round) shape in the Tamil script */
+  SCRIPT( taml, TAML,
+          "Tamil",
+          HB_SCRIPT_TAMIL,
+          HINTING_BOTTOM_TO_TOP,
+          "\xE0\xAF\xA6" ) /* ௦ */
+
   /* there are no simple forms for letters; we thus use two digit shapes */
   SCRIPT( telu, TELU,
           "Telugu",
 
 #ifdef AF_CONFIG_OPTION_INDIC
 
-  SCRIPT( gujr, GUJR,
-          "Gujarati",
-          HB_SCRIPT_GUJARATI,
-          HINTING_BOTTOM_TO_TOP,
-          "o" ) /* XXX */
-
-  SCRIPT( guru, GURU,
-          "Gurmukhi",
-          HB_SCRIPT_GURMUKHI,
-          HINTING_BOTTOM_TO_TOP,
-          "o" ) /* XXX */
-
   SCRIPT( limb, LIMB,
           "Limbu",
           HB_SCRIPT_LIMBU,
           HINTING_BOTTOM_TO_TOP,
           "o" ) /* XXX */
 
-  SCRIPT( mlym, MLYM,
-          "Malayalam",
-          HB_SCRIPT_MALAYALAM,
-          HINTING_BOTTOM_TO_TOP,
-          "o" ) /* XXX */
-
   SCRIPT( orya, ORYA,
           "Oriya",
           HB_SCRIPT_ORIYA,
           HINTING_BOTTOM_TO_TOP,
           "o" ) /* XXX */
 
-  SCRIPT( sinh, SINH,
-          "Sinhala",
-          HB_SCRIPT_SINHALA,
-          HINTING_BOTTOM_TO_TOP,
-          "o" ) /* XXX */
-
   SCRIPT( sund, SUND,
           "Sundanese",
           HB_SCRIPT_SUNDANESE,
           HINTING_BOTTOM_TO_TOP,
           "o" ) /* XXX */
 
-  SCRIPT( taml, TAML,
-          "Tamil",
-          HB_SCRIPT_TAMIL,
-          HINTING_BOTTOM_TO_TOP,
-          "o" ) /* XXX */
-
   SCRIPT( tibt, TIBT,
           "Tibetan",
           HB_SCRIPT_TIBETAN,
index 9c57258..e83a95b 100644 (file)
 #undef  META_STYLE_LATIN
 #define META_STYLE_LATIN( s, S, ds )                     \
           STYLE_LATIN( s, S, c2cp, C2CP, ds,             \
-                       "petite capticals from capitals", \
+                       "petite capitals from capitals", \
                        PETITE_CAPITALS_FROM_CAPITALS )   \
           STYLE_LATIN( s, S, c2sc, C2SC, ds,             \
-                       "small capticals from capitals",  \
+                       "small capitals from capitals",  \
                        SMALL_CAPITALS_FROM_CAPITALS )    \
           STYLE_LATIN( s, S, ordn, ORDN, ds,             \
                        "ordinals",                       \
          AF_BLUE_STRINGSET_ARAB,
          AF_COVERAGE_DEFAULT )
 
+  STYLE( armn_dflt, ARMN_DFLT,
+         "Armenian default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_ARMN,
+         AF_BLUE_STRINGSET_ARMN,
+         AF_COVERAGE_DEFAULT )
+
   STYLE( beng_dflt, BENG_DFLT,
          "Bengali default style",
          AF_WRITING_SYSTEM_LATIN,
          AF_BLUE_STRINGSET_BENG,
          AF_COVERAGE_DEFAULT )
 
+  STYLE( cher_dflt, CHER_DFLT,
+         "Cherokee default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_CHER,
+         AF_BLUE_STRINGSET_CHER,
+         AF_COVERAGE_DEFAULT )
+
   META_STYLE_LATIN( cyrl, CYRL, "Cyrillic" )
 
   STYLE( deva_dflt, DEVA_DFLT,
          AF_BLUE_STRINGSET_DEVA,
          AF_COVERAGE_DEFAULT )
 
+  STYLE( ethi_dflt, ETHI_DFLT,
+         "Ethiopic default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_ETHI,
+         AF_BLUE_STRINGSET_ETHI,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( geor_dflt, GEOR_DFLT,
+         "Georgian (Mkhedruli) default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_GEOR,
+         AF_BLUE_STRINGSET_GEOR,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( geok_dflt, GEOK_DFLT,
+         "Georgian (Khutsuri) default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_GEOK,
+         AF_BLUE_STRINGSET_GEOK,
+         AF_COVERAGE_DEFAULT )
+
   META_STYLE_LATIN( grek, GREK, "Greek" )
 
+  STYLE( gujr_dflt, GUJR_DFLT,
+         "Gujarati default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_GUJR,
+         AF_BLUE_STRINGSET_GUJR,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( guru_dflt, GURU_DFLT,
+         "Gurmukhi default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_GURU,
+         AF_BLUE_STRINGSET_GURU,
+         AF_COVERAGE_DEFAULT )
+
   STYLE( hebr_dflt, HEBR_DFLT,
          "Hebrew default style",
          AF_WRITING_SYSTEM_LATIN,
          AF_COVERAGE_DEFAULT )
 #endif
 
+  STYLE( mlym_dflt, MLYM_DFLT,
+         "Malayalam default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_MLYM,
+         AF_BLUE_STRINGSET_MLYM,
+         AF_COVERAGE_DEFAULT )
+
   STYLE( mymr_dflt, MYMR_DFLT,
          "Myanmar default style",
          AF_WRITING_SYSTEM_LATIN,
          "no style",
          AF_WRITING_SYSTEM_DUMMY,
          AF_SCRIPT_NONE,
-         (AF_Blue_Stringset)0,
+         AF_BLUE_STRINGSET_NONE,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( sinh_dflt, SINH_DFLT,
+         "Sinhala default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_SINH,
+         AF_BLUE_STRINGSET_SINH,
+         AF_COVERAGE_DEFAULT )
+
+  STYLE( taml_dflt, TAML_DFLT,
+         "Tamil default style",
+         AF_WRITING_SYSTEM_LATIN,
+         AF_SCRIPT_TAML,
+         AF_BLUE_STRINGSET_TAML,
          AF_COVERAGE_DEFAULT )
 
   STYLE( telu_dflt, TELU_DFLT,
                  (AF_Blue_Stringset)0,    \
                  AF_COVERAGE_DEFAULT )
 
-  STYLE_DEFAULT_INDIC( gujr, GUJR, "Gujarati" )
-  STYLE_DEFAULT_INDIC( guru, GURU, "Gurmukhi" )
   STYLE_DEFAULT_INDIC( limb, LIMB, "Limbu" )
-  STYLE_DEFAULT_INDIC( mlym, MLYM, "Malayalam" )
   STYLE_DEFAULT_INDIC( orya, ORYA, "Oriya" )
-  STYLE_DEFAULT_INDIC( sinh, SINH, "Sinhala" )
   STYLE_DEFAULT_INDIC( sund, SUND, "Sundanese" )
   STYLE_DEFAULT_INDIC( sylo, SYLO, "Syloti Nagri" )
-  STYLE_DEFAULT_INDIC( taml, TAML, "Tamil" )
   STYLE_DEFAULT_INDIC( tibt, TIBT, "Tibetan" )
 
 #endif /* AF_CONFIG_OPTION_INDIC */
index eae6e11..ef62043 100644 (file)
@@ -22,7 +22,7 @@
    *  Its main feature is the ability to differentiate between different
    *  writing systems and scripts in order to apply specific rules.
    *
-   *  The code has also been compartmentized into several entities that
+   *  The code has also been compartmentalized into several entities that
    *  should make algorithmic experimentation easier than with the old
    *  code.
    *
index 2bfbe8a..9e2ab89 100644 (file)
 
       /* scale from 26.6 to 16.16 */
       padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
-                      ? face->glyph->advance.y << 10
-                      : face->glyph->advance.x << 10;
+                      ? face->glyph->advance.y * 1024
+                      : face->glyph->advance.x * 1024;
     }
 
     return error;
index 7f0d9a6..f0a6aff 100644 (file)
     }
 
     /* for each row */
-    for ( y = 0; y < bitmap->rows ; y++ )
+    for ( y = 0; y < bitmap->rows; y++ )
     {
       /*
        * Horizontally:
index 5cfa012..e97fdbf 100644 (file)
 
 
     if ( !fontName || !face_index )
-      return FT_THROW( Invalid_Argument) ;
+      return FT_THROW( Invalid_Argument);
 
     err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
     if ( err )
index fa05347..c2dc618 100644 (file)
 
   /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */
   /* format too.  Here, since we can't expect that the TrueType font */
-  /* driver is loaded unconditially, we must parse the font by       */
+  /* driver is loaded unconditionally, we must parse the font by     */
   /* ourselves.  We are only interested in the name of the table and */
   /* the offset.                                                     */
 
       if ( face_index >= 0 && pstable_index == face_index )
         return FT_Err_Ok;
     }
+
     return FT_THROW( Table_Missing );
   }
 
     if ( error )
       goto Exit;
 
+    if ( offset > stream->size )
+    {
+      FT_TRACE2(( "open_face_PS_from_sfnt_stream: invalid table offset\n" ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+    else if ( length > stream->size - offset )
+    {
+      FT_TRACE2(( "open_face_PS_from_sfnt_stream: invalid table length\n" ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
     error = FT_Stream_Seek( stream, pos + offset );
     if ( error )
       goto Exit;
       goto Exit;
 
     error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
-    if ( error ) {
+    if ( error )
+    {
       FT_FREE( sfnt_ps );
       goto Exit;
     }
     FT_Long    face_index_in_resource = 0;
 
 
-    if ( face_index == -1 )
-      face_index = 0;
+    if ( face_index < 0 )
+      face_index = -face_index - 1;
     if ( face_index >= resource_cnt )
       return FT_THROW( Cannot_Open_Resource );
 
   {
     FT_Error   error;
     FT_Memory  memory;
-    FT_Module  module;
+    FT_Module  module = NULL;
     FT_UInt    nn;
 
 
index fa2d2cf..fc28225 100644 (file)
@@ -42,7 +42,7 @@
 
 
   static
-  const FT_Outline  null_outline = { 0, 0, 0, 0, 0, 0 };
+  const FT_Outline  null_outline = { 0, 0, NULL, NULL, NULL, 0 };
 
 
   /* documentation is in ftoutln.h */
index 4d3de46..4660c97 100644 (file)
         errors[i] = FT_Err_Ok;
 
       if ( errors[i] )
-        continue ;
+        continue;
 
       errors[i] = (FT_RACCESS_GUESS_TABLE_GET[i].func)( library,
                                                  stream, base_name,
index 8b5bad8..bb512a7 100644 (file)
 
       case ft_frame_short_be:
       case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
-        value = FT_NEXT_USHORT( cursor;
+        value = FT_NEXT_USHORT( cursor );
         sign_shift = 16;
         break;
 
index 52d96ac..b235e17 100644 (file)
        (a) += (b);
 
 /*
- * SET reads 4 input bytes in little-endian byte order and stores them
- * in a properly aligned word in host byte order.
+ * 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
- * doesn't work.
+ * 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) \
@@ -87,8 +94,8 @@
 #endif
 
 /*
- * This processes one or more 64-byte data blocks, but does NOT update
- * the bit counters.  There are no alignment requirements.
+ * 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)
 {
@@ -242,6 +249,12 @@ void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
        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;
@@ -262,33 +275,15 @@ void MD5_Final(unsigned char *result, MD5_CTX *ctx)
        memset(&ctx->buffer[used], 0, available - 8);
 
        ctx->lo <<= 3;
-       ctx->buffer[56] = ctx->lo;
-       ctx->buffer[57] = ctx->lo >> 8;
-       ctx->buffer[58] = ctx->lo >> 16;
-       ctx->buffer[59] = ctx->lo >> 24;
-       ctx->buffer[60] = ctx->hi;
-       ctx->buffer[61] = ctx->hi >> 8;
-       ctx->buffer[62] = ctx->hi >> 16;
-       ctx->buffer[63] = ctx->hi >> 24;
+       OUT(&ctx->buffer[56], ctx->lo)
+       OUT(&ctx->buffer[60], ctx->hi)
 
        body(ctx, ctx->buffer, 64);
 
-       result[0] = ctx->a;
-       result[1] = ctx->a >> 8;
-       result[2] = ctx->a >> 16;
-       result[3] = ctx->a >> 24;
-       result[4] = ctx->b;
-       result[5] = ctx->b >> 8;
-       result[6] = ctx->b >> 16;
-       result[7] = ctx->b >> 24;
-       result[8] = ctx->c;
-       result[9] = ctx->c >> 8;
-       result[10] = ctx->c >> 16;
-       result[11] = ctx->c >> 24;
-       result[12] = ctx->d;
-       result[13] = ctx->d >> 8;
-       result[14] = ctx->d >> 16;
-       result[15] = ctx->d >> 24;
+       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));
 }
index 4baa9ca..e1dce95 100644 (file)
       propid = ft_hash_str_lookup( name, &(font->proptbl) );
     }
 
-    /* Allocate another property if this is overflow. */
+    /* Allocate another property if this is overflowing. */
     if ( font->props_used == font->props_size )
     {
       if ( font->props_size == 0 )
       error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
       if ( error )
         goto Exit;
+
       /* at this point, `p->font' can't be NULL */
       p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1] );
+      /* We need at least 4 bytes per property. */
+      if ( p->cnt > p->size / 4 )
+      {
+        p->font->props_size = 0;
+
+        FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG5, lineno, "STARTPROPERTIES" ));
+        error = FT_THROW( Invalid_Argument );
+        goto Exit;
+      }
 
       if ( FT_NEW_ARRAY( p->font->props, p->cnt ) )
       {
index efe830d..1b12959 100644 (file)
@@ -325,7 +325,7 @@ FT_BEGIN_HEADER
         break;                                                    \
                                                                   \
       _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
-      if ( _try_done > 0 && ( list_changed ) )                    \
+      if ( _try_done > 0 && ( list_changed != NULL ) )            \
         *(FT_Bool*)( list_changed ) = TRUE;                       \
                                                                   \
       if ( _try_done == 0 )                                       \
index 52fb3c7..41a0ce9 100644 (file)
       return 0;
     }
 
-    if ( !face_id )
-      return 0;
-
     query.face_id    = face_id;
     query.cmap_index = (FT_UInt)cmap_index;
     query.char_code  = char_code;
index 1f44d80..661a32a 100644 (file)
     FTC_MruNode  mrunode;
 
 
-    if ( !aface || !face_id )
+    if ( !aface )
       return FT_THROW( Invalid_Argument );
 
     *aface = NULL;
     FT_UInt  nn;
 
 
-    if ( !manager || !face_id )
+    if ( !manager )
       return;
 
     /* this will remove all FTC_SizeNode that correspond to
index ea78a32..ae3c4ce 100644 (file)
@@ -185,7 +185,7 @@ FT_BEGIN_HEADER
         }                                                                   \
         _node = _node->next;                                                \
                                                                             \
-      } while ( _node != _first) ;                                          \
+      } while ( _node != _first)                                          \
     }                                                                       \
                                                                             \
     error = FTC_MruList_New( (list), (key), (FTC_MruNode*)(void*)&(node) ); \
index d9f8c66..512edd1 100644 (file)
@@ -70,7 +70,7 @@ FT_BEGIN_HEADER
    * Upon a function call if the error code is anything other than
    * `FT_Err_Ok', which is guaranteed to be zero, we
    * will return without altering that error.  This will allow the
-   * error to propogate and be handled at the appropriate location in
+   * error to propagate and be handled at the appropriate location in
    * the code.
    *
    * This allows a style of code where the error code is initialized
index 290f570..a898454 100644 (file)
@@ -220,7 +220,7 @@ FT_BEGIN_HEADER
 
     /* character space miter limit threshold */
     CF2_Fixed  miterLimit;
-    /* vertical/horzizontal snap distance in character space */
+    /* vertical/horizontal snap distance in character space */
     CF2_Fixed  snapThreshold;
 
     FT_Vector  offsetStart0;  /* first and second points of first */
index 7a82094..950a960 100644 (file)
       FT_UInt*  hinting_engine = (FT_UInt*)value;
 
 
-#ifndef CFF_CONFIG_OPTION_OLD_ENGINE
-      if ( *hinting_engine != FT_CFF_HINTING_ADOBE )
-        error = FT_ERR( Unimplemented_Feature );
-      else
+      if ( *hinting_engine == FT_CFF_HINTING_ADOBE
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+           || *hinting_engine == FT_CFF_HINTING_FREETYPE
 #endif
+         )
         driver->hinting_engine = *hinting_engine;
+      else
+        error = FT_ERR( Unimplemented_Feature );
 
       return error;
     }
index df57d67..752c18e 100644 (file)
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
     {
-      CFF_Font  cff  = (CFF_Font)(face->extra.data);
+      CFF_Font  cff = (CFF_Font)(face->extra.data);
 
 
       return cff_index_access_element( &cff->charstrings_index, glyph_index,
       /* the seac operator must not be nested */
       decoder->seac = TRUE;
       error = cff_decoder_parse_charstrings( decoder, charstring,
-                                             charstring_len );
+                                             charstring_len, 0 );
       decoder->seac = FALSE;
 
       cff_free_glyph_data( face, &charstring, charstring_len );
       /* the seac operator must not be nested */
       decoder->seac = TRUE;
       error = cff_decoder_parse_charstrings( decoder, charstring,
-                                             charstring_len );
+                                             charstring_len, 0 );
       decoder->seac = FALSE;
 
       cff_free_glyph_data( face, &charstring, charstring_len );
   /*                                                                       */
   /*    charstring_len  :: The length in bytes of the charstring stream.   */
   /*                                                                       */
+  /*    in_dict         :: Set to 1 if function is called from top or      */
+  /*                       private DICT (needed for Multiple Master CFFs). */
+  /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
   cff_decoder_parse_charstrings( CFF_Decoder*  decoder,
                                  FT_Byte*      charstring_base,
-                                 FT_ULong      charstring_len )
+                                 FT_ULong      charstring_len,
+                                 FT_Bool       in_dict )
   {
     FT_Error           error;
     CFF_Decoder_Zone*  zone;
     FT_Fixed*          stack;
     FT_Int             charstring_type =
                          decoder->cff->top_font.font_dict.charstring_type;
+    FT_UShort          num_designs =
+                         decoder->cff->top_font.font_dict.num_designs;
+    FT_UShort          num_axes =
+                         decoder->cff->top_font.font_dict.num_axes;
 
     T2_Hints_Funcs     hinter;
 
         if ( op == cff_op_unknown )
           continue;
 
+        /* in Multiple Master CFFs, T2 charstrings can appear in */
+        /* dictionaries, but some operators are prohibited       */
+        if ( in_dict )
+        {
+          switch ( op )
+          {
+          case cff_op_hstem:
+          case cff_op_vstem:
+          case cff_op_vmoveto:
+          case cff_op_rlineto:
+          case cff_op_hlineto:
+          case cff_op_vlineto:
+          case cff_op_rrcurveto:
+          case cff_op_hstemhm:
+          case cff_op_hintmask:
+          case cff_op_cntrmask:
+          case cff_op_rmoveto:
+          case cff_op_hmoveto:
+          case cff_op_vstemhm:
+          case cff_op_rcurveline:
+          case cff_op_rlinecurve:
+          case cff_op_vvcurveto:
+          case cff_op_hhcurveto:
+          case cff_op_vhcurveto:
+          case cff_op_hvcurveto:
+          case cff_op_hflex:
+          case cff_op_flex:
+          case cff_op_hflex1:
+          case cff_op_flex1:
+          case cff_op_callsubr:
+          case cff_op_callgsubr:
+            goto MM_Error;
+
+          default:
+            break;
+          }
+        }
+
         /* check arguments */
         req_args = cff_argument_counts[op];
         if ( req_args & CFF_COUNT_CHECK_WIDTH )
             case cff_op_endchar:
               /* If there is a width specified for endchar, we either have */
               /* 1 argument or 5 arguments.  We like to argue.             */
-              set_width_ok = ( num_args == 5 ) || ( num_args == 1 );
+              set_width_ok = in_dict
+                               ? 0
+                               : ( ( num_args == 5 ) || ( num_args == 1 ) );
               break;
 
             default:
             return error;
 
         case cff_op_endchar:
+          /* in dictionaries, `endchar' simply indicates end of data */
+          if ( in_dict )
+            return error;
+
           FT_TRACE4(( " endchar\n" ));
 
           /* We are going to emulate the seac operator. */
 
             FT_TRACE4(( " put\n" ));
 
+            /* the Type2 specification before version 16-March-2000 */
+            /* didn't give a hard-coded size limit of the temporary */
+            /* storage array; instead, an argument of the           */
+            /* `MultipleMaster' operator set the size               */
             if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
               decoder->buildchar[idx] = val;
           }
         case cff_op_store:
           /* this operator was removed from the Type2 specification */
           /* in version 16-March-2000                               */
-          FT_TRACE4(( " store\n"));
 
-          goto Unimplemented;
+          /* since we currently don't handle interpolation of multiple */
+          /* master fonts, this is a no-op                             */
+          FT_TRACE4(( " store\n"));
+          break;
 
         case cff_op_load:
           /* this operator was removed from the Type2 specification */
           /* in version 16-March-2000                               */
-          FT_TRACE4(( " load\n" ));
+          {
+            FT_Int  reg_idx = (FT_Int)args[0];
+            FT_Int  idx     = (FT_Int)args[1];
+            FT_Int  count   = (FT_Int)args[2];
+
+
+            FT_TRACE4(( " load\n" ));
+
+            /* since we currently don't handle interpolation of multiple */
+            /* master fonts, we store a vector [1 0 0 ...] in the        */
+            /* temporary storage array regardless of the Registry index  */
+            if ( reg_idx >= 0 && reg_idx <= 2             &&
+                 idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS &&
+                 count >= 0 && count <= num_axes          )
+            {
+              FT_Int  end, i;
+
 
-          goto Unimplemented;
+              end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS );
+
+              if ( idx < end )
+                decoder->buildchar[idx] = 1 << 16;
+
+              for ( i = idx + 1; i < end; i++ )
+                decoder->buildchar[i] = 0;
+            }
+          }
+          break;
 
         case cff_op_blend:
           /* this operator was removed from the Type2 specification */
           /* in version 16-March-2000                               */
-          FT_TRACE4(( " blend\n" ));
+          {
+            FT_Int  num_results = (FT_Int)( args[0] >> 16 );
+
+
+            FT_TRACE4(( " blend\n" ));
+
+            if ( num_results < 0 )
+              goto Syntax_Error;
+
+            if ( num_results * (FT_Int)num_designs > num_args )
+              goto Stack_Underflow;
 
-          goto Unimplemented;
+            /* since we currently don't handle interpolation of multiple */
+            /* master fonts, return the `num_results' values of the      */
+            /* first master                                              */
+            args     -= num_results * ( num_designs - 1 );
+            num_args -= num_results * ( num_designs - 1 );
+          }
+          break;
 
         case cff_op_dotsection:
           /* this operator is deprecated and ignored by the parser */
           break;
 
         default:
-        Unimplemented:
           FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
 
           if ( ip[-1] == 12 )
   Fail:
     return error;
 
+  MM_Error:
+    FT_TRACE4(( "cff_decoder_parse_charstrings:"
+                " invalid opcode found in top DICT charstring\n"));
+    return FT_THROW( Invalid_File_Format );
+
   Syntax_Error:
     FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
     return FT_THROW( Invalid_File_Format );
         if ( !error )
           error = cff_decoder_parse_charstrings( &decoder,
                                                  charstring,
-                                                 charstring_len );
+                                                 charstring_len,
+                                                 0 );
 
         cff_free_glyph_data( face, &charstring, &charstring_len );
       }
       if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
         error = cff_decoder_parse_charstrings( &decoder,
                                                charstring,
-                                               charstring_len );
+                                               charstring_len,
+                                               0 );
       else
 #endif
       {
index 2257307..b875fbe 100644 (file)
@@ -227,7 +227,8 @@ FT_BEGIN_HEADER
   FT_LOCAL( FT_Error )
   cff_decoder_parse_charstrings( CFF_Decoder*  decoder,
                                  FT_Byte*      charstring_base,
-                                 FT_ULong      charstring_len );
+                                 FT_ULong      charstring_len,
+                                 FT_Bool       in_dict );
 #endif
 
   FT_LOCAL( FT_Error )
index 42cc37e..3d1bda9 100644 (file)
   static FT_Error
   cff_index_get_pointers( CFF_Index   idx,
                           FT_Byte***  table,
-                          FT_Byte**   pool )
+                          FT_Byte**   pool,
+                          FT_ULong*   pool_size )
   {
     FT_Error   error     = FT_Err_Ok;
     FT_Memory  memory    = idx->stream->memory;
 
     FT_Byte**  t         = NULL;
     FT_Byte*   new_bytes = NULL;
+    FT_ULong   new_size;
 
 
     *table = NULL;
         goto Exit;
     }
 
-    if ( idx->count > 0                                        &&
-         !FT_NEW_ARRAY( t, idx->count + 1 )                    &&
-         ( !pool || !FT_ALLOC( new_bytes,
-                               idx->data_size + idx->count ) ) )
+    new_size = idx->data_size + idx->count;
+
+    if ( idx->count > 0                                &&
+         !FT_NEW_ARRAY( t, idx->count + 1 )            &&
+         ( !pool || !FT_ALLOC( new_bytes, new_size ) ) )
     {
       FT_ULong  n, cur_offset;
       FT_ULong  extra = 0;
 
       if ( pool )
         *pool = new_bytes;
+      if ( pool_size )
+        *pool_size = new_size;
     }
 
   Exit:
     /* When multiple GIDs map to the same CID, we choose the lowest */
     /* GID.  This is not described in any spec, but it matches the  */
     /* behaviour of recent Acroread versions.                       */
-    for ( j = (FT_Long)num_glyphs - 1; j >= 0 ; j-- )
+    for ( j = (FT_Long)num_glyphs - 1; j >= 0; j-- )
       charset->cids[charset->sids[j]] = (FT_UShort)j;
 
     charset->max_cid    = max_cid;
     FT_UShort  glyph_sid;
 
 
-    /* If the the offset is greater than 2, we have to parse the */
-    /* charset table.                                            */
+    /* If the offset is greater than 2, we have to parse the charset */
+    /* table.                                                        */
     if ( offset > 2 )
     {
       FT_UInt  j;
     CFF_Private      priv = &font->private_dict;
 
 
-    cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );
+    cff_parser_init( &parser,
+                     CFF_CODE_TOPDICT,
+                     &font->font_dict,
+                     library,
+                     0,
+                     0 );
 
     /* set defaults */
     FT_MEM_ZERO( top, sizeof ( *top ) );
       priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
       priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
 
-      cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );
+      cff_parser_init( &parser,
+                       CFF_CODE_PRIVATE,
+                       priv,
+                       library,
+                       top->num_designs,
+                       top->num_axes );
 
       if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
            FT_FRAME_ENTER( font->font_dict.private_size )                 )
         goto Exit;
 
       error = cff_index_get_pointers( &font->local_subrs_index,
-                                      &font->local_subrs, NULL );
+                                      &font->local_subrs, NULL, NULL );
       if ( error )
         goto Exit;
     }
 
     /* read the name, top dict, string and global subrs index */
     if ( FT_SET_ERROR( cff_index_init( &font->name_index,
-                                       stream, 0 ) )                  ||
+                                       stream, 0 ) )                       ||
          FT_SET_ERROR( cff_index_init( &font->font_dict_index,
-                                       stream, 0 ) )                  ||
+                                       stream, 0 ) )                       ||
          FT_SET_ERROR( cff_index_init( &string_index,
-                                       stream, 1 ) )                  ||
+                                       stream, 1 ) )                       ||
          FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
-                                       stream, 1 ) )                  ||
+                                       stream, 1 ) )                       ||
          FT_SET_ERROR( cff_index_get_pointers( &string_index,
                                                &font->strings,
-                                               &font->string_pool ) ) )
+                                               &font->string_pool,
+                                               &font->string_pool_size ) ) )
       goto Exit;
 
     font->num_strings = string_index.count;
     font->num_glyphs = font->charstrings_index.count;
 
     error = cff_index_get_pointers( &font->global_subrs_index,
-                                    &font->global_subrs, NULL );
+                                    &font->global_subrs, NULL, NULL );
 
     if ( error )
       goto Exit;
index e22ae82..0f07696 100644 (file)
         FT_TRACE4(( "SIDs\n" ));
 
         /* dump string index, including default strings for convenience */
-        for ( idx = 0; idx < cff->num_strings + 390; idx++ )
+        for ( idx = 0; idx <= 390; idx++ )
         {
           s = cff_index_get_sid_string( cff, idx );
           if ( s )
-            FT_TRACE4(("  %5d %s\n", idx, s ));
+            FT_TRACE4(( "  %5d %s\n", idx, s ));
+        }
+
+        /* In Multiple Master CFFs, two SIDs hold the Normalize Design  */
+        /* Vector (NDV) and Convert Design Vector (CDV) charstrings,    */
+        /* which may contain NULL bytes in the middle of the data, too. */
+        /* We thus access `cff->strings' directly.                      */
+        for ( idx = 1; idx < cff->num_strings; idx++ )
+        {
+          FT_Byte*    s1    = cff->strings[idx - 1];
+          FT_Byte*    s2    = cff->strings[idx];
+          FT_PtrDist  s1len = s2 - s1 - 1; /* without the final NULL byte */
+          FT_PtrDist  l;
+
+
+          FT_TRACE4(( "  %5d ", idx + 390 ));
+          for ( l = 0; l < s1len; l++ )
+            FT_TRACE4(( "%c", s1[l] ));
+          FT_TRACE4(( "\n" ));
+        }
+
+        /* print last element */
+        if ( cff->num_strings )
+        {
+          FT_Byte*    s1    = cff->strings[cff->num_strings - 1];
+          FT_Byte*    s2    = cff->string_pool + cff->string_pool_size;
+          FT_PtrDist  s1len = s2 - s1 - 1;
+          FT_PtrDist  l;
+
+
+          FT_TRACE4(( "  %5d ", cff->num_strings + 390 ));
+          for ( l = 0; l < s1len; l++ )
+            FT_TRACE4(( "%c", s1[l] ));
+          FT_TRACE4(( "\n" ));
         }
       }
 #endif /* FT_DEBUG_LEVEL_TRACE */
       if ( !dict->has_font_matrix )
         dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
 
-      /* Normalize the font matrix so that `matrix->yy' is 1; the */
-      /* scaling is done with `units_per_em' then (at this point, */
-      /* it already contains the scaling factor, but without      */
-      /* normalization of the matrix).                            */
+      /* Normalize the font matrix so that `matrix->yy' is 1; if  */
+      /* it is zero, we use `matrix->yx' instead.  The scaling is */
+      /* done with `units_per_em' then (at this point, it already */
+      /* contains the scaling factor, but without normalization   */
+      /* of the matrix).                                          */
       /*                                                          */
       /* Note that the offsets must be expressed in integer font  */
       /* units.                                                   */
         FT_Matrix*  matrix = &dict->font_matrix;
         FT_Vector*  offset = &dict->font_offset;
         FT_ULong*   upm    = &dict->units_per_em;
-        FT_Fixed    temp   = FT_ABS( matrix->yy );
+        FT_Fixed    temp;
 
 
+        temp = matrix->yy ? FT_ABS( matrix->yy )
+                          : FT_ABS( matrix->yx );
+
         if ( temp != 0x10000L )
         {
           *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
         matrix = &sub->font_matrix;
         offset = &sub->font_offset;
         upm    = &sub->units_per_em;
-        temp   = FT_ABS( matrix->yy );
+
+        temp = matrix->yy ? FT_ABS( matrix->yy )
+                          : FT_ABS( matrix->yx );
+
 
         if ( temp != 0x10000L )
         {
index acbdc5a..a4f986b 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "cfferrs.h"
 #include "cffpic.h"
+#include "cffgload.h"
 
 
   /*************************************************************************/
@@ -39,7 +40,9 @@
   cff_parser_init( CFF_Parser  parser,
                    FT_UInt     code,
                    void*       object,
-                   FT_Library  library)
+                   FT_Library  library,
+                   FT_UShort   num_designs,
+                   FT_UShort   num_axes )
   {
     FT_MEM_ZERO( parser, sizeof ( *parser ) );
 
@@ -47,6 +50,8 @@
     parser->object_code = code;
     parser->object      = object;
     parser->library     = library;
+    parser->num_designs = num_designs;
+    parser->num_axes    = num_axes;
   }
 
 
 
     if ( parser->top >= parser->stack + 6 )
     {
-      FT_Long  scaling;
+      FT_Fixed  values[6];
+      FT_Long   scalings[6];
+
+      FT_Long  min_scaling, max_scaling;
+      int      i;
 
 
       error = FT_Err_Ok;
 
       /* We expect a well-formed font matrix, this is, the matrix elements */
       /* `xx' and `yy' are of approximately the same magnitude.  To avoid  */
-      /* loss of precision, we use the magnitude of element `xx' to scale  */
-      /* all other elements.  The scaling factor is then contained in the  */
-      /* `units_per_em' value.                                             */
+      /* loss of precision, we use the magnitude of the largest matrix     */
+      /* element to scale all other elements.  The scaling factor is then  */
+      /* contained in the `units_per_em' value.                            */
 
-      matrix->xx = cff_parse_fixed_dynamic( data++, &scaling );
+      max_scaling = FT_LONG_MIN;
+      min_scaling = FT_LONG_MAX;
 
-      scaling = -scaling;
+      for ( i = 0; i < 6; i++ )
+      {
+        values[i] = cff_parse_fixed_dynamic( data++, &scalings[i] );
+        if ( values[i] )
+        {
+          if ( scalings[i] > max_scaling )
+            max_scaling = scalings[i];
+          if ( scalings[i] < min_scaling )
+            min_scaling = scalings[i];
+        }
+      }
 
-      if ( scaling < 0 || scaling > 9 )
+      if ( max_scaling < -9                  ||
+           max_scaling > 0                   ||
+           ( max_scaling - min_scaling ) < 0 ||
+           ( max_scaling - min_scaling ) > 9 )
       {
         /* Return default matrix in case of unlikely values. */
 
         FT_TRACE1(( "cff_parse_font_matrix:"
-                    " strange scaling value for xx element (%d),\n"
+                    " strange scaling values (minimum %d, maximum %d),\n"
                     "                      "
-                    " using default matrix\n", scaling ));
+                    " using default matrix\n", min_scaling, max_scaling ));
 
         matrix->xx = 0x10000L;
         matrix->yx = 0;
         goto Exit;
       }
 
-      matrix->yx = cff_parse_fixed_scaled( data++, scaling );
-      matrix->xy = cff_parse_fixed_scaled( data++, scaling );
-      matrix->yy = cff_parse_fixed_scaled( data++, scaling );
-      offset->x  = cff_parse_fixed_scaled( data++, scaling );
-      offset->y  = cff_parse_fixed_scaled( data,   scaling );
+      for ( i = 0; i < 6; i++ )
+      {
+        FT_Fixed  value = values[i];
+        FT_Long   divisor, half_divisor;
+
+
+        if ( !value )
+          continue;
+
+        divisor      = power_tens[max_scaling - scalings[i]];
+        half_divisor = divisor >> 1;
+
+        if ( value < 0 )
+        {
+          if ( FT_LONG_MIN + half_divisor < value )
+            values[i] = ( value - half_divisor ) / divisor;
+          else
+            values[i] = FT_LONG_MIN / divisor;
+        }
+        else
+        {
+          if ( FT_LONG_MAX - half_divisor > value )
+            values[i] = ( value + half_divisor ) / divisor;
+          else
+            values[i] = FT_LONG_MAX / divisor;
+        }
+      }
+
+      matrix->xx = values[0];
+      matrix->yx = values[1];
+      matrix->xy = values[2];
+      matrix->yy = values[3];
+      offset->x  = values[4];
+      offset->y  = values[5];
 
-      *upm = (FT_ULong)power_tens[scaling];
+      *upm = (FT_ULong)power_tens[-max_scaling];
 
       FT_TRACE4(( " [%f %f %f %f %f %f]\n",
                   (double)matrix->xx / *upm / 65536,
   }
 
 
+  /* The `MultipleMaster' operator comes before any  */
+  /* top DICT operators that contain T2 charstrings. */
+
+  static FT_Error
+  cff_parse_multiple_master( CFF_Parser  parser )
+  {
+    CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
+    FT_Error         error;
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+    /* beautify tracing message */
+    if ( ft_trace_levels[FT_COMPONENT] < 4 )
+      FT_TRACE1(( "Multiple Master CFFs not supported yet,"
+                  " handling first master design only\n" ));
+    else
+      FT_TRACE1(( " (not supported yet,"
+                  " handling first master design only)\n" ));
+#endif
+
+    error = FT_ERR( Stack_Underflow );
+
+    /* currently, we handle only the first argument */
+    if ( parser->top >= parser->stack + 5 )
+    {
+      FT_Long  num_designs = cff_parse_num( parser->stack );
+
+
+      if ( num_designs > 16 || num_designs < 2 )
+      {
+        FT_ERROR(( "cff_parse_multiple_master:"
+                   " Invalid number of designs\n" ));
+        error = FT_THROW( Invalid_File_Format );
+      }
+      else
+      {
+        dict->num_designs   = (FT_UShort)num_designs;
+        dict->num_axes      = (FT_UShort)( parser->top - parser->stack - 4 );
+
+        parser->num_designs = dict->num_designs;
+        parser->num_axes    = dict->num_axes;
+
+        error = FT_Err_Ok;
+      }
+    }
+
+    return error;
+  }
+
+
   static FT_Error
   cff_parse_cid_ros( CFF_Parser  parser )
   {
         if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
           goto Stack_Overflow;
 
-        *parser->top ++ = p;
+        *parser->top++ = p;
 
         /* now, skip it */
         if ( v == 30 )
         else if ( v > 246 )
           p += 1;
       }
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+      else if ( v == 31 )
+      {
+        /* a Type 2 charstring */
+
+        CFF_Decoder  decoder;
+        CFF_FontRec  cff_rec;
+        FT_Byte*     charstring_base;
+        FT_ULong     charstring_len;
+
+        FT_Fixed*  stack;
+        FT_Byte*   q;
+
+
+        charstring_base = ++p;
+
+        /* search `endchar' operator */
+        for (;;)
+        {
+          if ( p >= limit )
+            goto Exit;
+          if ( *p == 14 )
+            break;
+          p++;
+        }
+
+        charstring_len = (FT_ULong)( p - charstring_base ) + 1;
+
+        /* construct CFF_Decoder object */
+        FT_MEM_ZERO( &decoder, sizeof ( decoder ) );
+        FT_MEM_ZERO( &cff_rec, sizeof ( cff_rec ) );
+
+        cff_rec.top_font.font_dict.num_designs = parser->num_designs;
+        cff_rec.top_font.font_dict.num_axes    = parser->num_axes;
+        decoder.cff                            = &cff_rec;
+
+        error = cff_decoder_parse_charstrings( &decoder,
+                                               charstring_base,
+                                               charstring_len,
+                                               1 );
+
+        /* Now copy the stack data in the temporary decoder object,    */
+        /* converting it back to charstring number representations     */
+        /* (this is ugly, I know).                                     */
+        /*                                                             */
+        /* We overwrite the original top DICT charstring under the     */
+        /* assumption that the charstring representation of the result */
+        /* of `cff_decoder_parse_charstrings' is shorter, which should */
+        /* be always true.                                             */
+
+        q     = charstring_base - 1;
+        stack = decoder.stack;
+
+        while ( stack < decoder.top )
+        {
+          FT_ULong  num;
+          FT_Bool   neg;
+
+
+          if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
+            goto Stack_Overflow;
+
+          *parser->top++ = q;
+
+          if ( *stack < 0 )
+          {
+            num = (FT_ULong)-*stack;
+            neg = 1;
+          }
+          else
+          {
+            num = (FT_ULong)*stack;
+            neg = 0;
+          }
+
+          if ( num & 0xFFFFU )
+          {
+            if ( neg )
+              num = (FT_ULong)-num;
+
+            *q++ = 255;
+            *q++ = ( num & 0xFF000000U ) >> 24;
+            *q++ = ( num & 0x00FF0000U ) >> 16;
+            *q++ = ( num & 0x0000FF00U ) >>  8;
+            *q++ =   num & 0x000000FFU;
+          }
+          else
+          {
+            num >>= 16;
+
+            if ( neg )
+            {
+              if ( num <= 107 )
+                *q++ = (FT_Byte)( 139 - num );
+              else if ( num <= 1131 )
+              {
+                *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 251 );
+                *q++ = (FT_Byte)( ( num - 108 ) & 0xFF );
+              }
+              else
+              {
+                num = (FT_ULong)-num;
+
+                *q++ = 28;
+                *q++ = (FT_Byte)( num >> 8 );
+                *q++ = (FT_Byte)( num & 0xFF );
+              }
+            }
+            else
+            {
+              if ( num <= 107 )
+                *q++ = (FT_Byte)( num + 139 );
+              else if ( num <= 1131 )
+              {
+                *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 );
+                *q++ = (FT_Byte)( ( num - 108 ) & 0xFF );
+              }
+              else
+              {
+                *q++ = 28;
+                *q++ = (FT_Byte)( num >> 8 );
+                *q++ = (FT_Byte)( num & 0xFF );
+              }
+            }
+          }
+
+          stack++;
+        }
+      }
+#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
       else
       {
         /* This is not a number, hence it's an operator.  Compute its code */
index bb9425a..a95970e 100644 (file)
@@ -36,16 +36,19 @@ FT_BEGIN_HEADER
 
   typedef struct  CFF_ParserRec_
   {
-    FT_Library library;
-    FT_Byte*   start;
-    FT_Byte*   limit;
-    FT_Byte*   cursor;
+    FT_Library  library;
+    FT_Byte*    start;
+    FT_Byte*    limit;
+    FT_Byte*    cursor;
 
-    FT_Byte*   stack[CFF_MAX_STACK_DEPTH + 1];
-    FT_Byte**  top;
+    FT_Byte*    stack[CFF_MAX_STACK_DEPTH + 1];
+    FT_Byte**   top;
 
-    FT_UInt    object_code;
-    void*      object;
+    FT_UInt     object_code;
+    void*       object;
+
+    FT_UShort   num_designs; /* a copy of `CFF_FontRecDict->num_designs' */
+    FT_UShort   num_axes;    /* a copy of `CFF_FontRecDict->num_axes'    */
 
   } CFF_ParserRec, *CFF_Parser;
 
@@ -54,7 +57,9 @@ FT_BEGIN_HEADER
   cff_parser_init( CFF_Parser  parser,
                    FT_UInt     code,
                    void*       object,
-                   FT_Library  library);
+                   FT_Library  library,
+                   FT_UShort   num_designs,
+                   FT_UShort   num_axes );
 
   FT_LOCAL( FT_Error )
   cff_parser_run( CFF_Parser  parser,
index 44b6580..22637c7 100644 (file)
@@ -38,6 +38,9 @@
   CFF_FIELD_NUM     ( 13,    unique_id,           "UniqueID" )
   CFF_FIELD_CALLBACK( 5,     font_bbox,           "FontBBox" )
   CFF_FIELD_NUM     ( 0x108, stroke_width,        "StrokeWidth" )
+#if 0
+  CFF_FIELD_DELTA   ( 14,    xuid, 16,            "XUID" )
+#endif
   CFF_FIELD_NUM     ( 15,    charset_offset,      "charset" )
   CFF_FIELD_NUM     ( 16,    encoding_offset,     "Encoding" )
   CFF_FIELD_NUM     ( 17,    charstrings_offset,  "CharStrings" )
 #if 0
   CFF_FIELD_STRING  ( 0x116, base_font_name,      "BaseFontName" )
   CFF_FIELD_DELTA   ( 0x117, base_font_blend, 16, "BaseFontBlend" )
+#endif
+
+  /* the next two operators were removed from the Type2 specification */
+  /* in version 16-March-2000                                         */
   CFF_FIELD_CALLBACK( 0x118, multiple_master,     "MultipleMaster" )
-  CFF_FIELD_CALLBACK( 0x119, blend_axis_types,    "BlendAxisTypes" )
+#if 0
+  CFF_FIELD_CALLBACK( 0x11A, blend_axis_types,    "BlendAxisTypes" )
 #endif
 
   CFF_FIELD_CALLBACK( 0x11E, cid_ros,              "ROS" )
index 80f13fe..4426c7e 100644 (file)
@@ -145,6 +145,12 @@ FT_BEGIN_HEADER
     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;
+
   } CFF_FontRecDictRec, *CFF_FontRecDict;
 
 
@@ -250,6 +256,7 @@ FT_BEGIN_HEADER
     FT_UInt          num_strings;
     FT_Byte**        strings;
     FT_Byte*         string_pool;
+    FT_ULong         string_pool_size;
 
     CFF_SubFontRec   top_font;
     FT_UInt          num_subfonts;
index f1c39f6..73aca2a 100644 (file)
   /*************************************************************************/
 
 
+#define STARTDATA      "StartData"
+#define STARTDATA_LEN  ( sizeof ( STARTDATA ) - 1 )
+#define SFNTS          "/sfnts"
+#define SFNTS_LEN      ( sizeof ( SFNTS ) - 1 )
+
+
   FT_LOCAL_DEF( FT_Error )
   cid_parser_new( CID_Parser*    parser,
                   FT_Stream      stream,
     /* now, read the rest of the file until we find */
     /* `StartData' or `/sfnts'                      */
     {
-      FT_Byte   buffer[256 + 10];
-      FT_ULong  read_len = 256 + 10;
-      FT_Byte*  p        = buffer;
+      /*
+       * The algorithm is as follows (omitting the case with less than 256
+       * bytes to fill for simplicity).
+       *
+       * 1. Fill the buffer with 256 + STARTDATA_LEN bytes.
+       *
+       * 2. Search for the STARTDATA and SFNTS strings at positions
+       *    buffer[0], buffer[1], ...,
+       *    buffer[255 + STARTDATA_LEN - SFNTS_LEN].
+       *
+       * 3. Move the last STARTDATA_LEN bytes to buffer[0].
+       *
+       * 4. Fill the buffer with 256 bytes, starting at STARTDATA_LEN.
+       *
+       * 5. Repeat with step 2.
+       *
+       */
+      FT_Byte  buffer[256 + STARTDATA_LEN + 1];
+
+      /* values for the first loop */
+      FT_ULong  read_len    = 256 + STARTDATA_LEN;
+      FT_ULong  read_offset = 0;
+      FT_Byte*  p           = buffer;
 
 
       for ( offset = FT_STREAM_POS(); ; offset += 256 )
 
 
         stream_len = stream->size - FT_STREAM_POS();
-        if ( stream_len == 0 )
-        {
-          FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
-          error = FT_THROW( Invalid_File_Format );
-          goto Exit;
-        }
 
         read_len = FT_MIN( read_len, stream_len );
         if ( FT_STREAM_READ( p, read_len ) )
           goto Exit;
 
-        if ( read_len < 256 )
-          p[read_len]  = '\0';
+        /* ensure that we do not compare with data beyond the buffer */
+        p[read_len] = '\0';
 
-        limit = p + read_len - 10;
+        limit = p + read_len - SFNTS_LEN;
 
         for ( p = buffer; p < limit; p++ )
         {
-          if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 )
+          if ( p[0] == 'S'                                           &&
+               ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 )
           {
             /* save offset of binary data after `StartData' */
-            offset += (FT_ULong)( p - buffer + 10 );
+            offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN;
             goto Found;
           }
-          else if ( p[1] == 's' && ft_strncmp( (char*)p, "/sfnts", 6 ) == 0 )
+          else if ( p[1] == 's'                                   &&
+                    ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 )
           {
-            offset += (FT_ULong)( p - buffer + 7 );
+            offset += (FT_ULong)( p - buffer ) + SFNTS_LEN;
             goto Found;
           }
         }
 
-        FT_MEM_MOVE( buffer, p, 10 );
-        read_len = 256;
-        p = buffer + 10;
+        if ( read_offset + read_len < STARTDATA_LEN )
+        {
+          FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
+          error = FT_THROW( Invalid_File_Format );
+          goto Exit;
+        }
+
+        FT_MEM_MOVE( buffer,
+                     buffer + read_offset + read_len - STARTDATA_LEN,
+                     STARTDATA_LEN );
+
+        /* values for the next loop */
+        read_len    = 256;
+        read_offset = STARTDATA_LEN;
+        p           = buffer + read_offset;
       }
     }
 
     limit = parser->root.limit;
     cur   = parser->root.cursor;
 
-    while ( cur < limit )
+    while ( cur < limit - SFNTS_LEN )
     {
       if ( parser->root.error )
       {
         goto Exit;
       }
 
-      if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 )
+      if ( cur[0] == 'S'                                           &&
+           cur < limit - STARTDATA_LEN                             &&
+           ft_strncmp( (char*)cur, STARTDATA, STARTDATA_LEN ) == 0 )
       {
         if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 )
         {
 
         goto Exit;
       }
-      else if ( cur[1] == 's' && ft_strncmp( (char*)cur, "/sfnts", 6 ) == 0 )
+      else if ( cur[1] == 's'                                   &&
+                ft_strncmp( (char*)cur, SFNTS, SFNTS_LEN ) == 0 )
       {
         FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" ));
         error = FT_THROW( Unknown_File_Format );
   }
 
 
+#undef STARTDATA
+#undef STARTDATA_LEN
+#undef SFNTS
+#undef SFNTS_LEN
+
+
   FT_LOCAL_DEF( void )
   cid_parser_done( CID_Parser*  parser )
   {
index 2606e57..4b5e415 100644 (file)
     for ( i = 0; i < nnames; i++ )
     {
       if ( FT_Get_Sfnt_Name( gxvalid->face, i, &name ) != FT_Err_Ok )
-        continue ;
+        continue;
 
       if ( name.name_id == name_index )
         goto Out;
     if ( ( p + ( maxEntry + 1 ) * entrySize ) > limit )
       FT_INVALID_TOO_SHORT;
 
-    for (entry = 0; entry <= maxEntry ; entry++ )
+    for (entry = 0; entry <= maxEntry; entry++ )
     {
       FT_UShort                        newState_idx;
       FT_UShort                        flags;
index d49c4b4..9470c84 100644 (file)
@@ -338,7 +338,7 @@ FT_BEGIN_HEADER
                                                         \
                                                         \
               for ( b = p; b < (FT_Bytes)p + len; b++ ) \
-                FT_TRACE1(("\\x%02x", *b)) ;            \
+                FT_TRACE1(("\\x%02x", *b))            \
             }                                           \
           FT_END_STMNT
 
@@ -350,9 +350,9 @@ FT_BEGIN_HEADER
                                                         \
               for ( b = p; b < (FT_Bytes)p + len; b++ ) \
                 if ( 0x40 < *b && *b < 0x7E )           \
-                  FT_TRACE1(("%c", *b)) ;               \
+                  FT_TRACE1(("%c", *b))               \
                 else                                    \
-                  FT_TRACE1(("\\x%02x", *b)) ;          \
+                  FT_TRACE1(("\\x%02x", *b))          \
             }                                           \
           FT_END_STMNT
 
index fc8db0d..20d29bf 100644 (file)
                                         FT_Bytes       limit,
                                         GXV_Validator  gxvalid )
   {
-    FT_Bytes  p         = table ;
+    FT_Bytes  p         = table;
     FT_Bytes  wdc_end   = table + GXV_JUST_DATA( wdc_offset_max );
     FT_UInt   i;
 
index 97ff3bf..ee1ab36 100644 (file)
 
     GXV_NAME_ENTER( "validating coverage" );
 
-    GXV_TRACE(( "interprete coverage 0x%04x by Apple style\n", coverage ));
+    GXV_TRACE(( "interpret coverage 0x%04x by Apple style\n", coverage ));
 
     if ( KERN_IS_NEW( gxvalid ) )
     {
       }
     }
 
-    GXV_TRACE(( "cannot interprete coverage, broken kern subtable\n" ));
+    GXV_TRACE(( "cannot interpret coverage, broken kern subtable\n" ));
 
   Exit:
     GXV_EXIT;
index d600fa3..d31b641 100644 (file)
     +------ lcar --------------------+
     |                                |
     |      +===============+         |
-    |      | looup header  |         |
+    |      | lookup header |         |
     |      +===============+         |
     |      | BinSrchHeader |         |
     |      +===============+         |
index 24fed63..fd761d0 100644 (file)
 
 
     GXV_NAME_ENTER( "validating contents of substitutionTable" );
-    for ( i = 0; i < num_gids ; i ++ )
+    for ( i = 0; i < num_gids; i++ )
     {
       FT_UShort  dst_gid;
 
index 8accdfb..0f07c04 100644 (file)
 
     GXV_LIMIT_CHECK( nTracks * ( 4 + 2 + 2 ) );
 
-    for ( i = 0; i < nTracks; i ++ )
+    for ( i = 0; i < nTracks; i++ )
     {
       p = table + i * ( 4 + 2 + 2 );
       track     = FT_NEXT_LONG( p );
 
       gxv_sfntName_validate( nameIndex, 256, 32767, gxvalid );
 
-      for ( j = i; j < nTracks; j ++ )
+      for ( j = i; j < nTracks; j++ )
       {
          p = table + j * ( 4 + 2 + 2 );
          t = FT_NEXT_LONG( p );
index 9c1f183..9cab80e 100644 (file)
@@ -59,7 +59,7 @@
  /* original ZLib.                                                   */
 
 #ifndef USE_ZLIB_ZCALLOC
-#define MY_ZCALLOC /* prevent all zcalloc() & zfree() in zutils.c */
+#define MY_ZCALLOC /* prevent all zcalloc() & zfree() in zutil.c */
 #endif
 
 #include "zlib.h"
index 50d0d3f..d361ff4 100644 (file)
@@ -560,7 +560,7 @@ ZEXTERN(int)  inflateInit2 OF((z_streamp strm,
     inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
   if no more input was provided, Z_DATA_ERROR if no flush point has been found,
   or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
-  case, the application may save the current current value of total_in which
+  case, the application may save the current value of total_in which
   indicates where valid compressed data was found. In the error case, the
   application may repeatedly call inflateSync, providing more input each time,
   until success or end of the input data.
index 6c46178..6c785b6 100644 (file)
@@ -88,7 +88,7 @@
                                           FT_Int         isItalic )
   {
     FT_Bytes  p = table;
-    FT_UInt   i, cnt, table_size ;
+    FT_UInt   i, cnt, table_size;
 
     OTV_OPTIONAL_TABLE( Coverage );
     OTV_OPTIONAL_TABLE( DeviceTableOffset );
index fca677f..a86b45d 100644 (file)
@@ -442,7 +442,7 @@ THE SOFTWARE.
     int           i;
 
 
-    for ( i = 0 ; i < face->nprops && !found; i++ )
+    for ( i = 0; i < face->nprops && !found; i++ )
     {
       if ( !ft_strcmp( properties[i].name, prop ) )
         found = 1;
@@ -849,7 +849,7 @@ THE SOFTWARE.
     int           firstCol, lastCol;
     int           firstRow, lastRow;
     FT_ULong      nencoding;
-    int           encodingOffset;
+    FT_UShort     encodingOffset;
     int           i, j;
     FT_ULong      k;
     PCF_Encoding  encoding = NULL;
@@ -921,15 +921,19 @@ THE SOFTWARE.
     {
       for ( j = firstCol; j <= lastCol; j++ )
       {
+        /* X11's reference implementation uses the equivalent to  */
+        /* `FT_GET_SHORT', however PCF fonts with more than 32768 */
+        /* characters (e.g. `unifont.pcf') clearly show that an   */
+        /* unsigned value is needed.                              */
         if ( PCF_BYTE_ORDER( format ) == MSBFirst )
-          encodingOffset = FT_GET_SHORT();
+          encodingOffset = FT_GET_USHORT();
         else
-          encodingOffset = FT_GET_SHORT_LE();
+          encodingOffset = FT_GET_USHORT_LE();
 
-        if ( encodingOffset > -1 )
+        if ( encodingOffset != 0xFFFFU )
         {
           encoding[k].enc   = i * 256 + j;
-          encoding[k].glyph = (FT_UShort)encodingOffset;
+          encoding[k].glyph = encodingOffset;
 
           FT_TRACE5(( "  code %d (0x%04X): idx %d\n",
                       encoding[k].enc, encoding[k].enc, encoding[k].glyph ));
index 1dbbf95..f9cd1f6 100644 (file)
     /* XXX: we ignore the secondary stroke and edge definitions */
     /*      since we don't support native PFR hinting           */
     /*                                                          */
-    if ( flags & PFR_GLYPH_EXTRA_ITEMS )
+    if ( flags & PFR_GLYPH_SINGLE_EXTRA_ITEMS )
     {
       error = pfr_extra_items_skip( &p, limit );
       if ( error )
 
     /* ignore extra items when present */
     /*                                 */
-    if ( flags & PFR_GLYPH_EXTRA_ITEMS )
+    if ( flags & PFR_GLYPH_COMPOUND_EXTRA_ITEMS )
     {
       error = pfr_extra_items_skip( &p, limit );
       if ( error )
index ca1f37f..e509e70 100644 (file)
          FT_READ_USHORT( count )          )
       goto Exit;
 
-    /* check maximum value and a rough minimum size */
+    /* check maximum value and a rough minimum size:     */
+    /* - no more than 13106 log fonts                    */
+    /* - we need 5 bytes for a log header record         */
+    /* - we need at least 18 bytes for a log font record */
+    /* - the overall size is at least 95 bytes plus the  */
+    /*   log header and log font records                 */
     if ( count > ( ( 1 << 16 ) - 2 ) / 5                ||
-         2 + count * 5 >= stream->size - section_offset )
+         2 + count * 5 >= stream->size - section_offset ||
+         95 + count * ( 5 + 18 ) >= stream->size        )
     {
       FT_ERROR(( "pfr_log_font_count:"
                  " invalid number of logical fonts\n" ));
         if ( flags & PFR_LOG_2BYTE_STROKE )
           local++;
 
-        if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
+        if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER )
           local += 3;
       }
       if ( flags & PFR_LOG_BOLD )
 
   Too_Short:
     error = FT_THROW( Invalid_Table );
-    FT_ERROR(( "pfr_exta_item_load_stem_snaps:"
+    FT_ERROR(( "pfr_extra_item_load_stem_snaps:"
                " invalid stem snaps table\n" ));
     goto Exit;
   }
     FT_UInt     n, ok;
 
 
+    if ( *astring )
+      FT_FREE( *astring );
+
     if ( len > 0 && p[len - 1] == 0 )
       len--;
 
-    /* check that each character is ASCII for making sure not to
-       load garbage
-     */
+    /* check that each character is ASCII  */
+    /* for making sure not to load garbage */
     ok = ( len > 0 );
     for ( n = 0; n < len; n++ )
       if ( p[n] < 32 || p[n] > 127 )
       FT_MEM_COPY( result, p, len );
       result[len] = 0;
     }
+
   Exit:
     *astring = result;
     return error;
index 81b1312..769a3b6 100644 (file)
         FT_UInt    probe       = power * size;
         FT_UInt    extra       = count - power;
         FT_Byte*   base        = stream->cursor;
-        FT_Bool    twobytes    = FT_BOOL( item->flags & 1 );
-        FT_Bool    twobyte_adj = FT_BOOL( item->flags & 2 );
+        FT_Bool    twobytes    = FT_BOOL( item->flags & PFR_KERN_2BYTE_CHAR );
+        FT_Bool    twobyte_adj = FT_BOOL( item->flags & PFR_KERN_2BYTE_ADJ  );
         FT_Byte*   p;
         FT_UInt32  cpair;
 
index 22f6096..144f50c 100644 (file)
   pfr_lookup_bitmap_data( FT_Byte*   base,
                           FT_Byte*   limit,
                           FT_UInt    count,
-                          FT_UInt    flags,
+                          FT_UInt*   flags,
                           FT_UInt    char_code,
                           FT_ULong*  found_offset,
                           FT_ULong*  found_size )
   {
-    FT_UInt   left, right, char_len;
-    FT_Bool   two = FT_BOOL( flags & 1 );
+    FT_UInt   min, max, char_len;
+    FT_Bool   two = FT_BOOL( *flags & PFR_BITMAP_2BYTE_CHARCODE );
     FT_Byte*  buff;
 
 
     char_len = 4;
-    if ( two )       char_len += 1;
-    if ( flags & 2 ) char_len += 1;
-    if ( flags & 4 ) char_len += 1;
+    if ( two )
+      char_len += 1;
+    if ( *flags & PFR_BITMAP_2BYTE_SIZE )
+      char_len += 1;
+    if ( *flags & PFR_BITMAP_3BYTE_OFFSET )
+      char_len += 1;
+
+    if ( !( *flags & PFR_BITMAP_CHARCODES_VALIDATED ) )
+    {
+      FT_Byte*  p;
+      FT_Byte*  lim;
+      FT_UInt   code;
+      FT_Long   prev_code;
 
-    left  = 0;
-    right = count;
 
-    while ( left < right )
-    {
-      FT_UInt  middle, code;
+      *flags    |= PFR_BITMAP_VALID_CHARCODES;
+      prev_code  = -1;
+      lim        = base + count * char_len;
 
+      if ( lim > limit )
+      {
+        FT_TRACE0(( "pfr_lookup_bitmap_data:"
+                    " number of bitmap records too large,\n"
+                    "                       "
+                    " thus ignoring all bitmaps in this strike\n" ));
+        *flags &= ~PFR_BITMAP_VALID_CHARCODES;
+      }
+      else
+      {
+        /* check whether records are sorted by code */
+        for ( p = base; p < lim; p += char_len )
+        {
+          if ( two )
+            code = FT_PEEK_USHORT( p );
+          else
+            code = *p;
 
-      middle = ( left + right ) >> 1;
-      buff   = base + middle * char_len;
+          if ( (FT_Long)code <= prev_code )
+          {
+            FT_TRACE0(( "pfr_lookup_bitmap_data:"
+                        " bitmap records are not sorted,\n"
+                        "                       "
+                        " thus ignoring all bitmaps in this strike\n" ));
+            *flags &= ~PFR_BITMAP_VALID_CHARCODES;
+            break;
+          }
 
-      /* check that we are not outside of the table -- */
-      /* this is possible with broken fonts...         */
-      if ( buff + char_len > limit )
-        goto Fail;
+          prev_code = code;
+        }
+      }
+
+      *flags |= PFR_BITMAP_CHARCODES_VALIDATED;
+    }
+
+    /* ignore bitmaps in case table is not valid     */
+    /* (this might be sanitized, but PFR is dead...) */
+    if ( !( *flags & PFR_BITMAP_VALID_CHARCODES ) )
+      goto Fail;
+
+    min = 0;
+    max = count;
+
+    /* binary search */
+    while ( min < max )
+    {
+      FT_UInt  mid, code;
+
+
+      mid  = ( min + max ) >> 1;
+      buff = base + mid * char_len;
 
       if ( two )
         code = PFR_NEXT_USHORT( buff );
       else
         code = PFR_NEXT_BYTE( buff );
 
-      if ( code == char_code )
-        goto Found_It;
-
-      if ( code < char_code )
-        left = middle;
+      if ( char_code < code )
+        max = mid;
+      else if ( char_code > code )
+        min = mid + 1;
       else
-        right = middle;
+        goto Found_It;
     }
 
   Fail:
     return;
 
   Found_It:
-    if ( flags & 2 )
+    if ( *flags & PFR_BITMAP_2BYTE_SIZE )
       *found_size = PFR_NEXT_USHORT( buff );
     else
       *found_size = PFR_NEXT_BYTE( buff );
 
-    if ( flags & 4 )
+    if ( *flags & PFR_BITMAP_3BYTE_OFFSET )
       *found_offset = PFR_NEXT_ULONG( buff );
     else
       *found_offset = PFR_NEXT_USHORT( buff );
   {
     FT_Error  error = FT_Err_Ok;
     FT_Byte   flags;
-    FT_Char   c;
     FT_Byte   b;
     FT_Byte*  p = *pdata;
     FT_Long   xpos, ypos, advance;
     {
     case 0:
       PFR_CHECK( 1 );
-      c    = PFR_NEXT_INT8( p );
-      xpos = c >> 4;
-      ypos = ( (FT_Char)( c << 4 ) ) >> 4;
+      b    = PFR_NEXT_BYTE( p );
+      xpos = (FT_Char)b >> 4;
+      ypos = ( (FT_Char)( b << 4 ) ) >> 4;
       break;
 
     case 1:
 
     case 1:
       PFR_CHECK( 1 );
-      advance = PFR_NEXT_INT8( p ) << 8;
+      advance = PFR_NEXT_INT8( p ) * 256;
       break;
 
     case 2:
 
 
       char_len = 4;
-      if ( strike->flags & 1 ) char_len += 1;
-      if ( strike->flags & 2 ) char_len += 1;
-      if ( strike->flags & 4 ) char_len += 1;
+      if ( strike->flags & PFR_BITMAP_2BYTE_CHARCODE )
+        char_len += 1;
+      if ( strike->flags & PFR_BITMAP_2BYTE_SIZE )
+        char_len += 1;
+      if ( strike->flags & PFR_BITMAP_3BYTE_OFFSET )
+        char_len += 1;
 
       /* access data directly in the frame to speed lookups */
       if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
       pfr_lookup_bitmap_data( stream->cursor,
                               stream->limit,
                               strike->num_bitmaps,
-                              strike->flags,
+                              &strike->flags,
                               character->char_code,
                               &gps_offset,
                               &gps_size );
                                        &xpos, &ypos,
                                        &xsize, &ysize,
                                        &advance, &format );
+      if ( error )
+        goto Exit1;
 
       /*
        * Before allocating the target bitmap, we check whether the given
       {
         if ( FT_ERR_EQ( error, Invalid_Table ) )
           FT_ERROR(( "pfr_slot_load_bitmap: invalid bitmap dimensions\n" ));
-        goto Exit;
+        goto Exit1;
       }
 
       /*
         /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */
         glyph->root.metrics.width        = (FT_Pos)xsize << 6;
         glyph->root.metrics.height       = (FT_Pos)ysize << 6;
-        glyph->root.metrics.horiBearingX = xpos << 6;
-        glyph->root.metrics.horiBearingY = ypos << 6;
+        glyph->root.metrics.horiBearingX = xpos * 64;
+        glyph->root.metrics.horiBearingY = ypos * 64;
         glyph->root.metrics.horiAdvance  = FT_PIX_ROUND( ( advance >> 2 ) );
         glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
         glyph->root.metrics.vertBearingY = 0;
                       p,
                       stream->limit,
                       format,
-                      FT_BOOL(face->header.color_flags & 2),
+                      FT_BOOL( face->header.color_flags &
+                               PFR_FLAG_INVERT_BITMAP   ),
                       &glyph->root.bitmap );
         }
       }
 
+    Exit1:
       FT_FRAME_EXIT();
     }
 
index 592acbd..bd6c2cd 100644 (file)
@@ -69,12 +69,8 @@ FT_BEGIN_HEADER
 
 
   /* used in `color_flags' field of the PFR_Header */
-  typedef enum  PFR_HeaderFlags_
-  {
-    PFR_FLAG_BLACK_PIXEL   = 1,
-    PFR_FLAG_INVERT_BITMAP = 2
-
-  } PFR_HeaderFlags;
+#define PFR_FLAG_BLACK_PIXEL    0x01U
+#define PFR_FLAG_INVERT_BITMAP  0x02U
 
 
   /************************************************************************/
@@ -96,36 +92,27 @@ FT_BEGIN_HEADER
   } PFR_LogFontRec, *PFR_LogFont;
 
 
-  typedef enum  PFR_LogFlags_
-  {
-    PFR_LOG_EXTRA_ITEMS  = 0x40,
-    PFR_LOG_2BYTE_BOLD   = 0x20,
-    PFR_LOG_BOLD         = 0x10,
-    PFR_LOG_2BYTE_STROKE = 8,
-    PFR_LOG_STROKE       = 4,
-    PFR_LINE_JOIN_MASK   = 3
+#define PFR_LINE_JOIN_MITER   0x00U
+#define PFR_LINE_JOIN_ROUND   0x01U
+#define PFR_LINE_JOIN_BEVEL   0x02U
+#define PFR_LINE_JOIN_MASK    ( PFR_LINE_JOIN_ROUND | PFR_LINE_JOIN_BEVEL )
 
-  } PFR_LogFlags;
-
-
-  typedef enum  PFR_LineJoinFlags_
-  {
-    PFR_LINE_JOIN_MITER = 0,
-    PFR_LINE_JOIN_ROUND = 1,
-    PFR_LINE_JOIN_BEVEL = 2
-
-  } PFR_LineJoinFlags;
+#define PFR_LOG_STROKE        0x04U
+#define PFR_LOG_2BYTE_STROKE  0x08U
+#define PFR_LOG_BOLD          0x10U
+#define PFR_LOG_2BYTE_BOLD    0x20U
+#define PFR_LOG_EXTRA_ITEMS   0x40U
 
 
   /************************************************************************/
 
-  typedef enum  PFR_BitmapFlags_
-  {
-    PFR_BITMAP_3BYTE_OFFSET   = 4,
-    PFR_BITMAP_2BYTE_SIZE     = 2,
-    PFR_BITMAP_2BYTE_CHARCODE = 1
+#define PFR_BITMAP_2BYTE_CHARCODE  0x01U
+#define PFR_BITMAP_2BYTE_SIZE      0x02U
+#define PFR_BITMAP_3BYTE_OFFSET    0x04U
 
-  } PFR_BitmapFlags;
+  /*not part of the specification but used for implementation */
+#define PFR_BITMAP_CHARCODES_VALIDATED  0x40U
+#define PFR_BITMAP_VALID_CHARCODES      0x80U
 
 
   typedef struct  PFR_BitmapCharRec_
@@ -137,15 +124,11 @@ FT_BEGIN_HEADER
   } PFR_BitmapCharRec, *PFR_BitmapChar;
 
 
-  typedef enum  PFR_StrikeFlags_
-  {
-    PFR_STRIKE_2BYTE_COUNT  = 0x10,
-    PFR_STRIKE_3BYTE_OFFSET = 0x08,
-    PFR_STRIKE_3BYTE_SIZE   = 0x04,
-    PFR_STRIKE_2BYTE_YPPM   = 0x02,
-    PFR_STRIKE_2BYTE_XPPM   = 0x01
-
-  } PFR_StrikeFlags;
+#define PFR_STRIKE_2BYTE_XPPM    0x01U
+#define PFR_STRIKE_2BYTE_YPPM    0x02U
+#define PFR_STRIKE_3BYTE_SIZE    0x04U
+#define PFR_STRIKE_3BYTE_OFFSET  0x08U
+#define PFR_STRIKE_2BYTE_COUNT   0x10U
 
 
   typedef struct  PFR_StrikeRec_
@@ -266,38 +249,29 @@ FT_BEGIN_HEADER
   } PFR_PhyFontRec, *PFR_PhyFont;
 
 
-  typedef enum  PFR_PhyFlags_
-  {
-    PFR_PHY_EXTRA_ITEMS      = 0x80,
-    PFR_PHY_3BYTE_GPS_OFFSET = 0x20,
-    PFR_PHY_2BYTE_GPS_SIZE   = 0x10,
-    PFR_PHY_ASCII_CODE       = 0x08,
-    PFR_PHY_PROPORTIONAL     = 0x04,
-    PFR_PHY_2BYTE_CHARCODE   = 0x02,
-    PFR_PHY_VERTICAL         = 0x01
-
-  } PFR_PhyFlags;
+#define PFR_PHY_VERTICAL          0x01U
+#define PFR_PHY_2BYTE_CHARCODE    0x02U
+#define PFR_PHY_PROPORTIONAL      0x04U
+#define PFR_PHY_ASCII_CODE        0x08U
+#define PFR_PHY_2BYTE_GPS_SIZE    0x10U
+#define PFR_PHY_3BYTE_GPS_OFFSET  0x20U
+#define PFR_PHY_EXTRA_ITEMS       0x80U
 
 
-  typedef enum PFR_KernFlags_
-  {
-    PFR_KERN_2BYTE_CHAR  = 0x01,
-    PFR_KERN_2BYTE_ADJ   = 0x02
-
-  } PFR_KernFlags;
+#define PFR_KERN_2BYTE_CHAR  0x01U
+#define PFR_KERN_2BYTE_ADJ   0x02U
 
 
   /************************************************************************/
 
-  typedef enum  PFR_GlyphFlags_
-  {
-    PFR_GLYPH_IS_COMPOUND   = 0x80,
-    PFR_GLYPH_EXTRA_ITEMS   = 0x08,
-    PFR_GLYPH_1BYTE_XYCOUNT = 0x04,
-    PFR_GLYPH_XCOUNT        = 0x02,
-    PFR_GLYPH_YCOUNT        = 0x01
+#define PFR_GLYPH_YCOUNT         0x01U
+#define PFR_GLYPH_XCOUNT         0x02U
+#define PFR_GLYPH_1BYTE_XYCOUNT  0x04U
+
+#define PFR_GLYPH_SINGLE_EXTRA_ITEMS    0x08U
+#define PFR_GLYPH_COMPOUND_EXTRA_ITEMS  0x40U
 
-  } PFR_GlyphFlags;
+#define PFR_GLYPH_IS_COMPOUND  0x80U
 
 
   /* controlled coordinate */
@@ -321,14 +295,10 @@ FT_BEGIN_HEADER
   } PFR_SubGlyphRec, *PFR_SubGlyph;
 
 
-  typedef enum  PFR_SubgGlyphFlags_
-  {
-    PFR_SUBGLYPH_3BYTE_OFFSET = 0x80,
-    PFR_SUBGLYPH_2BYTE_SIZE   = 0x40,
-    PFR_SUBGLYPH_YSCALE       = 0x20,
-    PFR_SUBGLYPH_XSCALE       = 0x10
-
-  } PFR_SubGlyphFlags;
+#define PFR_SUBGLYPH_XSCALE        0x10U
+#define PFR_SUBGLYPH_YSCALE        0x20U
+#define PFR_SUBGLYPH_2BYTE_SIZE    0x40U
+#define PFR_SUBGLYPH_3BYTE_OFFSET  0x80U
 
 
   typedef struct  PFR_GlyphRec_
index 70f8fdd..f208b5f 100644 (file)
 
     for ( ; count > 0; count--, idx++ )
     {
-      FT_Byte*    q = (FT_Byte*)objects[idx] + field->offset;
+      FT_Byte*    q      = (FT_Byte*)objects[idx] + field->offset;
       FT_Long     val;
-      FT_String*  string;
+      FT_String*  string = NULL;
 
 
       skip_spaces( &cur, limit );
       case T1_FIELD_TYPE_MM_BBOX:
         {
           FT_Memory  memory = parser->memory;
-          FT_Fixed*  temp;
+          FT_Fixed*  temp   = NULL;
           FT_Int     result;
           FT_UInt    i;
 
index 86181cd..8f131be 100644 (file)
            * It turns out though that minimizing the total number of lit
            * pixels is also important, so position C), with one edge
            * aligned with a pixel boundary is actually preferable
-           * to A).  There are also more possibile positions for C) than
+           * to A).  There are also more possible positions for C) than
            * for A) or B), so it involves less distortion of the overall
            * character shape.
            */
             }
 
             /* We choose between B) and C) above based on the amount
-             * of fractinal stem width; for small amounts, choose
+             * of fractional stem width; for small amounts, choose
              * C) always, for large amounts, B) always, and inbetween,
              * pick whichever one involves less stem movement.
              */
index be71fc5..2ac5ef1 100644 (file)
@@ -80,7 +80,7 @@
 
 #if 0
 
-  /* org_width is is font units, result in device pixels, 26.6 format */
+  /* org_width is in font units, result in device pixels, 26.6 format */
   FT_LOCAL_DEF( FT_Pos )
   psh_dimension_snap_width( PSH_Dimension  dimension,
                             FT_Int         org_width )
index cde5a50..e5ccf01 100644 (file)
 #define FT_ERR_XCAT( x, y )  x ## y
 #define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
 
-#define FT_MAX( a, b )  ( (a) > (b) ? (a) : (b) )
-
   /* This macro is used to indicate that a function parameter is unused. */
   /* Its purpose is simply to reduce compiler warnings.  Note also that  */
   /* simply defining it as `(void)x' doesn't avoid warnings with certain */
 #define IS_TOP_OVERSHOOT( x )    \
           (Bool)( x - FLOOR( x ) >= ras.precision_half )
 
+#if FT_RENDER_POOL_SIZE > 2048
+#define FT_MAX_BLACK_POOL  ( FT_RENDER_POOL_SIZE / sizeof ( Long ) )
+#else
+#define FT_MAX_BLACK_POOL  ( 2048 / sizeof ( Long ) )
+#endif
+
   /* The most used variables are positioned at the top of the structure. */
   /* Thus, their offset can be coded with less opcodes, resulting in a   */
   /* smaller executable.                                                 */
 
 
   static void
-  ft_black_reset( black_PRaster  raster,
-                  char*          pool_base,
-                  Long           pool_size )
+  ft_black_reset( FT_Raster  raster,
+                  PByte      pool_base,
+                  ULong      pool_size )
   {
     FT_UNUSED( raster );
     FT_UNUSED( pool_base );
 
 
   static int
-  ft_black_set_mode( black_PRaster  raster,
-                     ULong          mode,
-                     const char*    palette )
+  ft_black_set_mode( FT_Raster  raster,
+                     ULong      mode,
+                     void*      args )
   {
     FT_UNUSED( raster );
     FT_UNUSED( mode );
-    FT_UNUSED( palette );
+    FT_UNUSED( args );
 
     return 0;
   }
 
 
   static int
-  ft_black_render( black_PRaster            raster,
+  ft_black_render( FT_Raster                raster,
                    const FT_Raster_Params*  params )
   {
     const FT_Outline*  outline    = (const FT_Outline*)params->source;
 #else
     black_TWorker  worker[1];
 
-    Long  buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( Long )];
+    Long  buffer[FT_MAX_BLACK_POOL];
 #endif
 
 
     if ( !target_map->buffer )
       return FT_THROW( Invalid );
 
+    /* reject too large outline coordinates */
+    {
+      FT_Vector*  vec   = outline->points;
+      FT_Vector*  limit = vec + outline->n_points;
+
+
+      for ( ; vec < limit; vec++ )
+      {
+        if ( vec->x < -0x1000000L || vec->x > 0x1000000L ||
+             vec->y < -0x1000000L || vec->y > 0x1000000L )
+         return FT_THROW( Invalid );
+      }
+    }
+
 #ifdef __REACTOS__
     worker = malloc(sizeof(black_TWorker));
     buffer = malloc(FT_MAX(FT_RENDER_POOL_SIZE, 2048));
 
     worker->buff     = buffer;
 #ifdef __REACTOS__
-    worker->sizeBuff = buffer + (FT_MAX(FT_RENDER_POOL_SIZE, 2048) / sizeof(Long));
+    worker->sizeBuff = buffer + FT_MAX_BLACK_POOL;
 #else
     worker->sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
 #endif
index 2cf2ee2..2e8c1ec 100644 (file)
              instance_size * num_instances > fvar_len )
         num_instances = 0;
 
+      /* we don't support Multiple Master CFFs yet */
+      if ( !face->goto_table( face, TTAG_CFF, stream, 0 ) )
+        num_instances = 0;
+
       /* we support at most 2^15 - 1 instances */
       if ( num_instances >= ( 1U << 15 ) - 1 )
       {
index 92ec523..01255a8 100644 (file)
             mid = max + 1;
 
           /* search in segments before the current segment */
-          for ( i = max ; i > 0; i-- )
+          for ( i = max; i > 0; i-- )
           {
             FT_UInt   prev_end;
             FT_Byte*  old_p;
 
       if ( char_code < start )
         max = mid;
-      else if ( char_code > start+cnt )
+      else if ( char_code > start + cnt )
         min = mid + 1;
       else
         return TRUE;
index f228f62..3277f1e 100644 (file)
@@ -2,7 +2,7 @@
 /*                                                                         */
 /*  ttpost.c                                                               */
 /*                                                                         */
-/*    Postcript name table processing for TrueType and OpenType fonts      */
+/*    PostScript name table processing for TrueType and OpenType fonts     */
 /*    (body).                                                              */
 /*                                                                         */
 /*  Copyright 1996-2016 by                                                 */
index 93762b0..ede45fd 100644 (file)
@@ -2,7 +2,7 @@
 /*                                                                         */
 /*  ttpost.h                                                               */
 /*                                                                         */
-/*    Postcript name table processing for TrueType and OpenType fonts      */
+/*    PostScript name table processing for TrueType and OpenType fonts     */
 /*    (specification).                                                     */
 /*                                                                         */
 /*  Copyright 1996-2016 by                                                 */
index 258cde9..790ce55 100644 (file)
 #define FT_BEGIN_STMNT  do {
 #define FT_END_STMNT    } while ( 0 )
 
+#define FT_MIN( a, b )  ( (a) < (b) ? (a) : (b) )
 #define FT_MAX( a, b )  ( (a) > (b) ? (a) : (b) )
 #define FT_ABS( a )     ( (a) < 0 ? -(a) : (a) )
 
@@ -302,7 +303,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
 #else /* FT_STATIC_RASTER */
 
-#define RAS_ARG   /* empty */
+#define RAS_ARG   void
 #define RAS_ARG_  /* empty */
 #define RAS_VAR   /* empty */
 #define RAS_VAR_  /* empty */
@@ -318,19 +319,19 @@ typedef ptrdiff_t  FT_PtrDist;
 #undef TRUNC
 #undef SCALED
 
-#define ONE_PIXEL       ( 1L << PIXEL_BITS )
+#define ONE_PIXEL       ( 1 << PIXEL_BITS )
 #define TRUNC( x )      ( (TCoord)( (x) >> PIXEL_BITS ) )
-#define SUBPIXELS( x )  ( (TPos)(x) << PIXEL_BITS )
+#define SUBPIXELS( x )  ( (TPos)(x) * ONE_PIXEL )
 #define FLOOR( x )      ( (x) & -ONE_PIXEL )
 #define CEILING( x )    ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
 #define ROUND( x )      ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
 
 #if PIXEL_BITS >= 6
-#define UPSCALE( x )    ( (x) << ( PIXEL_BITS - 6 ) )
+#define UPSCALE( x )    ( (x) * ( ONE_PIXEL >> 6 ) )
 #define DOWNSCALE( x )  ( (x) >> ( PIXEL_BITS - 6 ) )
 #else
 #define UPSCALE( x )    ( (x) >> ( 6 - PIXEL_BITS ) )
-#define DOWNSCALE( x )  ( (x) << ( 6 - PIXEL_BITS ) )
+#define DOWNSCALE( x )  ( (x) * ( 64 >> PIXEL_BITS ) )
 #endif
 
 
@@ -369,7 +370,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
 
   /* These macros speed up repetitive divisions by replacing them */
-  /* with multiplications and right shifts.                       */ 
+  /* with multiplications and right shifts.                       */
 #define FT_UDIVPREP( b )                                       \
   long  b ## _r = (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b )
 #define FT_UDIV( a, b )                                        \
@@ -386,38 +387,16 @@ typedef ptrdiff_t  FT_PtrDist;
   /* need to define them to "float" or "double" when experimenting with   */
   /* new algorithms                                                       */
 
-  typedef long  TCoord;   /* integer scanline/pixel coordinate */
   typedef long  TPos;     /* sub-pixel coordinate              */
-
-  /* determine the type used to store cell areas.  This normally takes at */
-  /* least PIXEL_BITS*2 + 1 bits.  On 16-bit systems, we need to use      */
-  /* `long' instead of `int', otherwise bad things happen                 */
-
-#if PIXEL_BITS <= 7
-
-  typedef int  TArea;
-
-#else /* PIXEL_BITS >= 8 */
-
-  /* approximately determine the size of integers using an ANSI-C header */
-#if FT_UINT_MAX == 0xFFFFU
-  typedef long  TArea;
-#else
-  typedef int   TArea;
-#endif
-
-#endif /* PIXEL_BITS >= 8 */
-
-
-  /* maximum number of gray spans in a call to the span callback */
-#define FT_MAX_GRAY_SPANS  32
+  typedef int   TCoord;   /* integer scanline/pixel coordinate */
+  typedef int   TArea;    /* cell areas, coordinate products   */
 
 
   typedef struct TCell_*  PCell;
 
   typedef struct  TCell_
   {
-    TPos    x;     /* same with gray_TWorker.ex    */
+    TCoord  x;     /* same with gray_TWorker.ex    */
     TCoord  cover; /* same with gray_TWorker.cover */
     TArea   area;
     PCell   next;
@@ -425,6 +404,17 @@ typedef ptrdiff_t  FT_PtrDist;
   } TCell;
 
 
+  /* maximum number of gray spans in a call to the span callback */
+#define FT_MAX_GRAY_SPANS  32
+
+  /* maximum number of gray cells in the buffer */
+#if FT_RENDER_POOL_SIZE > 2048
+#define FT_MAX_GRAY_POOL  ( FT_RENDER_POOL_SIZE / sizeof ( TCell ) )
+#else
+#define FT_MAX_GRAY_POOL  ( 2048 / sizeof ( TCell ) )
+#endif
+
+
 #if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
   /* We disable the warning `structure was padded due to   */
   /* __declspec(align())' in order to compile cleanly with */
@@ -438,9 +428,9 @@ typedef ptrdiff_t  FT_PtrDist;
     ft_jmp_buf  jump_buffer;
 
     TCoord  ex, ey;
-    TPos    min_ex, max_ex;
-    TPos    min_ey, max_ey;
-    TPos    count_ex, count_ey;
+    TCoord  min_ex, max_ex;
+    TCoord  min_ey, max_ey;
+    TCoord  count_ex, count_ey;
 
     TArea   area;
     TCoord  cover;
@@ -452,12 +442,8 @@ typedef ptrdiff_t  FT_PtrDist;
 
     TPos    x,  y;
 
-    FT_Vector   bez_stack[32 * 3 + 1];
-    int         lev_stack[32];
-
     FT_Outline  outline;
     FT_Bitmap   target;
-    FT_BBox     clip_box;
 
     FT_Span     gray_spans[FT_MAX_GRAY_SPANS];
     int         num_gray_spans;
@@ -466,14 +452,7 @@ typedef ptrdiff_t  FT_PtrDist;
     void*                render_span_data;
     int                  span_y;
 
-    int  band_size;
-    int  band_shoot;
-
-    void*       buffer;
-    long        buffer_size;
-
     PCell*     ycells;
-    TPos       ycount;
 
   } gray_TWorker, *gray_PWorker;
 
@@ -496,71 +475,32 @@ typedef ptrdiff_t  FT_PtrDist;
   } gray_TRaster, *gray_PRaster;
 
 
+#ifdef FT_DEBUG_LEVEL_TRACE
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* Initialize the cells table.                                           */
-  /*                                                                       */
-  static void
-  gray_init_cells( RAS_ARG_ void*  buffer,
-                            long   byte_size )
-  {
-    ras.buffer      = buffer;
-    ras.buffer_size = byte_size;
-
-    ras.ycells      = (PCell*) buffer;
-    ras.cells       = NULL;
-    ras.max_cells   = 0;
-    ras.num_cells   = 0;
-    ras.area        = 0;
-    ras.cover       = 0;
-    ras.invalid     = 1;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Compute the outline bounding box.                                     */
-  /*                                                                       */
+  /* to be called while in the debugger --                                */
+  /* this function causes a compiler warning since it is unused otherwise */
   static void
-  gray_compute_cbox( RAS_ARG )
+  gray_dump_cells( RAS_ARG )
   {
-    FT_Outline*  outline = &ras.outline;
-    FT_Vector*   vec     = outline->points;
-    FT_Vector*   limit   = vec + outline->n_points;
+    int  yindex;
 
 
-    if ( outline->n_points <= 0 )
+    for ( yindex = 0; yindex < ras.count_ey; yindex++ )
     {
-      ras.min_ex = ras.max_ex = 0;
-      ras.min_ey = ras.max_ey = 0;
-      return;
-    }
-
-    ras.min_ex = ras.max_ex = vec->x;
-    ras.min_ey = ras.max_ey = vec->y;
-
-    vec++;
+      PCell  cell;
 
-    for ( ; vec < limit; vec++ )
-    {
-      TPos  x = vec->x;
-      TPos  y = vec->y;
 
+      printf( "%3d:", yindex );
 
-      if ( x < ras.min_ex ) ras.min_ex = x;
-      if ( x > ras.max_ex ) ras.max_ex = x;
-      if ( y < ras.min_ey ) ras.min_ey = y;
-      if ( y > ras.max_ey ) ras.max_ey = y;
+      for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
+        printf( " (%3d, c:%4d, a:%6d)",
+                cell->x, cell->cover, cell->area );
+      printf( "\n" );
     }
-
-    /* truncate the bounding box to integer pixels */
-    ras.min_ex = ras.min_ex >> 6;
-    ras.min_ey = ras.min_ey >> 6;
-    ras.max_ex = ( ras.max_ex + 63 ) >> 6;
-    ras.max_ey = ( ras.max_ey + 63 ) >> 6;
   }
 
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
 
   /*************************************************************************/
   /*                                                                       */
@@ -570,7 +510,7 @@ typedef ptrdiff_t  FT_PtrDist;
   gray_find_cell( RAS_ARG )
   {
     PCell  *pcell, cell;
-    TPos    x = ras.ex;
+    TCoord  x = ras.ex;
 
 
     if ( x > ras.count_ex )
@@ -675,10 +615,10 @@ typedef ptrdiff_t  FT_PtrDist;
                             TCoord  ey )
   {
     if ( ex > ras.max_ex )
-      ex = (TCoord)( ras.max_ex );
+      ex = ras.max_ex;
 
     if ( ex < ras.min_ex )
-      ex = (TCoord)( ras.min_ex - 1 );
+      ex = ras.min_ex - 1;
 
     ras.area    = 0;
     ras.cover   = 0;
@@ -689,7 +629,7 @@ typedef ptrdiff_t  FT_PtrDist;
     gray_set_cell( RAS_VAR_ ex, ey );
   }
 
-#if 0
+#ifndef FT_LONG64
 
   /*************************************************************************/
   /*                                                                       */
@@ -702,17 +642,13 @@ typedef ptrdiff_t  FT_PtrDist;
                                  TPos    x2,
                                  TCoord  y2 )
   {
-    TCoord  ex1, ex2, fx1, fx2, delta, mod;
-    long    p, first, dx;
+    TCoord  ex1, ex2, fx1, fx2, first, delta, mod;
+    TPos    p, dx;
     int     incr;
 
 
-    dx = x2 - x1;
-
     ex1 = TRUNC( x1 );
     ex2 = TRUNC( x2 );
-    fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) );
-    fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) );
 
     /* trivial case.  Happens often */
     if ( y1 == y2 )
@@ -721,6 +657,9 @@ typedef ptrdiff_t  FT_PtrDist;
       return;
     }
 
+    fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) );
+    fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) );
+
     /* everything is located in a single cell.  That is easy! */
     /*                                                        */
     if ( ex1 == ex2 )
@@ -737,6 +676,7 @@ typedef ptrdiff_t  FT_PtrDist;
     p     = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
     first = ONE_PIXEL;
     incr  = 1;
+    dx    = x2 - x1;
 
     if ( dx < 0 )
     {
@@ -797,25 +737,22 @@ typedef ptrdiff_t  FT_PtrDist;
   gray_render_line( RAS_ARG_ TPos  to_x,
                              TPos  to_y )
   {
-    TCoord  ey1, ey2, fy1, fy2, mod;
-    TPos    dx, dy, x, x2;
-    long    p, first;
-    int     delta, rem, lift, incr;
+    TCoord  ey1, ey2, fy1, fy2, first, delta, mod;
+    TPos    p, dx, dy, x, x2;
+    int     incr;
 
 
     ey1 = TRUNC( ras.y );
     ey2 = TRUNC( to_y );     /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
-    fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) );
-    fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
-
-    dx = to_x - ras.x;
-    dy = to_y - ras.y;
 
     /* perform vertical clipping */
     if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
          ( ey1 <  ras.min_ey && ey2 <  ras.min_ey ) )
       goto End;
 
+    fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) );
+    fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
+
     /* everything is on a single scanline */
     if ( ey1 == ey2 )
     {
@@ -823,6 +760,9 @@ typedef ptrdiff_t  FT_PtrDist;
       goto End;
     }
 
+    dx = to_x - ras.x;
+    dy = to_y - ras.y;
+
     /* vertical line - avoid calling gray_render_scanline */
     incr = 1;
 
@@ -840,14 +780,14 @@ typedef ptrdiff_t  FT_PtrDist;
         incr  = -1;
       }
 
-      delta      = (int)( first - fy1 );
+      delta      = first - fy1;
       ras.area  += (TArea)two_fx * delta;
       ras.cover += delta;
       ey1       += incr;
 
       gray_set_cell( RAS_VAR_ ex, ey1 );
 
-      delta = (int)( first + first - ONE_PIXEL );
+      delta = first + first - ONE_PIXEL;
       area  = (TArea)two_fx * delta;
       while ( ey1 != ey2 )
       {
@@ -858,7 +798,7 @@ typedef ptrdiff_t  FT_PtrDist;
         gray_set_cell( RAS_VAR_ ex, ey1 );
       }
 
-      delta      = (int)( fy2 - ONE_PIXEL + first );
+      delta      = fy2 - ONE_PIXEL + first;
       ras.area  += (TArea)two_fx * delta;
       ras.cover += delta;
 
@@ -878,19 +818,22 @@ typedef ptrdiff_t  FT_PtrDist;
       dy    = -dy;
     }
 
-    FT_DIV_MOD( int, p, dy, delta, mod );
+    FT_DIV_MOD( TCoord, p, dy, delta, mod );
 
     x = ras.x + delta;
-    gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );
+    gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first );
 
     ey1 += incr;
     gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
 
     if ( ey1 != ey2 )
     {
-      p     = ONE_PIXEL * dx;
-      FT_DIV_MOD( int, p, dy, lift, rem );
-      mod -= (int)dy;
+      TCoord  lift, rem;
+
+
+      p    = ONE_PIXEL * dx;
+      FT_DIV_MOD( TCoord, p, dy, lift, rem );
+      mod -= (TCoord)dy;
 
       do
       {
@@ -898,14 +841,14 @@ typedef ptrdiff_t  FT_PtrDist;
         mod  += rem;
         if ( mod >= 0 )
         {
-          mod -= (int)dy;
+          mod -= (TCoord)dy;
           delta++;
         }
 
         x2 = x + delta;
-        gray_render_scanline( RAS_VAR_ ey1, x,
-                                       (TCoord)( ONE_PIXEL - first ), x2,
-                                       (TCoord)first );
+        gray_render_scanline( RAS_VAR_ ey1,
+                                       x, ONE_PIXEL - first,
+                                       x2, first );
         x = x2;
 
         ey1 += incr;
@@ -913,9 +856,9 @@ typedef ptrdiff_t  FT_PtrDist;
       } while ( ey1 != ey2 );
     }
 
-    gray_render_scanline( RAS_VAR_ ey1, x,
-                                   (TCoord)( ONE_PIXEL - first ), to_x,
-                                   fy2 );
+    gray_render_scanline( RAS_VAR_ ey1,
+                                   x, ONE_PIXEL - first,
+                                   to_x, fy2 );
 
   End:
     ras.x       = to_x;
@@ -936,8 +879,6 @@ typedef ptrdiff_t  FT_PtrDist;
     TCoord  ex1, ex2, ey1, ey2;
 
 
-    ex1 = TRUNC( ras.x );
-    ex2 = TRUNC( to_x );
     ey1 = TRUNC( ras.y );
     ey2 = TRUNC( to_y );
 
@@ -946,12 +887,15 @@ typedef ptrdiff_t  FT_PtrDist;
          ( ey1 <  ras.min_ey && ey2 <  ras.min_ey ) )
       goto End;
 
-    dx = to_x - ras.x;
-    dy = to_y - ras.y;
+    ex1 = TRUNC( ras.x );
+    ex2 = TRUNC( to_x );
 
     fx1 = ras.x - SUBPIXELS( ex1 );
     fy1 = ras.y - SUBPIXELS( ey1 );
 
+    dx = to_x - ras.x;
+    dy = to_y - ras.y;
+
     if ( ex1 == ex2 && ey1 == ey2 )       /* inside one cell */
       ;
     else if ( dy == 0 ) /* ex1 != ex2 */  /* any horizontal line */
@@ -984,7 +928,7 @@ typedef ptrdiff_t  FT_PtrDist;
     }
     else                                  /* any other line */
     {
-      TArea  prod = dx * fy1 - dy * fx1;
+      TPos  prod = dx * fy1 - dy * fx1;
       FT_UDIVPREP( dx );
       FT_UDIVPREP( dy );
 
@@ -1084,73 +1028,64 @@ typedef ptrdiff_t  FT_PtrDist;
   gray_render_conic( RAS_ARG_ const FT_Vector*  control,
                               const FT_Vector*  to )
   {
+    FT_Vector   bez_stack[16 * 2 + 1];  /* enough to accommodate bisections */
+    FT_Vector*  arc = bez_stack;
     TPos        dx, dy;
-    TPos        min, max, y;
-    int         top, level;
-    int*        levels;
-    FT_Vector*  arc;
+    int         draw, split;
 
 
-    levels = ras.lev_stack;
-
-    arc      = ras.bez_stack;
     arc[0].x = UPSCALE( to->x );
     arc[0].y = UPSCALE( to->y );
     arc[1].x = UPSCALE( control->x );
     arc[1].y = UPSCALE( control->y );
     arc[2].x = ras.x;
     arc[2].y = ras.y;
-    top      = 0;
+
+    /* short-cut the arc that crosses the current band */
+    if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
+           TRUNC( arc[1].y ) >= ras.max_ey &&
+           TRUNC( arc[2].y ) >= ras.max_ey ) ||
+         ( TRUNC( arc[0].y ) <  ras.min_ey &&
+           TRUNC( arc[1].y ) <  ras.min_ey &&
+           TRUNC( arc[2].y ) <  ras.min_ey ) )
+    {
+      ras.x = arc[0].x;
+      ras.y = arc[0].y;
+      return;
+    }
 
     dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
     dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
     if ( dx < dy )
       dx = dy;
 
-    if ( dx < ONE_PIXEL / 4 )
-      goto Draw;
-
-    /* short-cut the arc that crosses the current band */
-    min = max = arc[0].y;
-
-    y = arc[1].y;
-    if ( y < min ) min = y;
-    if ( y > max ) max = y;
-
-    y = arc[2].y;
-    if ( y < min ) min = y;
-    if ( y > max ) max = y;
-
-    if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
-      goto Draw;
-
-    level = 0;
-    do
+    /* We can calculate the number of necessary bisections because  */
+    /* each bisection predictably reduces deviation exactly 4-fold. */
+    /* Even 32-bit deviation would vanish after 16 bisections.      */
+    draw = 1;
+    while ( dx > ONE_PIXEL / 4 )
     {
-      dx >>= 2;
-      level++;
-    } while ( dx > ONE_PIXEL / 4 );
-
-    levels[0] = level;
+      dx   >>= 2;
+      draw <<= 1;
+    }
 
+    /* We use decrement counter to count the total number of segments */
+    /* to draw starting from 2^level. Before each draw we split as    */
+    /* many times as there are trailing zeros in the counter.         */
     do
     {
-      level = levels[top];
-      if ( level > 0 )
+      split = 1;
+      while ( ( draw & split ) == 0 )
       {
         gray_split_conic( arc );
         arc += 2;
-        top++;
-        levels[top] = levels[top - 1] = level - 1;
-        continue;
+        split <<= 1;
       }
 
-    Draw:
       gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
-      top--;
       arc -= 2;
 
-    } while ( top >= 0 );
+    } while ( --draw );
   }
 
 
@@ -1187,11 +1122,13 @@ typedef ptrdiff_t  FT_PtrDist;
                               const FT_Vector*  control2,
                               const FT_Vector*  to )
   {
-    FT_Vector*  arc;
-    TPos        min, max, y;
+    FT_Vector   bez_stack[16 * 3 + 1];  /* enough to accommodate bisections */
+    FT_Vector*  arc = bez_stack;
+    TPos        dx, dy, dx_, dy_;
+    TPos        dx1, dy1, dx2, dy2;
+    TPos        L, s, s_limit;
 
 
-    arc      = ras.bez_stack;
     arc[0].x = UPSCALE( to->x );
     arc[0].y = UPSCALE( to->y );
     arc[1].x = UPSCALE( control2->x );
@@ -1201,29 +1138,20 @@ typedef ptrdiff_t  FT_PtrDist;
     arc[3].x = ras.x;
     arc[3].y = ras.y;
 
-    /* Short-cut the arc that crosses the current band. */
-    min = max = arc[0].y;
-
-    y = arc[1].y;
-    if ( y < min )
-      min = y;
-    if ( y > max )
-      max = y;
-
-    y = arc[2].y;
-    if ( y < min )
-      min = y;
-    if ( y > max )
-      max = y;
-
-    y = arc[3].y;
-    if ( y < min )
-      min = y;
-    if ( y > max )
-      max = y;
-
-    if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
-      goto Draw;
+    /* short-cut the arc that crosses the current band */
+    if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
+           TRUNC( arc[1].y ) >= ras.max_ey &&
+           TRUNC( arc[2].y ) >= ras.max_ey &&
+           TRUNC( arc[3].y ) >= ras.max_ey ) ||
+         ( TRUNC( arc[0].y ) <  ras.min_ey &&
+           TRUNC( arc[1].y ) <  ras.min_ey &&
+           TRUNC( arc[2].y ) <  ras.min_ey &&
+           TRUNC( arc[3].y ) <  ras.min_ey ) )
+    {
+      ras.x = arc[0].x;
+      ras.y = arc[0].y;
+      return;
+    }
 
     for (;;)
     {
@@ -1232,64 +1160,53 @@ typedef ptrdiff_t  FT_PtrDist;
       /* F. Hain, at                                                      */
       /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
 
-      {
-        TPos  dx, dy, dx_, dy_;
-        TPos  dx1, dy1, dx2, dy2;
-        TPos  L, s, s_limit;
+      /* dx and dy are x and y components of the P0-P3 chord vector. */
+      dx = dx_ = arc[3].x - arc[0].x;
+      dy = dy_ = arc[3].y - arc[0].y;
 
+      L = FT_HYPOT( dx_, dy_ );
 
-        /* dx and dy are x and y components of the P0-P3 chord vector. */
-        dx = dx_ = arc[3].x - arc[0].x;
-        dy = dy_ = arc[3].y - arc[0].y;
+      /* Avoid possible arithmetic overflow below by splitting. */
+      if ( L > 32767 )
+        goto Split;
 
-        L = FT_HYPOT( dx_, dy_ );
+      /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
+      s_limit = L * (TPos)( ONE_PIXEL / 6 );
 
-        /* Avoid possible arithmetic overflow below by splitting. */
-        if ( L > 32767 )
-          goto Split;
+      /* s is L * the perpendicular distance from P1 to the line P0-P3. */
+      dx1 = arc[1].x - arc[0].x;
+      dy1 = arc[1].y - arc[0].y;
+      s = FT_ABS( dy * dx1 - dx * dy1 );
 
-        /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
-        s_limit = L * (TPos)( ONE_PIXEL / 6 );
+      if ( s > s_limit )
+        goto Split;
 
-        /* s is L * the perpendicular distance from P1 to the line P0-P3. */
-        dx1 = arc[1].x - arc[0].x;
-        dy1 = arc[1].y - arc[0].y;
-        s = FT_ABS( dy * dx1 - dx * dy1 );
+      /* s is L * the perpendicular distance from P2 to the line P0-P3. */
+      dx2 = arc[2].x - arc[0].x;
+      dy2 = arc[2].y - arc[0].y;
+      s = FT_ABS( dy * dx2 - dx * dy2 );
 
-        if ( s > s_limit )
-          goto Split;
+      if ( s > s_limit )
+        goto Split;
 
-        /* s is L * the perpendicular distance from P2 to the line P0-P3. */
-        dx2 = arc[2].x - arc[0].x;
-        dy2 = arc[2].y - arc[0].y;
-        s = FT_ABS( dy * dx2 - dx * dy2 );
+      /* Split super curvy segments where the off points are so far
+         from the chord that the angles P0-P1-P3 or P0-P2-P3 become
+         acute as detected by appropriate dot products. */
+      if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 ||
+           dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 )
+        goto Split;
 
-        if ( s > s_limit )
-          goto Split;
+      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
 
-        /* Split super curvy segments where the off points are so far
-           from the chord that the angles P0-P1-P3 or P0-P2-P3 become
-           acute as detected by appropriate dot products. */
-        if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 ||
-             dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 )
-          goto Split;
+      if ( arc == bez_stack )
+        return;
 
-        /* No reason to split. */
-        goto Draw;
-      }
+      arc -= 3;
+      continue;
 
     Split:
       gray_split_cubic( arc );
       arc += 3;
-      continue;
-
-    Draw:
-      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
-
-      if ( arc == ras.bez_stack )
-        return;
-
-      arc -= 3;
     }
   }
 
@@ -1311,8 +1228,8 @@ typedef ptrdiff_t  FT_PtrDist;
 
     gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
 
-    worker->x = x;
-    worker->y = y;
+    ras.x = x;
+    ras.y = y;
     return 0;
   }
 
@@ -1369,29 +1286,25 @@ typedef ptrdiff_t  FT_PtrDist;
 
       if ( coverage )
       {
+        unsigned char*  q = p + spans->x;
+
+
         /* For small-spans it is faster to do it by ourselves than
          * calling `memset'.  This is mainly due to the cost of the
          * function call.
          */
-        if ( spans->len >= 8 )
-          FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
-        else
+        switch ( spans->len )
         {
-          unsigned char*  q = p + spans->x;
-
-
-          switch ( spans->len )
-          {
-          case 7: *q++ = (unsigned char)coverage;
-          case 6: *q++ = (unsigned char)coverage;
-          case 5: *q++ = (unsigned char)coverage;
-          case 4: *q++ = (unsigned char)coverage;
-          case 3: *q++ = (unsigned char)coverage;
-          case 2: *q++ = (unsigned char)coverage;
-          case 1: *q   = (unsigned char)coverage;
-          default:
-            ;
-          }
+        case 7: *q++ = coverage;
+        case 6: *q++ = coverage;
+        case 5: *q++ = coverage;
+        case 4: *q++ = coverage;
+        case 3: *q++ = coverage;
+        case 2: *q++ = coverage;
+        case 1: *q   = coverage;
+        case 0: break;
+        default:
+          FT_MEM_SET( q, coverage, spans->len );
         }
       }
     }
@@ -1401,7 +1314,7 @@ typedef ptrdiff_t  FT_PtrDist;
   static void
   gray_hline( RAS_ARG_ TCoord  x,
                        TCoord  y,
-                       TPos    area,
+                       TArea   area,
                        TCoord  acount )
   {
     int  coverage;
@@ -1433,16 +1346,8 @@ typedef ptrdiff_t  FT_PtrDist;
         coverage = 255;
     }
 
-    y += (TCoord)ras.min_ey;
-    x += (TCoord)ras.min_ex;
-
-    /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
-    if ( x >= 32767 )
-      x = 32767;
-
-    /* FT_Span.y is an integer, so limit our coordinates appropriately */
-    if ( y >= FT_INT_MAX )
-      y = FT_INT_MAX;
+    y += ras.min_ey;
+    x += ras.min_ex;
 
     if ( coverage )
     {
@@ -1453,10 +1358,10 @@ typedef ptrdiff_t  FT_PtrDist;
       /* see whether we can add this span to the current list */
       count = ras.num_gray_spans;
       span  = ras.gray_spans + count - 1;
-      if ( count > 0                          &&
-           ras.span_y == y                    &&
-           (int)span->x + span->len == (int)x &&
-           span->coverage == coverage         )
+      if ( span->coverage == coverage &&
+           span->x + span->len == x   &&
+           ras.span_y == y            &&
+           count > 0                  )
       {
         span->len = (unsigned short)( span->len + acount );
         return;
@@ -1503,48 +1408,21 @@ typedef ptrdiff_t  FT_PtrDist;
   }
 
 
-#ifdef FT_DEBUG_LEVEL_TRACE
-
-  /* to be called while in the debugger --                                */
-  /* this function causes a compiler warning since it is unused otherwise */
   static void
-  gray_dump_cells( RAS_ARG )
+  gray_sweep( RAS_ARG )
   {
     int  yindex;
 
 
-    for ( yindex = 0; yindex < ras.ycount; yindex++ )
-    {
-      PCell  cell;
-
-
-      printf( "%3d:", yindex );
-
-      for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
-        printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area );
-      printf( "\n" );
-    }
-  }
-
-#endif /* FT_DEBUG_LEVEL_TRACE */
-
-
-  static void
-  gray_sweep( RAS_ARG_ const FT_Bitmap*  target )
-  {
-    int  yindex;
-
-    FT_UNUSED( target );
-
-
     if ( ras.num_cells == 0 )
       return;
 
     ras.num_gray_spans = 0;
+    ras.span_y         = 0;
 
     FT_TRACE7(( "gray_sweep: start\n" ));
 
-    for ( yindex = 0; yindex < ras.ycount; yindex++ )
+    for ( yindex = 0; yindex < ras.count_ey; yindex++ )
     {
       PCell   cell  = ras.ycells[yindex];
       TCoord  cover = 0;
@@ -1553,15 +1431,15 @@ typedef ptrdiff_t  FT_PtrDist;
 
       for ( ; cell != NULL; cell = cell->next )
       {
-        TPos  area;
+        TArea  area;
 
 
         if ( cell->x > x && cover != 0 )
-          gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
+          gray_hline( RAS_VAR_ x, yindex, (TArea)cover * ( ONE_PIXEL * 2 ),
                       cell->x - x );
 
         cover += cell->cover;
-        area   = cover * ( ONE_PIXEL * 2 ) - cell->area;
+        area   = (TArea)cover * ( ONE_PIXEL * 2 ) - cell->area;
 
         if ( area != 0 && cell->x >= 0 )
           gray_hline( RAS_VAR_ cell->x, yindex, area, 1 );
@@ -1570,7 +1448,7 @@ typedef ptrdiff_t  FT_PtrDist;
       }
 
       if ( cover != 0 )
-        gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
+        gray_hline( RAS_VAR_ x, yindex, (TArea)cover * ( ONE_PIXEL * 2 ),
                     ras.count_ex - x );
     }
 
@@ -1605,7 +1483,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
   /*************************************************************************/
   /*                                                                       */
-  /*  The following function should only compile in stand-alone mode,      */
+  /*  The following functions should only compile in stand-alone mode,     */
   /*  i.e., when building this component without the rest of FreeType.     */
   /*                                                                       */
   /*************************************************************************/
@@ -1883,12 +1761,87 @@ typedef ptrdiff_t  FT_PtrDist;
     return FT_THROW( Invalid_Outline );
   }
 
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Get_CBox                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Return an outline's `control box'.  The control box encloses all   */
+  /*    the outline's points, including Bézier control points.  Though it  */
+  /*    coincides with the exact bounding box for most glyphs, it can be   */
+  /*    slightly larger in some situations (like when rotating an outline  */
+  /*    that contains Bézier outside arcs).                                */
+  /*                                                                       */
+  /*    Computing the control box is very fast, while getting the bounding */
+  /*    box can take much more time as it needs to walk over all segments  */
+  /*    and arcs in the outline.  To get the latter, you can use the       */
+  /*    `ftbbox' component, which is dedicated to this single task.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    acbox   :: The outline's control box.                              */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    See @FT_Glyph_Get_CBox for a discussion of tricky fonts.           */
+  /*                                                                       */
+
+  static void
+  FT_Outline_Get_CBox( const FT_Outline*  outline,
+                       FT_BBox           *acbox )
+  {
+    TPos  xMin, yMin, xMax, yMax;
+
+
+    if ( outline && acbox )
+    {
+      if ( outline->n_points == 0 )
+      {
+        xMin = 0;
+        yMin = 0;
+        xMax = 0;
+        yMax = 0;
+      }
+      else
+      {
+        FT_Vector*  vec   = outline->points;
+        FT_Vector*  limit = vec + outline->n_points;
+
+
+        xMin = xMax = vec->x;
+        yMin = yMax = vec->y;
+        vec++;
+
+        for ( ; vec < limit; vec++ )
+        {
+          TPos  x, y;
+
+
+          x = vec->x;
+          if ( x < xMin ) xMin = x;
+          if ( x > xMax ) xMax = x;
+
+          y = vec->y;
+          if ( y < yMin ) yMin = y;
+          if ( y > yMax ) yMax = y;
+        }
+      }
+      acbox->xMin = xMin;
+      acbox->xMax = xMax;
+      acbox->yMin = yMin;
+      acbox->yMax = yMax;
+    }
+  }
+
 #endif /* STANDALONE_ */
 
 
   typedef struct  gray_TBand_
   {
-    TPos  min, max;
+    TCoord  min, max;
 
   } gray_TBand;
 
@@ -1920,10 +1873,18 @@ typedef ptrdiff_t  FT_PtrDist;
       error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
       if ( !ras.invalid )
         gray_record_cell( RAS_VAR );
+
+      FT_TRACE7(( "band [%d..%d]: %d cells\n",
+                  ras.min_ey, ras.max_ey, ras.num_cells ));
     }
     else
+    {
       error = FT_THROW( Memory_Overflow );
 
+      FT_TRACE7(( "band [%d..%d]: to be bisected\n",
+                  ras.min_ey, ras.max_ey ));
+    }
+
     return error;
   }
 
@@ -1931,47 +1892,34 @@ typedef ptrdiff_t  FT_PtrDist;
   static int
   gray_convert_glyph( RAS_ARG )
   {
-    gray_TBand            bands[40];
-    gray_TBand* volatile  band;
-    int volatile          n, num_bands;
-    TPos volatile         min, max, max_y;
-    FT_BBox*              clip;
-
-
-    /* Set up state in the raster object */
-    gray_compute_cbox( RAS_VAR );
-
-    /* clip to target bitmap, exit if nothing to do */
-    clip = &ras.clip_box;
-
-    if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax ||
-         ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax )
-      return 0;
-
-    if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin;
-    if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin;
-
-    if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax;
-    if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax;
+#ifdef __REACTOS__
+    TCell *buffer;
+#else
+    TCell        buffer[FT_MAX_GRAY_POOL];
+#endif
+    const int    band_size = FT_MAX_GRAY_POOL / 8;
+    gray_TBand   bands[32];
+    gray_TBand*  band;
+    int          n, num_bands;
+    TCoord       min, max, max_y;
 
-    ras.count_ex = ras.max_ex - ras.min_ex;
-    ras.count_ey = ras.max_ey - ras.min_ey;
+#ifdef __REACTOS__
+    buffer = malloc(FT_MAX(FT_RENDER_POOL_SIZE, 2048));
+#endif
 
     /* set up vertical bands */
-    num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
+    num_bands = (int)( ( ras.max_ey - ras.min_ey ) / band_size );
     if ( num_bands == 0 )
       num_bands = 1;
     if ( num_bands >= 39 )
       num_bands = 39;
 
-    ras.band_shoot = 0;
-
     min   = ras.min_ey;
     max_y = ras.max_ey;
 
     for ( n = 0; n < num_bands; n++, min = max )
     {
-      max = min + ras.band_size;
+      max = min + band_size;
       if ( n == num_bands - 1 || max > max_y )
         max = max_y;
 
@@ -1981,37 +1929,28 @@ typedef ptrdiff_t  FT_PtrDist;
 
       do
       {
-        TPos  bottom, top, middle;
-        int   error;
+        TCoord  bottom, top, middle;
+        int     error;
 
-        {
-          PCell  cells_max;
-          int    yindex;
-          long   cell_start, cell_end, cell_mod;
 
+        /* memory management */
+        {
+          size_t  ycount = (size_t)( band->max - band->min );
+          size_t  cell_start;
 
-          ras.ycells = (PCell*)ras.buffer;
-          ras.ycount = band->max - band->min;
-
-          cell_start = (long)sizeof ( PCell ) * ras.ycount;
-          cell_mod   = cell_start % (long)sizeof ( TCell );
-          if ( cell_mod > 0 )
-            cell_start += (long)sizeof ( TCell ) - cell_mod;
 
-          cell_end  = ras.buffer_size;
-          cell_end -= cell_end % (long)sizeof ( TCell );
+          cell_start = ( ycount * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
+                       sizeof ( TCell );
 
-          cells_max = (PCell)( (char*)ras.buffer + cell_end );
-          ras.cells = (PCell)( (char*)ras.buffer + cell_start );
-          if ( ras.cells >= cells_max )
+          if ( FT_MAX_GRAY_POOL - cell_start < 2 )
             goto ReduceBands;
 
-          ras.max_cells = cells_max - ras.cells;
-          if ( ras.max_cells < 2 )
-            goto ReduceBands;
+          ras.cells     = buffer + cell_start;
+          ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - cell_start );
 
-          for ( yindex = 0; yindex < ras.ycount; yindex++ )
-            ras.ycells[yindex] = NULL;
+          ras.ycells = (PCell*)buffer;
+          while ( ycount )
+            ras.ycells[--ycount] = NULL;
         }
 
         ras.num_cells = 0;
@@ -2024,12 +1963,17 @@ typedef ptrdiff_t  FT_PtrDist;
 
         if ( !error )
         {
-          gray_sweep( RAS_VAR_ &ras.target );
+          gray_sweep( RAS_VAR );
           band--;
           continue;
         }
         else if ( error != ErrRaster_Memory_Overflow )
+        {
+#ifdef __REACTOS__
+          free(buffer);
+#endif
           return 1;
+        }
 
       ReduceBands:
         /* render pool overflow; we will reduce the render band by half */
@@ -2041,15 +1985,13 @@ typedef ptrdiff_t  FT_PtrDist;
         /* be some problems.                                     */
         if ( middle == bottom )
         {
-#ifdef FT_DEBUG_LEVEL_TRACE
           FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
+#ifdef __REACTOS__
+          free(buffer);
 #endif
           return 1;
         }
 
-        if ( bottom-top >= ras.band_size )
-          ras.band_shoot++;
-
         band[1].min = bottom;
         band[1].max = middle;
         band[0].min = middle;
@@ -2058,34 +2000,24 @@ typedef ptrdiff_t  FT_PtrDist;
       } while ( band >= bands );
     }
 
-    if ( ras.band_shoot > 8 && ras.band_size > 16 )
-      ras.band_size = ras.band_size / 2;
+#ifdef __REACTOS__
+    free(buffer);
+#endif
 
     return 0;
   }
 
 
   static int
-  gray_raster_render( gray_PRaster             raster,
+  gray_raster_render( FT_Raster                raster,
                       const FT_Raster_Params*  params )
   {
     const FT_Outline*  outline     = (const FT_Outline*)params->source;
     const FT_Bitmap*   target_map  = params->target;
+    FT_BBox            cbox, clip;
 
-#ifdef __REACTOS__
-    gray_TWorker *worker;
-    int ret;
-    TCell *buffer;
-    long buffer_size = FT_MAX(FT_RENDER_POOL_SIZE, 2048);
-#else
     gray_TWorker  worker[1];
 
-    TCell  buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( TCell )];
-    long   buffer_size = sizeof ( buffer );
-#endif
-    int    band_size   = (int)( buffer_size /
-                                (long)( sizeof ( TCell ) * 8 ) );
-
 
     if ( !raster )
       return FT_THROW( Invalid_Argument );
@@ -2122,41 +2054,51 @@ typedef ptrdiff_t  FT_PtrDist;
     if ( !( params->flags & FT_RASTER_FLAG_AA ) )
       return FT_THROW( Invalid_Mode );
 
-#ifdef __REACTOS__
-    worker = malloc(sizeof(gray_TWorker));
-#endif
+    FT_Outline_Get_CBox( outline, &cbox );
+
+    /* reject too large outline coordinates */
+    if ( cbox.xMin < -0x1000000L || cbox.xMax > 0x1000000L ||
+         cbox.yMin < -0x1000000L || cbox.yMax > 0x1000000L )
+      return FT_THROW( Invalid_Outline );
+
+    /* truncate the bounding box to integer pixels */
+    cbox.xMin = cbox.xMin >> 6;
+    cbox.yMin = cbox.yMin >> 6;
+    cbox.xMax = ( cbox.xMax + 63 ) >> 6;
+    cbox.yMax = ( cbox.yMax + 63 ) >> 6;
 
     /* compute clipping box */
     if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
     {
       /* compute clip box from target pixmap */
-      ras.clip_box.xMin = 0;
-      ras.clip_box.yMin = 0;
-      ras.clip_box.xMax = (FT_Pos)target_map->width;
-      ras.clip_box.yMax = (FT_Pos)target_map->rows;
+      clip.xMin = 0;
+      clip.yMin = 0;
+      clip.xMax = (FT_Pos)target_map->width;
+      clip.yMax = (FT_Pos)target_map->rows;
     }
     else if ( params->flags & FT_RASTER_FLAG_CLIP )
-      ras.clip_box = params->clip_box;
+      clip = params->clip_box;
     else
     {
-      ras.clip_box.xMin = -32768L;
-      ras.clip_box.yMin = -32768L;
-      ras.clip_box.xMax =  32767L;
-      ras.clip_box.yMax =  32767L;
+      clip.xMin = -32768L;
+      clip.yMin = -32768L;
+      clip.xMax =  32767L;
+      clip.yMax =  32767L;
     }
 
-#ifdef __REACTOS__
-    buffer = malloc(buffer_size);
-#endif
+    /* clip to target bitmap, exit if nothing to do */
+    ras.min_ex = FT_MAX( cbox.xMin, clip.xMin );
+    ras.min_ey = FT_MAX( cbox.yMin, clip.yMin );
+    ras.max_ex = FT_MIN( cbox.xMax, clip.xMax );
+    ras.max_ey = FT_MIN( cbox.yMax, clip.yMax );
 
-    gray_init_cells( RAS_VAR_ buffer, buffer_size );
+    if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
+      return 0;
+
+    ras.count_ex = ras.max_ex - ras.min_ex;
+    ras.count_ey = ras.max_ey - ras.min_ey;
 
     ras.outline        = *outline;
-    ras.num_cells      = 0;
-    ras.invalid        = 1;
-    ras.band_size      = band_size;
-    ras.num_gray_spans = 0;
-    ras.span_y         = 0;
 
     if ( params->flags & FT_RASTER_FLAG_DIRECT )
     {
@@ -2170,14 +2112,7 @@ typedef ptrdiff_t  FT_PtrDist;
       ras.render_span_data = &ras;
     }
 
-#ifdef __REACTOS__
-    ret = gray_convert_glyph(RAS_VAR);
-    free(worker);
-    free(buffer);
-    return ret;
-#else
     return gray_convert_glyph( RAS_VAR );
-#endif
   }
 
 
@@ -2243,9 +2178,9 @@ typedef ptrdiff_t  FT_PtrDist;
 
 
   static void
-  gray_raster_reset( FT_Raster  raster,
-                     char*      pool_base,
-                     long       pool_size )
+  gray_raster_reset( FT_Raster       raster,
+                     unsigned char*  pool_base,
+                     unsigned long   pool_size )
   {
     FT_UNUSED( raster );
     FT_UNUSED( pool_base );
index 8da10b8..9b28780 100644 (file)
@@ -390,7 +390,7 @@ class  HtmlFormatter( Formatter ):
         """Convert a code sequence to HTML."""
         line = code_header + '\n'
         for l in lines:
-            line = line + html_quote( l ) + '\n'
+            line = line + html_quote( l ).rstrip() + '\n'
 
         return line + code_footer
 
index bbebabd..c9d4081 100644 (file)
       FT_UInt*  interpreter_version = (FT_UInt*)value;
 
 
-#ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( *interpreter_version != TT_INTERPRETER_VERSION_35 )
-        error = FT_ERR( Unimplemented_Feature );
-      else
+      if ( *interpreter_version == TT_INTERPRETER_VERSION_35
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+           || *interpreter_version == TT_INTERPRETER_VERSION_38
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+           || *interpreter_version == TT_INTERPRETER_VERSION_40
 #endif
+         )
         driver->interpreter_version = *interpreter_version;
+      else
+        error = FT_ERR( Unimplemented_Feature );
 
       return error;
     }
index 4ab6603..8be9b6a 100644 (file)
                   FT_UInt    glyph_index )
   {
     TT_Face    face   = loader->face;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
 
     loader->top_bearing  = top_bearing;
     loader->vadvance     = advance_height;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
          loader->exec                                             )
     {
       /* backwards compatibility mode on and off.                   */
       sph_set_tweaks( loader, glyph_index );
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     if ( !loader->linear_def )
     {
       load->glyph->control_len  = n_ins;
       load->glyph->control_data = load->exec->glyphIns;
 
-      FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
+      if ( n_ins )
+        FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
     }
 
 #endif /* TT_USE_BYTECODE_INTERPRETER */
   TT_Hint_Glyph( TT_Loader  loader,
                  FT_Bool    is_composite )
   {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
+    defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
     TT_Face    face   = loader->face;
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
 
 #endif
 
-    /* save glyph phantom points */
-    loader->pp1 = zone->cur[zone->n_points - 4];
-    loader->pp2 = zone->cur[zone->n_points - 3];
-    loader->pp3 = zone->cur[zone->n_points - 2];
-    loader->pp4 = zone->cur[zone->n_points - 1];
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* Save possibly modified glyph phantom points unless in v40 backwards */
+    /* compatibility mode, where no movement on the x axis means no reason */
+    /* to change bearings or advance widths.                               */
+    if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
+            !loader->exec->backwards_compatibility ) )
+    {
+#endif
+      loader->pp1 = zone->cur[zone->n_points - 4];
+      loader->pp2 = zone->cur[zone->n_points - 3];
+      loader->pp3 = zone->cur[zone->n_points - 2];
+      loader->pp4 = zone->cur[zone->n_points - 1];
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    }
+#endif
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
     {
       if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
       else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
         FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     return FT_Err_Ok;
   }
     }
 
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       TT_Face    face   = loader->face;
       TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 
       FT_Bool  do_scale = FALSE;
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
       }
       else
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
         /* scale the glyph */
                                             : -subglyph->transform.yx;
         int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
                                             : -subglyph->transform.xy;
-        int  d = subglyph->transform.yy > 0 ? subglyph->transform.yy
+        int  d = subglyph->transform.yy > 0 ?  subglyph->transform.yy
                                             : -subglyph->transform.yy;
         int  m = a > b ? a : b;
         int  n = c > d ? c : d;
    * (3) for everything else.
    *
    */
+  static void
+  tt_loader_set_pp( TT_Loader  loader )
+  {
+    FT_Bool  subpixel_hinting = 0;
+    FT_Bool  grayscale        = 0;
+    FT_Bool  use_aw_2         = 0;
+
 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
+#endif
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+    {
+      subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting
+                                      : 0;
+      grayscale        = loader->exec ? loader->exec->grayscale
+                                      : 0;
+    }
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+    {
+      subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting_lean
+                                      : 0;
+      grayscale        = loader->exec ? loader->exec->grayscale_cleartype
+                                      : 0;
+    }
+#endif
+
+    use_aw_2 = (FT_Bool)( subpixel_hinting && grayscale );
+
+    loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
+    loader->pp1.y = 0;
+    loader->pp2.x = loader->pp1.x + loader->advance;
+    loader->pp2.y = 0;
+
+    loader->pp3.x = use_aw_2 ? loader->advance / 2 : 0;
+    loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
+    loader->pp4.x = use_aw_2 ? loader->advance / 2 : 0;
+    loader->pp4.y = loader->pp3.y - loader->vadvance;
+  }
+
+
+  /* a utility function to retrieve i-th node from given FT_List */
+  static FT_ListNode
+  ft_list_get_node_at( FT_List  list,
+                       FT_UInt  index )
+  {
+    FT_ListNode  cur;
+
 
-#define TT_LOADER_SET_PP( loader )                                          \
-          do                                                                \
-          {                                                                 \
-            FT_Bool  subpixel_hinting_ = loader->exec                       \
-                                           ? loader->exec->subpixel_hinting \
-                                           : 0;                             \
-            FT_Bool  grayscale_        = loader->exec                       \
-                                           ? loader->exec->grayscale        \
-                                           : 0;                             \
-            FT_Bool  use_aw_2_         = (FT_Bool)( subpixel_hinting_ &&    \
-                                                    grayscale_        );    \
-                                                                            \
-                                                                            \
-            (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
-            (loader)->pp1.y = 0;                                            \
-            (loader)->pp2.x = (loader)->pp1.x + (loader)->advance;          \
-            (loader)->pp2.y = 0;                                            \
-                                                                            \
-            (loader)->pp3.x = use_aw_2_ ? (loader)->advance / 2 : 0;        \
-            (loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing;  \
-            (loader)->pp4.x = use_aw_2_ ? (loader)->advance / 2 : 0;        \
-            (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
-          } while ( 0 )
-
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-#define TT_LOADER_SET_PP( loader )                                          \
-          do                                                                \
-          {                                                                 \
-            (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
-            (loader)->pp1.y = 0;                                            \
-            (loader)->pp2.x = (loader)->pp1.x + (loader)->advance;          \
-            (loader)->pp2.y = 0;                                            \
-                                                                            \
-            (loader)->pp3.x = 0;                                            \
-            (loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing;  \
-            (loader)->pp4.x = 0;                                            \
-            (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
-          } while ( 0 )
-
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+    if ( !list )
+      return NULL;
+
+    for ( cur = list->head; cur; cur = cur->next )
+    {
+      if ( !index )
+        return cur;
+
+      index--;
+    }
+
+    return NULL;
+  }
 
 
   /*************************************************************************/
 
       /* must initialize points before (possibly) overriding */
       /* glyph metrics from the incremental interface        */
-      TT_LOADER_SET_PP( loader );
+      tt_loader_set_pp( loader );
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
       tt_get_metrics_incr_overrides( loader, glyph_index );
 
     /* must initialize phantom points before (possibly) overriding */
     /* glyph metrics from the incremental interface                */
-    TT_LOADER_SET_PP( loader );
+    tt_loader_set_pp( loader );
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     tt_get_metrics_incr_overrides( loader, glyph_index );
       FT_UInt   start_contour;
       FT_ULong  ins_pos;  /* position of composite instructions, if any */
 
+      FT_ListNode  node, node2;
+
 
       /*
        * We store the glyph index directly in the `node->data' pointer,
        * pointers with a width of at least 32 bits.
        */
 
+
+      /* clear the nodes filled by sibling chains */
+      node = ft_list_get_node_at( &loader->composites, recurse_count );
+      for ( node2 = node; node2; node2 = node2->next )
+        node2->data = (void*)ULONG_MAX;
+
       /* check whether we already have a composite glyph with this index */
       if ( FT_List_Find( &loader->composites,
                          (void*)(unsigned long)glyph_index ) )
         error = FT_THROW( Invalid_Composite );
         goto Exit;
       }
-      else
-      {
-        FT_ListNode  node = NULL;
 
+      else if ( node )
+        node->data = (void*)(unsigned long)glyph_index;
 
+      else
+      {
         if ( FT_NEW( node ) )
           goto Exit;
         node->data = (void*)(unsigned long)glyph_index;
         outline.n_points   = (short)( gloader->current.num_subglyphs + 4 );
         outline.n_contours = outline.n_points;
 
+        outline.points   = NULL;
+        outline.tags     = NULL;
+        outline.contours = NULL;
+
         if ( FT_NEW_ARRAY( points, outline.n_points )   ||
              FT_NEW_ARRAY( tags, outline.n_points )     ||
              FT_NEW_ARRAY( contours, outline.n_points ) )
                          FT_UInt    glyph_index )
   {
     TT_Face    face   = loader->face;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
+    defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
 #endif
 
     glyph->metrics.horiBearingY = bbox.yMax;
     glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
 
-    /* adjust advance width to the value contained in the hdmx table */
-    /* unless FT_LOAD_COMPUTE_METRICS is set                         */
-    if ( !face->postscript.isFixedPitch                    &&
-         IS_HINTED( loader->load_flags )                   &&
-         !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
+    /* Adjust advance width to the value contained in the hdmx table    */
+    /* unless FT_LOAD_COMPUTE_METRICS is set or backwards compatibility */
+    /* mode of the v40 interpreter is active.  See `ttinterp.h' for     */
+    /* details on backwards compatibility mode.                         */
+    if (
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+         !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
+            ( loader->exec && loader->exec->backwards_compatibility  ) ) &&
+#endif
+         !face->postscript.isFixedPitch                                  &&
+         IS_HINTED( loader->load_flags )                                 &&
+         !( loader->load_flags & FT_LOAD_COMPUTE_METRICS )               )
     {
       FT_Byte*  widthp;
 
                                            size->root.metrics.x_ppem,
                                            glyph_index );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
       }
       else
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
         if ( widthp )
 #ifdef TT_USE_BYTECODE_INTERPRETER
     FT_Bool    pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
 #endif
+#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
+    defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
+#endif
 
 
     face   = (TT_Face)glyph->face;
     if ( IS_HINTED( load_flags ) && !glyf_table_only )
     {
       TT_ExecContext  exec;
-      FT_Bool         grayscale;
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
+      FT_Bool         grayscale = TRUE;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      FT_Bool         subpixel_hinting_lean;
+      FT_Bool         grayscale_cleartype;
+#endif
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       FT_Bool  subpixel_hinting = FALSE;
 
 #if 0
       FT_Bool  subpixel_positioned;
       FT_Bool  gray_cleartype;
 #endif
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       FT_Bool  reexecute = FALSE;
 
       if ( !exec )
         return FT_THROW( Could_Not_Find_Context );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+      {
+        subpixel_hinting_lean   = TRUE;
+        grayscale_cleartype     = !FT_BOOL( load_flags         &
+                                            FT_LOAD_TARGET_LCD     ||
+                                            load_flags           &
+                                            FT_LOAD_TARGET_LCD_V   );
+        exec->vertical_lcd_lean = FT_BOOL( load_flags           &
+                                           FT_LOAD_TARGET_LCD_V );
+      }
+      else
+      {
+        subpixel_hinting_lean   = FALSE;
+        grayscale_cleartype     = FALSE;
+        exec->vertical_lcd_lean = FALSE;
+      }
+#endif
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
       }
       else
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-      {
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+        grayscale = FT_BOOL( !subpixel_hinting_lean               &&
+                             FT_LOAD_TARGET_MODE( load_flags ) !=
+                               FT_RENDER_MODE_MONO                );
+      else
+#endif
         grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
-                             FT_RENDER_MODE_MONO );
-      }
+                               FT_RENDER_MODE_MONO             );
 
       error = TT_Load_Context( exec, face, size );
       if ( error )
         return error;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
       }
       else
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+        if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+        {
+          /* a change from mono to subpixel rendering (and vice versa) */
+          /* requires a re-execution of the CVT program                */
+          if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
+          {
+            FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
+                        " re-executing `prep' table\n" ));
+
+            exec->subpixel_hinting_lean = subpixel_hinting_lean;
+            reexecute                   = TRUE;
+          }
+
+          /* a change from colored to grayscale subpixel rendering (and */
+          /* vice versa) requires a re-execution of the CVT program     */
+          if ( grayscale_cleartype != exec->grayscale_cleartype )
+          {
+            FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
+                        " re-executing `prep' table\n" ));
+
+            exec->grayscale_cleartype = grayscale_cleartype;
+            reexecute                 = TRUE;
+          }
+        }
+#endif
+
         /* a change from mono to grayscale rendering (and vice versa) */
         /* requires a re-execution of the CVT program                 */
         if ( grayscale != exec->grayscale )
       if ( exec->GS.instruct_control & 2 )
         exec->GS = tt_default_graphics_state;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       /* check whether we have a font hinted for ClearType --           */
       /* note that this flag can also be modified in a glyph's bytecode */
-      if ( exec->GS.instruct_control & 4 )
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+           exec->GS.instruct_control & 4                            )
         exec->ignore_x_mode = 0;
 #endif
 
index 5f760a2..9a02c5a 100644 (file)
       for ( i = 0; i < blend->tuplecount; i++ )
       {
         FT_TRACE5(( "  [ " ));
-        for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; j++ )
+        for ( j = 0; j < (FT_UInt)gvar_head.axisCount; j++ )
         {
           blend->tuplecoords[i * gvar_head.axisCount + j] =
             FT_GET_SHORT() * 4;                 /* convert to FT_Fixed */
     {
       FT_TRACE6(( "    axis coordinate %d (%.4f):\n",
                   i, blend->normalizedcoords[i] / 65536.0 ));
+      if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
+        FT_TRACE6(( "      intermediate coordinates %d (%.4f, %.4f):\n",
+                    i,
+                    im_start_coords[i] / 65536.0,
+                    im_end_coords[i] / 65536.0 ));
 
       /* It's not clear why (for intermediate tuples) we don't need     */
       /* to check against start/end -- the documentation says we don't. */
         continue;
       }
 
-      else if ( blend->normalizedcoords[i] == 0 )
+      if ( blend->normalizedcoords[i] == 0 )
       {
         FT_TRACE6(( "      axis coordinate is zero, stop\n" ));
         apply = 0;
         break;
       }
 
-      else if ( ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
-                ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) )
+      if ( blend->normalizedcoords[i] == tuple_coords[i] )
       {
-        FT_TRACE6(( "      tuple coordinate value %.4f is exceeded, stop\n",
+        FT_TRACE6(( "      tuple coordinate value %.4f fits perfectly\n",
                     tuple_coords[i] / 65536.0 ));
-        apply = 0;
-        break;
+        /* `apply' does not change */
+        continue;
       }
 
-      else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
+      if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
       {
-        FT_TRACE6(( "      tuple coordinate value %.4f fits\n",
-                    tuple_coords[i] / 65536.0 ));
         /* not an intermediate tuple */
-        apply = FT_MulFix( apply,
-                           blend->normalizedcoords[i] > 0
-                             ? blend->normalizedcoords[i]
-                             : -blend->normalizedcoords[i] );
-      }
 
-      else if ( blend->normalizedcoords[i] < im_start_coords[i] ||
-                blend->normalizedcoords[i] > im_end_coords[i]   )
-      {
-        FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] is exceeded,"
-                    " stop\n",
-                    im_start_coords[i] / 65536.0,
-                    im_end_coords[i] / 65536.0 ));
-        apply = 0;
-        break;
-      }
+        if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) ||
+             blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) )
+        {
+          FT_TRACE6(( "      tuple coordinate value %.4f is exceeded, stop\n",
+                      tuple_coords[i] / 65536.0 ));
+          apply = 0;
+          break;
+        }
 
-      else if ( blend->normalizedcoords[i] < tuple_coords[i] )
-      {
-        FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] fits\n",
-                    im_start_coords[i] / 65536.0,
-                    im_end_coords[i] / 65536.0 ));
+        FT_TRACE6(( "      tuple coordinate value %.4f fits\n",
+                    tuple_coords[i] / 65536.0 ));
         apply = FT_MulDiv( apply,
-                           blend->normalizedcoords[i] - im_start_coords[i],
-                           tuple_coords[i] - im_start_coords[i] );
+                           blend->normalizedcoords[i],
+                           tuple_coords[i] );
       }
-
       else
       {
-        FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] fits\n",
-                    im_start_coords[i] / 65536.0,
-                    im_end_coords[i] / 65536.0 ));
-        apply = FT_MulDiv( apply,
-                           im_end_coords[i] - blend->normalizedcoords[i],
-                           im_end_coords[i] - tuple_coords[i] );
+        /* intermediate tuple */
+
+        if ( blend->normalizedcoords[i] < im_start_coords[i] ||
+             blend->normalizedcoords[i] > im_end_coords[i]   )
+        {
+          FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] is exceeded,"
+                      " stop\n",
+                      im_start_coords[i] / 65536.0,
+                      im_end_coords[i] / 65536.0 ));
+          apply = 0;
+          break;
+        }
+
+        else if ( blend->normalizedcoords[i] < tuple_coords[i] )
+        {
+          FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] fits\n",
+                      im_start_coords[i] / 65536.0,
+                      im_end_coords[i] / 65536.0 ));
+          apply = FT_MulDiv( apply,
+                             blend->normalizedcoords[i] - im_start_coords[i],
+                             tuple_coords[i] - im_start_coords[i] );
+        }
+
+        else
+        {
+          FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] fits\n",
+                      im_start_coords[i] / 65536.0,
+                      im_end_coords[i] / 65536.0 ));
+          apply = FT_MulDiv( apply,
+                             im_end_coords[i] - blend->normalizedcoords[i],
+                             im_end_coords[i] - tuple_coords[i] );
+        }
       }
     }
 
index ccbb1d7..2e3f9ef 100644 (file)
 #define FT_COMPONENT  trace_ttinterp
 
 
-#define SUBPIXEL_HINTING                                                     \
+#define NO_SUBPIXEL_HINTING                                                  \
+          ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
+            TT_INTERPRETER_VERSION_35 )
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+#define SUBPIXEL_HINTING_INFINALITY                                          \
           ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
             TT_INTERPRETER_VERSION_38 )
+#endif
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+#define SUBPIXEL_HINTING_MINIMAL                                             \
+          ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
+            TT_INTERPRETER_VERSION_40 )
+#endif
 
 #define PROJECT( v1, v2 )                                                \
           exc->func_project( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
     exec->stackSize = 0;
     exec->glyphSize = 0;
 
-    exec->stack     = NULL;
-    exec->glyphIns  = NULL;
+    exec->stack    = NULL;
+    exec->glyphIns = NULL;
 
     exec->face = NULL;
     exec->size = NULL;
   static FT_Short
   GetShortIns( TT_ExecContext  exc )
   {
-    /* Reading a byte stream so there is no endianess (DaveP) */
+    /* Reading a byte stream so there is no endianness (DaveP) */
     exc->IP += 2;
     return (FT_Short)( ( exc->code[exc->IP - 2] << 8 ) +
                          exc->code[exc->IP - 1]      );
   /* <InOut>                                                               */
   /*    zone     :: The affected glyph zone.                               */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    See `ttinterp.h' for details on backwards compatibility mode.      */
+  /*    `Touches' the point.                                               */
+  /*                                                                       */
   static void
   Direct_Move( TT_ExecContext  exc,
                TT_GlyphZone    zone,
 
     if ( v != 0 )
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( !SUBPIXEL_HINTING                                      ||
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY                            &&
            ( !exc->ignore_x_mode                                ||
              ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+        zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+      else
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      /* Exception to the post-IUP curfew: Allow the x component of */
+      /* diagonal moves, but only post-IUP.  DejaVu tries to adjust */
+      /* diagonal stems like on `Z' and `z' post-IUP.               */
+      if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility )
+        zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+      else
+#endif
+
+      if ( NO_SUBPIXEL_HINTING )
         zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
 
     if ( v != 0 )
     {
-      zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( !( SUBPIXEL_HINTING_MINIMAL     &&
+              exc->backwards_compatibility &&
+              exc->iupx_called             &&
+              exc->iupy_called             ) )
+#endif
+        zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
     }
   /*                                                                       */
   /*   The following versions are used whenever both vectors are both      */
   /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
+  /*   See `ttinterp.h' for details on backwards compatibility mode.       */
   /*                                                                       */
   /*************************************************************************/
 
                  FT_UShort       point,
                  FT_F26Dot6      distance )
   {
-    FT_UNUSED( exc );
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode )
+      zone->cur[point].x += distance;
+    else
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility )
+      zone->cur[point].x += distance;
+    else
+#endif
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( !SUBPIXEL_HINTING   ||
-         !exc->ignore_x_mode )
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+    if ( NO_SUBPIXEL_HINTING )
       zone->cur[point].x += distance;
 
     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
   {
     FT_UNUSED( exc );
 
-    zone->cur[point].y += distance;
-    zone->tags[point]  |= FT_CURVE_TAG_TOUCH_Y;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    if ( !( SUBPIXEL_HINTING_MINIMAL             &&
+            exc->backwards_compatibility         &&
+            exc->iupx_called && exc->iupy_called ) )
+#endif
+      zone->cur[point].y += distance;
+
+    zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
   }
 
 
                         FT_F26Dot6      distance,
                         FT_F26Dot6      compensation )
   {
-    FT_F26Dot6 val;
+    FT_F26Dot6  val;
 
     FT_UNUSED( exc );
 
   /*    Rounded distance.                                                  */
   /*                                                                       */
   /* <Note>                                                                */
-  /*    The TrueType specification says very few about the relationship    */
+  /*    The TrueType specification says very little about the relationship */
   /*    between rounding and engine compensation.  However, it seems from  */
   /*    the description of super round that we should add the compensation */
   /*    before rounding.                                                   */
   Ins_RS( TT_ExecContext  exc,
           FT_Long*        args )
   {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-
     FT_ULong  I = (FT_ULong)args[0];
 
 
     }
     else
     {
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       /* subpixel hinting - avoid Typeman Dstroke and */
       /* IStroke and Vacuform rounds                  */
-      if ( SUBPIXEL_HINTING                            &&
+      if ( SUBPIXEL_HINTING_INFINALITY                 &&
            exc->ignore_x_mode                          &&
            ( ( I == 24                             &&
                ( exc->face->sph_found_func_flags &
                exc->iup_called                     ) ) )
         args[0] = 0;
       else
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
         args[0] = exc->storage[I];
     }
-
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-    FT_ULong  I = (FT_ULong)args[0];
-
-
-    if ( BOUNDSL( I, exc->storeSize ) )
-    {
-      if ( exc->pedantic_hinting )
-        ARRAY_BOUND_ERROR;
-      else
-        args[0] = 0;
-    }
-    else
-      args[0] = exc->storage[I];
-
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
   }
 
 
     TT_DefRecord*  rec;
     TT_DefRecord*  limit;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* arguments to opcodes are skipped by `SKIP_Code' */
     FT_Byte    opcode_pattern[9][12] = {
                  /* #0 inline delta function 1 */
     FT_UShort  opcode_pointer[9] = {  0, 0, 0, 0, 0, 0, 0, 0, 0 };
     FT_UShort  opcode_size[9]    = { 12, 8, 8, 6, 7, 4, 5, 4, 2 };
     FT_UShort  i;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
     /* some font programs are broken enough to redefine functions! */
     if ( n > exc->maxFunc )
       exc->maxFunc = (FT_UInt16)n;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* We don't know for sure these are typeman functions, */
     /* however they are only active when RS 22 is called   */
     if ( n >= 64 && n <= 66 )
     while ( SkipCode( exc ) == SUCCESS )
     {
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
-      if ( SUBPIXEL_HINTING )
+      if ( SUBPIXEL_HINTING_INFINALITY )
       {
         for ( i = 0; i < opcode_patterns; i++ )
         {
             ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
       }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       switch ( exc->opcode )
       {
     TT_CallRec*  pRec;
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     exc->sph_in_func_flags = 0x0000;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     if ( exc->callTop <= 0 )     /* We encountered an ENDF without a call */
     {
     if ( !def->active )
       goto Fail;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                               &&
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                                    &&
          exc->ignore_x_mode                                             &&
          ( ( exc->iup_called                                        &&
              ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
       goto Fail;
     else
       exc->sph_in_func_flags = def->sph_fdef_flags;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     /* check the call stack */
     if ( exc->callTop >= exc->callSize )
     if ( !def->active )
       goto Fail;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                    &&
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                         &&
          exc->ignore_x_mode                                  &&
          ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) )
       goto Fail;
     else
       exc->sph_in_func_flags = def->sph_fdef_flags;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     /* check stack */
     if ( exc->callTop >= exc->callSize )
       }
     }
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
-    if ( SUBPIXEL_HINTING   &&
-         exc->ignore_x_mode &&
-         FT_ABS( D ) == 64  )
+    if ( SUBPIXEL_HINTING_INFINALITY &&
+         exc->ignore_x_mode          &&
+         FT_ABS( D ) == 64           )
       D += 1;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     args[0] = D;
   }
     exc->GS.instruct_control &= ~(FT_Byte)Kf;
     exc->GS.instruct_control |= (FT_Byte)L;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    /* INSTCTRL modifying flag 3 also has an effect */
-    /* outside of the CVT program                   */
     if ( K == 3 )
-      exc->ignore_x_mode = FT_BOOL( L == 4 );
+    {
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      /* INSTCTRL modifying flag 3 also has an effect */
+      /* outside of the CVT program                   */
+      if ( SUBPIXEL_HINTING_INFINALITY )
+        exc->ignore_x_mode = FT_BOOL( L == 4 );
+#endif
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      /* Native ClearType fonts sign a waiver that turns off all backwards */
+      /* compatibility hacks and lets them program points to the grid like */
+      /* it's 1996.  They might sign a waiver for just one glyph, though.  */
+      if ( SUBPIXEL_HINTING_MINIMAL )
+        exc->backwards_compatibility = !FT_BOOL( L == 4 );
 #endif
+    }
   }
 
 
     FT_UShort  point;
 
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( SUBPIXEL_HINTING_MINIMAL     &&
+         exc->backwards_compatibility &&
+         exc->iupx_called             &&
+         exc->iupy_called             )
+      goto Fail;
+#endif
+
     if ( exc->top < exc->GS.loop )
     {
       if ( exc->pedantic_hinting )
     FT_UShort  I, K, L;
 
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( SUBPIXEL_HINTING_MINIMAL     &&
+         exc->backwards_compatibility &&
+         exc->iupx_called             &&
+         exc->iupy_called             )
+      return;
+#endif
+
     K = (FT_UShort)args[1];
     L = (FT_UShort)args[0];
 
     FT_UShort  I, K, L;
 
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    if ( SUBPIXEL_HINTING_MINIMAL     &&
+         exc->backwards_compatibility &&
+         exc->iupx_called             &&
+         exc->iupy_called             )
+      return;
+#endif
+
     K = (FT_UShort)args[1];
     L = (FT_UShort)args[0];
 
   }
 
 
+  /* See `ttinterp.h' for details on backwards compatibility mode. */
   static void
   Move_Zp2_Point( TT_ExecContext  exc,
                   FT_UShort       point,
   {
     if ( exc->GS.freeVector.x != 0 )
     {
-      exc->zp2.cur[point].x += dx;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( !( SUBPIXEL_HINTING_MINIMAL     &&
+              exc->backwards_compatibility ) )
+#endif
+        exc->zp2.cur[point].x += dx;
+
       if ( touch )
         exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
     }
 
     if ( exc->GS.freeVector.y != 0 )
     {
-      exc->zp2.cur[point].y += dy;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( !( SUBPIXEL_HINTING_MINIMAL     &&
+              exc->backwards_compatibility &&
+              exc->iupx_called             &&
+              exc->iupy_called             ) )
+#endif
+        exc->zp2.cur[point].y += dy;
+
       if ( touch )
         exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
     }
         }
       }
       else
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       /* doesn't follow Cleartype spec but produces better result */
-      if ( SUBPIXEL_HINTING   &&
-           exc->ignore_x_mode )
+      if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode )
         Move_Zp2_Point( exc, point, 0, dy, TRUE );
       else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
         Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
       exc->GS.loop--;
   {
     FT_F26Dot6  dx, dy;
     FT_UShort   point;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     FT_Int      B1, B2;
 #endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    FT_Bool     in_twilight = exc->GS.gep0 == 0 || \
+                              exc->GS.gep1 == 0 || \
+                              exc->GS.gep2 == 0;
+#endif
+
 
 
     if ( exc->top < exc->GS.loop + 1 )
         }
       }
       else
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY )
       {
         /*  If not using ignore_x_mode rendering, allow ZP2 move.        */
         /*  If inline deltas aren't allowed, skip ZP2 move.              */
         /*   - the glyph is specifically set to allow SHPIX moves        */
         /*   - the move is on a previously Y-touched point               */
 
-        if ( SUBPIXEL_HINTING   &&
-             exc->ignore_x_mode )
+        if ( exc->ignore_x_mode )
         {
           /* save point for later comparison */
           if ( exc->GS.freeVector.y != 0 )
         else
           Move_Zp2_Point( exc, point, dx, dy, TRUE );
       }
+      else
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+      if ( SUBPIXEL_HINTING_MINIMAL     &&
+           exc->backwards_compatibility )
+      {
+        /* Special case: allow SHPIX to move points in the twilight zone.  */
+        /* Otherwise, treat SHPIX the same as DELTAP.  Unbreaks various    */
+        /* fonts such as older versions of Rokkitt and DTL Argo T Light    */
+        /* that would glitch severly after calling ALIGNRP after a blocked */
+        /* SHPIX.                                                          */
+        if ( in_twilight                                                ||
+             ( !( exc->iupx_called && exc->iupy_called )              &&
+               ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
+                 ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y )    ) ) )
+          Move_Zp2_Point( exc, point, 0, dy, TRUE );
+      }
+      else
+#endif
+        Move_Zp2_Point( exc, point, dx, dy, TRUE );
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     Skip:
-
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-      Move_Zp2_Point( exc, point, dx, dy, TRUE );
-
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
+#endif
       exc->GS.loop--;
     }
 
   Ins_MSIRP( TT_ExecContext  exc,
              FT_Long*        args )
   {
-    FT_UShort   point;
+    FT_UShort   point = 0;
     FT_F26Dot6  distance;
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    FT_F26Dot6  control_value_cutin = 0; /* pacify compiler */
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    FT_F26Dot6  control_value_cutin = 0;
 
 
-    if ( SUBPIXEL_HINTING )
+    if ( SUBPIXEL_HINTING_INFINALITY )
     {
       control_value_cutin = exc->GS.control_value_cutin;
 
            !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
         control_value_cutin = 0;
     }
-
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     point = (FT_UShort)args[0];
 
 
     distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* subpixel hinting - make MSIRP respect CVT cut-in; */
-    if ( SUBPIXEL_HINTING                                    &&
+    if ( SUBPIXEL_HINTING_INFINALITY                         &&
          exc->ignore_x_mode                                  &&
          exc->GS.freeVector.x != 0                           &&
          FT_ABS( distance - args[1] ) >= control_value_cutin )
       distance = args[1];
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     exc->func_move( exc, &exc->zp1, point, args[1] - distance );
 
     if ( ( exc->opcode & 1 ) != 0 )
     {
       cur_dist = FAST_PROJECT( &exc->zp0.cur[point] );
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING          &&
-           exc->ignore_x_mode        &&
-           exc->GS.freeVector.x != 0 )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY &&
+           exc->ignore_x_mode          &&
+           exc->GS.freeVector.x != 0   )
         distance = Round_None(
                      exc,
                      cur_dist,
     cvtEntry            = (FT_ULong)args[1];
     point               = (FT_UShort)args[0];
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                   &&
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                        &&
          exc->ignore_x_mode                                 &&
          exc->GS.freeVector.x != 0                          &&
          exc->GS.freeVector.y == 0                          &&
          !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
       control_value_cutin = 0;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     if ( BOUNDS( point,     exc->zp0.n_points ) ||
          BOUNDSL( cvtEntry, exc->cvtSize )      )
 
     if ( exc->GS.gep0 == 0 )   /* If in twilight zone */
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */
       /* Determined via experimentation and may be incorrect...         */
-      if ( !SUBPIXEL_HINTING                      ||
-           ( !exc->ignore_x_mode                ||
-             !exc->face->sph_compatibility_mode ) )
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+      if ( !( SUBPIXEL_HINTING_INFINALITY           &&
+              ( exc->ignore_x_mode                &&
+                exc->face->sph_compatibility_mode ) ) )
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
         exc->zp0.org[point].x = TT_MulFix14( distance,
                                              exc->GS.freeVector.x );
       exc->zp0.org[point].y = TT_MulFix14( distance,
                                            exc->GS.freeVector.y ),
       exc->zp0.cur[point]   = exc->zp0.org[point];
     }
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                               &&
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                    &&
          exc->ignore_x_mode                             &&
          ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
          distance > 0                                   &&
          exc->GS.freeVector.y != 0                      )
       distance = 0;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     org_dist = FAST_PROJECT( &exc->zp0.cur[point] );
 
       if ( FT_ABS( distance - org_dist ) > control_value_cutin )
         distance = org_dist;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING          &&
-           exc->ignore_x_mode        &&
-           exc->GS.freeVector.x != 0 )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY &&
+           exc->ignore_x_mode          &&
+           exc->GS.freeVector.x != 0   )
         distance = Round_None( exc,
                                distance,
                                exc->tt_metrics.compensations[0] );
   Ins_MDRP( TT_ExecContext  exc,
             FT_Long*        args )
   {
-    FT_UShort   point;
+    FT_UShort   point = 0;
     FT_F26Dot6  org_dist, distance, minimum_distance;
 
 
     minimum_distance = exc->GS.minimum_distance;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                   &&
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                        &&
          exc->ignore_x_mode                                 &&
          exc->GS.freeVector.x != 0                          &&
          !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
       minimum_distance = 0;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     point = (FT_UShort)args[0];
 
 
     if ( ( exc->opcode & 4 ) != 0 )
     {
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-      if ( SUBPIXEL_HINTING          &&
-           exc->ignore_x_mode        &&
-           exc->GS.freeVector.x != 0 )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+      if ( SUBPIXEL_HINTING_INFINALITY &&
+           exc->ignore_x_mode          &&
+           exc->GS.freeVector.x != 0   )
         distance = Round_None(
                      exc,
                      org_dist,
                 org_dist,
                 control_value_cutin,
                 minimum_distance;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     FT_Int      B1           = 0; /* pacify compiler */
     FT_Int      B2           = 0;
     FT_Bool     reverse_move = FALSE;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
     minimum_distance    = exc->GS.minimum_distance;
     point               = (FT_UShort)args[0];
     cvtEntry            = (FT_ULong)( args[1] + 1 );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                   &&
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                        &&
          exc->ignore_x_mode                                 &&
          exc->GS.freeVector.x != 0                          &&
          !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
       control_value_cutin = minimum_distance = 0;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+    else
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
 
         cvt_dist = -cvt_dist;
     }
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                          &&
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                               &&
          exc->ignore_x_mode                                        &&
          exc->GS.freeVector.y != 0                                 &&
          ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
       else if ( cur_dist > 64 && cur_dist < 84 )
         cvt_dist += 32;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     /* control value cut-in and round */
 
     else
     {
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       /* do cvt cut-in always in MIRP for sph */
-      if ( SUBPIXEL_HINTING             &&
+      if ( SUBPIXEL_HINTING_INFINALITY  &&
            exc->ignore_x_mode           &&
            exc->GS.gep0 == exc->GS.gep1 )
       {
         if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
           cvt_dist = org_dist;
       }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       distance = Round_None(
                    exc,
       }
     }
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY )
     {
       B1 = exc->zp1.cur[point].y;
 
            ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
         distance += 64;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     exc->func_move( exc, &exc->zp1, point, distance - cur_dist );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY )
     {
       B2 = exc->zp1.cur[point].y;
 
         exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) );
     }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
   Fail:
     exc->GS.rp1 = exc->GS.rp0;
     FT_F26Dot6  distance;
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING                                          &&
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY                               &&
          exc->ignore_x_mode                                        &&
          exc->iup_called                                           &&
          ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
       exc->error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     if ( exc->top < exc->GS.loop                  ||
          BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
       R.x = FT_MulDiv( val, dax, discriminant );
       R.y = FT_MulDiv( val, day, discriminant );
 
+      /* XXX: Block in backwards_compatibility and/or post-IUP? */
       exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x;
       exc->zp2.cur[point].y = exc->zp1.cur[a0].y + R.y;
     }
     {
       /* else, take the middle of the middles of A and B */
 
+      /* XXX: Block in backwards_compatibility and/or post-IUP? */
       exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x +
                                 exc->zp1.cur[a1].x +
                                 exc->zp0.cur[b0].x +
     FT_Short  contour;       /* current contour */
 
 
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* See `ttinterp.h' for details on backwards compatibility mode. */
+    /* Allow IUP until it has been called on both axes.  Immediately */
+    /* return on subsequent ones.                                    */
+    if ( SUBPIXEL_HINTING_MINIMAL     &&
+         exc->backwards_compatibility )
+    {
+      if ( exc->iupx_called && exc->iupy_called )
+        return;
+
+      if ( exc->opcode & 1 )
+        exc->iupx_called = TRUE;
+      else
+        exc->iupy_called = TRUE;
+    }
+#endif
+
     /* ignore empty outlines */
     if ( exc->pts.n_contours == 0 )
       return;
     contour = 0;
     point   = 0;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    if ( SUBPIXEL_HINTING   &&
-         exc->ignore_x_mode )
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    if ( SUBPIXEL_HINTING_INFINALITY &&
+         exc->ignore_x_mode          )
     {
       exc->iup_called = TRUE;
       if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
         return;
     }
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     do
     {
     FT_UShort  A;
     FT_ULong   C, P;
     FT_Long    B;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     FT_UShort  B1, B2;
 
 
-    if ( SUBPIXEL_HINTING                                         &&
+    if ( SUBPIXEL_HINTING_INFINALITY                              &&
          exc->ignore_x_mode                                       &&
          exc->iup_called                                          &&
          ( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
       goto Fail;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     P    = (FT_ULong)exc->func_cur_ppem( exc );
     nump = (FT_ULong)args[0];   /* some points theoretically may occur more
             B++;
           B *= 1L << ( 6 - exc->GS.delta_shift );
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
-          if ( SUBPIXEL_HINTING )
+          if ( SUBPIXEL_HINTING_INFINALITY )
           {
             /*
              *  Allow delta move if
             }
           }
           else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-            exc->func_move( exc, &exc->zp0, A, B );
+          {
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+            /* See `ttinterp.h' for details on backwards compatibility */
+            /* mode.                                                   */
+            if ( SUBPIXEL_HINTING_MINIMAL     &&
+                 exc->backwards_compatibility )
+            {
+              if ( !( exc->iupx_called && exc->iupy_called )              &&
+                   ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
+                     ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y )        ) )
+                exc->func_move( exc, &exc->zp0, A, B );
+            }
+            else
+#endif
+              exc->func_move( exc, &exc->zp0, A, B );
+          }
         }
       }
       else
   Ins_GETINFO( TT_ExecContext  exc,
                FT_Long*        args )
   {
-    FT_Long  K;
+    FT_Long    K;
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
 
 
     K = 0;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /********************************/
     /* RASTERIZER VERSION           */
     /* Selector Bit:  0             */
     /* Return Bit(s): 0-7           */
     /*                              */
-    if ( SUBPIXEL_HINTING      &&
-         ( args[0] & 1 ) != 0  &&
-         exc->subpixel_hinting )
+    if ( SUBPIXEL_HINTING_INFINALITY &&
+         ( args[0] & 1 ) != 0        &&
+         exc->subpixel_hinting       )
     {
       if ( exc->ignore_x_mode )
       {
         K = TT_INTERPRETER_VERSION_38;
     }
     else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
       if ( ( args[0] & 1 ) != 0 )
-        K = TT_INTERPRETER_VERSION_35;
+        K = driver->interpreter_version;
 
     /********************************/
     /* GLYPH ROTATED                */
       K |= 1 << 8;
 
     /********************************/
-    /* HINTING FOR GRAYSCALE        */
+    /* BI-LEVEL HINTING AND         */
+    /* GRAYSCALE RENDERING          */
     /* Selector Bit:  5             */
     /* Return Bit(s): 12            */
     /*                              */
     if ( ( args[0] & 32 ) != 0 && exc->grayscale )
       K |= 1 << 12;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    if ( SUBPIXEL_HINTING_MINIMAL )
+    {
+      /********************************/
+      /* HINTING FOR SUBPIXEL         */
+      /* Selector Bit:  6             */
+      /* Return Bit(s): 13            */
+      /*                              */
+      /* v40 does subpixel hinting by default. */
+      if ( ( args[0] & 64 ) != 0 )
+        K |= 1 << 13;
+
+      /********************************/
+      /* VERTICAL LCD SUBPIXELS?      */
+      /* Selector Bit:  8             */
+      /* Return Bit(s): 15            */
+      /*                              */
+      if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd_lean )
+        K |= 1 << 15;
+
+      /********************************/
+      /* SUBPIXEL POSITIONED?         */
+      /* Selector Bit:  10            */
+      /* Return Bit(s): 17            */
+      /*                              */
+      /* XXX: FreeType supports it, dependent on what client does? */
+      if ( ( args[0] & 1024 ) != 0 )
+        K |= 1 << 17;
+
+      /********************************/
+      /* SYMMETRICAL SMOOTHING        */
+      /* Selector Bit:  11            */
+      /* Return Bit(s): 18            */
+      /*                              */
+      /* The only smoothing method FreeType supports unless someone sets */
+      /* FT_LOAD_TARGET_MONO.                                            */
+      if ( ( args[0] & 2048 ) != 0 )
+        K |= 1 << 18;
+
+      /********************************/
+      /* CLEARTYPE HINTING AND        */
+      /* GRAYSCALE RENDERING          */
+      /* Selector Bit:  12            */
+      /* Return Bit(s): 19            */
+      /*                              */
+      /* Grayscale rendering is what FreeType does anyway unless someone */
+      /* sets FT_LOAD_TARGET_MONO or FT_LOAD_TARGET_LCD(_V)              */
+      if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype )
+        K |= 1 << 19;
+    }
+#endif
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
-    if ( SUBPIXEL_HINTING                                     &&
+    if ( SUBPIXEL_HINTING_INFINALITY                          &&
          exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 )
     {
 
       }
     }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
     args[0] = K;
   }
     FT_Long    ins_counter = 0;  /* executed instructions counter */
     FT_UShort  i;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     FT_Byte    opcode_pattern[1][2] = {
                   /* #8 TypeMan Talk Align */
                   {
     FT_UShort  opcode_patterns   = 1;
     FT_UShort  opcode_pointer[1] = { 0 };
     FT_UShort  opcode_size[1]    = { 1 };
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     exc->iup_called = FALSE;
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /* Toggle backwards compatibility according to what font says, except  */
+    /* when it's a `tricky' font that heavily relies on the interpreter to */
+    /* render glyphs correctly, e.g. DFKai-SB.  Backwards compatibility    */
+    /* hacks may break it.                                                 */
+    if ( SUBPIXEL_HINTING_MINIMAL          &&
+         !FT_IS_TRICKY( &exc->face->root ) )
+      exc->backwards_compatibility = !( exc->GS.instruct_control & 4 );
+    else
+      exc->backwards_compatibility = FALSE;
+
+    exc->iupx_called = FALSE;
+    exc->iupy_called = FALSE;
+#endif
 
     /* set PPEM and CVT functions */
     exc->tt_metrics.ratio = 0;
       exc->step_ins = TRUE;
       exc->error    = FT_Err_Ok;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
-      if ( SUBPIXEL_HINTING )
+      if ( SUBPIXEL_HINTING_INFINALITY )
       {
         for ( i = 0; i < opcode_patterns; i++ )
         {
         }
       }
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
       {
         FT_Long*  args   = exc->stack + exc->args;
index e5a02b9..df7ce51 100644 (file)
@@ -99,7 +99,7 @@ FT_BEGIN_HEADER
   } TT_CallRec, *TT_CallStack;
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
   /*************************************************************************/
   /*                                                                       */
@@ -138,7 +138,7 @@ FT_BEGIN_HEADER
 
   } SPH_Font_Class;
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
   /*************************************************************************/
@@ -247,9 +247,135 @@ FT_BEGIN_HEADER
     TT_Set_CVT_Func    func_write_cvt; /* write a cvt entry (in pixels) */
     TT_Set_CVT_Func    func_move_cvt;  /* incr a cvt entry (in pixels)  */
 
-    FT_Bool            grayscale;      /* are we hinting for grayscale? */
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    FT_Bool            grayscale;      /* bi-level hinting and */
+                                       /* grayscale rendering  */
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    /*
+     * Modern TrueType fonts are usually rendered through Microsoft's
+     * collection of rendering techniques called ClearType (e.g., subpixel
+     * rendering and subpixel hinting).  When ClearType was introduced, most
+     * fonts were not ready.  Microsoft decided to implement a backwards
+     * compatibility mode that employed several simple to complicated
+     * assumptions and tricks that modified the interpretation of the
+     * bytecode contained in these fonts to make them look ClearType-y
+     * somehow.  Most (web)fonts that were released since then have come to
+     * rely on these hacks to render correctly, even some of Microsoft's
+     * flagship ClearType fonts (Calibri, Cambria, Segoe UI).
+     *
+     * The minimal subpixel hinting code (interpreter version 40) employs a
+     * small list of font-agnostic hacks to bludgeon non-native-ClearType
+     * fonts (except tricky ones[1]) into submission.  It will not try to
+     * toggle hacks for specific fonts for performance and complexity
+     * reasons.  The focus is on modern (web)fonts rather than legacy fonts
+     * that were made for black-and-white rendering.
+     *
+     * Major hacks
+     *
+     * - Any point movement on the x axis is ignored (cf. `Direct_Move' and
+     *   `Direct_Move_X').  This has the smallest code footprint and single
+     *   biggest effect.  The ClearType way to increase resolution is
+     *   supersampling the x axis, the FreeType way is ignoring instructions
+     *   on the x axis, which gives the same result in the majority of
+     *   cases.
+     *
+     * - Points are not moved post-IUP (neither on the x nor on the y axis),
+     *   except the x component of diagonal moves post-IUP (cf.
+     *   `Direct_Move', `Direct_Move_Y', `Move_Zp2_Point').  Post-IUP
+     *   changes are commonly used to `fix' pixel patterns which has little
+     *   use outside monochrome rendering.
+     *
+     * - SHPIX and DELTAP don't execute unless moving a composite on the
+     *   y axis or moving a previously y touched point.  SHPIX additionally
+     *   denies movement on the x axis (cf. `Ins_SHPIX' and `Ins_DELTAP').
+     *   Both instructions are commonly used to `fix' pixel patterns for
+     *   monochrome or Windows's GDI rendering but make little sense for
+     *   FreeType rendering.  Both can distort the outline.  See [2] for
+     *   details.
+     *
+     * - The hdmx table and modifications to phantom points are ignored.
+     *   Bearings and advance widths remain unchanged (except rounding them
+     *   outside the interpreter!), cf. `compute_glyph_metrics' and
+     *   `TT_Hint_Glyph'.  Letting non-native-ClearType fonts modify spacing
+     *   might mess up spacing.
+     *
+     * Minor hacks
+     *
+     * - FLIPRGON, FLIPRGOFF, and FLIPPT don't execute post-IUP.  This
+     *   prevents dents in e.g. Arial-Regular's `D' and `G' glyphs at
+     *   various sizes.
+     *
+     * (Post-IUP is the state after both IUP[x] and IUP[y] have been
+     * executed.)
+     *
+     * The best results are achieved for fonts that were from the outset
+     * designed with ClearType in mind, meaning they leave the x axis mostly
+     * alone and don't mess with the `final' outline to produce more
+     * pleasing pixel patterns.  The harder the designer tried to produce
+     * very specific patterns (`superhinting') for pre-ClearType-displays,
+     * the worse the results.
+     *
+     * Microsoft defines a way to turn off backwards compatibility and
+     * interpret instructions as before (called `native ClearType')[2][3].
+     * The font designer then regains full control and is responsible for
+     * making the font work correctly with ClearType without any
+     * hand-holding by the interpreter or rasterizer[4].  The v40
+     * interpreter assumes backwards compatibility by default, which can be
+     * turned off the same way by executing the following in the control
+     * program (cf. `Ins_INSTCTRL').
+     *
+     *   #PUSH 4,3
+     *   INSTCTRL[]
+     *
+     * [1] Tricky fonts as FreeType defines them rely on the bytecode
+     *     interpreter to display correctly.  Hacks can interfere with them,
+     *     so they get treated like native ClearType fonts (v40 with
+     *     backwards compatibility turned off).  Cf. `TT_RunIns'.
+     *
+     * [2] Proposed by Microsoft's Greg Hitchcock in
+     *     https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
+     *
+     * [3] Beat Stamm describes it in more detail:
+     *     http://www.beatstamm.com/typography/RTRCh4.htm#Sec12
+     *
+     * [4] The list of `native ClearType' fonts is small at the time of this
+     *     writing; I found the following on a Windows 10 Update 1511
+     *     installation: Constantia, Corbel, Sitka, Malgun Gothic, Microsoft
+     *     JhengHei (Bold and UI Bold), Microsoft YaHei (Bold and UI Bold),
+     *     SimSun, NSimSun, and Yu Gothic.
+     *
+     */
+
+    /* Using v40 implies subpixel hinting.  Used to detect interpreter */
+    /* version switches.  `_lean' to differentiate from the Infinality */
+    /* `subpixel_hinting', which is managed differently.               */
+    FT_Bool            subpixel_hinting_lean;
+
+    /* Long side of a LCD subpixel is vertical (e.g., screen is rotated). */
+    /* `_lean' to differentiate from the Infinality `vertical_lcd', which */
+    /* is managed differently.                                            */
+    FT_Bool            vertical_lcd_lean;
+
+    /* Default to backwards compatibility mode in v40 interpreter.  If  */
+    /* this is false, it implies the interpreter is in v35 or in native */
+    /* ClearType mode.                                                  */
+    FT_Bool            backwards_compatibility;
+
+    /* Useful for detecting and denying post-IUP trickery that is usually */
+    /* used to fix pixel patterns (`superhinting').                       */
+    FT_Bool            iupx_called;
+    FT_Bool            iupy_called;
+
+    /* ClearType hinting and grayscale rendering, as used by Universal */
+    /* Windows Platform apps (Windows 8 and above).  Like the standard */
+    /* colorful ClearType mode, it utilizes a vastly increased virtual */
+    /* resolution on the x axis.  Different from bi-level hinting and  */
+    /* grayscale rendering, the old mode from Win9x days that roughly  */
+    /* adheres to the physical pixel grid on both axes.                */
+    FT_Bool            grayscale_cleartype;
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     TT_Round_Func      func_round_sphn;   /* subpixel rounding function */
 
     FT_Bool            subpixel_hinting;  /* Using subpixel hinting?       */
@@ -279,7 +405,7 @@ FT_BEGIN_HEADER
     FT_ULong           sph_in_func_flags;     /* flags to indicate if in   */
                                               /* special functions         */
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
   } TT_ExecContextRec;
 
index cd4e294..ed3be2d 100644 (file)
     for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
     {
       if ( !has_cvt  && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
-        num_matched_ids[j] ++;
+        num_matched_ids[j]++;
       if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
-        num_matched_ids[j] ++;
+        num_matched_ids[j]++;
       if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
-        num_matched_ids[j] ++;
+        num_matched_ids[j]++;
       if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
         return TRUE;
     }
 
     TT_Driver  driver = (TT_Driver)ttdriver;
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-    driver->interpreter_version = TT_INTERPRETER_VERSION_38;
-#else
     driver->interpreter_version = TT_INTERPRETER_VERSION_35;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+    driver->interpreter_version = TT_INTERPRETER_VERSION_38;
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+    driver->interpreter_version = TT_INTERPRETER_VERSION_40;
 #endif
 
 #else /* !TT_USE_BYTECODE_INTERPRETER */
index 5a8f262..0395096 100644 (file)
@@ -27,7 +27,7 @@
 #include "ttsubpix.h"
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
   /*************************************************************************/
   /*                                                                       */
     }
   }
 
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#else /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
   /* ANSI C doesn't like empty source files */
   typedef int  _tt_subpix_dummy;
 
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
 /* END */
index 6313baa..86844da 100644 (file)
@@ -27,7 +27,7 @@
 FT_BEGIN_HEADER
 
 
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
 
   /*************************************************************************/
   /*                                                                       */
@@ -100,7 +100,7 @@ FT_BEGIN_HEADER
 #define SPH_OPTION_SET_COMPATIBLE_WIDTHS   FALSE
 #define SPH_OPTION_SET_RASTERIZER_VERSION  38
 
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
 FT_END_HEADER
index 3c7735d..bbd843c 100644 (file)
     /*   encoding of first glyph (1 byte)     */
     /*   encoding of second glyph (1 byte)    */
     /*   offset (little-endian short)         */
-    for ( ; p < limit ; p += 4 )
+    for ( ; p < limit; p += 4 )
     {
       kp->index1 = FT_Get_Char_Index( t1_face, p[0] );
       kp->index2 = FT_Get_Char_Index( t1_face, p[1] );
index a53037c..c981adc 100644 (file)
                                       /* Point to axes after MM_Var struct */
     mmvar->namedstyle      = NULL;
 
-    for ( i = 0 ; i < mmaster.num_axis; ++i )
+    for ( i = 0; i < mmaster.num_axis; ++i )
     {
       mmvar->axis[i].name    = mmaster.axis[i].name;
       mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum);
       /*                                                         */
       if ( face->type1.private_dict.lenIV >= 0 )
       {
-        FT_Byte*  temp;
+        FT_Byte*  temp = NULL;
 
 
         /* some fonts define empty subr records -- this is not totally */
         if ( face->type1.private_dict.lenIV >= 0 &&
              n < num_glyphs + TABLE_EXTEND       )
         {
-          FT_Byte*  temp;
+          FT_Byte*  temp = NULL;
 
 
           if ( size <= (FT_ULong)face->type1.private_dict.lenIV )
index f553f86..a009117 100644 (file)
@@ -67,7 +67,7 @@
                             "pshinter" );
     return ( module && pshinter && pshinter->get_globals_funcs )
            ? pshinter->get_globals_funcs( module )
-           : 0 ;
+           : 0;
   }
 
 
index cf9009b..f948916 100644 (file)
 
     for (;;)
     {
-      /* The format is simple:                   */
-      /*   `/glyphname' + index [+ def]          */
+      /* We support two formats.                     */
+      /*                                             */
+      /*   `/glyphname' + index [+ `def']            */
+      /*   `(glyphname)' [+ `cvn'] + index [+ `def'] */
+      /*                                             */
+      /* The latter format gets created by the       */
+      /* LilyPond typesetting program.               */
 
       T1_Skip_Spaces( parser );
 
       if ( parser->root.error )
         return;
 
-      if ( *cur == '/' )
+      if ( *cur == '/' || *cur == '(' )
       {
         FT_UInt  len;
+        FT_Bool  have_literal = ( *cur == '(' );
 
 
-        if ( cur + 2 >= limit )
+        if ( cur + ( have_literal ? 3 : 2 ) >= limit )
         {
           FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
           error = FT_THROW( Invalid_File_Format );
 
         cur++;                              /* skip `/' */
         len = (FT_UInt)( parser->root.cursor - cur );
+        if ( have_literal )
+          len--;
 
         error = T1_Add_Table( name_table, n, cur, len + 1 );
         if ( error )
 
         T1_Skip_Spaces( parser );
 
+        if ( have_literal )
+          T1_Skip_PS_Token( parser );
+
         cur = parser->root.cursor;
 
         (void)T1_ToInt( parser );