[FREETYPE] Update to v2.7.1. Patch by Katayama Hirofumi MZ, verified by me. CORE...
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 19 Mar 2017 17:53:42 +0000 (17:53 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 19 Mar 2017 17:53:42 +0000 (17:53 +0000)
svn path=/trunk/; revision=74206

136 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/include/freetype/config/ftconfig.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/freetype.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftimage.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftmm.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/ftrender.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/ftserv.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/services/svmetric.h [new file with mode: 0644]
reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/services/svmm.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/tttypes.h
reactos/sdk/lib/3rdparty/freetype/include/freetype/tttags.h
reactos/sdk/lib/3rdparty/freetype/src/autofit/afcjk.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/afdummy.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/afglobal.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/afhints.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/afindic.c
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/afloader.c
reactos/sdk/lib/3rdparty/freetype/src/autofit/afmodule.c
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/ftbbox.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftbitmap.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftcalc.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftdbgmem.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftglyph.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftmac.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftmm.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftobjs.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftrfork.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftsnames.c
reactos/sdk/lib/3rdparty/freetype/src/base/ftutil.c
reactos/sdk/lib/3rdparty/freetype/src/bdf/bdfdrivr.c
reactos/sdk/lib/3rdparty/freetype/src/bdf/bdflib.c
reactos/sdk/lib/3rdparty/freetype/src/bzip2/ftbzip2.c
reactos/sdk/lib/3rdparty/freetype/src/cache/ftcbasic.c
reactos/sdk/lib/3rdparty/freetype/src/cache/ftccache.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.c
reactos/sdk/lib/3rdparty/freetype/src/cache/ftcmru.h
reactos/sdk/lib/3rdparty/freetype/src/cache/ftcsbits.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2arrst.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2error.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2fixed.h
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2font.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2font.h
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2ft.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2ft.h
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2hints.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2intrp.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2stack.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cf2stack.h
reactos/sdk/lib/3rdparty/freetype/src/cff/cffcmap.c
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/cffload.c
reactos/sdk/lib/3rdparty/freetype/src/cff/cffload.h
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/cffpic.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/cidload.c
reactos/sdk/lib/3rdparty/freetype/src/cid/cidparse.c
reactos/sdk/lib/3rdparty/freetype/src/cid/cidriver.c
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvcommn.c
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvmod.c
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvmort.c
reactos/sdk/lib/3rdparty/freetype/src/gxvalid/gxvmorx.c
reactos/sdk/lib/3rdparty/freetype/src/gzip/ftgzip.c
reactos/sdk/lib/3rdparty/freetype/src/gzip/ftzconf.h [new file with mode: 0644]
reactos/sdk/lib/3rdparty/freetype/src/gzip/zlib.h
reactos/sdk/lib/3rdparty/freetype/src/lzw/ftzopen.c
reactos/sdk/lib/3rdparty/freetype/src/otvalid/otvcommn.c
reactos/sdk/lib/3rdparty/freetype/src/otvalid/otvmath.c
reactos/sdk/lib/3rdparty/freetype/src/otvalid/otvmod.c
reactos/sdk/lib/3rdparty/freetype/src/pcf/pcfdrivr.c
reactos/sdk/lib/3rdparty/freetype/src/pcf/pcfread.c
reactos/sdk/lib/3rdparty/freetype/src/pfr/pfrcmap.c
reactos/sdk/lib/3rdparty/freetype/src/pfr/pfrdrivr.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/pfrsbit.h
reactos/sdk/lib/3rdparty/freetype/src/psaux/psauxmod.c
reactos/sdk/lib/3rdparty/freetype/src/psaux/psobjs.c
reactos/sdk/lib/3rdparty/freetype/src/psaux/t1cmap.c
reactos/sdk/lib/3rdparty/freetype/src/psaux/t1decode.c
reactos/sdk/lib/3rdparty/freetype/src/pshinter/pshalgo.c
reactos/sdk/lib/3rdparty/freetype/src/pshinter/pshmod.c
reactos/sdk/lib/3rdparty/freetype/src/pshinter/pshrec.c
reactos/sdk/lib/3rdparty/freetype/src/psnames/psmodule.c
reactos/sdk/lib/3rdparty/freetype/src/psnames/pstables.h
reactos/sdk/lib/3rdparty/freetype/src/raster/ftraster.c
reactos/sdk/lib/3rdparty/freetype/src/raster/ftrend1.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/pngshim.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/pngshim.h
reactos/sdk/lib/3rdparty/freetype/src/sfnt/sfdriver.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/sfobjs.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/ttbdf.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/ttcmap.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/ttload.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/ttmtx.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/ttpost.c
reactos/sdk/lib/3rdparty/freetype/src/sfnt/ttsbit.c
reactos/sdk/lib/3rdparty/freetype/src/smooth/ftgrays.c
reactos/sdk/lib/3rdparty/freetype/src/smooth/ftsmooth.c
reactos/sdk/lib/3rdparty/freetype/src/tools/apinames.c
reactos/sdk/lib/3rdparty/freetype/src/tools/ftrandom/ftrandom.c
reactos/sdk/lib/3rdparty/freetype/src/tools/glnames.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/ttgxvar.h
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/ttpic.h
reactos/sdk/lib/3rdparty/freetype/src/truetype/ttpload.c
reactos/sdk/lib/3rdparty/freetype/src/type1/t1afm.c
reactos/sdk/lib/3rdparty/freetype/src/type1/t1driver.c
reactos/sdk/lib/3rdparty/freetype/src/type1/t1load.c
reactos/sdk/lib/3rdparty/freetype/src/type1/t1load.h
reactos/sdk/lib/3rdparty/freetype/src/type1/t1parse.c
reactos/sdk/lib/3rdparty/freetype/src/type42/t42drivr.c
reactos/sdk/lib/3rdparty/freetype/src/type42/t42objs.c
reactos/sdk/lib/3rdparty/freetype/src/type42/t42parse.c
reactos/sdk/lib/3rdparty/freetype/src/winfonts/winfnt.c

index 04ed3f1..8cc916b 100644 (file)
@@ -23,7 +23,7 @@ Used Version: 1.1
 Website: http://www.geocities.com/dborca/opengl/tc.html
 
 Title: FreeType
-Used Version: 2.7.0
+Used Version: 2.7.1
 Website: http://www.freetype.org
 
 Title: Mesa3D
index 113dd3c..23f5748 100644 (file)
+2016-09-08  Werner Lemberg  <wl@gnu.org>
+
+       * Version 2.7.1 released.
+       =========================
+
+
+       Tag sources with `VER-2-7-1'.
+
+       * docs/VERSION.TXT: Add entry for version 2.7.1.
+
+       * 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.7/2.7.1/, s/27/271/.
+
+       * include/freetype/freetype.h (FREETYPE_PATCH): Set to 1.
+
+       * builds/unix/configure.raw (version_info): Set to 19:0:13.
+       * CMakeLists.txt (VERSION_PATCH): Set to 1.
+
+2016-12-30  Werner Lemberg  <wl@gnu.org>
+
+       [ftfuzzer] Replace `rand' with an xorshift algorithm.
+
+       * src/tools/ftfuzzer/ftfuzzer.cc: Don't include `stdlib.h'.
+       (Random): Implement and use a 32bit `xorshift' algorithm.
+
+2016-12-30  Werner Lemberg  <wl@gnu.org>
+
+       [ftfuzzer] Restrict number of tested bitmap strikes.
+
+       Malformed fonts often have large values for the number of bitmap
+       strikes, and FreeType doesn't check the validity of all bitmap
+       strikes in advance.
+
+       Reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=353
+
+       * src/tools/ftfuzzer/ftfuzzer.cc: Include `stdlib.h' for `rand'.
+       (Random): Small class to provide n randomly selected numbers
+       (without repitition) out of the value set [1,N].
+       (LLVMFuzzerTestOneInput): Use it to test only up to 10 bitmap
+       strikes.
+
+2016-12-29  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Variation font API stability issues.
+
+       Make some functions work before a call to `TT_Set_MM_Blend'.
+
+       * src/truetype/ttgxvar.c (tt_hadvance_adjust): Exit immediately if
+       we don't blend.
+       (TT_Get_MM_Blend, TT_Get_Var_Design): Return default values if we
+       don't blend.
+
+2016-12-29  Werner Lemberg  <wl@gnu.org>
+
+       * src/truetype/ttgxvar.c (TT_Get_MM_Var): Check axis data.
+
+       Reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=348
+
+2016-12-29  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Tracing fixes.
+
+       * src/truetype/ttgxvar.c (tt_hadvance_adjust): Emit correct
+       information.
+       (TT_Set_Var_Design): Fix typo.
+       (TT_Get_Var_Design): Fix typos.
+
+2016-12-29  Werner Lemberg  <wl@gnu.org>
+
+       */*: Use `0.5f' for tracing 16.16 numbers.
+
+2016-12-29  Werner Lemberg  <wl@gnu.org>
+
+       [pcf] Protect against gzip bombs.
+
+       Fix suggested by Kostya; reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=345
+
+       * src/pcf/pcfread.c (pcf_read_TOC): Limit number of TOC entries to
+       1024.
+
+2016-12-28  Werner Lemberg  <wl@gnu.org>
+
+       [psnames] Only declare, not define, data in `pstables.h' (#49949).
+
+       Pdfium includes `pstables.h' a second time; moving the definition
+       from `pstables.h' to `psmodule.c' saves more than 60kByte data
+       segment space for this case.
+
+       * src/tools/glnames.py (StringTable::dump,
+       StringTable::dump_sublist, dump_encoding, dump_array): Emit
+       additional code to only define tables if `DEFINE_PS_TABLES' is set.
+
+       * src/psnames/pstables.h: Regenerated.
+       * src/psnames/psmodule.c (DEFINE_PS_TABLES): Define.
+
+2016-12-28  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Catch `blend' op in non-variant fonts.
+
+       Reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=334
+
+       * src/cff/cf2intrp.c (cf2_interpT2CharString) <cf2_cmdBLEND>: Don't
+       allow `blend' op for non-variant fonts.
+
+2016-12-28  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Better check of number of blends.
+
+       * src/cff/cf2intrp.c (cf2_interpT2CharString) <cf2_cmdBLEND>,
+       src/cff/cffparse.c (cff_parse_blend): Compare number of blends with
+       stack size.
+
+2016-12-27  Werner Lemberg  <wl@gnu.org>
+
+       Documentation updates.
+
+       * docs/CHANGES: Add missing information.
+
+       * docs/formats.txt: Rewritten and updated.
+
+2016-12-27  Werner Lemberg  <wl@gnu.org>
+
+       [truetype, type1] Implement `FT_Get_Var_Design_Coordinates'.
+
+       * src/truetype/ttgxvar.c (TT_Get_Var_Design): Implement.
+       (TT_Set_Var_Design): Fix tracing.
+
+       * src/type1/t1load.c (T1_Get_Var_Design): Implement.
+
+2016-12-24  Werner Lemberg  <wl@gnu.org>
+
+       * src/truetype/ttpload.c (tt_face_load_hdmx): Ignore `version'.
+
+       Problem reported by 張俊芝 <418092625@qq.com>.
+
+2016-12-24  Werner Lemberg  <wl@gnu.org>
+
+       * src/sfnt/ttsbit.c (tt_face_load_sbit): Allow more version values.
+
+       Some fonts seem to have the `version' field in the wrong byte order.
+
+       Problem reported by 張俊芝 <418092625@qq.com>.
+
+2016-12-24  Werner Lemberg  <wl@gnu.org>
+
+       * src/truetype/ttpload.c (tt_face_load_loca): Sanitize table length.
+
+       This trivial fix allows us to accept more fonts.
+
+       Problem reported by 張俊芝 <418092625@qq.com>.
+
+2016-12-24  Werner Lemberg  <wl@gnu.org>
+
+       * src/sfnt/sfobjs.c (sfnt_init_face): Fix tracing.
+
+2016-12-22  Werner Lemberg  <wl@gnu.org>
+
+       * CMakeLists.txt: Make it work with cmake 2.8.11.2 (#49909).
+
+2016-12-22  Werner Lemberg  <wl@gnu.org>
+
+       Ensure used preprocessor symbols are defined (#49790).
+
+       * builds/unix/ftconfig.in, builds/vms/ftconfig.h,
+       include/freetype/config/ftconfig.h: Check `__GNUC__', `__IBMC__',
+       and `__SUNPRO_C' correctly.
+
+2016-12-22  Werner Lemberg  <wl@gnu.org>
+
+       * src/base/ftrfork.c (FT_Raccess_Get_DataOffsets): Check `count'.
+
+       Reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=308
+
+2016-12-22  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Protect against invalid `vsindex' and `blend' values.
+
+       Reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=305
+
+       * src/cff/cf2intrp.c (cf2_interpT2CharString) <cf2_cmdVSINDEX,
+       cf2_cmdBLEND>: Implement it.
+
+2016-12-22  Werner Lemberg  <wl@gnu.org>
+
+       [ftfuzzer] Always use Adobe CFF engine.
+
+       * src/tools/ftfuzzer/ftfuzzer.cc (FT_Global::FT_Global): Implement
+       it.
+
+2016-12-21  Werner Lemberg  <wl@gnu.org>
+
+       * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Thinko.
+
+       I should really stop coding late in the evening...
+
+       Thanks again to Ben for checking.
+
+2016-12-21  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Support variation fonts.
+
+       (This ChangeLog entry was added later on.)
+
+       * src/autofit/afglobal.c (af_face_globals_free): Remove useless
+       code.
+
+       * src/base/ftmm.c (FT_Set_MM_Design_Coordinates,
+       * FT_Set_Var_Design_Coordinates, FT_Set_MM_Blend_Coordinates,
+       FT_Set_Var_Blend_Coordinates): Finalize
+       auto-hinter data to enforce recomputation.  Note that this is a
+       brute-force method which should be improved.
+
+2016-12-21  Werner Lemberg  <wl@gnu.org>
+
+       * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Thinko.
+
+       Don't apply deltas twice for non-phantom points.
+
+       Spotted by Ben Wagner.
+
+2016-12-21  Werner Lemberg  <wl@gnu.org>
+
+       [cff, truetype] Another try for #49829.
+
+       * src/cff/cffdrivr.c: Don't include
+       `FT_SERVICE_METRICS_VARIATIONS_H'.
+       (cff_get_advances): Use `ttface->variation_support'.
+
+       * src/truetype/ttdriver.c (tt_get_advances): Use
+       `ttface->variation_support'.
+
+       * src/truetype/ttgload.c (TT_Process_Simple_Glyph,
+       load_truetype_glyph): Use `ttface->variation_support'.
+
+2016-12-21  Werner Lemberg  <wl@gnu.org>
+
+       [truetype, sfnt] Introduce font variation flags to `TT_Face'.
+
+       * include/freetype/internal/tttypes.h (TT_FACE_FLAG_VAR_XXX):
+       New macros describing available functionality of various OpenType
+       tables related to font variation.
+       (TT_Face): New fields `variation_support' and `mvar_support',
+       replacing and extending `use_fvar'.
+
+       * src/sfnt/sfobjs.c (sfnt_init_face, sfnt_load_face): Use
+       `variation_support'.
+
+       * src/truetype/ttgxvar.c (ft_var_load_hvar): Set `variation_support'
+       field.
+       (TT_Vary_Apply_Glyph_Deltas): Updated.
+
+2016-12-21  Werner Lemberg  <wl@gnu.org>
+
+       [base] Improve sanity check for Mac resources (#49888).
+
+       * src/base/ftobjs.c (Mac_Read_sfnt_Resource): Abort if `rlen' is not
+       positive.
+
+2016-12-20  Werner Lemberg  <wl@gnu.org>
+
+       [base] More sanity checks for Mac resources.
+
+       We use
+
+         https://github.com/kreativekorp/ksfl/wiki/Macintosh-Resource-File-Format
+
+       and
+
+         https://developer.apple.com/legacy/library/documentation/mac/pdf/MoreMacintoshToolbox.pdf#page=151
+
+       as references.
+
+       * include/freetype/internal/ftrfork.h (FT_RFork_Ref): Use FT_Short
+       for `res_id'.
+
+       * src/base/ftrfork.c (FT_Raccess_Get_HeaderInfo): Extract map length
+       and use it to improve sanity checks.
+       Follow the specification more closely;in particular, all data types
+       are signed, not unsigned.
+       (FT_Raccess_Get_DataOffsets): Follow the specification more closely;
+       in particular, all data types are signed, not unsigned.
+       Add some sanity checks.
+
+2016-12-20  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Improve logic for getting fast advance widths.
+
+       * src/cff/cffdrivr.c (cff_get_advances), src/truetype/ttdriver.c
+       (tt_get_advances): Use `is_default_instance' for test; this gets
+       recomputed after changing blend coordinates.
+
+2016-12-20  Ben Wagner  <bungeman@google.com>
+           Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Fix linear metrics of GX variation fonts (#49829).
+
+       When asking for an unhinted non-default variations,
+       `linearVertAdvance' is currently the value from the `hmtx' table
+       instead of the actual value after applying the variation.  `HVAR'
+       support fixes this, but fonts will exist without that table and will
+       need sane fallback.
+
+       Problem also reported as
+
+         https://bugs.chromium.org/p/skia/issues/detail?id=5917
+
+       * src/truetype/ttgload.c (TT_Process_Simple_Glyph,
+       load_truetype_glyph): Implement linear advance adjustments if `HVAR'
+       or `VVAR' tables are missing.
+
+2016-12-20  Werner Lemberg  <wl@gnu.org>
+
+       [cff, truetype] Fast advance width retrieval for fonts with HVAR.
+
+       Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
+
+       * src/base/ftadvanc.c (LOAD_ADVANCE_FAST_CHECK): Don't handle MM.
+
+       * src/cff/cffdrivr.c: Include FT_SERVICE_METRICS_VARIATIONS_H.
+       (cff_get_advances): Test for HVAR and VVAR.
+
+       * src/truetype/ttdriver.c (tt_get_advances): Test for HVAR and VVAR.
+
+2016-12-18  Werner Lemberg  <wl@gnu.org>
+
+       [base] Fix invalid mac font recursion.
+
+       Reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=304
+
+       * src/base/ftobjs.c (FT_Open_Face): Code moved to...
+       (ft_open_face_internal): ... this function.
+       Add a parameter to control whether we try special Mac font handling
+       in case of failure.
+       (FT_Open_Face, FT_New_Face, FT_New_Memory_Face,
+       open_face_from_buffer): Use `ft_open_face_internal'.
+
+2016-12-18  Werner Lemberg  <wl@gnu.org>
+
+       * src/cff/cffobjs.c (cff_face_init): Make named instances work.
+
+2016-12-18  Werner Lemberg  <wl@gnu.org>
+
+       [truetype, cff] Extend `get_var_blend' function of MM service.
+
+       In particular, we need access to named instance data.
+
+       * include/freetype/internal/services/svmm.h (FT_Get_Var_Blend_Func):
+       Add argument for `FT_MM_Var'.
+
+       * src/cff/cffload.c (cff_get_var_blend): Updated.
+       * src/cff/cffload.h: Updated.
+
+       * src/cff/cf2ft.c (cf2_getNormalizedVector): Updated.
+
+       * src/truetype/ttgxvar.c (tt_get_var_blend): Updated.
+       Accept value `NULL' for arguments.
+       * src/truetype/ttgxvar.h: Updated.
+
+2016-12-18  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt] Handle `fvar' with zero axes as a non-MM font.
+
+       This is better behaviour than exiting with an error.
+
+       * include/freetype/internal/tttypes.h (TT_Face): Add `use_fvar'
+       field.
+
+       * src/sfnt/sfobjs.c (sfnt_init_face): Compute `use_fvar', also
+       updating the validation code.
+       Use `use_fvar' to compute FT_FACE_FLAG_MULTIPLE_MASTERS.
+
+       * src/truetype/ttgxvar.c (TT_Get_MM_Var): Remove `fvar' validation
+       code.
+
+2016-12-18  Werner Lemberg  <wl@gnu.org>
+
+       Minor GX code shuffling.
+
+       * include/freetype/internal/tttypes.h (TT_Face): Move
+       `is_default_instance' into TT_CONFIG_OPTION_GX_VAR_SUPPORT
+       block.
+
+       * src/sfnt/sfobjs.c (sfnt_init_face): Updated.
+       * src/truetype/ttgload.c (IS_DEFAULT_INSTANCE): New macro.
+       (TT_Load_Glyph): Use it.
+
+2016-12-18  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Better handling of non-CFF font formats.
+
+       * src/cff/cffload.c (cff_font_load): Pure CFFs don't have a
+       signature, so return `FT_Err_Unknown_File_Format' more often.
+
+2016-12-17  Werner Lemberg  <wl@gnu.org>
+
+       * src/cff/cffload.c (cff_build_blend_vector): Remove redundant code.
+
+2016-12-17  Werner Lemberg  <wl@gnu.org>
+
+       * src/truetype/ttobjs.c (tt_face_init): Simplify conditional code.
+
+2016-12-17  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt, truetype] Various sanitizing fixes.
+
+       * src/sfnt/sfobjs.c (sfnt_init_face): If the axis count in `fvar' is
+       zero, set `num_instances' to zero.
+
+       * src/truetype/ttgxvar.c (TT_Get_MM_Var): Handle `fvar' table with
+       zero axes as invalid.
+
+       * src/truetype/ttobjs.c (tt_face_init): Improve logic of loading
+       `loca', `cvt', `fpgm', and `prep' table.
+
+2016-12-17  Werner Lemberg  <wl@gnu.org>
+
+       Improve tracing of `FT_Open_Face'.
+
+       * src/base/ftobjs.c (FT_Open_Face): Return info on number of
+       available faces and numbered instances, or the indices of the
+       requested face and numbered instance.
+
+       * src/sfnt/sfobjs. (sfnt_open_font): Trace number of subfonts.
+
+2016-12-17  Werner Lemberg  <wl@gnu.org>
+
+       * src/cff/cffload.c (cff_load_private_dict): Always init `blend'.
+
+       Reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=295
+
+2016-12-16  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Fix `cvar' sanity test.
+
+       Reported by Dave Arnold.
+
+       * src/truetype/ttgxvar.c (tt_face_vary_cvt): Use tuple count mask.
+
+2016-12-16  Werner Lemberg  <wl@gnu.org>
+
+       [cff, truetype] Remove compiler warnings; fix `make multi'.
+
+       * src/cff/cf2font.h: Include `cffload.h'.
+
+       * src/cff/cffload.c: Include FT_MULTIPLE_MASTERS_H and
+       FT_SERVICE_MULTIPLE_MASTERS_H.
+       (cff_vstore_load): Eliminate `vsSize'.
+       (cff_load_private_dict): Tag as `FT_LOCAL_DEF'.
+
+       * src/cff/cffload.h: Include `cffobjs.h'.
+       Provide declaration for `cff_load_private_dict'.
+
+       * src/truetype/ttgxvar.c (ft_var_load_hvar): Eliminate
+       `minorVersion' and `map_offset'.
+
+2016-12-16  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Fix heap buffer overflow (#49858).
+
+       * src/cff/cffparse.c (cff_parser_run): Add one more stack size
+       check.
+
+2016-12-15  Werner Lemberg  <wl@gnu.org>
+
+       Fix clang warnings.
+
+       * src/cff/cffload.c (cff_blend_doBlend): Add cast.
+       (cff_subfont_load): Set `error' correctly.
+
+       * src/sfnt/ttmtx.c (tt_face_get_metrics): Typo.
+
+2016-12-15  Dave Arnold  <darnold@adobe.com>
+           Werner Lemberg  <wl@gnu.org>
+
+       [cff] Implement CFF2 support (2/2).
+
+       The font variation code.  All parts dependent on the GX code in the
+       `truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. 
+       In other words, you can still compile the `cff' module without
+       defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
+       support without font variation).
+
+       * src/cff/cf2font.c (cf2_font_setup): Add support for font
+       variation.
+       * src/cff/cf2font.h (CF2_Font): Add fields for variation data.
+
+       * src/cff/cf2ft.c (cf2_free_instance): Free blend data.
+       (cf2_getVStore, cf2_getNormalizedVector): New functions.
+       * src/cff/cf2ft.h: Updated.
+
+       * src/cff/cf2intrp.c: Include `cffload.h'.
+       (cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
+       (cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
+       (cf2_doBlend): New function.
+       (cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
+
+       * src/cff/cffload.c (FT_fdot14ToFixed): New macro.
+       (cff_vstore_done, cff_vstore_load): New functions.
+       (cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
+       cff_blend_check_vector): New functions.
+       (cff_load_private_dict): Add arguments for blend vector.
+       Handle blend data.
+       (cff_subfont_load, cff_subfont_done): Updated.
+       (cff_font_load): Handle CFF2 variation store data.
+       (cff_font_done): Updated.
+       * src/cff/cffload.h: Include `cffparse.h'.
+       Updated.
+
+       * src/cff/cffobjs.c (cff_face_done): Updated.
+
+       * src/cff/cffparse.c: Include `cffload.h'.
+       (cff_parse_num): Handle internal value 255.
+       (cff_parse_vsindex, cff_parse_blend): New functions.
+       (CFF_FIELD_BLEND): New macro.
+       (cff_parser_run): Updated.
+       * src/cff/cffparse.h (cff_kind_blend): New enum value.
+
+       * src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
+       dictionary values.
+
+       * src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
+       CFF_VStore, CFF_Blend): New structures.
+       (CFF_FontRecDict): Add `vstore_offset' field.
+       (CFF_Private): Add `vsindex' field.
+       (CFF_SubFont): Add fields for blend data.
+       (CFF_Font): Add `vstore' field.
+
+       * src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
+       since glyph variation data is directly embedded.
+       (TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
+
+2016-12-15  Dave Arnold  <darnold@adobe.com>
+           Werner Lemberg  <wl@gnu.org>
+
+       [cff] Implement CFF2 support (1/2).
+
+       This commit does not contain the blend code for font variation
+       support, which follows in another commit.
+
+       You should ignore whitespace while inspecting this commit.
+
+       * include/freetype/internal/tttypes.h (TT_Face): Add `isCFF2'
+       member.
+
+       * src/cff/cf2font.h (CF2_Font): Add `isCFF2' member.
+
+       * src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Handle `isCFF2'
+       flag.
+       (cf2_getMaxstack): New function.
+       * src/cff/cf2ft.h: Updated.
+
+       * src/cff/cf2intrp.c (cf2_escRESERVED_38): New enum.
+       (cf2_interpT2CharString): Handle CFF2 differences.
+       Add tracing message for errors.
+
+       * src/cff/cffdrivr.c (cff_get_glyph_name, cff_get_name_index):
+       Update for CFF2.
+
+       * src/cff/cffload.c (FT_FIXED_ONE): New macro.
+       (cff_index_init, cff_index_load_offsets, cff_index_access_element,
+       cff_index_get_name, cff_ft_select_get, cff_load_private_dict,
+       cff_subfont_load, cff_font_load): Handle CFF2.
+       * src/cff/cffload.h: Updated.
+
+       * src/cff/cffobjs.c (cff_face_init): Handle CFF2.
+
+       * src/cff/cffparse.c (cff_parse_maxstack): New function.
+       (CFFCODE_TOPDICT, CFFCODE_PRIVATE): Removed
+       * src/cff/cffparse.h (CFF2_MAX_STACK, CFF2_DEFAULT_STACK): New
+       macros.
+       (CFF2_CODE_TOPDICT, CFF2_CODE_FONTDICT, CFF2_CODE_PRIVATE): New
+       macros.
+
+       * src/cff/cfftoken.h: Add fields for CFF2 dictionaries (but no blend
+       stuff).
+
+       * src/cff/cfftypes.h (CFF_Index): Add `hdr_size' field.
+       (CFF_FontRecDict): Add `maxstack' field.
+       (CFF_Private): Add `subfont' field.
+       (CFF_Font): Add `top_dict_length' and `cff2' fields.
+
+       * src/sfnt/sfobjs.c (sfnt_load_face): Handle `CFF2' table.
+
+2016-12-15  Werner Lemberg  <wl@gnu.org>
+           Dave Arnold  <darnold@adobe.com>
+
+       [truetype] Provide HVAR advance width variation as a service.
+
+       Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
+
+       * src/truetype/ttdriver.c (tt_service_metrics_variations): Updated.
+
+       * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Prevent
+       double adjustment of advance width.
+
+       * src/sfnt/ttmtx.c: Include FT_SERVICE_METRICS_VARIATIONS_H.
+       (tt_face_get_metrics): Apply metrics variations.
+
+2016-12-15  Dave Arnold  <darnold@adobe.com>
+           Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Provide function to apply `HVAR' advance width variation.
+
+       Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
+
+       * src/truetype/ttgxvar.c (tt_hadvance_adjust): New function.
+       * src/truetype/ttgxvar.h: Updated.
+
+2016-12-15  Dave Arnold  <darnold@adobe.com>
+           Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Add `HVAR' table parsing.
+
+       Note that this is not complete yet; it only handles advance width
+       variation.
+
+       Activation of the code follows in another commit.
+
+       Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
+
+       * include/freetype/ftmm.h (FT_Var_Named_Style): Add `psid' member.
+
+       * src/truetype/ttgxvar.h (GX_HVarData, GX_AxisCoords, GX_HVarRegion,
+       GX_HVStore, GX_WidthMap): New auxiliary structures for...
+       (GX_HVarTable): ... HVAR main structure.
+       (GX_BlendRec): Add data for HVAR loading.
+
+       * src/truetype/ttgxvar.c (FT_FIXED_ONE, FT_fdot14ToFixed,
+       FT_intToFixed, FT_fixedToInt): New macros.
+       (ft_var_load_hvar): New function.
+       (TT_Get_MM_Var): Updated.
+       (tt_done_blend): Deallocate HVAR data.
+
+2016-12-15  Dave Arnold  <darnold@adobe.com>
+
+       [cff] Extend number parsing.
+
+       The forthcoming CFF2 support needs a dynamic parsing limit.
+
+       * src/cff/cffparse.c (cff_parse_num, do_fixed, cff_parse_fixed,
+       cff_parse_fixed_scaled, cff_parse_fixed_dynamic): Add argument for
+       parser.
+       (cff_parse_font_matrix, cff_parse_font_bbox, cff_parse_private_dict,
+       cff_parse_multiple_master, cff_parse_cid_ros, cff_parser_run): Updated.
+
+       * src/cff/cffparse.h (cff_parse_num): Export locally.
+
+2016-12-15  Dave Arnold  <darnold@adobe.com>
+
+       [cff] Implement dynamic stack size for Adobe engine.
+
+       This also adds `cf2_stack_setReal' and `cf2_stack_pop', needed for
+       the forthcoming CFF2 support.
+
+       * src/cff/cf2stack.c (cf2_stack_init): Add argument for stack size.
+       (cf2_stack_free): Deallocate stack.
+       (cf2_stack_count, cf2_stack_pushInt, cf2_stack_pushFixed,
+       cf2_stack_popInt, cf2_stack_popFixed, cf2_stack_getReal,
+       cf2_stack_clear): Updated.
+       (cf2_stack_setReal, cf2_stack_pop): New functions.
+
+       * src/cff/cf2stack.h (CF2_Stack): Add `stackSize' member.
+       Update function declarations.
+
+       * src/cff/cf2intrp.c (cf2_interpT2CharString): Updated.
+
+       * src/cff/cffparse.c (cff_parser_init): Add parameter for stack
+       size; return error code.
+       (cff_parser_done): New function.
+       (cff_parser_run): Updated.
+
+       * src/cff/cffparse.h (CFF_Parser): Add `stackSize' member and make
+       `stack' a pointer.
+       Update function declarations.
+
+       * src/cff/cffload.c (cff_load_private_dict, cff_subfont_load):
+       Updated.
+
+2016-12-15  Dave Arnold  <darnold@adobe.com>
+           Werner Lemberg  <wl@gnu.org>
+
+       [cff] Code shuffling.
+
+       * src/cff/cfftypes.h (CFF_Font): Add `library' and `base_offset'
+       fields.
+
+       * src/cff/cffload.c (cff_subfont_load): Change last argument to
+       `CFF_Font'
+       Split off parsing of private dictionary into...
+       (cff_load_private_dict): ...this new function.
+       (cff_font_load): Updated.
+
+2016-12-14  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt, truetype] Add framework for Metrics Variations service.
+
+       No effect yet; service functions will be implemented later on.
+
+       Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
+
+       * include/freetype/internal/services/svmetric.h: New file.
+
+       * include/freetype/internal/ftserv.h
+       (FT_SERVICE_METRICS_VARIATIONS_H): New macro.
+
+       * include/freetype/internal/tttypes.h (TT_Face): New field `var'.
+
+       * src/sfnt/sfobjs.c: Include FT_SERVICE_METRICS_VARIATIONS_H.
+       (sfnt_init_face): Initialize `face->var'.
+
+       * src/truetype/ttdriver.c: Include FT_SERVICE_METRICS_VARIATIONS_H.
+       (tt_service_metrics_variations): New service.
+       (tt_services): Updated.
+
+       * src/truetype/ttpic.h: Updated.
+
+2016-12-14  Werner Lemberg  <wl@gnu.org>
+
+       [cff] Add Multiple Masters service.
+
+       The code simply uses the MM functions from the `truetype' module.
+
+       Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
+
+       * include/freetype/internal/tttypes.h (TT_Face): New field `mm'.
+
+       * src/cff/cffdrivr.c: Include FT_SERVICE_MULTIPLE_MASTERS_H.
+       (cff_set_mm_blend, cff_get_mm_blend, cff_get_mm_var,
+       cff_set_var_design, cff_get_var_design): New functions.
+       (cff_service_multi_masters): New service.
+       (cff_services): Updated.
+
+       * src/cff/cffload.c (cff_get_var_blend, cff_done_blend): New
+       functions.
+       * src/cff/cffload.h: Updated.
+
+       * src/cff/cffpic.h (CFF_SERVICE_MULTI_MASTERS_GET): New macro.
+
+       * src/sfnt/sfobjs.c: Include FT_SERVICE_MULTIPLE_MASTERS_H.
+       (sfnt_init_face): Initialize `face->mm'.
+
+2016-12-14  Werner Lemberg  <wl@gnu.org>
+
+       Extend functionality of `ft_module_get_service'.
+
+       It can now differentiate between local and global searches.
+
+       * src/base/ftobjs.c (ft_module_get_service): Add `global' argument.
+       (FT_Get_TrueType_Engine_Type): Updated.
+
+       * src/cff/cffdrivr.c (cff_get_ps_name, cff_get_cmap_info): Updated.
+
+       * include/freetype/internal/ftobjs.h: Updated.
+       * include/freetype/internal/ftserv.h (FT_FACE_FIND_GLOBAL_SERVICE):
+       Updated.
+
+2016-12-14  Werner Lemberg  <wl@gnu.org>
+
+       * src/truetype/ttgxvar.c (tt_get_var_blend): Fix compiler warning.
+
+2016-12-14  Dave Arnold  <darnold@adobe.com>
+           Werner Lemberg  <wl@gnu.org>
+
+       [sfnt, cff] Minor preparations.
+
+       * include/freetype/tttags.h (TTAG_CFF2, TTAG_HVAR, TTAG_MVAR,
+       TTAG_VVAR): New SFNT table tags.
+
+       * src/cff/cf2fixed.h (CF2_FIXED_ONE, CF2_FIXED_EPSILON): Add cast.
+
+2016-12-10  Werner Lemberg  <wl@gnu.org>
+
+       [truetype, type1] Add `get_var_blend' to MM service.
+
+       For internal use; we want to share code between the forthcoming CFF2
+       support and TrueType.
+
+       * include/freetype/internal/services/svmm.h (FT_Get_Var_Blend_Func):
+       New typedef.
+       (MultiMasters): Add `get_var_blend'.
+       (FT_Service_MultiMasters): Updated.
+
+       * src/truetype/ttgxvar.c (tt_get_var_blend): New function.
+       * src/truetype/ttgxvar.h: Updated.
+
+       * src/truetype/ttdriver.c (tt_service_gx_multi_masters): Updated.
+       * src/type1/t1driver.c (t1_service_multi_masters): Updated.
+
+2016-12-10  Werner Lemberg  <wl@gnu.org>
+
+       [truetype, type1] Add `done_blend' to MM service.
+
+       For internal use; we want to share code between the forthcoming CFF2
+       support and TrueType.
+
+       * include/freetype/internal/services/svmm.h (FT_Done_Blend_Func):
+       New typedef.
+       (MultiMasters): Add `done_blend'.
+       (FT_Service_MultiMasters): Updated.
+
+       * src/truetype/ttgxvar.c (tt_done_blend): Use `TT_Face' as argument.
+       * src/truetype/ttgxvar.h: Updated.
+
+       * src/truetype/ttobjs.c (TT_Face_Done): Updated.
+
+       * src/truetype/ttdriver.c (tt_service_gx_multi_masters): Updated.
+       * src/type1/t1driver.c (t1_service_multi_masters): Updated.
+
+2016-12-09  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt] Revert change from 2016-12-08.
+
+       I missed the functionality of `ft_module_get_service', which makes
+       the change unnecessary.
+
+2016-12-08  Werner Lemberg  <wl@gnu.org>
+
+       Add framework to support services with 8 functions.
+
+       We will need this for CFF variation font support.
+
+       * include/freetype/internal/ftserv.h (FT_DEFINE_SERVICEDESCREC8):
+       New macro.
+
+2016-12-08  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt] Add `get_glyph_name' and `get_name_index' to SFNT interface.
+
+       CFF2 fonts will need access to those two functions.
+
+       * include/freetype/internal/sfnt.h: Include FT_SERVICE_GLYPH_DICT_H.
+       (SFNT_Interface): Add `get_glyph_name' and `get_name_index' members.
+       (FT_DEFINE_SFNT_INTERFACE): Updated.
+
+       * src/sfnt/sfdriver.c (sfnt_get_glyph_name, sfnt_get_name_index):
+       Fix signatures to exactly correspond to the glyph dict service
+       function typedefs.
+       (sfnt_interface): Updated.
+
+2016-12-06  Dave Arnold  <darnold@adobe.com>
+
+       Add `FT_Get_Var_Design_Coordinates' function.
+
+       Note that the low-level functions aren't implemented yet.
+
+       * include/freetype/ftmm.h: Declare.
+
+       * include/freetype/internal/services/svmm.h
+       (FT_Get_Var_Design_Func): New typedef.
+       (MultiMasters): New MM service function `get_var_design'.
+       (FT_DEFINE_SERVICE_MULTIMASTERSREC): Updated.
+       Update all callers.
+
+       * src/base/ftmm.c (FT_Get_Var_Design_Coordinates): Implement.
+
+       * src/truetype/ttdriver.c: Updated.
+
+       * src/truetype/ttgxvar.c (TT_Get_Var_Design): New dummy function to
+       handle `get_var_design' service.
+       * src/truetype/ttgxvar.h: Updated.
+
+       * src/type1/t1driver.c: Updated.
+
+       * src/type1/t1load.c (T1_Get_Var_Design): New dummp function to
+       handle `get_var_design' service.
+       * src/type1/t1load.h: Updated.
+
+2016-12-06  Werner Lemberg  <wl@gnu.org>
+
+       * src/type1/t1load.c (parse_subrs): Fix memory leak.
+
+       The `subrs' keyword might erroneously occur multiple times.
+
+       Reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=231
+
+2016-12-01  Werner Lemberg  <wl@gnu.org>
+
+       [gzip] Improve building with external zlib (#49673).
+
+       Building FreeType with external zlib 1.2.8 makes msvc 14 stop with
+       the following error.
+
+         ftgzip.c
+         zlib-1.2.8\zlib.h(86): error C2061:
+                                syntax error: identifier 'z_const'
+         zlib-1.2.8\zlib.h(94): error C2054:
+                                expected '(' to follow 'z_const'
+         zlib-1.2.8\zlib.h(94): error C2085:
+                                'msg': not in formal parameter list
+         ...
+         zlib-1.2.8\zlib.h(877): fatal error C1003:
+                                 error count exceeds 100; stopping compilation
+
+       The error happens because FreeType keeps an own copy of zlib-1.1.4
+       under `src/gzip'.  When building `src/gzip/ftgzip.c' with
+       FT_CONFIG_OPTION_SYSTEM_ZLIB defined, it uses
+
+         #include <zlib.h>
+
+       which correctly finds an external `zlib.h', but `zlib.h' itself has
+       a line
+
+         #include "zconf.h"
+
+       which makes Visual Studio 2015 find `src/gzip/zconf.h' while
+       compiling the files in `src/gzip'.
+
+       * src/gzip/zconf.h: Rename to...
+       * src/gzip/ftzconf.h: ... this.
+       * src/gzip/zlib.h, src/gzip/rules.mk (GZIP_DRV_SRCS): Updated.
+
+2016-12-01  Oleksandr Chekhovskyi  <oleksandr.chekhovskyi@gmail.com>
+
+       [autofit] Fix Emscripten crash (patch #9180).
+
+       Function calls through pointers must use a matching signature to
+       work on Emscripten, since such calls are dispatched through lookup
+       tables grouped by signature.
+
+       * src/autofit/aftypes.h (AF_WritingSystem_ApplyHintsFunc): Fix
+       typedef.
+
+2016-11-29  Werner Lemberg  <wl@gnu.org>
+
+       [smooth] Revert previous commit.  Already fixed with 6ca54c64.
+
+2016-11-29  Werner Lemberg  <wl@gnu.org>
+
+       [smooth] Avoid conditional jump on uninitialized value (#49711).
+
+       * src/smooth/ftgrays.c (gray_raster_render): Initialize `worker'.
+
+2016-11-27  Nikolaus Waxweiler  <madigens@gmail.com>
+
+       [autofit] Code shuffling.
+
+       Also improve some comments and remove unused code.
+
+       No functional change.
+
+       * src/autofit/afloader.c (af_loader_load_g): Merged with...
+       (af_loader_load_glyph): ...this function.
+       Split off emboldening code into...
+       (af_loader_embolden_glyph_in_slot): ... this function.
+
+2016-11-17  Werner Lemberg  <wl@gnu.org>
+
+       Better support of LLP64 systems with gcc (and clang).
+
+       * builds/unix/configure.raw: Call `AC_TYPE_LONG_LONG_INT'.
+
+       * builds/unix/ftconfig.in (FT_LONG64): Enable for LLP64 systems (and
+       suppress warnings) even without `FT_CONFIG_OPTION_FORCE_INT64'.
+
+2016-11-10  Werner Lemberg  <wl@gnu.org>
+
+       Fix `lcd_weights' array size.
+
+       * include/freetype/internal/ftobjs.h (FT_LibraryRec): Do it.
+
+       Reported by Nikolaus.
+
+2016-11-06  Werner Lemberg  <wl@gnu.org>
+
+       * src/base/ftobjs.c (FT_Render_Glyph_Internal): Fix tracing.
+
+2016-11-06  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt] Improve FT_LOAD_BITMAP_METRICS_ONLY for `sbix' format.
+
+       It's unavoidable to call the PNG engine, but to get the metrics it
+       is sufficient to read the PNG image's header only.
+
+       * src/sfnt/pngshim.c (Load_SBit_Png): Add argument to control the
+       allocation of the glyph slot.
+       * src/sfnt/pngshim.h: Updated.
+       * src/sfnt/ttsbit.c (tt_sbit_decoder_load_png,
+       tt_face_load_sbix_image, tt_face_load_sbit_image): Updated.
+
+2016-11-06  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt] Speed up `sbix' lookup.
+
+       This also fixes a bug introduced in 2016-10-01 which prevents
+       display of embedded bitmap fonts that use the `sbix' format.
+
+       * src/sfnt/ttsbit.c (tt_face_load_sbit): Store `sbix' size and
+       offset also in `ebdt_size' and `ebdt_start', respectively.  This
+       makes the test for an embedded bitmap data table succeed for this
+       format.
+
+       (tt_face_load_strike_metrics) <TT_SBIT_TABLE_TYPE_SBIX>: Use
+       `ebdt_size' and `ebdt_start'
+       (tt_face_load_sbix_image): Ditto.
+
+2016-11-06  Seigo Nonaka  <nona@google.com>
+           Werner Lemberg  <wl@gnu.org>
+
+       Introduce a way of quickly retrieving (embedded) bitmap metrics.
+
+       `FT_Load_Glyph' doesn't generate a bitmap for a non-bitmap glyph
+       until the user calls `FT_Render_Glyph'.  However, it always
+       allocates memory for bitmaps and copies or decodes the contents of a
+       bitmap glyph, which can be quite slow for PNG data.
+
+       * include/freetype/freetype.h (FT_LOAD_BITMAP_METRICS_ONLY): New
+       macro.
+
+       * src/base/ftobjs.c (FT_Load_Glyph): Unset FT_LOAD_RENDER if
+       FT_LOAD_BITMAP_METRICS_ONLY is used.
+
+       * src/sfnt/ttsbit.c (tt_sbit_decoder_alloc_bitmap,
+       tt_sbit_decoder_load_bitmap): Add argument to control allocation of
+       the glyph slot.
+       (tt_sbit_decoder_load_image, tt_sbit_decoder_load_compound,
+       tt_face_load_sbit_image): Updated.
+
+       * src/pcf/pcfdrivr.c (PCF_Glyph_Load): Quickly exit if
+       `FT_LOAD_BITMAP_METRICS_ONLY' is set.
+
+       * src/pfr/pfrsbit.c, src/pfr/pfrsbit.h (pfr_slot_load_bitmap): Add
+       argument to control allocation of the glyph slot.
+       * src/pfr/pfrobjs (pfr_slot_load): Updated.
+
+       * src/winfonts/winfnt.c (FNT_Load_Glyph): Ditto.
+
+       * docs/CHANGES: Updated.
+
+2016-11-06  Werner Lemberg  <wl@gnu.org>
+
+       Synchronize with gnulib (#49448).
+
+       * include/freetype/config/ftconfig.h, builds/unix/ftconfig.in,
+       builds/vms/ftconfig.h (FT_TYPEOF): Update code to use definition in
+       current version of `intprops.h'.
+       Other minor synchronization to reduce code differences between the
+       three files.
+
+2016-11-03  Behdad Esfahbod  <behdad@behdad.org>
+
+       [truetype] Clamp variation requests to valid range.
+
+       This is required by OpenType 1.8; it also avoids rounding surprises.
+
+       * src/truetype/ttgxvar.c (TT_Set_Var_Design): Clamp design coordinates
+       outside of the allowed range to always stay within the range instead
+       of producing an error.
+
+2016-10-29  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Remove clang warnings.
+
+       * src/truetype/ttinterp.h (TT_ExecContextRec): Using `FT_ULong' for
+       loop counter handling.
+
+       * src/truetype/ttinterp.c: Updated.
+       (Ins_SCANTYPE): Use signed constant.
+       (TT_RunIns): Ensure `num_twilight_points' is 16bit.
+
+2016-10-27  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Fix commit from 2014-11-24.
+
+       Problem reported by Hin-Tak Leung  <htl10@users.sourceforge.net>.
+
+       * src/truetype/ttpload.c (tt_face_load_hdmx): Fix file checking
+       logic.
+
+2016-10-26  Werner Lemberg  <wl@gnu.org>
+
+       Add `FT_Get_{MM,Var}_Blend_Coordinates' functions.
+
+       * include/freetype/ftmm.h: Declare.
+
+       * include/freetype/internal/services/svmm.h (FT_Get_MM_Blend_Func):
+       New typedef.
+       (MultiMasters): New MM service function `get_mm_blend'.
+       (FT_DEFINE_SERVICE_MULTIMASTERSREC): Updated.
+       Update all callers.
+
+       * src/base/ftmm.c (FT_Get_MM_Blend_Coordinates,
+       FT_Get_Var_Blend_Coordinates): Implement.
+
+       * src/truetype/ttdriver.c: Updated.
+
+       * src/truetype/ttgxvar.c (TT_Get_MM_Blend): New function to handle
+       `get_mm_blend' service.
+       * src/truetype/ttgxvar.h: Updated.
+
+       * src/type1/t1driver.c: Updated.
+
+       * src/type1/t1load.c (T1_Get_MM_Blend): New function to handle
+       `get_mm_blend' service.
+       * src/type1/t1load.h: Updated.
+
+       * docs/CHANGES: Document.
+
+2016-10-26  Werner Lemberg  <wl@gnu.org>
+
+       * src/type1/t1load.c (parse_subrs): Fix limit check.
+
+       Reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=81
+
+2016-10-25  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [cff] Correct cmap format reporting (#24819).
+
+       * src/cff/cffdrivr.c (cff_get_cmap_info): Throw an error on synthetic
+       charmap instead of guessing its format and language.
+
+2016-10-22  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Fix SCANTYPE instruction (#49394).
+
+       * src/truetype/ttinterp.c (Ins_SCANTYPE): Only use lower 16bits.
+
+2016-10-22  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt] Improve handling of invalid post 2.5 tables [#49393].
+
+       * src/sfnt/ttpost.c (load_format_25): We need at least a single
+       table entry.
+
+2016-10-14  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Fix handling of `cvar' table data.
+
+       Reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53
+
+       * src/truetype/ttgxvar.c (tt_face_vary_cvt): Ignore invalid CVT
+       indices.
+
+2016-10-11  Werner Lemberg  <wl@gnu.org>
+
+       [psaux] Fix handling of invalid flex subrs.
+
+       Problem reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=52
+
+       * src/psaux/t1decode.c (t1_decoder_parse_charstrings)
+       <op_callothersubr>: Set `flex_state' after error checking.
+
+2016-10-11  Werner Lemberg  <wl@gnu.org>
+
+       * src/truetype/ttgxvar.c (tt_done_blend): Fix deallocation.
+
+2016-10-08  Werner Lemberg  <wl@gnu.org>
+
+       * src/cid/cidload.c (cid_face_open): Properly propagate `error'.
+
+2016-10-08  Werner Lemberg  <wl@gnu.org>
+
+       [cid] Fix parsing of subr offsets.
+
+       Bug introduced 2016-05-16.
+
+       * src/cid/cidparse.c (cid_parser_new): Fix off-by-one error.
+
+2016-10-01  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt] Disable bitmap strikes if we don't have a bitmap data table.
+
+       * src/sfnt/ttsbit.c (tt_face_load_sbit): Check whether we have
+       a bitmap data table.
+
+2016-10-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Remove impossibility.
+
+       * src/smooth/ftgrays.c (TWorker): Rearrange fields.
+       (gray_convert_glyph): Remove impossible condition and clean up.
+
+2016-09-29  Werner Lemberg  <wl@gnu.org>
+
+       [pcf] Enrich family name with foundry name and glyph width info.
+
+       This is a very old patch from openSuSE (from 2006, submitted to
+       FreeType in 2011) that I forgot to apply.
+
+         https://build.opensuse.org/package/view_file/openSUSE:Factory/freetype2/freetype2-bitmap-foundry.patch
+
+       Prepend the foundry name plus a space to the family name.  There are
+       many fonts just called `Fixed' which look completely different, and
+       which have nothing to do with each other.  When selecting `Fixed' in
+       KDE or Gnome one gets results that appear rather random, the style
+       changes often if one changes the size and one cannot select some
+       fonts at all.
+
+       We also check whether we have `wide' characters; all put together,
+       we get family names like `Sony Fixed' or `Misc Fixed Wide'.
+
+       * src/pcf/pcfread.c (pcf_load_font): Implement it.
+
+       * docs/CHANGES: Document it.
+
+2016-09-29  Werner Lemberg  <wl@gnu.org>
+
+       [ftfuzzer] Speed up.
+
+       * src/tools/ftfuzzer/ftfuzzer.cc (LLVMFuzzerTestOneInput): Don't
+       check for embedded bitmaps if we have a non-default instance.
+
+2016-09-29  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Disallow bitmap strokes for non-default instances.
+
+       Also speed up access of default instances if GX variations are
+       active.
+
+       * include/freetype/internal/tttypes.h (TT_FaceRec): Add
+       `is_default_instance' member.
+
+       * src/sfnt/sfobjs.c (sfnt_init_face): Initialize
+       `is_default_instance'.
+
+       * src/truetype/ttgload.c (TT_Process_Simple_Glyph,
+       load_truetype_glyph): Add test for default instance.
+       (TT_Load_Glyph): Load embedded bitmaps for default instance only.
+
+       * src/truetype/ttgxvar.c (TT_Set_MM_Blend): Compute
+       `is_default_instance'.
+
+2016-09-29  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Clean up `TT_Face' structure.
+
+       * include/freetype/internal/tttypes.h (TT_FaceRec): Remove unused
+       fields `horz_metrics' and `vert_metrics'.
+       Update documentation.
+
+       * src/sfnt/sfobjs.c (sfnt_done_face): Updated.
+
+2016-09-28  Werner Lemberg  <wl@gnu.org>
+
+       More FT_ZERO usage.
+
+       * src/gxvalid/gxvcommn.c (gxv_ClassTable_validate):
+       s/ft_memset/FT_MEM_ZERO/.
+
+       * src/psaux/t1decode.c (t1_decoder_parse_charstrings):
+       s/ft_memset/FT_ARRAY_ZERO/.
+
+       * src/raster/ftraster.c (FT_ZERO): Define.
+       (ft_black_new): Use it.
+       * src/raster/ftrend1.c (ft_raster1_get_cbox):
+       s/FT_MEM_ZERO/FT_ZERO/.
+
+       * src/smooth/ftgrays.c (FT_ZERO): Define.
+       (gray_raster_new): Use it.
+       * src/smooth/ftsmooth.c (ft_smooth_get_cbox):
+       s/FT_MEM_ZERO/FT_ZERO/.
+
+2016-09-28  Werner Lemberg  <wl@gnu.org>
+
+       */*: s/FT_MEM_ZERO/FT_ZERO/ where appropriate.
+
+2016-09-27  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Trace number of executed opcodes.
+
+       * src/truetype/ttinterp.c (TT_RunIns): Implement it.
+
+2016-09-27  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Speed up `TT_Load_Glyph'.
+
+       This avoids additional calls to `tt_face_lookup_table' for the
+       `glyf' table, which can be expensive.
+
+       * include/freetype/internal/tttypes.h (TT_LoaderRec): Move
+       `glyf_offset' field to ...
+       (TT_FaceRec): ... this structure.
+       * src/truetype/ttgload.c (load_truetype_glyph): Updated.
+       (tt_loader_init): Move initialization of `glyf_offset' to ...
+       * src/truetype/ttpload.c (tt_face_load_loca): ... this function.
+
+2016-09-27  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Introduce dynamic limits for some bytecode opcodes.
+
+       This speeds up FreeType's handling of malformed fonts.
+
+       * src/truetype/ttinterp.c (TT_RunIns): Set up limits for the number
+       of twilight points, the total number of negative jumps, and the
+       total number of loops in LOOPCALL opcodes.  The values are based on
+       the number of points and entries in the CVT table.
+       (Ins_JMPR): Test negative jump counter.
+       (Ins_LOOPCALL): Test loopcall counter.
+
+       * src/truetype/ttinterp.h (TT_ExecContext): Updated.
+
+       * docs/CHANGES: Updated.
+
+2016-09-25  Werner Lemberg  <wl@gnu.org>
+
+       [truetype] Sanitize only last entry of `loca' table.
+
+       Without this patch, a loca sequence like `0 100000 0 100000 ...',
+       where value 100000 is larger than the `glyf' table size, makes
+       FreeType handle the whole `glyf' table as a single glyph again and
+       again, which is certainly invalid (and can be very slow, too).
+
+       * src/truetype/ttpload.c (tt_face_get_location): Implement.
+       Improve tracing messages.
+
+2016-09-25  Werner Lemberg  <wl@gnu.org>
+
+       * src/tools/ftfuzzer/ftfuzzer.cc (LLVMFuzzerTestOneInput): Fix typo.
+
+2016-09-24  Werner Lemberg  <wl@gnu.org>
+
+       [autofit] Tracing fixes.
+
+       * src/autofit/afmodule.c (af_autofitter_load_glyph): Call dumping
+       functions only if we actually do tracing.
+
+2016-09-22  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Reduce divisions in the line renderer.
+
+       We don't need some divisions if a line segments stays within a single
+       row or a single column of pixels.
+
+       * src/smooth/ftgrays.c (gray_render_line) [FT_LONG64]: Make divisions
+       conditional.
+
+2016-09-15  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       * src/smooth/ftgrays.c (gray_sweep): Remove check for empty table.
+
+2016-09-14  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Another tiny speed-up.
+
+       * src/smooth/ftgrays.c (gray_find_cell): Merge into...
+       (gray_record_cell): ... this function.
+
+2016-09-11  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       * src/smooth/ftgrays.c (gray_{find,set}_cell): Remove dubious code.
+
+2016-09-11  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+       [smooth] Fix valgrind warning and reoptimize.
+
+       The algorithm calls `gray_set_cell' at the start of each new contour
+       or when the contours cross the cell boundaries. Double-checking for
+       that is wasteful.
+
+       * src/smooth/ftgrays.c (gray_set_cell): Remove check for a new cell.
+       (gray_convert_glyph): Remove initialization introduced by 44b172e88.
+
+2016-09-10  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt] Fix previous commit.
+
+       Problems reported as
+
+         https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=40
+
+       We now map the strike index right before accessing the physical
+       data, not earlier.
+
+       * src/sfnt/sfobjs.c (sfnt_load_face): Set `face->sbit_strike_map'
+       after creating the map so that...
+
+       * src/sfnt/ttsbit.c (tt_face_load_strike_metrics): ... this function
+       can be used before and after setting up `sbit_strike_map'.
+       (tt_face_set_sbit_strike): Revert change.
+       (tt_sbit_decoder_init, tt_face_load_sbix_image): Map strike index.
+
+       * src/truetype/ttdriver.c (tt_size_select): Revert change.
+
+2016-09-09  Werner Lemberg  <wl@gnu.org>
+
+       [ftfuzzer] Minor improvements.
+
+       * src/tools/ftfuzzer/ftfuzzer.cc (LLVMFuzzerTestOneInput): Ignore
+       invalid strikes.
+       Use better values for call to `FT_Set_Char_Size'.
+
+2016-09-09  Werner Lemberg  <wl@gnu.org>
+
+       [sfnt] Don't provide (completely) broken strike data.
+
+       FreeType tries to sanitize strike header data; we now reject
+       completely broken ones.
+
+       * include/freetype/internal/tttypes.h (TT_FaceRec): New
+       `sbit_strike_map' array pointer.
+
+       * src/base/ftobjs.c (FT_Match_Size): Reject matches where either
+       width or height would be zero.
+       Add tracing message in case of error.
+
+       * src/sfnt/sfobjs.c (sfnt_load_face): Populate `sbit_strike_map',
+       only using (more or less) valid strike header data for
+       FT_Face's `available_sizes' array.
+       (sfnt_done_face): Updated.
+
+       * src/sfnt/ttsbit.c (tt_face_set_sbit_strike): Use
+       `sbit_strike_map'.
+       (tt_face_load_strike_metrics): Improve tracing.
+
+       * src/truetype/ttdriver.c (tt_size_select): Use `sbit_strike_map'.
+
 2016-09-08  Werner Lemberg  <wl@gnu.org>
 
        * Version 2.7 released.
 
        * src/tools/ftrandom/ftrandom.c (GOOD_FONTS_DIR): Provide better
        default.
-       (error_fraction): Make it of type `double' to work as advertized \96
+       (error_fraction): Make it of type `double' to work as advertized 
        this was completely broken.
        Update all related code.
        (error_count, fcnt): Make it unsigned to fix compiler warnings.
index 5a49290..097024c 100644 (file)
@@ -1,5 +1,5 @@
-  FreeType 2.7
-  ============
+  FreeType 2.7.1
+  ==============
 
   Homepage: http://www.freetype.org
 
@@ -24,9 +24,9 @@
 
   and download one of the following files.
 
-    freetype-doc-2.7.tar.bz2
-    freetype-doc-2.7.tar.gz
-    ftdoc27.zip
+    freetype-doc-2.7.1.tar.bz2
+    freetype-doc-2.7.1.tar.gz
+    ftdoc271.zip
 
   To view the documentation online, go to
 
index 157a704..62b807f 100644 (file)
@@ -143,6 +143,14 @@ FT_BEGIN_HEADER
 #endif
 
 
+  /* Fix compiler warning with sgi compiler */
+#if defined( __sgi ) && !defined( __GNUC__ )
+#if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 )
+#pragma set woff 3505
+#endif
+#endif
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Section>                                                             */
@@ -338,10 +346,11 @@ FT_BEGIN_HEADER
 
 
   /* typeof condition taken from gnulib's `intprops.h' header file */
-#if ( __GNUC__ >= 2                         || \
-      defined( __IBM__TYPEOF__ )            || \
-      ( __SUNPRO_C >= 0x5110 && !__STDC__ ) )
-#define FT_TYPEOF( type )  (__typeof__ (type))
+#if ( ( defined( __GNUC__ ) && __GNUC__ >= 2 )                       || \
+      ( defined( __IBMC__ ) && __IBMC__ >= 1210 &&                      \
+        defined( __IBM__TYPEOF__ ) )                                 || \
+      ( defined( __SUNPRO_C ) && __SUNPRO_C >= 0x5110 && !__STDC__ ) )
+#define FT_TYPEOF( type )  ( __typeof__ ( type ) )
 #else
 #define FT_TYPEOF( type )  /* empty */
 #endif
index 3a50734..08f5952 100644 (file)
@@ -951,6 +951,10 @@ FT_BEGIN_HEADER
   /*                           strikes in the face.  It is set to NULL if  */
   /*                           there is no bitmap strike.                  */
   /*                                                                       */
+  /*                           Note that FreeType tries to sanitize the    */
+  /*                           strike data since they are sometimes sloppy */
+  /*                           or incorrect, but this can easily fail.     */
+  /*                                                                       */
   /*    num_charmaps        :: The number of charmaps in the face.         */
   /*                                                                       */
   /*    charmaps            :: An array of the charmaps of the face.       */
@@ -1727,7 +1731,6 @@ FT_BEGIN_HEADER
   /*    position (e.g., coordinates (0,0) on the baseline).  Of course,    */
   /*    `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP.         */
   /*                                                                       */
-  /* <Note>                                                                */
   /*    Here is a small pseudo code fragment that shows how to use         */
   /*    `lsb_delta' and `rsb_delta':                                       */
   /*                                                                       */
@@ -1755,6 +1758,12 @@ FT_BEGIN_HEADER
   /*      endfor                                                           */
   /*    }                                                                  */
   /*                                                                       */
+  /*    If you use strong auto-hinting, you *must* apply these delta       */
+  /*    values!  Otherwise you will experience far too large inter-glyph   */
+  /*    spacing at small rendering sizes in most cases.  Note that it      */
+  /*    doesn't harm to use the above code for other hinting modes also,   */
+  /*    since the delta values are zero then.                              */
+  /*                                                                       */
   typedef struct  FT_GlyphSlotRec_
   {
     FT_Library        library;
@@ -2322,7 +2331,10 @@ FT_BEGIN_HEADER
   /*    FT_Select_Size                                                     */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Select a bitmap strike.                                            */
+  /*    Select a bitmap strike.  To be more precise, this function sets    */
+  /*    the scaling factors of the active @FT_Size object in a face so     */
+  /*    that bitmaps from this particular strike are taken by              */
+  /*    @FT_Load_Glyph and friends.                                        */
   /*                                                                       */
   /* <InOut>                                                               */
   /*    face         :: A handle to a target face object.                  */
@@ -2334,6 +2346,20 @@ FT_BEGIN_HEADER
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    For bitmaps embedded in outline fonts it is common that only a     */
+  /*    subset of the available glyphs at a given ppem value is available. */
+  /*    FreeType silently uses outlines if there is no bitmap for a given  */
+  /*    glyph index.                                                       */
+  /*                                                                       */
+  /*    For GX variation fonts, a bitmap strike makes sense only if the    */
+  /*    default instance is active (this is, no glyph variation takes      */
+  /*    place); otherwise, FreeType simply ignores bitmap strikes.  The    */
+  /*    same is true for all named instances that are different from the   */
+  /*    default instance.                                                  */
+  /*                                                                       */
+  /*    Don't use this function if you are using the FreeType cache API.   */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Select_Size( FT_Face  face,
                   FT_Int   strike_index );
@@ -2786,6 +2812,14 @@ FT_BEGIN_HEADER
    *
    *     Currently, this flag is only implemented for TrueType fonts.
    *
+   *   FT_LOAD_BITMAP_METRICS_ONLY ::
+   *     This flag is used to request loading of the metrics and bitmap
+   *     image information of a (possibly embedded) bitmap glyph without
+   *     allocating or copying the bitmap image data itself.  No effect if
+   *     the target glyph is not a bitmap image.
+   *
+   *     This flag unsets @FT_LOAD_RENDER.
+   *
    *   FT_LOAD_CROP_BITMAP ::
    *     Ignored.  Deprecated.
    *
@@ -2832,6 +2866,7 @@ FT_BEGIN_HEADER
   /* Bits 16..19 are used by `FT_LOAD_TARGET_' */
 #define FT_LOAD_COLOR                        ( 1L << 20 )
 #define FT_LOAD_COMPUTE_METRICS              ( 1L << 21 )
+#define FT_LOAD_BITMAP_METRICS_ONLY          ( 1L << 22 )
 
   /* */
 
@@ -4206,7 +4241,7 @@ FT_BEGIN_HEADER
    */
 #define FREETYPE_MAJOR  2
 #define FREETYPE_MINOR  7
-#define FREETYPE_PATCH  0
+#define FREETYPE_PATCH  1
 
 
   /*************************************************************************/
index 4f86c56..7b46155 100644 (file)
@@ -1180,6 +1180,7 @@ FT_BEGIN_HEADER
   typedef struct  FT_Raster_Funcs_
   {
     FT_Glyph_Format        glyph_format;
+
     FT_Raster_NewFunc      raster_new;
     FT_Raster_ResetFunc    raster_reset;
     FT_Raster_SetModeFunc  raster_set_mode;
index b5d6858..a0238c5 100644 (file)
@@ -171,6 +171,7 @@ FT_BEGIN_HEADER
   {
     FT_Fixed*  coords;
     FT_UInt    strid;
+    FT_UInt    psid;   /* since 2.7.1 */
 
   } FT_Var_Named_Style;
 
@@ -334,6 +335,34 @@ FT_BEGIN_HEADER
                                  FT_Fixed*  coords );
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Var_Design_Coordinates                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    For Multiple Master and GX Var fonts, get the design coordinates   */
+  /*    of the currently selected interpolated font.                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the source face.                         */
+  /*                                                                       */
+  /*    num_coords :: The number of design coordinates to retrieve.  If it */
+  /*                  is larger than the number of axes, set the excess    */
+  /*                  values to~0.                                         */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    coords     :: The design coordinates array.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0~means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Get_Var_Design_Coordinates( FT_Face    face,
+                                 FT_UInt    num_coords,
+                                 FT_Fixed*  coords );
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -353,7 +382,8 @@ FT_BEGIN_HEADER
   /*                  use default values for the remaining axes.           */
   /*                                                                       */
   /*    coords     :: The design coordinates array (each element must be   */
-  /*                  between 0 and 1.0).                                  */
+  /*                  between 0 and 1.0 for MM fonts, and between -1.0 and */
+  /*                  1.0 for GX var fonts).                               */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
@@ -364,6 +394,35 @@ FT_BEGIN_HEADER
                                FT_Fixed*  coords );
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_MM_Blend_Coordinates                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    For Multiple Masters and GX var fonts, get the normalized blend    */
+  /*    coordinates of the currently selected interpolated font.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the source face.                         */
+  /*                                                                       */
+  /*    num_coords :: The number of normalized blend coordinates to        */
+  /*                  retrieve.  If it is larger than the number of axes,  */
+  /*                  set the excess values to~0.5 for MM fonts, and to~0  */
+  /*                  for GX var fonts.                                    */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    coords     :: The normalized blend coordinates array.              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0~means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Get_MM_Blend_Coordinates( FT_Face    face,
+                               FT_UInt    num_coords,
+                               FT_Fixed*  coords );
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -377,6 +436,20 @@ FT_BEGIN_HEADER
                                 FT_UInt    num_coords,
                                 FT_Fixed*  coords );
 
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Var_Blend_Coordinates                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This is another name of @FT_Get_MM_Blend_Coordinates.              */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Get_Var_Blend_Coordinates( FT_Face    face,
+                                FT_UInt    num_coords,
+                                FT_Fixed*  coords );
+
   /* */
 
 
index 9f7ed9e..278d24a 100644 (file)
@@ -75,6 +75,7 @@ FT_BEGIN_HEADER
   {
     FT_Long                 glyph_size;
     FT_Glyph_Format         glyph_format;
+
     FT_Glyph_InitFunc       glyph_init;
     FT_Glyph_DoneFunc       glyph_done;
     FT_Glyph_CopyFunc       glyph_copy;
index 0a9f2d4..25b18a5 100644 (file)
@@ -193,6 +193,7 @@ FT_BEGIN_HEADER
   typedef struct  FT_CMap_ClassRec_
   {
     FT_ULong               size;
+
     FT_CMap_InitFunc       init;
     FT_CMap_DoneFunc       done;
     FT_CMap_CharIndexFunc  char_index;
@@ -530,7 +531,8 @@ FT_BEGIN_HEADER
 
   FT_BASE( FT_Pointer )
   ft_module_get_service( FT_Module    module,
-                         const char*  service_id );
+                         const char*  service_id,
+                         FT_Bool      global );
 
 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
   FT_BASE( FT_Error )
@@ -874,7 +876,7 @@ FT_BEGIN_HEADER
 #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
     FT_LcdFilter             lcd_filter;
     FT_Int                   lcd_extra;        /* number of extra pixels */
-    FT_Byte                  lcd_weights[7];   /* filter weights, if any */
+    FT_Byte                  lcd_weights[5];   /* filter weights, if any */
     FT_Bitmap_LcdFilterFunc  lcd_filter_func;  /* filtering callback     */
 #endif
 
index b923401..718fa62 100644 (file)
@@ -43,11 +43,12 @@ FT_BEGIN_HEADER
 
   typedef struct  FT_RFork_Ref_
   {
-    FT_UShort  res_id;
-    FT_Long    offset;
+    FT_Short  res_id;
+    FT_Long   offset;
 
   } FT_RFork_Ref;
 
+
 #ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
   typedef FT_Error
   (*ft_raccess_guess_func)( FT_Library  library,
index 9189717..663722f 100644 (file)
@@ -109,27 +109,27 @@ FT_BEGIN_HEADER
    */
 #ifdef __cplusplus
 
-#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )               \
-  FT_BEGIN_STMNT                                                   \
-    FT_Module    module = FT_MODULE( FT_FACE( face )->driver );    \
-    FT_Pointer   _tmp_;                                            \
-    FT_Pointer*  _pptr_ = (FT_Pointer*)&(ptr);                     \
-                                                                   \
-                                                                   \
-    _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \
-    *_pptr_ = _tmp_;                                               \
+#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )                  \
+  FT_BEGIN_STMNT                                                      \
+    FT_Module    module = FT_MODULE( FT_FACE( face )->driver );       \
+    FT_Pointer   _tmp_;                                               \
+    FT_Pointer*  _pptr_ = (FT_Pointer*)&(ptr);                        \
+                                                                      \
+                                                                      \
+    _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
+    *_pptr_ = _tmp_;                                                  \
   FT_END_STMNT
 
 #else /* !C++ */
 
-#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )               \
-  FT_BEGIN_STMNT                                                   \
-    FT_Module   module = FT_MODULE( FT_FACE( face )->driver );     \
-    FT_Pointer  _tmp_;                                             \
-                                                                   \
-                                                                   \
-    _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \
-    ptr   = _tmp_;                                                 \
+#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id )                  \
+  FT_BEGIN_STMNT                                                      \
+    FT_Module   module = FT_MODULE( FT_FACE( face )->driver );        \
+    FT_Pointer  _tmp_;                                                \
+                                                                      \
+                                                                      \
+    _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id, 1 ); \
+    ptr   = _tmp_;                                                    \
   FT_END_STMNT
 
 #endif /* !C++ */
@@ -167,6 +167,7 @@ FT_BEGIN_HEADER
   /*    FT_DEFINE_SERVICEDESCREC5                                          */
   /*    FT_DEFINE_SERVICEDESCREC6                                          */
   /*    FT_DEFINE_SERVICEDESCREC7                                          */
+  /*    FT_DEFINE_SERVICEDESCREC8                                          */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Used to initialize an array of FT_ServiceDescRec structures.       */
@@ -283,6 +284,28 @@ FT_BEGIN_HEADER
     { NULL, NULL }                                                          \
   };
 
+#define FT_DEFINE_SERVICEDESCREC8( class_,                                  \
+                                   serv_id_1, serv_data_1,                  \
+                                   serv_id_2, serv_data_2,                  \
+                                   serv_id_3, serv_data_3,                  \
+                                   serv_id_4, serv_data_4,                  \
+                                   serv_id_5, serv_data_5,                  \
+                                   serv_id_6, serv_data_6,                  \
+                                   serv_id_7, serv_data_7,                  \
+                                   serv_id_8, serv_data_8 )                 \
+  static const FT_ServiceDescRec  class_[] =                                \
+  {                                                                         \
+    { serv_id_1, serv_data_1 },                                             \
+    { serv_id_2, serv_data_2 },                                             \
+    { serv_id_3, serv_data_3 },                                             \
+    { serv_id_4, serv_data_4 },                                             \
+    { serv_id_5, serv_data_5 },                                             \
+    { serv_id_6, serv_data_6 },                                             \
+    { serv_id_7, serv_data_7 },                                             \
+    { serv_id_8, serv_data_8 },                                             \
+    { NULL, NULL }                                                          \
+  };
+
 #else /* FT_CONFIG_OPTION_PIC */
 
 #define FT_DEFINE_SERVICEDESCREC1( class_,                                  \
@@ -593,6 +616,62 @@ FT_BEGIN_HEADER
     return FT_Err_Ok;                                                       \
   }
 
+#define FT_DEFINE_SERVICEDESCREC8( class_,                                  \
+                                   serv_id_1, serv_data_1,                  \
+                                   serv_id_2, serv_data_2,                  \
+                                   serv_id_3, serv_data_3,                  \
+                                   serv_id_4, serv_data_4,                  \
+                                   serv_id_5, serv_data_5,                  \
+                                   serv_id_6, serv_data_6,                  \
+                                   serv_id_7, serv_data_7,                  \
+                                   serv_id_8, serv_data_8 )                 \
+  void                                                                      \
+  FT_Destroy_Class_ ## class_( FT_Library          library,                 \
+                               FT_ServiceDescRec*  clazz )                  \
+  {                                                                         \
+    FT_Memory  memory = library->memory;                                    \
+                                                                            \
+                                                                            \
+    if ( clazz )                                                            \
+      FT_FREE( clazz );                                                     \
+  }                                                                         \
+                                                                            \
+  FT_Error                                                                  \
+  FT_Create_Class_ ## class_( FT_Library           library,                 \
+                              FT_ServiceDescRec**  output_class)            \
+  {                                                                         \
+    FT_ServiceDescRec*  clazz  = NULL;                                      \
+    FT_Error            error;                                              \
+    FT_Memory           memory = library->memory;                           \
+                                                                            \
+                                                                            \
+    if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 9 ) )                         \
+      return error;                                                         \
+                                                                            \
+    clazz[0].serv_id   = serv_id_1;                                         \
+    clazz[0].serv_data = serv_data_1;                                       \
+    clazz[1].serv_id   = serv_id_2;                                         \
+    clazz[1].serv_data = serv_data_2;                                       \
+    clazz[2].serv_id   = serv_id_3;                                         \
+    clazz[2].serv_data = serv_data_3;                                       \
+    clazz[3].serv_id   = serv_id_4;                                         \
+    clazz[3].serv_data = serv_data_4;                                       \
+    clazz[4].serv_id   = serv_id_5;                                         \
+    clazz[4].serv_data = serv_data_5;                                       \
+    clazz[5].serv_id   = serv_id_6;                                         \
+    clazz[5].serv_data = serv_data_6;                                       \
+    clazz[6].serv_id   = serv_id_7;                                         \
+    clazz[6].serv_data = serv_data_7;                                       \
+    clazz[7].serv_id   = serv_id_8;                                         \
+    clazz[7].serv_data = serv_data_8;                                       \
+    clazz[8].serv_id   = NULL;                                              \
+    clazz[8].serv_data = NULL;                                              \
+                                                                            \
+    *output_class = clazz;                                                  \
+                                                                            \
+    return FT_Err_Ok;                                                       \
+  }
+
 #endif /* FT_CONFIG_OPTION_PIC */
 
 
@@ -739,6 +818,7 @@ FT_BEGIN_HEADER
 #define FT_SERVICE_GLYPH_DICT_H         <freetype/internal/services/svgldict.h>
 #define FT_SERVICE_GX_VALIDATE_H        <freetype/internal/services/svgxval.h>
 #define FT_SERVICE_KERNING_H            <freetype/internal/services/svkern.h>
+#define FT_SERVICE_METRICS_VARIATIONS_H <freetype/internal/services/svmetric.h>
 #define FT_SERVICE_MULTIPLE_MASTERS_H   <freetype/internal/services/svmm.h>
 #define FT_SERVICE_OPENTYPE_VALIDATE_H  <freetype/internal/services/svotval.h>
 #define FT_SERVICE_PFR_H                <freetype/internal/services/svpfr.h>
diff --git a/reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/services/svmetric.h b/reactos/sdk/lib/3rdparty/freetype/include/freetype/internal/services/svmetric.h
new file mode 100644 (file)
index 0000000..7a4fed4
--- /dev/null
@@ -0,0 +1,155 @@
+/***************************************************************************/
+/*                                                                         */
+/*  svmetric.h                                                             */
+/*                                                                         */
+/*    The FreeType services for metrics variations (specification).        */
+/*                                                                         */
+/*  Copyright 2016 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef SVMETRIC_H_
+#define SVMETRIC_H_
+
+#include FT_INTERNAL_SERVICE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*
+   *  A service to manage the `HVAR, `MVAR', and `VVAR' OpenType tables.
+   *
+   */
+
+#define FT_SERVICE_ID_METRICS_VARIATIONS  "metrics-variations"
+
+
+  /* HVAR */
+
+  typedef FT_Error
+  (*FT_HAdvance_Adjust_Func)( FT_Face  face,
+                              FT_UInt  gindex,
+                              FT_Int  *avalue );
+
+  typedef FT_Error
+  (*FT_LSB_Adjust_Func)( FT_Face  face,
+                         FT_UInt  gindex,
+                         FT_Int  *avalue );
+
+  typedef FT_Error
+  (*FT_RSB_Adjust_Func)( FT_Face  face,
+                         FT_UInt  gindex,
+                         FT_Int  *avalue );
+
+  /* VVAR */
+
+  typedef FT_Error
+  (*FT_VAdvance_Adjust_Func)( FT_Face  face,
+                              FT_UInt  gindex,
+                              FT_Int  *avalue );
+
+  typedef FT_Error
+  (*FT_TSB_Adjust_Func)( FT_Face  face,
+                         FT_UInt  gindex,
+                         FT_Int  *avalue );
+
+  typedef FT_Error
+  (*FT_BSB_Adjust_Func)( FT_Face  face,
+                         FT_UInt  gindex,
+                         FT_Int  *avalue );
+
+  typedef FT_Error
+  (*FT_VOrg_Adjust_Func)( FT_Face  face,
+                          FT_UInt  gindex,
+                          FT_Int  *avalue );
+
+  /* MVAR */
+
+  typedef FT_Error
+  (*FT_Metrics_Adjust_Func)( FT_Face   face,
+                             FT_ULong  tag,
+                             FT_Int   *avalue );
+
+
+  FT_DEFINE_SERVICE( MetricsVariations )
+  {
+    FT_HAdvance_Adjust_Func  hadvance_adjust;
+    FT_LSB_Adjust_Func       lsb_adjust;
+    FT_RSB_Adjust_Func       rsb_adjust;
+
+    FT_VAdvance_Adjust_Func  vadvance_adjust;
+    FT_TSB_Adjust_Func       tsb_adjust;
+    FT_BSB_Adjust_Func       bsb_adjust;
+    FT_VOrg_Adjust_Func      vorg_adjust;
+
+    FT_Metrics_Adjust_Func   metrics_adjust;
+  };
+
+
+#ifndef FT_CONFIG_OPTION_PIC
+
+#define FT_DEFINE_SERVICE_METRICSVARIATIONSREC( class_,            \
+                                                hadvance_adjust_,  \
+                                                lsb_adjust_,       \
+                                                rsb_adjust_,       \
+                                                vadvance_adjust_,  \
+                                                tsb_adjust_,       \
+                                                bsb_adjust_,       \
+                                                vorg_adjust_,      \
+                                                metrics_adjust_  ) \
+  static const FT_Service_MetricsVariationsRec  class_ =           \
+  {                                                                \
+    hadvance_adjust_,                                              \
+    lsb_adjust_,                                                   \
+    rsb_adjust_,                                                   \
+    vadvance_adjust_,                                              \
+    tsb_adjust_,                                                   \
+    bsb_adjust_,                                                   \
+    vorg_adjust_,                                                  \
+    metrics_adjust_                                                \
+  };
+
+#else /* FT_CONFIG_OPTION_PIC */
+
+#define FT_DEFINE_SERVICE_METRICSVARIATIONSREC( class_,               \
+                                                hadvance_adjust_,     \
+                                                lsb_adjust_,          \
+                                                rsb_adjust_,          \
+                                                vadvance_adjust_,     \
+                                                tsb_adjust_,          \
+                                                bsb_adjust_,          \
+                                                vorg_adjust_,         \
+                                                metrics_adjust_  )    \
+  void                                                                \
+  FT_Init_Class_ ## class_( FT_Service_MetricsVariationsRec*  clazz ) \
+  {                                                                   \
+    clazz->hadvance_adjust = hadvance_adjust_;                        \
+    clazz->lsb_adjust      = lsb_adjust_;                             \
+    clazz->rsb_adjust      = rsb_adjust_;                             \
+    clazz->vadvance_adjust = vadvance_adjust_;                        \
+    clazz->tsb_adjust      = tsb_adjust_;                             \
+    clazz->bsb_adjust      = bsb_adjust_;                             \
+    clazz->vorg_adjust     = vorg_adjust_;                            \
+    clazz->metrics_adjust  = metrics_adjust_;                         \
+  };
+
+#endif /* FT_CONFIG_OPTION_PIC */
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* SVMETRIC_H_ */
+
+
+/* END */
index b78a19f..e54845a 100644 (file)
@@ -58,46 +58,91 @@ FT_BEGIN_HEADER
                            FT_UInt   num_coords,
                            FT_Long*  coords );
 
+  typedef FT_Error
+  (*FT_Get_Var_Design_Func)( FT_Face    face,
+                             FT_UInt    num_coords,
+                             FT_Fixed*  coords );
+
+  typedef FT_Error
+  (*FT_Get_MM_Blend_Func)( FT_Face   face,
+                           FT_UInt   num_coords,
+                           FT_Long*  coords );
+
+  typedef FT_Error
+  (*FT_Get_Var_Blend_Func)( FT_Face      face,
+                            FT_UInt     *num_coords,
+                            FT_Fixed*   *coords,
+                            FT_MM_Var*  *mm_var );
+
+  typedef void
+  (*FT_Done_Blend_Func)( FT_Face );
+
 
   FT_DEFINE_SERVICE( MultiMasters )
   {
     FT_Get_MM_Func          get_mm;
     FT_Set_MM_Design_Func   set_mm_design;
     FT_Set_MM_Blend_Func    set_mm_blend;
+    FT_Get_MM_Blend_Func    get_mm_blend;
     FT_Get_MM_Var_Func      get_mm_var;
     FT_Set_Var_Design_Func  set_var_design;
+    FT_Get_Var_Design_Func  get_var_design;
+
+    /* for internal use; only needed for code sharing between modules */
+    FT_Get_Var_Blend_Func   get_var_blend;
+    FT_Done_Blend_Func      done_blend;
   };
 
 
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_,                          \
-                                           get_mm_,                         \
-                                           set_mm_design_,                  \
-                                           set_mm_blend_,                   \
-                                           get_mm_var_,                     \
-                                           set_var_design_ )                \
-  static const FT_Service_MultiMastersRec  class_ =                         \
-  {                                                                         \
-    get_mm_, set_mm_design_, set_mm_blend_, get_mm_var_, set_var_design_    \
+#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_,           \
+                                           get_mm_,          \
+                                           set_mm_design_,   \
+                                           set_mm_blend_,    \
+                                           get_mm_blend_,    \
+                                           get_mm_var_,      \
+                                           set_var_design_,  \
+                                           get_var_design_,  \
+                                           get_var_blend_,   \
+                                           done_blend_     ) \
+  static const FT_Service_MultiMastersRec  class_ =          \
+  {                                                          \
+    get_mm_,                                                 \
+    set_mm_design_,                                          \
+    set_mm_blend_,                                           \
+    get_mm_blend_,                                           \
+    get_mm_var_,                                             \
+    set_var_design_,                                         \
+    get_var_design_,                                         \
+    get_var_blend_,                                          \
+    done_blend_                                              \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_,                          \
-                                           get_mm_,                         \
-                                           set_mm_design_,                  \
-                                           set_mm_blend_,                   \
-                                           get_mm_var_,                     \
-                                           set_var_design_ )                \
-  void                                                                      \
-  FT_Init_Class_ ## class_( FT_Service_MultiMastersRec*  clazz )            \
-  {                                                                         \
-    clazz->get_mm         = get_mm_;                                        \
-    clazz->set_mm_design  = set_mm_design_;                                 \
-    clazz->set_mm_blend   = set_mm_blend_;                                  \
-    clazz->get_mm_var     = get_mm_var_;                                    \
-    clazz->set_var_design = set_var_design_;                                \
+#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_,               \
+                                           get_mm_,              \
+                                           set_mm_design_,       \
+                                           set_mm_blend_,        \
+                                           get_mm_blend_,        \
+                                           get_mm_var_,          \
+                                           set_var_design_,      \
+                                           get_var_design_,      \
+                                           get_var_blend_,       \
+                                           done_blend_ )         \
+  void                                                           \
+  FT_Init_Class_ ## class_( FT_Service_MultiMastersRec*  clazz ) \
+  {                                                              \
+    clazz->get_mm         = get_mm_;                             \
+    clazz->set_mm_design  = set_mm_design_;                      \
+    clazz->set_mm_blend   = set_mm_blend_;                       \
+    clazz->get_mm_blend   = get_mm_blend_;                       \
+    clazz->get_mm_var     = get_mm_var_;                         \
+    clazz->set_var_design = set_var_design_;                     \
+    clazz->get_var_design = get_var_design_;                     \
+    clazz->get_var_blend  = get_var_blend_;                      \
+    clazz->done_blend     = done_blend_;                         \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
index 4ed980b..eef3b10 100644 (file)
@@ -1060,6 +1060,75 @@ FT_BEGIN_HEADER
   } TT_SbitTableType;
 
 
+  /* OpenType 1.8 brings new tables for variation font support;  */
+  /* to make the old MM and GX fonts still work we need to check */
+  /* the presence (and validity) of the functionality provided   */
+  /* by those tables.  The following flag macros are for the     */
+  /* field `variation_support'.                                  */
+  /*                                                             */
+  /* Note that `fvar' gets checked immediately at font loading,  */
+  /* while the other features are only loaded if MM support is   */
+  /* actually requested.                                         */
+
+  /* FVAR */
+#define TT_FACE_FLAG_VAR_FVAR  ( 1 << 0 )
+
+  /* HVAR */
+#define TT_FACE_FLAG_VAR_HADVANCE  ( 1 << 1 )
+#define TT_FACE_FLAG_VAR_LSB       ( 1 << 2 )
+#define TT_FACE_FLAG_VAR_RSB       ( 1 << 3 )
+
+  /* VVAR */
+#define TT_FACE_FLAG_VAR_VADVANCE  ( 1 << 4 )
+#define TT_FACE_FLAG_VAR_TSB       ( 1 << 5 )
+#define TT_FACE_FLAG_VAR_BSB       ( 1 << 6 )
+#define TT_FACE_FLAG_VAR_VORG      ( 1 << 7 )
+
+  /* MVAR gasp data */
+#define TT_FACE_FLAG_VAR_GASP_0  ( 1 << 20 )
+#define TT_FACE_FLAG_VAR_GASP_1  ( 1 << 21 )
+#define TT_FACE_FLAG_VAR_GASP_2  ( 1 << 22 )
+#define TT_FACE_FLAG_VAR_GASP_3  ( 1 << 23 )
+#define TT_FACE_FLAG_VAR_GASP_4  ( 1 << 24 )
+#define TT_FACE_FLAG_VAR_GASP_5  ( 1 << 25 )
+#define TT_FACE_FLAG_VAR_GASP_6  ( 1 << 26 )
+#define TT_FACE_FLAG_VAR_GASP_7  ( 1 << 27 )
+#define TT_FACE_FLAG_VAR_GASP_8  ( 1 << 28 )
+#define TT_FACE_FLAG_VAR_GASP_9  ( 1 << 29 )
+
+  /* The following flag macros are for the field `mvar_support'. */
+
+  /* remaining MVAR data */
+#define TT_FACE_FLAG_VAR_CPHT  ( 1 <<  0 )
+#define TT_FACE_FLAG_VAR_HASC  ( 1 <<  1 )
+#define TT_FACE_FLAG_VAR_HCLA  ( 1 <<  2 )
+#define TT_FACE_FLAG_VAR_HCLD  ( 1 <<  3 )
+#define TT_FACE_FLAG_VAR_HCOF  ( 1 <<  4 )
+#define TT_FACE_FLAG_VAR_HCRN  ( 1 <<  5 )
+#define TT_FACE_FLAG_VAR_HCRS  ( 1 <<  6 )
+#define TT_FACE_FLAG_VAR_HDSC  ( 1 <<  7 )
+#define TT_FACE_FLAG_VAR_HLGP  ( 1 <<  8 )
+#define TT_FACE_FLAG_VAR_SBXO  ( 1 <<  9 )
+#define TT_FACE_FLAG_VAR_SBXS  ( 1 << 10 )
+#define TT_FACE_FLAG_VAR_SBYO  ( 1 << 11 )
+#define TT_FACE_FLAG_VAR_SBYS  ( 1 << 12 )
+#define TT_FACE_FLAG_VAR_SPXO  ( 1 << 13 )
+#define TT_FACE_FLAG_VAR_SPXS  ( 1 << 14 )
+#define TT_FACE_FLAG_VAR_SPYO  ( 1 << 15 )
+#define TT_FACE_FLAG_VAR_SPYS  ( 1 << 16 )
+#define TT_FACE_FLAG_VAR_STRO  ( 1 << 17 )
+#define TT_FACE_FLAG_VAR_STRS  ( 1 << 18 )
+#define TT_FACE_FLAG_VAR_UNDO  ( 1 << 19 )
+#define TT_FACE_FLAG_VAR_UNDS  ( 1 << 20 )
+#define TT_FACE_FLAG_VAR_VASC  ( 1 << 21 )
+#define TT_FACE_FLAG_VAR_VCOF  ( 1 << 22 )
+#define TT_FACE_FLAG_VAR_VCRN  ( 1 << 23 )
+#define TT_FACE_FLAG_VAR_VCRS  ( 1 << 24 )
+#define TT_FACE_FLAG_VAR_VDSC  ( 1 << 25 )
+#define TT_FACE_FLAG_VAR_VLGP  ( 1 << 26 )
+#define TT_FACE_FLAG_VAR_XHGT  ( 1 << 27 )
+
+
   /*************************************************************************/
   /*                                                                       */
   /*                         TrueType Face Type                            */
@@ -1161,6 +1230,11 @@ FT_BEGIN_HEADER
   /*                                                                       */
   /*    psnames              :: A pointer to the PostScript names service. */
   /*                                                                       */
+  /*    mm                   :: A pointer to the Multiple Masters service. */
+  /*                                                                       */
+  /*    var                  :: A pointer to the Metrics Variations        */
+  /*                            service.                                   */
+  /*                                                                       */
   /*    hdmx                 :: The face's horizontal device metrics       */
   /*                            (`hdmx' table).  This table is optional in */
   /*                            TrueType/OpenType fonts.                   */
@@ -1182,18 +1256,6 @@ FT_BEGIN_HEADER
   /*                            file  `ttconfig.h' for comments on the     */
   /*                            TT_CONFIG_OPTION_POSTSCRIPT_NAMES option.  */
   /*                                                                       */
-  /*    num_locations        :: The number of glyph locations in this      */
-  /*                            TrueType file.  This should be             */
-  /*                            identical to the number of glyphs.         */
-  /*                            Ignored for Type 2 fonts.                  */
-  /*                                                                       */
-  /*    glyph_locations      :: An array of longs.  These are offsets to   */
-  /*                            glyph data within the `glyf' table.        */
-  /*                            Ignored for Type 2 font faces.             */
-  /*                                                                       */
-  /*    glyf_len             :: The length of the `glyf' table.  Needed    */
-  /*                            for malformed `loca' tables.               */
-  /*                                                                       */
   /*    font_program_size    :: Size in bytecodes of the face's font       */
   /*                            program.  0 if none defined.  Ignored for  */
   /*                            Type 2 fonts.                              */
@@ -1219,20 +1281,20 @@ FT_BEGIN_HEADER
   /*                            units.  Comes from the `cvt ' table.       */
   /*                            Ignored for Type 2 fonts.                  */
   /*                                                                       */
-  /*    num_kern_pairs       :: The number of kerning pairs present in the */
-  /*                            font file.  The engine only loads the      */
-  /*                            first horizontal format 0 kern table it    */
-  /*                            finds in the font file.  Ignored for       */
-  /*                            Type 2 fonts.                              */
-  /*                                                                       */
-  /*    kern_table_index     :: The index of the kerning table in the font */
-  /*                            kerning directory.  Ignored for Type 2     */
-  /*                            fonts.                                     */
-  /*                                                                       */
   /*    interpreter          :: A pointer to the TrueType bytecode         */
   /*                            interpreters field is also used to hook    */
   /*                            the debugger in `ttdebug'.                 */
   /*                                                                       */
+  /*    extra                :: Reserved for third-party font drivers.     */
+  /*                                                                       */
+  /*    postscript_name      :: The PS name of the font.  Used by the      */
+  /*                            postscript name service.                   */
+  /*                                                                       */
+  /*    glyf_len             :: The length of the `glyf' table.  Needed    */
+  /*                            for malformed `loca' tables.               */
+  /*                                                                       */
+  /*    glyf_offset          :: The file offset of the `glyf' table.       */
+  /*                                                                       */
   /*    doblend              :: A boolean which is set if the font should  */
   /*                            be blended (this is for GX var).           */
   /*                                                                       */
@@ -1240,10 +1302,92 @@ FT_BEGIN_HEADER
   /*                            variation tables (rather like Multiple     */
   /*                            Master data).                              */
   /*                                                                       */
-  /*    extra                :: Reserved for third-party font drivers.     */
+  /*    is_default_instance  :: Set if the glyph outlines can be used      */
+  /*                            unmodified (i.e., without applying glyph   */
+  /*                            variation deltas).                         */
   /*                                                                       */
-  /*    postscript_name      :: The PS name of the font.  Used by the      */
-  /*                            postscript name service.                   */
+  /*    variation_support    :: Flags that indicate which OpenType         */
+  /*                            functionality related to font variation    */
+  /*                            support is present, valid, and usable.     */
+  /*                            For example, TT_FACE_FLAG_VAR_FVAR is only */
+  /*                            set if we have at least one design axis.   */
+  /*                                                                       */
+  /*    mvar_support         :: Flags that indicate which metrics          */
+  /*                            variations are supported.                  */
+  /*                                                                       */
+  /*    horz_metrics_size    :: The size of the `hmtx' table.              */
+  /*                                                                       */
+  /*    vert_metrics_size    :: The size of the `vmtx' table.              */
+  /*                                                                       */
+  /*    num_locations        :: The number of glyph locations in this      */
+  /*                            TrueType file.  This should be             */
+  /*                            identical to the number of glyphs.         */
+  /*                            Ignored for Type 2 fonts.                  */
+  /*                                                                       */
+  /*    glyph_locations      :: An array of longs.  These are offsets to   */
+  /*                            glyph data within the `glyf' table.        */
+  /*                            Ignored for Type 2 font faces.             */
+  /*                                                                       */
+  /*    hdmx_table           :: A pointer to the `hdmx' table.             */
+  /*                                                                       */
+  /*    hdmx_table_size      :: The size of the `hdmx' table.              */
+  /*                                                                       */
+  /*    hdmx_record_count    :: The number of hdmx records.                */
+  /*                                                                       */
+  /*    hdmx_record_size     :: The size of a single hdmx record.          */
+  /*                                                                       */
+  /*    hdmx_record_sizes    :: An array holding the ppem sizes available  */
+  /*                            in the `hdmx' table.                       */
+  /*                                                                       */
+  /*    sbit_table           :: A pointer to the font's embedded bitmap    */
+  /*                            location table.                            */
+  /*                                                                       */
+  /*    sbit_table_size      :: The size of `sbit_table'.                  */
+  /*                                                                       */
+  /*    sbit_table_type      :: The sbit table type (CBLC, SBIX, etc.).    */
+  /*                                                                       */
+  /*    sbit_num_strikes     :: The number of sbit strikes exposed by      */
+  /*                            FreeType's API, omitting invalid strikes.  */
+  /*                                                                       */
+  /*    sbit_strike_map      :: A mapping between the strike indices       */
+  /*                            exposed by the API and the indices used in */
+  /*                            the font's sbit table.                     */
+  /*                                                                       */
+  /*    kern_table           :: A pointer to the `kern' table.             */
+  /*                                                                       */
+  /*    kern_table_size      :: The size of the `kern' table.              */
+  /*                                                                       */
+  /*    num_kern_tables      :: The number of supported kern subtables     */
+  /*                            (up to 32; FreeType recognizes only        */
+  /*                            horizontal ones with format 0).            */
+  /*                                                                       */
+  /*    kern_avail_bits      :: The availability status of kern subtables; */
+  /*                            if bit n is set, table n is available.     */
+  /*                                                                       */
+  /*    kern_order_bits      :: The sortedness status of kern subtables;   */
+  /*                            if bit n is set, table n is sorted.        */
+  /*                                                                       */
+  /*    bdf                  :: Data related to an SFNT font's `bdf'       */
+  /*                            table; see `tttypes.h'.                    */
+  /*                                                                       */
+  /*    horz_metrics_offset  :: The file offset of the `hmtx' table.       */
+  /*                                                                       */
+  /*    vert_metrics_offset  :: The file offset of the `vmtx' table.       */
+  /*                                                                       */
+  /*    sph_found_func_flags :: Flags identifying special bytecode         */
+  /*                            functions (used by the v38 implementation  */
+  /*                            of the bytecode interpreter).              */
+  /*                                                                       */
+  /*    sph_compatibility_mode ::                                          */
+  /*                            This flag is set if we are in ClearType    */
+  /*                            backwards compatibility mode (used by the  */
+  /*                            v38 implementation of the bytecode         */
+  /*                            interpreter).                              */
+  /*                                                                       */
+  /*    ebdt_start           :: The file offset of the sbit data table     */
+  /*                            (CBDT, bdat, etc.).                        */
+  /*                                                                       */
+  /*    ebdt_size            :: The size of the sbit data table.           */
   /*                                                                       */
   typedef struct  TT_FaceRec_
   {
@@ -1288,6 +1432,16 @@ FT_BEGIN_HEADER
     /* handle glyph names <-> unicode & Mac values                   */
     void*                 psnames;
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+    /* a typeless pointer to the FT_Service_MultiMasters table used to */
+    /* handle variation fonts                                          */
+    void*                 mm;
+
+    /* a typeless pointer to the FT_Service_MetricsVariationsRec table */
+    /* used to handle the HVAR, VVAR, and MVAR OpenType tables         */
+    void*                 var;
+#endif
+
 
     /***********************************************************************/
     /*                                                                     */
@@ -1344,18 +1498,22 @@ FT_BEGIN_HEADER
     const char*           postscript_name;
 
     FT_ULong              glyf_len;
+    FT_ULong              glyf_offset;    /* since 2.7.1 */
+
+    FT_Bool               isCFF2;         /* since 2.7.1 */
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     FT_Bool               doblend;
     GX_Blend              blend;
+
+    FT_Bool               is_default_instance;   /* since 2.7.1 */
+    FT_UInt32             variation_support;     /* since 2.7.1 */
+    FT_UInt32             mvar_support;          /* since 2.7.1 */
 #endif
 
     /* since version 2.2 */
 
-    FT_Byte*              horz_metrics;
     FT_ULong              horz_metrics_size;
-
-    FT_Byte*              vert_metrics;
     FT_ULong              vert_metrics_size;
 
     FT_ULong              num_locations; /* in broken TTF, gid > 0xFFFF */
@@ -1371,6 +1529,7 @@ FT_BEGIN_HEADER
     FT_ULong              sbit_table_size;
     TT_SbitTableType      sbit_table_type;
     FT_UInt               sbit_num_strikes;
+    FT_UInt*              sbit_strike_map;
 
     FT_Byte*              kern_table;
     FT_ULong              kern_table_size;
@@ -1491,8 +1650,6 @@ FT_BEGIN_HEADER
     FT_Vector        pp1;
     FT_Vector        pp2;
 
-    FT_ULong         glyf_offset;
-
     /* the zone where we load our glyphs */
     TT_GlyphZoneRec  base;
     TT_GlyphZoneRec  zone;
index f3c9aa5..63f6258 100644 (file)
@@ -43,6 +43,7 @@ FT_BEGIN_HEADER
 #define TTAG_CBDT  FT_MAKE_TAG( 'C', 'B', 'D', 'T' )
 #define TTAG_CBLC  FT_MAKE_TAG( 'C', 'B', 'L', 'C' )
 #define TTAG_CFF   FT_MAKE_TAG( 'C', 'F', 'F', ' ' )
+#define TTAG_CFF2  FT_MAKE_TAG( 'C', 'F', 'F', '2' )
 #define TTAG_CID   FT_MAKE_TAG( 'C', 'I', 'D', ' ' )
 #define TTAG_cmap  FT_MAKE_TAG( 'c', 'm', 'a', 'p' )
 #define TTAG_cvar  FT_MAKE_TAG( 'c', 'v', 'a', 'r' )
@@ -61,6 +62,7 @@ FT_BEGIN_HEADER
 #define TTAG_GPOS  FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
 #define TTAG_GSUB  FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
 #define TTAG_gvar  FT_MAKE_TAG( 'g', 'v', 'a', 'r' )
+#define TTAG_HVAR  FT_MAKE_TAG( 'H', 'V', 'A', 'R' )
 #define TTAG_hdmx  FT_MAKE_TAG( 'h', 'd', 'm', 'x' )
 #define TTAG_head  FT_MAKE_TAG( 'h', 'e', 'a', 'd' )
 #define TTAG_hhea  FT_MAKE_TAG( 'h', 'h', 'e', 'a' )
@@ -79,6 +81,7 @@ FT_BEGIN_HEADER
 #define TTAG_MMSD  FT_MAKE_TAG( 'M', 'M', 'S', 'D' )
 #define TTAG_mort  FT_MAKE_TAG( 'm', 'o', 'r', 't' )
 #define TTAG_morx  FT_MAKE_TAG( 'm', 'o', 'r', 'x' )
+#define TTAG_MVAR  FT_MAKE_TAG( 'M', 'V', 'A', 'R' )
 #define TTAG_name  FT_MAKE_TAG( 'n', 'a', 'm', 'e' )
 #define TTAG_opbd  FT_MAKE_TAG( 'o', 'p', 'b', 'd' )
 #define TTAG_OS2   FT_MAKE_TAG( 'O', 'S', '/', '2' )
@@ -100,6 +103,7 @@ FT_BEGIN_HEADER
 #define TTAG_VDMX  FT_MAKE_TAG( 'V', 'D', 'M', 'X' )
 #define TTAG_vhea  FT_MAKE_TAG( 'v', 'h', 'e', 'a' )
 #define TTAG_vmtx  FT_MAKE_TAG( 'v', 'm', 't', 'x' )
+#define TTAG_VVAR  FT_MAKE_TAG( 'V', 'V', 'A', 'R' )
 #define TTAG_wOFF  FT_MAKE_TAG( 'w', 'O', 'F', 'F' )
 
 
index f21ae3a..68e72f8 100644 (file)
 
     sizeof ( AF_CJKMetricsRec ),
 
-    (AF_WritingSystem_InitMetricsFunc) af_cjk_metrics_init,
-    (AF_WritingSystem_ScaleMetricsFunc)af_cjk_metrics_scale,
-    (AF_WritingSystem_DoneMetricsFunc) NULL,
-    (AF_WritingSystem_GetStdWidthsFunc)af_cjk_get_standard_widths,
+    (AF_WritingSystem_InitMetricsFunc) af_cjk_metrics_init,        /* style_metrics_init    */
+    (AF_WritingSystem_ScaleMetricsFunc)af_cjk_metrics_scale,       /* style_metrics_scale   */
+    (AF_WritingSystem_DoneMetricsFunc) NULL,                       /* style_metrics_done    */
+    (AF_WritingSystem_GetStdWidthsFunc)af_cjk_get_standard_widths, /* style_metrics_getstdw */
 
-    (AF_WritingSystem_InitHintsFunc)   af_cjk_hints_init,
-    (AF_WritingSystem_ApplyHintsFunc)  af_cjk_hints_apply
+    (AF_WritingSystem_InitHintsFunc)   af_cjk_hints_init,          /* style_hints_init      */
+    (AF_WritingSystem_ApplyHintsFunc)  af_cjk_hints_apply          /* style_hints_apply     */
   )
 
 
 
     sizeof ( AF_CJKMetricsRec ),
 
-    (AF_WritingSystem_InitMetricsFunc) NULL,
-    (AF_WritingSystem_ScaleMetricsFunc)NULL,
-    (AF_WritingSystem_DoneMetricsFunc) NULL,
-    (AF_WritingSystem_GetStdWidthsFunc)NULL,
+    (AF_WritingSystem_InitMetricsFunc) NULL, /* style_metrics_init    */
+    (AF_WritingSystem_ScaleMetricsFunc)NULL, /* style_metrics_scale   */
+    (AF_WritingSystem_DoneMetricsFunc) NULL, /* style_metrics_done    */
+    (AF_WritingSystem_GetStdWidthsFunc)NULL, /* style_metrics_getstdw */
 
-    (AF_WritingSystem_InitHintsFunc)   NULL,
-    (AF_WritingSystem_ApplyHintsFunc)  NULL
+    (AF_WritingSystem_InitHintsFunc)   NULL, /* style_hints_init      */
+    (AF_WritingSystem_ApplyHintsFunc)  NULL  /* style_hints_apply     */
   )
 
 
index f3960c8..ff47dcb 100644 (file)
 
     sizeof ( AF_StyleMetricsRec ),
 
-    (AF_WritingSystem_InitMetricsFunc) NULL,
-    (AF_WritingSystem_ScaleMetricsFunc)NULL,
-    (AF_WritingSystem_DoneMetricsFunc) NULL,
-    (AF_WritingSystem_GetStdWidthsFunc)NULL,
+    (AF_WritingSystem_InitMetricsFunc) NULL,                /* style_metrics_init    */
+    (AF_WritingSystem_ScaleMetricsFunc)NULL,                /* style_metrics_scale   */
+    (AF_WritingSystem_DoneMetricsFunc) NULL,                /* style_metrics_done    */
+    (AF_WritingSystem_GetStdWidthsFunc)NULL,                /* style_metrics_getstdw */
 
-    (AF_WritingSystem_InitHintsFunc)   af_dummy_hints_init,
-    (AF_WritingSystem_ApplyHintsFunc)  af_dummy_hints_apply
+    (AF_WritingSystem_InitHintsFunc)   af_dummy_hints_init, /* style_hints_init      */
+    (AF_WritingSystem_ApplyHintsFunc)  af_dummy_hints_apply /* style_hints_apply     */
   )
 
 
index ac6dcaf..11ed0df 100644 (file)
       AF_Script_UniRange  range;
 
 
-      if ( script_class->script_uni_ranges == NULL )
+      if ( !script_class->script_uni_ranges )
         continue;
 
       /*
       globals->hb_buf = NULL;
 #endif
 
-      globals->glyph_count               = 0;
-      globals->stem_darkening_for_ppem   = 0;
-      globals->darken_x                  = 0;
-      globals->darken_y                  = 0;
-      globals->standard_vertical_width   = 0;
-      globals->standard_horizontal_width = 0;
-      globals->scale_down_factor         = 0;
-      /* no need to free this one! */
-      globals->glyph_styles              = NULL;
-      globals->face                      = NULL;
-
+      /* no need to free `globals->glyph_styles'; */
+      /* it is part of the `globals' array        */
       FT_FREE( globals );
     }
   }
                              [style_class->writing_system];
 
     metrics = globals->metrics[style];
-    if ( metrics == NULL )
+    if ( !metrics )
     {
       /* create the global metrics object if necessary */
       FT_Memory  memory = globals->face->memory;
index 0f7f6e5..8ad3e1c 100644 (file)
@@ -45,7 +45,7 @@
 
     if ( axis->num_segments < AF_SEGMENTS_EMBEDDED )
     {
-      if ( axis->segments == NULL )
+      if ( !axis->segments )
       {
         axis->segments     = axis->embedded.segments;
         axis->max_segments = AF_SEGMENTS_EMBEDDED;
 
     if ( axis->num_edges < AF_EDGES_EMBEDDED )
     {
-      if ( axis->edges == NULL )
+      if ( !axis->edges )
       {
         axis->edges     = axis->embedded.edges;
         axis->max_edges = AF_EDGES_EMBEDDED;
 
     if ( new_max <= AF_CONTOURS_EMBEDDED )
     {
-      if ( hints->contours == NULL )
+      if ( !hints->contours )
       {
         hints->contours     = hints->embedded.contours;
         hints->max_contours = AF_CONTOURS_EMBEDDED;
 
     if ( new_max <= AF_POINTS_EMBEDDED )
     {
-      if ( hints->points == NULL )
+      if ( !hints->points )
       {
         hints->points     = hints->embedded.points;
         hints->max_points = AF_POINTS_EMBEDDED;
         AF_Point  point, first, last;
 
 
-        if ( edge == NULL )
+        if ( !edge )
           continue;
 
         first = seg->first;
         AF_Point  point, first, last;
 
 
-        if ( edge == NULL )
+        if ( !edge )
           continue;
 
         first = seg->first;
index 097a2b2..cfaf719 100644 (file)
 
     sizeof ( AF_CJKMetricsRec ),
 
-    (AF_WritingSystem_InitMetricsFunc) af_indic_metrics_init,
-    (AF_WritingSystem_ScaleMetricsFunc)af_indic_metrics_scale,
-    (AF_WritingSystem_DoneMetricsFunc) NULL,
-    (AF_WritingSystem_GetStdWidthsFunc)af_indic_get_standard_widths,
+    (AF_WritingSystem_InitMetricsFunc) af_indic_metrics_init,        /* style_metrics_init    */
+    (AF_WritingSystem_ScaleMetricsFunc)af_indic_metrics_scale,       /* style_metrics_scale   */
+    (AF_WritingSystem_DoneMetricsFunc) NULL,                         /* style_metrics_done    */
+    (AF_WritingSystem_GetStdWidthsFunc)af_indic_get_standard_widths, /* style_metrics_getstdw */
 
-    (AF_WritingSystem_InitHintsFunc)   af_indic_hints_init,
-    (AF_WritingSystem_ApplyHintsFunc)  af_indic_hints_apply
+    (AF_WritingSystem_InitHintsFunc)   af_indic_hints_init,          /* style_hints_init      */
+    (AF_WritingSystem_ApplyHintsFunc)  af_indic_hints_apply          /* style_hints_apply     */
   )
 
 
 
     sizeof ( AF_CJKMetricsRec ),
 
-    (AF_WritingSystem_InitMetricsFunc) NULL,
-    (AF_WritingSystem_ScaleMetricsFunc)NULL,
-    (AF_WritingSystem_DoneMetricsFunc) NULL,
-    (AF_WritingSystem_GetStdWidthsFunc)NULL,
+    (AF_WritingSystem_InitMetricsFunc) NULL, /* style_metrics_init    */
+    (AF_WritingSystem_ScaleMetricsFunc)NULL, /* style_metrics_scale   */
+    (AF_WritingSystem_DoneMetricsFunc) NULL, /* style_metrics_done    */
+    (AF_WritingSystem_GetStdWidthsFunc)NULL, /* style_metrics_getstdw */
 
-    (AF_WritingSystem_InitHintsFunc)   NULL,
-    (AF_WritingSystem_ApplyHintsFunc)  NULL
+    (AF_WritingSystem_InitHintsFunc)   NULL, /* style_hints_init      */
+    (AF_WritingSystem_ApplyHintsFunc)  NULL  /* style_hints_apply     */
   )
 
 
index 09b3609..5775dd8 100644 (file)
                 "af_latin_metrics_scale_dim:"
                 " x height alignment (style `%s'):\n"
                 "                           "
-                " vertical scaling changed from %.4f to %.4f (by %d%%)\n"
+                " vertical scaling changed from %.5f to %.5f (by %d%%)\n"
                 "\n",
                 af_style_names[metrics->root.style_class->style],
                 scale / 65536.0,
                                 seg->serif->edge         &&
                                 seg->serif->edge != edge );
 
-          if ( ( seg->link && seg->link->edge != NULL ) || is_serif )
+          if ( ( seg->link && seg->link->edge ) || is_serif )
           {
             AF_Edge     edge2;
             AF_Segment  seg2;
 
     sizeof ( AF_LatinMetricsRec ),
 
-    (AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init,
-    (AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale,
-    (AF_WritingSystem_DoneMetricsFunc) NULL,
-    (AF_WritingSystem_GetStdWidthsFunc)af_latin_get_standard_widths,
+    (AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init,        /* style_metrics_init    */
+    (AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale,       /* style_metrics_scale   */
+    (AF_WritingSystem_DoneMetricsFunc) NULL,                         /* style_metrics_done    */
+    (AF_WritingSystem_GetStdWidthsFunc)af_latin_get_standard_widths, /* style_metrics_getstdw */
 
-    (AF_WritingSystem_InitHintsFunc)   af_latin_hints_init,
-    (AF_WritingSystem_ApplyHintsFunc)  af_latin_hints_apply
+    (AF_WritingSystem_InitHintsFunc)   af_latin_hints_init,          /* style_hints_init      */
+    (AF_WritingSystem_ApplyHintsFunc)  af_latin_hints_apply          /* style_hints_apply     */
   )
 
 
index 5db4a41..e1cc1f5 100644 (file)
                                 seg->serif->edge         &&
                                 seg->serif->edge != edge );
 
-          if ( ( seg->link && seg->link->edge != NULL ) || is_serif )
+          if ( ( seg->link && seg->link->edge ) || is_serif )
           {
             AF_Edge     edge2;
             AF_Segment  seg2;
 
     sizeof ( AF_LatinMetricsRec ),
 
-    (AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init,
-    (AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale,
-    (AF_WritingSystem_DoneMetricsFunc) NULL,
-    (AF_WritingSystem_GetStdWidthsFunc)af_latin2_get_standard_widths,
+    (AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init,        /* style_metrics_init    */
+    (AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale,       /* style_metrics_scale   */
+    (AF_WritingSystem_DoneMetricsFunc) NULL,                          /* style_metrics_done    */
+    (AF_WritingSystem_GetStdWidthsFunc)af_latin2_get_standard_widths, /* style_metrics_getstdw */
 
-    (AF_WritingSystem_InitHintsFunc)   af_latin2_hints_init,
-    (AF_WritingSystem_ApplyHintsFunc)  af_latin2_hints_apply
+    (AF_WritingSystem_InitHintsFunc)   af_latin2_hints_init,          /* style_hints_init      */
+    (AF_WritingSystem_ApplyHintsFunc)  af_latin2_hints_apply          /* style_hints_apply     */
   )
 
 
index 26bba06..7f75fc3 100644 (file)
@@ -51,7 +51,7 @@
     loader->face    = face;
     loader->globals = (AF_FaceGlobals)face->autohint.data;
 
-    if ( loader->globals == NULL )
+    if ( !loader->globals )
     {
       error = af_face_globals_new( face, &loader->globals, module );
       if ( !error )
           ( (FT_Fixed)( (f) * 65536.0 + 0.5 ) )
 
 
-  /* Do the main work of `af_loader_load_glyph'.  Note that we never   */
-  /* have to deal with composite glyphs as those get loaded into       */
-  /* FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function. */
-  /* In the rare cases where FT_LOAD_NO_RECURSE is set, it implies     */
-  /* FT_LOAD_NO_SCALE and as such the auto-hinter is never called.     */
-
   static FT_Error
-  af_loader_load_g( AF_Loader  loader,
-                    AF_Scaler  scaler,
-                    FT_UInt    glyph_index,
-                    FT_Int32   load_flags )
+  af_loader_embolden_glyph_in_slot( AF_Loader        loader,
+                                    FT_Face          face,
+                                    AF_StyleMetrics  style_metrics )
   {
-    AF_Module  module = loader->globals->module;
+    FT_Error  error = FT_Err_Ok;
 
-    FT_Error          error;
-    FT_Face           face     = loader->face;
-    AF_StyleMetrics   metrics  = loader->metrics;
-    AF_GlyphHints     hints    = loader->hints;
-    FT_GlyphSlot      slot     = face->glyph;
-    FT_Slot_Internal  internal = slot->internal;
-    FT_GlyphLoader    gloader  = internal->loader;
-    FT_Int32          flags;
+    FT_GlyphSlot           slot    = face->glyph;
+    AF_FaceGlobals         globals = loader->globals;
+    AF_WritingSystemClass  writing_system_class;
 
+    FT_Pos  stdVW = 0;
+    FT_Pos  stdHW = 0;
 
-    flags = load_flags | FT_LOAD_LINEAR_DESIGN;
-    error = FT_Load_Glyph( face, glyph_index, flags );
-    if ( error )
+    FT_Bool  size_changed = face->size->metrics.x_ppem
+                              != globals->stem_darkening_for_ppem;
+
+    FT_Fixed  em_size  = af_intToFixed( face->units_per_EM );
+    FT_Fixed  em_ratio = FT_DivFix( af_intToFixed( 1000 ), em_size );
+
+    FT_Matrix  scale_down_matrix = { 0x10000L, 0, 0, 0x10000L };
+
+
+    /* Skip stem darkening for broken fonts. */
+    if ( !face->units_per_EM )
+    {
+      error = FT_Err_Corrupted_Font_Header;
       goto Exit;
+    }
 
     /*
-     * Apply stem darkening (emboldening) here before hints are applied to
-     * the outline.  Glyphs are scaled down proportionally to the
-     * emboldening so that curve points don't fall outside their precomputed
-     * blue zones.
-     *
-     * Any emboldening done by the font driver (e.g., the CFF driver)
-     * doesn't reach here because the autohinter loads the unprocessed
-     * glyphs in font units for analysis (functions `af_*_metrics_init_*')
-     * and then above to prepare it for the rasterizers by itself,
-     * independently of the font driver.  So emboldening must be done here,
-     * within the autohinter.
-     *
-     * All glyphs to be autohinted pass through here one by one.  The
-     * standard widths can therefore change from one glyph to the next,
-     * depending on what script a glyph is assigned to (each script has its
-     * own set of standard widths and other metrics).  The darkening amount
-     * must therefore be recomputed for each size and
-     * `standard_{vertical,horizontal}_width' change.
+     *  We depend on the writing system (script analyzers) to supply
+     *  standard widths for the script of the glyph we are looking at.  If
+     *  it can't deliver, stem darkening is disabled.
      */
-    if ( !module->no_stem_darkening )
+    writing_system_class =
+      AF_WRITING_SYSTEM_CLASSES_GET[style_metrics->style_class->writing_system];
+
+    if ( writing_system_class->style_metrics_getstdw )
+      writing_system_class->style_metrics_getstdw( style_metrics,
+                                                   &stdHW,
+                                                   &stdVW );
+    else
     {
-      AF_FaceGlobals         globals = loader->globals;
-      AF_WritingSystemClass  writing_system_class;
+      error = FT_Err_Unimplemented_Feature;
+      goto Exit;
+    }
 
-      FT_Pos  stdVW = 0;
-      FT_Pos  stdHW = 0;
+    if ( size_changed                                               ||
+         ( stdVW > 0 && stdVW != globals->standard_vertical_width ) )
+    {
+      FT_Fixed  darken_by_font_units_x, darken_x;
 
-      FT_Bool  size_changed = face->size->metrics.x_ppem
-                                != globals->stem_darkening_for_ppem;
 
-      FT_Fixed  em_size  = af_intToFixed( face->units_per_EM );
-      FT_Fixed  em_ratio = FT_DivFix( af_intToFixed( 1000 ), em_size );
+      darken_by_font_units_x =
+        af_intToFixed( af_loader_compute_darkening( loader,
+                                                    face,
+                                                    stdVW ) );
+      darken_x = FT_DivFix( FT_MulFix( darken_by_font_units_x,
+                                       face->size->metrics.x_scale ),
+                            em_ratio );
 
-      FT_Matrix  scale_down_matrix = { 0x10000L, 0, 0, 0x10000L };
+      globals->standard_vertical_width = stdVW;
+      globals->stem_darkening_for_ppem = face->size->metrics.x_ppem;
+      globals->darken_x                = af_fixedToInt( darken_x );
+    }
+
+    if ( size_changed                                                 ||
+         ( stdHW > 0 && stdHW != globals->standard_horizontal_width ) )
+    {
+      FT_Fixed  darken_by_font_units_y, darken_y;
 
 
-      /* Skip stem darkening for broken fonts. */
-      if ( !face->units_per_EM )
-        goto After_Emboldening;
+      darken_by_font_units_y =
+        af_intToFixed( af_loader_compute_darkening( loader,
+                                                    face,
+                                                    stdHW ) );
+      darken_y = FT_DivFix( FT_MulFix( darken_by_font_units_y,
+                                       face->size->metrics.y_scale ),
+                            em_ratio );
+
+      globals->standard_horizontal_width = stdHW;
+      globals->stem_darkening_for_ppem   = face->size->metrics.x_ppem;
+      globals->darken_y                  = af_fixedToInt( darken_y );
 
       /*
-       * We depend on the writing system (script analyzers) to supply
-       * standard widths for the script of the glyph we are looking at.  If
-       * it can't deliver, stem darkening is effectively disabled.
+       *  Scale outlines down on the Y-axis to keep them inside their blue
+       *  zones.  The stronger the emboldening, the stronger the downscaling
+       *  (plus heuristical padding to prevent outlines still falling out
+       *  their zones due to rounding).
+       *
+       *  Reason: `FT_Outline_Embolden' works by shifting the rightmost
+       *  points of stems farther to the right, and topmost points farther
+       *  up.  This positions points on the Y-axis outside their
+       *  pre-computed blue zones and leads to distortion when applying the
+       *  hints in the code further below.  Code outside this emboldening
+       *  block doesn't know we are presenting it with modified outlines the
+       *  analyzer didn't see!
+       *
+       *  An unfortunate side effect of downscaling is that the emboldening
+       *  effect is slightly decreased.  The loss becomes more pronounced
+       *  versus the CFF driver at smaller sizes, e.g., at 9ppem and below.
        */
-      writing_system_class =
-        AF_WRITING_SYSTEM_CLASSES_GET[metrics->style_class->writing_system];
+      globals->scale_down_factor =
+        FT_DivFix( em_size - ( darken_by_font_units_y + af_intToFixed( 8 ) ),
+                   em_size );
+    }
 
-      if ( writing_system_class->style_metrics_getstdw )
-        writing_system_class->style_metrics_getstdw( metrics,
-                                                     &stdHW,
-                                                     &stdVW );
-      else
-        goto After_Emboldening;
+    FT_Outline_EmboldenXY( &slot->outline,
+                           globals->darken_x,
+                           globals->darken_y );
 
+    scale_down_matrix.yy = globals->scale_down_factor;
+    FT_Outline_Transform( &slot->outline, &scale_down_matrix );
 
-      if ( size_changed                                               ||
-           ( stdVW > 0 && stdVW != globals->standard_vertical_width ) )
-      {
-        FT_Fixed  darken_by_font_units_x, darken_x;
+  Exit:
+    return error;
+  }
 
 
-        darken_by_font_units_x =
-          af_intToFixed( af_loader_compute_darkening( loader,
-                                                      face,
-                                                      stdVW ) );
-        darken_x = FT_DivFix( FT_MulFix( darken_by_font_units_x,
-                                         face->size->metrics.x_scale ),
-                              em_ratio );
+  /* Load the glyph at index into the current slot of a face and hint it. */
 
-        globals->standard_vertical_width = stdVW;
-        globals->stem_darkening_for_ppem = face->size->metrics.x_ppem;
-        globals->darken_x                = af_fixedToInt( darken_x );
-      }
+  FT_LOCAL_DEF( FT_Error )
+  af_loader_load_glyph( AF_Loader  loader,
+                        AF_Module  module,
+                        FT_Face    face,
+                        FT_UInt    glyph_index,
+                        FT_Int32   load_flags )
+  {
+    FT_Error  error;
 
-      if ( size_changed                                                 ||
-           ( stdHW > 0 && stdHW != globals->standard_horizontal_width ) )
-      {
-        FT_Fixed  darken_by_font_units_y, darken_y;
-
-
-        darken_by_font_units_y =
-          af_intToFixed( af_loader_compute_darkening( loader,
-                                                      face,
-                                                      stdHW ) );
-        darken_y = FT_DivFix( FT_MulFix( darken_by_font_units_y,
-                                         face->size->metrics.y_scale ),
-                              em_ratio );
-
-        globals->standard_horizontal_width = stdHW;
-        globals->stem_darkening_for_ppem   = face->size->metrics.x_ppem;
-        globals->darken_y                  = af_fixedToInt( darken_y );
-
-        /*
-         * Scale outlines down on the Y-axis to keep them inside their blue
-         * zones.  The stronger the emboldening, the stronger the
-         * downscaling (plus heuristical padding to prevent outlines still
-         * falling out their zones due to rounding).
-         *
-         * Reason: `FT_Outline_Embolden' works by shifting the rightmost
-         * points of stems farther to the right, and topmost points farther
-         * up.  This positions points on the Y-axis outside their
-         * pre-computed blue zones and leads to distortion when applying the
-         * hints in the code further below.  Code outside this emboldening
-         * block doesn't know we are presenting it with modified outlines
-         * the analyzer didn't see!
-         *
-         * An unfortunate side effect of downscaling is that the emboldening
-         * effect is slightly decreased.  The loss becomes more pronounced
-         * versus the CFF driver at smaller sizes, e.g., at 9ppem and below.
-         */
-        globals->scale_down_factor =
-          FT_DivFix( em_size - ( darken_by_font_units_y + af_intToFixed( 8 ) ),
-                     em_size );
-      }
+    FT_Size           size     = face->size;
+    FT_GlyphSlot      slot     = face->glyph;
+    FT_Slot_Internal  internal = slot->internal;
+    FT_GlyphLoader    gloader  = internal->loader;
+
+    AF_GlyphHints          hints          = loader->hints;
+    AF_ScalerRec           scaler;
+    AF_StyleMetrics        style_metrics;
+    FT_UInt                style_options  = AF_STYLE_NONE_DFLT;
+    AF_StyleClass          style_class;
+    AF_WritingSystemClass  writing_system_class;
+
+#ifdef FT_CONFIG_OPTION_PIC
+    AF_FaceGlobals  globals = loader->globals;
+#endif
+
+
+    if ( !size )
+      return FT_THROW( Invalid_Size_Handle );
+
+    FT_ZERO( &scaler );
+
+    /*
+     *  TODO: This code currently doesn't support fractional advance widths,
+     *  i.e.  placing hinted glyphs at anything other than integer
+     *  x-positions.  This is only relevant for the warper code, which
+     *  scales and shifts glyphs to optimize blackness of stems (hinting on
+     *  the x-axis by nature places things on pixel integers, hinting on the
+     *  y-axis only, i.e.  LIGHT mode, doesn't touch the x-axis).  The delta
+     *  values of the scaler would need to be adjusted.
+     */
+    scaler.face    = face;
+    scaler.x_scale = size->metrics.x_scale;
+    scaler.x_delta = 0;
+    scaler.y_scale = size->metrics.y_scale;
+    scaler.y_delta = 0;
+
+    scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
+    scaler.flags       = 0;
+
+    error = af_loader_reset( loader, module, face );
+    if ( error )
+      goto Exit;
+
+#ifdef FT_OPTION_AUTOFIT2
+    /* XXX: undocumented hook to activate the latin2 writing system. */
+    if ( load_flags & ( 1UL << 20 ) )
+      style_options = AF_STYLE_LTN2_DFLT;
+#endif
+
+    /*
+     *  Glyphs (really code points) are assigned to scripts.  Script
+     *  analysis is done lazily: For each glyph that passes through here,
+     *  the corresponding script analyzer is called, but returns immediately
+     *  if it has been run already.
+     */
+    error = af_face_globals_get_metrics( loader->globals, glyph_index,
+                                         style_options, &style_metrics );
+    if ( error )
+      goto Exit;
 
-      FT_Outline_EmboldenXY( &slot->outline,
-                             globals->darken_x,
-                             globals->darken_y );
+    style_class          = style_metrics->style_class;
+    writing_system_class =
+      AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system];
 
-      scale_down_matrix.yy = globals->scale_down_factor;
-      FT_Outline_Transform( &slot->outline, &scale_down_matrix );
+    loader->metrics = style_metrics;
+
+    if ( writing_system_class->style_metrics_scale )
+      writing_system_class->style_metrics_scale( style_metrics, &scaler );
+    else
+      style_metrics->scaler = scaler;
+
+    if ( writing_system_class->style_hints_init )
+    {
+      error = writing_system_class->style_hints_init( hints,
+                                                      style_metrics );
+      if ( error )
+        goto Exit;
     }
 
-  After_Emboldening:
+    /*
+     *  Do the main work of `af_loader_load_glyph'.  Note that we never have
+     *  to deal with composite glyphs as those get loaded into
+     *  FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function.
+     *  In the rare cases where FT_LOAD_NO_RECURSE is set, it implies
+     *  FT_LOAD_NO_SCALE and as such the auto-hinter is never called.
+     */
+    load_flags |=  FT_LOAD_NO_SCALE         |
+                   FT_LOAD_IGNORE_TRANSFORM |
+                   FT_LOAD_LINEAR_DESIGN;
+    load_flags &= ~FT_LOAD_RENDER;
+
+    error = FT_Load_Glyph( face, glyph_index, load_flags );
+    if ( error )
+      goto Exit;
+
+    /*
+     *  Apply stem darkening (emboldening) here before hints are applied to
+     *  the outline.  Glyphs are scaled down proportionally to the
+     *  emboldening so that curve points don't fall outside their
+     *  precomputed blue zones.
+     *
+     *  Any emboldening done by the font driver (e.g., the CFF driver)
+     *  doesn't reach here because the autohinter loads the unprocessed
+     *  glyphs in font units for analysis (functions `af_*_metrics_init_*')
+     *  and then above to prepare it for the rasterizers by itself,
+     *  independently of the font driver.  So emboldening must be done here,
+     *  within the autohinter.
+     *
+     *  All glyphs to be autohinted pass through here one by one.  The
+     *  standard widths can therefore change from one glyph to the next,
+     *  depending on what script a glyph is assigned to (each script has its
+     *  own set of standard widths and other metrics).  The darkening amount
+     *  must therefore be recomputed for each size and
+     *  `standard_{vertical,horizontal}_width' change.
+     *
+     *  Ignore errors and carry on without emboldening.
+     */
+    if ( !module->no_stem_darkening )
+      af_loader_embolden_glyph_in_slot( loader, face, style_metrics );
+
     loader->transformed = internal->glyph_transformed;
     if ( loader->transformed )
     {
                               loader->trans_delta.x,
                               loader->trans_delta.y );
 
-      /* compute original horizontal phantom points (and ignore */
-      /* vertical ones)                                         */
+      /* compute original horizontal phantom points */
+      /* (and ignore vertical ones)                 */
       loader->pp1.x = hints->x_delta;
       loader->pp1.y = hints->y_delta;
       loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
       if ( slot->outline.n_points == 0 )
         goto Hint_Metrics;
 
-      /* now load the slot image into the auto-outline and run the */
-      /* automatic hinting process                                 */
+      /* now load the slot image into the auto-outline */
+      /* and run the automatic hinting process         */
       {
 #ifdef FT_CONFIG_OPTION_PIC
-        AF_FaceGlobals         globals = loader->globals;
+        AF_FaceGlobals  globals = loader->globals;
 #endif
-        AF_StyleClass          style_class = metrics->style_class;
-        AF_WritingSystemClass  writing_system_class =
-          AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system];
 
 
         if ( writing_system_class->style_hints_apply )
           writing_system_class->style_hints_apply( glyph_index,
                                                    hints,
                                                    &gloader->base.outline,
-                                                   metrics );
+                                                   style_metrics );
       }
 
       /* we now need to adjust the metrics according to the change in */
       /* width/positioning that occurred during the hinting process   */
-      if ( scaler->render_mode != FT_RENDER_MODE_LIGHT )
+      if ( scaler.render_mode != FT_RENDER_MODE_LIGHT )
       {
-        FT_Pos        old_rsb, old_lsb, new_lsb;
-        FT_Pos        pp1x_uh, pp2x_uh;
+        FT_Pos  old_rsb, old_lsb, new_lsb;
+        FT_Pos  pp1x_uh, pp2x_uh;
+
         AF_AxisHints  axis  = &hints->axis[AF_DIMENSION_HORZ];
         AF_Edge       edge1 = axis->edges;         /* leftmost edge  */
         AF_Edge       edge2 = edge1 +
         if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
         {
           old_rsb = loader->pp2.x - edge2->opos;
-          old_lsb = edge1->opos;
+          /* loader->pp1.x is always zero at this point of time */
+          old_lsb = edge1->opos /* - loader->pp1.x */;
           new_lsb = edge1->pos;
 
-          /* remember unhinted values to later account */
-          /* for rounding errors                       */
-
           pp1x_uh = new_lsb    - old_lsb;
           pp2x_uh = edge2->pos + old_rsb;
 
 
       vvector.x = slot->metrics.vertBearingX - slot->metrics.horiBearingX;
       vvector.y = slot->metrics.vertBearingY - slot->metrics.horiBearingY;
-      vvector.x = FT_MulFix( vvector.x, metrics->scaler.x_scale );
-      vvector.y = FT_MulFix( vvector.y, metrics->scaler.y_scale );
+      vvector.x = FT_MulFix( vvector.x, style_metrics->scaler.x_scale );
+      vvector.y = FT_MulFix( vvector.y, style_metrics->scaler.y_scale );
 
       /* transform the hinted outline if needed */
       if ( loader->transformed )
         FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
         FT_Vector_Transform( &vvector, &loader->trans_matrix );
       }
-#if 1
+
       /* we must translate our final outline by -pp1.x and compute */
       /* the new metrics                                           */
       if ( loader->pp1.x )
         FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
-#endif
+
       FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
 
       bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
       /* for mono-width fonts (like Andale, Courier, etc.) we need */
       /* to keep the original rounded advance width; ditto for     */
       /* digits if all have the same advance width                 */
-#if 0
-      if ( !FT_IS_FIXED_WIDTH( slot->face ) )
-        slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
-      else
-        slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
-                                               x_scale );
-#else
-      if ( scaler->render_mode != FT_RENDER_MODE_LIGHT                      &&
+      if ( scaler.render_mode != FT_RENDER_MODE_LIGHT                       &&
            ( FT_IS_FIXED_WIDTH( slot->face )                              ||
              ( af_face_globals_is_digit( loader->globals, glyph_index ) &&
-               metrics->digits_have_same_width                          ) ) )
+               style_metrics->digits_have_same_width                    ) ) )
       {
-        slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
-                                               metrics->scaler.x_scale );
+        slot->metrics.horiAdvance =
+          FT_MulFix( slot->metrics.horiAdvance,
+                     style_metrics->scaler.x_scale );
 
         /* Set delta values to 0.  Otherwise code that uses them is */
         /* going to ruin the fixed advance width.                   */
         if ( slot->metrics.horiAdvance )
           slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
       }
-#endif
 
       slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
-                                             metrics->scaler.y_scale );
+                                             style_metrics->scaler.y_scale );
 
       slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
       slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
 
-#if 0
-      /* reassign all outline fields except flags to protect them */
-      slot->outline.n_contours = internal->loader->base.outline.n_contours;
-      slot->outline.n_points   = internal->loader->base.outline.n_points;
-      slot->outline.points     = internal->loader->base.outline.points;
-      slot->outline.tags       = internal->loader->base.outline.tags;
-      slot->outline.contours   = internal->loader->base.outline.contours;
-#endif
-
       slot->format  = FT_GLYPH_FORMAT_OUTLINE;
     }
 
   }
 
 
-  /* Load a glyph. */
-
-  FT_LOCAL_DEF( FT_Error )
-  af_loader_load_glyph( AF_Loader  loader,
-                        AF_Module  module,
-                        FT_Face    face,
-                        FT_UInt    gindex,
-                        FT_Int32   load_flags )
-  {
-    FT_Error      error;
-    FT_Size       size   = face->size;
-    AF_ScalerRec  scaler;
-
-
-    if ( !size )
-      return FT_THROW( Invalid_Size_Handle );
-
-    FT_ZERO( &scaler );
-
-    scaler.face    = face;
-    scaler.x_scale = size->metrics.x_scale;
-    scaler.x_delta = 0;  /* XXX: TODO: add support for sub-pixel hinting */
-    scaler.y_scale = size->metrics.y_scale;
-    scaler.y_delta = 0;  /* XXX: TODO: add support for sub-pixel hinting */
-
-    scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
-    scaler.flags       = 0;  /* XXX: fix this */
-
-    error = af_loader_reset( loader, module, face );
-    if ( !error )
-    {
-      AF_StyleMetrics  metrics;
-      FT_UInt          options = AF_STYLE_NONE_DFLT;
-
-
-#ifdef FT_OPTION_AUTOFIT2
-      /* XXX: undocumented hook to activate the latin2 writing system */
-      if ( load_flags & ( 1UL << 20 ) )
-        options = AF_STYLE_LTN2_DFLT;
-#endif
-
-      error = af_face_globals_get_metrics( loader->globals, gindex,
-                                           options, &metrics );
-      if ( !error )
-      {
-#ifdef FT_CONFIG_OPTION_PIC
-        AF_FaceGlobals         globals = loader->globals;
-#endif
-        AF_StyleClass          style_class = metrics->style_class;
-        AF_WritingSystemClass  writing_system_class =
-          AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system];
-
-
-        loader->metrics = metrics;
-
-        if ( writing_system_class->style_metrics_scale )
-          writing_system_class->style_metrics_scale( metrics, &scaler );
-        else
-          metrics->scaler = scaler;
-
-        load_flags |=  FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
-        load_flags &= ~FT_LOAD_RENDER;
-
-        if ( writing_system_class->style_hints_init )
-        {
-          error = writing_system_class->style_hints_init( loader->hints,
-                                                          metrics );
-          if ( error )
-            goto Exit;
-        }
-
-        error = af_loader_load_g( loader, &scaler, gindex, load_flags );
-      }
-    }
-  Exit:
-    return error;
-  }
-
-
   /*
    * Compute amount of font units the face should be emboldened by, in
    * analogy to the CFF driver's `cf2_computeDarkening' function.  See there
index 5f831e0..42e5691 100644 (file)
 
   FT_DEFINE_SERVICE_PROPERTIESREC(
     af_service_properties,
+
     (FT_Properties_SetFunc)af_property_set,        /* set_property */
     (FT_Properties_GetFunc)af_property_get )       /* get_property */
 
 
   FT_DEFINE_SERVICEDESCREC1(
     af_services,
+
     FT_SERVICE_ID_PROPERTIES, &AF_SERVICE_PROPERTIES_GET )
 
 
     error = af_loader_load_glyph( loader, module, slot->face,
                                   glyph_index, load_flags );
 
-    af_glyph_hints_dump_points( hints, 0 );
-    af_glyph_hints_dump_segments( hints, 0 );
-    af_glyph_hints_dump_edges( hints, 0 );
+#ifdef FT_DEBUG_LEVEL_TRACE
+    if ( ft_trace_levels[FT_COMPONENT] )
+    {
+#endif
+      af_glyph_hints_dump_points( hints, 0 );
+      af_glyph_hints_dump_segments( hints, 0 );
+      af_glyph_hints_dump_edges( hints, 0 );
+#ifdef FT_DEBUG_LEVEL_TRACE
+    }
+#endif
 
     af_loader_done( loader );
 
 
   FT_DEFINE_AUTOHINTER_INTERFACE(
     af_autofitter_interface,
+
     NULL,                                                    /* reset_face */
     NULL,                                              /* get_global_hints */
     NULL,                                             /* done_global_hints */
 
     (const void*)&AF_INTERFACE_GET,
 
-    (FT_Module_Constructor)af_autofitter_init,
-    (FT_Module_Destructor) af_autofitter_done,
-    (FT_Module_Requester)  af_get_interface )
+    (FT_Module_Constructor)af_autofitter_init,  /* module_init   */
+    (FT_Module_Destructor) af_autofitter_done,  /* module_done   */
+    (FT_Module_Requester)  af_get_interface     /* get_interface */
+  )
 
 
 /* END */
index ef62043..61b6b12 100644 (file)
@@ -221,7 +221,7 @@ extern void*  _af_debug_hints;
   (*AF_WritingSystem_InitHintsFunc)( AF_GlyphHints    hints,
                                      AF_StyleMetrics  metrics );
 
-  typedef void
+  typedef FT_Error
   (*AF_WritingSystem_ApplyHintsFunc)( FT_UInt          glyph_index,
                                       AF_GlyphHints    hints,
                                       FT_Outline*      outline,
index 9e2ab89..59c7450 100644 (file)
@@ -36,7 +36,7 @@
     if ( flags & FT_LOAD_NO_SCALE )
       return FT_Err_Ok;
 
-    if ( face->size == NULL )
+    if ( !face->size )
       return FT_THROW( Invalid_Size_Handle );
 
     if ( flags & FT_LOAD_VERTICAL_LAYOUT )
    /*  - unscaled load                                             */
    /*  - unhinted load                                             */
    /*  - light-hinted load                                         */
-   /*  - neither a MM nor a GX font                                */
+   /*  - if a variations font, it must have an `HVAR' or `VVAR'    */
+   /*    table (thus the old MM or GX fonts don't qualify; this    */
+   /*    gets checked by the driver-specific functions)            */
 
-#define LOAD_ADVANCE_FAST_CHECK( face, flags )                          \
-          ( ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING )    ||   \
-              FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT ) && \
-            !FT_HAS_MULTIPLE_MASTERS( face )                         )
+#define LOAD_ADVANCE_FAST_CHECK( face, flags )                      \
+          ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING )    || \
+            FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )
 
 
   /* documentation is in ftadvanc.h */
index d3e45ff..804dc90 100644 (file)
   }
 
 
-  FT_DEFINE_OUTLINE_FUNCS(bbox_interface,
-    (FT_Outline_MoveTo_Func) BBox_Move_To,
-    (FT_Outline_LineTo_Func) BBox_Line_To,
-    (FT_Outline_ConicTo_Func)BBox_Conic_To,
-    (FT_Outline_CubicTo_Func)BBox_Cubic_To,
-    0, 0
+  FT_DEFINE_OUTLINE_FUNCS(
+    bbox_interface,
+
+    (FT_Outline_MoveTo_Func) BBox_Move_To,   /* move_to  */
+    (FT_Outline_LineTo_Func) BBox_Line_To,   /* line_to  */
+    (FT_Outline_ConicTo_Func)BBox_Conic_To,  /* conic_to */
+    (FT_Outline_CubicTo_Func)BBox_Cubic_To,  /* cubic_to */
+    0,                                       /* shift    */
+    0                                        /* delta    */
   )
 
 
     {
       abbox->xMin = abbox->xMax = 0;
       abbox->yMin = abbox->yMax = 0;
+
       return 0;
     }
 
 
     for ( n = 0; n < outline->n_points; n++ )
     {
-      FT_UPDATE_BBOX( vec, cbox);
+      FT_UPDATE_BBOX( vec, cbox );
 
       if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON )
-        FT_UPDATE_BBOX( vec, bbox);
+        FT_UPDATE_BBOX( vec, bbox );
 
       vec++;
     }
       TBBox_Rec  user;
 
 #ifdef FT_CONFIG_OPTION_PIC
-      FT_Outline_Funcs bbox_interface;
-      Init_Class_bbox_interface(&bbox_interface);
+      FT_Outline_Funcs  bbox_interface;
+
+
+      Init_Class_bbox_interface( &bbox_interface );
 #endif
 
       user.bbox = bbox;
index f0a6aff..f98012e 100644 (file)
@@ -76,7 +76,7 @@
     source_pitch_sign = source->pitch < 0 ? -1 : 1;
     target_pitch_sign = target->pitch < 0 ? -1 : 1;
 
-    if ( source->buffer == NULL )
+    if ( !source->buffer )
     {
       *target = *source;
       if ( source_pitch_sign != target_pitch_sign )
index 67549d0..1c23922 100644 (file)
       FT_Add64( &temp, &temp2, &temp );
 
       /* last attempt to ditch long division */
-      a = temp.hi == 0 ? temp.lo / c
-                       : ft_div64by32( temp.hi, temp.lo, c );
+      a = ( temp.hi == 0 ) ? temp.lo / c
+                           : ft_div64by32( temp.hi, temp.lo, c );
     }
 
     a_ = (FT_Long)a;
       ft_multo64( a, b, &temp );
 
       /* last attempt to ditch long division */
-      a = temp.hi == 0 ? temp.lo / c
-                       : ft_div64by32( temp.hi, temp.lo, c );
+      a = ( temp.hi == 0 ) ? temp.lo / c
+                           : ft_div64by32( temp.hi, temp.lo, c );
     }
 
     a_ = (FT_Long)a;
index 38d1a80..fcdceef 100644 (file)
                       ft_mem_table_alloc(
                         table,
                         new_size * (FT_Long)sizeof ( FT_MemNode ) );
-      if ( new_buckets == NULL )
+      if ( !new_buckets )
         return;
 
       FT_ARRAY_ZERO( new_buckets, new_size );
 
 
     table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) );
-    if ( table == NULL )
+    if ( !table )
       goto Exit;
 
     FT_ZERO( table );
     for (;;)
     {
       node = *pnode;
-      if ( node == NULL )
+      if ( !node )
         break;
 
       if ( node->file_name == _ft_debug_file   &&
     }
 
     node = (FT_MemSource)ft_mem_table_alloc( table, sizeof ( *node ) );
-    if ( node == NULL )
+    if ( !node )
       ft_mem_debug_panic(
         "not enough memory to perform memory debugging\n" );
 
 
       /* we need to create a new node in this table */
       node = (FT_MemNode)ft_mem_table_alloc( table, sizeof ( *node ) );
-      if ( node == NULL )
+      if ( !node )
         ft_mem_debug_panic( "not enough memory to run memory tests" );
 
       node->address = address;
     FT_MemTable  table = (FT_MemTable)memory->user;
 
 
-    if ( block == NULL )
+    if ( !block )
       ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",
                           FT_FILENAME( _ft_debug_file ),
                           _ft_debug_lineno );
 
     /* the following is valid according to ANSI C */
 #if 0
-    if ( block == NULL || cur_size == 0 )
+    if ( !block || !cur_size )
       ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",
                           file_name, line_no );
 #endif
       return NULL;
 
     new_block = (FT_Pointer)ft_mem_table_alloc( table, new_size );
-    if ( new_block == NULL )
+    if ( !new_block )
       return NULL;
 
     ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );
         memory->free    = ft_mem_debug_free;
 
         p = getenv( "FT2_ALLOC_TOTAL_MAX" );
-        if ( p != NULL )
+        if ( p )
         {
           FT_Long  total_max = ft_strtol( p, NULL, 10 );
 
         }
 
         p = getenv( "FT2_ALLOC_COUNT_MAX" );
-        if ( p != NULL )
+        if ( p )
         {
           FT_Long  total_count = ft_strtol( p, NULL, 10 );
 
         }
 
         p = getenv( "FT2_KEEP_ALIVE" );
-        if ( p != NULL )
+        if ( p )
         {
           FT_Long  keep_alive = ft_strtol( p, NULL, 10 );
 
index c2376dd..d336b1c 100644 (file)
   }
 
 
-  FT_DEFINE_GLYPH(ft_bitmap_glyph_class,
+  FT_DEFINE_GLYPH(
+    ft_bitmap_glyph_class,
+
     sizeof ( FT_BitmapGlyphRec ),
     FT_GLYPH_FORMAT_BITMAP,
 
-    ft_bitmap_glyph_init,
-    ft_bitmap_glyph_done,
-    ft_bitmap_glyph_copy,
-    0,                          /* FT_Glyph_TransformFunc */
-    ft_bitmap_glyph_bbox,
-    0                           /* FT_Glyph_PrepareFunc   */
+    ft_bitmap_glyph_init,    /* FT_Glyph_InitFunc       glyph_init      */
+    ft_bitmap_glyph_done,    /* FT_Glyph_DoneFunc       glyph_done      */
+    ft_bitmap_glyph_copy,    /* FT_Glyph_CopyFunc       glyph_copy      */
+    NULL,                    /* FT_Glyph_TransformFunc  glyph_transform */
+    ft_bitmap_glyph_bbox,    /* FT_Glyph_GetBBoxFunc    glyph_bbox      */
+    NULL                     /* FT_Glyph_PrepareFunc    glyph_prepare   */
   )
 
 
   }
 
 
-  FT_DEFINE_GLYPH( ft_outline_glyph_class,
+  FT_DEFINE_GLYPH(
+    ft_outline_glyph_class,
+
     sizeof ( FT_OutlineGlyphRec ),
     FT_GLYPH_FORMAT_OUTLINE,
 
-    ft_outline_glyph_init,
-    ft_outline_glyph_done,
-    ft_outline_glyph_copy,
-    ft_outline_glyph_transform,
-    ft_outline_glyph_bbox,
-    ft_outline_glyph_prepare
+    ft_outline_glyph_init,      /* FT_Glyph_InitFunc       glyph_init      */
+    ft_outline_glyph_done,      /* FT_Glyph_DoneFunc       glyph_done      */
+    ft_outline_glyph_copy,      /* FT_Glyph_CopyFunc       glyph_copy      */
+    ft_outline_glyph_transform, /* FT_Glyph_TransformFunc  glyph_transform */
+    ft_outline_glyph_bbox,      /* FT_Glyph_GetBBoxFunc    glyph_bbox      */
+    ft_outline_glyph_prepare    /* FT_Glyph_PrepareFunc    glyph_prepare   */
   )
 
 
     /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
     /* then calling FT_Render_Glyph_Internal()                            */
 
-    FT_MEM_ZERO( &dummy, sizeof ( dummy ) );
-    FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );
+    FT_ZERO( &dummy );
+    FT_ZERO( &dummy_internal );
     dummy.internal = &dummy_internal;
     dummy.library  = library;
     dummy.format   = clazz->glyph_format;
index e97fdbf..f0edc94 100644 (file)
     for (;;)
     {
       post_data = Get1Resource( TTAG_POST, res_id++ );
-      if ( post_data == NULL )
+      if ( !post_data )
         break;  /* we are done */
 
       code = (*post_data)[0];
     for (;;)
     {
       post_data = Get1Resource( TTAG_POST, res_id++ );
-      if ( post_data == NULL )
+      if ( !post_data )
         break;  /* we are done */
 
       post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
         if ( last_code != -1 )
         {
           /* we are done adding a chunk, fill in the size field */
-          if ( size_p != NULL )
+          if ( size_p )
           {
             *size_p++ = (FT_Byte)(   pfb_chunk_size         & 0xFF );
             *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8  ) & 0xFF );
 
 
     sfnt = GetResource( TTAG_sfnt, sfnt_id );
-    if ( sfnt == NULL )
+    if ( !sfnt )
       return FT_THROW( Invalid_Handle );
 
     sfnt_size = (FT_ULong)GetHandleSize( sfnt );
       return FT_THROW( Cannot_Open_Resource );
 
     num_faces_in_res = 0;
-    for ( res_index = 1; ; ++res_index )
+    for ( res_index = 1; ; res_index++ )
     {
       short  num_faces_in_fond;
 
     /* if it works, fine.                                           */
 
     error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
-    if ( error == 0 )
-      return error;
+    if ( error )
+    {
+      /* let it fall through to normal loader (.ttf, .otf, etc.); */
+      /* we signal this by returning no error and no FT_Face      */
+      *aface = NULL;
+    }
 
-    /* let it fall through to normal loader (.ttf, .otf, etc.); */
-    /* we signal this by returning no error and no FT_Face      */
-    *aface = NULL;
-    return 0;
+    return FT_Err_Ok;
   }
 
 
     /* try resourcefork based font: LWFN, FFIL */
     error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
                                        face_index, aface );
-    if ( error != 0 || *aface != NULL )
+    if ( error || *aface )
       return error;
 
     /* let it fall through to normal loader (.ttf, .otf, etc.) */
     args.flags    = FT_OPEN_PATHNAME;
     args.pathname = (char*)pathname;
+
     return FT_Open_Face( library, &args, face_index, aface );
   }
 
       error = FT_THROW( Cannot_Open_Resource );
 
     error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
-    if ( error != 0 || *aface != NULL )
+    if ( error || *aface )
       return error;
 
     /* fallback to datafork font */
index 6b759ca..1b724ac 100644 (file)
         error = service->set_mm_design( face, num_coords, coords );
     }
 
+    /* enforce recomputation of auto-hinting data */
+    if ( !error && face->autohint.finalizer )
+    {
+      face->autohint.finalizer( face->autohint.data );
+      face->autohint.data = NULL;
+    }
+
     return error;
   }
 
         error = service->set_var_design( face, num_coords, coords );
     }
 
+    /* enforce recomputation of auto-hinting data */
+    if ( !error && face->autohint.finalizer )
+    {
+      face->autohint.finalizer( face->autohint.data );
+      face->autohint.data = NULL;
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in ftmm.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_Var_Design_Coordinates( FT_Face    face,
+                                 FT_UInt    num_coords,
+                                 FT_Fixed*  coords )
+  {
+    FT_Error                 error;
+    FT_Service_MultiMasters  service;
+
+
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( !coords )
+      return FT_THROW( Invalid_Argument );
+
+    error = ft_face_get_mm_service( face, &service );
+    if ( !error )
+    {
+      error = FT_ERR( Invalid_Argument );
+      if ( service->get_var_design )
+        error = service->get_var_design( face, num_coords, coords );
+    }
+
     return error;
   }
 
     {
       error = FT_ERR( Invalid_Argument );
       if ( service->set_mm_blend )
-         error = service->set_mm_blend( face, num_coords, coords );
+        error = service->set_mm_blend( face, num_coords, coords );
+    }
+
+    /* enforce recomputation of auto-hinting data */
+    if ( !error && face->autohint.finalizer )
+    {
+      face->autohint.finalizer( face->autohint.data );
+      face->autohint.data = NULL;
     }
 
     return error;
     {
       error = FT_ERR( Invalid_Argument );
       if ( service->set_mm_blend )
-         error = service->set_mm_blend( face, num_coords, coords );
+        error = service->set_mm_blend( face, num_coords, coords );
+    }
+
+    /* enforce recomputation of auto-hinting data */
+    if ( !error && face->autohint.finalizer )
+    {
+      face->autohint.finalizer( face->autohint.data );
+      face->autohint.data = NULL;
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in ftmm.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_MM_Blend_Coordinates( FT_Face    face,
+                               FT_UInt    num_coords,
+                               FT_Fixed*  coords )
+  {
+    FT_Error                 error;
+    FT_Service_MultiMasters  service;
+
+
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( !coords )
+      return FT_THROW( Invalid_Argument );
+
+    error = ft_face_get_mm_service( face, &service );
+    if ( !error )
+    {
+      error = FT_ERR( Invalid_Argument );
+      if ( service->get_mm_blend )
+        error = service->get_mm_blend( face, num_coords, coords );
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in ftmm.h */
+
+  /* This is exactly the same as the previous function.  It exists for */
+  /* orthogonality.                                                    */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_Var_Blend_Coordinates( FT_Face    face,
+                                FT_UInt    num_coords,
+                                FT_Fixed*  coords )
+  {
+    FT_Error                 error;
+    FT_Service_MultiMasters  service;
+
+
+    /* check of `face' delayed to `ft_face_get_mm_service' */
+
+    if ( !coords )
+      return FT_THROW( Invalid_Argument );
+
+    error = ft_face_get_mm_service( face, &service );
+    if ( !error )
+    {
+      error = FT_ERR( Invalid_Argument );
+      if ( service->get_mm_blend )
+        error = service->get_mm_blend( face, num_coords, coords );
     }
 
     return error;
index 0c9e409..4f2a9ec 100644 (file)
 #define GRID_FIT_METRICS
 
 
+  /* forward declaration */
+  static FT_Error
+  ft_open_face_internal( FT_Library           library,
+                         const FT_Open_Args*  args,
+                         FT_Long              face_index,
+                         FT_Face             *aface,
+                         FT_Bool              test_mac_fonts );
+
+
   FT_BASE_DEF( FT_Pointer )
   ft_service_list_lookup( FT_ServiceDesc  service_descriptors,
                           const char*     service_id )
       load_flags &= ~FT_LOAD_RENDER;
     }
 
+    if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY )
+      load_flags &= ~FT_LOAD_RENDER;
+
     /*
      * Determine whether we need to auto-hint or not.
      * The general rules are:
 
     end = first + face->num_charmaps;  /* points after the last one */
 
-    for ( cur = first; cur < end; ++cur )
+    for ( cur = first; cur < end; cur++ )
     {
       if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE    &&
            cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
     args.pathname = (char*)pathname;
     args.stream   = NULL;
 
-    return FT_Open_Face( library, &args, face_index, aface );
+    return ft_open_face_internal( library, &args, face_index, aface, 1 );
   }
 
 #endif
     args.memory_size = file_size;
     args.stream      = NULL;
 
-    return FT_Open_Face( library, &args, face_index, aface );
+    return ft_open_face_internal( library, &args, face_index, aface, 1 );
   }
 
 
 
   /* Finalizer for a memory stream; gets called by FT_Done_Face(). */
   /* It frees the memory it uses.                                  */
-  /* From ftmac.c.                                                 */
+  /* From `ftmac.c'.                                               */
   static void
   memory_stream_close( FT_Stream  stream )
   {
 
 
   /* Create a new memory stream from a buffer and a size. */
-  /* From ftmac.c.                                        */
+  /* From `ftmac.c'.                                      */
   static FT_Error
   new_memory_stream( FT_Library           library,
                      FT_Byte*             base,
       return FT_THROW( Invalid_Argument );
 
     *astream = NULL;
-    memory = library->memory;
+    memory   = library->memory;
     if ( FT_NEW( stream ) )
       goto Exit;
 
 
 
   /* Create a new FT_Face given a buffer and a driver name. */
-  /* from ftmac.c */
+  /* From `ftmac.c'.                                        */
   FT_LOCAL_DEF( FT_Error )
   open_face_from_buffer( FT_Library   library,
                          FT_Byte*     base,
       return error;
     }
 
-    args.flags = FT_OPEN_STREAM;
+    args.flags  = FT_OPEN_STREAM;
     args.stream = stream;
     if ( driver_name )
     {
-      args.flags = args.flags | FT_OPEN_DRIVER;
+      args.flags  = args.flags | FT_OPEN_DRIVER;
       args.driver = FT_Get_Module( library, driver_name );
     }
 
       face_index &= 0x7FFF0000L; /* retain GX data */
 #endif
 
-    error = FT_Open_Face( library, &args, face_index, aface );
+    error = ft_open_face_internal( library, &args, face_index, aface, 0 );
 
-    if ( error == FT_Err_Ok )
+    if ( !error )
       (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
     else
 #ifdef FT_MACINTOSH
   {
     FT_Error   error  = FT_ERR( Cannot_Open_Resource );
     FT_Memory  memory = library->memory;
+
     FT_Byte*   pfb_data = NULL;
     int        i, type, flags;
     FT_ULong   len;
     /* Find the length of all the POST resources, concatenated.  Assume */
     /* worst case (each resource in its own section).                   */
     pfb_len = 0;
-    for ( i = 0; i < resource_cnt; ++i )
+    for ( i = 0; i < resource_cnt; i++ )
     {
       error = FT_Stream_Seek( stream, (FT_ULong)offsets[i] );
       if ( error )
         goto Exit;
-      if ( FT_READ_ULONG( temp ) )
+      if ( FT_READ_ULONG( temp ) )  /* actually LONG */
         goto Exit;
 
       /* FT2 allocator takes signed long buffer length,
        */
       FT_TRACE4(( "                 POST fragment #%d: length=0x%08x"
                   " total pfb_len=0x%08x\n",
-                  i, temp, pfb_len + temp + 6));
+                  i, temp, pfb_len + temp + 6 ));
+
       if ( FT_MAC_RFORK_MAX_LEN < temp               ||
            FT_MAC_RFORK_MAX_LEN - temp < pfb_len + 6 )
       {
         FT_TRACE2(( "             MacOS resource length cannot exceed"
-                    " 0x%08x\n", FT_MAC_RFORK_MAX_LEN ));
+                    " 0x%08x\n",
+                    FT_MAC_RFORK_MAX_LEN ));
+
         error = FT_THROW( Invalid_Offset );
         goto Exit;
       }
       pfb_len += temp + 6;
     }
 
-    FT_TRACE2(( "             total buffer size to concatenate %d"
-                " POST fragments: 0x%08x\n",
-                 resource_cnt, pfb_len + 2));
-    if ( pfb_len + 2 < 6 ) {
+    FT_TRACE2(( "             total buffer size to concatenate"
+                " %d POST fragments: 0x%08x\n",
+                 resource_cnt, pfb_len + 2 ));
+
+    if ( pfb_len + 2 < 6 )
+    {
       FT_TRACE2(( "             too long fragment length makes"
-                  " pfb_len confused: pfb_len=0x%08x\n", pfb_len ));
+                  " pfb_len confused: pfb_len=0x%08x\n",
+                  pfb_len ));
+
       error = FT_THROW( Array_Too_Large );
       goto Exit;
     }
+
     if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
       goto Exit;
 
     pfb_pos     = 6;
     pfb_lenpos  = 2;
 
-    len = 0;
+    len  = 0;
     type = 1;
-    for ( i = 0; i < resource_cnt; ++i )
+
+    for ( i = 0; i < resource_cnt; i++ )
     {
       error = FT_Stream_Seek( stream, (FT_ULong)offsets[i] );
       if ( error )
 
       if ( FT_READ_USHORT( flags ) )
         goto Exit2;
-      FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n",
-                   i, offsets[i], rlen, flags ));
+
+      FT_TRACE3(( "POST fragment[%d]:"
+                  " offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n",
+                  i, offsets[i], rlen, flags ));
 
       error = FT_ERR( Array_Too_Large );
-      /* postpone the check of rlen longer than buffer until FT_Stream_Read() */
+
+      /* postpone the check of `rlen longer than buffer' */
+      /* until `FT_Stream_Read'                          */
+
       if ( ( flags >> 8 ) == 0 )        /* Comment, should not be loaded */
       {
-        FT_TRACE3(( "    Skip POST fragment #%d because it is a comment\n", i ));
+        FT_TRACE3(( "    Skip POST fragment #%d because it is a comment\n",
+                    i ));
         continue;
       }
 
-      /* the flags are part of the resource, so rlen >= 2.  */
+      /* the flags are part of the resource, so rlen >= 2,  */
       /* but some fonts declare rlen = 0 for empty fragment */
       if ( rlen > 2 )
         rlen -= 2;
       else
       {
         FT_TRACE3(( "    Write POST fragment #%d header (4-byte) to buffer"
-                    " %p + 0x%08x\n", i, pfb_data, pfb_lenpos ));
+                    " %p + 0x%08x\n",
+                    i, pfb_data, pfb_lenpos ));
+
         if ( pfb_lenpos + 3 > pfb_len + 2 )
           goto Exit2;
+
         pfb_data[pfb_lenpos    ] = (FT_Byte)( len );
         pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );
         pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );
           break;
 
         FT_TRACE3(( "    Write POST fragment #%d header (6-byte) to buffer"
-                    " %p + 0x%08x\n", i, pfb_data, pfb_pos ));
+                    " %p + 0x%08x\n",
+                    i, pfb_data, pfb_pos ));
+
         if ( pfb_pos + 6 > pfb_len + 2 )
           goto Exit2;
+
         pfb_data[pfb_pos++] = 0x80;
 
         type = flags >> 8;
-        len = rlen;
+        len  = rlen;
 
         pfb_data[pfb_pos++] = (FT_Byte)type;
         pfb_lenpos          = pfb_pos;
         goto Exit2;
 
       FT_TRACE3(( "    Load POST fragment #%d (%d byte) to buffer"
-                  " %p + 0x%08x\n", i, rlen, pfb_data, pfb_pos ));
+                  " %p + 0x%08x\n",
+                  i, rlen, pfb_data, pfb_pos ));
+
       error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
       if ( error )
         goto Exit2;
+
       pfb_pos += rlen;
     }
 
     error = FT_ERR( Array_Too_Large );
+
     if ( pfb_pos + 2 > pfb_len + 2 )
       goto Exit2;
     pfb_data[pfb_pos++] = 0x80;
                                   aface );
 
   Exit2:
-    if ( error == FT_ERR( Array_Too_Large ) )
+    if ( FT_ERR_EQ( error, Array_Too_Large ) )
       FT_TRACE2(( "  Abort due to too-short buffer to store"
                   " all POST fragments\n" ));
-    else if ( error == FT_ERR( Invalid_Offset ) )
+    else if ( FT_ERR_EQ( error, Invalid_Offset ) )
       FT_TRACE2(( "  Abort due to invalid offset in a POST fragment\n" ));
+
     if ( error )
       error = FT_ERR( Cannot_Open_Resource );
     FT_FREE( pfb_data );
 
     if ( FT_READ_LONG( rlen ) )
       goto Exit;
-    if ( rlen == -1 )
+    if ( rlen 1 )
       return FT_THROW( Cannot_Open_Resource );
     if ( (FT_ULong)rlen > FT_MAC_RFORK_MAX_LEN )
       return FT_THROW( Invalid_Offset );
   {
     FT_Memory  memory = library->memory;
     FT_Error   error;
-    FT_Long    map_offset, rdara_pos;
+    FT_Long    map_offset, rdata_pos;
     FT_Long    *data_offsets;
     FT_Long    count;
 
 
     error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,
-                                       &map_offset, &rdara_pos );
+                                       &map_offset, &rdata_pos );
     if ( error )
       return error;
 
     /* POST resources must be sorted to concatenate properly */
     error = FT_Raccess_Get_DataOffsets( library, stream,
-                                        map_offset, rdara_pos,
+                                        map_offset, rdata_pos,
                                         TTAG_POST, TRUE,
                                         &data_offsets, &count );
     if ( !error )
     /* sfnt resources should not be sorted to preserve the face order by
        QuickDraw API */
     error = FT_Raccess_Get_DataOffsets( library, stream,
-                                        map_offset, rdara_pos,
+                                        map_offset, rdata_pos,
                                         TTAG_sfnt, FALSE,
                                         &data_offsets, &count );
     if ( !error )
     FT_Long        dlen, offset;
 
 
-    if ( NULL == stream )
+    if ( !stream )
       return FT_THROW( Invalid_Stream_Operation );
 
     error = FT_Stream_Seek( stream, 0 );
                 const FT_Open_Args*  args,
                 FT_Long              face_index,
                 FT_Face             *aface )
+  {
+    return ft_open_face_internal( library, args, face_index, aface, 1 );
+  }
+
+
+  static FT_Error
+  ft_open_face_internal( FT_Library           library,
+                         const FT_Open_Args*  args,
+                         FT_Long              face_index,
+                         FT_Face             *aface,
+                         FT_Bool              test_mac_fonts )
   {
     FT_Error     error;
     FT_Driver    driver = NULL;
     FT_Module*   cur;
     FT_Module*   limit;
 
+#ifndef FT_CONFIG_OPTION_MAC_FONTS
+    FT_UNUSED( test_mac_fonts );
+#endif
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+    FT_TRACE3(( "FT_Open_Face: " ));
+    if ( face_index < 0 )
+      FT_TRACE3(( "Requesting number of faces and named instances\n"));
+    else
+    {
+      FT_TRACE3(( "Requesting face %ld", face_index & 0xFFFFL ));
+      if ( face_index & 0x7FFF0000L )
+        FT_TRACE3(( ", named instance %ld", face_index >> 16 ));
+      FT_TRACE3(( "\n" ));
+    }
+#endif
 
     /* test for valid `library' delayed to `FT_Stream_New' */
 
             goto Success;
 
 #ifdef FT_CONFIG_OPTION_MAC_FONTS
-          if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 &&
+          if ( test_mac_fonts                                           &&
+               ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 &&
                FT_ERR_EQ( error, Table_Missing )                        )
           {
             /* TrueType but essential tables are missing */
         goto Fail2;
 
 #if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
-      error = load_mac_face( library, stream, face_index, aface, args );
-      if ( !error )
+      if ( test_mac_fonts )
       {
-        /* We don't want to go to Success here.  We've already done that. */
-        /* On the other hand, if we succeeded we still need to close this */
-        /* stream (we opened a different stream which extracted the       */
-        /* interesting information out of this stream here.  That stream  */
-        /* will still be open and the face will point to it).             */
-        FT_Stream_Free( stream, external_stream );
-        return error;
+        error = load_mac_face( library, stream, face_index, aface, args );
+        if ( !error )
+        {
+          /* We don't want to go to Success here.  We've already done   */
+          /* that.  On the other hand, if we succeeded we still need to */
+          /* close this stream (we opened a different stream which      */
+          /* extracted the interesting information out of this stream   */
+          /* here.  That stream will still be open and the face will    */
+          /* point to it).                                              */
+          FT_Stream_Free( stream, external_stream );
+          return error;
+        }
       }
 
       if ( FT_ERR_NEQ( error, Unknown_File_Format ) )
       destroy_face( memory, face, driver );
 
   Exit:
+#ifdef FT_DEBUG_LEVEL_TRACE
+    if ( !error && face_index < 0 )
+    {
+      FT_TRACE3(( "FT_Open_Face: The font has %ld faces\n"
+                  "              and %ld named instances for face %ld\n",
+                  face->num_faces,
+                  face->style_flags >> 16,
+                  -face_index - 1 ));
+    }
+#endif
+
     FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
 
     return error;
     w = FT_PIX_ROUND( w );
     h = FT_PIX_ROUND( h );
 
+    if ( !w || !h )
+      return FT_THROW( Invalid_Pixel_Size );
+
     for ( i = 0; i < face->num_fixed_sizes; i++ )
     {
       FT_Bitmap_Size*  bsize = face->available_sizes + i;
       }
     }
 
+    FT_TRACE3(( "FT_Match_Size: no matching bitmap strike\n" ));
+
     return FT_THROW( Invalid_Pixel_Size );
   }
 
     FT_CMap    cmap = NULL;
 
 
-    if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
+    if ( !clazz || !charmap || !charmap->face )
       return FT_THROW( Invalid_Argument );
 
     face   = charmap->face;
       FT_CMap     ucmap = FT_CMAP( face->charmap );
 
 
-      if ( charmap != NULL )
+      if ( charmap )
       {
         FT_CMap  vcmap = FT_CMAP( charmap );
 
       FT_CharMap  charmap = find_variant_selector_charmap( face );
 
 
-      if ( charmap != NULL )
+      if ( charmap )
       {
         FT_CMap  vcmap = FT_CMAP( charmap );
 
       FT_CharMap  charmap = find_variant_selector_charmap( face );
 
 
-      if ( charmap != NULL )
+      if ( charmap )
       {
         FT_CMap    vcmap  = FT_CMAP( charmap );
         FT_Memory  memory = FT_FACE_MEMORY( face );
       FT_CharMap  charmap = find_variant_selector_charmap( face );
 
 
-      if ( charmap != NULL )
+      if ( charmap )
       {
         FT_CMap    vcmap  = FT_CMAP( charmap );
         FT_Memory  memory = FT_FACE_MEMORY( face );
       FT_CharMap  charmap = find_variant_selector_charmap( face );
 
 
-      if ( charmap != NULL )
+      if ( charmap )
       {
         FT_CMap    vcmap  = FT_CMAP( charmap );
         FT_Memory  memory = FT_FACE_MEMORY( face );
     if ( face && FT_IS_SFNT( face ) )
     {
       FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
-      if ( service != NULL )
+      if ( service )
         table = service->get_table( face, tag );
     }
 
       return FT_THROW( Invalid_Face_Handle );
 
     FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
-    if ( service == NULL )
+    if ( !service )
       return FT_THROW( Unimplemented_Feature );
 
     return service->load_table( face, tag, offset, buffer, length );
       return FT_THROW( Invalid_Face_Handle );
 
     FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
-    if ( service == NULL )
+    if ( !service )
       return FT_THROW( Unimplemented_Feature );
 
     return service->table_info( face, table_index, tag, &offset, length );
 
     face = charmap->face;
     FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
-    if ( service == NULL )
+    if ( !service )
       return 0;
     if ( service->get_cmap_info( charmap, &cmap_info ))
       return 0;
 
     face = charmap->face;
     FT_FACE_FIND_SERVICE( face, service, TT_CMAP );
-    if ( service == NULL )
+    if ( !service )
       return -1;
     if ( service->get_cmap_info( charmap, &cmap_info ))
       return -1;
     if ( ft_trace_levels[trace_bitmap] >= 3 )
     {
       /* we convert to a single bitmap format for computing the checksum */
-      if ( !error )
+      if ( !error && slot->bitmap.buffer )
       {
         FT_Bitmap  bitmap;
         FT_Error   err;
 
   FT_BASE_DEF( FT_Pointer )
   ft_module_get_service( FT_Module    module,
-                         const char*  service_id )
+                         const char*  service_id,
+                         FT_Bool      global )
   {
     FT_Pointer  result = NULL;
 
       if ( module->clazz->get_interface )
         result = module->clazz->get_interface( module, service_id );
 
-      if ( result == NULL )
+      if ( global && !result )
       {
         /* we didn't find it, look in all other modules then */
         FT_Library  library = module->library;
             if ( cur[0]->clazz->get_interface )
             {
               result = cur[0]->clazz->get_interface( cur[0], service_id );
-              if ( result != NULL )
+              if ( result )
                 break;
             }
           }
 
         service = (FT_Service_TrueTypeEngine)
                     ft_module_get_service( module,
-                                           FT_SERVICE_ID_TRUETYPE_ENGINE );
+                                           FT_SERVICE_ID_TRUETYPE_ENGINE,
+                                           0 );
         if ( service )
           result = service->engine_type;
       }
index 4660c97..eac2ddb 100644 (file)
@@ -56,7 +56,7 @@
   {
     FT_Error       error;
     unsigned char  head[16], head2[16];
-    FT_Long        map_pos, rdata_len;
+    FT_Long        map_pos, map_len, rdata_len;
     int            allzeros, allmatch, i;
     FT_Long        type_list;
 
     if ( error )
       return error;
 
-    error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );
+    error = FT_Stream_Read( stream, (FT_Byte*)head, 16 );
     if ( error )
       return error;
 
     /* ensure positive values */
-    if ( head[0] >= 0x80 || head[4] >= 0x80 || head[8] >= 0x80 )
+    if ( head[0]  >= 0x80 ||
+         head[4]  >= 0x80 ||
+         head[8]  >= 0x80 ||
+         head[12] >= 0x80 )
       return FT_THROW( Unknown_File_Format );
 
     *rdata_pos = ( head[ 0] << 24 ) |
                  ( head[ 9] << 16 ) |
                  ( head[10] <<  8 ) |
                    head[11];
+    map_len    = ( head[12] << 24 ) |
+                 ( head[13] << 16 ) |
+                 ( head[14] <<  8 ) |
+                   head[15];
 
-    /* map_len = head[12] .. head[15] */
-
-    if ( *rdata_pos != map_pos - rdata_len || map_pos == 0 )
+    /* the map must not be empty */
+    if ( !map_pos )
       return FT_THROW( Unknown_File_Format );
 
-    if ( FT_LONG_MAX - rfork_offset < *rdata_pos ||
-         FT_LONG_MAX - rfork_offset < map_pos    )
+    /* check whether rdata and map overlap */
+    if ( *rdata_pos < map_pos )
+    {
+      if ( *rdata_pos > map_pos - rdata_len )
+        return FT_THROW( Unknown_File_Format );
+    }
+    else
+    {
+      if ( map_pos > *rdata_pos - map_len )
+        return FT_THROW( Unknown_File_Format );
+    }
+
+    /* check whether end of rdata or map exceeds stream size */
+    if ( FT_LONG_MAX - rdata_len < *rdata_pos                               ||
+         FT_LONG_MAX - map_len < map_pos                                    ||
+
+         FT_LONG_MAX - ( *rdata_pos + rdata_len ) < rfork_offset            ||
+         FT_LONG_MAX - ( map_pos + map_len ) < rfork_offset                 ||
+
+         (FT_ULong)( rfork_offset + *rdata_pos + rdata_len ) > stream->size ||
+         (FT_ULong)( rfork_offset + map_pos + map_len ) > stream->size      )
       return FT_THROW( Unknown_File_Format );
 
     *rdata_pos += rfork_offset;
 
     allzeros = 1;
     allmatch = 1;
-    for ( i = 0; i < 16; ++i )
+    for ( i = 0; i < 16; i++ )
     {
       if ( head2[i] != 0 )
         allzeros = 0;
 
     /* If we have reached this point then it is probably a mac resource */
     /* file.  Now, does it contain any interesting resources?           */
-    /* Skip handle to next resource map, the file resource number, and  */
-    /* attributes.                                                      */
+
     (void)FT_STREAM_SKIP( 4        /* skip handle to next resource map */
                           + 2      /* skip file resource number */
                           + 2 );   /* skip attributes */
 
-    if ( FT_READ_USHORT( type_list ) )
+    if ( FT_READ_SHORT( type_list ) )
       return error;
-    if ( type_list == -1 )
+    if ( type_list < 0 )
       return FT_THROW( Unknown_File_Format );
 
     error = FT_Stream_Seek( stream, (FT_ULong)( map_pos + type_list ) );
     if ( error )
       return error;
 
-    if ( FT_READ_USHORT( cnt ) )
+    if ( FT_READ_SHORT( cnt ) )
       return error;
     cnt++;
 
-    for ( i = 0; i < cnt; ++i )
+    /* `rpos' is a signed 16bit integer offset to resource records; the    */
+    /* size of a resource record is 12 bytes.  The map header is 28 bytes, */
+    /* and a type list needs 10 bytes or more.  If we assume that the name */
+    /* list is empty and we have only a single entry in the type list,     */
+    /* there can be at most                                                */
+    /*                                                                     */
+    /*   (32768 - 28 - 10) / 12 = 2727                                     */
+    /*                                                                     */
+    /* resources.                                                          */
+    /*                                                                     */
+    /* A type list starts with a two-byte counter, followed by 10-byte     */
+    /* type records.  Assuming that there are no resources, the number of  */
+    /* type records can be at most                                         */
+    /*                                                                     */
+    /*   (32768 - 28 - 2) / 8 = 4079                                       */
+    /*                                                                     */
+    if ( cnt > 4079 )
+      return FT_THROW( Invalid_Table );
+
+    for ( i = 0; i < cnt; i++ )
     {
       if ( FT_READ_LONG( tag_internal ) ||
-           FT_READ_USHORT( subcnt )     ||
-           FT_READ_USHORT( rpos )       )
+           FT_READ_SHORT( subcnt )      ||
+           FT_READ_SHORT( rpos )        )
         return error;
 
       FT_TRACE2(( "Resource tags: %c%c%c%c\n",
         *count = subcnt + 1;
         rpos  += map_offset;
 
+        /* a zero count might be valid in the resource specification, */
+        /* however, it is completely useless to us                    */
+        if ( *count < 1 || *count > 2727 )
+          return FT_THROW( Invalid_Table );
+
         error = FT_Stream_Seek( stream, (FT_ULong)rpos );
         if ( error )
           return error;
         if ( FT_NEW_ARRAY( ref, *count ) )
           return error;
 
-        for ( j = 0; j < *count; ++j )
+        for ( j = 0; j < *count; j++ )
         {
-          if ( FT_READ_USHORT( ref[j].res_id ) )
+          if ( FT_READ_SHORT( ref[j].res_id ) )
             goto Exit;
-          if ( FT_STREAM_SKIP( 2 ) ) /* resource name */
+          if ( FT_STREAM_SKIP( 2 ) )  /* resource name offset */
             goto Exit;
-          if ( FT_READ_LONG( temp ) )
+          if ( FT_READ_LONG( temp ) ) /* attributes (8bit), offset (24bit) */
             goto Exit;
-          if ( FT_STREAM_SKIP( 4 ) ) /* mbz */
+          if ( FT_STREAM_SKIP( 4 ) )  /* mbz */
+            goto Exit;
+
+          if ( ref[j].res_id < 0 || temp < 0 )
+          {
+            error = FT_THROW( Invalid_Table );
             goto Exit;
+          }
 
           ref[j].offset = temp & 0xFFFFFFL;
+
           FT_TRACE3(( "             [%d]:"
                       " resource_id=0x%04x, offset=0x%08x\n",
                       j, ref[j].res_id, ref[j].offset ));
         }
 
-        if (sort_by_res_id)
+        if ( sort_by_res_id )
         {
-          ft_qsort( ref, (size_t)*count, sizeof ( FT_RFork_Ref ),
-                    ( int(*)(const void*, const void*) )
-                    ft_raccess_sort_ref_by_id );
+          ft_qsort( ref,
+                    (size_t)*count,
+                    sizeof ( FT_RFork_Ref ),
+                    ( int(*)(const void*,
+                             const void*) )ft_raccess_sort_ref_by_id );
 
           FT_TRACE3(( "             -- sort resources by their ids --\n" ));
-          for ( j = 0; j < *count; ++ j ) {
+
+          for ( j = 0; j < *count; j++ )
             FT_TRACE3(( "             [%d]:"
                         " resource_id=0x%04x, offset=0x%08x\n",
                         j, ref[j].res_id, ref[j].offset ));
-          }
         }
 
         if ( FT_NEW_ARRAY( offsets_internal, *count ) )
          *      gap between reference IDs are acceptable?
          *      further investigation on Apple implementation is needed.
          */
-        for ( j = 0; j < *count; ++j )
+        for ( j = 0; j < *count; j++ )
           offsets_internal[j] = rdata_pos + ref[j].offset;
 
         *offsets = offsets_internal;
index ce79641..e0d5f82 100644 (file)
@@ -58,7 +58,7 @@
 
 
         /* load name on demand */
-        if ( entry->stringLength > 0 && entry->string == NULL )
+        if ( entry->stringLength > 0 && !entry->string )
         {
           FT_Memory  memory = face->memory;
           FT_Stream  stream = face->stream;
index fad7d1a..36d2dd7 100644 (file)
@@ -74,7 +74,7 @@
     if ( size > 0 )
     {
       block = memory->alloc( memory, size );
-      if ( block == NULL )
+      if ( !block )
         error = FT_THROW( Out_Of_Memory );
     }
     else if ( size < 0 )
     }
     else if ( cur_count == 0 )
     {
-      FT_ASSERT( block == NULL );
+      FT_ASSERT( !block );
 
       block = ft_mem_alloc( memory, new_count*item_size, &error );
     }
 
 
       block2 = memory->realloc( memory, cur_size, new_size, block );
-      if ( block2 == NULL )
+      if ( !block2 )
         error = FT_THROW( Out_Of_Memory );
       else
         block = block2;
index a381cf6..a2242be 100644 (file)
@@ -276,7 +276,7 @@ THE SOFTWARE.
 
         len = lengths[nn];
 
-        if ( src == NULL )
+        if ( !src )
           continue;
 
         /* separate elements with a space */
@@ -423,7 +423,7 @@ THE SOFTWARE.
       else
         bdfface->family_name = NULL;
 
-      if ( ( error = bdf_interpret_style( face ) ) != 0 )
+      if ( FT_SET_ERROR( bdf_interpret_style( face ) ) )
         goto Exit;
 
       /* the number of glyphs (with one slot for the undefined glyph */
@@ -439,7 +439,7 @@ THE SOFTWARE.
         FT_Short         resolution_x = 0, resolution_y = 0;
 
 
-        FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
+        FT_ZERO( bsize );
 
         bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
 
@@ -866,10 +866,10 @@ THE SOFTWARE.
       0x10000L,
       0x20000L,
 
-      0,    /* module-specific interface */
+      NULL,    /* module-specific interface */
 
-      0,                        /* FT_Module_Constructor  module_init   */
-      0,                        /* FT_Module_Destructor   module_done   */
+      NULL,                     /* FT_Module_Constructor  module_init   */
+      NULL,                     /* FT_Module_Destructor   module_done   */
       bdf_driver_requester      /* FT_Module_Requester    get_interface */
     },
 
@@ -879,16 +879,16 @@ THE SOFTWARE.
 
     BDF_Face_Init,              /* FT_Face_InitFunc  init_face */
     BDF_Face_Done,              /* FT_Face_DoneFunc  done_face */
-    0,                          /* FT_Size_InitFunc  init_size */
-    0,                          /* FT_Size_DoneFunc  done_size */
-    0,                          /* FT_Slot_InitFunc  init_slot */
-    0,                          /* FT_Slot_DoneFunc  done_slot */
+    NULL,                       /* FT_Size_InitFunc  init_size */
+    NULL,                       /* FT_Size_DoneFunc  done_size */
+    NULL,                       /* FT_Slot_InitFunc  init_slot */
+    NULL,                       /* FT_Slot_DoneFunc  done_slot */
 
     BDF_Glyph_Load,             /* FT_Slot_LoadFunc  load_glyph */
 
-    0,                          /* FT_Face_GetKerningFunc   get_kerning  */
-    0,                          /* FT_Face_AttachFunc       attach_file  */
-    0,                          /* FT_Face_GetAdvancesFunc  get_advances */
+    NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
+    NULL,                       /* FT_Face_AttachFunc       attach_file  */
+    NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
 
     BDF_Size_Request,           /* FT_Size_RequestFunc  request_size */
     BDF_Size_Select             /* FT_Size_SelectFunc   select_size  */
index e1dce95..7fd95a7 100644 (file)
     /* See whether this property type exists yet or not. */
     /* If not, create it.                                */
     propid = ft_hash_str_lookup( name, &(font->proptbl) );
-    if ( propid == NULL )
+    if ( !propid )
     {
       error = bdf_create_property( name, BDF_ATOM, font );
       if ( error )
       }
 
       fp = font->props + font->props_size;
-      FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) );
+      FT_ZERO( fp );
       font->props_size++;
     }
 
         p->font->comments[p->font->comments_len] = 0;
       }
     }
-    else if ( error == FT_Err_Ok )
+    else if ( !error )
       error = FT_THROW( Invalid_File_Format );
 
     *font = p->font;
index 4577a83..4d0b388 100644 (file)
     bzstream->next_in  = (char*)zip->buffer;
 
     if ( BZ2_bzDecompressInit( bzstream, 0, 0 ) != BZ_OK ||
-         bzstream->next_in == NULL                       )
+         !bzstream->next_in                              )
       error = FT_THROW( Invalid_File_Format );
 
   Exit:
index 8e6de8c..fc8905c 100644 (file)
   {
     {
       sizeof ( FTC_BasicFamilyRec ),
-      ftc_basic_family_compare,
-      ftc_basic_family_init,
-      0,                        /* FTC_MruNode_ResetFunc */
-      0                         /* FTC_MruNode_DoneFunc  */
+
+      ftc_basic_family_compare, /* FTC_MruNode_CompareFunc  node_compare */
+      ftc_basic_family_init,    /* FTC_MruNode_InitFunc     node_init    */
+      NULL,                     /* FTC_MruNode_ResetFunc    node_reset   */
+      NULL                      /* FTC_MruNode_DoneFunc     node_done    */
     },
-    ftc_basic_family_load_glyph
+
+    ftc_basic_family_load_glyph /* FTC_IFamily_LoadGlyphFunc  family_load_glyph */
   };
 
 
   const FTC_GCacheClassRec  ftc_basic_image_cache_class =
   {
     {
-      ftc_inode_new,
-      ftc_inode_weight,
-      ftc_gnode_compare,
-      ftc_basic_gnode_compare_faceid,
-      ftc_inode_free,
+      ftc_inode_new,                  /* FTC_Node_NewFunc      node_new           */
+      ftc_inode_weight,               /* FTC_Node_WeightFunc   node_weight        */
+      ftc_gnode_compare,              /* FTC_Node_CompareFunc  node_compare       */
+      ftc_basic_gnode_compare_faceid, /* FTC_Node_CompareFunc  node_remove_faceid */
+      ftc_inode_free,                 /* FTC_Node_FreeFunc     node_free          */
 
       sizeof ( FTC_GCacheRec ),
-      ftc_gcache_init,
-      ftc_gcache_done
+      ftc_gcache_init,                /* FTC_Cache_InitFunc    cache_init         */
+      ftc_gcache_done                 /* FTC_Cache_DoneFunc    cache_done         */
     },
+
     (FTC_MruListClass)&ftc_basic_image_family_class
   };
 
   {
     {
       sizeof ( FTC_BasicFamilyRec ),
-      ftc_basic_family_compare,
-      ftc_basic_family_init,
-      0,                            /* FTC_MruNode_ResetFunc */
-      0                             /* FTC_MruNode_DoneFunc  */
+      ftc_basic_family_compare,     /* FTC_MruNode_CompareFunc  node_compare */
+      ftc_basic_family_init,        /* FTC_MruNode_InitFunc     node_init    */
+      NULL,                         /* FTC_MruNode_ResetFunc    node_reset   */
+      NULL                          /* FTC_MruNode_DoneFunc     node_done    */
     },
+
     ftc_basic_family_get_count,
     ftc_basic_family_load_bitmap
   };
   const FTC_GCacheClassRec  ftc_basic_sbit_cache_class =
   {
     {
-      ftc_snode_new,
-      ftc_snode_weight,
-      ftc_snode_compare,
-      ftc_basic_gnode_compare_faceid,
-      ftc_snode_free,
+      ftc_snode_new,                  /* FTC_Node_NewFunc      node_new           */
+      ftc_snode_weight,               /* FTC_Node_WeightFunc   node_weight        */
+      ftc_snode_compare,              /* FTC_Node_CompareFunc  node_compare       */
+      ftc_basic_gnode_compare_faceid, /* FTC_Node_CompareFunc  node_remove_faceid */
+      ftc_snode_free,                 /* FTC_Node_FreeFunc     node_free          */
 
       sizeof ( FTC_GCacheRec ),
-      ftc_gcache_init,
-      ftc_gcache_done
+      ftc_gcache_init,                /* FTC_Cache_InitFunc    cache_init         */
+      ftc_gcache_done                 /* FTC_Cache_DoneFunc    cache_done         */
     },
+
     (FTC_MruListClass)&ftc_basic_sbit_family_class
   };
 
index 3b1a4bc..de20255 100644 (file)
         for (;;)
         {
           node = *pnode;
-          if ( node == NULL )
+          if ( !node )
             break;
 
           if ( node->hash & ( mask + 1 ) )
       FTC_Node  node = *pnode;
 
 
-      if ( node == NULL )
+      if ( !node )
       {
         FT_TRACE0(( "ftc_node_hash_unlink: unknown node\n" ));
         return;
     cache = manager->caches[node->cache_index];
 
 #ifdef FT_DEBUG_ERROR
-    if ( cache == NULL )
+    if ( !cache )
     {
       FT_TRACE0(( "ftc_node_destroy: invalid node handle\n" ));
       return;
     FTC_Node_CompareFunc  compare = cache->clazz.node_compare;
 
 
-    if ( cache == NULL || anode == NULL )
+    if ( !cache || !anode )
       return FT_THROW( Invalid_Argument );
 
     /* Go to the `top' node of the list sharing same masked hash */
     for (;;)
     {
       node = *pnode;
-      if ( node == NULL )
+      if ( !node )
         goto NewNode;
 
       if ( node->hash == hash                           &&
       /* Update pnode by modified linked list */
       while ( *pnode != node )
       {
-        if ( *pnode == NULL )
+        if ( !*pnode )
         {
           FT_ERROR(( "FTC_Cache_Lookup: oops!!!  node missing\n" ));
           goto NewNode;
         FT_Bool   list_changed = FALSE;
 
 
-        if ( node == NULL )
+        if ( !node )
           break;
 
         if ( cache->clazz.node_remove_faceid( node, face_id,
index 1b12959..ab4ea51 100644 (file)
@@ -227,7 +227,7 @@ FT_BEGIN_HEADER
     for (;;)                                                             \
     {                                                                    \
       _node = *_pnode;                                                   \
-      if ( _node == NULL )                                               \
+      if ( !_node )                                                      \
         goto NewNode_;                                                   \
                                                                          \
       if ( _node->hash == _hash                             &&           \
@@ -245,7 +245,7 @@ FT_BEGIN_HEADER
       /* Update _pnode by possibly modified linked list */               \
       while ( *_pnode != _node )                                         \
       {                                                                  \
-        if ( *_pnode == NULL )                                           \
+        if ( !*_pnode )                                                  \
         {                                                                \
           FT_ERROR(( "FTC_CACHE_LOOKUP_CMP: oops!!! node missing\n" ));  \
           goto NewNode_;                                                 \
@@ -325,7 +325,7 @@ FT_BEGIN_HEADER
         break;                                                    \
                                                                   \
       _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
-      if ( _try_done > 0 && ( list_changed != NULL ) )            \
+      if ( _try_done > 0 && list_changed != NULL )                \
         *(FT_Bool*)( list_changed ) = TRUE;                       \
                                                                   \
       if ( _try_done == 0 )                                       \
index 41a0ce9..f0a85f9 100644 (file)
   static
   const FTC_CacheClassRec  ftc_cmap_cache_class =
   {
-    ftc_cmap_node_new,
-    ftc_cmap_node_weight,
-    ftc_cmap_node_compare,
-    ftc_cmap_node_remove_faceid,
-    ftc_cmap_node_free,
+    ftc_cmap_node_new,           /* FTC_Node_NewFunc      node_new           */
+    ftc_cmap_node_weight,        /* FTC_Node_WeightFunc   node_weight        */
+    ftc_cmap_node_compare,       /* FTC_Node_CompareFunc  node_compare       */
+    ftc_cmap_node_remove_faceid, /* FTC_Node_CompareFunc  node_remove_faceid */
+    ftc_cmap_node_free,          /* FTC_Node_FreeFunc     node_free          */
 
     sizeof ( FTC_CacheRec ),
-    ftc_cache_init,
-    ftc_cache_done,
+    ftc_cache_init,              /* FTC_Cache_InitFunc    cache_init         */
+    ftc_cache_done,              /* FTC_Cache_DoneFunc    cache_done         */
   };
 
 
index 661a32a..9a25b97 100644 (file)
   const FTC_MruListClassRec  ftc_size_list_class =
   {
     sizeof ( FTC_SizeNodeRec ),
-    ftc_size_node_compare,
-    ftc_size_node_init,
-    ftc_size_node_reset,
-    ftc_size_node_done
+
+    ftc_size_node_compare,  /* FTC_MruNode_CompareFunc  node_compare */
+    ftc_size_node_init,     /* FTC_MruNode_InitFunc     node_init    */
+    ftc_size_node_reset,    /* FTC_MruNode_ResetFunc    node_reset   */
+    ftc_size_node_done      /* FTC_MruNode_DoneFunc     node_done    */
   };
 
 
   {
     sizeof ( FTC_FaceNodeRec),
 
-    ftc_face_node_compare,
-    ftc_face_node_init,
-    0,                          /* FTC_MruNode_ResetFunc */
-    ftc_face_node_done
+    ftc_face_node_compare,  /* FTC_MruNode_CompareFunc  node_compare */
+    ftc_face_node_init,     /* FTC_MruNode_InitFunc     node_init    */
+    NULL,                   /* FTC_MruNode_ResetFunc    node_reset   */
+    ftc_face_node_done      /* FTC_MruNode_DoneFunc     node_done    */
   };
 
 
                 manager->num_nodes ));
 #endif
 
-    if ( manager->cur_weight < manager->max_weight || first == NULL )
+    if ( manager->cur_weight < manager->max_weight || !first )
       return;
 
     /* go to last node -- it's a circular list */
 
 
     /* try to remove `count' nodes from the list */
-    if ( first == NULL )  /* empty list! */
+    if ( !first )  /* empty list! */
       return 0;
 
     /* go to last node - it's a circular list */
index d107584..7c460b9 100644 (file)
@@ -76,7 +76,7 @@
     FTC_MruNode  first = *plist;
 
 
-    FT_ASSERT( first != NULL );
+    FT_ASSERT( first );
 
     if ( first != node )
     {
     FTC_MruNode  prev, next;
 
 
-    FT_ASSERT( first != NULL );
+    FT_ASSERT( first );
 
 #ifdef FT_DEBUG_ERROR
       {
                    FTC_MruNode  *anode )
   {
     FT_Error     error;
-    FTC_MruNode  node = NULL;
+    FTC_MruNode  node   = NULL;
     FT_Memory    memory = list->memory;
 
 
 
 
     node = FTC_MruList_Find( list, key );
-    if ( node == NULL )
+    if ( !node )
       return FTC_MruList_New( list, key, anode );
 
     *anode = node;
 
 
     first = list->nodes;
-    while ( first && ( selection == NULL || selection( first, key ) ) )
+    while ( first && ( !selection || selection( first, key ) ) )
     {
       FTC_MruList_Remove( list, first );
       first = list->nodes;
index ae3c4ce..27ad55a 100644 (file)
@@ -108,6 +108,7 @@ FT_BEGIN_HEADER
   typedef struct  FTC_MruListClassRec_
   {
     FT_Offset                node_size;
+
     FTC_MruNode_CompareFunc  node_compare;
     FTC_MruNode_InitFunc     node_init;
     FTC_MruNode_ResetFunc    node_reset;
@@ -115,6 +116,7 @@ FT_BEGIN_HEADER
 
   } FTC_MruListClassRec;
 
+
   typedef struct  FTC_MruListRec_
   {
     FT_UInt              num_nodes;
index d6f1ddc..78cd8de 100644 (file)
        *
        */
 
-      if ( sbit->buffer == NULL && sbit->width == 255 )
+      if ( !sbit->buffer && sbit->width == 255 )
       {
         FT_ULong  size;
         FT_Error  error;
index 89f3e9f..6796450 100644 (file)
@@ -58,7 +58,7 @@
                      FT_Error*     error,
                      size_t        sizeItem )
   {
-    FT_ASSERT( arrstack != NULL );
+    FT_ASSERT( arrstack );
 
     /* initialize the structure */
     arrstack->memory    = memory;
@@ -78,7 +78,7 @@
     FT_Memory  memory = arrstack->memory;     /* for FT_FREE */
 
 
-    FT_ASSERT( arrstack != NULL );
+    FT_ASSERT( arrstack );
 
     arrstack->allocated = 0;
     arrstack->count     = 0;
@@ -95,7 +95,7 @@
   cf2_arrstack_setNumElements( CF2_ArrStack  arrstack,
                                size_t        numElements )
   {
-    FT_ASSERT( arrstack != NULL );
+    FT_ASSERT( arrstack );
 
     {
       FT_Error   error  = FT_Err_Ok;        /* for FT_REALLOC */
   cf2_arrstack_setCount( CF2_ArrStack  arrstack,
                          size_t        numElements )
   {
-    FT_ASSERT( arrstack != NULL );
+    FT_ASSERT( arrstack );
 
     if ( numElements > arrstack->allocated )
     {
   FT_LOCAL_DEF( void )
   cf2_arrstack_clear( CF2_ArrStack  arrstack )
   {
-    FT_ASSERT( arrstack != NULL );
+    FT_ASSERT( arrstack );
 
     arrstack->count = 0;
   }
   FT_LOCAL_DEF( size_t )
   cf2_arrstack_size( const CF2_ArrStack  arrstack )
   {
-    FT_ASSERT( arrstack != NULL );
+    FT_ASSERT( arrstack );
 
     return arrstack->count;
   }
   FT_LOCAL_DEF( void* )
   cf2_arrstack_getBuffer( const CF2_ArrStack  arrstack )
   {
-    FT_ASSERT( arrstack != NULL );
+    FT_ASSERT( arrstack );
 
     return arrstack->ptr;
   }
     void*  newPtr;
 
 
-    FT_ASSERT( arrstack != NULL );
+    FT_ASSERT( arrstack );
 
     if ( idx >= arrstack->count )
     {
   cf2_arrstack_push( CF2_ArrStack  arrstack,
                      const void*   ptr )
   {
-    FT_ASSERT( arrstack != NULL );
+    FT_ASSERT( arrstack );
 
     if ( arrstack->count == arrstack->allocated )
     {
       }
     }
 
-    FT_ASSERT( ptr != NULL );
+    FT_ASSERT( ptr );
 
     {
       size_t  offset = arrstack->count * arrstack->sizeItem;
index b5595a3..e3dd69f 100644 (file)
@@ -44,7 +44,7 @@
   cf2_setError( FT_Error*  error,
                 FT_Error   value )
   {
-    if ( error && *error == 0 )
+    if ( error && !*error )
       *error = value;
   }
 
index 74af377..2e4b503 100644 (file)
@@ -51,8 +51,8 @@ FT_BEGIN_HEADER
 
 #define CF2_FIXED_MAX      ( (CF2_Fixed)0x7FFFFFFFL )
 #define CF2_FIXED_MIN      ( (CF2_Fixed)0x80000000L )
-#define CF2_FIXED_ONE      0x10000L
-#define CF2_FIXED_EPSILON  0x0001
+#define CF2_FIXED_ONE      ( (CF2_Fixed)0x10000L )
+#define CF2_FIXED_EPSILON  ( (CF2_Fixed)0x0001 )
 
   /* in C 89, left and right shift of negative numbers is  */
   /* implementation specific behaviour in the general case */
index 83fd348..a86e361 100644 (file)
   }
 
 
-  /* set up values for the current FontDict and matrix */
+  /* set up values for the current FontDict and matrix; */
+  /* called for each glyph to be rendered               */
 
   /* caller's transform is adjusted for subpixel positioning */
   static void
 
     FT_Bool  needExtraSetup = FALSE;
 
+    CFF_VStoreRec*  vstore;
+    FT_Bool         hasVariations = FALSE;
+
     /* character space units */
     CF2_Fixed  boldenX = font->syntheticEmboldeningAmountX;
     CF2_Fixed  boldenY = font->syntheticEmboldeningAmountY;
     CFF_SubFont  subFont;
     CF2_Fixed    ppem;
 
+    CF2_UInt   lenNormalizedV = 0;
+    FT_Fixed*  normalizedV    = NULL;
+
 
     /* clear previous error */
     font->error = FT_Err_Ok;
       needExtraSetup    = TRUE;
     }
 
+    /* check for variation vectors */
+    vstore        = cf2_getVStore( decoder );
+    hasVariations = ( vstore->dataCount != 0 );
+
+    if ( hasVariations )
+    {
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+      /* check whether Private DICT in this subfont needs to be reparsed */
+      font->error = cf2_getNormalizedVector( decoder,
+                                             &lenNormalizedV,
+                                             &normalizedV );
+      if ( font->error )
+        return;
+
+      if ( cff_blend_check_vector( &subFont->blend,
+                                   subFont->private_dict.vsindex,
+                                   lenNormalizedV,
+                                   normalizedV ) )
+      {
+        /* blend has changed, reparse */
+        cff_load_private_dict( decoder->cff,
+                               subFont,
+                               lenNormalizedV,
+                               normalizedV );
+        needExtraSetup = TRUE;
+      }
+#endif
+
+      /* copy from subfont */
+      font->blend.font = subFont->blend.font;
+
+      /* clear state of charstring blend */
+      font->blend.usedBV = FALSE;
+
+      /* initialize value for charstring */
+      font->vsindex = subFont->private_dict.vsindex;
+
+      /* store vector inputs for blends in charstring */
+      font->lenNDV = lenNormalizedV;
+      font->NDV    = normalizedV;
+    }
+
     /* if ppem has changed, we need to recompute some cached data         */
     /* note: because of CID font matrix concatenation, ppem and transform */
     /*       do not necessarily track.                                    */
 
       /* compute blue zones for this instance */
       cf2_blues_init( &font->blues, font );
-    }
+
+    } /* needExtraSetup */
   }
 
 
index bd05e69..17ecd17 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "cf2ft.h"
 #include "cf2blues.h"
+#include "cffload.h"
 
 
 FT_BEGIN_HEADER
@@ -63,6 +64,7 @@ FT_BEGIN_HEADER
     FT_Memory  memory;
     FT_Error   error;     /* shared error for this instance */
 
+    FT_Bool             isCFF2;
     CF2_RenderingFlags  renderingFlags;
 
     /* variables that depend on Transform:  */
@@ -74,6 +76,12 @@ FT_BEGIN_HEADER
     CF2_Matrix  outerTransform;    /* post hinting; includes rotations */
     CF2_Fixed   ppem;              /* transform-dependent              */
 
+    /* variation data */
+    CFF_BlendRec  blend;            /* cached charstring blend vector  */
+    CF2_UInt      vsindex;          /* current vsindex                 */
+    CF2_UInt      lenNDV;           /* current length NDV or zero      */
+    FT_Fixed*     NDV;              /* ptr to current NDV or NULL      */
+
     CF2_Int  unitsPerEm;
 
     CF2_Fixed  syntheticEmboldeningAmountX;   /* character space units */
index 55f3206..c0d067e 100644 (file)
       FT_Memory  memory = font->memory;
 
 
-      (void)memory;
+      FT_FREE( font->blend.lastNDV );
+      FT_FREE( font->blend.BV );
     }
   }
 
                     FT_Memory    memory,
                     FT_Error*    error )
   {
-    FT_MEM_ZERO( outline, sizeof ( CF2_OutlineRec ) );
+    FT_ZERO( outline );
 
     outline->root.memory = memory;
     outline->root.error  = error;
     font = (CF2_Font)decoder->cff->cf2_instance.data;
 
     /* on first glyph, allocate instance structure */
-    if ( decoder->cff->cf2_instance.data == NULL )
+    if ( !decoder->cff->cf2_instance.data )
     {
       decoder->cff->cf2_instance.finalizer =
         (FT_Generic_Finalizer)cf2_free_instance;
                                &hinted,
                                &scaled );
 
+      /* copy isCFF2 boolean from TT_Face to CF2_Font */
+      font->isCFF2 = builder->face->isCFF2;
+
       font->renderingFlags = 0;
       if ( hinted )
         font->renderingFlags |= CF2_FlagsHinted;
   }
 
 
+  /* get pointer to VStore structure */
+  FT_LOCAL_DEF( CFF_VStore )
+  cf2_getVStore( CFF_Decoder*  decoder )
+  {
+    FT_ASSERT( decoder && decoder->cff );
+
+    return &decoder->cff->vstore;
+  }
+
+
+  /* get maxstack value from CFF2 Top DICT */
+  FT_LOCAL_DEF( FT_UInt )
+  cf2_getMaxstack( CFF_Decoder*  decoder )
+  {
+    FT_ASSERT( decoder && decoder->cff );
+
+    return decoder->cff->top_font.font_dict.maxstack;
+  }
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+  /* Get normalized design vector for current render request; */
+  /* return pointer and length.                               */
+  /*                                                          */
+  /* Note: Uses FT_Fixed not CF2_Fixed for the vector.        */
+  FT_LOCAL_DEF( FT_Error )
+  cf2_getNormalizedVector( CFF_Decoder*  decoder,
+                           CF2_UInt     *len,
+                           FT_Fixed*    *vec )
+  {
+    FT_ASSERT( decoder && decoder->builder.face );
+    FT_ASSERT( vec && len );
+
+    return cff_get_var_blend( decoder->builder.face, len, vec, NULL );
+  }
+#endif
+
+
   /* get `y_ppem' from `CFF_Size' */
   FT_LOCAL_DEF( CF2_Fixed )
   cf2_getPpemY( CFF_Decoder*  decoder )
index 8e55e84..b054a6e 100644 (file)
@@ -64,6 +64,18 @@ FT_BEGIN_HEADER
   FT_LOCAL( CFF_SubFont )
   cf2_getSubfont( CFF_Decoder*  decoder );
 
+  FT_LOCAL( CFF_VStore )
+  cf2_getVStore( CFF_Decoder*  decoder );
+
+  FT_LOCAL( FT_UInt )
+  cf2_getMaxstack( CFF_Decoder*  decoder );
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+  FT_LOCAL( FT_Error )
+  cf2_getNormalizedVector( CFF_Decoder*  decoder,
+                           CF2_UInt     *len,
+                           FT_Fixed*    *vec );
+#endif
 
   FT_LOCAL( CF2_Fixed )
   cf2_getPpemY( CFF_Decoder*  decoder );
index bbbe8e3..c8f7dfe 100644 (file)
         /* calculate all four possibilities; moves down are negative */
         CF2_Fixed  downMoveDown = 0 - fracDown;
         CF2_Fixed  upMoveDown   = 0 - fracUp;
-        CF2_Fixed  downMoveUp   = fracDown == 0
+        CF2_Fixed  downMoveUp   = ( fracDown == 0 )
                                     ? 0
                                     : cf2_intToFixed( 1 ) - fracDown;
-        CF2_Fixed  upMoveUp     = fracUp == 0
+        CF2_Fixed  upMoveUp     = ( fracUp == 0 )
                                     ? 0
                                     : cf2_intToFixed( 1 ) - fracUp;
 
index 77bb896..bd3a566 100644 (file)
@@ -47,6 +47,8 @@
 
 #include "cf2error.h"
 
+#include "cffload.h"
+
 
   /*************************************************************************/
   /*                                                                       */
     cf2_cmdESC,          /* 12 */
     cf2_cmdRESERVED_13,  /* 13 */
     cf2_cmdENDCHAR,      /* 14 */
-    cf2_cmdRESERVED_15,  /* 15 */
-    cf2_cmdRESERVED_16,  /* 16 */
+    cf2_cmdVSINDEX,      /* 15 */
+    cf2_cmdBLEND,        /* 16 */
     cf2_cmdRESERVED_17,  /* 17 */
     cf2_cmdHSTEMHM,      /* 18 */
     cf2_cmdHINTMASK,     /* 19 */
     cf2_escHFLEX,        /* 34 */
     cf2_escFLEX,         /* 35 */
     cf2_escHFLEX1,       /* 36 */
-    cf2_escFLEX1         /* 37 */
+    cf2_escFLEX1,        /* 37 */
+    cf2_escRESERVED_38   /* 38     & all higher     */
   };
 
 
     vals[0] = *curX;
     vals[1] = *curY;
     index   = 0;
-    isHFlex = readFromStack[9] == FALSE;
+    isHFlex = FT_BOOL( readFromStack[9] == FALSE );
     top     = isHFlex ? 9 : 10;
 
     for ( i = 0; i < top; i++ )
   }
 
 
+  /* Blend numOperands on the stack,                */
+  /* store results into the first numBlends values, */
+  /* then pop remaining arguments.                  */
+  static void
+  cf2_doBlend( const CFF_Blend  blend,
+               CF2_Stack        opStack,
+               CF2_UInt         numBlends )
+  {
+    CF2_UInt  delta;
+    CF2_UInt  base;
+    CF2_UInt  i, j;
+    CF2_UInt  numOperands = (CF2_UInt)( numBlends * blend->lenBV );
+
+
+    base  = cf2_stack_count( opStack ) - numOperands;
+    delta = base + numBlends;
+
+    for ( i = 0; i < numBlends; i++ )
+    {
+      const CF2_Fixed*  weight = &blend->BV[1];
+
+      /* start with first term */
+      CF2_Fixed  sum = cf2_stack_getReal( opStack, i + base );
+
+
+      for ( j = 1; j < blend->lenBV; j++ )
+        sum += FT_MulFix( *weight++, cf2_stack_getReal( opStack, delta++ ) );
+
+      /* store blended result  */
+      cf2_stack_setReal( opStack, i + base, sum );
+    }
+
+    /* leave only `numBlends' results on stack */
+    cf2_stack_pop( opStack, numOperands - numBlends );
+  }
+
+
   /*
    * `error' is a shared error code used by many objects in this
    * routine.  Before the code continues from an error, it must check and
     CF2_Fixed  hintOriginY = curY;
 
     CF2_Stack  opStack = NULL;
+    FT_UInt    stackSize;
     FT_Byte    op1;                       /* first opcode byte */
 
     CF2_F16Dot16  storage[CF2_STORAGE_SIZE];    /* for `put' and `get' */
      * If one of the above operators occurs without explicitly specifying
      * a width, we assume the default width.
      *
+     * CFF2 charstrings always return the default width (0).
+     *
      */
-    haveWidth = FALSE;
+    haveWidth = font->isCFF2 ? TRUE : FALSE;
     *width    = cf2_getDefaultWidthX( decoder );
 
     /*
-     * Note: at this point, all pointers to resources must be NULL
-     * and all local objects must be initialized.
-     * There must be no branches to exit: above this point.
+     * Note: At this point, all pointers to resources must be NULL
+     *       and all local objects must be initialized.
+     *       There must be no branches to `exit:' above this point.
      *
      */
 
     /* allocate an operand stack */
-    opStack = cf2_stack_init( memory, error );
+    stackSize = font->isCFF2 ? cf2_getMaxstack( decoder )
+                             : CF2_OPERAND_STACK_SIZE;
+    opStack   = cf2_stack_init( memory, error, stackSize );
+
     if ( !opStack )
     {
       lastError = FT_THROW( Out_Of_Memory );
       {
         /* If we've reached the end of the charstring, simulate a */
         /* cf2_cmdRETURN or cf2_cmdENDCHAR.                       */
+        /* We do this for both CFF and CFF2.                      */
         if ( charstringIndex )
           op1 = cf2_cmdRETURN;  /* end of buffer for subroutine */
         else
           op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
       }
       else
+      {
         op1 = (FT_Byte)cf2_buf_readByte( charstring );
 
+        /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */
+        /* Note: Trace message will report 0 instead of 11 or 14. */
+        if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) &&
+             font->isCFF2                                      )
+          op1 = cf2_cmdRESERVED_0;
+      }
+
       /* check for errors once per loop */
       if ( *error )
         goto exit;
       case cf2_cmdRESERVED_2:
       case cf2_cmdRESERVED_9:
       case cf2_cmdRESERVED_13:
-      case cf2_cmdRESERVED_15:
-      case cf2_cmdRESERVED_16:
       case cf2_cmdRESERVED_17:
         /* we may get here if we have a prior error */
         FT_TRACE4(( " unknown op (%d)\n", op1 ));
         break;
 
+      case cf2_cmdVSINDEX:
+        FT_TRACE4(( " vsindex\n" ));
+
+        if ( !font->isCFF2 )
+          break;    /* clear stack & ignore */
+
+        if ( font->blend.usedBV )
+        {
+          /* vsindex not allowed after blend */
+          lastError = FT_THROW( Invalid_Glyph_Format );
+          goto exit;
+        }
+
+        {
+          FT_Int  temp = cf2_stack_popInt( opStack );
+
+
+          if ( temp >= 0 )
+            font->vsindex = (FT_UInt)temp;
+        }
+        break;
+
+      case cf2_cmdBLEND:
+        {
+          FT_UInt  numBlends;
+
+
+          FT_TRACE4(( " blend\n" ));
+
+          if ( !font->isCFF2 )
+            break;    /* clear stack & ignore */
+
+          /* do we have a `blend' op in a non-variant font? */
+          if ( !font->blend.font )
+          {
+            lastError = FT_THROW( Invalid_Glyph_Format );
+            goto exit;
+          }
+
+          /* check cached blend vector */
+          if ( cff_blend_check_vector( &font->blend,
+                                       font->vsindex,
+                                       font->lenNDV,
+                                       font->NDV ) )
+          {
+            lastError = cff_blend_build_vector( &font->blend,
+                                                font->vsindex,
+                                                font->lenNDV,
+                                                font->NDV );
+            if ( lastError )
+              goto exit;
+          }
+
+          /* do the blend */
+          numBlends = (FT_UInt)cf2_stack_popInt( opStack );
+          if ( numBlends > stackSize )
+          {
+            lastError = FT_THROW( Invalid_Glyph_Format );
+            goto exit;
+          }
+
+          cf2_doBlend( &font->blend, opStack, numBlends );
+
+          font->blend.usedBV = TRUE;
+        }
+        continue;     /* do not clear the stack */
+
       case cf2_cmdHSTEMHM:
       case cf2_cmdHSTEM:
         FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
           CF2_UInt  index;
           CF2_UInt  count = cf2_stack_count( opStack );
 
-          FT_Bool  isX = op1 == cf2_cmdHLINETO;
+          FT_Bool  isX = FT_BOOL( op1 == cf2_cmdHLINETO );
 
 
           FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
           FT_Byte  op2 = (FT_Byte)cf2_buf_readByte( charstring );
 
 
+          /* first switch for 2-byte operators handles CFF2      */
+          /* and opcodes that are reserved for both CFF and CFF2 */
           switch ( op2 )
           {
-          case cf2_escDOTSECTION:
-            /* something about `flip type of locking' -- ignore it */
-            FT_TRACE4(( " dotsection\n" ));
+          case cf2_escHFLEX:
+            {
+              static const FT_Bool  readFromStack[12] =
+              {
+                TRUE /* dx1 */, FALSE /* dy1 */,
+                TRUE /* dx2 */, TRUE  /* dy2 */,
+                TRUE /* dx3 */, FALSE /* dy3 */,
+                TRUE /* dx4 */, FALSE /* dy4 */,
+                TRUE /* dx5 */, FALSE /* dy5 */,
+                TRUE /* dx6 */, FALSE /* dy6 */
+              };
 
-            break;
 
-          case cf2_escAND:
-            {
-              CF2_F16Dot16  arg1;
-              CF2_F16Dot16  arg2;
+              FT_TRACE4(( " hflex\n" ));
+
+              cf2_doFlex( opStack,
+                          &curX,
+                          &curY,
+                          &glyphPath,
+                          readFromStack,
+                          FALSE /* doConditionalLastRead */ );
+            }
+            continue;
 
+          case cf2_escFLEX:
+            {
+              static const FT_Bool  readFromStack[12] =
+              {
+                TRUE /* dx1 */, TRUE /* dy1 */,
+                TRUE /* dx2 */, TRUE /* dy2 */,
+                TRUE /* dx3 */, TRUE /* dy3 */,
+                TRUE /* dx4 */, TRUE /* dy4 */,
+                TRUE /* dx5 */, TRUE /* dy5 */,
+                TRUE /* dx6 */, TRUE /* dy6 */
+              };
 
-              FT_TRACE4(( " and\n" ));
 
-              arg2 = cf2_stack_popFixed( opStack );
-              arg1 = cf2_stack_popFixed( opStack );
+              FT_TRACE4(( " flex\n" ));
 
-              cf2_stack_pushInt( opStack, arg1 && arg2 );
+              cf2_doFlex( opStack,
+                          &curX,
+                          &curY,
+                          &glyphPath,
+                          readFromStack,
+                          FALSE /* doConditionalLastRead */ );
             }
-            continue; /* do not clear the stack */
+            break;      /* TODO: why is this not a continue? */
 
-          case cf2_escOR:
+          case cf2_escHFLEX1:
             {
-              CF2_F16Dot16  arg1;
-              CF2_F16Dot16  arg2;
-
+              static const FT_Bool  readFromStack[12] =
+              {
+                TRUE /* dx1 */, TRUE  /* dy1 */,
+                TRUE /* dx2 */, TRUE  /* dy2 */,
+                TRUE /* dx3 */, FALSE /* dy3 */,
+                TRUE /* dx4 */, FALSE /* dy4 */,
+                TRUE /* dx5 */, TRUE  /* dy5 */,
+                TRUE /* dx6 */, FALSE /* dy6 */
+              };
 
-              FT_TRACE4(( " or\n" ));
 
-              arg2 = cf2_stack_popFixed( opStack );
-              arg1 = cf2_stack_popFixed( opStack );
+              FT_TRACE4(( " hflex1\n" ));
 
-              cf2_stack_pushInt( opStack, arg1 || arg2 );
+              cf2_doFlex( opStack,
+                          &curX,
+                          &curY,
+                          &glyphPath,
+                          readFromStack,
+                          FALSE /* doConditionalLastRead */ );
             }
-            continue; /* do not clear the stack */
+            continue;
 
-          case cf2_escNOT:
+          case cf2_escFLEX1:
             {
-              CF2_F16Dot16  arg;
-
+              static const FT_Bool  readFromStack[12] =
+              {
+                TRUE  /* dx1 */, TRUE  /* dy1 */,
+                TRUE  /* dx2 */, TRUE  /* dy2 */,
+                TRUE  /* dx3 */, TRUE  /* dy3 */,
+                TRUE  /* dx4 */, TRUE  /* dy4 */,
+                TRUE  /* dx5 */, TRUE  /* dy5 */,
+                FALSE /* dx6 */, FALSE /* dy6 */
+              };
 
-              FT_TRACE4(( " not\n" ));
 
-              arg = cf2_stack_popFixed( opStack );
+              FT_TRACE4(( " flex1\n" ));
 
-              cf2_stack_pushInt( opStack, !arg );
+              cf2_doFlex( opStack,
+                          &curX,
+                          &curY,
+                          &glyphPath,
+                          readFromStack,
+                          TRUE /* doConditionalLastRead */ );
             }
-            continue; /* do not clear the stack */
+            continue;
+
+          /* these opcodes are reserved in both CFF & CFF2 */
+          case cf2_escRESERVED_1:
+          case cf2_escRESERVED_2:
+          case cf2_escRESERVED_6:
+          case cf2_escRESERVED_7:
+          case cf2_escRESERVED_8:
+          case cf2_escRESERVED_13:
+          case cf2_escRESERVED_16:
+          case cf2_escRESERVED_17:
+          case cf2_escRESERVED_19:
+          case cf2_escRESERVED_25:
+          case cf2_escRESERVED_31:
+          case cf2_escRESERVED_32:
+          case cf2_escRESERVED_33:
+            FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+            break;
 
-          case cf2_escABS:
+          default:
             {
-              CF2_F16Dot16  arg;
+              if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 )
+                FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+              else
+              {
+                /* second switch for 2-byte operators handles just CFF */
+                switch ( op2 )
+                {
 
+                case cf2_escDOTSECTION:
+                  /* something about `flip type of locking' -- ignore it */
+                  FT_TRACE4(( " dotsection\n" ));
 
-              FT_TRACE4(( " abs\n" ));
+                  break;
 
-              arg = cf2_stack_popFixed( opStack );
+                case cf2_escAND:
+                  {
+                    CF2_F16Dot16  arg1;
+                    CF2_F16Dot16  arg2;
 
-              cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
-            }
-            continue; /* do not clear the stack */
 
-          case cf2_escADD:
-            {
-              CF2_F16Dot16  summand1;
-              CF2_F16Dot16  summand2;
+                    FT_TRACE4(( " and\n" ));
 
+                    arg2 = cf2_stack_popFixed( opStack );
+                    arg1 = cf2_stack_popFixed( opStack );
 
-              FT_TRACE4(( " add\n" ));
+                    cf2_stack_pushInt( opStack, arg1 && arg2 );
+                  }
+                  continue; /* do not clear the stack */
 
-              summand2 = cf2_stack_popFixed( opStack );
-              summand1 = cf2_stack_popFixed( opStack );
+                case cf2_escOR:
+                  {
+                    CF2_F16Dot16  arg1;
+                    CF2_F16Dot16  arg2;
 
-              cf2_stack_pushFixed( opStack, summand1 + summand2 );
-            }
-            continue; /* do not clear the stack */
 
-          case cf2_escSUB:
-            {
-              CF2_F16Dot16  minuend;
-              CF2_F16Dot16  subtrahend;
+                    FT_TRACE4(( " or\n" ));
 
+                    arg2 = cf2_stack_popFixed( opStack );
+                    arg1 = cf2_stack_popFixed( opStack );
 
-              FT_TRACE4(( " sub\n" ));
+                    cf2_stack_pushInt( opStack, arg1 || arg2 );
+                  }
+                  continue; /* do not clear the stack */
 
-              subtrahend = cf2_stack_popFixed( opStack );
-              minuend    = cf2_stack_popFixed( opStack );
+                case cf2_escNOT:
+                  {
+                    CF2_F16Dot16  arg;
 
-              cf2_stack_pushFixed( opStack, minuend - subtrahend );
-            }
-            continue; /* do not clear the stack */
 
-          case cf2_escDIV:
-            {
-              CF2_F16Dot16  dividend;
-              CF2_F16Dot16  divisor;
+                    FT_TRACE4(( " not\n" ));
 
+                    arg = cf2_stack_popFixed( opStack );
 
-              FT_TRACE4(( " div\n" ));
+                    cf2_stack_pushInt( opStack, !arg );
+                  }
+                  continue; /* do not clear the stack */
 
-              divisor  = cf2_stack_popFixed( opStack );
-              dividend = cf2_stack_popFixed( opStack );
+                case cf2_escABS:
+                  {
+                    CF2_F16Dot16  arg;
 
-              cf2_stack_pushFixed( opStack, FT_DivFix( dividend, divisor ) );
-            }
-            continue; /* do not clear the stack */
 
-          case cf2_escNEG:
-            {
-              CF2_F16Dot16  arg;
+                    FT_TRACE4(( " abs\n" ));
 
+                    arg = cf2_stack_popFixed( opStack );
 
-              FT_TRACE4(( " neg\n" ));
+                    cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
+                  }
+                  continue; /* do not clear the stack */
 
-              arg = cf2_stack_popFixed( opStack );
+                case cf2_escADD:
+                  {
+                    CF2_F16Dot16  summand1;
+                    CF2_F16Dot16  summand2;
 
-              cf2_stack_pushFixed( opStack, -arg );
-            }
-            continue; /* do not clear the stack */
 
-          case cf2_escEQ:
-            {
-              CF2_F16Dot16  arg1;
-              CF2_F16Dot16  arg2;
+                    FT_TRACE4(( " add\n" ));
 
+                    summand2 = cf2_stack_popFixed( opStack );
+                    summand1 = cf2_stack_popFixed( opStack );
 
-              FT_TRACE4(( " eq\n" ));
+                    cf2_stack_pushFixed( opStack, summand1 + summand2 );
+                  }
+                  continue; /* do not clear the stack */
 
-              arg2 = cf2_stack_popFixed( opStack );
-              arg1 = cf2_stack_popFixed( opStack );
+                case cf2_escSUB:
+                  {
+                    CF2_F16Dot16  minuend;
+                    CF2_F16Dot16  subtrahend;
 
-              cf2_stack_pushInt( opStack, arg1 == arg2 );
-            }
-            continue; /* do not clear the stack */
 
-          case cf2_escDROP:
-            FT_TRACE4(( " drop\n" ));
+                    FT_TRACE4(( " sub\n" ));
 
-            (void)cf2_stack_popFixed( opStack );
-            continue; /* do not clear the stack */
+                    subtrahend = cf2_stack_popFixed( opStack );
+                    minuend    = cf2_stack_popFixed( opStack );
 
-          case cf2_escPUT:
-            {
-              CF2_F16Dot16  val;
-              CF2_Int       idx;
+                    cf2_stack_pushFixed( opStack, minuend - subtrahend );
+                  }
+                  continue; /* do not clear the stack */
 
+                case cf2_escDIV:
+                  {
+                    CF2_F16Dot16  dividend;
+                    CF2_F16Dot16  divisor;
 
-              FT_TRACE4(( " put\n" ));
 
-              idx = cf2_stack_popInt( opStack );
-              val = cf2_stack_popFixed( opStack );
+                    FT_TRACE4(( " div\n" ));
 
-              if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
-                storage[idx] = val;
-            }
-            continue; /* do not clear the stack */
+                    divisor  = cf2_stack_popFixed( opStack );
+                    dividend = cf2_stack_popFixed( opStack );
 
-          case cf2_escGET:
-            {
-              CF2_Int  idx;
+                    cf2_stack_pushFixed( opStack, FT_DivFix( dividend, divisor ) );
+                  }
+                  continue; /* do not clear the stack */
 
+                case cf2_escNEG:
+                  {
+                    CF2_F16Dot16  arg;
 
-              FT_TRACE4(( " get\n" ));
 
-              idx = cf2_stack_popInt( opStack );
+                    FT_TRACE4(( " neg\n" ));
 
-              if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
-                cf2_stack_pushFixed( opStack, storage[idx] );
-            }
-            continue; /* do not clear the stack */
+                    arg = cf2_stack_popFixed( opStack );
 
-          case cf2_escIFELSE:
-            {
-              CF2_F16Dot16  arg1;
-              CF2_F16Dot16  arg2;
-              CF2_F16Dot16  cond1;
-              CF2_F16Dot16  cond2;
+                    cf2_stack_pushFixed( opStack, -arg );
+                  }
+                  continue; /* do not clear the stack */
 
+                case cf2_escEQ:
+                  {
+                    CF2_F16Dot16  arg1;
+                    CF2_F16Dot16  arg2;
 
-              FT_TRACE4(( " ifelse\n" ));
 
-              cond2 = cf2_stack_popFixed( opStack );
-              cond1 = cf2_stack_popFixed( opStack );
-              arg2  = cf2_stack_popFixed( opStack );
-              arg1  = cf2_stack_popFixed( opStack );
+                    FT_TRACE4(( " eq\n" ));
 
-              cf2_stack_pushFixed( opStack, cond1 <= cond2 ? arg1 : arg2 );
-            }
-            continue; /* do not clear the stack */
+                    arg2 = cf2_stack_popFixed( opStack );
+                    arg1 = cf2_stack_popFixed( opStack );
 
-          case cf2_escRANDOM: /* in spec */
-            FT_TRACE4(( " random\n" ));
+                    cf2_stack_pushInt( opStack, arg1 == arg2 );
+                  }
+                  continue; /* do not clear the stack */
 
-            CF2_FIXME;
-            break;
+                case cf2_escDROP:
+                  FT_TRACE4(( " drop\n" ));
 
-          case cf2_escMUL:
-            {
-              CF2_F16Dot16  factor1;
-              CF2_F16Dot16  factor2;
+                  (void)cf2_stack_popFixed( opStack );
+                  continue; /* do not clear the stack */
 
+                case cf2_escPUT:
+                  {
+                    CF2_F16Dot16  val;
+                    CF2_Int       idx;
 
-              FT_TRACE4(( " mul\n" ));
 
-              factor2 = cf2_stack_popFixed( opStack );
-              factor1 = cf2_stack_popFixed( opStack );
+                    FT_TRACE4(( " put\n" ));
 
-              cf2_stack_pushFixed( opStack, FT_MulFix( factor1, factor2 ) );
-            }
-            continue; /* do not clear the stack */
+                    idx = cf2_stack_popInt( opStack );
+                    val = cf2_stack_popFixed( opStack );
 
-          case cf2_escSQRT:
-            {
-              CF2_F16Dot16  arg;
+                    if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
+                      storage[idx] = val;
+                  }
+                  continue; /* do not clear the stack */
 
+                case cf2_escGET:
+                  {
+                    CF2_Int  idx;
 
-              FT_TRACE4(( " sqrt\n" ));
 
-              arg = cf2_stack_popFixed( opStack );
-              if ( arg > 0 )
-              {
-                FT_Fixed  root = arg;
-                FT_Fixed  new_root;
+                    FT_TRACE4(( " get\n" ));
 
+                    idx = cf2_stack_popInt( opStack );
 
-                /* Babylonian method */
-                for (;;)
-                {
-                  new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
-                  if ( new_root == root )
-                    break;
-                  root = new_root;
-                }
-                arg = new_root;
-              }
-              else
-                arg = 0;
+                    if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
+                      cf2_stack_pushFixed( opStack, storage[idx] );
+                  }
+                  continue; /* do not clear the stack */
 
-              cf2_stack_pushFixed( opStack, arg );
-            }
-            continue; /* do not clear the stack */
+                case cf2_escIFELSE:
+                  {
+                    CF2_F16Dot16  arg1;
+                    CF2_F16Dot16  arg2;
+                    CF2_F16Dot16  cond1;
+                    CF2_F16Dot16  cond2;
 
-          case cf2_escDUP:
-            {
-              CF2_F16Dot16  arg;
 
+                    FT_TRACE4(( " ifelse\n" ));
 
-              FT_TRACE4(( " dup\n" ));
+                    cond2 = cf2_stack_popFixed( opStack );
+                    cond1 = cf2_stack_popFixed( opStack );
+                    arg2  = cf2_stack_popFixed( opStack );
+                    arg1  = cf2_stack_popFixed( opStack );
 
-              arg = cf2_stack_popFixed( opStack );
+                    cf2_stack_pushFixed( opStack, cond1 <= cond2 ? arg1 : arg2 );
+                  }
+                  continue; /* do not clear the stack */
 
-              cf2_stack_pushFixed( opStack, arg );
-              cf2_stack_pushFixed( opStack, arg );
-            }
-            continue; /* do not clear the stack */
+                case cf2_escRANDOM: /* in spec */
+                  FT_TRACE4(( " random\n" ));
 
-          case cf2_escEXCH:
-            {
-              CF2_F16Dot16  arg1;
-              CF2_F16Dot16  arg2;
+                  CF2_FIXME;
+                  break;
 
+                case cf2_escMUL:
+                  {
+                    CF2_F16Dot16  factor1;
+                    CF2_F16Dot16  factor2;
 
-              FT_TRACE4(( " exch\n" ));
 
-              arg2 = cf2_stack_popFixed( opStack );
-              arg1 = cf2_stack_popFixed( opStack );
+                    FT_TRACE4(( " mul\n" ));
 
-              cf2_stack_pushFixed( opStack, arg2 );
-              cf2_stack_pushFixed( opStack, arg1 );
-            }
-            continue; /* do not clear the stack */
+                    factor2 = cf2_stack_popFixed( opStack );
+                    factor1 = cf2_stack_popFixed( opStack );
 
-          case cf2_escINDEX:
-            {
-              CF2_Int   idx;
-              CF2_UInt  size;
+                    cf2_stack_pushFixed( opStack, FT_MulFix( factor1, factor2 ) );
+                  }
+                  continue; /* do not clear the stack */
 
+                case cf2_escSQRT:
+                  {
+                    CF2_F16Dot16  arg;
 
-              FT_TRACE4(( " index\n" ));
 
-              idx  = cf2_stack_popInt( opStack );
-              size = cf2_stack_count( opStack );
+                    FT_TRACE4(( " sqrt\n" ));
 
-              if ( size > 0 )
-              {
-                /* for `cf2_stack_getReal', index 0 is bottom of stack */
-                CF2_UInt  gr_idx;
+                    arg = cf2_stack_popFixed( opStack );
+                    if ( arg > 0 )
+                    {
+                      FT_Fixed  root = arg;
+                      FT_Fixed  new_root;
 
 
-                if ( idx < 0 )
-                  gr_idx = size - 1;
-                else if ( (CF2_UInt)idx >= size )
-                  gr_idx = 0;
-                else
-                  gr_idx = size - 1 - (CF2_UInt)idx;
+                      /* Babylonian method */
+                      for (;;)
+                      {
+                        new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
+                        if ( new_root == root )
+                          break;
+                        root = new_root;
+                      }
+                      arg = new_root;
+                    }
+                    else
+                      arg = 0;
 
-                cf2_stack_pushFixed( opStack,
-                                     cf2_stack_getReal( opStack, gr_idx ) );
-              }
-            }
-            continue; /* do not clear the stack */
+                    cf2_stack_pushFixed( opStack, arg );
+                  }
+                  continue; /* do not clear the stack */
 
-          case cf2_escROLL:
-            {
-              CF2_Int  idx;
-              CF2_Int  count;
+                case cf2_escDUP:
+                  {
+                    CF2_F16Dot16  arg;
 
 
-              FT_TRACE4(( " roll\n" ));
+                    FT_TRACE4(( " dup\n" ));
 
-              idx   = cf2_stack_popInt( opStack );
-              count = cf2_stack_popInt( opStack );
+                    arg = cf2_stack_popFixed( opStack );
 
-              cf2_stack_roll( opStack, count, idx );
-            }
-            continue; /* do not clear the stack */
+                    cf2_stack_pushFixed( opStack, arg );
+                    cf2_stack_pushFixed( opStack, arg );
+                  }
+                  continue; /* do not clear the stack */
 
-          case cf2_escHFLEX:
-            {
-              static const FT_Bool  readFromStack[12] =
-              {
-                TRUE /* dx1 */, FALSE /* dy1 */,
-                TRUE /* dx2 */, TRUE  /* dy2 */,
-                TRUE /* dx3 */, FALSE /* dy3 */,
-                TRUE /* dx4 */, FALSE /* dy4 */,
-                TRUE /* dx5 */, FALSE /* dy5 */,
-                TRUE /* dx6 */, FALSE /* dy6 */
-              };
+                case cf2_escEXCH:
+                  {
+                    CF2_F16Dot16  arg1;
+                    CF2_F16Dot16  arg2;
 
 
-              FT_TRACE4(( " hflex\n" ));
+                    FT_TRACE4(( " exch\n" ));
 
-              cf2_doFlex( opStack,
-                          &curX,
-                          &curY,
-                          &glyphPath,
-                          readFromStack,
-                          FALSE /* doConditionalLastRead */ );
-            }
-            continue;
+                    arg2 = cf2_stack_popFixed( opStack );
+                    arg1 = cf2_stack_popFixed( opStack );
 
-          case cf2_escFLEX:
-            {
-              static const FT_Bool  readFromStack[12] =
-              {
-                TRUE /* dx1 */, TRUE /* dy1 */,
-                TRUE /* dx2 */, TRUE /* dy2 */,
-                TRUE /* dx3 */, TRUE /* dy3 */,
-                TRUE /* dx4 */, TRUE /* dy4 */,
-                TRUE /* dx5 */, TRUE /* dy5 */,
-                TRUE /* dx6 */, TRUE /* dy6 */
-              };
+                    cf2_stack_pushFixed( opStack, arg2 );
+                    cf2_stack_pushFixed( opStack, arg1 );
+                  }
+                  continue; /* do not clear the stack */
 
+                case cf2_escINDEX:
+                  {
+                    CF2_Int   idx;
+                    CF2_UInt  size;
 
-              FT_TRACE4(( " flex\n" ));
 
-              cf2_doFlex( opStack,
-                          &curX,
-                          &curY,
-                          &glyphPath,
-                          readFromStack,
-                          FALSE /* doConditionalLastRead */ );
-            }
-            break;      /* TODO: why is this not a continue? */
+                    FT_TRACE4(( " index\n" ));
 
-          case cf2_escHFLEX1:
-            {
-              static const FT_Bool  readFromStack[12] =
-              {
-                TRUE /* dx1 */, TRUE  /* dy1 */,
-                TRUE /* dx2 */, TRUE  /* dy2 */,
-                TRUE /* dx3 */, FALSE /* dy3 */,
-                TRUE /* dx4 */, FALSE /* dy4 */,
-                TRUE /* dx5 */, TRUE  /* dy5 */,
-                TRUE /* dx6 */, FALSE /* dy6 */
-              };
+                    idx  = cf2_stack_popInt( opStack );
+                    size = cf2_stack_count( opStack );
 
+                    if ( size > 0 )
+                    {
+                      /* for `cf2_stack_getReal', index 0 is bottom of stack */
+                      CF2_UInt  gr_idx;
 
-              FT_TRACE4(( " hflex1\n" ));
 
-              cf2_doFlex( opStack,
-                          &curX,
-                          &curY,
-                          &glyphPath,
-                          readFromStack,
-                          FALSE /* doConditionalLastRead */ );
-            }
-            continue;
+                      if ( idx < 0 )
+                        gr_idx = size - 1;
+                      else if ( (CF2_UInt)idx >= size )
+                        gr_idx = 0;
+                      else
+                        gr_idx = size - 1 - (CF2_UInt)idx;
 
-          case cf2_escFLEX1:
-            {
-              static const FT_Bool  readFromStack[12] =
-              {
-                TRUE  /* dx1 */, TRUE  /* dy1 */,
-                TRUE  /* dx2 */, TRUE  /* dy2 */,
-                TRUE  /* dx3 */, TRUE  /* dy3 */,
-                TRUE  /* dx4 */, TRUE  /* dy4 */,
-                TRUE  /* dx5 */, TRUE  /* dy5 */,
-                FALSE /* dx6 */, FALSE /* dy6 */
-              };
+                      cf2_stack_pushFixed( opStack,
+                                           cf2_stack_getReal( opStack, gr_idx ) );
+                    }
+                  }
+                  continue; /* do not clear the stack */
 
+                case cf2_escROLL:
+                  {
+                    CF2_Int  idx;
+                    CF2_Int  count;
 
-              FT_TRACE4(( " flex1\n" ));
 
-              cf2_doFlex( opStack,
-                          &curX,
-                          &curY,
-                          &glyphPath,
-                          readFromStack,
-                          TRUE /* doConditionalLastRead */ );
-            }
-            continue;
+                    FT_TRACE4(( " roll\n" ));
 
-          case cf2_escRESERVED_1:
-          case cf2_escRESERVED_2:
-          case cf2_escRESERVED_6:
-          case cf2_escRESERVED_7:
-          case cf2_escRESERVED_8:
-          case cf2_escRESERVED_13:
-          case cf2_escRESERVED_16:
-          case cf2_escRESERVED_17:
-          case cf2_escRESERVED_19:
-          case cf2_escRESERVED_25:
-          case cf2_escRESERVED_31:
-          case cf2_escRESERVED_32:
-          case cf2_escRESERVED_33:
-          default:
-            FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+                    idx   = cf2_stack_popInt( opStack );
+                    count = cf2_stack_popInt( opStack );
 
-          }; /* end of switch statement checking `op2' */
+                    cf2_stack_roll( opStack, count, idx );
+                  }
+                  continue; /* do not clear the stack */
 
+                } /* end of 2nd switch checking op2 */
+              }
+            }
+          } /* end of 1st switch checking op2 */
         } /* case cf2_cmdESC */
+
         break;
 
       case cf2_cmdENDCHAR:
         /* close path if still open */
         cf2_glyphpath_closeOpenPath( &glyphPath );
 
-        if ( cf2_stack_count( opStack ) > 1 )
+        /* disable seac for CFF2 (charstring ending with args on stack) */
+        if ( !font->isCFF2 && cf2_stack_count( opStack ) > 1 )
         {
           /* must be either 4 or 5 --                       */
           /* this is a (deprecated) implied `seac' operator */
             {
               x1 = cf2_stack_getReal( opStack, index ) + curX;
 
-              ++index;
+              index++;
             }
             else
               x1 = curX;
             {
               y1 = cf2_stack_getReal( opStack, index ) + curY;
 
-              ++index;
+              index++;
             }
             else
               y1 = curY;
           CF2_UInt  count, count1 = cf2_stack_count( opStack );
           CF2_UInt  index = 0;
 
-          FT_Bool  alternate = op1 == cf2_cmdHVCURVETO;
+          FT_Bool  alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO );
 
 
           /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
               {
                 x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
 
-                ++index;
+                index++;
               }
               else
                 x3 = x2;
               {
                 y3 = cf2_stack_getReal( opStack, index + 4 ) + y2;
 
-                ++index;
+                index++;
               }
               else
                 y3 = y2;
                              ( byte3 <<  8 ) |
                                byte4         );
 
-            FT_TRACE4(( " %.2f", v / 65536.0 ));
+            FT_TRACE4(( " %.5f", v / 65536.0 ));
 
             cf2_stack_pushFixed( opStack, v );
           }
     /* check whether last error seen is also the first one */
     cf2_setError( error, lastError );
 
+    if ( *error )
+      FT_TRACE4(( "charstring error %d\n", *error ));
+
     /* free resources from objects we've used */
     cf2_glyphpath_finalize( &glyphPath );
     cf2_arrstack_finalize( &vStemHintArray );
index 8f3adb6..12a026d 100644 (file)
@@ -51,7 +51,8 @@
   /* `error').                                               */
   FT_LOCAL_DEF( CF2_Stack )
   cf2_stack_init( FT_Memory  memory,
-                  FT_Error*  e )
+                  FT_Error*  e,
+                  FT_UInt    stackSize )
   {
     FT_Error  error = FT_Err_Ok;     /* for FT_NEW */
 
       /* initialize the structure; FT_NEW zeroes it */
       stack->memory = memory;
       stack->error  = e;
-      stack->top    = &stack->buffer[0]; /* empty stack */
     }
 
+    /* allocate the stack buffer */
+    if ( FT_NEW_ARRAY( stack->buffer, stackSize ) )
+    {
+      FT_FREE( stack );
+      return NULL;
+    }
+
+    stack->stackSize = stackSize;
+    stack->top       = stack->buffer;     /* empty stack */
+
     return stack;
   }
 
@@ -77,6 +87,8 @@
     {
       FT_Memory  memory = stack->memory;
 
+      /* free the buffer */
+      FT_FREE( stack->buffer );
 
       /* free the main structure */
       FT_FREE( stack );
@@ -87,7 +99,7 @@
   FT_LOCAL_DEF( CF2_UInt )
   cf2_stack_count( CF2_Stack  stack )
   {
-    return (CF2_UInt)( stack->top - &stack->buffer[0] );
+    return (CF2_UInt)( stack->top - stack->buffer );
   }
 
 
   cf2_stack_pushInt( CF2_Stack  stack,
                      CF2_Int    val )
   {
-    if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] )
+    if ( stack->top == stack->buffer + stack->stackSize )
     {
       CF2_SET_ERROR( stack->error, Stack_Overflow );
       return;     /* stack overflow */
 
     stack->top->u.i  = val;
     stack->top->type = CF2_NumberInt;
-    ++stack->top;
+    stack->top++;
   }
 
 
   cf2_stack_pushFixed( CF2_Stack  stack,
                        CF2_Fixed  val )
   {
-    if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] )
+    if ( stack->top == stack->buffer + stack->stackSize )
     {
       CF2_SET_ERROR( stack->error, Stack_Overflow );
       return;     /* stack overflow */
 
     stack->top->u.r  = val;
     stack->top->type = CF2_NumberFixed;
-    ++stack->top;
+    stack->top++;
   }
 
 
   FT_LOCAL_DEF( CF2_Int )
   cf2_stack_popInt( CF2_Stack  stack )
   {
-    if ( stack->top == &stack->buffer[0] )
+    if ( stack->top == stack->buffer )
     {
       CF2_SET_ERROR( stack->error, Stack_Underflow );
       return 0;   /* underflow */
       return 0;   /* type mismatch */
     }
 
-    --stack->top;
+    stack->top--;
 
     return stack->top->u.i;
   }
   FT_LOCAL_DEF( CF2_Fixed )
   cf2_stack_popFixed( CF2_Stack  stack )
   {
-    if ( stack->top == &stack->buffer[0] )
+    if ( stack->top == stack->buffer )
     {
       CF2_SET_ERROR( stack->error, Stack_Underflow );
       return cf2_intToFixed( 0 );    /* underflow */
     }
 
-    --stack->top;
+    stack->top--;
 
     switch ( stack->top->type )
     {
   cf2_stack_getReal( CF2_Stack  stack,
                      CF2_UInt   idx )
   {
-    FT_ASSERT( cf2_stack_count( stack ) <= CF2_OPERAND_STACK_SIZE );
+    FT_ASSERT( cf2_stack_count( stack ) <= stack->stackSize );
 
     if ( idx >= cf2_stack_count( stack ) )
     {
   }
 
 
-  FT_LOCAL( void )
+  /* provide random access to stack */
+  FT_LOCAL_DEF( void )
+  cf2_stack_setReal( CF2_Stack  stack,
+                     CF2_UInt   idx,
+                     CF2_Fixed  val )
+  {
+    if ( idx > cf2_stack_count( stack ) )
+    {
+      CF2_SET_ERROR( stack->error, Stack_Overflow );
+      return;
+    }
+
+    stack->buffer[idx].u.r  = val;
+    stack->buffer[idx].type = CF2_NumberFixed;
+  }
+
+
+  /* discard (pop) num values from stack */
+  FT_LOCAL_DEF( void )
+  cf2_stack_pop( CF2_Stack  stack,
+                 CF2_UInt   num )
+  {
+    if ( num > cf2_stack_count( stack ) )
+    {
+      CF2_SET_ERROR( stack->error, Stack_Underflow );
+      return;
+    }
+    stack->top -= num;
+  }
+
+
+  FT_LOCAL_DEF( void )
   cf2_stack_roll( CF2_Stack  stack,
                   CF2_Int    count,
                   CF2_Int    shift )
   FT_LOCAL_DEF( void )
   cf2_stack_clear( CF2_Stack  stack )
   {
-    stack->top = &stack->buffer[0];
+    stack->top = stack->buffer;
   }
 
 
index e740a7a..ef08eef 100644 (file)
@@ -62,15 +62,17 @@ FT_BEGIN_HEADER
   {
     FT_Memory         memory;
     FT_Error*         error;
-    CF2_StackNumber   buffer[CF2_OPERAND_STACK_SIZE];
+    CF2_StackNumber*  buffer;
     CF2_StackNumber*  top;
+    FT_UInt           stackSize;
 
   } CF2_StackRec, *CF2_Stack;
 
 
   FT_LOCAL( CF2_Stack )
   cf2_stack_init( FT_Memory  memory,
-                  FT_Error*  error );
+                  FT_Error*  error,
+                  FT_UInt    stackSize );
   FT_LOCAL( void )
   cf2_stack_free( CF2_Stack  stack );
 
@@ -92,6 +94,14 @@ FT_BEGIN_HEADER
   FT_LOCAL( CF2_Fixed )
   cf2_stack_getReal( CF2_Stack  stack,
                      CF2_UInt   idx );
+  FT_LOCAL( void )
+  cf2_stack_setReal( CF2_Stack  stack,
+                     CF2_UInt   idx,
+                     CF2_Fixed  val );
+
+  FT_LOCAL( void )
+  cf2_stack_pop( CF2_Stack  stack,
+                 CF2_UInt   num );
 
   FT_LOCAL( void )
   cf2_stack_roll( CF2_Stack  stack,
index 3ef4832..695ba69 100644 (file)
   }
 
 
-  FT_DEFINE_CMAP_CLASS(cff_cmap_encoding_class_rec,
+  FT_DEFINE_CMAP_CLASS(
+    cff_cmap_encoding_class_rec,
+
     sizeof ( CFF_CMapStdRec ),
 
-    (FT_CMap_InitFunc)     cff_cmap_encoding_init,
-    (FT_CMap_DoneFunc)     cff_cmap_encoding_done,
-    (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index,
-    (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next,
+    (FT_CMap_InitFunc)     cff_cmap_encoding_init,        /* init       */
+    (FT_CMap_DoneFunc)     cff_cmap_encoding_done,        /* done       */
+    (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index,  /* char_index */
+    (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next,   /* char_next  */
 
-    NULL, NULL, NULL, NULL, NULL
+    (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+    (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+    (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+    (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+    (FT_CMap_VariantCharListFunc) NULL   /* variantchar_list */
   )
 
 
   }
 
 
-  FT_DEFINE_CMAP_CLASS(cff_cmap_unicode_class_rec,
+  FT_DEFINE_CMAP_CLASS(
+    cff_cmap_unicode_class_rec,
+
     sizeof ( PS_UnicodesRec ),
 
-    (FT_CMap_InitFunc)     cff_cmap_unicode_init,
-    (FT_CMap_DoneFunc)     cff_cmap_unicode_done,
-    (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index,
-    (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next,
+    (FT_CMap_InitFunc)     cff_cmap_unicode_init,        /* init       */
+    (FT_CMap_DoneFunc)     cff_cmap_unicode_done,        /* done       */
+    (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index,  /* char_index */
+    (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next,   /* char_next  */
 
-    NULL, NULL, NULL, NULL, NULL
+    (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+    (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+    (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+    (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+    (FT_CMap_VariantCharListFunc) NULL   /* variantchar_list */
   )
 
+
 /* END */
index 67bf09d..3182528 100644 (file)
 #include "cffcmap.h"
 #include "cffparse.h"
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include FT_SERVICE_MULTIPLE_MASTERS_H
+#endif
+
 #include "cfferrs.h"
 #include "cffpic.h"
 
 
       if ( flags & FT_LOAD_VERTICAL_LAYOUT )
       {
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+        /* no fast retrieval for blended MM fonts without VVAR table */
+        if ( !ttface->is_default_instance                               &&
+             !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+          return FT_THROW( Unimplemented_Feature );
+#endif
+
         /* check whether we have data from the `vmtx' table at all; */
         /* otherwise we extract the info from the CFF glyphstrings  */
         /* (instead of synthesizing a global value using the `OS/2' */
       }
       else
       {
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+        /* no fast retrieval for blended MM fonts without HVAR table */
+        if ( !ttface->is_default_instance                               &&
+             !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+          return FT_THROW( Unimplemented_Feature );
+#endif
+
         /* check whether we have data from the `hmtx' table at all */
         if ( !ttface->horizontal.number_Of_HMetrics )
           goto Missing_Table;
     FT_Error    error;
 
 
+    /* CFF2 table does not have glyph names; */
+    /* we need to use `post' table method    */
+    if ( font->version_major == 2 )
+    {
+      FT_Library            library     = FT_FACE_LIBRARY( face );
+      FT_Module             sfnt_module = FT_Get_Module( library, "sfnt" );
+      FT_Service_GlyphDict  service     =
+        (FT_Service_GlyphDict)ft_module_get_service(
+                                 sfnt_module,
+                                 FT_SERVICE_ID_GLYPH_DICT,
+                                 0 );
+
+
+      if ( service && service->get_name )
+        return service->get_name( FT_FACE( face ),
+                                  glyph_index,
+                                  buffer,
+                                  buffer_max );
+      else
+      {
+        FT_ERROR(( "cff_get_glyph_name:"
+                   " cannot get glyph name from a CFF2 font\n"
+                   "                   "
+                   " without the `PSNames' module\n" ));
+        error = FT_THROW( Missing_Module );
+        goto Exit;
+      }
+    }
+
     if ( !font->psnames )
     {
       FT_ERROR(( "cff_get_glyph_name:"
     cff     = (CFF_FontRec *)face->extra.data;
     charset = &cff->charset;
 
+    /* CFF2 table does not have glyph names; */
+    /* we need to use `post' table method    */
+    if ( cff->version_major == 2 )
+    {
+      FT_Library            library     = FT_FACE_LIBRARY( face );
+      FT_Module             sfnt_module = FT_Get_Module( library, "sfnt" );
+      FT_Service_GlyphDict  service     =
+        (FT_Service_GlyphDict)ft_module_get_service(
+                                 sfnt_module,
+                                 FT_SERVICE_ID_GLYPH_DICT,
+                                 0 );
+
+
+      if ( service && service->name_index )
+        return service->name_index( FT_FACE( face ), glyph_name );
+      else
+      {
+        FT_ERROR(( "cff_get_name_index:"
+                   " cannot get glyph index from a CFF2 font\n"
+                   "                   "
+                   " without the `PSNames' module\n" ));
+        return 0;
+      }
+    }
+
     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
     if ( !psnames )
       return 0;
 
   FT_DEFINE_SERVICE_GLYPHDICTREC(
     cff_service_glyph_dict,
+
     (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,      /* get_name   */
     (FT_GlyphDict_NameIndexFunc)cff_get_name_index       /* name_index */
   )
     FT_Error  error = FT_Err_Ok;
 
 
-    if ( cff && cff->font_info == NULL )
+    if ( cff && !cff->font_info )
     {
-      CFF_FontRecDict  dict   = &cff->top_font.font_dict;
+      CFF_FontRecDict  dict      = &cff->top_font.font_dict;
       PS_FontInfoRec  *font_info = NULL;
-      FT_Memory        memory = face->root.memory;
+      FT_Memory        memory    = face->root.memory;
 
 
       if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
 
   FT_DEFINE_SERVICE_PSINFOREC(
     cff_service_ps_info,
+
     (PS_GetFontInfoFunc)   cff_ps_get_font_info,    /* ps_get_font_info    */
     (PS_GetFontExtraFunc)  NULL,                    /* ps_get_font_extra   */
     (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,  /* ps_has_glyph_names  */
       FT_Service_PsFontName  service     =
         (FT_Service_PsFontName)ft_module_get_service(
                                  sfnt_module,
-                                 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME );
+                                 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME,
+                                 0 );
 
 
       if ( service && service->get_ps_font_name )
 
   FT_DEFINE_SERVICE_PSFONTNAMEREC(
     cff_service_ps_name,
+
     (FT_PsName_GetFunc)cff_get_ps_name      /* get_ps_font_name */
   )
 
     FT_Library  library = FT_FACE_LIBRARY( face );
 
 
-    cmap_info->language = 0;
-    cmap_info->format   = 0;
-
     if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
          cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET  )
     {
       FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
       FT_Service_TTCMaps  service =
         (FT_Service_TTCMaps)ft_module_get_service( sfnt,
-                                                   FT_SERVICE_ID_TT_CMAP );
+                                                   FT_SERVICE_ID_TT_CMAP,
+                                                   0 );
 
 
       if ( service && service->get_cmap_info )
         error = service->get_cmap_info( charmap, cmap_info );
     }
+    else
+      error = FT_THROW( Invalid_CharMap_Format );
 
     return error;
   }
 
   FT_DEFINE_SERVICE_TTCMAPSREC(
     cff_service_get_cmap_info,
+
     (TT_CMap_Info_GetFunc)cff_get_cmap_info    /* get_cmap_info */
   )
 
 
       if ( registry )
       {
-        if ( cff->registry == NULL )
+        if ( !cff->registry )
           cff->registry = cff_index_get_sid_string( cff,
                                                     dict->cid_registry );
         *registry = cff->registry;
 
       if ( ordering )
       {
-        if ( cff->ordering == NULL )
+        if ( !cff->ordering )
           cff->ordering = cff_index_get_sid_string( cff,
                                                     dict->cid_ordering );
         *ordering = cff->ordering;
 
   FT_DEFINE_SERVICE_CIDREC(
     cff_service_cid_info,
+
     (FT_CID_GetRegistryOrderingSupplementFunc)
       cff_get_ros,                             /* get_ros                  */
     (FT_CID_GetIsInternallyCIDKeyedFunc)
 
   FT_DEFINE_SERVICE_PROPERTIESREC(
     cff_service_properties,
+
     (FT_Properties_SetFunc)cff_property_set,      /* set_property */
     (FT_Properties_GetFunc)cff_property_get )     /* get_property */
 
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+  /*
+   *  MULTIPLE MASTER SERVICE
+   *
+   */
+
+  static FT_Error
+  cff_set_mm_blend( CFF_Face   face,
+                    FT_UInt    num_coords,
+                    FT_Fixed*  coords )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    return mm->set_mm_blend( FT_FACE( face ), num_coords, coords );
+  }
+
+
+  static FT_Error
+  cff_get_mm_blend( CFF_Face   face,
+                    FT_UInt    num_coords,
+                    FT_Fixed*  coords )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    return mm->get_mm_blend( FT_FACE( face ), num_coords, coords );
+  }
+
+
+  static FT_Error
+  cff_get_mm_var( CFF_Face     face,
+                  FT_MM_Var*  *master )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    return mm->get_mm_var( FT_FACE( face ), master );
+  }
+
+
+  static FT_Error
+  cff_set_var_design( CFF_Face   face,
+                      FT_UInt    num_coords,
+                      FT_Fixed*  coords )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    return mm->set_var_design( FT_FACE( face ), num_coords, coords );
+  }
+
+
+  static FT_Error
+  cff_get_var_design( CFF_Face   face,
+                      FT_UInt    num_coords,
+                      FT_Fixed*  coords )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    return mm->get_var_design( FT_FACE( face ), num_coords, coords );
+  }
+
+
+  FT_DEFINE_SERVICE_MULTIMASTERSREC(
+    cff_service_multi_masters,
+
+    (FT_Get_MM_Func)        NULL,                   /* get_mm         */
+    (FT_Set_MM_Design_Func) NULL,                   /* set_mm_design  */
+    (FT_Set_MM_Blend_Func)  cff_set_mm_blend,       /* set_mm_blend   */
+    (FT_Get_MM_Blend_Func)  cff_get_mm_blend,       /* get_mm_blend   */
+    (FT_Get_MM_Var_Func)    cff_get_mm_var,         /* get_mm_var     */
+    (FT_Set_Var_Design_Func)cff_set_var_design,     /* set_var_design */
+    (FT_Get_Var_Design_Func)cff_get_var_design,     /* get_var_design */
+
+    (FT_Get_Var_Blend_Func) cff_get_var_blend,      /* get_var_blend  */
+    (FT_Done_Blend_Func)    cff_done_blend          /* done_blend     */
+  )
+#endif
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
 
-#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
+#if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \
+     defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
+  FT_DEFINE_SERVICEDESCREC8(
+    cff_services,
+
+    FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
+    FT_SERVICE_ID_MULTI_MASTERS,        &CFF_SERVICE_MULTI_MASTERS_GET,
+    FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
+    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
+    FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
+    FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
+    FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
+    FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
+  )
+#elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES
   FT_DEFINE_SERVICEDESCREC7(
     cff_services,
+
     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
   )
+#elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
+  FT_DEFINE_SERVICEDESCREC7(
+    cff_services,
+
+    FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
+    FT_SERVICE_ID_MULTI_MASTERS,        &CFF_SERVICE_MULTI_MASTERS_GET,
+    FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
+    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
+    FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
+    FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
+    FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
+  )
 #else
   FT_DEFINE_SERVICEDESCREC6(
     cff_services,
+
     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
 #endif
 
     result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
-    if ( result != NULL )
+    if ( result )
       return result;
 
     /* `driver' is not yet evaluated in non-PIC mode */
       0x10000L,
       0x20000L,
 
-      0,   /* module-specific interface */
+      NULL,   /* module-specific interface */
 
       cff_driver_init,          /* FT_Module_Constructor  module_init   */
       cff_driver_done,          /* FT_Module_Destructor   module_done   */
     cff_glyph_load,             /* FT_Slot_LoadFunc  load_glyph */
 
     cff_get_kerning,            /* FT_Face_GetKerningFunc   get_kerning  */
-    0,                          /* FT_Face_AttachFunc       attach_file  */
+    NULL,                       /* FT_Face_AttachFunc       attach_file  */
     cff_get_advances,           /* FT_Face_GetAdvancesFunc  get_advances */
 
     cff_size_request,           /* FT_Size_RequestFunc  request_size */
index 4f375a6..d8084f8 100644 (file)
 
 
     /* clear everything */
-    FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
+    FT_ZERO( decoder );
 
     /* initialize builder */
     cff_builder_init( &decoder->builder, face, size, slot, hinting );
         if ( !( val & 0xFFFFL ) )
           FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) ));
         else
-          FT_TRACE4(( " %.2f", val / 65536.0 ));
+          FT_TRACE4(( " %.5f", val / 65536.0 ));
 #endif
 
       }
 
         case cff_op_and:
           {
-            FT_Fixed  cond = args[0] && args[1];
+            FT_Fixed  cond = ( args[0] && args[1] );
 
 
             FT_TRACE4(( " and\n" ));
 
         case cff_op_or:
           {
-            FT_Fixed  cond = args[0] || args[1];
+            FT_Fixed  cond = ( args[0] || args[1] );
 
 
             FT_TRACE4(( " or\n" ));
 
         case cff_op_eq:
           {
-            FT_Fixed  cond = args[0] == args[1];
+            FT_Fixed  cond = ( args[0] == args[1] );
 
 
             FT_TRACE4(( " eq\n" ));
index 470fa82..c1e6b14 100644 (file)
 #include FT_TRUETYPE_TAGS_H
 #include FT_TYPE1_TABLES_H
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include FT_MULTIPLE_MASTERS_H
+#include FT_SERVICE_MULTIPLE_MASTERS_H
+#endif
+
 #include "cffload.h"
 #include "cffparse.h"
 
 #include "cfferrs.h"
 
 
+#define FT_FIXED_ONE  ( (FT_Fixed)0x10000 )
+
+
 #if 1
 
   static const FT_UShort  cff_isoadobe_charset[229] =
   static FT_Error
   cff_index_init( CFF_Index  idx,
                   FT_Stream  stream,
-                  FT_Bool    load )
+                  FT_Bool    load,
+                  FT_Bool    cff2 )
   {
     FT_Error   error;
     FT_Memory  memory = stream->memory;
-    FT_UShort  count;
+    FT_UInt    count;
 
 
-    FT_MEM_ZERO( idx, sizeof ( *idx ) );
+    FT_ZERO( idx );
 
     idx->stream = stream;
     idx->start  = FT_STREAM_POS();
-    if ( !FT_READ_USHORT( count ) &&
-         count > 0                )
+
+    if ( cff2 )
+    {
+      if ( FT_READ_ULONG( count ) )
+        goto Exit;
+      idx->hdr_size = 5;
+    }
+    else
+    {
+      if ( FT_READ_USHORT( count ) )
+        goto Exit;
+      idx->hdr_size = 3;
+    }
+
+    if ( count > 0 )
     {
       FT_Byte   offsize;
       FT_ULong  size;
       idx->off_size = offsize;
       size          = (FT_ULong)( count + 1 ) * offsize;
 
-      idx->data_offset = idx->start + 3 + size;
+      idx->data_offset = idx->start + idx->hdr_size + size;
 
       if ( FT_STREAM_SKIP( size - offsize ) )
         goto Exit;
         FT_FRAME_RELEASE( idx->bytes );
 
       FT_FREE( idx->offsets );
-      FT_MEM_ZERO( idx, sizeof ( *idx ) );
+      FT_ZERO( idx );
     }
   }
 
     FT_Memory  memory = stream->memory;
 
 
-    if ( idx->count > 0 && idx->offsets == NULL )
+    if ( idx->count > 0 && !idx->offsets )
     {
       FT_Byte    offsize = idx->off_size;
       FT_ULong   data_size;
       data_size = (FT_ULong)( idx->count + 1 ) * offsize;
 
       if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
-           FT_STREAM_SEEK( idx->start + 3 )             ||
+           FT_STREAM_SEEK( idx->start + idx->hdr_size ) ||
            FT_FRAME_ENTER( data_size )                  )
         goto Exit;
 
 
     *table = NULL;
 
-    if ( idx->offsets == NULL )
+    if ( !idx->offsets )
     {
       error = cff_index_load_offsets( idx );
       if ( error )
         FT_ULong  pos = element * idx->off_size;
 
 
-        if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
+        if ( FT_STREAM_SEEK( idx->start + idx->hdr_size + pos ) )
           goto Exit;
 
         off1 = cff_index_read_offset( idx, &error );
                       FT_UInt   element )
   {
     CFF_Index   idx = &font->name_index;
-    FT_Memory   memory = idx->stream->memory;
+    FT_Memory   memory;
     FT_Byte*    bytes;
     FT_ULong    byte_len;
     FT_Error    error;
     FT_String*  name = 0;
 
 
+    if ( !idx->stream )  /* CFF2 does not include a name index */
+      goto Exit;
+
+    memory = idx->stream->memory;
+
     error = cff_index_access_element( idx, element, &bytes, &byte_len );
     if ( error )
       goto Exit;
     FT_Byte  fd = 0;
 
 
+    /* if there is no FDSelect, return zero               */
+    /* Note: CFF2 with just one Font Dict has no FDSelect */
+    if ( !fdselect->data )
+      goto Exit;
+
     switch ( fdselect->format )
     {
     case 0:
       ;
     }
 
+  Exit:
     return fd;
   }
 
   }
 
 
+  static void
+  cff_vstore_done( CFF_VStoreRec*  vstore,
+                   FT_Memory       memory )
+  {
+    FT_UInt  i;
+
+
+    /* free regionList and axisLists */
+    if ( vstore->varRegionList )
+    {
+      for ( i = 0; i < vstore->regionCount; i++ )
+        FT_FREE( vstore->varRegionList[i].axisList );
+    }
+    FT_FREE( vstore->varRegionList );
+
+    /* free varData and indices */
+    if ( vstore->varData )
+    {
+      for ( i = 0; i < vstore->dataCount; i++ )
+        FT_FREE( vstore->varData[i].regionIndices );
+    }
+    FT_FREE( vstore->varData );
+  }
+
+
+  /* convert 2.14 to Fixed */
+  #define FT_fdot14ToFixed( x )  ( ( (FT_Fixed)( (FT_Int16)(x) ) ) << 2 )
+
+
+  static FT_Error
+  cff_vstore_load( CFF_VStoreRec*  vstore,
+                   FT_Stream       stream,
+                   FT_ULong        base_offset,
+                   FT_ULong        offset )
+  {
+    FT_Memory  memory = stream->memory;
+    FT_Error   error  = FT_ERR( Invalid_File_Format );
+
+    FT_ULong*  dataOffsetArray = NULL;
+    FT_UInt    i, j;
+
+
+    /* no offset means no vstore to parse */
+    if ( offset )
+    {
+      FT_UInt   vsOffset;
+      FT_UInt   format;
+      FT_ULong  regionListOffset;
+
+
+      /* we need to parse the table to determine its size; */
+      /* skip table length                                 */
+      if ( FT_STREAM_SEEK( base_offset + offset ) ||
+           FT_STREAM_SKIP( 2 )                    )
+        goto Exit;
+
+      /* actual variation store begins after the length */
+      vsOffset = FT_STREAM_POS();
+
+      /* check the header */
+      if ( FT_READ_USHORT( format ) )
+        goto Exit;
+      if ( format != 1 )
+      {
+        error = FT_THROW( Invalid_File_Format );
+        goto Exit;
+      }
+
+      /* read top level fields */
+      if ( FT_READ_ULONG( regionListOffset )   ||
+           FT_READ_USHORT( vstore->dataCount ) )
+        goto Exit;
+
+      /* make temporary copy of item variation data offsets; */
+      /* we'll parse region list first, then come back       */
+      if ( FT_NEW_ARRAY( dataOffsetArray, vstore->dataCount ) )
+        goto Exit;
+
+      for ( i = 0; i < vstore->dataCount; i++ )
+      {
+        if ( FT_READ_ULONG( dataOffsetArray[i] ) )
+          goto Exit;
+      }
+
+      /* parse regionList and axisLists */
+      if ( FT_STREAM_SEEK( vsOffset + regionListOffset ) ||
+           FT_READ_USHORT( vstore->axisCount )           ||
+           FT_READ_USHORT( vstore->regionCount )         )
+        goto Exit;
+
+      if ( FT_NEW_ARRAY( vstore->varRegionList, vstore->regionCount ) )
+        goto Exit;
+
+      for ( i = 0; i < vstore->regionCount; i++ )
+      {
+        CFF_VarRegion*  region = &vstore->varRegionList[i];
+
+
+        if ( FT_NEW_ARRAY( region->axisList, vstore->axisCount ) )
+          goto Exit;
+
+        for ( j = 0; j < vstore->axisCount; j++ )
+        {
+          CFF_AxisCoords*  axis = &region->axisList[j];
+
+          FT_Int16  start14, peak14, end14;
+
+
+          if ( FT_READ_SHORT( start14 ) ||
+               FT_READ_SHORT( peak14 )  ||
+               FT_READ_SHORT( end14 )   )
+            goto Exit;
+
+          axis->startCoord = FT_fdot14ToFixed( start14 );
+          axis->peakCoord  = FT_fdot14ToFixed( peak14 );
+          axis->endCoord   = FT_fdot14ToFixed( end14 );
+        }
+      }
+
+      /* use dataOffsetArray now to parse varData items */
+      if ( FT_NEW_ARRAY( vstore->varData, vstore->dataCount ) )
+        goto Exit;
+
+      for ( i = 0; i < vstore->dataCount; i++ )
+      {
+        CFF_VarData*  data = &vstore->varData[i];
+
+
+        if ( FT_STREAM_SEEK( vsOffset + dataOffsetArray[i] ) )
+          goto Exit;
+
+        /* ignore `itemCount' and `shortDeltaCount' */
+        /* because CFF2 has no delta sets           */
+        if ( FT_STREAM_SKIP( 4 ) )
+          goto Exit;
+
+        /* Note: just record values; consistency is checked later    */
+        /*       by cff_blend_build_vector when it consumes `vstore' */
+
+        if ( FT_READ_USHORT( data->regionIdxCount ) )
+          goto Exit;
+
+        if ( FT_NEW_ARRAY( data->regionIndices, data->regionIdxCount ) )
+          goto Exit;
+
+        for ( j = 0; j < data->regionIdxCount; j++ )
+        {
+          if ( FT_READ_USHORT( data->regionIndices[j] ) )
+            goto Exit;
+        }
+      }
+    }
+
+    error = FT_Err_Ok;
+
+  Exit:
+    FT_FREE( dataOffsetArray );
+    if ( error )
+      cff_vstore_done( vstore, memory );
+
+    return error;
+  }
+
+
+  /* Clear blend stack (after blend values are consumed). */
+  /*                                                      */
+  /* TODO: Should do this in cff_run_parse, but subFont   */
+  /*       ref is not available there.                    */
+  /*                                                      */
+  /* Allocation is not changed when stack is cleared.     */
+  FT_LOCAL_DEF( void )
+  cff_blend_clear( CFF_SubFont  subFont )
+  {
+    subFont->blend_top  = subFont->blend_stack;
+    subFont->blend_used = 0;
+  }
+
+
+  /* Blend numOperands on the stack,                       */
+  /* store results into the first numBlends values,        */
+  /* then pop remaining arguments.                         */
+  /*                                                       */
+  /* This is comparable to `cf2_doBlend' but               */
+  /* the cffparse stack is different and can't be written. */
+  /* Blended values are written to a different buffer,     */
+  /* using reserved operator 255.                          */
+  /*                                                       */
+  /* Blend calculation is done in 16.16 fixed point.       */
+  FT_LOCAL_DEF( FT_Error )
+  cff_blend_doBlend( CFF_SubFont  subFont,
+                     CFF_Parser   parser,
+                     FT_UInt      numBlends )
+  {
+    FT_UInt  delta;
+    FT_UInt  base;
+    FT_UInt  i, j;
+    FT_UInt  size;
+
+    CFF_Blend  blend = &subFont->blend;
+
+    FT_Memory  memory = subFont->blend.font->memory; /* for FT_REALLOC */
+    FT_Error   error  = FT_Err_Ok;                   /* for FT_REALLOC */
+
+    /* compute expected number of operands for this blend */
+    FT_UInt  numOperands = (FT_UInt)( numBlends * blend->lenBV );
+    FT_UInt  count       = (FT_UInt)( parser->top - 1 - parser->stack );
+
+
+    if ( numOperands > count )
+    {
+      FT_TRACE4(( " cff_blend_doBlend: Stack underflow %d args\n", count ));
+
+      error = FT_THROW( Stack_Underflow );
+      goto Exit;
+    }
+
+    /* check whether we have room for `numBlends' values at `blend_top' */
+    size = 5 * numBlends;           /* add 5 bytes per entry    */
+    if ( subFont->blend_used + size > subFont->blend_alloc )
+    {
+      /* increase or allocate `blend_stack' and reset `blend_top'; */
+      /* prepare to append `numBlends' values to the buffer        */
+      if ( FT_REALLOC( subFont->blend_stack,
+                       subFont->blend_alloc,
+                       subFont->blend_alloc + size ) )
+        goto Exit;
+
+      subFont->blend_top    = subFont->blend_stack + subFont->blend_used;
+      subFont->blend_alloc += size;
+    }
+    subFont->blend_used += size;
+
+    base  = count - numOperands;     /* index of first blend arg */
+    delta = base + numBlends;        /* index of first delta arg */
+
+    for ( i = 0; i < numBlends; i++ )
+    {
+      const FT_Int32*  weight = &blend->BV[1];
+      FT_Int32         sum;
+
+
+      /* convert inputs to 16.16 fixed point */
+      sum = cff_parse_num( parser, &parser->stack[i + base] ) << 16;
+
+      for ( j = 1; j < blend->lenBV; j++ )
+        sum += FT_MulFix( *weight++,
+                          cff_parse_num( parser,
+                                         &parser->stack[delta++] ) << 16 );
+
+      /* point parser stack to new value on blend_stack */
+      parser->stack[i + base] = subFont->blend_top;
+
+      /* Push blended result as Type 2 5-byte fixed point number (except   */
+      /* that host byte order is used).  This will not conflict with       */
+      /* actual DICTs because 255 is a reserved opcode in both CFF and     */
+      /* CFF2 DICTs.  See `cff_parse_num' for decode of this, which rounds */
+      /* to an integer.                                                    */
+      *subFont->blend_top++             = 255;
+      *((FT_UInt32*)subFont->blend_top) = (FT_UInt32)sum; /* write 4 bytes */
+      subFont->blend_top               += 4;
+    }
+
+    /* leave only numBlends results on parser stack */
+    parser->top = &parser->stack[base + numBlends];
+
+  Exit:
+    return error;
+  }
+
+
+  /* Compute a blend vector from variation store index and normalized  */
+  /* vector based on pseudo-code in OpenType Font Variations Overview. */
+  /*                                                                   */
+  /* Note: lenNDV == 0 produces a default blend vector, (1,0,0,...).   */
+  FT_LOCAL_DEF( FT_Error )
+  cff_blend_build_vector( CFF_Blend  blend,
+                          FT_UInt    vsindex,
+                          FT_UInt    lenNDV,
+                          FT_Fixed*  NDV )
+  {
+    FT_Error   error  = FT_Err_Ok;            /* for FT_REALLOC */
+    FT_Memory  memory = blend->font->memory;  /* for FT_REALLOC */
+
+    FT_UInt       len;
+    CFF_VStore    vs;
+    CFF_VarData*  varData;
+    FT_UInt       master;
+
+
+    FT_ASSERT( lenNDV == 0 || NDV );
+
+    blend->builtBV = FALSE;
+
+    vs = &blend->font->vstore;
+
+    /* VStore and fvar must be consistent */
+    if ( lenNDV != 0 && lenNDV != vs->axisCount )
+    {
+      FT_TRACE4(( " cff_blend_build_vector: Axis count mismatch\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    if ( vsindex >= vs->dataCount )
+    {
+      FT_TRACE4(( " cff_blend_build_vector: vsindex out of range\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    /* select the item variation data structure */
+    varData = &vs->varData[vsindex];
+
+    /* prepare buffer for the blend vector */
+    len = varData->regionIdxCount + 1;    /* add 1 for default component */
+    if ( FT_REALLOC( blend->BV,
+                     blend->lenBV * sizeof( *blend->BV ),
+                     len * sizeof( *blend->BV ) ) )
+      goto Exit;
+
+    blend->lenBV = len;
+
+    /* outer loop steps through master designs to be blended */
+    for ( master = 0; master < len; master++ )
+    {
+      FT_UInt         j;
+      FT_UInt         idx;
+      CFF_VarRegion*  varRegion;
+
+
+      /* default factor is always one */
+      if ( master == 0 )
+      {
+        blend->BV[master] = FT_FIXED_ONE;
+        FT_TRACE4(( "   build blend vector len %d\n"
+                    "   [ %f ",
+                    len,
+                    blend->BV[master] / 65536.0 ));
+        continue;
+      }
+
+      /* VStore array does not include default master, so subtract one */
+      idx       = varData->regionIndices[master - 1];
+      varRegion = &vs->varRegionList[idx];
+
+      if ( idx >= vs->regionCount )
+      {
+        FT_TRACE4(( " cff_blend_build_vector:"
+                    " region index out of range\n" ));
+        error = FT_THROW( Invalid_File_Format );
+        goto Exit;
+      }
+
+      /* Note: `lenNDV' could be zero.                              */
+      /*       In that case, build default blend vector (1,0,0...). */
+      /*       In the normal case, initialize each component to 1   */
+      /*       before inner loop.                                   */
+      if ( lenNDV != 0 )
+        blend->BV[master] = FT_FIXED_ONE; /* default */
+
+      /* inner loop steps through axes in this region */
+      for ( j = 0; j < lenNDV; j++ )
+      {
+        CFF_AxisCoords*  axis = &varRegion->axisList[j];
+        FT_Fixed         axisScalar;
+
+
+        /* compute the scalar contribution of this axis; */
+        /* ignore invalid ranges                         */
+        if ( axis->startCoord > axis->peakCoord ||
+             axis->peakCoord > axis->endCoord   )
+          axisScalar = FT_FIXED_ONE;
+
+        else if ( axis->startCoord < 0 &&
+                  axis->endCoord > 0   &&
+                  axis->peakCoord != 0 )
+          axisScalar = FT_FIXED_ONE;
+
+        /* peak of 0 means ignore this axis */
+        else if ( axis->peakCoord == 0 )
+          axisScalar = FT_FIXED_ONE;
+
+        /* ignore this region if coords are out of range */
+        else if ( NDV[j] < axis->startCoord ||
+                  NDV[j] > axis->endCoord   )
+          axisScalar = 0;
+
+        /* calculate a proportional factor */
+        else
+        {
+          if ( NDV[j] == axis->peakCoord )
+            axisScalar = FT_FIXED_ONE;
+          else if ( NDV[j] < axis->peakCoord )
+            axisScalar = FT_DivFix( NDV[j] - axis->startCoord,
+                                    axis->peakCoord - axis->startCoord );
+          else
+            axisScalar = FT_DivFix( axis->endCoord - NDV[j],
+                                    axis->endCoord - axis->peakCoord );
+        }
+
+        /* take product of all the axis scalars */
+        blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar );
+      }
+
+      FT_TRACE4(( ", %f ",
+                  blend->BV[master] / 65536.0 ));
+    }
+
+    FT_TRACE4(( "]\n" ));
+
+    /* record the parameters used to build the blend vector */
+    blend->lastVsindex = vsindex;
+
+    if ( lenNDV != 0 )
+    {
+      /* user has set a normalized vector */
+      if ( FT_REALLOC( blend->lastNDV,
+                       blend->lenNDV * sizeof ( *NDV ),
+                       lenNDV * sizeof ( *NDV ) ) )
+        goto Exit;
+
+      blend->lenNDV = lenNDV;
+      FT_MEM_COPY( blend->lastNDV,
+                   NDV,
+                   lenNDV * sizeof ( *NDV ) );
+    }
+
+    blend->builtBV = TRUE;
+
+  Exit:
+    return error;
+  }
+
+
+  /* `lenNDV' is zero for default vector;           */
+  /* return TRUE if blend vector needs to be built. */
+  FT_LOCAL_DEF( FT_Bool )
+  cff_blend_check_vector( CFF_Blend  blend,
+                          FT_UInt    vsindex,
+                          FT_UInt    lenNDV,
+                          FT_Fixed*  NDV )
+  {
+    if ( !blend->builtBV                             ||
+         blend->lastVsindex != vsindex               ||
+         blend->lenNDV != lenNDV                     ||
+         ( lenNDV                                  &&
+           memcmp( NDV,
+                   blend->lastNDV,
+                   lenNDV * sizeof ( *NDV ) ) != 0 ) )
+    {
+      /* need to build blend vector */
+      return TRUE;
+    }
+
+    return FALSE;
+  }
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+  FT_LOCAL_DEF( FT_Error )
+  cff_get_var_blend( CFF_Face     face,
+                     FT_UInt     *num_coords,
+                     FT_Fixed*   *coords,
+                     FT_MM_Var*  *mm_var )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    return mm->get_var_blend( FT_FACE( face ), num_coords, coords, mm_var );
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cff_done_blend( CFF_Face  face )
+  {
+    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+
+    mm->done_blend( FT_FACE( face ) );
+  }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
+
   static void
   cff_encoding_done( CFF_Encoding  encoding )
   {
   }
 
 
+  /* Parse private dictionary; first call is always from `cff_face_init', */
+  /* so NDV has not been set for CFF2 variation.                          */
+  /*                                                                      */
+  /* `cff_slot_load' must call this function each time NDV changes.       */
+  FT_LOCAL_DEF( FT_Error )
+  cff_load_private_dict( CFF_Font     font,
+                         CFF_SubFont  subfont,
+                         FT_UInt      lenNDV,
+                         FT_Fixed*    NDV )
+  {
+    FT_Error         error  = FT_Err_Ok;
+    CFF_ParserRec    parser;
+    CFF_FontRecDict  top    = &subfont->font_dict;
+    CFF_Private      priv   = &subfont->private_dict;
+    FT_Stream        stream = font->stream;
+    FT_UInt          stackSize;
+
+
+    /* store handle needed to access memory, vstore for blend;    */
+    /* we need this for clean-up even if there is no private DICT */
+    subfont->blend.font   = font;
+    subfont->blend.usedBV = FALSE;  /* clear state */
+
+    if ( !top->private_offset || !top->private_size )
+      goto Exit2;       /* no private DICT, do nothing */
+
+    /* set defaults */
+    FT_ZERO( priv );
+
+    priv->blue_shift       = 7;
+    priv->blue_fuzz        = 1;
+    priv->lenIV            = -1;
+    priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
+    priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
+
+    /* provide inputs for blend calculations */
+    priv->subfont   = subfont;
+    subfont->lenNDV = lenNDV;
+    subfont->NDV    = NDV;
+
+    stackSize = font->cff2 ? font->top_font.font_dict.maxstack
+                           : CFF_MAX_STACK_DEPTH + 1;
+
+    if ( cff_parser_init( &parser,
+                          font->cff2 ? CFF2_CODE_PRIVATE : CFF_CODE_PRIVATE,
+                          priv,
+                          font->library,
+                          stackSize,
+                          top->num_designs,
+                          top->num_axes ) )
+      goto Exit;
+
+    if ( FT_STREAM_SEEK( font->base_offset + top->private_offset ) ||
+         FT_FRAME_ENTER( top->private_size )                       )
+      goto Exit;
+
+    FT_TRACE4(( " private dictionary:\n" ));
+    error = cff_parser_run( &parser,
+                            (FT_Byte*)stream->cursor,
+                            (FT_Byte*)stream->limit );
+    FT_FRAME_EXIT();
+
+    if ( error )
+      goto Exit;
+
+    /* ensure that `num_blue_values' is even */
+    priv->num_blue_values &= ~1;
+
+  Exit:
+    /* clean up */
+    cff_blend_clear( subfont ); /* clear blend stack */
+    cff_parser_done( &parser ); /* free parser stack */
+
+  Exit2:
+    /* no clean up (parser not initialized) */
+    return error;
+  }
+
+
+  /* There are 3 ways to call this function, distinguished by code.  */
+  /*                                                                 */
+  /* . CFF_CODE_TOPDICT for either a CFF Top DICT or a CFF Font DICT */
+  /* . CFF2_CODE_TOPDICT for CFF2 Top DICT                           */
+  /* . CFF2_CODE_FONTDICT for CFF2 Font DICT                         */
+
   static FT_Error
-  cff_subfont_load( CFF_SubFont  font,
+  cff_subfont_load( CFF_SubFont  subfont,
                     CFF_Index    idx,
                     FT_UInt      font_index,
                     FT_Stream    stream,
                     FT_ULong     base_offset,
-                    FT_Library   library )
+                    FT_UInt      code,
+                    CFF_Font     font )
   {
     FT_Error         error;
     CFF_ParserRec    parser;
     FT_Byte*         dict = NULL;
     FT_ULong         dict_len;
-    CFF_FontRecDict  top  = &font->font_dict;
-    CFF_Private      priv = &font->private_dict;
-
-
-    cff_parser_init( &parser,
-                     CFF_CODE_TOPDICT,
-                     &font->font_dict,
-                     library,
-                     0,
-                     0 );
+    CFF_FontRecDict  top  = &subfont->font_dict;
+    CFF_Private      priv = &subfont->private_dict;
+
+    FT_Bool  cff2      = FT_BOOL( code == CFF2_CODE_TOPDICT  ||
+                                  code == CFF2_CODE_FONTDICT );
+    FT_UInt  stackSize = cff2 ? CFF2_DEFAULT_STACK
+                              : CFF_MAX_STACK_DEPTH;
+
+
+    /* Note: We use default stack size for CFF2 Font DICT because        */
+    /*       Top and Font DICTs are not allowed to have blend operators. */
+    error = cff_parser_init( &parser,
+                             code,
+                             &subfont->font_dict,
+                             font->library,
+                             stackSize,
+                             0,
+                             0 );
+    if ( error )
+      goto Exit;
 
     /* set defaults */
-    FT_MEM_ZERO( top, sizeof ( *top ) );
+    FT_ZERO( top );
 
     top->underline_position  = -( 100L << 16 );
     top->underline_thickness = 50L << 16;
     top->cid_ordering        = 0xFFFFU;
     top->cid_font_name       = 0xFFFFU;
 
-    error = cff_index_access_element( idx, font_index, &dict, &dict_len );
+    /* set default stack size */
+    top->maxstack            = cff2 ? CFF2_DEFAULT_STACK : 48;
+
+    if ( idx->count )   /* count is nonzero for a real index */
+      error = cff_index_access_element( idx, font_index, &dict, &dict_len );
+    else
+    {
+      /* CFF2 has a fake top dict index;     */
+      /* simulate `cff_index_access_element' */
+
+      /* Note: macros implicitly use `stream' and set `error' */
+      if ( FT_STREAM_SEEK( idx->data_offset )       ||
+           FT_FRAME_EXTRACT( idx->data_size, dict ) )
+        goto Exit;
+
+      dict_len = idx->data_size;
+    }
+
     if ( !error )
     {
       FT_TRACE4(( " top dictionary:\n" ));
       error = cff_parser_run( &parser, dict, dict + dict_len );
     }
 
-    cff_index_forget_element( idx, &dict );
+    /* clean up regardless of error */
+    if ( idx->count )
+      cff_index_forget_element( idx, &dict );
+    else
+      FT_FRAME_RELEASE( dict );
 
     if ( error )
       goto Exit;
     if ( top->cid_registry != 0xFFFFU )
       goto Exit;
 
-    /* parse the private dictionary, if any */
-    if ( top->private_offset && top->private_size )
-    {
-      /* set defaults */
-      FT_MEM_ZERO( priv, sizeof ( *priv ) );
-
-      priv->blue_shift       = 7;
-      priv->blue_fuzz        = 1;
-      priv->lenIV            = -1;
-      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,
-                       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;
-
-      FT_TRACE4(( " private dictionary:\n" ));
-      error = cff_parser_run( &parser,
-                              (FT_Byte*)stream->cursor,
-                              (FT_Byte*)stream->limit );
-      FT_FRAME_EXIT();
-      if ( error )
-        goto Exit;
-
-      /* ensure that `num_blue_values' is even */
-      priv->num_blue_values &= ~1;
-    }
+    /* Parse the private dictionary, if any.                   */
+    /*                                                         */
+    /* CFF2 does not have a private dictionary in the Top DICT */
+    /* but may have one in a Font DICT.  We need to parse      */
+    /* the latter here in order to load any local subrs.       */
+    error = cff_load_private_dict( font, subfont, 0, 0 );
+    if ( error )
+      goto Exit;
 
     /* read the local subrs, if any */
     if ( priv->local_subrs_offset )
                            priv->local_subrs_offset ) )
         goto Exit;
 
-      error = cff_index_init( &font->local_subrs_index, stream, 1 );
+      error = cff_index_init( &subfont->local_subrs_index, stream, 1, cff2 );
       if ( error )
         goto Exit;
 
-      error = cff_index_get_pointers( &font->local_subrs_index,
-                                      &font->local_subrs, NULL, NULL );
+      error = cff_index_get_pointers( &subfont->local_subrs_index,
+                                      &subfont->local_subrs, NULL, NULL );
       if ( error )
         goto Exit;
     }
 
   Exit:
+    cff_parser_done( &parser ); /* free parser stack */
+
     return error;
   }
 
     {
       cff_index_done( &subfont->local_subrs_index );
       FT_FREE( subfont->local_subrs );
+
+      FT_FREE( subfont->blend.lastNDV );
+      FT_FREE( subfont->blend.BV );
+      FT_FREE( subfont->blend_stack );
     }
   }
 
                  FT_Stream  stream,
                  FT_Int     face_index,
                  CFF_Font   font,
-                 FT_Bool    pure_cff )
+                 FT_Bool    pure_cff,
+                 FT_Bool    cff2 )
   {
     static const FT_Frame_Field  cff_header_fields[] =
     {
 #undef  FT_STRUCTURE
 #define FT_STRUCTURE  CFF_FontRec
 
-      FT_FRAME_START( 4 ),
+      FT_FRAME_START( 3 ),
         FT_FRAME_BYTE( version_major ),
         FT_FRAME_BYTE( version_minor ),
         FT_FRAME_BYTE( header_size ),
-        FT_FRAME_BYTE( absolute_offsize ),
       FT_FRAME_END
     };
 
     FT_ZERO( font );
     FT_ZERO( &string_index );
 
-    font->stream = stream;
-    font->memory = memory;
-    dict         = &font->top_font.font_dict;
-    base_offset  = FT_STREAM_POS();
+    dict        = &font->top_font.font_dict;
+    base_offset = FT_STREAM_POS();
+
+    font->library     = library;
+    font->stream      = stream;
+    font->memory      = memory;
+    font->cff2        = cff2;
+    font->base_offset = base_offset;
 
     /* read CFF font header */
     if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
       goto Exit;
 
-    /* check format */
-    if ( font->version_major   != 1 ||
-         font->header_size      < 4 ||
-         font->absolute_offsize > 4 )
+    if ( cff2 )
     {
-      FT_TRACE2(( "  not a CFF font header\n" ));
-      error = FT_THROW( Unknown_File_Format );
-      goto Exit;
+      if ( font->version_major != 2 ||
+           font->header_size < 5    )
+      {
+        FT_TRACE2(( "  not a CFF2 font header\n" ));
+        error = FT_THROW( Unknown_File_Format );
+        goto Exit;
+      }
+
+      if ( FT_READ_USHORT( font->top_dict_length ) )
+        goto Exit;
+    }
+    else
+    {
+      FT_Byte  absolute_offset;
+
+
+      if ( FT_READ_BYTE( absolute_offset ) )
+        goto Exit;
+
+      if ( font->version_major != 1 ||
+           font->header_size < 4    ||
+           absolute_offset > 4      )
+      {
+        FT_TRACE2(( "  not a CFF font header\n" ));
+        error = FT_THROW( Unknown_File_Format );
+        goto Exit;
+      }
     }
 
     /* skip the rest of the header */
-    if ( FT_STREAM_SKIP( font->header_size - 4 ) )
+    if ( FT_STREAM_SEEK( base_offset + font->header_size ) )
+    {
+      /* For pure CFFs we have read only four bytes so far.  Contrary to */
+      /* other formats like SFNT those bytes doesn't define a signature; */
+      /* it is thus possible that the font isn't a CFF at all.           */
+      if ( pure_cff )
+      {
+        FT_TRACE2(( "  not a CFF file\n" ));
+        error = FT_THROW( Unknown_File_Format );
+      }
       goto Exit;
+    }
 
-    /* read the name, top dict, string and global subrs index */
-    if ( FT_SET_ERROR( cff_index_init( &font->name_index,
-                                       stream, 0 ) )                       ||
-         FT_SET_ERROR( cff_index_init( &font->font_dict_index,
-                                       stream, 0 ) )                       ||
-         FT_SET_ERROR( cff_index_init( &string_index,
-                                       stream, 1 ) )                       ||
-         FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
-                                       stream, 1 ) )                       ||
-         FT_SET_ERROR( cff_index_get_pointers( &string_index,
-                                               &font->strings,
-                                               &font->string_pool,
-                                               &font->string_pool_size ) ) )
-      goto Exit;
+    if ( cff2 )
+    {
+      /* For CFF2, the top dict data immediately follow the header    */
+      /* and the length is stored in the header `offSize' field;      */
+      /* there is no index for it.                                    */
+      /*                                                              */
+      /* Use the `font_dict_index' to save the current position       */
+      /* and length of data, but leave count at zero as an indicator. */
+      FT_ZERO( &font->font_dict_index );
+
+      font->font_dict_index.data_offset = FT_STREAM_POS();
+      font->font_dict_index.data_size   = font->top_dict_length;
+
+      /* skip the top dict data for now, we will parse it later */
+      if ( FT_STREAM_SKIP( font->top_dict_length ) )
+        goto Exit;
+
+      /* next, read the global subrs index */
+      if ( FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
+                                         stream, 1, cff2 ) ) )
+        goto Exit;
+    }
+    else
+    {
+      /* for CFF, read the name, top dict, string and global subrs index */
+      if ( FT_SET_ERROR( cff_index_init( &font->name_index,
+                                         stream, 0, cff2 ) ) )
+      {
+        if ( pure_cff )
+        {
+          FT_TRACE2(( "  not a CFF file\n" ));
+          error = FT_THROW( Unknown_File_Format );
+        }
+        goto Exit;
+      }
+
+      if ( FT_SET_ERROR( cff_index_init( &font->font_dict_index,
+                                         stream, 0, cff2 ) )                 ||
+           FT_SET_ERROR( cff_index_init( &string_index,
+                                         stream, 1, cff2 ) )                 ||
+           FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
+                                         stream, 1, cff2 ) )                 ||
+           FT_SET_ERROR( cff_index_get_pointers( &string_index,
+                                                 &font->strings,
+                                                 &font->string_pool,
+                                                 &font->string_pool_size ) ) )
+        goto Exit;
+    }
 
     font->num_strings = string_index.count;
 
                               subfont_index,
                               stream,
                               base_offset,
-                              library );
+                              cff2 ? CFF2_CODE_TOPDICT : CFF_CODE_TOPDICT,
+                              font );
     if ( error )
       goto Exit;
 
     if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
       goto Exit;
 
-    error = cff_index_init( &font->charstrings_index, stream, 0 );
+    error = cff_index_init( &font->charstrings_index, stream, 0, cff2 );
     if ( error )
       goto Exit;
 
-    /* now, check for a CID font */
-    if ( dict->cid_registry != 0xFFFFU )
+    /* now, check for a CID or CFF2 font */
+    if ( dict->cid_registry != 0xFFFFU ||
+         cff2                          )
     {
       CFF_IndexRec  fd_index;
       CFF_SubFont   sub = NULL;
       FT_UInt       idx;
 
 
+      /* for CFF2, read the Variation Store if available;                 */
+      /* this must follow the Top DICT parse and precede any Private DICT */
+      error = cff_vstore_load( &font->vstore,
+                               stream,
+                               base_offset,
+                               dict->vstore_offset );
+      if ( error )
+        goto Exit;
+
       /* this is a CID-keyed font, we must now allocate a table of */
       /* sub-fonts, then load each of them separately              */
       if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
         goto Exit;
 
-      error = cff_index_init( &fd_index, stream, 0 );
+      error = cff_index_init( &fd_index, stream, 0, cff2 );
       if ( error )
         goto Exit;
 
+      /* Font Dicts are not limited to 256 for CFF2. */
+      /* TODO: support this for CFF2                 */
       if ( fd_index.count > CFF_MAX_CID_FONTS )
       {
         FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
       {
         sub = font->subfonts[idx];
         FT_TRACE4(( "parsing subfont %u\n", idx ));
-        error = cff_subfont_load( sub, &fd_index, idx,
-                                  stream, base_offset, library );
+        error = cff_subfont_load( sub,
+                                  &fd_index,
+                                  idx,
+                                  stream,
+                                  base_offset,
+                                  cff2 ? CFF2_CODE_FONTDICT
+                                       : CFF_CODE_TOPDICT,
+                                  font );
         if ( error )
           goto Fail_CID;
       }
 
-      /* now load the FD Select array */
-      error = CFF_Load_FD_Select( &font->fd_select,
-                                  font->charstrings_index.count,
-                                  stream,
-                                  base_offset + dict->cid_fd_select_offset );
+      /* now load the FD Select array;               */
+      /* CFF2 omits FDSelect if there is only one FD */
+      if ( !cff2 || fd_index.count > 1 )
+        error = CFF_Load_FD_Select( &font->fd_select,
+                                    font->charstrings_index.count,
+                                    stream,
+                                    base_offset + dict->cid_fd_select_offset );
 
     Fail_CID:
       cff_index_done( &fd_index );
       goto Exit;
 
     /* read the Charset and Encoding tables if available */
-    if ( font->num_glyphs > 0 )
+    if ( !cff2 && font->num_glyphs > 0 )
     {
       FT_Bool  invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
 
     cff_index_done( &font->charstrings_index );
 
     /* release font dictionaries, but only if working with */
-    /* a CID keyed CFF font                                */
+    /* a CID keyed CFF font or a CFF2 font                 */
     if ( font->num_subfonts > 0 )
     {
       for ( idx = 0; idx < font->num_subfonts; idx++ )
 
     cff_encoding_done( &font->encoding );
     cff_charset_done( &font->charset, font->stream );
+    cff_vstore_done( &font->vstore, memory );
 
     cff_subfont_done( memory, &font->top_font );
 
index 1dd07ba..dc3a2c5 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <ft2build.h>
 #include "cfftypes.h"
+#include "cffparse.h"
+#include "cffobjs.h"  /* for CFF_Face */
 
 
 FT_BEGIN_HEADER
@@ -60,20 +62,58 @@ FT_BEGIN_HEADER
 
 
   FT_LOCAL( FT_Error )
-  cff_font_load( FT_Library library,
-                 FT_Stream  stream,
-                 FT_Int     face_index,
-                 CFF_Font   font,
-                 FT_Bool    pure_cff );
+  cff_font_load( FT_Library  library,
+                 FT_Stream   stream,
+                 FT_Int      face_index,
+                 CFF_Font    font,
+                 FT_Bool     pure_cff,
+                 FT_Bool     cff2 );
 
   FT_LOCAL( void )
   cff_font_done( CFF_Font  font );
 
 
+  FT_LOCAL( FT_Error )
+  cff_load_private_dict( CFF_Font     font,
+                         CFF_SubFont  subfont,
+                         FT_UInt      lenNDV,
+                         FT_Fixed*    NDV );
+
   FT_LOCAL( FT_Byte )
   cff_fd_select_get( CFF_FDSelect  fdselect,
                      FT_UInt       glyph_index );
 
+  FT_LOCAL( FT_Bool )
+  cff_blend_check_vector( CFF_Blend  blend,
+                          FT_UInt    vsindex,
+                          FT_UInt    lenNDV,
+                          FT_Fixed*  NDV );
+
+  FT_LOCAL( FT_Error )
+  cff_blend_build_vector( CFF_Blend  blend,
+                          FT_UInt    vsindex,
+                          FT_UInt    lenNDV,
+                          FT_Fixed*  NDV );
+
+  FT_LOCAL( void )
+  cff_blend_clear( CFF_SubFont  subFont );
+
+  FT_LOCAL( FT_Error )
+  cff_blend_doBlend( CFF_SubFont  subfont,
+                     CFF_Parser   parser,
+                     FT_UInt      numBlends );
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+  FT_LOCAL( FT_Error )
+  cff_get_var_blend( CFF_Face     face,
+                     FT_UInt     *num_coords,
+                     FT_Fixed*   *coords,
+                     FT_MM_Var*  *mm_var );
+
+  FT_LOCAL( void )
+  cff_done_blend( CFF_Face  face );
+#endif
+
 
 FT_END_HEADER
 
index 0f07696..926effc 100644 (file)
     FT_UInt      n, count;
 
 
-    FT_MEM_ZERO( priv, sizeof ( *priv ) );
+    FT_ZERO( priv );
 
     count = priv->num_blue_values = cpriv->num_blue_values;
     for ( n = 0; n < count; n++ )
       FT_Int  idx;
 
 
-      for ( idx = 1; idx <= style_name_length; ++idx )
+      for ( idx = 1; idx <= style_name_length; idx++ )
       {
         if ( family_name[family_name_length - idx] !=
              style_name[style_name_length - idx] )
                   family_name[idx] == ' ' ||
                   family_name[idx] == '_' ||
                   family_name[idx] == '+' ) )
-          --idx;
+          idx--;
 
         if ( idx > 0 )
           family_name[idx + 1] = '\0';
     FT_Service_PsCMaps  psnames;
     PSHinter_Service    pshinter;
     FT_Bool             pure_cff    = 1;
+    FT_Bool             cff2        = 0;
     FT_Bool             sfnt_format = 0;
     FT_Library          library     = cffface->driver->root.library;
 
           goto Exit;
       }
 
-      /* now load the CFF part of the file */
-      error = face->goto_table( face, TTAG_CFF, stream, 0 );
+      /* now load the CFF part of the file; */
+      /* give priority to CFF2              */
+      error = face->goto_table( face, TTAG_CFF2, stream, 0 );
+      if ( !error )
+      {
+        cff2         = 1;
+        face->isCFF2 = cff2;
+      }
+
+      if ( FT_ERR_EQ( error, Table_Missing ) )
+        error = face->goto_table( face, TTAG_CFF, stream, 0 );
+
       if ( error )
         goto Exit;
     }
         goto Exit;
 
       face->extra.data = cff;
-      error = cff_font_load( library, stream, face_index, cff, pure_cff );
+      error = cff_font_load( library,
+                             stream,
+                             face_index,
+                             cff,
+                             pure_cff,
+                             cff2 );
       if ( error )
         goto Exit;
 
       }
 #endif /* FT_DEBUG_LEVEL_TRACE */
 
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+    {
+      FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
+
+      FT_Int  instance_index = face_index >> 16;
+
+
+      if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
+           mm                                 &&
+           instance_index > 0                 )
+      {
+        FT_MM_Var*  mm_var;
+
+
+        error = mm->get_mm_var( cffface, NULL );
+        if ( error )
+          goto Exit;
+
+        mm->get_var_blend( cffface, NULL, NULL, &mm_var );
+
+        if ( mm_var->namedstyle )
+        {
+          FT_Var_Named_Style*  named_style;
+          FT_String*           style_name;
+
+
+          /* in `face_index', the instance index starts with value 1 */
+          named_style = mm_var->namedstyle + instance_index - 1;
+          error = sfnt->get_name( face,
+                                  (FT_UShort)named_style->strid,
+                                  &style_name );
+          if ( error )
+            goto Exit;
+
+          /* set style name; if already set, replace it */
+          if ( face->root.style_name )
+            FT_FREE( face->root.style_name );
+          face->root.style_name = style_name;
+
+          /* finally, select the named instance */
+          error = mm->set_var_design( cffface,
+                                      mm_var->num_axis,
+                                      named_style->coords );
+          if ( error )
+            goto Exit;
+        }
+      }
+    }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
+
+
       if ( !dict->has_font_matrix )
         dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
 
         error = FT_Err_Ok;
 
         /* if no Unicode charmap was previously selected, select this one */
-        if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps )
+        if ( !cffface->charmap && nn != (FT_UInt)cffface->num_charmaps )
           cffface->charmap = cffface->charmaps[nn];
 
       Skip_Unicode:
         FT_FREE( face->extra.data );
       }
     }
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+    cff_done_blend( face );
+    face->blend = NULL;
+#endif
   }
 
 
index a4f986b..ee538c3 100644 (file)
@@ -24,6 +24,7 @@
 #include "cfferrs.h"
 #include "cffpic.h"
 #include "cffgload.h"
+#include "cffload.h"
 
 
   /*************************************************************************/
 #define FT_COMPONENT  trace_cffparse
 
 
-  FT_LOCAL_DEF( void )
+  FT_LOCAL_DEF( FT_Error )
   cff_parser_init( CFF_Parser  parser,
                    FT_UInt     code,
                    void*       object,
                    FT_Library  library,
+                   FT_UInt     stackSize,
                    FT_UShort   num_designs,
                    FT_UShort   num_axes )
   {
-    FT_MEM_ZERO( parser, sizeof ( *parser ) );
+    FT_Memory  memory = library->memory;    /* for FT_NEW_ARRAY */
+    FT_Error   error;                       /* for FT_NEW_ARRAY */
+
+
+    FT_ZERO( parser );
 
+#if 0
     parser->top         = parser->stack;
+#endif
     parser->object_code = code;
     parser->object      = object;
     parser->library     = library;
     parser->num_designs = num_designs;
     parser->num_axes    = num_axes;
+
+    /* allocate the stack buffer */
+    if ( FT_NEW_ARRAY( parser->stack, stackSize ) )
+    {
+      FT_FREE( parser->stack );
+      goto Exit;
+    }
+
+    parser->stackSize = stackSize;
+    parser->top       = parser->stack;    /* empty stack */
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cff_parser_done( CFF_Parser  parser )
+  {
+    FT_Memory  memory = parser->library->memory;    /* for FT_FREE */
+
+
+    FT_FREE( parser->stack );
   }
 
 
 
 
   /* read a number, either integer or real */
-  static FT_Long
-  cff_parse_num( FT_Byte**  d )
+  FT_LOCAL_DEF( FT_Long )
+  cff_parse_num( CFF_Parser  parser,
+                 FT_Byte**   d )
   {
-    return **d == 30 ? ( cff_parse_real( d[0], d[1], 0, NULL ) >> 16 )
-                     :   cff_parse_integer( d[0], d[1] );
+    if ( **d == 30 )
+    {
+      /* binary-coded decimal is truncated to integer */
+      return cff_parse_real( *d, parser->limit, 0, NULL ) >> 16;
+    }
+
+    else if ( **d == 255 )
+    {
+      /* 16.16 fixed point is used internally for CFF2 blend results. */
+      /* Since these are trusted values, a limit check is not needed. */
+
+      /* After the 255, 4 bytes are in host order. */
+      /* Blend result is rounded to integer.       */
+      return (FT_Long)( *( (FT_UInt32 *) ( d[0] + 1 ) ) + 0x8000U ) >> 16;
+    }
+
+    else
+      return cff_parse_integer( *d, parser->limit );
   }
 
 
   /* read a floating point number, either integer or real */
   static FT_Fixed
-  do_fixed( FT_Byte**  d,
-            FT_Long    scaling )
+  do_fixed( CFF_Parser  parser,
+            FT_Byte**   d,
+            FT_Long     scaling )
   {
     if ( **d == 30 )
-      return cff_parse_real( d[0], d[1], scaling, NULL );
+      return cff_parse_real( *d, parser->limit, scaling, NULL );
     else
     {
-      FT_Long  val = cff_parse_integer( d[0], d[1] );
+      FT_Long  val = cff_parse_integer( *d, parser->limit );
 
 
       if ( scaling )
 
   /* read a floating point number, either integer or real */
   static FT_Fixed
-  cff_parse_fixed( FT_Byte**  d )
+  cff_parse_fixed( CFF_Parser  parser,
+                   FT_Byte**   d )
   {
-    return do_fixed( d, 0 );
+    return do_fixed( parser, d, 0 );
   }
 
 
   /* read a floating point number, either integer or real, */
   /* but return `10^scaling' times the number read in      */
   static FT_Fixed
-  cff_parse_fixed_scaled( FT_Byte**  d,
-                          FT_Long    scaling )
+  cff_parse_fixed_scaled( CFF_Parser  parser,
+                          FT_Byte**   d,
+                          FT_Long     scaling )
   {
-    return do_fixed( d, scaling );
+    return do_fixed( parser, d, scaling );
   }
 
 
   /* and return it as precise as possible -- `scaling' returns */
   /* the scaling factor (as a power of 10)                     */
   static FT_Fixed
-  cff_parse_fixed_dynamic( FT_Byte**  d,
-                           FT_Long*   scaling )
+  cff_parse_fixed_dynamic( CFF_Parser  parser,
+                           FT_Byte**   d,
+                           FT_Long*    scaling )
   {
     FT_ASSERT( scaling );
 
     if ( **d == 30 )
-      return cff_parse_real( d[0], d[1], 0, scaling );
+      return cff_parse_real( *d, parser->limit, 0, scaling );
     else
     {
       FT_Long  number;
 
       for ( i = 0; i < 6; i++ )
       {
-        values[i] = cff_parse_fixed_dynamic( data++, &scalings[i] );
+        values[i] = cff_parse_fixed_dynamic( parser, data++, &scalings[i] );
         if ( values[i] )
         {
           if ( scalings[i] > max_scaling )
 
     if ( parser->top >= parser->stack + 4 )
     {
-      bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );
-      bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
-      bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
-      bbox->yMax = FT_RoundFix( cff_parse_fixed( data   ) );
+      bbox->xMin = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
+      bbox->yMin = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
+      bbox->xMax = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
+      bbox->yMax = FT_RoundFix( cff_parse_fixed( parser, data   ) );
       error = FT_Err_Ok;
 
       FT_TRACE4(( " [%d %d %d %d]\n",
       FT_Long  tmp;
 
 
-      tmp = cff_parse_num( data++ );
+      tmp = cff_parse_num( parser, data++ );
       if ( tmp < 0 )
       {
         FT_ERROR(( "cff_parse_private_dict: Invalid dictionary size\n" ));
       }
       dict->private_size = (FT_ULong)tmp;
 
-      tmp = cff_parse_num( data );
+      tmp = cff_parse_num( parser, data );
       if ( tmp < 0 )
       {
         FT_ERROR(( "cff_parse_private_dict: Invalid dictionary offset\n" ));
     /* currently, we handle only the first argument */
     if ( parser->top >= parser->stack + 5 )
     {
-      FT_Long  num_designs = cff_parse_num( parser->stack );
+      FT_Long  num_designs = cff_parse_num( parser, parser->stack );
 
 
       if ( num_designs > 16 || num_designs < 2 )
 
     if ( parser->top >= parser->stack + 3 )
     {
-      dict->cid_registry = (FT_UInt)cff_parse_num( data++ );
-      dict->cid_ordering = (FT_UInt)cff_parse_num( data++ );
+      dict->cid_registry = (FT_UInt)cff_parse_num( parser, data++ );
+      dict->cid_ordering = (FT_UInt)cff_parse_num( parser, data++ );
       if ( **data == 30 )
         FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));
-      dict->cid_supplement = cff_parse_num( data );
+      dict->cid_supplement = cff_parse_num( parser, data );
       if ( dict->cid_supplement < 0 )
         FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",
                    dict->cid_supplement ));
   }
 
 
+  static FT_Error
+  cff_parse_vsindex( CFF_Parser  parser )
+  {
+    /* vsindex operator can only be used in a Private DICT */
+    CFF_Private  priv = (CFF_Private)parser->object;
+    FT_Byte**    data = parser->stack;
+    CFF_Blend    blend;
+    FT_Error     error;
+
+
+    if ( !priv || !priv->subfont )
+    {
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    blend = &priv->subfont->blend;
+
+    if ( blend->usedBV )
+    {
+      FT_ERROR(( " cff_parse_vsindex: vsindex not allowed after blend\n" ));
+      error = FT_THROW( Syntax_Error );
+      goto Exit;
+    }
+
+    priv->vsindex = (FT_UInt)cff_parse_num( parser, data++ );
+
+    FT_TRACE4(( " %d\n", priv->vsindex ));
+
+    error = FT_Err_Ok;
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_Error
+  cff_parse_blend( CFF_Parser  parser )
+  {
+    /* blend operator can only be used in a Private DICT */
+    CFF_Private  priv = (CFF_Private)parser->object;
+    CFF_SubFont  subFont;
+    CFF_Blend    blend;
+    FT_UInt      numBlends;
+    FT_Error     error;
+
+
+    error = FT_ERR( Stack_Underflow );
+
+    if ( !priv || !priv->subfont )
+    {
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    subFont = priv->subfont;
+    blend   = &subFont->blend;
+
+    if ( cff_blend_check_vector( blend,
+                                 priv->vsindex,
+                                 subFont->lenNDV,
+                                 subFont->NDV ) )
+    {
+      error = cff_blend_build_vector( blend,
+                                      priv->vsindex,
+                                      subFont->lenNDV,
+                                      subFont->NDV );
+      if ( error )
+        goto Exit;
+    }
+
+    numBlends = (FT_UInt)cff_parse_num( parser, parser->top - 1 );
+    if ( numBlends > parser->stackSize )
+    {
+      FT_ERROR(( "cff_parse_blend: Invalid number of blends\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    FT_TRACE4(( "   %d values blended\n", numBlends ));
+
+    error = cff_blend_doBlend( subFont, parser, numBlends );
+
+    blend->usedBV = TRUE;
+
+  Exit:
+    return error;
+  }
+
+
+  /* maxstack operator increases parser and operand stacks for CFF2 */
+  static FT_Error
+  cff_parse_maxstack( CFF_Parser  parser )
+  {
+    /* maxstack operator can only be used in a Top DICT */
+    CFF_FontRecDict  dict  = (CFF_FontRecDict)parser->object;
+    FT_Byte**        data  = parser->stack;
+    FT_Error         error = FT_Err_Ok;
+
+
+    if ( !dict )
+    {
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    dict->maxstack = (FT_UInt)cff_parse_num( parser, data++ );
+    if ( dict->maxstack > CFF2_MAX_STACK )
+      dict->maxstack = CFF2_MAX_STACK;
+    if ( dict->maxstack < CFF2_DEFAULT_STACK )
+      dict->maxstack = CFF2_DEFAULT_STACK;
+
+    FT_TRACE4(( " %d\n", dict->maxstack ));
+
+  Exit:
+    return error;
+  }
+
+
 #define CFF_FIELD_NUM( code, name, id )             \
           CFF_FIELD( code, name, id, cff_kind_num )
 #define CFF_FIELD_FIXED( code, name, id )             \
 #define CFF_FIELD_BOOL( code, name, id )             \
           CFF_FIELD( code, name, id, cff_kind_bool )
 
-#define CFFCODE_TOPDICT  0x1000
-#define CFFCODE_PRIVATE  0x2000
-
 
 #ifndef FT_CONFIG_OPTION_PIC
 
             0, 0                             \
           },
 
+#define CFF_FIELD_BLEND( code, id ) \
+          {                         \
+            cff_kind_blend,         \
+            code | CFFCODE,         \
+            0, 0,                   \
+            cff_parse_blend,        \
+            0, 0                    \
+          },
+
 #define CFF_FIELD( code, name, id, kind ) \
           {                               \
             kind,                         \
             id                               \
           },
 
+#define CFF_FIELD_BLEND( code, id ) \
+          {                         \
+            cff_kind_blend,         \
+            code | CFFCODE,         \
+            0, 0,                   \
+            cff_parse_blend,        \
+            0, 0,                   \
+            id                      \
+          },
+
 #define CFF_FIELD( code, name, id, kind ) \
           {                               \
             kind,                         \
     {
       FT_UInt  v = *p;
 
-
-      if ( v >= 27 && v != 31 )
+      /* Opcode 31 is legacy MM T2 operator, not a number.      */
+      /* Opcode 255 is reserved and should not appear in fonts; */
+      /* it is used internally for CFF2 blends.                 */
+      if ( v >= 27 && v != 31 && v != 255 )
       {
         /* it's a number; we will push its position on the stack */
-        if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
+        if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
           goto Stack_Overflow;
 
         *parser->top++ = 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 ) );
+        FT_ZERO( &decoder );
+        FT_ZERO( &cff_rec );
 
         cff_rec.top_font.font_dict.num_designs = parser->num_designs;
         cff_rec.top_font.font_dict.num_axes    = parser->num_axes;
           FT_Bool   neg;
 
 
-          if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
+          if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
             goto Stack_Overflow;
 
           *parser->top++ = q;
         /* and look for it in our current list.                            */
 
         FT_UInt                   code;
-        FT_UInt                   num_args = (FT_UInt)
-                                             ( parser->top - parser->stack );
+        FT_UInt                   num_args;
         const CFF_Field_Handler*  field;
 
 
+        if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
+          goto Stack_Overflow;
+
+        num_args     = (FT_UInt)( parser->top - parser->stack );
         *parser->top = p;
-        code = v;
+        code         = v;
+
         if ( v == 12 )
         {
           /* two byte operator */
             case cff_kind_bool:
             case cff_kind_string:
             case cff_kind_num:
-              val = cff_parse_num( parser->stack );
+              val = cff_parse_num( parser, parser->stack );
               goto Store_Number;
 
             case cff_kind_fixed:
-              val = cff_parse_fixed( parser->stack );
+              val = cff_parse_fixed( parser, parser->stack );
               goto Store_Number;
 
             case cff_kind_fixed_thousand:
-              val = cff_parse_fixed_scaled( parser->stack, 3 );
+              val = cff_parse_fixed_scaled( parser, parser->stack, 3 );
 
             Store_Number:
               switch ( field->size )
                 val = 0;
                 while ( num_args > 0 )
                 {
-                  val += cff_parse_num( data++ );
+                  val += cff_parse_num( parser, data++ );
                   switch ( field->size )
                   {
                   case (8 / FT_CHAR_BIT):
               }
               break;
 
-            default:  /* callback */
+            default:  /* callback or blend */
               error = field->reader( parser );
               if ( error )
                 goto Exit;
 
       Found:
         /* clear stack */
-        parser->top = parser->stack;
+        /* TODO: could clear blend stack here,       */
+        /*       but we don't have access to subFont */
+        if ( field->kind != cff_kind_blend )
+          parser->top = parser->stack;
       }
       p++;
     }
index a95970e..6088fec 100644 (file)
 FT_BEGIN_HEADER
 
 
+  /* CFF uses constant parser stack size; */
+  /* CFF2 can increase from default 193   */
 #define CFF_MAX_STACK_DEPTH  96
+#define CFF2_MAX_STACK      513
+#define CFF2_DEFAULT_STACK  193
 
-#define CFF_CODE_TOPDICT  0x1000
-#define CFF_CODE_PRIVATE  0x2000
+#define CFF_CODE_TOPDICT    0x1000
+#define CFF_CODE_PRIVATE    0x2000
+#define CFF2_CODE_TOPDICT   0x3000
+#define CFF2_CODE_FONTDICT  0x4000
+#define CFF2_CODE_PRIVATE   0x5000
 
 
   typedef struct  CFF_ParserRec_
@@ -41,8 +48,9 @@ FT_BEGIN_HEADER
     FT_Byte*    limit;
     FT_Byte*    cursor;
 
-    FT_Byte*    stack[CFF_MAX_STACK_DEPTH + 1];
+    FT_Byte**   stack;
     FT_Byte**   top;
+    FT_UInt     stackSize;  /* allocated size */
 
     FT_UInt     object_code;
     void*       object;
@@ -53,14 +61,22 @@ FT_BEGIN_HEADER
   } CFF_ParserRec, *CFF_Parser;
 
 
-  FT_LOCAL( void )
+  FT_LOCAL( FT_Long )
+  cff_parse_num( CFF_Parser  parser,
+                 FT_Byte**   d );
+
+  FT_LOCAL( FT_Error )
   cff_parser_init( CFF_Parser  parser,
                    FT_UInt     code,
                    void*       object,
                    FT_Library  library,
+                   FT_UInt     stackSize,
                    FT_UShort   num_designs,
                    FT_UShort   num_axes );
 
+  FT_LOCAL( void )
+  cff_parser_done( CFF_Parser  parser );
+
   FT_LOCAL( FT_Error )
   cff_parser_run( CFF_Parser  parser,
                   FT_Byte*    start,
@@ -77,6 +93,7 @@ FT_BEGIN_HEADER
     cff_kind_bool,
     cff_kind_delta,
     cff_kind_callback,
+    cff_kind_blend,
 
     cff_kind_max  /* do not remove */
   };
index bed6b35..4737b9e 100644 (file)
@@ -32,6 +32,7 @@
 #define CFF_SERVICE_CID_INFO_GET         cff_service_cid_info
 #define CFF_SERVICE_PROPERTIES_GET       cff_service_properties
 #define CFF_SERVICES_GET                 cff_services
+#define CFF_SERVICE_MULTI_MASTERS_GET    cff_service_multi_masters
 #define CFF_CMAP_ENCODING_CLASS_REC_GET  cff_cmap_encoding_class_rec
 #define CFF_CMAP_UNICODE_CLASS_REC_GET   cff_cmap_unicode_class_rec
 #define CFF_FIELD_HANDLERS_GET           cff_field_handlers
index 22637c7..fd41c6c 100644 (file)
@@ -20,7 +20,7 @@
 #define FT_STRUCTURE  CFF_FontRecDictRec
 
 #undef  CFFCODE
-#define CFFCODE       CFFCODE_TOPDICT
+#define CFFCODE       CFF_CODE_TOPDICT
 
   CFF_FIELD_STRING  ( 0,     version,             "Version" )
   CFF_FIELD_STRING  ( 1,     notice,              "Notice" )
@@ -78,7 +78,7 @@
 #undef  FT_STRUCTURE
 #define FT_STRUCTURE  CFF_PrivateRec
 #undef  CFFCODE
-#define CFFCODE       CFFCODE_PRIVATE
+#define CFFCODE       CFF_CODE_PRIVATE
 
   CFF_FIELD_DELTA     ( 6,     blue_values, 14,        "BlueValues" )
   CFF_FIELD_DELTA     ( 7,     other_blues, 10,        "OtherBlues" )
   CFF_FIELD_NUM       ( 21,    nominal_width,          "nominalWidthX" )
 
 
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  CFF_FontRecDictRec
+#undef  CFFCODE
+#define CFFCODE       CFF2_CODE_TOPDICT
+
+  CFF_FIELD_CALLBACK( 0x107, font_matrix,          "FontMatrix" )
+  CFF_FIELD_NUM     ( 17,    charstrings_offset,   "CharStrings" )
+  CFF_FIELD_NUM     ( 0x124, cid_fd_array_offset,  "FDArray" )
+  CFF_FIELD_NUM     ( 0x125, cid_fd_select_offset, "FDSelect" )
+  CFF_FIELD_NUM     ( 24,    vstore_offset,        "vstore" )
+  CFF_FIELD_CALLBACK( 25,    maxstack,             "maxstack" )
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  CFF_FontRecDictRec
+#undef  CFFCODE
+#define CFFCODE       CFF2_CODE_FONTDICT
+
+  CFF_FIELD_CALLBACK( 18,    private_dict, "Private" )
+  CFF_FIELD_CALLBACK( 0x107, font_matrix,  "FontMatrix" )
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  CFF_PrivateRec
+#undef  CFFCODE
+#define CFFCODE       CFF2_CODE_PRIVATE
+
+  CFF_FIELD_DELTA     ( 6,     blue_values, 14,        "BlueValues" )
+  CFF_FIELD_DELTA     ( 7,     other_blues, 10,        "OtherBlues" )
+  CFF_FIELD_DELTA     ( 8,     family_blues, 14,       "FamilyBlues" )
+  CFF_FIELD_DELTA     ( 9,     family_other_blues, 10, "FamilyOtherBlues" )
+  CFF_FIELD_FIXED_1000( 0x109, blue_scale,             "BlueScale" )
+  CFF_FIELD_NUM       ( 0x10A, blue_shift,             "BlueShift" )
+  CFF_FIELD_NUM       ( 0x10B, blue_fuzz,              "BlueFuzz" )
+  CFF_FIELD_NUM       ( 10,    standard_width,         "StdHW" )
+  CFF_FIELD_NUM       ( 11,    standard_height,        "StdVW" )
+  CFF_FIELD_DELTA     ( 0x10C, snap_widths, 13,        "StemSnapH" )
+  CFF_FIELD_DELTA     ( 0x10D, snap_heights, 13,       "StemSnapV" )
+  CFF_FIELD_NUM       ( 0x111, language_group,         "LanguageGroup" )
+  CFF_FIELD_FIXED     ( 0x112, expansion_factor,       "ExpansionFactor" )
+  CFF_FIELD_CALLBACK  ( 22,    vsindex,                "vsindex" )
+  CFF_FIELD_BLEND     ( 23,                            "blend" )
+  CFF_FIELD_NUM       ( 19,    local_subrs_offset,     "Subrs" )
+
+
 /* END */
index 4426c7e..4dae0f2 100644 (file)
@@ -64,6 +64,7 @@ FT_BEGIN_HEADER
   {
     FT_Stream  stream;
     FT_ULong   start;
+    FT_UInt    hdr_size;
     FT_UInt    count;
     FT_Byte    off_size;
     FT_ULong   data_offset;
@@ -102,6 +103,79 @@ FT_BEGIN_HEADER
   } CFF_CharsetRec, *CFF_Charset;
 
 
+  /* cf. similar fields in file `ttgxvar.h' from the `truetype' module */
+
+  typedef struct  CFF_VarData_
+  {
+#if 0
+    FT_UInt  itemCount;       /* not used; always zero */
+    FT_UInt  shortDeltaCount; /* not used; always zero */
+#endif
+
+    FT_UInt   regionIdxCount; /* number of regions in this var data */
+    FT_UInt*  regionIndices;  /* array of `regionCount' indices;    */
+                              /* these index `varRegionList'        */
+  } CFF_VarData;
+
+
+  /* contribution of one axis to a region */
+  typedef struct  CFF_AxisCoords_
+  {
+    FT_Fixed  startCoord;
+    FT_Fixed  peakCoord;      /* zero peak means no effect (factor = 1) */
+    FT_Fixed  endCoord;
+
+  } CFF_AxisCoords;
+
+
+  typedef struct  CFF_VarRegion_
+  {
+    CFF_AxisCoords*  axisList;      /* array of axisCount records */
+
+  } CFF_VarRegion;
+
+
+  typedef struct  CFF_VStoreRec_
+  {
+    FT_UInt         dataCount;
+    CFF_VarData*    varData;        /* array of dataCount records      */
+                                    /* vsindex indexes this array      */
+    FT_UShort       axisCount;
+    FT_UInt         regionCount;    /* total number of regions defined */
+    CFF_VarRegion*  varRegionList;
+
+  } CFF_VStoreRec, *CFF_VStore;
+
+
+  /* forward reference */
+  typedef struct CFF_FontRec_*  CFF_Font;
+
+
+  /* This object manages one cached blend vector.                  */
+  /*                                                               */
+  /* There is a BlendRec for Private DICT parsing in each subfont  */
+  /* and a BlendRec for charstrings in CF2_Font instance data.     */
+  /* A cached BV may be used across DICTs or Charstrings if inputs */
+  /* have not changed.                                             */
+  /*                                                               */
+  /* `usedBV' is reset at the start of each parse or charstring.   */
+  /* vsindex cannot be changed after a BV is used.                 */
+  /*                                                               */
+  /* Note: NDV is long (32/64 bit), while BV is 16.16 (FT_Int32).  */
+  typedef struct  CFF_BlendRec_
+  {
+    FT_Bool    builtBV;        /* blendV has been built           */
+    FT_Bool    usedBV;         /* blendV has been used            */
+    CFF_Font   font;           /* top level font struct           */
+    FT_UInt    lastVsindex;    /* last vsindex used               */
+    FT_UInt    lenNDV;         /* normDV length (aka numAxes)     */
+    FT_Fixed*  lastNDV;        /* last NDV used                   */
+    FT_UInt    lenBV;          /* BlendV length (aka numMasters)  */
+    FT_Int32*  BV;             /* current blendV (per DICT/glyph) */
+
+  } CFF_BlendRec, *CFF_Blend;
+
+
   typedef struct  CFF_FontRecDictRec_
   {
     FT_UInt    version;
@@ -151,9 +225,17 @@ FT_BEGIN_HEADER
     FT_UShort  num_designs;
     FT_UShort  num_axes;
 
+    /* fields for CFF2 */
+    FT_ULong   vstore_offset;
+    FT_UInt    maxstack;
+
   } CFF_FontRecDictRec, *CFF_FontRecDict;
 
 
+  /* forward reference */
+  typedef struct CFF_SubFontRec_*  CFF_SubFont;
+
+
   typedef struct  CFF_PrivateRec_
   {
     FT_Byte   num_blue_values;
@@ -186,6 +268,10 @@ FT_BEGIN_HEADER
     FT_Pos    default_width;
     FT_Pos    nominal_width;
 
+    /* fields for CFF2 */
+    FT_UInt      vsindex;
+    CFF_SubFont  subfont;
+
   } CFF_PrivateRec, *CFF_Private;
 
 
@@ -213,10 +299,29 @@ FT_BEGIN_HEADER
     CFF_FontRecDictRec  font_dict;
     CFF_PrivateRec      private_dict;
 
-    CFF_IndexRec        local_subrs_index;
-    FT_Byte**           local_subrs; /* array of pointers into Local Subrs INDEX data */
+    /* fields for CFF2 */
+    CFF_BlendRec  blend;      /* current blend vector       */
+    FT_UInt       lenNDV;     /* current length NDV or zero */
+    FT_Fixed*     NDV;        /* ptr to current NDV or NULL */
+
+    /* `blend_stack' is a writable buffer to hold blend results.          */
+    /* This buffer is to the side of the normal cff parser stack;         */
+    /* `cff_parse_blend' and `cff_blend_doBlend' push blend results here. */
+    /* The normal stack then points to these values instead of the DICT   */
+    /* because all other operators in Private DICT clear the stack.       */
+    /* `blend_stack' could be cleared at each operator other than blend.  */
+    /* Blended values are stored as 5-byte fixed point values.            */
+
+    FT_Byte*  blend_stack;    /* base of stack allocation     */
+    FT_Byte*  blend_top;      /* first empty slot             */
+    FT_UInt   blend_used;     /* number of bytes in use       */
+    FT_UInt   blend_alloc;    /* number of bytes allocated    */
 
-  } CFF_SubFontRec, *CFF_SubFont;
+    CFF_IndexRec  local_subrs_index;
+    FT_Byte**     local_subrs; /* array of pointers           */
+                               /* into Local Subrs INDEX data */
+
+  } CFF_SubFontRec;
 
 
 #define CFF_MAX_CID_FONTS  256
@@ -224,16 +329,20 @@ FT_BEGIN_HEADER
 
   typedef struct  CFF_FontRec_
   {
+    FT_Library       library;
     FT_Stream        stream;
-    FT_Memory        memory;
+    FT_Memory        memory;        /* TODO: take this from stream->memory? */
+    FT_ULong         base_offset;   /* offset to start of CFF */
     FT_UInt          num_faces;
     FT_UInt          num_glyphs;
 
     FT_Byte          version_major;
     FT_Byte          version_minor;
     FT_Byte          header_size;
-    FT_Byte          absolute_offsize;
 
+    FT_UInt          top_dict_length;   /* cff2 only */
+
+    FT_Bool          cff2;
 
     CFF_IndexRec     name_index;
     CFF_IndexRec     top_dict_index;
@@ -280,7 +389,9 @@ FT_BEGIN_HEADER
     /* since version 2.4.12 */
     FT_Generic       cf2_instance;
 
-  } CFF_FontRec, *CFF_Font;
+    CFF_VStoreRec    vstore;        /* parsed vstore structure */
+
+  } CFF_FontRec;
 
 
 FT_END_HEADER
index 21397c2..fc2a3cf 100644 (file)
   {
     FT_UNUSED( face );
 
-    FT_MEM_ZERO( loader, sizeof ( *loader ) );
+    FT_ZERO( loader );
   }
 
 
       }
 
       /* we must convert the data section from hexadecimal to binary */
-      if ( FT_ALLOC( face->binary_data, parser->binary_length )         ||
-           cid_hex_to_binary( face->binary_data, parser->binary_length,
-                              parser->data_offset, face )               )
+      if ( FT_ALLOC( face->binary_data, parser->binary_length )    ||
+           FT_SET_ERROR( cid_hex_to_binary( face->binary_data,
+                                            parser->binary_length,
+                                            parser->data_offset,
+                                            face ) )               )
         goto Exit;
 
       FT_Stream_OpenMemory( face->cid_stream,
index cb07c45..1b27b2e 100644 (file)
@@ -65,7 +65,7 @@
     FT_Byte   *arg1, *arg2;
 
 
-    FT_MEM_ZERO( parser, sizeof ( *parser ) );
+    FT_ZERO( parser );
     psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
 
     parser->stream = stream;
                ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 )
           {
             /* save offset of binary data after `StartData' */
-            offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN;
+            offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
             goto Found;
           }
           else if ( p[1] == 's'                                   &&
                     ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 )
           {
-            offset += (FT_ULong)( p - buffer ) + SFNTS_LEN;
+            offset += (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
             goto Found;
           }
         }
index 64141ab..2573656 100644 (file)
       0x10000L,  /* version 1.0 of driver */
       0x20000L,  /* requires FreeType 2.0 */
 
-      0,    /* module-specific interface */
+      NULL,    /* module-specific interface */
 
       cid_driver_init,          /* FT_Module_Constructor  module_init   */
       cid_driver_done,          /* FT_Module_Destructor   module_done   */
 
     cid_slot_load_glyph,        /* FT_Slot_LoadFunc  load_glyph */
 
-    0,                          /* FT_Face_GetKerningFunc   get_kerning  */
-    0,                          /* FT_Face_AttachFunc       attach_file  */
-    0,                          /* FT_Face_GetAdvancesFunc  get_advances */
+    NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
+    NULL,                       /* FT_Face_AttachFunc       attach_file  */
+    NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
 
     cid_size_request,           /* FT_Size_RequestFunc  request_size */
-    0                           /* FT_Size_SelectFunc   select_size  */
+    NULL                        /* FT_Size_SelectFunc   select_size  */
   };
 
 
index 4b5e415..b324bc6 100644 (file)
       FT_INVALID_FORMAT;
 
     func = fmt_funcs_table[format];
-    if ( func == NULL )
+    if ( !func )
       FT_INVALID_FORMAT;
 
     func( p, limit, gxvalid );
       FT_UShort  i;
 
 
-      ft_memset( nGlyphInClass, 0, 256 );
+      FT_MEM_ZERO( nGlyphInClass, 256 );
 
 
       for ( i = 0; i < nGlyphs; i++ )
         break;
       }
 
-      if ( NULL != gxvalid->statetable.entry_validate_func )
+      if ( gxvalid->statetable.entry_validate_func )
         gxvalid->statetable.entry_validate_func( state,
                                                  flags,
                                                  &glyphOffset,
     if ( stateSize > 0xFF )
       FT_INVALID_DATA;
 
-    if ( gxvalid->statetable.optdata_load_func != NULL )
+    if ( gxvalid->statetable.optdata_load_func )
       gxvalid->statetable.optdata_load_func( p, limit, gxvalid );
 
-    if ( gxvalid->statetable.subtable_setup_func != NULL)
+    if ( gxvalid->statetable.subtable_setup_func )
       setup_func = gxvalid->statetable.subtable_setup_func;
     else
       setup_func = gxv_StateTable_subtable_setup;
         goto Exit;
       }
 
-      if ( NULL != gxvalid->xstatetable.entry_validate_func )
+      if ( gxvalid->xstatetable.entry_validate_func )
         gxvalid->xstatetable.entry_validate_func( state,
                                                   flags,
                                                   &glyphOffset,
 
     GXV_TRACE(( "StateTable Subtables\n" ));
 
-    if ( gxvalid->xstatetable.optdata_load_func != NULL )
+    if ( gxvalid->xstatetable.optdata_load_func )
       gxvalid->xstatetable.optdata_load_func( p, limit, gxvalid );
 
-    if ( gxvalid->xstatetable.subtable_setup_func != NULL )
+    if ( gxvalid->xstatetable.subtable_setup_func )
       setup_func = gxvalid->xstatetable.subtable_setup_func;
     else
       setup_func = gxv_XStateTable_subtable_setup;
index e589a7f..32fd84e 100644 (file)
     0x10000L,
     0x20000L,
 
-    0,              /* module-specific interface */
+    NULL,              /* module-specific interface */
 
-    (FT_Module_Constructor)0,
-    (FT_Module_Destructor) 0,
-    (FT_Module_Requester)  gxvalid_get_service
+    (FT_Module_Constructor)NULL,                /* module_init   */
+    (FT_Module_Destructor) NULL,                /* module_done   */
+    (FT_Module_Requester)  gxvalid_get_service  /* get_interface */
   };
 
 
index b83a2b2..1209392 100644 (file)
         FT_INVALID_FORMAT;
 
       func = fmt_funcs_table[type];
-      if ( func == NULL )
+      if ( !func )
         GXV_TRACE(( "morx type %d is reserved\n", type ));
 
       func( p, p + rest, gxvalid );
index a3abe43..b626993 100644 (file)
@@ -98,7 +98,7 @@
         FT_INVALID_FORMAT;
 
       func = fmt_funcs_table[type];
-      if ( func == NULL )
+      if ( !func )
         GXV_TRACE(( "morx type %d is reserved\n", type ));
 
       func( p, p + rest, gxvalid );
index 9cab80e..74b467f 100644 (file)
 
 #else /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
 
/* In this case, we include our own modified sources of the ZLib    */
/* within the "ftgzip" component.  The modifications were necessary */
/* to #include all files without conflicts, as well as preventing   */
/* the definition of "extern" functions that may cause linking      */
/* conflicts when a program is linked with both FreeType and the    */
/* original ZLib.                                                   */
 /* In this case, we include our own modified sources of the ZLib  */
 /* within the `gzip' component.  The modifications were necessary */
 /* to #include all files without conflicts, as well as preventing */
 /* the definition of `extern' functions that may cause linking    */
 /* conflicts when a program is linked with both FreeType and the  */
 /* original ZLib.                                                 */
 
 #ifndef USE_ZLIB_ZCALLOC
 #define MY_ZCALLOC /* prevent all zcalloc() & zfree() in zutil.c */
 #endif
 
+  /* Note that our `zlib.h' includes `ftzconf.h' instead of `zconf.h'; */
+  /* the main reason is that even a global `zlib.h' includes `zconf.h' */
+  /* with                                                              */
+  /*                                                                   */
+  /*   #include "zconf.h"                                              */
+  /*                                                                   */
+  /* instead of the expected                                           */
+  /*                                                                   */
+  /*   #include <zconf.h>                                              */
+  /*                                                                   */
+  /* so that configuration with `FT_CONFIG_OPTION_SYSTEM_ZLIB' might   */
+  /* include the wrong `zconf.h' file, leading to errors.              */
 #include "zlib.h"
 
 #undef  SLOW
     zstream->next_in  = zip->buffer;
 
     if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK ||
-         zstream->next_in == NULL                     )
+         !zstream->next_in                           )
       error = FT_THROW( Invalid_File_Format );
 
   Exit:
diff --git a/reactos/sdk/lib/3rdparty/freetype/src/gzip/ftzconf.h b/reactos/sdk/lib/3rdparty/freetype/src/gzip/ftzconf.h
new file mode 100644 (file)
index 0000000..3abf0ba
--- /dev/null
@@ -0,0 +1,284 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_         z_deflateInit_
+#  define deflate              z_deflate
+#  define deflateEnd           z_deflateEnd
+#  define inflateInit_         z_inflateInit_
+#  define inflate              z_inflate
+#  define inflateEnd           z_inflateEnd
+#  define deflateInit2_        z_deflateInit2_
+#  define deflateSetDictionary z_deflateSetDictionary
+#  define deflateCopy          z_deflateCopy
+#  define deflateReset         z_deflateReset
+#  define deflateParams        z_deflateParams
+#  define inflateInit2_        z_inflateInit2_
+#  define inflateSetDictionary z_inflateSetDictionary
+#  define inflateSync          z_inflateSync
+#  define inflateSyncPoint     z_inflateSyncPoint
+#  define inflateReset         z_inflateReset
+#  define compress             z_compress
+#  define compress2            z_compress2
+#  define uncompress           z_uncompress
+#  define adler32              z_adler32
+#  define crc32                z_crc32
+#  define get_crc_table        z_get_crc_table
+
+#  define Byte   z_Byte
+#  define uInt   z_uInt
+#  define uLong  z_uLong
+#  define Bytef  z_Bytef
+#  define charf  z_charf
+#  define intf   z_intf
+#  define uIntf  z_uIntf
+#  define uLongf z_uLongf
+#  define voidpf z_voidpf
+#  define voidp  z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+#  define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+#  ifndef __32BIT__
+#    define __32BIT__
+#  endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+
+/* WinCE doesn't have errno.h */
+#ifdef _WIN32_WCE
+#  define NO_ERRNO_H
+#endif
+
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32))  && !defined(STDC)
+#  define STDC
+#endif
+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
+#  ifndef STDC
+#    define STDC
+#  endif
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Old Borland C and LCC incorrectly complains about missing returns: */
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+#  define NEED_DUMMY_RETURN
+#endif
+
+#if defined(__LCC__)
+#  define  NEED_DUMMY_RETURN
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+   /* MSC small or medium model */
+#  define SMALL_MEDIUM
+#  ifdef _MSC_VER
+#    define FAR _far
+#  else
+#    define FAR far
+#  endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+#  ifndef __32BIT__
+#    define SMALL_MEDIUM
+#    define FAR _far
+#  endif
+#endif
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if defined(ZLIB_DLL)
+#  if defined(_WINDOWS) || defined(WINDOWS)
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+#    define ZEXPORT(x)  x WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA(x)  x WINAPIV
+#    else
+#      define ZEXPORTVA(x)  x FAR _cdecl _export
+#    endif
+#  endif
+#  if defined (__BORLANDC__)
+#    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
+#      include <windows.h>
+#      define ZEXPORT(x) x __declspec(dllexport) WINAPI
+#      define ZEXPORTRVA(x)  x __declspec(dllexport) WINAPIV
+#    else
+#      if defined (_Windows) && defined (__DLL__)
+#        define ZEXPORT(x) x _export
+#        define ZEXPORTVA(x) x _export
+#      endif
+#    endif
+#  endif
+#endif
+
+
+#ifndef ZEXPORT
+#  define ZEXPORT(x)   static x
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA(x)   static x
+#endif
+#ifndef ZEXTERN
+#  define ZEXTERN(x) static x
+#endif
+#ifndef ZEXTERNDEF
+#  define ZEXTERNDEF(x)  static x
+#endif
+
+#ifndef FAR
+#   define FAR
+#endif
+
+#if !defined(MACOS) && !defined(TARGET_OS_MAC)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void FAR *voidpf;
+   typedef void     *voidp;
+#else
+   typedef Byte FAR *voidpf;
+   typedef Byte     *voidp;
+#endif
+
+#ifdef HAVE_UNISTD_H
+#  include <sys/types.h> /* for off_t */
+#  include <unistd.h>    /* for SEEK_* and off_t */
+#  define z_off_t  off_t
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define  z_off_t long
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(inflate_blocks,"INBL")
+#   pragma map(inflate_blocks_new,"INBLNE")
+#   pragma map(inflate_blocks_free,"INBLFR")
+#   pragma map(inflate_blocks_reset,"INBLRE")
+#   pragma map(inflate_codes_free,"INCOFR")
+#   pragma map(inflate_codes,"INCO")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_flush,"INFLU")
+#   pragma map(inflate_mask,"INMA")
+#   pragma map(inflate_set_dictionary,"INSEDI2")
+#   pragma map(inflate_copyright,"INCOPY")
+#   pragma map(inflate_trees_bits,"INTRBI")
+#   pragma map(inflate_trees_dynamic,"INTRDY")
+#   pragma map(inflate_trees_fixed,"INTRFI")
+#   pragma map(inflate_trees_free,"INTRFR")
+#endif
+
+#endif /* _ZCONF_H */
index d361ff4..a4e82c6 100644 (file)
@@ -31,7 +31,7 @@
 #ifndef _ZLIB_H
 #define _ZLIB_H
 
-#include "zconf.h"
+#include "ftzconf.h"
 
 #ifdef __cplusplus
 extern "C" {
index 9e66ba9..a2cc453 100644 (file)
       {
         while ( state->stack_top > 0 )
         {
-          --state->stack_top;
+          state->stack_top--;
 
           if ( buffer )
             buffer[result] = state->stack[state->stack_top];
index 2e88e10..6a68444 100644 (file)
@@ -68,7 +68,7 @@
 
         OTV_LIMIT_CHECK( GlyphCount * 2 );        /* GlyphArray */
 
-        for ( i = 0; i < GlyphCount; ++i )
+        for ( i = 0; i < GlyphCount; i++ )
         {
           FT_UInt  gid;
 
index 6c785b6..47e2f87 100644 (file)
@@ -60,7 +60,7 @@
     table_size = 2 * ( 56 + 51 );
 
     p += 4 * 2;                 /* First 4 constants have no device tables */
-    for ( i = 0; i < 51; ++i )
+    for ( i = 0; i < 51; i++ )
     {
       p += 2;                                            /* skip the value */
       OTV_OPTIONAL_OFFSET( DeviceTableOffset );
     OTV_SIZE_CHECK( Coverage );
     otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)cnt );
 
-    for ( i = 0; i < cnt; ++i )
+    for ( i = 0; i < cnt; i++ )
     {
       p += 2;                                            /* Skip the value */
       OTV_OPTIONAL_OFFSET( DeviceTableOffset );
     table_size = 4 + 4 * cnt;
 
     /* Heights */
-    for ( i = 0; i < cnt; ++i )
+    for ( i = 0; i < cnt; i++ )
     {
       p += 2;                                            /* Skip the value */
       OTV_OPTIONAL_OFFSET( DeviceTableOffset );
     }
 
     /* One more Kerning value */
-    for ( i = 0; i < cnt + 1; ++i )
+    for ( i = 0; i < cnt + 1; i++ )
     {
       p += 2;                                            /* Skip the value */
       OTV_OPTIONAL_OFFSET( DeviceTableOffset );
     OTV_SIZE_CHECK( Coverage );
     otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)cnt );
 
-    for ( i = 0; i < cnt; ++i )
+    for ( i = 0; i < cnt; i++ )
     {
-      for ( j = 0; j < 4; ++j )
+      for ( j = 0; j < 4; j++ )
       {
         OTV_OPTIONAL_OFFSET( MKRecordOffset );
         OTV_SIZE_CHECK( MKRecordOffset );
     if ( DeviceTableOffset )
       otv_Device_validate( table + DeviceTableOffset, otvalid );
 
-    for ( i = 0; i < pcnt; ++i )
+    for ( i = 0; i < pcnt; i++ )
     {
       FT_UInt  gid;
 
     OTV_LIMIT_CHECK( 4 * vcnt );
     table_size = 4 + 4 * vcnt;
 
-    for ( i = 0; i < vcnt; ++i )
+    for ( i = 0; i < vcnt; i++ )
     {
       FT_UInt  gid;
 
     if ( HCoverage )
       otv_Coverage_validate( table + HCoverage, otvalid, (FT_Int)hcnt );
 
-    for ( i = 0; i < vcnt; ++i )
+    for ( i = 0; i < vcnt; i++ )
     {
       OTV_OPTIONAL_OFFSET( Offset );
       OTV_SIZE_CHECK( Offset );
       otv_MathGlyphConstruction_validate( table + Offset, otvalid );
     }
 
-    for ( i = 0; i < hcnt; ++i )
+    for ( i = 0; i < hcnt; i++ )
     {
       OTV_OPTIONAL_OFFSET( Offset );
       OTV_SIZE_CHECK( Offset );
index 972bd1b..aed5e9c 100644 (file)
     0x10000L,
     0x20000L,
 
-    0,              /* module-specific interface */
+    NULL,              /* module-specific interface */
 
-    (FT_Module_Constructor)0,
-    (FT_Module_Destructor) 0,
-    (FT_Module_Requester)  otvalid_get_service
+    (FT_Module_Constructor)NULL,                /* module_init   */
+    (FT_Module_Destructor) NULL,                /* module_done   */
+    (FT_Module_Requester)  otvalid_get_service  /* get_interface */
   };
 
 
index 0996d10..d60cc3e 100644 (file)
@@ -492,8 +492,6 @@ THE SOFTWARE.
     PCF_Metric  metric;
     FT_ULong    bytes;
 
-    FT_UNUSED( load_flags );
-
 
     FT_TRACE1(( "PCF_Glyph_Load: glyph index %d\n", glyph_index ));
 
@@ -550,6 +548,24 @@ THE SOFTWARE.
       return FT_THROW( Invalid_File_Format );
     }
 
+    slot->format      = FT_GLYPH_FORMAT_BITMAP;
+    slot->bitmap_left = metric->leftSideBearing;
+    slot->bitmap_top  = metric->ascent;
+
+    slot->metrics.horiAdvance  = (FT_Pos)( metric->characterWidth * 64 );
+    slot->metrics.horiBearingX = (FT_Pos)( metric->leftSideBearing * 64 );
+    slot->metrics.horiBearingY = (FT_Pos)( metric->ascent * 64 );
+    slot->metrics.width        = (FT_Pos)( ( metric->rightSideBearing -
+                                             metric->leftSideBearing ) * 64 );
+    slot->metrics.height       = (FT_Pos)( bitmap->rows * 64 );
+
+    ft_synthesize_vertical_metrics( &slot->metrics,
+                                    ( face->accel.fontAscent +
+                                      face->accel.fontDescent ) * 64 );
+
+    if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY )
+      goto Exit;
+
     /* XXX: to do: are there cases that need repadding the bitmap? */
     bytes = (FT_ULong)bitmap->pitch * bitmap->rows;
 
@@ -582,21 +598,6 @@ THE SOFTWARE.
       }
     }
 
-    slot->format      = FT_GLYPH_FORMAT_BITMAP;
-    slot->bitmap_left = metric->leftSideBearing;
-    slot->bitmap_top  = metric->ascent;
-
-    slot->metrics.horiAdvance  = (FT_Pos)( metric->characterWidth * 64 );
-    slot->metrics.horiBearingX = (FT_Pos)( metric->leftSideBearing * 64 );
-    slot->metrics.horiBearingY = (FT_Pos)( metric->ascent * 64 );
-    slot->metrics.width        = (FT_Pos)( ( metric->rightSideBearing -
-                                             metric->leftSideBearing ) * 64 );
-    slot->metrics.height       = (FT_Pos)( bitmap->rows * 64 );
-
-    ft_synthesize_vertical_metrics( &slot->metrics,
-                                    ( face->accel.fontAscent +
-                                      face->accel.fontDescent ) * 64 );
-
   Exit:
     return error;
   }
@@ -617,7 +618,7 @@ THE SOFTWARE.
 
 
     prop = pcf_find_property( face, prop_name );
-    if ( prop != NULL )
+    if ( prop )
     {
       if ( prop->isString )
       {
@@ -700,10 +701,10 @@ THE SOFTWARE.
       0x10000L,
       0x20000L,
 
-      0,    /* module-specific interface */
+      NULL,    /* module-specific interface */
 
-      0,                        /* FT_Module_Constructor  module_init   */
-      0,                        /* FT_Module_Destructor   module_done   */
+      NULL,                     /* FT_Module_Constructor  module_init   */
+      NULL,                     /* FT_Module_Destructor   module_done   */
       pcf_driver_requester      /* FT_Module_Requester    get_interface */
     },
 
@@ -713,16 +714,16 @@ THE SOFTWARE.
 
     PCF_Face_Init,              /* FT_Face_InitFunc  init_face */
     PCF_Face_Done,              /* FT_Face_DoneFunc  done_face */
-    0,                          /* FT_Size_InitFunc  init_size */
-    0,                          /* FT_Size_DoneFunc  done_size */
-    0,                          /* FT_Slot_InitFunc  init_slot */
-    0,                          /* FT_Slot_DoneFunc  done_slot */
+    NULL,                       /* FT_Size_InitFunc  init_size */
+    NULL,                       /* FT_Size_DoneFunc  done_size */
+    NULL,                       /* FT_Slot_InitFunc  init_slot */
+    NULL,                       /* FT_Slot_DoneFunc  done_slot */
 
     PCF_Glyph_Load,             /* FT_Slot_LoadFunc  load_glyph */
 
-    0,                          /* FT_Face_GetKerningFunc   get_kerning  */
-    0,                          /* FT_Face_AttachFunc       attach_file  */
-    0,                          /* FT_Face_GetAdvancesFunc  get_advances */
+    NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
+    NULL,                       /* FT_Face_AttachFunc       attach_file  */
+    NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
 
     PCF_Size_Request,           /* FT_Size_RequestFunc  request_size */
     PCF_Size_Select             /* FT_Size_SelectFunc   select_size  */
index a86b45d..95ee570 100644 (file)
@@ -109,13 +109,18 @@ THE SOFTWARE.
     if ( stream->size < 16 )
       return FT_THROW( Invalid_File_Format );
 
-    /* we need 16 bytes per TOC entry */
-    if ( toc->count > stream->size >> 4 )
+    /* We need 16 bytes per TOC entry.  Additionally, as a */
+    /* heuristic protection against gzip bombs (i.e., very */
+    /* small input files that expand to insanely large     */
+    /* files), we limit the number of TOC entries to 1024. */
+    if ( toc->count > stream->size >> 4 ||
+         toc->count > 1024              )
     {
       FT_TRACE0(( "pcf_read_TOC: adjusting number of tables"
                   " (from %d to %d)\n",
-                  toc->count, stream->size >> 4 ));
-      toc->count = stream->size >> 4;
+                  toc->count,
+                  FT_MIN( stream->size >> 4, 1024 ) ));
+      toc->count = FT_MIN( stream->size >> 4, 1024 );
     }
 
     if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
@@ -319,7 +324,7 @@ THE SOFTWARE.
 
 
       /* parsing normal metrics */
-      fields = PCF_BYTE_ORDER( format ) == MSBFirst
+      fields = ( PCF_BYTE_ORDER( format ) == MSBFirst )
                ? pcf_metric_msb_header
                : pcf_metric_header;
 
@@ -1156,7 +1161,7 @@ THE SOFTWARE.
 
         len = lengths[nn];
 
-        if ( src == NULL )
+        if ( !src )
           continue;
 
         /* separate elements with a space */
@@ -1260,14 +1265,63 @@ THE SOFTWARE.
       if ( face->accel.constantWidth )
         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
 
-      if ( ( error = pcf_interpret_style( face ) ) != 0 )
-         goto Exit;
+      if ( FT_SET_ERROR( pcf_interpret_style( face ) ) )
+        goto Exit;
 
       prop = pcf_find_property( face, "FAMILY_NAME" );
       if ( prop && prop->isString )
       {
-        if ( FT_STRDUP( root->family_name, prop->value.atom ) )
-          goto Exit;
+        /* Prepend the foundry name plus a space to the family name.      */
+        /* There are many fonts just called `Fixed' which look completely */
+        /* different, and which have nothing to do with each other.  When */
+        /* selecting `Fixed' in KDE or Gnome one gets results that appear */
+        /* rather random, the style changes often if one changes the size */
+        /* and one cannot select some fonts at all.                       */
+        /*                                                                */
+        /* We also check whether we have `wide' characters; all put       */
+        /* together, we get family names like `Sony Fixed' or `Misc Fixed */
+        /* Wide'.                                                         */
+        PCF_Property  foundry_prop, point_size_prop, average_width_prop;
+
+        int  l    = ft_strlen( prop->value.atom ) + 1;
+        int  wide = 0;
+
+
+        foundry_prop       = pcf_find_property( face, "FOUNDRY" );
+        point_size_prop    = pcf_find_property( face, "POINT_SIZE" );
+        average_width_prop = pcf_find_property( face, "AVERAGE_WIDTH" );
+
+        if ( point_size_prop && average_width_prop )
+        {
+          if ( average_width_prop->value.l >= point_size_prop->value.l )
+          {
+            /* This font is at least square shaped or even wider */
+            wide = 1;
+            l   += ft_strlen( " Wide" );
+          }
+        }
+
+        if ( foundry_prop && foundry_prop->isString )
+        {
+          l += ft_strlen( foundry_prop->value.atom ) + 1;
+
+          if ( FT_NEW_ARRAY( root->family_name, l ) )
+            goto Exit;
+
+          ft_strcpy( root->family_name, foundry_prop->value.atom );
+          ft_strcat( root->family_name, " " );
+          ft_strcat( root->family_name, prop->value.atom );
+        }
+        else
+        {
+          if ( FT_NEW_ARRAY( root->family_name, l ) )
+            goto Exit;
+
+          ft_strcpy( root->family_name, prop->value.atom );
+        }
+
+        if ( wide )
+          ft_strcat( root->family_name, " Wide" );
       }
       else
         root->family_name = NULL;
@@ -1290,7 +1344,7 @@ THE SOFTWARE.
         FT_Short         resolution_x = 0, resolution_y = 0;
 
 
-        FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
+        FT_ZERO( bsize );
 
         /* for simplicity, we take absolute values of integer properties */
 
index a1439c2..f1f9c53 100644 (file)
   {
     sizeof ( PFR_CMapRec ),
 
-    (FT_CMap_InitFunc)     pfr_cmap_init,
-    (FT_CMap_DoneFunc)     pfr_cmap_done,
-    (FT_CMap_CharIndexFunc)pfr_cmap_char_index,
-    (FT_CMap_CharNextFunc) pfr_cmap_char_next,
-
-    NULL, NULL, NULL, NULL, NULL
+    (FT_CMap_InitFunc)     pfr_cmap_init,        /* init       */
+    (FT_CMap_DoneFunc)     pfr_cmap_done,        /* done       */
+    (FT_CMap_CharIndexFunc)pfr_cmap_char_index,  /* char_index */
+    (FT_CMap_CharNextFunc) pfr_cmap_char_next,   /* char_next  */
+
+    (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+    (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+    (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+    (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+    (FT_CMap_VariantCharListFunc) NULL   /* variantchar_list */
   };
 
 
index b81c15e..2316cd3 100644 (file)
       0x10000L,
       0x20000L,
 
-      0,    /* module-specific interface */
+      NULL,    /* module-specific interface */
 
-      0,                        /* FT_Module_Constructor  module_init   */
-      0,                        /* FT_Module_Destructor   module_done   */
+      NULL,                     /* FT_Module_Constructor  module_init   */
+      NULL,                     /* FT_Module_Destructor   module_done   */
       pfr_get_service           /* FT_Module_Requester    get_interface */
     },
 
 
     pfr_face_init,              /* FT_Face_InitFunc  init_face */
     pfr_face_done,              /* FT_Face_DoneFunc  done_face */
-    0,                          /* FT_Size_InitFunc  init_size */
-    0,                          /* FT_Size_DoneFunc  done_size */
+    NULL,                       /* FT_Size_InitFunc  init_size */
+    NULL,                       /* FT_Size_DoneFunc  done_size */
     pfr_slot_init,              /* FT_Slot_InitFunc  init_slot */
     pfr_slot_done,              /* FT_Slot_DoneFunc  done_slot */
 
     pfr_slot_load,              /* FT_Slot_LoadFunc  load_glyph */
 
     pfr_get_kerning,            /* FT_Face_GetKerningFunc   get_kerning  */
-    0,                          /* FT_Face_AttachFunc       attach_file  */
-    0,                          /* FT_Face_GetAdvancesFunc  get_advances */
+    NULL,                       /* FT_Face_AttachFunc       attach_file  */
+    NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
 
-    0,                          /* FT_Size_RequestFunc  request_size */
-    0,                          /* FT_Size_SelectFunc   select_size  */
+    NULL,                       /* FT_Size_RequestFunc  request_size */
+    NULL,                       /* FT_Size_SelectFunc   select_size  */
   };
 
 
index e509e70..aad759a 100644 (file)
     FT_UInt    len    = (FT_UInt)( limit - p );
 
 
-    if ( phy_font->font_id != NULL )
+    if ( phy_font->font_id )
       goto Exit;
 
     if ( FT_ALLOC( phy_font->font_id, len + 1 ) )
     FT_Memory  memory = phy_font->memory;
 
 
-    if ( phy_font->vertical.stem_snaps != NULL )
+    if ( phy_font->vertical.stem_snaps )
       goto Exit;
 
     PFR_CHECK( 1 );
index 769a3b6..0491d13 100644 (file)
        * nothing.
        */
       pfrface->family_name = phy_font->family_name;
-      if ( pfrface->family_name == NULL )
+      if ( !pfrface->family_name )
         pfrface->family_name = phy_font->font_id;
 
       /* note that the style name can be NULL in certain PFR fonts,
     /* try to load an embedded bitmap */
     if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 )
     {
-      error = pfr_slot_load_bitmap( slot, size, gindex );
-      if ( error == 0 )
+      error = pfr_slot_load_bitmap(
+                slot,
+                size,
+                gindex,
+                ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) != 0 );
+      if ( !error )
         goto Exit;
     }
 
index 144f50c..f9dbf73 100644 (file)
   FT_LOCAL( FT_Error )
   pfr_slot_load_bitmap( PFR_Slot  glyph,
                         PFR_Size  size,
-                        FT_UInt   glyph_index )
+                        FT_UInt   glyph_index,
+                        FT_Bool   metrics_only )
   {
     FT_Error     error;
     PFR_Face     face   = (PFR_Face) glyph->root.face;
         glyph->root.bitmap_left = (FT_Int)xpos;
         glyph->root.bitmap_top  = (FT_Int)( ypos + (FT_Long)ysize );
 
+        if ( metrics_only )
+          goto Exit1;
+
         /* Allocate and read bitmap data */
         {
           FT_ULong  len = (FT_ULong)glyph->root.bitmap.pitch * ysize;
index 94ead28..676ad55 100644 (file)
@@ -26,7 +26,8 @@ FT_BEGIN_HEADER
   FT_LOCAL( FT_Error )
   pfr_slot_load_bitmap( PFR_Slot  glyph,
                         PFR_Size  size,
-                        FT_UInt   glyph_index );
+                        FT_UInt   glyph_index,
+                        FT_Bool   metrics_only );
 
 FT_END_HEADER
 
index 80805e6..b1b8b19 100644 (file)
   FT_CALLBACK_TABLE_DEF
   const PS_Table_FuncsRec  ps_table_funcs =
   {
-    ps_table_new,
-    ps_table_done,
-    ps_table_add,
-    ps_table_release
+    ps_table_new,     /* init    */
+    ps_table_done,    /* done    */
+    ps_table_add,     /* add     */
+    ps_table_release  /* release */
   };
 
 
   FT_CALLBACK_TABLE_DEF
   const PS_Parser_FuncsRec  ps_parser_funcs =
   {
-    ps_parser_init,
-    ps_parser_done,
-    ps_parser_skip_spaces,
-    ps_parser_skip_PS_token,
-    ps_parser_to_int,
-    ps_parser_to_fixed,
-    ps_parser_to_bytes,
-    ps_parser_to_coord_array,
-    ps_parser_to_fixed_array,
-    ps_parser_to_token,
-    ps_parser_to_token_array,
-    ps_parser_load_field,
-    ps_parser_load_field_table
+    ps_parser_init,             /* init             */
+    ps_parser_done,             /* done             */
+
+    ps_parser_skip_spaces,      /* skip_spaces      */
+    ps_parser_skip_PS_token,    /* skip_PS_token    */
+
+    ps_parser_to_int,           /* to_int           */
+    ps_parser_to_fixed,         /* to_fixed         */
+    ps_parser_to_bytes,         /* to_bytes         */
+    ps_parser_to_coord_array,   /* to_coord_array   */
+    ps_parser_to_fixed_array,   /* to_fixed_array   */
+    ps_parser_to_token,         /* to_token         */
+    ps_parser_to_token_array,   /* to_token_array   */
+
+    ps_parser_load_field,       /* load_field       */
+    ps_parser_load_field_table  /* load_field_table */
   };
 
 
   FT_CALLBACK_TABLE_DEF
   const T1_Builder_FuncsRec  t1_builder_funcs =
   {
-    t1_builder_init,
-    t1_builder_done,
-    t1_builder_check_points,
-    t1_builder_add_point,
-    t1_builder_add_point1,
-    t1_builder_add_contour,
-    t1_builder_start_point,
-    t1_builder_close_contour
+    t1_builder_init,          /* init */
+    t1_builder_done,          /* done */
+
+    t1_builder_check_points,  /* check_points  */
+    t1_builder_add_point,     /* add_point     */
+    t1_builder_add_point1,    /* add_point1    */
+    t1_builder_add_contour,   /* add_contour   */
+    t1_builder_start_point,   /* start_point   */
+    t1_builder_close_contour  /* close_contour */
   };
 
 
   FT_CALLBACK_TABLE_DEF
   const T1_Decoder_FuncsRec  t1_decoder_funcs =
   {
-    t1_decoder_init,
-    t1_decoder_done,
-    t1_decoder_parse_charstrings
+    t1_decoder_init,              /* init              */
+    t1_decoder_done,              /* done              */
+    t1_decoder_parse_charstrings  /* parse_charstrings */
   };
 
 
@@ -83,9 +87,9 @@
   FT_CALLBACK_TABLE_DEF
   const AFM_Parser_FuncsRec  afm_parser_funcs =
   {
-    afm_parser_init,
-    afm_parser_done,
-    afm_parser_parse
+    afm_parser_init,  /* init  */
+    afm_parser_done,  /* done  */
+    afm_parser_parse  /* parse */
   };
 #endif
 
 
     &psaux_interface,  /* module-specific interface */
 
-    (FT_Module_Constructor)0,
-    (FT_Module_Destructor) 0,
-    (FT_Module_Requester)  0
+    (FT_Module_Constructor)NULL,  /* module_init   */
+    (FT_Module_Destructor) NULL,  /* module_done   */
+    (FT_Module_Requester)  NULL   /* get_interface */
   };
 
 
index f208b5f..6e528d4 100644 (file)
       FT_Byte  c = *cur;
 
 
-      ++cur;
+      cur++;
 
       if ( c == '\\' )
       {
         case '\\':
         case '(':
         case ')':
-          ++cur;
+          cur++;
           break;
 
         default:
           /* skip octal escape or ignore backslash */
-          for ( i = 0; i < 3 && cur < limit; ++i )
+          for ( i = 0; i < 3 && cur < limit; i++ )
           {
             if ( !IS_OCTAL_DIGIT( *cur ) )
               break;
 
-            ++cur;
+            cur++;
           }
         }
       }
 
     FT_ASSERT( **acur == '{' );
 
-    for ( cur = *acur; cur < limit && error == FT_Err_Ok; ++cur )
+    for ( cur = *acur; cur < limit && error == FT_Err_Ok; cur++ )
     {
       switch ( *cur )
       {
       case '{':
-        ++embed;
+        embed++;
         break;
 
       case '}':
-        --embed;
+        embed--;
         if ( embed == 0 )
         {
-          ++cur;
+          cur++;
           goto end;
         }
         break;
       /* ************ otherwise, it is any token **************/
     default:
       token->start = cur;
-      token->type  = ( *cur == '/' ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY );
+      token->type  = ( *cur == '/' ) ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY;
       ps_parser_skip_PS_token( parser );
       cur = parser->cursor;
       if ( !parser->error )
         if ( !token.type )
           break;
 
-        if ( tokens != NULL && cur < limit )
+        if ( tokens && cur < limit )
           *cur = token;
 
         cur++;
 
       old_cur = cur;
 
-      if ( coords != NULL && count >= max_coords )
+      if ( coords && count >= max_coords )
         break;
 
       /* call PS_Conv_ToFixed() even if coords == NULL */
       /* to properly parse number at `cur'             */
-      *( coords != NULL ? &coords[count] : &dummy ) =
+      *( coords ? &coords[count] : &dummy ) =
         (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
 
       if ( old_cur == cur )
 
       old_cur = cur;
 
-      if ( values != NULL && count >= max_values )
+      if ( values && count >= max_values )
         break;
 
       /* call PS_Conv_ToFixed() even if coords == NULL */
       /* to properly parse number at `cur'             */
-      *( values != NULL ? &values[count] : &dummy ) =
+      *( values ? &values[count] : &dummy ) =
         PS_Conv_ToFixed( &cur, limit, power_ten );
 
       if ( old_cur == cur )
 
           /* for this to work (FT_String**)q must have been */
           /* initialized to NULL                            */
-          if ( *(FT_String**)q != NULL )
+          if ( *(FT_String**)q )
           {
             FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
                         field->ident ));
index 43abb98..7b289b7 100644 (file)
@@ -45,7 +45,7 @@
     cmap->code_to_sid   = is_expert ? psnames->adobe_expert_encoding
                                     : psnames->adobe_std_encoding;
 
-    FT_ASSERT( cmap->code_to_sid != NULL );
+    FT_ASSERT( cmap->code_to_sid );
   }
 
 
   {
     sizeof ( T1_CMapStdRec ),
 
-    (FT_CMap_InitFunc)     t1_cmap_standard_init,
-    (FT_CMap_DoneFunc)     t1_cmap_std_done,
-    (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,
-    (FT_CMap_CharNextFunc) t1_cmap_std_char_next,
+    (FT_CMap_InitFunc)     t1_cmap_standard_init,   /* init       */
+    (FT_CMap_DoneFunc)     t1_cmap_std_done,        /* done       */
+    (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,  /* char_index */
+    (FT_CMap_CharNextFunc) t1_cmap_std_char_next,   /* char_next  */
 
-    NULL, NULL, NULL, NULL, NULL
+    (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+    (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+    (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+    (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+    (FT_CMap_VariantCharListFunc) NULL   /* variantchar_list */
   };
 
 
   {
     sizeof ( T1_CMapStdRec ),
 
-    (FT_CMap_InitFunc)     t1_cmap_expert_init,
-    (FT_CMap_DoneFunc)     t1_cmap_std_done,
-    (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,
-    (FT_CMap_CharNextFunc) t1_cmap_std_char_next,
+    (FT_CMap_InitFunc)     t1_cmap_expert_init,     /* init       */
+    (FT_CMap_DoneFunc)     t1_cmap_std_done,        /* done       */
+    (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,  /* char_index */
+    (FT_CMap_CharNextFunc) t1_cmap_std_char_next,   /* char_next  */
 
-    NULL, NULL, NULL, NULL, NULL
+    (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+    (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+    (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+    (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+    (FT_CMap_VariantCharListFunc) NULL   /* variantchar_list */
   };
 
 
     cmap->count   = (FT_UInt)encoding->code_last - cmap->first;
     cmap->indices = encoding->char_index;
 
-    FT_ASSERT( cmap->indices != NULL );
+    FT_ASSERT( cmap->indices );
     FT_ASSERT( encoding->code_first <= encoding->code_last );
 
     return 0;
     FT_UInt32  char_code = *pchar_code;
 
 
-    ++char_code;
+    char_code++;
 
     if ( char_code < cmap->first )
       char_code = cmap->first;
   {
     sizeof ( T1_CMapCustomRec ),
 
-    (FT_CMap_InitFunc)     t1_cmap_custom_init,
-    (FT_CMap_DoneFunc)     t1_cmap_custom_done,
-    (FT_CMap_CharIndexFunc)t1_cmap_custom_char_index,
-    (FT_CMap_CharNextFunc) t1_cmap_custom_char_next,
+    (FT_CMap_InitFunc)     t1_cmap_custom_init,        /* init       */
+    (FT_CMap_DoneFunc)     t1_cmap_custom_done,        /* done       */
+    (FT_CMap_CharIndexFunc)t1_cmap_custom_char_index,  /* char_index */
+    (FT_CMap_CharNextFunc) t1_cmap_custom_char_next,   /* char_next  */
 
-    NULL, NULL, NULL, NULL, NULL
+    (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+    (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+    (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+    (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+    (FT_CMap_VariantCharListFunc) NULL   /* variantchar_list */
   };
 
 
   {
     sizeof ( PS_UnicodesRec ),
 
-    (FT_CMap_InitFunc)     t1_cmap_unicode_init,
-    (FT_CMap_DoneFunc)     t1_cmap_unicode_done,
-    (FT_CMap_CharIndexFunc)t1_cmap_unicode_char_index,
-    (FT_CMap_CharNextFunc) t1_cmap_unicode_char_next,
+    (FT_CMap_InitFunc)     t1_cmap_unicode_init,        /* init       */
+    (FT_CMap_DoneFunc)     t1_cmap_unicode_done,        /* done       */
+    (FT_CMap_CharIndexFunc)t1_cmap_unicode_char_index,  /* char_index */
+    (FT_CMap_CharNextFunc) t1_cmap_unicode_char_next,   /* char_next  */
 
-    NULL, NULL, NULL, NULL, NULL
+    (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+    (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+    (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+    (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+    (FT_CMap_VariantCharListFunc) NULL   /* variantchar_list */
   };
 
 
index 98f6ce1..1cd9d73 100644 (file)
                ( decoder->buildchar == NULL )  );
 
     if ( decoder->buildchar && decoder->len_buildchar > 0 )
-      ft_memset( &decoder->buildchar[0],
-                 0,
-                 sizeof ( decoder->buildchar[0] ) * decoder->len_buildchar );
+      FT_ARRAY_ZERO( decoder->buildchar, decoder->len_buildchar );
 
     FT_TRACE4(( "\n"
                 "Start charstring\n" ));
           if ( arg_cnt != 3 )
             goto Unexpected_OtherSubr;
 
-          if ( decoder->flex_state       == 0 ||
+          if ( !decoder->flex_state           ||
                decoder->num_flex_vectors != 7 )
           {
             FT_ERROR(( "t1_decoder_parse_charstrings:"
           if ( arg_cnt != 0 )
             goto Unexpected_OtherSubr;
 
+          if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
+               FT_SET_ERROR( t1_builder_check_points( builder, 6 ) )   )
+            goto Fail;
+
           decoder->flex_state        = 1;
           decoder->num_flex_vectors  = 0;
-          if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != FT_Err_Ok                                   ||
-               ( error = t1_builder_check_points( builder, 6 ) )
-                 != FT_Err_Ok                                   )
-            goto Fail;
           break;
 
         case 2:                     /* add flex vectors */
             if ( arg_cnt != 0 )
               goto Unexpected_OtherSubr;
 
-            if ( decoder->flex_state == 0 )
+            if ( !decoder->flex_state )
             {
               FT_ERROR(( "t1_decoder_parse_charstrings:"
                          " missing flex start\n" ));
             PS_Blend  blend = decoder->blend;
 
 
-            if ( arg_cnt != 1 || blend == NULL )
+            if ( arg_cnt != 1 || !blend )
               goto Unexpected_OtherSubr;
 
             idx = Fix2Int( top[0] );
             PS_Blend  blend = decoder->blend;
 
 
-            if ( arg_cnt != 2 || blend == NULL )
+            if ( arg_cnt != 2 || !blend )
               goto Unexpected_OtherSubr;
 
             idx = Fix2Int( top[1] );
             PS_Blend  blend = decoder->blend;
 
 
-            if ( arg_cnt != 1 || blend == NULL )
+            if ( arg_cnt != 1 || !blend )
               goto Unexpected_OtherSubr;
 
             idx = Fix2Int( top[0] );
 
             FT_TRACE4(( "BuildCharArray = [ " ));
 
-            for ( i = 0; i < decoder->len_buildchar; ++i )
+            for ( i = 0; i < decoder->len_buildchar; i++ )
               FT_TRACE4(( "%d ", decoder->buildchar[i] ));
 
             FT_TRACE4(( "]\n" ));
         case op_hlineto:
           FT_TRACE4(( " hlineto" ));
 
-          if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != FT_Err_Ok )
+          if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
             goto Fail;
 
           x += top[0];
         case op_hvcurveto:
           FT_TRACE4(( " hvcurveto" ));
 
-          if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != FT_Err_Ok                                   ||
-               ( error = t1_builder_check_points( builder, 3 ) )
-                 != FT_Err_Ok                                   )
+          if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
+               FT_SET_ERROR( t1_builder_check_points( builder, 3 ) )   )
             goto Fail;
 
           x += top[0];
         case op_rlineto:
           FT_TRACE4(( " rlineto" ));
 
-          if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != FT_Err_Ok )
+          if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
             goto Fail;
 
           x += top[0];
           y += top[1];
 
         Add_Line:
-          if ( ( error = t1_builder_add_point1( builder, x, y ) )
-                 != FT_Err_Ok )
+          if ( FT_SET_ERROR( t1_builder_add_point1( builder, x, y ) ) )
             goto Fail;
           break;
 
         case op_rrcurveto:
           FT_TRACE4(( " rrcurveto" ));
 
-          if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != FT_Err_Ok                                   ||
-               ( error = t1_builder_check_points( builder, 3 ) )
-                 != FT_Err_Ok                                   )
+          if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
+               FT_SET_ERROR( t1_builder_check_points( builder, 3 ) )   )
             goto Fail;
 
           x += top[0];
         case op_vhcurveto:
           FT_TRACE4(( " vhcurveto" ));
 
-          if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != FT_Err_Ok                                   ||
-               ( error = t1_builder_check_points( builder, 3 ) )
-                 != FT_Err_Ok                                   )
+          if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ||
+               FT_SET_ERROR( t1_builder_check_points( builder, 3 ) )   )
             goto Fail;
 
           y += top[0];
         case op_vlineto:
           FT_TRACE4(( " vlineto" ));
 
-          if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != FT_Err_Ok )
+          if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) )
             goto Fail;
 
           y += top[0];
           /* otherwise, we divide numbers in 16.16 format --    */
           /* in both cases, it is the same operation            */
           *top = FT_DivFix( top[0], top[1] );
-          ++top;
+          top++;
 
           large_int = FALSE;
           break;
                    FT_Render_Mode       hint_mode,
                    T1_Decoder_Callback  parse_callback )
   {
-    FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
+    FT_ZERO( decoder );
 
     /* retrieve PSNames interface from list of current modules */
     {
index 8f131be..5a538e2 100644 (file)
   static void
   psh_print_zone( PSH_Zone  zone )
   {
-    printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n",
+    printf( "zone [scale,delta,min,max] = [%.5f,%.2f,%d,%d]\n",
              zone->scale / 65536.0,
              zone->delta / 64.0,
              zone->min,
 
 
     /* clear all fields */
-    FT_MEM_ZERO( glyph, sizeof ( *glyph ) );
+    FT_ZERO( glyph );
 
     memory = glyph->memory = globals->memory;
 
           }
         }
 
-        if ( point->hint == NULL )
+        if ( !point->hint )
         {
           for ( nn = 0; nn < num_hints; nn++ )
           {
     PS_Mask         mask      = table->hint_masks->masks;
     FT_UInt         num_masks = table->hint_masks->num_masks;
     FT_UInt         first     = 0;
-    FT_Int          major_dir = dimension == 0 ? PSH_DIR_VERTICAL
-                                               : PSH_DIR_HORIZONTAL;
+    FT_Int          major_dir = ( dimension == 0 ) ? PSH_DIR_VERTICAL
+                                                   : PSH_DIR_HORIZONTAL;
     PSH_Dimension   dim       = &glyph->globals->dimension[dimension];
     FT_Fixed        scale     = dim->scale_mult;
     FT_Int          threshold;
index fa4ad1f..d5d53ab 100644 (file)
 
   FT_DEFINE_PSHINTER_INTERFACE(
     pshinter_interface,
+
     pshinter_get_globals_funcs,
     pshinter_get_t1_funcs,
-    pshinter_get_t2_funcs )
+    pshinter_get_t2_funcs
+  )
 
 
   FT_DEFINE_MODULE(
 
     &PSHINTER_INTERFACE_GET,              /* module-specific interface */
 
-    (FT_Module_Constructor)ps_hinter_init,
-    (FT_Module_Destructor) ps_hinter_done,
-    (FT_Module_Requester)  NULL )   /* no additional interface for now */
-
+    (FT_Module_Constructor)ps_hinter_init,  /* module_init   */
+    (FT_Module_Destructor) ps_hinter_done,  /* module_done   */
+    (FT_Module_Requester)  NULL             /* get_interface */
+  )
 
 /* END */
index d7cc4a0..3aeb265 100644 (file)
   ps_hints_init( PS_Hints   hints,
                  FT_Memory  memory )
   {
-    FT_MEM_ZERO( hints, sizeof ( *hints ) );
+    FT_ZERO( hints );
     hints->memory = memory;
   }
 
   FT_LOCAL_DEF( void )
   t1_hints_funcs_init( T1_Hints_FuncsRec*  funcs )
   {
-    FT_MEM_ZERO( (char*)funcs, sizeof ( *funcs ) );
+    FT_ZERO( funcs );
 
     funcs->open  = (T1_Hints_OpenFunc)    t1_hints_open;
     funcs->close = (T1_Hints_CloseFunc)   ps_hints_close;
   FT_LOCAL_DEF( void )
   t2_hints_funcs_init( T2_Hints_FuncsRec*  funcs )
   {
-    FT_MEM_ZERO( funcs, sizeof ( *funcs ) );
+    FT_ZERO( funcs );
 
     funcs->open    = (T2_Hints_OpenFunc)   t2_hints_open;
     funcs->close   = (T2_Hints_CloseFunc)  ps_hints_close;
index 345402d..01b85c3 100644 (file)
@@ -22,6 +22,8 @@
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
 
 #include "psmodule.h"
+
+#define  DEFINE_PS_TABLES
 #include "pstables.h"
 
 #include "psnamerr.h"
 
   FT_DEFINE_SERVICE_PSCMAPSREC(
     pscmaps_interface,
+
     (PS_Unicode_ValueFunc)     ps_unicode_value,        /* unicode_value         */
     (PS_Unicodes_InitFunc)     ps_unicodes_init,        /* unicodes_init         */
     (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,  /* unicodes_char_index   */
     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings     */
 
     t1_standard_encoding,                               /* adobe_std_encoding    */
-    t1_expert_encoding )                                /* adobe_expert_encoding */
+    t1_expert_encoding                                  /* adobe_expert_encoding */
+  )
 
 #else
 
   FT_DEFINE_SERVICE_PSCMAPSREC(
     pscmaps_interface,
+
     NULL,                                               /* unicode_value         */
     NULL,                                               /* unicodes_init         */
     NULL,                                               /* unicodes_char_index   */
     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings     */
 
     t1_standard_encoding,                               /* adobe_std_encoding    */
-    t1_expert_encoding )                                /* adobe_expert_encoding */
+    t1_expert_encoding                                  /* adobe_expert_encoding */
+  )
 
 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
 
 
   FT_DEFINE_SERVICEDESCREC1(
     pscmaps_services,
+
     FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET )
 
 
 
     PUT_PS_NAMES_SERVICE(
       (void*)&PSCMAPS_INTERFACE_GET ),   /* module specific interface */
-    (FT_Module_Constructor)NULL,
-    (FT_Module_Destructor) NULL,
-    (FT_Module_Requester)  PUT_PS_NAMES_SERVICE( psnames_get_service ) )
+
+    (FT_Module_Constructor)NULL,                                       /* module_init   */
+    (FT_Module_Destructor) NULL,                                       /* module_done   */
+    (FT_Module_Requester)  PUT_PS_NAMES_SERVICE( psnames_get_service ) /* get_interface */
+  )
 
 
 /* END */
index eb827fa..309f16b 100644 (file)
   /* This file has been generated automatically -- do not edit! */
 
 
-  static const char  ft_standard_glyph_names[3696] =
+#ifndef  DEFINE_PS_TABLES
+#ifdef  __cplusplus
+  extern "C"
+#else
+  extern
+#endif
+#endif
+  const char  ft_standard_glyph_names[3696]
+#ifdef  DEFINE_PS_TABLES
+  =
   {
     '.','n','u','l','l', 0,
     'n','o','n','m','a','r','k','i','n','g','r','e','t','u','r','n', 0,
     'R','e','g','u','l','a','r', 0,
     'R','o','m','a','n', 0,
     'S','e','m','i','b','o','l','d', 0,
-  };
+  }
+#endif /* DEFINE_PS_TABLES */
+  ;
 
 
 #define FT_NUM_MAC_NAMES  258
 
   /* Values are offsets into the `ft_standard_glyph_names' table */
 
-  static const short  ft_mac_names[FT_NUM_MAC_NAMES] =
+#ifndef  DEFINE_PS_TABLES
+#ifdef  __cplusplus
+  extern "C"
+#else
+  extern
+#endif
+#endif
+  const short  ft_mac_names[FT_NUM_MAC_NAMES]
+#ifdef  DEFINE_PS_TABLES
+  =
   {
      253,   0,   6, 261, 267, 274, 283, 294, 301, 309, 758, 330, 340, 351,
      360, 365, 371, 378, 385, 391, 396, 400, 404, 410, 415, 420, 424, 430,
     1066,1073,1101,1143,1536,1783,1596,1843,1253,1207,1319,1579,1826,1229,
     1270,1313,1323,1171,1290,1332,1211,1235,1276, 169, 175, 182, 189, 200,
      209, 218, 225, 232, 239, 246
-  };
+  }
+#endif /* DEFINE_PS_TABLES */
+  ;
 
 
 #define FT_NUM_SID_NAMES  391
 
   /* Values are offsets into the `ft_standard_glyph_names' table */
 
-  static const short  ft_sid_names[FT_NUM_SID_NAMES] =
+#ifndef  DEFINE_PS_TABLES
+#ifdef  __cplusplus
+  extern "C"
+#else
+  extern
+#endif
+#endif
+  const short  ft_sid_names[FT_NUM_SID_NAMES]
+#ifdef  DEFINE_PS_TABLES
+  =
   {
      253, 261, 267, 274, 283, 294, 301, 309, 319, 330, 340, 351, 360, 365,
      371, 378, 385, 391, 396, 400, 404, 410, 415, 420, 424, 430, 436, 441,
     3237,3249,3264,3275,3283,3297,3309,3321,3338,3353,3365,3377,3394,3409,
     3418,3430,3442,3454,3471,3483,3498,3506,3518,3530,3542,3559,3574,3586,
     3597,3612,3620,3628,3636,3644,3650,3655,3660,3666,3673,3681,3687
-  };
+  }
+#endif /* DEFINE_PS_TABLES */
+  ;
 
 
   /* the following are indices into the SID name table */
-  static const unsigned short  t1_standard_encoding[256] =
+#ifndef  DEFINE_PS_TABLES
+#ifdef  __cplusplus
+  extern "C"
+#else
+  extern
+#endif
+#endif
+  const unsigned short  t1_standard_encoding[256]
+#ifdef  DEFINE_PS_TABLES
+  =
   {
       0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
       0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     137,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
       0,138,  0,139,  0,  0,  0,  0,140,141,142,143,  0,  0,  0,  0,
       0,144,  0,  0,  0,145,  0,  0,146,147,148,149,  0,  0,  0,  0
-  };
+  }
+#endif /* DEFINE_PS_TABLES */
+  ;
 
 
   /* the following are indices into the SID name table */
-  static const unsigned short  t1_expert_encoding[256] =
+#ifndef  DEFINE_PS_TABLES
+#ifdef  __cplusplus
+  extern "C"
+#else
+  extern
+#endif
+#endif
+  const unsigned short  t1_expert_encoding[256]
+#ifdef  DEFINE_PS_TABLES
+  =
   {
       0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
       0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,
     347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,
     363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378
-  };
+  }
+#endif /* DEFINE_PS_TABLES */
+  ;
 
 
   /*
 
 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
 
-  static const unsigned char  ft_adobe_glyph_list[55997L] =
+#ifndef  DEFINE_PS_TABLES
+#ifdef  __cplusplus
+  extern "C"
+#else
+  extern
+#endif
+#endif
+  const unsigned char  ft_adobe_glyph_list[55997L]
+#ifdef  DEFINE_PS_TABLES
+  =
   {
       0, 52,  0,106,  2,167,  3, 63,  4,220,  6,125,  9,143, 10, 23,
      11,137, 12,199, 14,246, 15, 87, 16,233, 17,219, 18,104, 19, 88,
     248,232,239,239,107,128,  2,144,243,244,242,239,235,101,128,  1,
     182,117,  2,218,167,218,178,232,233,242,225,231,225,238, 97,128,
      48, 90,235,225,244,225,235,225,238, 97,128, 48,186
-  };
+  }
+#endif /* DEFINE_PS_TABLES */
+  ;
 
 
   /*
index e5ccf01..85a3b4d 100644 (file)
 
 #ifndef FT_MEM_ZERO
 #define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
+#endif
+
+#ifndef FT_ZERO
+#define FT_ZERO( p )  FT_MEM_ZERO( p, sizeof ( *(p) ) )
 #endif
 
   /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
         state_bez = y1 < y3 ? Ascending_State : Descending_State;
         if ( ras.state != state_bez )
         {
-          Bool  o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 )
-                                                 : IS_TOP_OVERSHOOT( y1 );
+          Bool  o = ( state_bez == Ascending_State )
+                      ? IS_BOTTOM_OVERSHOOT( y1 )
+                      : IS_TOP_OVERSHOOT( y1 );
 
 
           /* finalize current profile if any */
         /* detect a change of direction */
         if ( ras.state != state_bez )
         {
-          Bool  o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 )
-                                                 : IS_TOP_OVERSHOOT( y1 );
+          Bool  o = ( state_bez == Ascending_State )
+                      ? IS_BOTTOM_OVERSHOOT( y1 )
+                      : IS_TOP_OVERSHOOT( y1 );
 
 
           /* finalize current profile if any */
           pxl = e2;
 
         /* check that the other pixel isn't set */
-        e1 = pxl == e1 ? e2 : e1;
+        e1 = ( pxl == e1 ) ? e2 : e1;
 
         e1 = TRUNC( e1 );
 
           pxl = e2;
 
         /* check that the other pixel isn't set */
-        e1 = pxl == e1 ? e2 : e1;
+        e1 = ( pxl == e1 ) ? e2 : e1;
 
         e1 = TRUNC( e1 );
 
 
 
      *araster = (FT_Raster)&the_raster;
-     FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
+     FT_ZERO( &the_raster );
      ft_black_init( &the_raster );
 
      return 0;
 
     FT_GLYPH_FORMAT_OUTLINE,
 
-    (FT_Raster_New_Func)     ft_black_new,
-    (FT_Raster_Reset_Func)   ft_black_reset,
-    (FT_Raster_Set_Mode_Func)ft_black_set_mode,
-    (FT_Raster_Render_Func)  ft_black_render,
-    (FT_Raster_Done_Func)    ft_black_done )
+    (FT_Raster_New_Func)     ft_black_new,       /* raster_new      */
+    (FT_Raster_Reset_Func)   ft_black_reset,     /* raster_reset    */
+    (FT_Raster_Set_Mode_Func)ft_black_set_mode,  /* raster_set_mode */
+    (FT_Raster_Render_Func)  ft_black_render,    /* raster_render   */
+    (FT_Raster_Done_Func)    ft_black_done       /* raster_done     */
+  )
 
 
 /* END */
index 494f112..5bd4b30 100644 (file)
@@ -88,7 +88,7 @@
                        FT_GlyphSlot  slot,
                        FT_BBox*      cbox )
   {
-    FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
+    FT_ZERO( cbox );
 
     if ( slot->format == render->glyph_format )
       FT_Outline_Get_CBox( &slot->outline, cbox );
   }
 
 
-  FT_DEFINE_RENDERER( ft_raster1_renderer_class,
+  FT_DEFINE_RENDERER(
+    ft_raster1_renderer_class,
 
       FT_MODULE_RENDERER,
       sizeof ( FT_RendererRec ),
       0x10000L,
       0x20000L,
 
-      0,    /* module specific interface */
+      NULL,    /* module specific interface */
 
-      (FT_Module_Constructor)ft_raster1_init,
-      (FT_Module_Destructor) 0,
-      (FT_Module_Requester)  0
-    ,
+      (FT_Module_Constructor)ft_raster1_init,  /* module_init   */
+      (FT_Module_Destructor) NULL,             /* module_done   */
+      (FT_Module_Requester)  NULL,             /* get_interface */
 
     FT_GLYPH_FORMAT_OUTLINE,
 
-    (FT_Renderer_RenderFunc)   ft_raster1_render,
-    (FT_Renderer_TransformFunc)ft_raster1_transform,
-    (FT_Renderer_GetCBoxFunc)  ft_raster1_get_cbox,
-    (FT_Renderer_SetModeFunc)  ft_raster1_set_mode,
+    (FT_Renderer_RenderFunc)   ft_raster1_render,     /* render_glyph    */
+    (FT_Renderer_TransformFunc)ft_raster1_transform,  /* transform_glyph */
+    (FT_Renderer_GetCBoxFunc)  ft_raster1_get_cbox,   /* get_glyph_cbox  */
+    (FT_Renderer_SetModeFunc)  ft_raster1_set_mode,   /* set_mode        */
 
-    (FT_Raster_Funcs*)    &FT_STANDARD_RASTER_GET
+    (FT_Raster_Funcs*)&FT_STANDARD_RASTER_GET         /* raster_class    */
   )
 
 
index 2815759..ff67292 100644 (file)
                  FT_Memory        memory,
                  FT_Byte*         data,
                  FT_UInt          png_len,
-                 FT_Bool          populate_map_and_metrics )
+                 FT_Bool          populate_map_and_metrics,
+                 FT_Bool          metrics_only )
   {
     FT_Bitmap    *map   = &slot->bitmap;
     FT_Error      error = FT_Err_Ok;
 
     if ( populate_map_and_metrics )
     {
-      FT_ULong  size;
-
-
       metrics->width  = (FT_UShort)imgWidth;
       metrics->height = (FT_UShort)imgHeight;
 
         error = FT_THROW( Array_Too_Large );
         goto DestroyExit;
       }
-
-      /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */
-      size = map->rows * (FT_ULong)map->pitch;
-
-      error = ft_glyphslot_alloc_bitmap( slot, size );
-      if ( error )
-        goto DestroyExit;
     }
 
     /* convert palette/gray image to rgb */
       goto DestroyExit;
     }
 
+    if ( metrics_only )
+      goto DestroyExit;
+
     switch ( color_type )
     {
     default:
       break;
     }
 
+    if ( populate_map_and_metrics )
+    {
+      /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */
+      FT_ULong  size = map->rows * (FT_ULong)map->pitch;
+
+
+      error = ft_glyphslot_alloc_bitmap( slot, size );
+      if ( error )
+        goto DestroyExit;
+    }
+
     if ( FT_NEW_ARRAY( rows, imgHeight ) )
     {
       error = FT_THROW( Out_Of_Memory );
index ff05871..0af4bfc 100644 (file)
@@ -38,7 +38,8 @@ FT_BEGIN_HEADER
                  FT_Memory        memory,
                  FT_Byte*         data,
                  FT_UInt          png_len,
-                 FT_Bool          populate_map_and_metrics );
+                 FT_Bool          populate_map_and_metrics,
+                 FT_Bool          metrics_only );
 
 #endif
 
index 2233269..1f15223 100644 (file)
@@ -88,7 +88,7 @@
       break;
 
     case FT_SFNT_OS2:
-      table = face->os2.version == 0xFFFFU ? NULL : &face->os2;
+      table = ( face->os2.version == 0xFFFFU ) ? NULL : &face->os2;
       break;
 
     case FT_SFNT_POST:
 
   FT_DEFINE_SERVICE_SFNT_TABLEREC(
     sfnt_service_sfnt_table,
+
     (FT_SFNT_TableLoadFunc)tt_face_load_any,     /* load_table */
     (FT_SFNT_TableGetFunc) get_sfnt_table,       /* get_table  */
-    (FT_SFNT_TableInfoFunc)sfnt_table_info )     /* table_info */
+    (FT_SFNT_TableInfoFunc)sfnt_table_info       /* table_info */
+  )
 
 
 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    */
 
   static FT_Error
-  sfnt_get_glyph_name( TT_Face     face,
+  sfnt_get_glyph_name( FT_Face     face,
                        FT_UInt     glyph_index,
                        FT_Pointer  buffer,
                        FT_UInt     buffer_max )
     FT_Error    error;
 
 
-    error = tt_face_get_ps_name( face, glyph_index, &gname );
+    error = tt_face_get_ps_name( (TT_Face)face, glyph_index, &gname );
     if ( !error )
       FT_STRCPYN( buffer, gname, buffer_max );
 
 
 
   static FT_UInt
-  sfnt_get_name_index( TT_Face     face,
+  sfnt_get_name_index( FT_Face     face,
                        FT_String*  glyph_name )
   {
-    FT_Face  root = &face->root;
+    TT_Face  ttface = (TT_Face)face;
 
     FT_UInt  i, max_gid = FT_UINT_MAX;
 
 
-    if ( root->num_glyphs < 0 )
+    if ( face->num_glyphs < 0 )
       return 0;
-    else if ( (FT_ULong)root->num_glyphs < FT_UINT_MAX )
-      max_gid = (FT_UInt)root->num_glyphs;
+    else if ( (FT_ULong)face->num_glyphs < FT_UINT_MAX )
+      max_gid = (FT_UInt)face->num_glyphs;
     else
       FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n",
-                  FT_UINT_MAX, root->num_glyphs ));
+                  FT_UINT_MAX, face->num_glyphs ));
 
     for ( i = 0; i < max_gid; i++ )
     {
       FT_String*  gname;
-      FT_Error    error = tt_face_get_ps_name( face, i, &gname );
+      FT_Error    error = tt_face_get_ps_name( ttface, i, &gname );
 
 
       if ( error )
 
   FT_DEFINE_SERVICE_GLYPHDICTREC(
     sfnt_service_glyph_dict,
-    (FT_GlyphDict_GetNameFunc)  sfnt_get_glyph_name,    /* get_name   */
-    (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index )   /* name_index */
 
+    (FT_GlyphDict_GetNameFunc)  sfnt_get_glyph_name,    /* get_name   */
+    (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index     /* name_index */
+  )
 
 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
 
 
   FT_DEFINE_SERVICE_PSFONTNAMEREC(
     sfnt_service_ps_name,
-    (FT_PsName_GetFunc)sfnt_get_ps_name )     /* get_ps_font_name */
+
+    (FT_PsName_GetFunc)sfnt_get_ps_name       /* get_ps_font_name */
+  )
 
 
   /*
    */
   FT_DEFINE_SERVICE_TTCMAPSREC(
     tt_service_get_cmap_info,
-    (TT_CMap_Info_GetFunc)tt_get_cmap_info )  /* get_cmap_info */
+
+    (TT_CMap_Info_GetFunc)tt_get_cmap_info    /* get_cmap_info */
+  )
 
 
 #ifdef TT_CONFIG_OPTION_BDF
 
   FT_DEFINE_SERVICE_BDFRec(
     sfnt_service_bdf,
+
     (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id,     /* get_charset_id */
-    (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop )  /* get_property   */
+    (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop    /* get_property   */
+  )
 
 
 #endif /* TT_CONFIG_OPTION_BDF */
 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
   FT_DEFINE_SERVICEDESCREC5(
     sfnt_services,
+
     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
     FT_SERVICE_ID_GLYPH_DICT,           &SFNT_SERVICE_GLYPH_DICT_GET,
 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
   FT_DEFINE_SERVICEDESCREC4(
     sfnt_services,
+
     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
     FT_SERVICE_ID_GLYPH_DICT,           &SFNT_SERVICE_GLYPH_DICT_GET,
 #elif defined TT_CONFIG_OPTION_BDF
   FT_DEFINE_SERVICEDESCREC4(
     sfnt_services,
+
     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
     FT_SERVICE_ID_BDF,                  &SFNT_SERVICE_BDF_GET,
 #else
   FT_DEFINE_SERVICEDESCREC3(
     sfnt_services,
+
     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
     FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
 
   FT_DEFINE_SFNT_INTERFACE(
     sfnt_interface,
+
     tt_face_goto_table,     /* TT_Loader_GotoTableFunc goto_table      */
 
     sfnt_init_face,         /* TT_Init_Face_Func       init_face       */
 
     (const void*)&SFNT_INTERFACE_GET,  /* module specific interface */
 
-    (FT_Module_Constructor)0,
-    (FT_Module_Destructor) 0,
-    (FT_Module_Requester)  sfnt_get_interface )
+    (FT_Module_Constructor)NULL,               /* module_init   */
+    (FT_Module_Destructor) NULL,               /* module_done   */
+    (FT_Module_Requester)  sfnt_get_interface  /* get_interface */
+  )
 
 
 /* END */
index 4413bbc..818009e 100644 (file)
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
 #include FT_SFNT_NAMES_H
 #include FT_GZIP_H
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include FT_SERVICE_MULTIPLE_MASTERS_H
+#include FT_SERVICE_METRICS_VARIATIONS_H
+#endif
+
 #include "sferrors.h"
 
 #ifdef TT_CONFIG_OPTION_BDF
 
     if ( rec && convert )
     {
-      if ( rec->string == NULL )
+      if ( !rec->string )
       {
         FT_Stream  stream = face->name_table.stream;
 
       if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
         return error;
 
+      FT_TRACE3(( "                with %ld subfonts\n",
+                  face->ttc_header.count ));
+
       if ( face->ttc_header.count == 0 )
         return FT_THROW( Invalid_Table );
 
 
     FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+    if ( !face->mm )
+    {
+      /* we want the MM interface from the `truetype' module only */
+      FT_Module  tt_module = FT_Get_Module( library, "truetype" );
+
+
+      face->mm = ft_module_get_service( tt_module,
+                                        FT_SERVICE_ID_MULTI_MASTERS,
+                                        0 );
+    }
+
+    FT_FACE_FIND_GLOBAL_SERVICE( face, face->var, METRICS_VARIATIONS );
+#endif
+
     FT_TRACE2(( "SFNT driver\n" ));
 
     error = sfnt_open_font( stream, face );
     /* Stream may have changed in sfnt_open_font. */
     stream = face->root.stream;
 
-    FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_instance_index ));
+    FT_TRACE2(( "sfnt_init_face: %08p, %d\n", face, face_instance_index ));
 
     face_index = FT_ABS( face_instance_index ) & 0xFFFF;
 
       FT_Int  instance_index;
 
 
+      face->is_default_instance = 1;
+
       instance_index = FT_ABS( face_instance_index ) >> 16;
 
       /* test whether current face is a GX font with named instances */
            fvar_len < 20                                          ||
            FT_READ_ULONG( version )                               ||
            FT_READ_USHORT( offset )                               ||
-           FT_STREAM_SKIP( 2 )                                    ||
+           FT_STREAM_SKIP( 2 ) /* count_size_pairs */             ||
            FT_READ_USHORT( num_axes )                             ||
            FT_READ_USHORT( axis_size )                            ||
            FT_READ_USHORT( num_instances )                        ||
         instance_size = 0;
       }
 
-      /* check that the data is bound by the table length; */
-      /* based on similar code in function `TT_Get_MM_Var' */
+      /* check that the data is bound by the table length */
       if ( version != 0x00010000UL                    ||
+#if 0
+           /* fonts like `JamRegular.ttf' have an incorrect value for   */
+           /* `count_size_pairs'; since value 2 is hard-coded in `fvar' */
+           /* version 1.0, we simply ignore it                          */
+           count_size_pairs != 2                      ||
+#endif
            axis_size != 20                            ||
+           num_axes == 0                              ||
+           /* `num_axes' limit implied by 16-bit `instance_size' */
            num_axes > 0x3FFE                          ||
-           instance_size != 4 + 4 * num_axes          ||
+           !( instance_size == 4 + 4 * num_axes ||
+              instance_size == 6 + 4 * num_axes )     ||
            num_instances > 0x7EFF                     ||
            offset                          +
              axis_size * num_axes          +
              instance_size * num_instances > fvar_len )
         num_instances = 0;
+      else
+        face->variation_support |= TT_FACE_FLAG_VAR_FVAR;
 
       /* we don't support Multiple Master CFFs yet */
       if ( !face->goto_table( face, TTAG_CFF, stream, 0 ) )
 
     /* do we have outlines in there? */
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
-    has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 ||
-                           tt_face_lookup_table( face, TTAG_glyf )    != 0 ||
-                           tt_face_lookup_table( face, TTAG_CFF )     != 0 );
+    has_outline = FT_BOOL( face->root.internal->incremental_interface ||
+                           tt_face_lookup_table( face, TTAG_glyf )    ||
+                           tt_face_lookup_table( face, TTAG_CFF )     ||
+                           tt_face_lookup_table( face, TTAG_CFF2 )    );
 #else
-    has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
-                           tt_face_lookup_table( face, TTAG_CFF )  != 0 );
+    has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) ||
+                           tt_face_lookup_table( face, TTAG_CFF )  ||
+                           tt_face_lookup_table( face, TTAG_CFF2 ) );
 #endif
 
     is_apple_sbit = 0;
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
       /* Don't bother to load the tables unless somebody asks for them. */
       /* No need to do work which will (probably) not be used.          */
-      if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
-           tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
-           tt_face_lookup_table( face, TTAG_gvar ) != 0 )
-        flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+      if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR )
+      {
+        if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
+             tt_face_lookup_table( face, TTAG_gvar ) != 0 )
+          flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+        if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 )
+          flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+      }
 #endif
 
       root->face_flags = flags;
                                                   charmap->encoding_id );
 
 #if 0
-          if ( root->charmap     == NULL &&
+          if ( !root->charmap                           &&
                charmap->encoding == FT_ENCODING_UNICODE )
           {
             /* set 'root->charmap' to the first Unicode encoding we find */
        *  depths in the FT_Bitmap_Size record.  This is a design error.
        */
       {
-        FT_UInt  i, count;
+        FT_UInt  count;
 
 
         count = face->sbit_num_strikes;
           FT_Short         avgwidth = face->os2.xAvgCharWidth;
           FT_Size_Metrics  metrics;
 
+          FT_UInt*  sbit_strike_map = NULL;
+          FT_UInt   strike_idx, bsize_idx;
+
 
           if ( em_size == 0 || face->os2.version == 0xFFFFU )
           {
             em_size = 1;
           }
 
-          if ( FT_NEW_ARRAY( root->available_sizes, count ) )
+          /* to avoid invalid strike data in the `available_sizes' field */
+          /* of `FT_Face', we map `available_sizes' indices to strike    */
+          /* indices                                                     */
+          if ( FT_NEW_ARRAY( root->available_sizes, count ) ||
+               FT_NEW_ARRAY( sbit_strike_map, count ) )
             goto Exit;
 
-          for ( i = 0; i < count; i++ )
+          bsize_idx = 0;
+          for ( strike_idx = 0; strike_idx < count; strike_idx++ )
           {
-            FT_Bitmap_Size*  bsize = root->available_sizes + i;
+            FT_Bitmap_Size*  bsize = root->available_sizes + bsize_idx;
 
 
-            error = sfnt->load_strike_metrics( face, i, &metrics );
+            error = sfnt->load_strike_metrics( face, strike_idx, &metrics );
             if ( error )
-              goto Exit;
+              continue;
 
             bsize->height = (FT_Short)( metrics.height >> 6 );
-            bsize->width = (FT_Short)(
-                ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
+            bsize->width  = (FT_Short)(
+              ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
 
             bsize->x_ppem = metrics.x_ppem << 6;
             bsize->y_ppem = metrics.y_ppem << 6;
 
             /* assume 72dpi */
             bsize->size   = metrics.y_ppem << 6;
+
+            /* only use strikes with valid PPEM values */
+            if ( bsize->x_ppem && bsize->y_ppem )
+              sbit_strike_map[bsize_idx++] = strike_idx;
           }
 
-          root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
-          root->num_fixed_sizes = (FT_Int)count;
+          /* reduce array size to the actually used elements */
+          (void)FT_RENEW_ARRAY( sbit_strike_map, count, bsize_idx );
+
+          /* from now on, all strike indices are mapped */
+          /* using `sbit_strike_map'                    */
+          if ( bsize_idx )
+          {
+            face->sbit_strike_map = sbit_strike_map;
+
+            root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
+            root->num_fixed_sizes = (FT_Int)bsize_idx;
+          }
         }
       }
 
       face->cmap_size = 0;
     }
 
-    /* freeing the horizontal metrics */
-    {
-      FT_Stream  stream = FT_FACE_STREAM( face );
-
-
-      FT_FRAME_RELEASE( face->horz_metrics );
-      FT_FRAME_RELEASE( face->vert_metrics );
-      face->horz_metrics_size = 0;
-      face->vert_metrics_size = 0;
-    }
+    face->horz_metrics_size = 0;
+    face->vert_metrics_size = 0;
 
-    /* freeing the vertical ones, if any */
+    /* freeing vertical metrics, if any */
     if ( face->vertical_info )
     {
       FT_FREE( face->vertical.long_metrics  );
 
     /* freeing sbit size table */
     FT_FREE( face->root.available_sizes );
+    FT_FREE( face->sbit_strike_map );
     face->root.num_fixed_sizes = 0;
 
     FT_FREE( face->postscript_name );
index f891691..62acf09 100644 (file)
@@ -48,7 +48,7 @@
       FT_Stream  stream = FT_FACE(face)->stream;
 
 
-      if ( bdf->table != NULL )
+      if ( bdf->table )
         FT_FRAME_RELEASE( bdf->table );
 
       bdf->table_end    = NULL;
 
     error = FT_ERR( Invalid_Argument );
 
-    if ( size == NULL || property_name == NULL )
+    if ( !size || !property_name )
       goto Exit;
 
     property_len = ft_strlen( property_name );
       FT_UInt  _ppem  = FT_NEXT_USHORT( p );
       FT_UInt  _count = FT_NEXT_USHORT( p );
 
+
       if ( _ppem == size->metrics.y_ppem )
       {
         count = _count;
     {
       FT_UInt  type = FT_PEEK_USHORT( p + 4 );
 
+
       if ( ( type & 0x10 ) != 0 )
       {
         FT_UInt32  name_offset = FT_PEEK_ULONG( p     );
index cd7467d..e48c15c 100644 (file)
 
   FT_DEFINE_TT_CMAP(
     tt_cmap0_class_rec,
-    sizeof ( TT_CMapRec ),
 
-    (FT_CMap_InitFunc)     tt_cmap_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap0_char_next,
+      sizeof ( TT_CMapRec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
+      (FT_CMap_DoneFunc)     NULL,                 /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap0_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap0_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     0,
-    (TT_CMap_ValidateFunc)tt_cmap0_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap0_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap0_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap0_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_0 */
 
 
   FT_DEFINE_TT_CMAP(
     tt_cmap2_class_rec,
-    sizeof ( TT_CMapRec ),
 
-    (FT_CMap_InitFunc)     tt_cmap_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap2_char_next,
+      sizeof ( TT_CMapRec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
+      (FT_CMap_DoneFunc)     NULL,                 /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap2_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap2_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     2,
-    (TT_CMap_ValidateFunc)tt_cmap2_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap2_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap2_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap2_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_2 */
 
 
   FT_DEFINE_TT_CMAP(
     tt_cmap4_class_rec,
-    sizeof ( TT_CMap4Rec ),
-    (FT_CMap_InitFunc)     tt_cmap4_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap4_char_next,
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      sizeof ( TT_CMap4Rec ),
+
+      (FT_CMap_InitFunc)     tt_cmap4_init,        /* init       */
+      (FT_CMap_DoneFunc)     NULL,                 /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap4_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap4_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     4,
-    (TT_CMap_ValidateFunc)tt_cmap4_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap4_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap4_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap4_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
 
 
   FT_DEFINE_TT_CMAP(
     tt_cmap6_class_rec,
-    sizeof ( TT_CMapRec ),
 
-    (FT_CMap_InitFunc)     tt_cmap_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap6_char_next,
+      sizeof ( TT_CMapRec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
+      (FT_CMap_DoneFunc)     NULL,                 /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap6_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap6_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     6,
-    (TT_CMap_ValidateFunc)tt_cmap6_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap6_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap6_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap6_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
 
 
   FT_DEFINE_TT_CMAP(
     tt_cmap8_class_rec,
-    sizeof ( TT_CMapRec ),
 
-    (FT_CMap_InitFunc)     tt_cmap_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap8_char_next,
+      sizeof ( TT_CMapRec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap_init,         /* init       */
+      (FT_CMap_DoneFunc)     NULL,                 /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap8_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap8_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     8,
-    (TT_CMap_ValidateFunc)tt_cmap8_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap8_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap8_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap8_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
 
 
   FT_DEFINE_TT_CMAP(
     tt_cmap10_class_rec,
-    sizeof ( TT_CMapRec ),
 
-    (FT_CMap_InitFunc)     tt_cmap_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap10_char_next,
+      sizeof ( TT_CMapRec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap_init,          /* init       */
+      (FT_CMap_DoneFunc)     NULL,                  /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap10_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap10_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     10,
-    (TT_CMap_ValidateFunc)tt_cmap10_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap10_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap10_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap10_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
 
 
   FT_DEFINE_TT_CMAP(
     tt_cmap12_class_rec,
-    sizeof ( TT_CMap12Rec ),
 
-    (FT_CMap_InitFunc)     tt_cmap12_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap12_char_next,
+      sizeof ( TT_CMap12Rec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap12_init,        /* init       */
+      (FT_CMap_DoneFunc)     NULL,                  /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap12_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap12_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     12,
-    (TT_CMap_ValidateFunc)tt_cmap12_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap12_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap12_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap12_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
 
 
   FT_DEFINE_TT_CMAP(
     tt_cmap13_class_rec,
-    sizeof ( TT_CMap13Rec ),
 
-    (FT_CMap_InitFunc)     tt_cmap13_init,
-    (FT_CMap_DoneFunc)     NULL,
-    (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap13_char_next,
+      sizeof ( TT_CMap13Rec ),
 
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
+      (FT_CMap_InitFunc)     tt_cmap13_init,        /* init       */
+      (FT_CMap_DoneFunc)     NULL,                  /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap13_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap13_char_next,   /* char_next  */
+
+      (FT_CMap_CharVarIndexFunc)    NULL,  /* char_var_index   */
+      (FT_CMap_CharVarIsDefaultFunc)NULL,  /* char_var_default */
+      (FT_CMap_VariantListFunc)     NULL,  /* variant_list     */
+      (FT_CMap_CharVariantListFunc) NULL,  /* charvariant_list */
+      (FT_CMap_VariantCharListFunc) NULL,  /* variantchar_list */
 
     13,
-    (TT_CMap_ValidateFunc)tt_cmap13_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap13_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap13_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap13_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_13 */
 
 
 
     cmap->max_results = 0;
-    if ( memory != NULL && cmap->results != NULL )
+    if ( memory && cmap->results )
       FT_FREE( cmap->results );
   }
 
           if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
             FT_INVALID_TOO_SHORT;
 
-          for ( i = 0; i < numRanges; ++i )
+          for ( i = 0; i < numRanges; i++ )
           {
             FT_ULong  base = TT_NEXT_UINT24( defp );
             FT_ULong  cnt  = FT_NEXT_BYTE( defp );
           if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 5 )
             FT_INVALID_TOO_SHORT;
 
-          for ( i = 0; i < numMappings; ++i )
+          for ( i = 0; i < numMappings; i++ )
           {
             FT_ULong  uni = TT_NEXT_UINT24( ndp );
             FT_ULong  gid = TT_NEXT_USHORT( ndp );
       return NULL;
 
     result = cmap14->results;
-    for ( i = 0; i < count; ++i )
+    for ( i = 0; i < count; i++ )
     {
       result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
       p        += 8;
     if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
       return NULL;
 
-    for ( q = cmap14->results; count > 0; --count )
+    for ( q = cmap14->results; count > 0; count-- )
     {
       FT_UInt32  varSel    = TT_NEXT_UINT24( p );
       FT_ULong   defOff    = TT_NEXT_ULONG( p );
     if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
       return NULL;
 
-    for ( q = cmap14->results; numRanges > 0; --numRanges )
+    for ( q = cmap14->results; numRanges > 0; numRanges-- )
     {
       FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
 
       return NULL;
 
     ret = cmap14->results;
-    for ( i = 0; i < numMappings; ++i )
+    for ( i = 0; i < numMappings; i++ )
     {
       ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
       p += 2;
       {
         if ( nuni > duni + dcnt )
         {
-          for ( k = 0; k <= dcnt; ++k )
+          for ( k = 0; k <= dcnt; k++ )
             ret[i++] = duni + k;
 
-          ++di;
+          di++;
 
           if ( di > numRanges )
             break;
             ret[i++] = nuni;
           /* If it is within the default range then ignore it -- */
           /* that should not have happened                       */
-          ++ni;
+          ni++;
           if ( ni > numMappings )
             break;
 
         {
           ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
           p += 2;
-          ++ni;
+          ni++;
         }
       }
       else if ( di <= numRanges )
         /* If we get here then we have run out of all non-default     */
         /* mappings.  We have read one default range which we haven't */
         /* stored and there may be others that need to be read.       */
-        for ( k = 0; k <= dcnt; ++k )
+        for ( k = 0; k <= dcnt; k++ )
           ret[i++] = duni + k;
 
         while ( di < numRanges )
           duni = (FT_UInt32)TT_NEXT_UINT24( dp );
           dcnt = FT_NEXT_BYTE( dp );
 
-          for ( k = 0; k <= dcnt; ++k )
+          for ( k = 0; k <= dcnt; k++ )
             ret[i++] = duni + k;
-          ++di;
+          di++;
         }
       }
 
 
   FT_DEFINE_TT_CMAP(
     tt_cmap14_class_rec,
-    sizeof ( TT_CMap14Rec ),
 
-    (FT_CMap_InitFunc)     tt_cmap14_init,
-    (FT_CMap_DoneFunc)     tt_cmap14_done,
-    (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
-    (FT_CMap_CharNextFunc) tt_cmap14_char_next,
+      sizeof ( TT_CMap14Rec ),
+
+      (FT_CMap_InitFunc)     tt_cmap14_init,        /* init       */
+      (FT_CMap_DoneFunc)     tt_cmap14_done,        /* done       */
+      (FT_CMap_CharIndexFunc)tt_cmap14_char_index,  /* char_index */
+      (FT_CMap_CharNextFunc) tt_cmap14_char_next,   /* char_next  */
 
-    /* Format 14 extension functions */
-    (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
-    (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
-    (FT_CMap_VariantListFunc)     tt_cmap14_variants,
-    (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
-    (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
+      /* Format 14 extension functions */
+      (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
+      (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
+      (FT_CMap_VariantListFunc)     tt_cmap14_variants,
+      (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
+      (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
 
     14,
-    (TT_CMap_ValidateFunc)tt_cmap14_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap14_get_info )
+    (TT_CMap_ValidateFunc)tt_cmap14_validate,  /* validate      */
+    (TT_CMap_Info_GetFunc)tt_cmap14_get_info   /* get_cmap_info */
+  )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
 
               error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
             }
 
-            if ( valid.validator.error == 0 )
+            if ( !valid.validator.error )
             {
               FT_CMap  ttcmap;
 
           }
         }
 
-        if ( *pclazz == NULL )
+        if ( !*pclazz )
         {
           FT_TRACE0(( "tt_face_build_cmaps:"
                       " unsupported cmap sub-table ignored\n" ));
index a653a71..d615bba 100644 (file)
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    tt_face_load_max_profile                                           */
+  /*    tt_face_load_maxp                                                  */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Loads the maximum profile into a face object.                      */
index 186f873..8c5508e 100644 (file)
 #include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_STREAM_H
 #include FT_TRUETYPE_TAGS_H
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include FT_SERVICE_METRICS_VARIATIONS_H
+#endif
+
 #include "ttmtx.h"
 
 #include "sferrors.h"
     FT_ULong        table_pos, table_size, table_end;
     FT_UShort       k;
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+    FT_Service_MetricsVariations  var =
+      (FT_Service_MetricsVariations)face->var;
+#endif
+
 
     if ( vertical )
     {
       *abearing = 0;
       *aadvance = 0;
     }
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+    if ( var )
+    {
+      FT_Face  f = FT_FACE( face );
+      FT_Int   a = (FT_Int)*aadvance;
+      FT_Int   b = (FT_Int)*abearing;
+
+
+      if ( vertical )
+      {
+        if ( var->vadvance_adjust )
+          var->vadvance_adjust( f, gindex, &a );
+        if ( var->tsb_adjust )
+          var->tsb_adjust( f, gindex, &b );
+      }
+      else
+      {
+        if ( var->hadvance_adjust )
+          var->hadvance_adjust( f, gindex, &a );
+        if ( var->lsb_adjust )
+          var->lsb_adjust( f, gindex, &b );
+      }
+
+      *aadvance = (FT_UShort)a;
+      *abearing = (FT_Short)b;
+    }
+#endif
   }
 
 
index 3277f1e..ef81e63 100644 (file)
       goto Exit;
 
     /* check the number of glyphs */
-    if ( num_glyphs > face->max_profile.numGlyphs || num_glyphs > 258 )
+    if ( num_glyphs > face->max_profile.numGlyphs ||
+         num_glyphs > 258                         ||
+         num_glyphs < 1                           )
     {
       error = FT_THROW( Invalid_File_Format );
       goto Exit;
index 36c261d..bf6ecca 100644 (file)
@@ -48,6 +48,7 @@
   {
     FT_Error  error;
     FT_ULong  table_size;
+    FT_ULong  table_start;
 
 
     face->sbit_table       = NULL;
@@ -83,6 +84,8 @@
       goto Exit;
     }
 
+    table_start = FT_STREAM_POS();
+
     switch ( (FT_UInt)face->sbit_table_type )
     {
     case TT_SBIT_TABLE_TYPE_EBLC:
         version     = FT_NEXT_LONG( p );
         num_strikes = FT_NEXT_ULONG( p );
 
+        /* there's at least one font (FZShuSong-Z01, version 3)   */
+        /* that uses the wrong byte order for the `version' field */
         if ( ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00020000UL &&
-             ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00030000UL )
+             ( (FT_ULong)version & 0x0000FFFFUL ) != 0x00000200UL &&
+             ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00030000UL &&
+             ( (FT_ULong)version & 0x0000FFFFUL ) != 0x00000300UL )
         {
           error = FT_THROW( Unknown_File_Format );
           goto Exit;
       break;
 
     default:
+      /* we ignore unknown table formats */
       error = FT_THROW( Unknown_File_Format );
       break;
     }
 
     if ( !error )
-      FT_TRACE3(( "sbit_num_strikes: %u\n", face->sbit_num_strikes ));
+      FT_TRACE3(( "tt_face_load_sbit_strikes: found %u strikes\n",
+                  face->sbit_num_strikes ));
 
     face->ebdt_start = 0;
     face->ebdt_size  = 0;
 
-    if ( face->sbit_table_type != TT_SBIT_TABLE_TYPE_NONE )
+    if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX )
+    {
+      /* the `sbix' table is self-contained; */
+      /* it has no associated data table     */
+      face->ebdt_start = table_start;
+      face->ebdt_size  = table_size;
+    }
+    else if ( face->sbit_table_type != TT_SBIT_TABLE_TYPE_NONE )
     {
       FT_ULong  ebdt_size;
 
       }
     }
 
+    if ( !face->ebdt_size )
+    {
+      FT_TRACE2(( "tt_face_load_sbit_strikes:"
+                  " no embedded bitmap data table found;\n"
+                  "                          "
+                  " resetting number of strikes to zero\n" ));
+      face->sbit_num_strikes = 0;
+    }
+
     return FT_Err_Ok;
 
   Exit:
                                FT_ULong          strike_index,
                                FT_Size_Metrics*  metrics )
   {
-    if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
-      return FT_THROW( Invalid_Argument );
+    /* we have to test for the existence of `sbit_strike_map'    */
+    /* because the function gets also used at the very beginning */
+    /* to construct `sbit_strike_map' itself                     */
+    if ( face->sbit_strike_map )
+    {
+      if ( strike_index >= (FT_ULong)face->root.num_fixed_sizes )
+        return FT_THROW( Invalid_Argument );
+
+      /* map to real index */
+      strike_index = face->sbit_strike_map[strike_index];
+    }
+    else
+    {
+      if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
+        return FT_THROW( Invalid_Argument );
+    }
 
     switch ( (FT_UInt)face->sbit_table_type )
     {
             FT_TRACE2(( "tt_face_load_strike_metrics:"
                         " sanitizing invalid ascender and descender\n"
                         "                            "
-                        " values for strike (%d, %d)\n",
+                        " values for strike %d (%dppem, %dppem)\n",
+                        strike_index,
                         metrics->x_ppem, metrics->y_ppem ));
 
             /* sanitize buggy ascender and descender values */
         FT_UInt         offset;
         FT_UShort       upem, ppem, resolution;
         TT_HoriHeader  *hori;
-        FT_ULong        table_size;
         FT_Pos          ppem_; /* to reduce casts */
 
         FT_Error  error;
         p      = face->sbit_table + 8 + 4 * strike_index;
         offset = FT_NEXT_ULONG( p );
 
-        error = face->goto_table( face, TTAG_sbix, stream, &table_size );
-        if ( error )
-          return error;
-
-        if ( offset + 4  > table_size )
+        if ( offset + 4 > face->ebdt_size )
           return FT_THROW( Invalid_File_Format );
 
-        if ( FT_STREAM_SEEK( FT_STREAM_POS() + offset ) ||
-             FT_FRAME_ENTER( 4 )                        )
+        if ( FT_STREAM_SEEK( face->ebdt_start + offset ) ||
+             FT_FRAME_ENTER( 4 )                         )
           return error;
 
         ppem       = FT_GET_USHORT();
     FT_Stream  stream = face->root.stream;
 
 
+    strike_index = face->sbit_strike_map[strike_index];
+
     if ( !face->ebdt_size )
       goto Exit;
     if ( FT_STREAM_SEEK( face->ebdt_start ) )
 
 
   static FT_Error
-  tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder  decoder )
+  tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder  decoder,
+                                FT_Bool         metrics_only )
   {
     FT_Error    error = FT_Err_Ok;
     FT_UInt     width, height;
     if ( size == 0 )
       goto Exit;     /* exit successfully! */
 
+    if ( metrics_only )
+      goto Exit;     /* only metrics are requested */
+
     error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size );
     if ( error )
       goto Exit;
                               FT_UInt         glyph_index,
                               FT_Int          x_pos,
                               FT_Int          y_pos,
-                              FT_UInt         recurse_count );
+                              FT_UInt         recurse_count,
+                              FT_Bool         metrics_only );
 
   typedef FT_Error  (*TT_SBitDecoder_LoadFunc)(
                       TT_SBitDecoder  decoder,
                                           gindex,
                                           x_pos + dx,
                                           y_pos + dy,
-                                          recurse_count + 1 );
+                                          recurse_count + 1,
+                                          /* request full bitmap image */
+                                          FALSE );
       if ( error )
         break;
     }
                            decoder->stream->memory,
                            p,
                            png_len,
+                           FALSE,
                            FALSE );
 
   Exit:
                                FT_ULong        glyph_size,
                                FT_Int          x_pos,
                                FT_Int          y_pos,
-                               FT_UInt         recurse_count )
+                               FT_UInt         recurse_count,
+                               FT_Bool         metrics_only )
   {
     FT_Error   error;
     FT_Stream  stream = decoder->stream;
 
       if ( !decoder->bitmap_allocated )
       {
-        error = tt_sbit_decoder_alloc_bitmap( decoder );
+        error = tt_sbit_decoder_alloc_bitmap( decoder, metrics_only );
+
         if ( error )
           goto Fail;
       }
 
+      if ( metrics_only )
+        goto Fail; /* this is not an error */
+
       error = loader( decoder, p, p_limit, x_pos, y_pos, recurse_count );
     }
 
                               FT_UInt         glyph_index,
                               FT_Int          x_pos,
                               FT_Int          y_pos,
-                              FT_UInt         recurse_count )
+                              FT_UInt         recurse_count,
+                              FT_Bool         metrics_only )
   {
     FT_Byte*  p          = decoder->eblc_base + decoder->strike_index_array;
     FT_Byte*  p_limit    = decoder->eblc_limit;
                                         image_end,
                                         x_pos,
                                         y_pos,
-                                        recurse_count );
+                                        recurse_count,
+                                        metrics_only );
 
   Failure:
     return FT_THROW( Invalid_Table );
                            FT_UInt              glyph_index,
                            FT_Stream            stream,
                            FT_Bitmap           *map,
-                           TT_SBit_MetricsRec  *metrics )
+                           TT_SBit_MetricsRec  *metrics,
+                           FT_Bool              metrics_only )
   {
-    FT_UInt   sbix_pos, strike_offset, glyph_start, glyph_end;
-    FT_ULong  table_size;
+    FT_UInt   strike_offset, glyph_start, glyph_end;
     FT_Int    originOffsetX, originOffsetY;
     FT_Tag    graphicType;
     FT_Int    recurse_depth = 0;
     FT_UNUSED( map );
 
 
+    strike_index = face->sbit_strike_map[strike_index];
+
     metrics->width  = 0;
     metrics->height = 0;
 
     p = face->sbit_table + 8 + 4 * strike_index;
     strike_offset = FT_NEXT_ULONG( p );
 
-    error = face->goto_table( face, TTAG_sbix, stream, &table_size );
-    if ( error )
-      return error;
-    sbix_pos = FT_STREAM_POS();
-
   retry:
     if ( glyph_index > (FT_UInt)face->root.num_glyphs )
       return FT_THROW( Invalid_Argument );
 
-    if ( strike_offset >= table_size                          ||
-         table_size - strike_offset < 4 + glyph_index * 4 + 8 )
+    if ( strike_offset >= face->ebdt_size                          ||
+         face->ebdt_size - strike_offset < 4 + glyph_index * 4 + 8 )
       return FT_THROW( Invalid_File_Format );
 
-    if ( FT_STREAM_SEEK( sbix_pos + strike_offset + 4 + glyph_index * 4 ) ||
-         FT_FRAME_ENTER( 8 )                                              )
+    if ( FT_STREAM_SEEK( face->ebdt_start  +
+                         strike_offset + 4 +
+                         glyph_index * 4   ) ||
+         FT_FRAME_ENTER( 8 )                 )
       return error;
 
     glyph_start = FT_GET_ULONG();
 
     if ( glyph_start == glyph_end )
       return FT_THROW( Invalid_Argument );
-    if ( glyph_start > glyph_end                ||
-         glyph_end - glyph_start < 8            ||
-         table_size - strike_offset < glyph_end )
+    if ( glyph_start > glyph_end                     ||
+         glyph_end - glyph_start < 8                 ||
+         face->ebdt_size - strike_offset < glyph_end )
       return FT_THROW( Invalid_File_Format );
 
-    if ( FT_STREAM_SEEK( sbix_pos + strike_offset + glyph_start ) ||
-         FT_FRAME_ENTER( glyph_end - glyph_start )                )
+    if ( FT_STREAM_SEEK( face->ebdt_start + strike_offset + glyph_start ) ||
+         FT_FRAME_ENTER( glyph_end - glyph_start )                        )
       return error;
 
     originOffsetX = FT_GET_SHORT();
                              stream->memory,
                              stream->cursor,
                              glyph_end - glyph_start - 8,
-                             TRUE );
+                             TRUE,
+                             metrics_only );
 #else
       error = FT_THROW( Unimplemented_Feature );
 #endif
         error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
         if ( !error )
         {
-          error = tt_sbit_decoder_load_image( decoder,
-                                              glyph_index,
-                                              0,
-                                              0,
-                                              0 );
+          error = tt_sbit_decoder_load_image(
+                    decoder,
+                    glyph_index,
+                    0,
+                    0,
+                    0,
+                    ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) != 0 );
           tt_sbit_decoder_done( decoder );
         }
       }
       break;
 
     case TT_SBIT_TABLE_TYPE_SBIX:
-      error = tt_face_load_sbix_image( face,
-                                       strike_index,
-                                       glyph_index,
-                                       stream,
-                                       map,
-                                       metrics );
+      error = tt_face_load_sbix_image(
+                face,
+                strike_index,
+                glyph_index,
+                stream,
+                map,
+                metrics,
+                ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) != 0 );
       break;
 
     default:
     }
 
     /* Flatten color bitmaps if color was not requested. */
-    if ( !error                                &&
-         !( load_flags & FT_LOAD_COLOR )       &&
-         map->pixel_mode == FT_PIXEL_MODE_BGRA )
+    if ( !error                                        &&
+         !( load_flags & FT_LOAD_COLOR )               &&
+         !( load_flags & FT_LOAD_BITMAP_METRICS_ONLY ) &&
+         map->pixel_mode == FT_PIXEL_MODE_BGRA         )
     {
       FT_Bitmap   new_map;
       FT_Library  library = face->root.glyph->library;
index d3d6c49..c5323fc 100644 (file)
@@ -284,6 +284,10 @@ typedef ptrdiff_t  FT_PtrDist;
 
 #ifndef FT_MEM_ZERO
 #define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
+#endif
+
+#ifndef FT_ZERO
+#define FT_ZERO( p )  FT_MEM_ZERO( p, sizeof ( *(p) ) )
 #endif
 
   /* as usual, for the speed hungry :-) */
@@ -371,8 +375,9 @@ typedef ptrdiff_t  FT_PtrDist;
 
   /* These macros speed up repetitive divisions by replacing them */
   /* with multiplications and right shifts.                       */
-#define FT_UDIVPREP( b )                                       \
-  long  b ## _r = (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b )
+#define FT_UDIVPREP( c, b )                                        \
+  long  b ## _r = c ? (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b ) \
+                    : 0
 #define FT_UDIV( a, b )                                        \
   ( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >>   \
     ( sizeof( long ) * FT_CHAR_BIT - PIXEL_BITS ) )
@@ -438,6 +443,7 @@ typedef ptrdiff_t  FT_PtrDist;
     TCoord  cover;
     int     invalid;
 
+    PCell*      ycells;
     PCell       cells;
     FT_PtrDist  max_cells;
     FT_PtrDist  num_cells;
@@ -450,8 +456,6 @@ typedef ptrdiff_t  FT_PtrDist;
     FT_Raster_Span_Func  render_span;
     void*                render_span_data;
 
-    PCell*     ycells;
-
   } gray_TWorker, *gray_PWorker;
 
 #if defined( _MSC_VER )
@@ -504,25 +508,22 @@ typedef ptrdiff_t  FT_PtrDist;
   /*                                                                       */
   /* Record the current cell in the table.                                 */
   /*                                                                       */
-  static PCell
-  gray_find_cell( RAS_ARG )
+  static void
+  gray_record_cell( RAS_ARG )
   {
     PCell  *pcell, cell;
     TCoord  x = ras.ex;
 
 
-    if ( x > ras.max_ex )
-      x = ras.max_ex;
-
     pcell = &ras.ycells[ras.ey - ras.min_ey];
     for (;;)
     {
       cell = *pcell;
-      if ( cell == NULL || cell->x > x )
+      if ( !cell || cell->x > x )
         break;
 
       if ( cell->x == x )
-        goto Exit;
+        goto Found;
 
       pcell = &cell->next;
     }
@@ -530,30 +531,21 @@ typedef ptrdiff_t  FT_PtrDist;
     if ( ras.num_cells >= ras.max_cells )
       ft_longjmp( ras.jump_buffer, 1 );
 
+    /* insert new cell */
     cell        = ras.cells + ras.num_cells++;
     cell->x     = x;
-    cell->area  = 0;
-    cell->cover = 0;
+    cell->area  = ras.area;
+    cell->cover = ras.cover;
 
     cell->next  = *pcell;
     *pcell      = cell;
 
-  Exit:
-    return cell;
-  }
-
+    return;
 
-  static void
-  gray_record_cell( RAS_ARG )
-  {
-    if ( ras.area | ras.cover )
-    {
-      PCell  cell = gray_find_cell( RAS_VAR );
-
-
-      cell->area  += ras.area;
-      cell->cover += ras.cover;
-    }
+  Found:
+    /* update old cell */
+    cell->area  += ras.area;
+    cell->cover += ras.cover;
   }
 
 
@@ -577,24 +569,18 @@ typedef ptrdiff_t  FT_PtrDist;
 
     /* All cells that are on the left of the clipping region go to the */
     /* min_ex - 1 horizontal position.                                 */
-    if ( ex > ras.max_ex )
-      ex = ras.max_ex;
 
     if ( ex < ras.min_ex )
       ex = ras.min_ex - 1;
 
-    /* are we moving to a different cell ? */
-    if ( ex != ras.ex || ey != ras.ey )
-    {
-      /* record the current one if it is valid */
-      if ( !ras.invalid )
-        gray_record_cell( RAS_VAR );
+    /* record the current one if it is valid */
+    if ( !ras.invalid )
+      gray_record_cell( RAS_VAR );
 
-      ras.area  = 0;
-      ras.cover = 0;
-      ras.ex    = ex;
-      ras.ey    = ey;
-    }
+    ras.area  = 0;
+    ras.cover = 0;
+    ras.ex    = ex;
+    ras.ey    = ey;
 
     ras.invalid = ( ey >= ras.max_ey || ey < ras.min_ey ||
                     ex >= ras.max_ex );
@@ -908,8 +894,8 @@ typedef ptrdiff_t  FT_PtrDist;
     else                                  /* any other line */
     {
       TPos  prod = dx * fy1 - dy * fx1;
-      FT_UDIVPREP( dx );
-      FT_UDIVPREP( dy );
+      FT_UDIVPREP( ex1 != ex2, dx );
+      FT_UDIVPREP( ey1 != ey2, dy );
 
 
       /* The fundamental value `prod' determines which side and the  */
@@ -1316,9 +1302,6 @@ typedef ptrdiff_t  FT_PtrDist;
     int  y;
 
 
-    if ( ras.num_cells == 0 )
-      return;
-
     FT_TRACE7(( "gray_sweep: start\n" ));
 
     for ( y = ras.min_ey; y < ras.max_ey; y++ )
@@ -1718,12 +1701,14 @@ typedef ptrdiff_t  FT_PtrDist;
   FT_DEFINE_OUTLINE_FUNCS(
     func_interface,
 
-    (FT_Outline_MoveTo_Func) gray_move_to,
-    (FT_Outline_LineTo_Func) gray_line_to,
-    (FT_Outline_ConicTo_Func)gray_conic_to,
-    (FT_Outline_CubicTo_Func)gray_cubic_to,
-    0,
-    0 )
+    (FT_Outline_MoveTo_Func) gray_move_to,   /* move_to  */
+    (FT_Outline_LineTo_Func) gray_line_to,   /* line_to  */
+    (FT_Outline_ConicTo_Func)gray_conic_to,  /* conic_to */
+    (FT_Outline_CubicTo_Func)gray_cubic_to,  /* cubic_to */
+
+    0,                                       /* shift    */
+    0                                        /* delta    */
+  )
 
 
   static int
@@ -1813,21 +1798,18 @@ typedef ptrdiff_t  FT_PtrDist;
           cell_start = ( ycount * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
                        sizeof ( TCell );
 
-          if ( FT_MAX_GRAY_POOL - cell_start < 2 )
-            goto ReduceBands;
-
           ras.cells     = buffer + cell_start;
           ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - cell_start );
+          ras.num_cells = 0;
 
           ras.ycells = (PCell*)buffer;
           while ( ycount )
             ras.ycells[--ycount] = NULL;
         }
 
-        ras.num_cells = 0;
         ras.invalid   = 1;
         ras.min_ey    = band[1];
-        ras.max_ey    = ras.ey = band[0];
+        ras.max_ey    = band[0];
 
         error = gray_convert_glyph_inner( RAS_VAR );
 
@@ -1845,7 +1827,6 @@ typedef ptrdiff_t  FT_PtrDist;
           return 1;
         }
 
-      ReduceBands:
         /* render pool overflow; we will reduce the render band by half */
         width >>= 1;
 
@@ -1878,8 +1859,8 @@ typedef ptrdiff_t  FT_PtrDist;
   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;
+    const FT_Outline*  outline    = (const FT_Outline*)params->source;
+    const FT_Bitmap*   target_map = params->target;
     FT_BBox            cbox, clip;
 
 #ifndef FT_STATIC_RASTER
@@ -2003,7 +1984,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
 
     *araster = (FT_Raster)&the_raster;
-    FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
+    FT_ZERO( &the_raster );
 
     return 0;
   }
@@ -2079,11 +2060,12 @@ typedef ptrdiff_t  FT_PtrDist;
 
     FT_GLYPH_FORMAT_OUTLINE,
 
-    (FT_Raster_New_Func)     gray_raster_new,
-    (FT_Raster_Reset_Func)   gray_raster_reset,
-    (FT_Raster_Set_Mode_Func)gray_raster_set_mode,
-    (FT_Raster_Render_Func)  gray_raster_render,
-    (FT_Raster_Done_Func)    gray_raster_done )
+    (FT_Raster_New_Func)     gray_raster_new,       /* raster_new      */
+    (FT_Raster_Reset_Func)   gray_raster_reset,     /* raster_reset    */
+    (FT_Raster_Set_Mode_Func)gray_raster_set_mode,  /* raster_set_mode */
+    (FT_Raster_Render_Func)  gray_raster_render,    /* raster_render   */
+    (FT_Raster_Done_Func)    gray_raster_done       /* raster_done     */
+  )
 
 
 /* END */
index 7927676..5f6aa60 100644 (file)
@@ -87,7 +87,7 @@
                       FT_GlyphSlot  slot,
                       FT_BBox*      cbox )
   {
-    FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
+    FT_ZERO( cbox );
 
     if ( slot->format == render->glyph_format )
       FT_Outline_Get_CBox( &slot->outline, cbox );
 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
     FT_Pos       height_org, width_org;
 #endif
-    FT_Int       hmul    = mode == FT_RENDER_MODE_LCD;
-    FT_Int       vmul    = mode == FT_RENDER_MODE_LCD_V;
+    FT_Int       hmul    = ( mode == FT_RENDER_MODE_LCD );
+    FT_Int       vmul    = ( mode == FT_RENDER_MODE_LCD_V );
 
     FT_Raster_Params  params;
 
   }
 
 
-  FT_DEFINE_RENDERER( ft_smooth_renderer_class,
+  FT_DEFINE_RENDERER(
+    ft_smooth_renderer_class,
 
       FT_MODULE_RENDERER,
       sizeof ( FT_RendererRec ),
       0x10000L,
       0x20000L,
 
-      0,    /* module specific interface */
+      NULL,    /* module specific interface */
 
-      (FT_Module_Constructor)ft_smooth_init,
-      (FT_Module_Destructor) 0,
-      (FT_Module_Requester)  0
-    ,
+      (FT_Module_Constructor)ft_smooth_init,  /* module_init   */
+      (FT_Module_Destructor) NULL,            /* module_done   */
+      (FT_Module_Requester)  NULL,            /* get_interface */
 
     FT_GLYPH_FORMAT_OUTLINE,
 
-    (FT_Renderer_RenderFunc)   ft_smooth_render,
-    (FT_Renderer_TransformFunc)ft_smooth_transform,
-    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
-    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
+    (FT_Renderer_RenderFunc)   ft_smooth_render,     /* render_glyph    */
+    (FT_Renderer_TransformFunc)ft_smooth_transform,  /* transform_glyph */
+    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,   /* get_glyph_cbox  */
+    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,   /* set_mode        */
 
-    (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
+    (FT_Raster_Funcs*)&FT_GRAYS_RASTER_GET           /* raster_class    */
   )
 
 
-  FT_DEFINE_RENDERER( ft_smooth_lcd_renderer_class,
+  FT_DEFINE_RENDERER(
+    ft_smooth_lcd_renderer_class,
 
       FT_MODULE_RENDERER,
       sizeof ( FT_RendererRec ),
       0x10000L,
       0x20000L,
 
-      0,    /* module specific interface */
+      NULL,    /* module specific interface */
 
-      (FT_Module_Constructor)ft_smooth_init,
-      (FT_Module_Destructor) 0,
-      (FT_Module_Requester)  0
-    ,
+      (FT_Module_Constructor)ft_smooth_init,  /* module_init   */
+      (FT_Module_Destructor) NULL,            /* module_done   */
+      (FT_Module_Requester)  NULL,            /* get_interface */
 
     FT_GLYPH_FORMAT_OUTLINE,
 
-    (FT_Renderer_RenderFunc)   ft_smooth_render_lcd,
-    (FT_Renderer_TransformFunc)ft_smooth_transform,
-    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
-    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
+    (FT_Renderer_RenderFunc)   ft_smooth_render_lcd,  /* render_glyph    */
+    (FT_Renderer_TransformFunc)ft_smooth_transform,   /* transform_glyph */
+    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,    /* get_glyph_cbox  */
+    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,    /* set_mode        */
 
-    (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
+    (FT_Raster_Funcs*)&FT_GRAYS_RASTER_GET            /* raster_class    */
   )
 
-  FT_DEFINE_RENDERER( ft_smooth_lcdv_renderer_class,
+
+  FT_DEFINE_RENDERER(
+    ft_smooth_lcdv_renderer_class,
 
       FT_MODULE_RENDERER,
       sizeof ( FT_RendererRec ),
       0x10000L,
       0x20000L,
 
-      0,    /* module specific interface */
+      NULL,    /* module specific interface */
 
-      (FT_Module_Constructor)ft_smooth_init,
-      (FT_Module_Destructor) 0,
-      (FT_Module_Requester)  0
-    ,
+      (FT_Module_Constructor)ft_smooth_init,  /* module_init   */
+      (FT_Module_Destructor) NULL,            /* module_done   */
+      (FT_Module_Requester)  NULL,            /* get_interface */
 
     FT_GLYPH_FORMAT_OUTLINE,
 
-    (FT_Renderer_RenderFunc)   ft_smooth_render_lcd_v,
-    (FT_Renderer_TransformFunc)ft_smooth_transform,
-    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,
-    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,
+    (FT_Renderer_RenderFunc)   ft_smooth_render_lcd_v,  /* render_glyph    */
+    (FT_Renderer_TransformFunc)ft_smooth_transform,     /* transform_glyph */
+    (FT_Renderer_GetCBoxFunc)  ft_smooth_get_cbox,      /* get_glyph_cbox  */
+    (FT_Renderer_SetModeFunc)  ft_smooth_set_mode,      /* set_mode        */
 
-    (FT_Raster_Funcs*)    &FT_GRAYS_RASTER_GET
+    (FT_Raster_Funcs*)&FT_GRAYS_RASTER_GET              /* raster_class    */
   )
 
 
index 9f81b1a..73bc99d 100644 (file)
@@ -90,14 +90,14 @@ names_add( const char*  name,
     max_names += (max_names >> 1) + 4;
     the_names  = (NameRec*)realloc( the_names,
                                     sizeof ( the_names[0] ) * max_names );
-    if ( the_names == NULL )
+    if ( !the_names )
       panic( "not enough memory" );
   }
   nm = &the_names[num_names++];
 
   nm->hash = h;
   nm->name = (char*)malloc( len+1 );
-  if ( nm->name == NULL )
+  if ( !nm->name )
     panic( "not enough memory" );
 
   memcpy( nm->name, name, len );
@@ -159,7 +159,7 @@ names_dump( FILE*         out,
         char         temp[512];
 
 
-        if ( dll_name == NULL )
+        if ( !dll_name )
         {
           fprintf( stderr,
                    "you must provide a DLL name with the -d option!\n" );
@@ -168,7 +168,7 @@ names_dump( FILE*         out,
 
         /* we must omit the .dll suffix from the library name */
         dot = strchr( dll_name, '.' );
-        if ( dot != NULL )
+        if ( dot )
         {
           int  len = dot - dll_name;
 
@@ -190,7 +190,7 @@ names_dump( FILE*         out,
 
     case OUTPUT_NETWARE_IMP:
       {
-        if ( dll_name != NULL )
+        if ( dll_name )
           fprintf( out, "  (%s)\n", dll_name );
         for ( nn = 0; nn < num_names - 1; nn++ )
           fprintf( out, "  %s,\n", the_names[nn].name );
@@ -371,7 +371,7 @@ int  main( int argc, const char* const*  argv )
           arg += 2;
 
         out = fopen( arg, "wt" );
-        if ( out == NULL )
+        if ( !out )
         {
           fprintf( stderr, "could not open '%s' for writing\n", argv[2] );
           exit(3);
@@ -440,7 +440,7 @@ int  main( int argc, const char* const*  argv )
     {
       FILE*  file = fopen( argv[0], "rb" );
 
-      if ( file == NULL )
+      if ( !file )
         fprintf( stderr, "unable to open '%s'\n", argv[0] );
       else
       {
index ff31169..ab5cfc9 100644 (file)
 
     FT_Set_Char_Size( face, 0, font_size, 72, 72 );
 
-    for ( gid = 0; gid < face->num_glyphs; ++gid )
+    for ( gid = 0; gid < face->num_glyphs; gid++ )
     {
       if ( check_outlines         &&
            FT_IS_SCALABLE( face ) )
       num = face->num_faces;
       FT_Done_Face( face );
 
-      for ( i = 0; i < num; ++i )
+      for ( i = 0; i < num; i++ )
       {
         if ( !FT_New_Face( context, testfont, i, &face ) )
           TestFace( face );
     char*  pt;
 
 
-    if ( extensions == NULL )
+    if ( !extensions )
       return true;
 
     pt = strrchr( filename, '.' );
-    if ( pt == NULL )
+    if ( !pt )
       return false;
     if ( pt < strrchr( filename, '/' ) )
       return false;
 
-    for ( i = 0; extensions[i] != NULL; ++i )
+    for ( i = 0; extensions[i] != NULL; i++ )
       if ( strcasecmp( pt + 1, extensions[i] ) == 0 ||
            strcasecmp( pt,     extensions[i] ) == 0 )
         return true;
     item->isbinary = item->isascii = item->ishex = false;
 
     foo = fopen( item->name, "rb" );
-    if ( foo != NULL )
+    if ( foo )
     {
       /* Try to guess the file type from the first few characters... */
       int  ch1 = getc( foo );
       else if ( ch1 == '%' && ch2 == '!' )
       {
         /* Random PostScript */
-        if ( strstr( item->name, ".pfa" ) != NULL ||
-             strstr( item->name, ".PFA" ) != NULL )
+        if ( strstr( item->name, ".pfa" ) ||
+             strstr( item->name, ".PFA" ) )
           item->ishex = true;
         else
           item->isascii = true;
     max  = 0;
     fcnt = 0;
 
-    for ( i = 0; fontdirs[i] != NULL; ++i )
+    for ( i = 0; fontdirs[i] != NULL; i++ )
     {
       DIR*            examples;
       struct dirent*  ent;
 
 
       examples = opendir( fontdirs[i] );
-      if ( examples == NULL )
+      if ( !examples )
       {
         fprintf( stderr,
                  "Can't open example font directory `%s'\n",
                   "%s/%s", fontdirs[i], ent->d_name );
         if ( stat( buffer, &statb ) == -1 || S_ISDIR( statb.st_mode ) )
           continue;
-        if ( extensions == NULL || extmatch( buffer, extensions ) )
+        if ( !extensions || extmatch( buffer, extensions ) )
         {
           if ( fcnt >= max )
           {
             max += 100;
             fontlist = realloc( fontlist, max * sizeof ( struct fontlist ) );
-            if ( fontlist == NULL )
+            if ( !fontlist )
             {
               fprintf( stderr, "Can't allocate memory\n" );
               exit( 1 );
           fontlist[fcnt].len  = statb.st_size;
 
           figurefiletype( &fontlist[fcnt] );
-          ++fcnt;
+          fcnt++;
         }
       }
 
             char*             newfont )
   {
     static char   buffer[8096];
-    FILE          *good, *new;
+    FILE          *good, *newf;
     size_t        len;
     unsigned int  i, err_cnt;
 
 
     good = fopen( item->name, "r" );
-    if ( good == NULL )
+    if ( !good )
     {
       fprintf( stderr, "Can't open `%s'\n", item->name );
       return false;
     }
 
-    new = fopen( newfont, "w+" );
-    if ( new == NULL )
+    newf = fopen( newfont, "w+" );
+    if ( !newf )
     {
       fprintf( stderr, "Can't create temporary output file `%s'\n",
                newfont );
     }
 
     while ( ( len = fread( buffer, 1, sizeof ( buffer ), good ) ) > 0 )
-      fwrite( buffer, 1, len, new );
+      fwrite( buffer, 1, len, newf );
 
     fclose( good );
 
     err_cnt = getErrorCnt( item );
-    for ( i = 0; i < err_cnt; ++i )
+    for ( i = 0; i < err_cnt; i++ )
     {
-      fseek( new, getRandom( 0, (int)( item->len - 1 ) ), SEEK_SET );
+      fseek( newf, getRandom( 0, (int)( item->len - 1 ) ), SEEK_SET );
 
       if ( item->isbinary )
-        putc( getRandom( 0, 0xFF ), new );
+        putc( getRandom( 0, 0xFF ), newf );
       else if ( item->isascii )
-        putc( getRandom( 0x20, 0x7E ), new );
+        putc( getRandom( 0x20, 0x7E ), newf );
       else
       {
         int  hex = getRandom( 0, 15 );
         else
           hex += 'A' - 10;
 
-        putc( hex, new );
+        putc( hex, newf );
       }
     }
 
-    if ( ferror( new ) )
+    if ( ferror( newf ) )
     {
-      fclose( new );
+      fclose( newf );
       unlink( newfont );
       return false;
     }
 
-    fclose( new );
+    fclose( newf );
 
     return true;
   }
     dirs = calloc( (size_t)( argc + 1 ), sizeof ( char ** ) );
     exts = calloc( (size_t)( argc + 1 ), sizeof ( char ** ) );
 
-    for ( i = 1; i < argc; ++i )
+    for ( i = 1; i < argc; i++ )
     {
       char*  pt = argv[i];
       char*  end;
 
 
       if ( pt[0] == '-' && pt[1] == '-' )
-        ++pt;
+        pt++;
 
       if ( strcmp( pt, "-all" ) == 0 )
         allexts = true;
       dirs = default_dir_list;
     }
 
-    if ( testfile != NULL )
+    if ( testfile )
       ExecuteTest( testfile );         /* This should never return */
 
     time( &now );
index 0729c2b..3569f06 100644 (file)
@@ -415,7 +415,7 @@ t1_expert_encoding = \
 # This data has been taken literally from the files `glyphlist.txt'
 # and `zapfdingbats.txt' version 2.0, Sept 2002.  It is available from
 #
-#   http://sourceforge.net/adobe/aglfn/
+#   https://github.com/adobe-type-tools/agl-aglfn
 #
 adobe_glyph_list = """\
 A;0041
@@ -4920,8 +4920,17 @@ class StringTable:
 
   def dump( self, file ):
     write = file.write
-    write( "  static const char  " + self.master_table +
-           "[" + repr( self.total ) + "] =\n" )
+    write( "#ifndef  DEFINE_PS_TABLES\n" )
+    write( "#ifdef  __cplusplus\n" )
+    write( '  extern "C"\n' )
+    write( "#else\n" )
+    write( "  extern\n" )
+    write( "#endif\n" )
+    write( "#endif\n" )
+    write( "  const char  " + self.master_table +
+           "[" + repr( self.total ) + "]\n" )
+    write( "#ifdef  DEFINE_PS_TABLES\n" )
+    write( "  =\n" )
     write( "  {\n" )
 
     line = ""
@@ -4930,7 +4939,10 @@ class StringTable:
       line += string.join( ( re.findall( ".", name ) ), "','" )
       line += "', 0,\n"
 
-    write( line + "  };\n\n\n" )
+    write( line )
+    write( "  }\n" )
+    write( "#endif /* DEFINE_PS_TABLES */\n" )
+    write( "  ;\n\n\n" )
 
   def dump_sublist( self, file, table_name, macro_name, sublist ):
     write = file.write
@@ -4938,8 +4950,17 @@ class StringTable:
 
     write( "  /* Values are offsets into the `" +
            self.master_table + "' table */\n\n" )
-    write( "  static const short  " + table_name +
-           "[" + macro_name + "] =\n" )
+    write( "#ifndef  DEFINE_PS_TABLES\n" )
+    write( "#ifdef  __cplusplus\n" )
+    write( '  extern "C"\n' )
+    write( "#else\n" )
+    write( "  extern\n" )
+    write( "#endif\n" )
+    write( "#endif\n" )
+    write( "  const short  " + table_name +
+           "[" + macro_name + "]\n" )
+    write( "#ifdef  DEFINE_PS_TABLES\n" )
+    write( "  =\n" )
     write( "  {\n" )
 
     line  = "    "
@@ -4955,7 +4976,11 @@ class StringTable:
         col   = 0
         comma = ",\n    "
 
-    write( line + "\n  };\n\n\n" )
+    write( line )
+    write( "\n" )
+    write( "  }\n" )
+    write( "#endif /* DEFINE_PS_TABLES */\n" )
+    write( "  ;\n\n\n" )
 
 
 # We now store the Adobe Glyph List in compressed form.  The list is put
@@ -5188,8 +5213,17 @@ def dump_encoding( file, encoding_name, encoding_list ):
 
   write = file.write
   write( "  /* the following are indices into the SID name table */\n" )
-  write( "  static const unsigned short  " + encoding_name +
-         "[" + repr( len( encoding_list ) ) + "] =\n" )
+  write( "#ifndef  DEFINE_PS_TABLES\n" )
+  write( "#ifdef  __cplusplus\n" )
+  write( '  extern "C"\n' )
+  write( "#else\n" )
+  write( "  extern\n" )
+  write( "#endif\n" )
+  write( "#endif\n" )
+  write( "  const unsigned short  " + encoding_name +
+         "[" + repr( len( encoding_list ) ) + "]\n" )
+  write( "#ifdef  DEFINE_PS_TABLES\n" )
+  write( "  =\n" )
   write( "  {\n" )
 
   line  = "    "
@@ -5204,14 +5238,27 @@ def dump_encoding( file, encoding_name, encoding_list ):
       col = 0
       comma = ",\n    "
 
-  write( line + "\n  };\n\n\n" )
+  write( line )
+  write( "\n" )
+  write( "  }\n" )
+  write( "#endif /* DEFINE_PS_TABLES */\n" )
+  write( "  ;\n\n\n" )
 
 
 def dump_array( the_array, write, array_name ):
   """dumps a given encoding"""
 
-  write( "  static const unsigned char  " + array_name +
-         "[" + repr( len( the_array ) ) + "L] =\n" )
+  write( "#ifndef  DEFINE_PS_TABLES\n" )
+  write( "#ifdef  __cplusplus\n" )
+  write( '  extern "C"\n' )
+  write( "#else\n" )
+  write( "  extern\n" )
+  write( "#endif\n" )
+  write( "#endif\n" )
+  write( "  const unsigned char  " + array_name +
+         "[" + repr( len( the_array ) ) + "L]\n" )
+  write( "#ifdef  DEFINE_PS_TABLES\n" )
+  write( "  =\n" )
   write( "  {\n" )
 
   line  = ""
@@ -5232,7 +5279,11 @@ def dump_array( the_array, write, array_name ):
       write( line )
       line = ""
 
-  write( line + "\n  };\n\n\n" )
+  write( line )
+  write( "\n" )
+  write( "  }\n" )
+  write( "#endif /* DEFINE_PS_TABLES */\n" )
+  write( "  ;\n\n\n" )
 
 
 def main():
@@ -5267,7 +5318,7 @@ def main():
   write( "/*                                                                         */\n" )
   write( "/*    PostScript glyph names.                                              */\n" )
   write( "/*                                                                         */\n" )
-  write( "/*  Copyright 2005-2015 by                                                 */\n" )
+  write( "/*  Copyright 2005-2016 by                                                 */\n" )
   write( "/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */\n" )
   write( "/*                                                                         */\n" )
   write( "/*  This file is part of the FreeType project, and may only be used,       */\n" )
index 6520c93..af8b205 100644 (file)
@@ -25,6 +25,7 @@
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 #include FT_MULTIPLE_MASTERS_H
 #include FT_SERVICE_MULTIPLE_MASTERS_H
+#include FT_SERVICE_METRICS_VARIATIONS_H
 #endif
 
 #include FT_SERVICE_TRUETYPE_ENGINE_H
 
   FT_DEFINE_SERVICE_PROPERTIESREC(
     tt_service_properties,
+
     (FT_Properties_SetFunc)tt_property_set,     /* set_property */
-    (FT_Properties_GetFunc)tt_property_get )    /* get_property */
+    (FT_Properties_GetFunc)tt_property_get      /* get_property */
+  )
 
 
   /*************************************************************************/
                    FT_Fixed  *advances )
   {
     FT_UInt  nn;
-    TT_Face  face = (TT_Face) ttface;
+    TT_Face  face = (TT_Face)ttface;
 
 
     /* XXX: TODO: check for sbits */
 
     if ( flags & FT_LOAD_VERTICAL_LAYOUT )
     {
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+      /* no fast retrieval for blended MM fonts without VVAR table */
+      if ( !face->is_default_instance                               &&
+           !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+        return FT_THROW( Unimplemented_Feature );
+#endif
+
       for ( nn = 0; nn < count; nn++ )
       {
         FT_Short   tsb;
     }
     else
     {
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+      /* no fast retrieval for blended MM fonts without HVAR table */
+      if ( !face->is_default_instance                               &&
+           !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+        return FT_THROW( Unimplemented_Feature );
+#endif
+
       for ( nn = 0; nn < count; nn++ )
       {
         FT_Short   lsb;
     }
     else
     {
-      SFNT_Service      sfnt    = (SFNT_Service) ttface->sfnt;
+      SFNT_Service      sfnt    = (SFNT_Service)ttface->sfnt;
       FT_Size_Metrics*  metrics = &size->metrics;
 
 
     if ( FT_HAS_FIXED_SIZES( size->face ) )
     {
       TT_Face       ttface = (TT_Face)size->face;
-      SFNT_Service  sfnt   = (SFNT_Service) ttface->sfnt;
+      SFNT_Service  sfnt   = (SFNT_Service)ttface->sfnt;
       FT_ULong      strike_index;
 
 
   /*************************************************************************/
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
   FT_DEFINE_SERVICE_MULTIMASTERSREC(
     tt_service_gx_multi_masters,
+
     (FT_Get_MM_Func)        NULL,                   /* get_mm         */
     (FT_Set_MM_Design_Func) NULL,                   /* set_mm_design  */
     (FT_Set_MM_Blend_Func)  TT_Set_MM_Blend,        /* set_mm_blend   */
+    (FT_Get_MM_Blend_Func)  TT_Get_MM_Blend,        /* get_mm_blend   */
     (FT_Get_MM_Var_Func)    TT_Get_MM_Var,          /* get_mm_var     */
-    (FT_Set_Var_Design_Func)TT_Set_Var_Design )     /* set_var_design */
-#endif
+    (FT_Set_Var_Design_Func)TT_Set_Var_Design,      /* set_var_design */
+    (FT_Get_Var_Design_Func)TT_Get_Var_Design,      /* get_var_design */
+
+    (FT_Get_Var_Blend_Func) tt_get_var_blend,       /* get_var_blend  */
+    (FT_Done_Blend_Func)    tt_done_blend           /* done_blend     */
+  )
+
+  FT_DEFINE_SERVICE_METRICSVARIATIONSREC(
+    tt_service_metrics_variations,
+
+    (FT_HAdvance_Adjust_Func)tt_hadvance_adjust,     /* hadvance_adjust */
+    (FT_LSB_Adjust_Func)     NULL,                   /* lsb_adjust      */
+    (FT_RSB_Adjust_Func)     NULL,                   /* rsb_adjust      */
+
+    (FT_VAdvance_Adjust_Func)NULL,                   /* vadvance_adjust */
+    (FT_TSB_Adjust_Func)     NULL,                   /* tsb_adjust      */
+    (FT_BSB_Adjust_Func)     NULL,                   /* bsb_adjust      */
+    (FT_VOrg_Adjust_Func)    NULL,                   /* vorg_adjust     */
+
+    (FT_Metrics_Adjust_Func) NULL                    /* metrics_adjust  */
+  )
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
 
 
   static const FT_Service_TrueTypeEngineRec  tt_service_truetype_engine =
 
   FT_DEFINE_SERVICE_TTGLYFREC(
     tt_service_truetype_glyf,
-    (TT_Glyf_GetLocationFunc)tt_face_get_location )    /* get_location */
+
+    (TT_Glyf_GetLocationFunc)tt_face_get_location      /* get_location */
+  )
 
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-  FT_DEFINE_SERVICEDESCREC5(
+  FT_DEFINE_SERVICEDESCREC6(
     tt_services,
-    FT_SERVICE_ID_FONT_FORMAT,     FT_FONT_FORMAT_TRUETYPE,
-    FT_SERVICE_ID_MULTI_MASTERS,   &TT_SERVICE_GX_MULTI_MASTERS_GET,
-    FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
-    FT_SERVICE_ID_TT_GLYF,         &TT_SERVICE_TRUETYPE_GLYF_GET,
-    FT_SERVICE_ID_PROPERTIES,      &TT_SERVICE_PROPERTIES_GET )
+
+    FT_SERVICE_ID_FONT_FORMAT,        FT_FONT_FORMAT_TRUETYPE,
+    FT_SERVICE_ID_MULTI_MASTERS,      &TT_SERVICE_GX_MULTI_MASTERS_GET,
+    FT_SERVICE_ID_METRICS_VARIATIONS, &TT_SERVICE_METRICS_VARIATIONS_GET,
+    FT_SERVICE_ID_TRUETYPE_ENGINE,    &tt_service_truetype_engine,
+    FT_SERVICE_ID_TT_GLYF,            &TT_SERVICE_TRUETYPE_GLYF_GET,
+    FT_SERVICE_ID_PROPERTIES,         &TT_SERVICE_PROPERTIES_GET )
 #else
   FT_DEFINE_SERVICEDESCREC4(
     tt_services,
+
     FT_SERVICE_ID_FONT_FORMAT,     FT_FONT_FORMAT_TRUETYPE,
     FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
     FT_SERVICE_ID_TT_GLYF,         &TT_SERVICE_TRUETYPE_GLYF_GET,
 #endif
 
     result = ft_service_list_lookup( TT_SERVICES_GET, tt_interface );
-    if ( result != NULL )
+    if ( result )
       return result;
 
 #ifndef FT_CONFIG_OPTION_PIC
       0x10000L,        /* driver version == 1.0                 */
       0x20000L,        /* driver requires FreeType 2.0 or above */
 
-      0,    /* module-specific interface */
+      NULL,    /* module-specific interface */
 
       tt_driver_init,           /* FT_Module_Constructor  module_init   */
       tt_driver_done,           /* FT_Module_Destructor   module_done   */
     tt_size_init,               /* FT_Size_InitFunc  init_size */
     tt_size_done,               /* FT_Size_DoneFunc  done_size */
     tt_slot_init,               /* FT_Slot_InitFunc  init_slot */
-    0,                          /* FT_Slot_DoneFunc  done_slot */
+    NULL,                       /* FT_Slot_DoneFunc  done_slot */
 
     tt_glyph_load,              /* FT_Slot_LoadFunc  load_glyph */
 
     tt_get_kerning,             /* FT_Face_GetKerningFunc   get_kerning  */
-    0,                          /* FT_Face_AttachFunc       attach_file  */
+    NULL,                       /* FT_Face_AttachFunc       attach_file  */
     tt_get_advances,            /* FT_Face_GetAdvancesFunc  get_advances */
 
     tt_size_request,            /* FT_Size_RequestFunc  request_size */
index 2d0b29f..a0cdfc8 100644 (file)
     flag       = (FT_Byte*)outline->tags;
     flag_limit = flag + n_points;
 
-    FT_ASSERT( flag != NULL );
+    FT_ASSERT( flag );
 
     while ( flag < flag_limit )
     {
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
-    if ( loader->face->doblend )
+    if ( loader->face->doblend && !loader->face->is_default_instance )
     {
       /* Deltas apply to the unscaled data. */
       error = TT_Vary_Apply_Glyph_Deltas( loader->face,
                                           loader->glyph_index,
                                           outline,
                                           (FT_UInt)n_points );
+
+      /* recalculate linear horizontal and vertical advances */
+      /* if we don't have HVAR and VVAR, respectively        */
+      if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+        loader->linear = outline->points[n_points - 3].x -
+                         outline->points[n_points - 4].x;
+      if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+        loader->vadvance = outline->points[n_points - 1].x -
+                           outline->points[n_points - 2].x;
+
       if ( error )
         return error;
     }
       offset            = 0;
       loader->byte_len  = glyph_data.length;
 
-      FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
+      FT_ZERO( &inc_stream );
       FT_Stream_OpenMemory( &inc_stream,
                             glyph_data.pointer,
                             (FT_ULong)glyph_data.length );
     {
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
       /* for the incremental interface, `glyf_offset' is always zero */
-      if ( !loader->glyf_offset                        &&
+      if ( !face->glyf_offset                          &&
            !face->root.internal->incremental_interface )
 #else
-      if ( !loader->glyf_offset )
+      if ( !face->glyf_offset )
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
       {
         FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
       }
 
       error = face->access_glyph_frame( loader, glyph_index,
-                                        loader->glyf_offset + offset,
+                                        face->glyf_offset + offset,
                                         (FT_UInt)loader->byte_len );
       if ( error )
         goto Exit;
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
-      if ( loader->face->doblend )
+      if ( loader->face->doblend && !loader->face->is_default_instance )
       {
         /* a small outline structure with four elements for */
         /* communication with `TT_Vary_Apply_Glyph_Deltas'  */
         loader->pp3.y = points[2].y;
         loader->pp4.x = points[3].x;
         loader->pp4.y = points[3].y;
+
+
+        /* recalculate linear horizontal and vertical advances */
+        /* if we don't have HVAR and VVAR, respectively        */
+        if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+          loader->linear = loader->pp2.x - loader->pp1.x;
+        if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+          loader->vadvance = loader->pp4.x - loader->pp3.x;
       }
 
 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
-      if ( face->doblend )
+      if ( face->doblend && !face->is_default_instance )
       {
         short        i, limit;
         FT_SubGlyph  subglyph;
 
         /* this call provides additional offsets */
         /* for each component's translation      */
-        if ( ( error = TT_Vary_Apply_Glyph_Deltas(
-                         face,
-                         glyph_index,
-                         &outline,
-                         (FT_UInt)outline.n_points ) ) != 0 )
+        if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas(
+                             face,
+                             glyph_index,
+                             &outline,
+                             (FT_UInt)outline.n_points ) ) )
           goto Exit1;
 
         subglyph = gloader->current.subglyphs;
         loader->pp4.x = points[i + 3].x;
         loader->pp4.y = points[i + 3].y;
 
+        /* recalculate linear horizontal and vertical advances */
+        /* if we don't have HVAR and VVAR, respectively        */
+        if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+          loader->linear = loader->pp2.x - loader->pp1.x;
+        if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+          loader->vadvance = loader->pp4.x - loader->pp3.x;
+
       Exit1:
         FT_FREE( outline.points );
         FT_FREE( outline.tags );
         {
           FT_Vector  pp[4];
 
+          FT_Int  linear_hadvance;
+          FT_Int  linear_vadvance;
+
 
           /* Each time we call load_truetype_glyph in this loop, the   */
           /* value of `gloader.base.subglyphs' can change due to table */
           pp[2] = loader->pp3;
           pp[3] = loader->pp4;
 
+          linear_hadvance = loader->linear;
+          linear_vadvance = loader->vadvance;
+
           num_base_points = (FT_UInt)gloader->base.outline.n_points;
 
           error = load_truetype_glyph( loader,
             loader->pp2 = pp[1];
             loader->pp3 = pp[2];
             loader->pp4 = pp[3];
+
+            loader->linear   = linear_hadvance;
+            loader->vadvance = linear_vadvance;
           }
 
           num_points = (FT_UInt)gloader->base.outline.n_points;
     face   = (TT_Face)glyph->face;
     stream = face->root.stream;
 
-    FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
+    FT_ZERO( loader );
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
 
 
 #endif /* TT_USE_BYTECODE_INTERPRETER */
 
-    /* seek to the beginning of the glyph table -- for Type 42 fonts     */
-    /* the table might be accessed from a Postscript stream or something */
-    /* else...                                                           */
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
-
-    if ( face->root.internal->incremental_interface )
-      loader->glyf_offset = 0;
-    else
-
-#endif
-
-    {
-      error = face->goto_table( face, TTAG_glyf, stream, 0 );
-
-      if ( FT_ERR_EQ( error, Table_Missing ) )
-        loader->glyf_offset = 0;
-      else if ( error )
-      {
-        FT_ERROR(( "tt_loader_init: could not access glyph table\n" ));
-        return error;
-      }
-      else
-        loader->glyf_offset = FT_STREAM_POS();
-    }
-
     /* get face's glyph loader */
     if ( !glyf_table_only )
     {
     FT_Error      error;
     TT_LoaderRec  loader;
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#define IS_DEFAULT_INSTANCE  ( ( (TT_Face)glyph->face )->is_default_instance )
+#else
+#define IS_DEFAULT_INSTANCE  1
+#endif
+
 
     FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
 
 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
-    /* try to load embedded bitmap if any              */
-    /*                                                 */
-    /* XXX: The convention should be emphasized in     */
-    /*      the documents because it can be confusing. */
+    /* try to load embedded bitmap (if any) */
     if ( size->strike_index != 0xFFFFFFFFUL      &&
-         ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
+         ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
+         IS_DEFAULT_INSTANCE                     )
     {
       error = load_sbit_image( size, glyph, glyph_index, load_flags );
       if ( !error )
index c0d013c..cf4f7b1 100644 (file)
         segment->correspondence[j].fromCoord = FT_GET_SHORT() * 4;
         segment->correspondence[j].toCoord   = FT_GET_SHORT() * 4;
 
-        FT_TRACE5(( "    mapping %.4f to %.4f\n",
+        FT_TRACE5(( "    mapping %.5f to %.5f\n",
                     segment->correspondence[j].fromCoord / 65536.0,
                     segment->correspondence[j].toCoord / 65536.0 ));
       }
   }
 
 
+  /* some macros we need */
+  #define FT_FIXED_ONE  ( (FT_Fixed)0x10000 )
+
+  #define FT_fdot14ToFixed( x )                    \
+          ( ( (FT_Fixed)( (FT_Int16)(x) ) ) << 2 )
+  #define FT_intToFixed( i )                     \
+          ( (FT_Fixed)( (FT_UInt32)(i) << 16 ) )
+  #define FT_fixedToInt( x )                                   \
+          ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_var_load_hvar                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parse the `HVAR' table and set `blend->hvar_loaded' to TRUE.       */
+  /*                                                                       */
+  /*    On success, `blend->hvar_checked' is set to TRUE.                  */
+  /*                                                                       */
+  /*    Some memory may remain allocated on error; it is always freed in   */
+  /*    `tt_done_blend', however.                                          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face :: The font face.                                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  ft_var_load_hvar( TT_Face  face )
+  {
+    FT_Stream  stream = FT_FACE_STREAM( face );
+    FT_Memory  memory = stream->memory;
+
+    GX_Blend  blend = face->blend;
+
+    FT_Error   error;
+    FT_UShort  majorVersion;
+    FT_ULong   table_len;
+    FT_ULong   table_offset;
+    FT_ULong   store_offset;
+
+    FT_ULong*  dataOffsetArray = NULL;
+
+
+    blend->hvar_loaded = TRUE;
+
+    FT_TRACE2(( "HVAR " ));
+
+    error = face->goto_table( face, TTAG_HVAR, stream, &table_len );
+    if ( error )
+    {
+      FT_TRACE2(( "is missing\n" ));
+      goto Exit;
+    }
+
+    table_offset = FT_STREAM_POS();
+
+    /* skip minor version */
+    if ( FT_READ_USHORT( majorVersion ) ||
+         FT_STREAM_SKIP( 2 )            )
+      goto Exit;
+    if ( majorVersion != 1 )
+    {
+      FT_TRACE2(( "bad table version %d\n", majorVersion ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
+    /* skip map offset */
+    if ( FT_READ_ULONG( store_offset ) ||
+         FT_STREAM_SKIP( 4 )           )
+      goto Exit;
+
+    /* parse item variation store */
+    {
+      FT_UShort  format;
+      FT_ULong   region_offset;
+      FT_UInt    i, j, k;
+      FT_UInt    shortDeltaCount;
+
+      GX_HVStore    itemStore;
+      GX_HVarTable  hvarTable;
+      GX_HVarData   hvarData;
+
+
+      if ( FT_STREAM_SEEK( table_offset + store_offset ) ||
+           FT_READ_USHORT( format )                      )
+        goto Exit;
+      if ( format != 1 )
+      {
+        FT_TRACE2(( "bad store format %d\n", format ));
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+
+      if ( FT_NEW( blend->hvar_table ) )    /* allocate table at top level */
+        goto Exit;
+
+      hvarTable = blend->hvar_table;
+      itemStore = &hvarTable->itemStore;
+
+      /* read top level fields */
+      if ( FT_READ_ULONG( region_offset )         ||
+           FT_READ_USHORT( itemStore->dataCount ) )
+        goto Exit;
+
+      /* make temporary copy of item variation data offsets; */
+      /* we will parse region list first, then come back     */
+      if ( FT_NEW_ARRAY( dataOffsetArray, itemStore->dataCount ) )
+        goto Exit;
+
+      for ( i = 0; i < itemStore->dataCount; i++ )
+      {
+        if ( FT_READ_ULONG( dataOffsetArray[i] ) )
+          goto Exit;
+      }
+
+      /* parse array of region records (region list) */
+      if ( FT_STREAM_SEEK( table_offset + store_offset + region_offset ) )
+        goto Exit;
+
+      if ( FT_READ_USHORT( itemStore->axisCount )   ||
+           FT_READ_USHORT( itemStore->regionCount ) )
+        goto Exit;
+
+      if ( FT_NEW_ARRAY( itemStore->varRegionList, itemStore->regionCount ) )
+        goto Exit;
+
+      for ( i = 0; i < itemStore->regionCount; i++ )
+      {
+        GX_AxisCoords  axisCoords;
+
+
+        if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList,
+                           itemStore->axisCount ) )
+          goto Exit;
+
+        axisCoords = itemStore->varRegionList[i].axisList;
+
+        for ( j = 0; j < itemStore->axisCount; j++ )
+        {
+          FT_Short  start, peak, end;
+
+
+          if ( FT_READ_SHORT( start ) ||
+               FT_READ_SHORT( peak )  ||
+               FT_READ_SHORT( end )   )
+            goto Exit;
+
+          axisCoords[j].startCoord = FT_fdot14ToFixed( start );
+          axisCoords[j].peakCoord  = FT_fdot14ToFixed( peak );
+          axisCoords[j].endCoord   = FT_fdot14ToFixed( end );
+        }
+      }
+
+      /* end of region list parse */
+
+      /* use dataOffsetArray now to parse varData items */
+      if ( FT_NEW_ARRAY( itemStore->varData, itemStore->dataCount ) )
+        goto Exit;
+
+      for ( i = 0; i < itemStore->dataCount; i++ )
+      {
+        hvarData = &itemStore->varData[i];
+
+        if ( FT_STREAM_SEEK( table_offset       +
+                             store_offset       +
+                             dataOffsetArray[i] ) )
+          goto Exit;
+
+        if ( FT_READ_USHORT( hvarData->itemCount )      ||
+             FT_READ_USHORT( shortDeltaCount )          ||
+             FT_READ_USHORT( hvarData->regionIdxCount ) )
+          goto Exit;
+
+        /* check some data consistency */
+        if ( shortDeltaCount > hvarData->regionIdxCount )
+        {
+          FT_TRACE2(( "bad short count %d or region count %d\n",
+                      shortDeltaCount,
+                      hvarData->regionIdxCount ));
+          error = FT_THROW( Invalid_Table );
+          goto Exit;
+        }
+
+        if ( hvarData->regionIdxCount > itemStore->regionCount )
+        {
+          FT_TRACE2(( "inconsistent regionCount %d in varData[%d]\n",
+                      hvarData->regionIdxCount,
+                      i ));
+          error = FT_THROW( Invalid_Table );
+          goto Exit;
+        }
+
+        /* parse region indices */
+        if ( FT_NEW_ARRAY( hvarData->regionIndices,
+                           hvarData->regionIdxCount ) )
+          goto Exit;
+
+        for ( j = 0; j < hvarData->regionIdxCount; j++ )
+        {
+          if ( FT_READ_USHORT( hvarData->regionIndices[j] ) )
+            goto Exit;
+
+          if ( hvarData->regionIndices[j] >= itemStore->regionCount )
+          {
+            FT_TRACE2(( "bad region index %d\n",
+                        hvarData->regionIndices[j] ));
+            error = FT_THROW( Invalid_Table );
+            goto Exit;
+          }
+        }
+
+        /* Parse delta set.                                                */
+        /*                                                                 */
+        /* On input, deltas are ( shortDeltaCount + regionIdxCount ) bytes */
+        /* each; on output, deltas are expanded to `regionIdxCount' shorts */
+        /* each.                                                           */
+        if ( FT_NEW_ARRAY( hvarData->deltaSet,
+                           hvarData->regionIdxCount * hvarData->itemCount ) )
+          goto Exit;
+
+        /* the delta set is stored as a 2-dimensional array of shorts; */
+        /* sign-extend signed bytes to signed shorts                   */
+        for ( j = 0; j < hvarData->itemCount * hvarData->regionIdxCount; )
+        {
+          for ( k = 0; k < shortDeltaCount; k++, j++ )
+          {
+            /* read the short deltas */
+            FT_Short  delta;
+
+
+            if ( FT_READ_SHORT( delta ) )
+              goto Exit;
+
+            hvarData->deltaSet[j] = delta;
+          }
+
+          for ( ; k < hvarData->regionIdxCount; k++, j++ )
+          {
+            /* read the (signed) byte deltas */
+            FT_Char  delta;
+
+
+            if ( FT_READ_CHAR( delta ) )
+              goto Exit;
+
+            hvarData->deltaSet[j] = delta;
+          }
+        }
+      }
+    }
+
+    /* end parse item variation store */
+
+    /* parse width map */
+    {
+      GX_WidthMap  widthMap;
+
+      FT_UShort  format;
+      FT_UInt    entrySize;
+      FT_UInt    innerBitCount;
+      FT_UInt    innerIndexMask;
+      FT_UInt    i, j;
+
+
+      widthMap = &blend->hvar_table->widthMap;
+
+      if ( FT_READ_USHORT( format )             ||
+           FT_READ_USHORT( widthMap->mapCount ) )
+        goto Exit;
+
+      if ( format & 0xFFC0 )
+      {
+        FT_TRACE2(( "bad map format %d\n", format ));
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+
+      /* bytes per entry: 1, 2, 3, or 4 */
+      entrySize      = ( ( format & 0x0030 ) >> 4 ) + 1;
+      innerBitCount  = ( format & 0x000F ) + 1;
+      innerIndexMask = ( 1 << innerBitCount ) - 1;
+
+      if ( FT_NEW_ARRAY( widthMap->innerIndex, widthMap->mapCount ) )
+        goto Exit;
+
+      if ( FT_NEW_ARRAY( widthMap->outerIndex, widthMap->mapCount ) )
+        goto Exit;
+
+      for ( i = 0; i < widthMap->mapCount; i++ )
+      {
+        FT_UInt  mapData = 0;
+        FT_UInt  outerIndex, innerIndex;
+
+
+        /* read map data one unsigned byte at a time, big endian */
+        for ( j = 0; j < entrySize; j++ )
+        {
+          FT_Byte  data;
+
+
+          if ( FT_READ_BYTE( data ) )
+            goto Exit;
+
+          mapData = ( mapData << 8 ) | data;
+        }
+
+        outerIndex = mapData >> innerBitCount;
+
+        if ( outerIndex >= blend->hvar_table->itemStore.dataCount )
+        {
+          FT_TRACE2(( "outerIndex[%d] == %d out of range\n",
+                      i,
+                      outerIndex ));
+          error = FT_THROW( Invalid_Table );
+          goto Exit;
+        }
+
+        widthMap->outerIndex[i] = outerIndex;
+
+        innerIndex = mapData & innerIndexMask;
+
+        if ( innerIndex >=
+               blend->hvar_table->itemStore.varData[outerIndex].itemCount )
+        {
+          FT_TRACE2(( "innerIndex[%d] == %d out of range\n",
+                      i,
+                      innerIndex ));
+          error = FT_THROW( Invalid_Table );
+            goto Exit;
+        }
+
+        widthMap->innerIndex[i] = innerIndex;
+      }
+    }
+
+    /* end parse width map */
+
+    FT_TRACE2(( "loaded\n" ));
+    error = FT_Err_Ok;
+
+  Exit:
+    FT_FREE( dataOffsetArray );
+
+    if ( !error )
+    {
+      blend->hvar_checked = TRUE;
+
+      /* TODO: implement other HVAR stuff */
+      face->variation_support |= TT_FACE_FLAG_VAR_HADVANCE;
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    tt_hadvance_adjust                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Apply HVAR advance width adjustment of a given glyph.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    gindex :: The glyph index.                                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: The font face.                                           */
+  /*                                                                       */
+  /*    adelta :: Points to width value that gets modified.                */
+  /*                                                                       */
+  FT_LOCAL_DEF( FT_Error )
+  tt_hadvance_adjust( TT_Face  face,
+                      FT_UInt  gindex,
+                      FT_Int  *avalue )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+    GX_HVarData  varData;
+
+    FT_UInt    innerIndex, outerIndex;
+    FT_UInt    master, j;
+    FT_Fixed   netAdjustment = 0;     /* accumulated adjustment */
+    FT_Fixed   scaledDelta;
+    FT_Short*  deltaSet;
+    FT_Fixed   delta;
+
+
+    if ( !face->doblend || !face->blend )
+      goto Exit;
+
+    if ( !face->blend->hvar_loaded )
+    {
+      /* initialize hvar table */
+      face->blend->hvar_error = ft_var_load_hvar( face );
+    }
+
+    if ( !face->blend->hvar_checked )
+    {
+      error = face->blend->hvar_error;
+      goto Exit;
+    }
+
+    /* advance width adjustments are always present in an `HVAR' table, */
+    /* so need to test for this capability                              */
+
+    if ( gindex >= face->blend->hvar_table->widthMap.mapCount )
+    {
+      FT_TRACE2(( "gindex %d out of range\n", gindex ));
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    /* trust that HVAR parser has checked indices */
+    outerIndex = face->blend->hvar_table->widthMap.outerIndex[gindex];
+    innerIndex = face->blend->hvar_table->widthMap.innerIndex[gindex];
+    varData    = &face->blend->hvar_table->itemStore.varData[outerIndex];
+    deltaSet   = &varData->deltaSet[varData->regionIdxCount * innerIndex];
+
+    /* See pseudo code from `Font Variations Overview' */
+    /* in the OpenType specification.                  */
+
+    /* outer loop steps through master designs to be blended */
+    for ( master = 0; master < varData->regionIdxCount; master++ )
+    {
+      FT_Fixed  scalar      = FT_FIXED_ONE;
+      FT_UInt   regionIndex = varData->regionIndices[master];
+
+      GX_AxisCoords  axis = face->blend
+                              ->hvar_table
+                              ->itemStore.varRegionList[regionIndex]
+                                         .axisList;
+
+
+      /* inner loop steps through axes in this region */
+      for ( j = 0;
+            j < face->blend->hvar_table->itemStore.axisCount;
+            j++, axis++ )
+      {
+        FT_Fixed  axisScalar;
+
+
+        /* compute the scalar contribution of this axis; */
+        /* ignore invalid ranges                         */
+        if ( axis->startCoord > axis->peakCoord ||
+             axis->peakCoord > axis->endCoord   )
+          axisScalar = FT_FIXED_ONE;
+
+        else if ( axis->startCoord < 0 &&
+                  axis->endCoord > 0   &&
+                  axis->peakCoord != 0 )
+          axisScalar = FT_FIXED_ONE;
+
+        /* peak of 0 means ignore this axis */
+        else if ( axis->peakCoord == 0 )
+          axisScalar = FT_FIXED_ONE;
+
+        /* ignore this region if coords are out of range */
+        else if ( face->blend->normalizedcoords[j] < axis->startCoord ||
+                  face->blend->normalizedcoords[j] > axis->endCoord   )
+          axisScalar = 0;
+
+        /* calculate a proportional factor */
+        else
+        {
+          if ( face->blend->normalizedcoords[j] == axis->peakCoord )
+            axisScalar = FT_FIXED_ONE;
+          else if ( face->blend->normalizedcoords[j] < axis->peakCoord )
+            axisScalar =
+              FT_DivFix( face->blend->normalizedcoords[j] - axis->startCoord,
+                         axis->peakCoord - axis->startCoord );
+          else
+            axisScalar =
+              FT_DivFix( axis->endCoord - face->blend->normalizedcoords[j],
+                         axis->endCoord - axis->peakCoord );
+        }
+
+        /* take product of all the axis scalars */
+        scalar = FT_MulFix( scalar, axisScalar );
+
+      } /* per-axis loop */
+
+      /* get the scaled delta for this region */
+      delta       = FT_intToFixed( deltaSet[master] );
+      scaledDelta = FT_MulFix( scalar, delta );
+
+      /* accumulate the adjustments from each region */
+      netAdjustment = netAdjustment + scaledDelta;
+
+    } /* per-region loop */
+
+    /* apply the accumulated adjustment to derive the interpolated value */
+    FT_TRACE5(( "horizontal width %d adjusted by %d units (HVAR)\n",
+                *avalue,
+                FT_fixedToInt( netAdjustment ) ));
+
+    *avalue += FT_fixedToInt( netAdjustment );
+
+  Exit:
+    return error;
+  }
+
+
   typedef struct  GX_GVar_Head_
   {
     FT_Long    version;
 
     FT_TRACE2(( "GVAR " ));
 
-    if ( ( error = face->goto_table( face,
-                                     TTAG_gvar,
-                                     stream,
-                                     &table_len ) ) != 0 )
+    if ( FT_SET_ERROR( face->goto_table( face,
+                                         TTAG_gvar,
+                                         stream,
+                                         &table_len ) ) )
     {
       FT_TRACE2(( "is missing\n" ));
       goto Exit;
         {
           blend->tuplecoords[i * gvar_head.axisCount + j] =
             FT_GET_SHORT() * 4;                 /* convert to FT_Fixed */
-          FT_TRACE5(( "%.4f ",
+          FT_TRACE5(( "%.5f ",
             blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 ));
         }
         FT_TRACE5(( "]\n" ));
 
     for ( i = 0; i < blend->num_axis; i++ )
     {
-      FT_TRACE6(( "    axis coordinate %d (%.4f):\n",
+      FT_TRACE6(( "    axis coordinate %d (%.5f):\n",
                   i, blend->normalizedcoords[i] / 65536.0 ));
       if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
-        FT_TRACE6(( "      intermediate coordinates %d (%.4f, %.4f):\n",
+        FT_TRACE6(( "      intermediate coordinates %d (%.5f, %.5f):\n",
                     i,
                     im_start_coords[i] / 65536.0,
                     im_end_coords[i] / 65536.0 ));
 
       if ( blend->normalizedcoords[i] == tuple_coords[i] )
       {
-        FT_TRACE6(( "      tuple coordinate value %.4f fits perfectly\n",
+        FT_TRACE6(( "      tuple coordinate value %.5f fits perfectly\n",
                     tuple_coords[i] / 65536.0 ));
         /* `apply' does not change */
         continue;
         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",
+          FT_TRACE6(( "      tuple coordinate value %.5f is exceeded, stop\n",
                       tuple_coords[i] / 65536.0 ));
           apply = 0;
           break;
         }
 
-        FT_TRACE6(( "      tuple coordinate value %.4f fits\n",
+        FT_TRACE6(( "      tuple coordinate value %.5f fits\n",
                     tuple_coords[i] / 65536.0 ));
         apply = FT_MulDiv( apply,
                            blend->normalizedcoords[i],
         if ( blend->normalizedcoords[i] < im_start_coords[i] ||
              blend->normalizedcoords[i] > im_end_coords[i]   )
         {
-          FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] is exceeded,"
+          FT_TRACE6(( "      intermediate tuple range [%.5f;%.5f] is exceeded,"
                       " stop\n",
                       im_start_coords[i] / 65536.0,
                       im_end_coords[i] / 65536.0 ));
 
         else if ( blend->normalizedcoords[i] < tuple_coords[i] )
         {
-          FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] fits\n",
+          FT_TRACE6(( "      intermediate tuple range [%.5f;%.5f] fits\n",
                       im_start_coords[i] / 65536.0,
                       im_end_coords[i] / 65536.0 ));
           apply = FT_MulDiv( apply,
 
         else
         {
-          FT_TRACE6(( "      intermediate tuple range [%.4f;%.4f] fits\n",
+          FT_TRACE6(( "      intermediate tuple range [%.5f;%.5f] fits\n",
                       im_start_coords[i] / 65536.0,
                       im_end_coords[i] / 65536.0 ));
           apply = FT_MulDiv( apply,
       }
     }
 
-    FT_TRACE6(( "    apply factor is %.4f\n", apply / 65536.0 ));
+    FT_TRACE6(( "    apply factor is %.5f\n", apply / 65536.0 ));
 
     return apply;
   }
     FT_Var_Axis*         a;
     FT_Var_Named_Style*  ns;
     GX_FVar_Head         fvar_head;
+    FT_Bool              usePsName;
 
     static const FT_Frame_Field  fvar_fields[] =
     {
     /* read the font data and set up the internal representation */
     /* if not already done                                       */
 
-    if ( face->blend == NULL )
+    if ( !face->blend )
     {
       FT_TRACE2(( "FVAR " ));
 
       /* both `fvar' and `gvar' must be present */
-      if ( ( error = face->goto_table( face, TTAG_gvar,
-                                       stream, &table_len ) ) != 0 )
+      if ( FT_SET_ERROR( face->goto_table( face, TTAG_gvar,
+                                           stream, &table_len ) ) )
       {
-        FT_TRACE1(( "\n"
-                    "TT_Get_MM_Var: `gvar' table is missing\n" ));
-        goto Exit;
+        /* CFF2 is an alternate to gvar here */
+        if ( FT_SET_ERROR( face->goto_table( face, TTAG_CFF2,
+                                             stream, &table_len ) ) )
+        {
+          FT_TRACE1(( "\n"
+                      "TT_Get_MM_Var: `gvar' or `CFF2' table is missing\n" ));
+          goto Exit;
+        }
       }
 
-      if ( ( error = face->goto_table( face, TTAG_fvar,
-                                       stream, &table_len ) ) != 0 )
+      if ( FT_SET_ERROR( face->goto_table( face, TTAG_fvar,
+                                           stream, &table_len ) ) )
       {
         FT_TRACE1(( "is missing\n" ));
         goto Exit;
 
       fvar_start = FT_STREAM_POS( );
 
+      /* the validity of the `fvar' header data was already checked */
+      /* in function `sfnt_init_face'                               */
       if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) )
         goto Exit;
 
-      if ( fvar_head.version != (FT_Long)0x00010000L                      ||
-#if 0
-           /* fonts like `JamRegular.ttf' have an incorrect value for */
-           /* `countSizePairs'; since value 2 is hard-coded in `fvar' */
-           /* version 1.0, we simply ignore it                        */
-           fvar_head.countSizePairs != 2                                  ||
-#endif
-           fvar_head.axisSize != 20                                       ||
-           /* axisCount limit implied by 16-bit instanceSize */
-           fvar_head.axisCount > 0x3FFE                                   ||
-           fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount          ||
-           /* instanceCount limit implied by limited range of name IDs */
-           fvar_head.instanceCount > 0x7EFF                               ||
-           fvar_head.offsetToData + fvar_head.axisCount * 20U +
-             fvar_head.instanceCount * fvar_head.instanceSize > table_len )
-      {
-        FT_TRACE1(( "\n"
-                    "TT_Get_MM_Var: invalid `fvar' header\n" ));
-        error = FT_THROW( Invalid_Table );
-        goto Exit;
-      }
+      usePsName = FT_BOOL( fvar_head.instanceSize ==
+                           6 + 4 * fvar_head.axisCount );
 
       FT_TRACE2(( "loaded\n" ));
 
         a->name[3] = (FT_String)( ( a->tag       ) & 0xFF );
         a->name[4] = '\0';
 
-        FT_TRACE5(( "  \"%s\": minimum=%.4f, default=%.4f, maximum=%.4f\n",
+        if ( a->minimum > a->def ||
+             a->def > a->maximum )
+        {
+          FT_TRACE2(( "TT_Get_MM_Var:"
+                      " invalid \"%s\" axis record; disabling\n",
+                      a->name ));
+
+          a->minimum = a->def;
+          a->maximum = a->def;
+        }
+
+        FT_TRACE5(( "  \"%s\": minimum=%.5f, default=%.5f, maximum=%.5f\n",
                     a->name,
                     a->minimum / 65536.0,
                     a->def / 65536.0,
       ns = mmvar->namedstyle;
       for ( i = 0; i < fvar_head.instanceCount; i++, ns++ )
       {
-        if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) )
+        /* PostScript names add 2 bytes to the instance record size */
+        if ( FT_FRAME_ENTER( ( usePsName ? 6L : 4L ) +
+                             4L * fvar_head.axisCount ) )
           goto Exit;
 
         ns->strid       =    FT_GET_USHORT();
         for ( j = 0; j < fvar_head.axisCount; j++ )
           ns->coords[j] = FT_GET_LONG();
 
+        if ( usePsName )
+          ns->psid = FT_GET_USHORT();
+
         FT_FRAME_EXIT();
       }
     }
 
     /* fill the output array if requested */
 
-    if ( master != NULL )
+    if ( master )
     {
       FT_UInt  n;
 
     GX_Blend    blend;
     FT_MM_Var*  mmvar;
     FT_UInt     i;
+    FT_Bool     is_default_instance = 1;
     FT_Memory   memory = face->root.memory;
 
     enum
 
     face->doblend = FALSE;
 
-    if ( face->blend == NULL )
+    if ( !face->blend )
     {
-      if ( ( error = TT_Get_MM_Var( face, NULL ) ) != 0 )
+      if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
         goto Exit;
     }
 
 
     for ( i = 0; i < num_coords; i++ )
     {
-      FT_TRACE5(( "  %.4f\n", coords[i] / 65536.0 ));
+      FT_TRACE5(( "  %.5f\n", coords[i] / 65536.0 ));
       if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
       {
-        FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.4f\n"
+        FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.5f\n"
                     "                 is out of range [-1;1]\n",
                     coords[i] / 65536.0 ));
         error = FT_THROW( Invalid_Argument );
         goto Exit;
       }
+
+      if ( coords[i] != 0 )
+        is_default_instance = 0;
     }
 
     FT_TRACE5(( "\n" ));
 
-    if ( blend->glyphoffsets == NULL )
-      if ( ( error = ft_var_load_gvar( face ) ) != 0 )
+    if ( !face->isCFF2 && !blend->glyphoffsets )
+      if ( FT_SET_ERROR( ft_var_load_gvar( face ) ) )
         goto Exit;
 
-    if ( blend->normalizedcoords == NULL )
+    if ( !blend->normalizedcoords )
     {
       if ( FT_NEW_ARRAY( blend->normalizedcoords, mmvar->num_axis ) )
         goto Exit;
 
     face->doblend = TRUE;
 
-    if ( face->cvt != NULL )
+    if ( face->cvt )
     {
       switch ( manageCvt )
       {
       }
     }
 
+    face->is_default_instance = is_default_instance;
+
   Exit:
     return error;
   }
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Get_MM_Blend                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Get the blend (normalized) coordinates for this instance of the    */
+  /*    font.                                                              */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The font.                                            */
+  /*                  Initialize the blend structure with `gvar' data.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    num_coords :: The number of available coordinates.  If it is       */
+  /*                  larger than the number of axes, set the excess       */
+  /*                  values to 0.                                         */
+  /*                                                                       */
+  /*    coords     :: An array of `num_coords', each between [-1,1].       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF( FT_Error )
+  TT_Get_MM_Blend( TT_Face    face,
+                   FT_UInt    num_coords,
+                   FT_Fixed*  coords )
+  {
+    FT_Error  error = FT_Err_Ok;
+    GX_Blend  blend;
+    FT_UInt   i, nc;
+
+
+    if ( !face->blend )
+    {
+      if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
+        return error;
+    }
+
+    blend = face->blend;
+
+    nc = num_coords;
+    if ( num_coords > blend->num_axis )
+    {
+      FT_TRACE2(( "TT_Get_MM_Blend: only using first %d of %d coordinates\n",
+                  blend->num_axis, num_coords ));
+      nc = blend->num_axis;
+    }
+
+    if ( face->doblend )
+    {
+      for ( i = 0; i < nc; i++ )
+        coords[i] = blend->normalizedcoords[i];
+    }
+    else
+    {
+      for ( i = 0; i < nc; i++ )
+        coords[i] = 0;
+    }
+
+    for ( ; i < num_coords; i++ )
+      coords[i] = 0;
+
+    return FT_Err_Ok;
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
     FT_Memory       memory = face->root.memory;
 
 
-    if ( face->blend == NULL )
+    if ( !face->blend )
     {
-      if ( ( error = TT_Get_MM_Var( face, NULL ) ) != 0 )
+      if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
         goto Exit;
     }
 
       num_coords = mmvar->num_axis;
     }
 
-    /* Axis normalization is a two stage process.  First we normalize */
+    /* Axis normalization is a two-stage process.  First we normalize */
     /* based on the [min,def,max] values for the axis to be [-1,0,1]. */
     /* Then, if there's an `avar' table, we renormalize this range.   */
 
     a = mmvar->axis;
     for ( i = 0; i < num_coords; i++, a++ )
     {
-      FT_TRACE5(( "  %.4f\n", coords[i] / 65536.0 ));
-      if ( coords[i] > a->maximum || coords[i] < a->minimum )
+      FT_Fixed  coord = coords[i];
+
+
+      FT_TRACE5(( "  %.5f\n", coord / 65536.0 ));
+      if ( coord > a->maximum || coord < a->minimum )
       {
-        FT_TRACE1(( "TT_Set_Var_Design: normalized design coordinate %.4f\n"
-                    "                   is out of range [%.4f;%.4f]\n",
-                    coords[i] / 65536.0,
-                    a->minimum / 65536.0,
-                    a->maximum / 65536.0 ));
-        error = FT_THROW( Invalid_Argument );
-        goto Exit;
+        FT_TRACE1((
+          "TT_Set_Var_Design: design coordinate %.5f\n"
+          "                   is out of range [%.5f;%.5f]; clamping\n",
+          coord / 65536.0,
+          a->minimum / 65536.0,
+          a->maximum / 65536.0 ));
+
+        if ( coord > a->maximum)
+          coord = a->maximum;
+        else
+          coord = a->minimum;
       }
 
-      if ( coords[i] < a->def )
+      if ( coord < a->def )
         normalized[i] = -FT_DivFix( coords[i] - a->def,
                                     a->minimum - a->def );
-      else if ( a->maximum == a->def )
-        normalized[i] = 0;
-      else
+      else if ( coord > a->def )
         normalized[i] = FT_DivFix( coords[i] - a->def,
                                    a->maximum - a->def );
+      else
+        normalized[i] = 0;
     }
 
     FT_TRACE5(( "\n" ));
     if ( !blend->avar_checked )
       ft_var_load_avar( face );
 
-    if ( blend->avar_segment != NULL )
+    if ( blend->avar_segment )
     {
       FT_TRACE5(( "normalized design coordinates"
                   " before applying `avar' data:\n" ));
       {
         for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
         {
-          FT_TRACE5(( "  %.4f\n", normalized[i] / 65536.0 ));
           if ( normalized[i] < av->correspondence[j].fromCoord )
           {
+            FT_TRACE5(( "  %.5f\n", normalized[i] / 65536.0 ));
+
             normalized[i] =
               FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord,
                          av->correspondence[j].toCoord -
   }
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Get_Var_Design                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Get the design coordinates of the currently selected interpolated  */
+  /*    font.                                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the source face.                         */
+  /*                                                                       */
+  /*    num_coords :: The number of design coordinates to retrieve.  If it */
+  /*                  is larger than the number of axes, set the excess    */
+  /*                  values to~0.                                         */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    coords     :: The design coordinates array.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0~means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF( FT_Error )
+  TT_Get_Var_Design( TT_Face    face,
+                     FT_UInt    num_coords,
+                     FT_Fixed*  coords )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+    GX_Blend      blend;
+    FT_MM_Var*    mmvar;
+    FT_Var_Axis*  a;
+
+    FT_UInt  i, j, nc;
+
+
+    if ( !face->blend )
+    {
+      if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
+        return error;
+    }
+
+    blend = face->blend;
+
+    nc = num_coords;
+    if ( num_coords > blend->num_axis )
+    {
+      FT_TRACE2(( "TT_Get_Var_Design: only using first %d of %d coordinates\n",
+                  blend->num_axis, num_coords ));
+      nc = blend->num_axis;
+    }
+
+    if ( face->doblend )
+    {
+      for ( i = 0; i < nc; i++ )
+        coords[i] = blend->normalizedcoords[i];
+    }
+    else
+    {
+      for ( i = 0; i < nc; i++ )
+        coords[i] = 0;
+    }
+
+    for ( ; i < num_coords; i++ )
+      coords[i] = 0;
+
+    if ( !blend->avar_checked )
+      ft_var_load_avar( face );
+
+    if ( blend->avar_segment )
+    {
+      GX_AVarSegment  av = blend->avar_segment;
+
+
+      FT_TRACE5(( "design coordinates"
+                  " after removing `avar' distortion:\n" ));
+
+      for ( i = 0; i < nc; i++, av++ )
+      {
+        for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
+        {
+          if ( coords[i] < av->correspondence[j].toCoord )
+          {
+            coords[i] =
+              FT_MulDiv( coords[i] - av->correspondence[j - 1].toCoord,
+                         av->correspondence[j].fromCoord -
+                           av->correspondence[j - 1].fromCoord,
+                         av->correspondence[j].toCoord -
+                           av->correspondence[j - 1].toCoord ) +
+              av->correspondence[j - 1].fromCoord;
+
+            FT_TRACE5(( "  %.5f\n", coords[i] / 65536.0 ));
+            break;
+          }
+        }
+      }
+    }
+
+    mmvar = blend->mmvar;
+    a     = mmvar->axis;
+
+    for ( i = 0; i < nc; i++, a++ )
+    {
+      if ( coords[i] < 0 )
+        coords[i] = a->def + FT_MulFix( coords[i],
+                                        a->def - a->minimum );
+      else if ( coords[i] > 0 )
+        coords[i] = a->def + FT_MulFix( coords[i],
+                                        a->maximum - a->def );
+      else
+        coords[i] = a->def;
+    }
+
+    return FT_Err_Ok;
+  }
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*****                                                               *****/
 
     FT_TRACE2(( "CVAR " ));
 
-    if ( blend == NULL )
+    if ( !blend )
     {
       FT_TRACE2(( "\n"
                   "tt_face_vary_cvt: no blend specified\n" ));
       goto Exit;
     }
 
-    if ( face->cvt == NULL )
+    if ( !face->cvt )
     {
       FT_TRACE2(( "\n"
                   "tt_face_vary_cvt: no `cvt ' table\n" ));
     offsetToData = FT_GET_USHORT();
 
     /* rough sanity test */
-    if ( offsetToData + tupleCount * 4 > table_len )
+    if ( offsetToData + ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) * 4 >
+           table_len )
     {
       FT_TRACE2(( "tt_face_vary_cvt:"
                   " invalid CVT variation array header\n" ));
                                              table_len,
                                              point_count == 0 ? face->cvt_size
                                                               : point_count );
-      if ( localpoints == NULL || deltas == NULL )
+      if ( !localpoints || !deltas )
         ; /* failure, ignore it */
 
       else if ( localpoints == ALL_POINTS )
 
         for ( j = 0; j < point_count; j++ )
         {
-          int      pindex   = localpoints[j];
-          FT_Long  orig_cvt = face->cvt[pindex];
+          int      pindex;
+          FT_Long  orig_cvt;
+
 
+          pindex = localpoints[j];
+          if ( (FT_ULong)pindex >= face->cvt_size )
+            continue;
 
+          orig_cvt          = face->cvt[pindex];
           face->cvt[pindex] = (FT_Short)( orig_cvt +
                                           FT_MulFix( deltas[j], apply ) );
 
     FT_Short    *deltas_x, *deltas_y;
 
 
-    if ( !face->doblend || blend == NULL )
+    if ( !face->doblend || !blend )
       return FT_THROW( Invalid_Argument );
 
     if ( glyph_index >= blend->gv_glyphcnt      ||
                                           point_count == 0 ? n_points
                                                            : point_count );
 
-      if ( points == NULL || deltas_y == NULL || deltas_x == NULL )
+      if ( !points || !deltas_y || !deltas_x )
         ; /* failure, ignore it */
 
       else if ( points == ALL_POINTS )
           FT_Pos  delta_y = FT_MulFix( deltas_y[j], apply );
 
 
-          outline->points[j].x += delta_x;
-          outline->points[j].y += delta_y;
+          if ( j < n_points - 3 )
+          {
+            outline->points[j].x += delta_x;
+            outline->points[j].y += delta_y;
+          }
+          else
+          {
+            /* To avoid double adjustment of advance width or height, */
+            /* adjust phantom points only if there is no HVAR or VVAR */
+            /* support, respectively.                                 */
+            if ( j == ( n_points - 3 )          &&
+                 !( face->variation_support   &
+                    TT_FACE_FLAG_VAR_HADVANCE ) )
+              outline->points[j].x += delta_x;
+
+            else if ( j == ( n_points - 2 )        &&
+                      !( face->variation_support &
+                         TT_FACE_FLAG_VAR_LSB    ) )
+              outline->points[j].x += delta_x;
+
+            else if ( j == ( n_points - 1 )          &&
+                      !( face->variation_support   &
+                         TT_FACE_FLAG_VAR_VADVANCE ) )
+              outline->points[j].y += delta_y;
+
+            else if ( j == ( n_points - 0 )        &&
+                      !( face->variation_support &
+                         TT_FACE_FLAG_VAR_TSB    ) )
+              outline->points[j].y += delta_y;
+          }
 
 #ifdef FT_DEBUG_LEVEL_TRACE
           if ( delta_x || delta_y )
   }
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    tt_get_var_blend                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An extended internal version of `TT_Get_MM_Blend' that returns     */
+  /*    pointers instead of copying data, without any initialization of    */
+  /*    the MM machinery in case it isn't loaded yet.                      */
+  /*                                                                       */
+  FT_LOCAL_DEF( FT_Error )
+  tt_get_var_blend( TT_Face      face,
+                    FT_UInt     *num_coords,
+                    FT_Fixed*   *coords,
+                    FT_MM_Var*  *mm_var )
+  {
+    if ( face->blend )
+    {
+      if ( num_coords )
+        *num_coords = face->blend->num_axis;
+      if ( coords )
+        *coords     = face->blend->normalizedcoords;
+      if ( mm_var )
+        *mm_var     = face->blend->mmvar;
+    }
+    else
+    {
+      if ( num_coords )
+        *num_coords = 0;
+      if ( coords )
+        *coords     = NULL;
+      if ( mm_var )
+        *mm_var     = NULL;
+    }
+
+    return FT_Err_Ok;
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
   /*    Free the blend internal data structure.                            */
   /*                                                                       */
   FT_LOCAL_DEF( void )
-  tt_done_blend( FT_Memory  memory,
-                 GX_Blend   blend )
+  tt_done_blend( TT_Face  face )
   {
-    if ( blend != NULL )
+    FT_Memory  memory = FT_FACE_MEMORY( face );
+    GX_Blend   blend  = face->blend;
+
+
+    if ( blend )
     {
-      FT_UInt  i;
+      FT_UInt  i, num_axes;
+
 
+      /* blend->num_axis might not be set up yet */
+      num_axes = blend->mmvar->num_axis;
 
       FT_FREE( blend->normalizedcoords );
       FT_FREE( blend->mmvar );
 
-      if ( blend->avar_segment != NULL )
+      if ( blend->avar_segment )
       {
-        for ( i = 0; i < blend->num_axis; i++ )
+        for ( i = 0; i < num_axes; i++ )
           FT_FREE( blend->avar_segment[i].correspondence );
         FT_FREE( blend->avar_segment );
       }
 
+      if ( blend->hvar_table )
+      {
+        if ( blend->hvar_table->itemStore.varData )
+        {
+          for ( i = 0; i < blend->hvar_table->itemStore.dataCount; i++ )
+          {
+            FT_FREE( blend->hvar_table->itemStore.varData[i].regionIndices );
+            FT_FREE( blend->hvar_table->itemStore.varData[i].deltaSet );
+          }
+          FT_FREE( blend->hvar_table->itemStore.varData );
+        }
+
+        if ( blend->hvar_table->itemStore.varRegionList )
+        {
+          for ( i = 0; i < blend->hvar_table->itemStore.regionCount; i++ )
+            FT_FREE( blend->hvar_table->itemStore.varRegionList[i].axisList );
+          FT_FREE( blend->hvar_table->itemStore.varRegionList );
+        }
+
+        FT_FREE( blend->hvar_table->widthMap.innerIndex );
+        FT_FREE( blend->hvar_table->widthMap.outerIndex );
+        FT_FREE( blend->hvar_table );
+      }
+
       FT_FREE( blend->tuplecoords );
       FT_FREE( blend->glyphoffsets );
       FT_FREE( blend );
index aa8f6ea..215e109 100644 (file)
@@ -61,6 +61,77 @@ FT_BEGIN_HEADER
   } GX_AVarSegmentRec, *GX_AVarSegment;
 
 
+  typedef struct  GX_HVarDataRec_
+  {
+    FT_UInt    itemCount;      /* number of delta sets per item         */
+    FT_UInt    regionIdxCount; /* number of region indices in this data */
+    FT_UInt*   regionIndices;  /* array of `regionCount' indices;       */
+                               /* these index `varRegionList'           */
+    FT_Short*  deltaSet;       /* array of `itemCount' deltas           */
+                               /* use `innerIndex' for this array       */
+
+  } GX_HVarDataRec, *GX_HVarData;
+
+
+  /* contribution of one axis to a region */
+  typedef struct  GX_AxisCoordsRec_
+  {
+    FT_Fixed  startCoord;
+    FT_Fixed  peakCoord;      /* zero means no effect (factor = 1) */
+    FT_Fixed  endCoord;
+
+  } GX_AxisCoordsRec, *GX_AxisCoords;
+
+
+  typedef struct  GX_HVarRegionRec_
+  {
+    GX_AxisCoords  axisList;               /* array of axisCount records */
+
+  } GX_HVarRegionRec, *GX_HVarRegion;
+
+
+  /* HVAR item variation store */
+  typedef struct  GX_HVStoreRec_
+  {
+    FT_UInt        dataCount;
+    GX_HVarData    varData;            /* array of dataCount records;     */
+                                       /* use `outerIndex' for this array */
+    FT_UShort      axisCount;
+    FT_UInt        regionCount;        /* total number of regions defined */
+    GX_HVarRegion  varRegionList;
+
+  } GX_HVStoreRec, *GX_HVStore;
+
+
+  typedef struct  GX_WidthMapRec_
+  {
+    FT_UInt   mapCount;
+    FT_UInt*  outerIndex;             /* indices to item var data */
+    FT_UInt*  innerIndex;             /* indices to delta set     */
+
+  } GX_WidthMapRec, *GX_WidthMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    GX_HVarTableRec                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Data from the `HVAR' table.                                        */
+  /*                                                                       */
+  typedef struct  GX_HVarTableRec_
+  {
+    GX_HVStoreRec   itemStore;        /* Item Variation Store */
+    GX_WidthMapRec  widthMap;         /* Advance Width Mapping */
+#if 0
+    GX_LSBMap       LsbMap;           /* not implemented */
+    GX_RSBMap       RsbMap;           /* not implemented */
+#endif
+
+  } GX_HVarTableRec, *GX_HVarTable;
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Struct>                                                              */
@@ -89,6 +160,11 @@ FT_BEGIN_HEADER
     FT_Bool         avar_checked;
     GX_AVarSegment  avar_segment;
 
+    FT_Bool         hvar_loaded;
+    FT_Bool         hvar_checked;
+    FT_Error        hvar_error;
+    GX_HVarTable    hvar_table;
+
     FT_UInt         tuplecount;      /* shared tuples in `gvar'           */
     FT_Fixed*       tuplecoords;     /* tuplecoords[tuplecount][num_axis] */
 
@@ -148,6 +224,11 @@ FT_BEGIN_HEADER
                    FT_UInt    num_coords,
                    FT_Fixed*  coords );
 
+  FT_LOCAL( FT_Error )
+  TT_Get_MM_Blend( TT_Face    face,
+                   FT_UInt    num_coords,
+                   FT_Fixed*  coords );
+
   FT_LOCAL( FT_Error )
   TT_Set_Var_Design( TT_Face    face,
                      FT_UInt    num_coords,
@@ -157,6 +238,10 @@ FT_BEGIN_HEADER
   TT_Get_MM_Var( TT_Face      face,
                  FT_MM_Var*  *master );
 
+  FT_LOCAL( FT_Error )
+  TT_Get_Var_Design( TT_Face    face,
+                     FT_UInt    num_coords,
+                     FT_Fixed*  coords );
 
   FT_LOCAL( FT_Error )
   tt_face_vary_cvt( TT_Face    face,
@@ -169,10 +254,19 @@ FT_BEGIN_HEADER
                               FT_Outline*  outline,
                               FT_UInt      n_points );
 
+  FT_LOCAL( FT_Error )
+  tt_hadvance_adjust( TT_Face  face,
+                      FT_UInt  gindex,
+                      FT_Int  *adelta );
+
+  FT_LOCAL( FT_Error )
+  tt_get_var_blend( TT_Face      face,
+                    FT_UInt     *num_coords,
+                    FT_Fixed*   *coords,
+                    FT_MM_Var*  *mm_var );
 
   FT_LOCAL( void )
-  tt_done_blend( FT_Memory  memory,
-                 GX_Blend   blend );
+  tt_done_blend( TT_Face  face );
 
 
 FT_END_HEADER
index 2d15ea7..4a506ee 100644 (file)
 
     coderange = &exec->codeRangeTable[range - 1];
 
-    FT_ASSERT( coderange->base != NULL );
+    FT_ASSERT( coderange->base );
 
     /* NOTE: Because the last instruction of a program may be a CALL */
     /*       which will return to the first byte *after* the code    */
 
       /* In case of multi-threading it can happen that the old size object */
       /* no longer exists, thus we must clear all glyph zone references.   */
-      ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) );
+      FT_ZERO( &exec->zp0 );
       exec->zp1 = exec->zp0;
       exec->zp2 = exec->zp0;
     }
 
     range = &exc->codeRangeTable[aRange - 1];
 
-    if ( range->base == NULL )     /* invalid coderange */
+    if ( !range->base )     /* invalid coderange */
     {
       exc->error = FT_THROW( Invalid_CodeRange );
       return FAILURE;
             FT_Long*        args )
   {
     if ( args[0] == 0 && exc->args == 0 )
+    {
       exc->error = FT_THROW( Bad_Argument );
+      return;
+    }
+
     exc->IP += args[0];
     if ( exc->IP < 0                                             ||
          ( exc->callTop > 0                                    &&
            exc->IP > exc->callStack[exc->callTop - 1].Def->end ) )
+    {
       exc->error = FT_THROW( Bad_Argument );
+      return;
+    }
+
     exc->step_ins = FALSE;
+
+    if ( args[0] < 0 )
+    {
+      if ( ++exc->neg_jump_counter > exc->neg_jump_counter_max )
+        exc->error = FT_THROW( Execution_Too_Long );
+    }
   }
 
 
       Ins_Goto_CodeRange( exc, def->range, def->start );
 
       exc->step_ins = FALSE;
+
+      exc->loopcall_counter += (FT_ULong)args[0];
+      if ( exc->loopcall_counter > exc->loopcall_counter_max )
+        exc->error = FT_THROW( Execution_Too_Long );
     }
 
     return;
   /*                                                                       */
   /* SCANTYPE[]:   SCAN TYPE                                               */
   /* Opcode range: 0x8D                                                    */
-  /* Stack:        uint32? -->                                             */
+  /* Stack:        uint16 -->                                              */
   /*                                                                       */
   static void
   Ins_SCANTYPE( TT_ExecContext  exc,
                 FT_Long*        args )
   {
     if ( args[0] >= 0 )
-      exc->GS.scan_type = (FT_Int)args[0];
+      exc->GS.scan_type = (FT_Int)args[0] & 0xFFFF;
   }
 
 
     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;
+    FT_Bool     in_twilight = FT_BOOL( exc->GS.gep0 == 0 ||
+                                       exc->GS.gep1 == 0 ||
+                                       exc->GS.gep2 == 0 );
 #endif
 
 
      * Otherwise, by definition, the value of exc->twilight.orus[n] is (0,0),
      * for every n.
      */
-    twilight = exc->GS.gep0 == 0 || exc->GS.gep1 == 0 || exc->GS.gep2 == 0;
+    twilight = ( exc->GS.gep0 == 0 ||
+                 exc->GS.gep1 == 0 ||
+                 exc->GS.gep2 == 0 );
 
     if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) )
     {
       cur_range = PROJECT( &exc->zp1.cur[exc->GS.rp2], cur_base );
     }
 
-    for ( ; exc->GS.loop > 0; --exc->GS.loop )
+    for ( ; exc->GS.loop > 0; exc->GS.loop-- )
     {
       FT_UInt     point = (FT_UInt)exc->stack[--exc->args];
       FT_F26Dot6  org_dist, cur_dist, new_dist;
   FT_EXPORT_DEF( FT_Error )
   TT_RunIns( TT_ExecContext  exc )
   {
-    FT_Long    ins_counter = 0;  /* executed instructions counter */
+    FT_ULong   ins_counter = 0;  /* executed instructions counter */
+    FT_ULong   num_twilight_points;
     FT_UShort  i;
 
 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     exc->iupy_called = FALSE;
 #endif
 
+    /* We restrict the number of twilight points to a reasonable,     */
+    /* heuristic value to avoid slow execution of malformed bytecode. */
+    num_twilight_points = FT_MAX( 30,
+                                  2 * ( exc->pts.n_points + exc->cvtSize ) );
+    if ( exc->twilight.n_points > num_twilight_points )
+    {
+      if ( num_twilight_points > 0xFFFFU )
+        num_twilight_points = 0xFFFFU;
+
+      FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n"
+                  "           from %d to the more reasonable value %d\n",
+                  exc->twilight.n_points,
+                  num_twilight_points ));
+      exc->twilight.n_points = (FT_UShort)num_twilight_points;
+    }
+
+    /* Set up loop detectors.  We restrict the number of LOOPCALL loops  */
+    /* and the number of JMPR, JROT, and JROF calls with a negative      */
+    /* argument to values that depend on the size of the CVT table and   */
+    /* the number of points in the current glyph (if applicable).        */
+    /*                                                                   */
+    /* The idea is that in real-world bytecode you either iterate over   */
+    /* all CVT entries, or over all points (or contours) of a glyph, and */
+    /* such iterations don't happen very often.                          */
+    exc->loopcall_counter = 0;
+    exc->neg_jump_counter = 0;
+
+    /* The maximum values are heuristic. */
+    exc->loopcall_counter_max = FT_MAX( 100,
+                                        10 * ( exc->pts.n_points +
+                                               exc->cvtSize ) );
+    FT_TRACE5(( "TT_RunIns: Limiting total number of loops in LOOPCALL"
+                " to %d\n", exc->loopcall_counter_max ));
+
+    exc->neg_jump_counter_max = exc->loopcall_counter_max;
+    FT_TRACE5(( "TT_RunIns: Limiting total number of backward jumps"
+                " to %d\n", exc->neg_jump_counter_max ));
+
     /* set PPEM and CVT functions */
     exc->tt_metrics.ratio = 0;
     if ( exc->metrics.x_ppem != exc->metrics.y_ppem )
     } while ( !exc->instruction_trap );
 
   LNo_Error_:
+    FT_TRACE4(( "  %d instructions executed\n", ins_counter ));
     return FT_Err_Ok;
 
   LErrorCodeOverflow_:
index 53f0944..33a9b12 100644 (file)
@@ -408,6 +408,14 @@ FT_BEGIN_HEADER
 
 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
+    /* We maintain two counters (in addition to the instruction counter) */
+    /* that act as loop detectors for LOOPCALL and jump opcodes with     */
+    /* negative arguments.                                               */
+    FT_ULong           loopcall_counter;
+    FT_ULong           loopcall_counter_max;
+    FT_ULong           neg_jump_counter;
+    FT_ULong           neg_jump_counter_max;
+
   } TT_ExecContextRec;
 
 
index ed3be2d..7e37113 100644 (file)
     FT_Error  error;
 
 
-    FT_MEM_ZERO( zone, sizeof ( *zone ) );
+    FT_ZERO( zone );
     zone->memory = memory;
 
     if ( FT_NEW_ARRAY( zone->org,      maxPoints   ) ||
 
     if ( FT_IS_SCALABLE( ttface ) )
     {
-
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
-
       if ( !ttface->internal->incremental_interface )
-        error = tt_face_load_loca( face, stream );
-      if ( !error )
-        error = tt_face_load_cvt( face, stream );
-      if ( !error )
-        error = tt_face_load_fpgm( face, stream );
-      if ( !error )
-        error = tt_face_load_prep( face, stream );
-
-      /* Check the scalable flag based on `loca'. */
-      if ( !ttface->internal->incremental_interface &&
-           ttface->num_fixed_sizes                  &&
-           face->glyph_locations                    &&
-           tt_check_single_notdef( ttface )         )
+#endif
       {
-        FT_TRACE5(( "tt_face_init:"
-                    " Only the `.notdef' glyph has an outline.\n"
-                    "             "
-                    " Resetting scalable flag to FALSE.\n" ));
+        error = tt_face_load_loca( face, stream );
 
-        ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
+        /* having a (non-zero) `glyf' table without */
+        /* a `loca' table is not valid              */
+        if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) )
+          goto Exit;
+        if ( error )
+          goto Exit;
       }
 
-#else /* !FT_CONFIG_OPTION_INCREMENTAL */
+      /* `fpgm', `cvt', and `prep' are optional */
+      error = tt_face_load_cvt( face, stream );
+      if ( error && FT_ERR_NEQ( error, Table_Missing ) )
+        goto Exit;
 
-      if ( !error )
-        error = tt_face_load_loca( face, stream );
-      if ( !error )
-        error = tt_face_load_cvt( face, stream );
-      if ( !error )
-        error = tt_face_load_fpgm( face, stream );
-      if ( !error )
-        error = tt_face_load_prep( face, stream );
+      error = tt_face_load_fpgm( face, stream );
+      if ( error && FT_ERR_NEQ( error, Table_Missing ) )
+        goto Exit;
+
+      error = tt_face_load_prep( face, stream );
+      if ( error && FT_ERR_NEQ( error, Table_Missing ) )
+        goto Exit;
 
       /* Check the scalable flag based on `loca'. */
-      if ( ttface->num_fixed_sizes          &&
-           face->glyph_locations            &&
-           tt_check_single_notdef( ttface ) )
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+      if ( !ttface->internal->incremental_interface )
+#endif
       {
-        FT_TRACE5(( "tt_face_init:"
-                    " Only the `.notdef' glyph has an outline.\n"
-                    "             "
-                    " Resetting scalable flag to FALSE.\n" ));
+        if ( ttface->num_fixed_sizes          &&
+             face->glyph_locations            &&
+             tt_check_single_notdef( ttface ) )
+        {
+          FT_TRACE5(( "tt_face_init:"
+                      " Only the `.notdef' glyph has an outline.\n"
+                      "             "
+                      " Resetting scalable flag to FALSE.\n" ));
 
-        ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
+          ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
+        }
       }
-
-#endif /* !FT_CONFIG_OPTION_INCREMENTAL */
-
     }
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     face->cvt_program_size  = 0;
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-    tt_done_blend( memory, face->blend );
+    tt_done_blend( face );
     face->blend = NULL;
 #endif
   }
index f725865..a71d589 100644 (file)
 
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define TT_SERVICES_GET                  tt_services
-#define TT_SERVICE_GX_MULTI_MASTERS_GET  tt_service_gx_multi_masters
-#define TT_SERVICE_TRUETYPE_GLYF_GET     tt_service_truetype_glyf
-#define TT_SERVICE_PROPERTIES_GET        tt_service_properties
+#define TT_SERVICES_GET                    tt_services
+#define TT_SERVICE_GX_MULTI_MASTERS_GET    tt_service_gx_multi_masters
+#define TT_SERVICE_METRICS_VARIATIONS_GET  tt_service_metrics_variations
+#define TT_SERVICE_TRUETYPE_GLYF_GET       tt_service_truetype_glyf
+#define TT_SERVICE_PROPERTIES_GET          tt_service_properties
 
 #else /* FT_CONFIG_OPTION_PIC */
 
 #include FT_MULTIPLE_MASTERS_H
 #include FT_SERVICE_MULTIPLE_MASTERS_H
+#include FT_SERVICE_METRICS_VARIATIONS_H
 #include FT_SERVICE_TRUETYPE_GLYF_H
 #include FT_SERVICE_PROPERTIES_H
 
@@ -42,12 +44,13 @@ FT_BEGIN_HEADER
 
   typedef struct  TTModulePIC_
   {
-    FT_ServiceDescRec*          tt_services;
+    FT_ServiceDescRec*               tt_services;
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-    FT_Service_MultiMastersRec  tt_service_gx_multi_masters;
+    FT_Service_MultiMastersRec       tt_service_gx_multi_masters;
+    FT_Service_MetricsVariationsRec  tt_service_metrics_variations;
 #endif
-    FT_Service_TTGlyfRec        tt_service_truetype_glyf;
-    FT_Service_PropertiesRec    tt_service_properties;
+    FT_Service_TTGlyfRec             tt_service_truetype_glyf;
+    FT_Service_PropertiesRec         tt_service_properties;
 
   } TTModulePIC;
 
@@ -56,6 +59,8 @@ FT_BEGIN_HEADER
           ( (TTModulePIC*)((lib)->pic_container.truetype) )
 #define TT_SERVICES_GET                       \
           ( GET_PIC( library )->tt_services )
+#define TT_SERVICE_METRICS_VARIATIONS_GET                       \
+          ( GET_PIC( library )->tt_service_metrics_variations )
 #define TT_SERVICE_GX_MULTI_MASTERS_GET                       \
           ( GET_PIC( library )->tt_service_gx_multi_masters )
 #define TT_SERVICE_TRUETYPE_GLYF_GET                       \
index ca158ac..d756d38 100644 (file)
     /* it is possible that a font doesn't have a glyf table at all */
     /* or its size is zero                                         */
     if ( FT_ERR_EQ( error, Table_Missing ) )
-      face->glyf_len = 0;
+    {
+      face->glyf_len    = 0;
+      face->glyf_offset = 0;
+    }
     else if ( error )
       goto Exit;
+    else
+    {
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+      if ( face->root.internal->incremental_interface )
+        face->glyf_offset = 0;
+      else
+#endif
+        face->glyf_offset = FT_STREAM_POS();
+    }
 
     FT_TRACE2(( "Locations " ));
     error = face->goto_table( face, TTAG_loca, stream, &table_len );
       if ( table_len >= 0x40000L )
       {
         FT_TRACE2(( "table too large\n" ));
-        error = FT_THROW( Invalid_Table );
-        goto Exit;
+        table_len = 0x3FFFFL;
       }
       face->num_locations = table_len >> shift;
     }
       if ( table_len >= 0x20000L )
       {
         FT_TRACE2(( "table too large\n" ));
-        error = FT_THROW( Invalid_Table );
-        goto Exit;
+        table_len = 0x1FFFFL;
       }
       face->num_locations = table_len >> shift;
     }
       }
     }
 
-    /* Check broken location data */
+    /* Check broken location data. */
     if ( pos1 > face->glyf_len )
     {
       FT_TRACE1(( "tt_face_get_location:"
-                  " too large offset=0x%08lx found for gid=0x%04lx,\n"
+                  " too large offset (0x%08lx) found for glyph index %ld,\n"
                   "                     "
-                  " exceeding the end of glyf table (0x%08lx)\n",
+                  " exceeding the end of `glyf' table (0x%08lx)\n",
                   pos1, gindex, face->glyf_len ));
       *asize = 0;
       return 0;
 
     if ( pos2 > face->glyf_len )
     {
-      FT_TRACE1(( "tt_face_get_location:"
-                  " too large offset=0x%08lx found for gid=0x%04lx,\n"
-                  "                     "
-                  " truncate at the end of glyf table (0x%08lx)\n",
-                  pos2, gindex + 1, face->glyf_len ));
-      pos2 = face->glyf_len;
+      /* We try to sanitize the last `loca' entry. */
+      if ( gindex == face->num_locations - 1 )
+      {
+        FT_TRACE1(( "tt_face_get_location:"
+                    " too large offset (0x%08lx) found for glyph index %ld,\n"
+                    "                     "
+                    " truncating at the end of `glyf' table (0x%08lx)\n",
+                    pos2, gindex + 1, face->glyf_len ));
+        pos2 = face->glyf_len;
+      }
+      else
+      {
+        FT_TRACE1(( "tt_face_get_location:"
+                    " too large offset (0x%08lx) found for glyph index %ld,\n"
+                    "                     "
+                    " exceeding the end of `glyf' table (0x%08lx)\n",
+                    pos2, gindex + 1, face->glyf_len ));
+        *asize = 0;
+        return 0;
+      }
     }
 
     /* The `loca' table must be ordered; it refers to the length of */
   {
     FT_Error   error;
     FT_Memory  memory = stream->memory;
-    FT_UInt    version, nn, num_records;
+    FT_UInt    nn, num_records;
     FT_ULong   table_size, record_size;
     FT_Byte*   p;
     FT_Byte*   limit;
     p     = face->hdmx_table;
     limit = p + table_size;
 
-    version     = FT_NEXT_USHORT( p );
+    /* Given that `hdmx' tables are losing its importance (for example, */
+    /* variation fonts introduced in OpenType 1.8 must not have this    */
+    /* table) we no longer test for a correct `version' field.          */
+    p          += 2;
     num_records = FT_NEXT_USHORT( p );
     record_size = FT_NEXT_ULONG( p );
 
       record_size &= 0xFFFFU;
 
     /* The limit for `num_records' is a heuristic value. */
-    if ( version != 0           ||
-         num_records > 255      ||
-         record_size > 0x10001L ||
-         record_size < 4        )
+    if ( num_records > 255              ||
+         ( num_records > 0            &&
+           ( record_size > 0x10001L ||
+             record_size < 4        ) ) )
     {
       error = FT_THROW( Invalid_File_Format );
       goto Fail;
index bbd843c..5c7f389 100644 (file)
       kp++;
     }
 
-    if ( oldcharmap != NULL )
+    if ( oldcharmap )
       error = FT_Set_Charmap( t1_face, oldcharmap );
     if ( error )
       goto Exit;
       {
         t1_face->face_flags |= FT_FACE_FLAG_KERNING;
         face->afm_data       = fi;
-        fi = NULL;
+        fi                   = NULL;
       }
     }
 
     FT_FRAME_EXIT();
 
   Exit:
-    if ( fi != NULL )
+    if ( fi )
       T1_Done_Metrics( memory, fi );
 
     return error;
index f1e60d4..fd9e13e 100644 (file)
     (FT_Get_MM_Func)        T1_Get_Multi_Master,   /* get_mm         */
     (FT_Set_MM_Design_Func) T1_Set_MM_Design,      /* set_mm_design  */
     (FT_Set_MM_Blend_Func)  T1_Set_MM_Blend,       /* set_mm_blend   */
+    (FT_Get_MM_Blend_Func)  T1_Get_MM_Blend,       /* get_mm_blend   */
     (FT_Get_MM_Var_Func)    T1_Get_MM_Var,         /* get_mm_var     */
-    (FT_Set_Var_Design_Func)T1_Set_Var_Design      /* set_var_design */
+    (FT_Set_Var_Design_Func)T1_Set_Var_Design,     /* set_var_design */
+    (FT_Get_Var_Design_Func)T1_Get_Var_Design,     /* get_var_design */
+
+    (FT_Get_Var_Blend_Func) NULL,                  /* get_var_blend  */
+    (FT_Done_Blend_Func)    T1_Done_Blend          /* done_blend     */
   };
 #endif
 
       0x10000L,
       0x20000L,
 
-      0,    /* module-specific interface */
+      NULL,    /* module-specific interface */
 
       T1_Driver_Init,           /* FT_Module_Constructor  module_init   */
       T1_Driver_Done,           /* FT_Module_Destructor   module_done   */
     T1_Load_Glyph,              /* FT_Slot_LoadFunc  load_glyph */
 
 #ifdef T1_CONFIG_OPTION_NO_AFM
-    0,                          /* FT_Face_GetKerningFunc   get_kerning  */
-    0,                          /* FT_Face_AttachFunc       attach_file  */
+    NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
+    NULL,                       /* FT_Face_AttachFunc       attach_file  */
 #else
     Get_Kerning,                /* FT_Face_GetKerningFunc   get_kerning  */
     T1_Read_Metrics,            /* FT_Face_AttachFunc       attach_file  */
     T1_Get_Advances,            /* FT_Face_GetAdvancesFunc  get_advances */
 
     T1_Size_Request,            /* FT_Size_RequestFunc  request_size */
-    0                           /* FT_Size_SelectFunc   select_size  */
+    NULL                        /* FT_Size_SelectFunc   select_size  */
   };
 
 
index e728cf4..f6b43dc 100644 (file)
     if ( ncv <= axismap->blend_points[0] )
       return INT_TO_FIXED( axismap->design_points[0] );
 
-    for ( j = 1; j < axismap->num_points; ++j )
+    for ( j = 1; j < axismap->num_points; j++ )
     {
       if ( ncv <= axismap->blend_points[j] )
         return INT_TO_FIXED( axismap->design_points[j - 1] ) +
                                       /* 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);
                         axiscoords,
                         blend->num_axis );
 
-      for ( i = 0; i < mmaster.num_axis; ++i )
+      for ( i = 0; i < mmaster.num_axis; i++ )
         mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i],
                                             axiscoords[i] );
     }
   }
 
 
+  FT_LOCAL_DEF( FT_Error )
+  T1_Get_MM_Blend( T1_Face    face,
+                   FT_UInt    num_coords,
+                   FT_Fixed*  coords )
+  {
+    PS_Blend  blend = face->blend;
+
+    FT_Fixed  axiscoords[4];
+    FT_UInt   i, nc;
+
+
+    if ( !blend )
+      return FT_THROW( Invalid_Argument );
+
+    mm_weights_unmap( blend->weight_vector,
+                      axiscoords,
+                      blend->num_axis );
+
+    nc = num_coords;
+    if ( num_coords > blend->num_axis )
+    {
+      FT_TRACE2(( "T1_Get_MM_Blend: only using first %d of %d coordinates\n",
+                  blend->num_axis, num_coords ));
+      nc = blend->num_axis;
+    }
+
+    for ( i = 0; i < nc; i++ )
+      coords[i] = axiscoords[i];
+    for ( ; i < num_coords; i++ )
+      coords[i] = 0x8000;
+
+    return FT_Err_Ok;
+  }
+
+
   FT_LOCAL_DEF( FT_Error )
   T1_Set_MM_Design( T1_Face   face,
                     FT_UInt   num_coords,
      if ( num_coords > T1_MAX_MM_AXIS )
        num_coords = T1_MAX_MM_AXIS;
 
-     for ( i = 0; i < num_coords; ++i )
+     for ( i = 0; i < num_coords; i++ )
        lcoords[i] = FIXED_TO_INT( coords[i] );
 
      return T1_Set_MM_Design( face, num_coords, lcoords );
   }
 
 
+  FT_LOCAL_DEF( FT_Error )
+  T1_Get_Var_Design( T1_Face    face,
+                     FT_UInt    num_coords,
+                     FT_Fixed*  coords )
+  {
+    PS_Blend  blend = face->blend;
+
+    FT_Fixed  axiscoords[4];
+    FT_UInt   i, nc;
+
+
+    if ( !blend )
+      return FT_THROW( Invalid_Argument );
+
+    mm_weights_unmap( blend->weight_vector,
+                      axiscoords,
+                      blend->num_axis );
+
+    nc = num_coords;
+    if ( num_coords > blend->num_axis )
+    {
+      FT_TRACE2(( "T1_Get_Var_Design:"
+                  " only using first %d of %d coordinates\n",
+                  blend->num_axis, num_coords ));
+      nc = blend->num_axis;
+    }
+
+    for ( i = 0; i < nc; i++ )
+      coords[i] = mm_axis_unmap( &blend->design_map[i], axiscoords[i] );
+    for ( ; i < num_coords; i++ )
+      coords[i] = 0;
+
+    return FT_Err_Ok;
+  }
+
+
   FT_LOCAL_DEF( void )
   T1_Done_Blend( T1_Face  face )
   {
     FT_Error   error;
     FT_Int     num_subrs;
     FT_UInt    count;
-    FT_Hash    hash = NULL;
 
     PSAux_Service  psaux = (PSAux_Service)face->psaux;
 
     }
 
     /* we certainly need more than 8 bytes per subroutine */
-    if ( parser->root.limit > parser->root.cursor                      &&
+    if ( parser->root.limit >= parser->root.cursor                     &&
          num_subrs > ( parser->root.limit - parser->root.cursor ) >> 3 )
     {
       /*
                   ( parser->root.limit - parser->root.cursor ) >> 3 ));
       num_subrs = ( parser->root.limit - parser->root.cursor ) >> 3;
 
-      if ( !hash )
+      if ( !loader->subrs_hash )
       {
-        if ( FT_NEW( hash ) )
+        if ( FT_NEW( loader->subrs_hash ) )
           goto Fail;
 
-        loader->subrs_hash = hash;
-
-        error = ft_hash_num_init( hash, memory );
+        error = ft_hash_num_init( loader->subrs_hash, memory );
         if ( error )
           goto Fail;
       }
 
       /* if we use a hash, the subrs index is the key, and a running */
       /* counter specified for `T1_Add_Table' acts as the value      */
-      if ( hash )
+      if ( loader->subrs_hash )
       {
-        ft_hash_num_insert( idx, count, hash, memory );
+        ft_hash_num_insert( idx, count, loader->subrs_hash, memory );
         idx = count;
       }
 
                 parser->root.error = t1_load_keyword( face,
                                                       loader,
                                                       keyword );
-                if ( parser->root.error != FT_Err_Ok )
+                if ( parser->root.error )
                 {
                   if ( FT_ERR_EQ( parser->root.error, Ignore ) )
                     parser->root.error = FT_Err_Ok;
   {
     FT_UNUSED( face );
 
-    FT_MEM_ZERO( loader, sizeof ( *loader ) );
+    FT_ZERO( loader );
   }
 
 
index b96fe5a..72445c5 100644 (file)
@@ -70,7 +70,7 @@ FT_BEGIN_HEADER
   T1_Get_Multi_Master( T1_Face           face,
                        FT_Multi_Master*  master );
 
-  FT_LOCAL_DEF( FT_Error )
+  FT_LOCAL( FT_Error )
   T1_Get_MM_Var( T1_Face      face,
                  FT_MM_Var*  *master );
 
@@ -79,12 +79,22 @@ FT_BEGIN_HEADER
                    FT_UInt    num_coords,
                    FT_Fixed*  coords );
 
+  FT_LOCAL( FT_Error )
+  T1_Get_MM_Blend( T1_Face    face,
+                   FT_UInt    num_coords,
+                   FT_Fixed*  coords );
+
   FT_LOCAL( FT_Error )
   T1_Set_MM_Design( T1_Face   face,
                     FT_UInt   num_coords,
                     FT_Long*  coords );
 
-  FT_LOCAL_DEF( FT_Error )
+  FT_LOCAL( FT_Error )
+  T1_Get_Var_Design( T1_Face    face,
+                     FT_UInt    num_coords,
+                     FT_Fixed*  coords );
+
+  FT_LOCAL( FT_Error )
   T1_Set_Var_Design( T1_Face    face,
                      FT_UInt    num_coords,
                      FT_Fixed*  coords );
index 563d9f3..478c80b 100644 (file)
                 *cur == '\t'               ||
                 (test_cr && *cur == '\r' ) ||
                 *cur == '\n'               ) )
-        ++cur;
+        cur++;
       if ( cur >= limit )
       {
         FT_ERROR(( "T1_Get_Private_Dict:"
index 54c4eb3..dad35c2 100644 (file)
       0x10000L,
       0x20000L,
 
-      0,    /* module-specific interface */
+      NULL,    /* module-specific interface */
 
       T42_Driver_Init,          /* FT_Module_Constructor  module_init   */
       T42_Driver_Done,          /* FT_Module_Destructor   module_done   */
 
     T42_GlyphSlot_Load,         /* FT_Slot_LoadFunc  load_glyph */
 
-    0,                          /* FT_Face_GetKerningFunc   get_kerning  */
-    0,                          /* FT_Face_AttachFunc       attach_file  */
-    0,                          /* FT_Face_GetAdvancesFunc  get_advances */
+    NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
+    NULL,                       /* FT_Face_AttachFunc       attach_file  */
+    NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
 
     T42_Size_Request,           /* FT_Size_RequestFunc  request_size */
     T42_Size_Select             /* FT_Size_SelectFunc   select_size  */
index 089ae0f..1e4907b 100644 (file)
     FT_Error       error   = FT_Err_Ok;
 
 
-    if ( face->glyph == NULL )
+    if ( !face->glyph )
     {
       /* First glyph slot for this face */
       slot->ttslot = t42face->ttf_face->glyph;
index f948916..ef36ffe 100644 (file)
       if ( *cur == '/' || *cur == '(' )
       {
         FT_UInt  len;
-        FT_Bool  have_literal = ( *cur == '(' );
+        FT_Bool  have_literal = FT_BOOL( *cur == '(' );
 
 
         if ( cur + ( have_literal ? 3 : 2 ) >= limit )
   {
     FT_UNUSED( face );
 
-    FT_MEM_ZERO( loader, sizeof ( *loader ) );
+    FT_ZERO( loader );
     loader->num_glyphs = 0;
     loader->num_chars  = 0;
 
index a0a1800..99cc966 100644 (file)
     FT_ULong    offset;
     FT_Bool     new_format;
 
-    FT_UNUSED( load_flags );
-
 
     if ( !face )
     {
       goto Exit;
     }
 
+    bitmap->rows       = font->header.pixel_height;
+    bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
+
+    slot->bitmap_left     = 0;
+    slot->bitmap_top      = font->header.ascent;
+    slot->format          = FT_GLYPH_FORMAT_BITMAP;
+
+    /* now set up metrics */
+    slot->metrics.width        = (FT_Pos)( bitmap->width << 6 );
+    slot->metrics.height       = (FT_Pos)( bitmap->rows << 6 );
+    slot->metrics.horiAdvance  = (FT_Pos)( bitmap->width << 6 );
+    slot->metrics.horiBearingX = 0;
+    slot->metrics.horiBearingY = slot->bitmap_top << 6;
+
+    ft_synthesize_vertical_metrics( &slot->metrics,
+                                    (FT_Pos)( bitmap->rows << 6 ) );
+
+    if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY )
+      goto Exit;
+
     /* jump to glyph data */
     p = font->fnt_frame + /* font->header.bits_offset */ + offset;
 
       FT_Byte*   write;
 
 
-      bitmap->pitch      = (int)pitch;
-      bitmap->rows       = font->header.pixel_height;
-      bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
-
+      bitmap->pitch = (int)pitch;
       if ( !pitch                                                 ||
            offset + pitch * bitmap->rows > font->header.file_size )
       {
         for ( write = column; p < limit; p++, write += bitmap->pitch )
           *write = *p;
       }
-    }
 
-    slot->internal->flags = FT_GLYPH_OWN_BITMAP;
-    slot->bitmap_left     = 0;
-    slot->bitmap_top      = font->header.ascent;
-    slot->format          = FT_GLYPH_FORMAT_BITMAP;
-
-    /* now set up metrics */
-    slot->metrics.width        = (FT_Pos)( bitmap->width << 6 );
-    slot->metrics.height       = (FT_Pos)( bitmap->rows << 6 );
-    slot->metrics.horiAdvance  = (FT_Pos)( bitmap->width << 6 );
-    slot->metrics.horiBearingX = 0;
-    slot->metrics.horiBearingY = slot->bitmap_top << 6;
-
-    ft_synthesize_vertical_metrics( &slot->metrics,
-                                    (FT_Pos)( bitmap->rows << 6 ) );
+      slot->internal->flags = FT_GLYPH_OWN_BITMAP;
+    }
 
   Exit:
     return error;
       0x10000L,
       0x20000L,
 
-      0,    /* module-specific interface */
+      NULL, /* module-specific interface */
 
-      0,                        /* FT_Module_Constructor  module_init   */
-      0,                        /* FT_Module_Destructor   module_done   */
+      NULL,                     /* FT_Module_Constructor  module_init   */
+      NULL,                     /* FT_Module_Destructor   module_done   */
       winfnt_get_service        /* FT_Module_Requester    get_interface */
     },
 
 
     FNT_Face_Init,              /* FT_Face_InitFunc  init_face */
     FNT_Face_Done,              /* FT_Face_DoneFunc  done_face */
-    0,                          /* FT_Size_InitFunc  init_size */
-    0,                          /* FT_Size_DoneFunc  done_size */
-    0,                          /* FT_Slot_InitFunc  init_slot */
-    0,                          /* FT_Slot_DoneFunc  done_slot */
+    NULL,                       /* FT_Size_InitFunc  init_size */
+    NULL,                       /* FT_Size_DoneFunc  done_size */
+    NULL,                       /* FT_Slot_InitFunc  init_slot */
+    NULL,                       /* FT_Slot_DoneFunc  done_slot */
 
     FNT_Load_Glyph,             /* FT_Slot_LoadFunc  load_glyph */
 
-    0,                          /* FT_Face_GetKerningFunc   get_kerning  */
-    0,                          /* FT_Face_AttachFunc       attach_file  */
-    0,                          /* FT_Face_GetAdvancesFunc  get_advances */
+    NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
+    NULL,                       /* FT_Face_AttachFunc       attach_file  */
+    NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
 
     FNT_Size_Request,           /* FT_Size_RequestFunc  request_size */
     FNT_Size_Select             /* FT_Size_SelectFunc   select_size  */