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
+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.
- FreeType 2.7
- ============
+ FreeType 2.7.1
+ ==============
Homepage: http://www.freetype.org
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
#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> */
/* 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
/* 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. */
/* 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': */
/* */
/* 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;
/* 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. */
/* <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 );
*
* 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.
*
/* 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 )
/* */
*/
#define FREETYPE_MAJOR 2
#define FREETYPE_MINOR 7
-#define FREETYPE_PATCH 0
+#define FREETYPE_PATCH 1
/*************************************************************************/
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;
{
FT_Fixed* coords;
FT_UInt strid;
+ FT_UInt psid; /* since 2.7.1 */
} FT_Var_Named_Style;
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> */
/* 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. */
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> */
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 );
+
/* */
{
FT_Long glyph_size;
FT_Glyph_Format glyph_format;
+
FT_Glyph_InitFunc glyph_init;
FT_Glyph_DoneFunc glyph_done;
FT_Glyph_CopyFunc glyph_copy;
typedef struct FT_CMap_ClassRec_
{
FT_ULong size;
+
FT_CMap_InitFunc init;
FT_CMap_DoneFunc done;
FT_CMap_CharIndexFunc char_index;
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 )
#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
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,
*/
#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++ */
/* FT_DEFINE_SERVICEDESCREC5 */
/* FT_DEFINE_SERVICEDESCREC6 */
/* FT_DEFINE_SERVICEDESCREC7 */
+ /* FT_DEFINE_SERVICEDESCREC8 */
/* */
/* <Description> */
/* Used to initialize an array of FT_ServiceDescRec structures. */
{ 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_, \
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 */
#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>
--- /dev/null
+/***************************************************************************/
+/* */
+/* 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 */
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 */
} 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 */
/* */
/* 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. */
/* 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. */
/* 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). */
/* */
/* 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_
{
/* 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
+
/***********************************************************************/
/* */
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 */
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;
FT_Vector pp1;
FT_Vector pp2;
- FT_ULong glyf_offset;
-
/* the zone where we load our glyphs */
TT_GlyphZoneRec base;
TT_GlyphZoneRec zone;
#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' )
#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' )
#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' )
#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' )
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 */
)
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 */
)
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;
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;
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 */
)
"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 */
)
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 */
)
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
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 */
(*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,
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 */
}
- 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;
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 )
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;
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 );
}
- 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;
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 */
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;
#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;
}
{
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;
/* 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;
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;
len = lengths[nn];
- if ( src == NULL )
+ if ( !src )
continue;
/* separate elements with a space */
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 */
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 );
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 */
},
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 */
/* 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;
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:
{
{
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
};
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,
for (;;) \
{ \
_node = *_pnode; \
- if ( _node == NULL ) \
+ if ( !_node ) \
goto NewNode_; \
\
if ( _node->hash == _hash && \
/* 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_; \
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 ) \
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 */
};
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 */
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;
typedef struct FTC_MruListClassRec_
{
FT_Offset node_size;
+
FTC_MruNode_CompareFunc node_compare;
FTC_MruNode_InitFunc node_init;
FTC_MruNode_ResetFunc node_reset;
} FTC_MruListClassRec;
+
typedef struct FTC_MruListRec_
{
FT_UInt num_nodes;
*
*/
- if ( sbit->buffer == NULL && sbit->width == 255 )
+ if ( !sbit->buffer && sbit->width == 255 )
{
FT_ULong size;
FT_Error error;
FT_Error* error,
size_t sizeItem )
{
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
/* initialize the structure */
arrstack->memory = memory;
FT_Memory memory = arrstack->memory; /* for FT_FREE */
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
arrstack->allocated = 0;
arrstack->count = 0;
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;
cf2_setError( FT_Error* error,
FT_Error value )
{
- if ( error && *error == 0 )
+ if ( error && !*error )
*error = value;
}
#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 */
}
- /* 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 */
}
#include "cf2ft.h"
#include "cf2blues.h"
+#include "cffload.h"
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: */
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 */
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 )
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 );
/* 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;
#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 );
/* `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;
}
{
FT_Memory memory = stack->memory;
+ /* free the buffer */
+ FT_FREE( stack->buffer );
/* free the main structure */
FT_FREE( stack );
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;
}
{
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 );
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,
}
- 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 */
#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 */
/* 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" ));
#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 = ®ion->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 );
#include <ft2build.h>
#include "cfftypes.h"
+#include "cffparse.h"
+#include "cffobjs.h" /* for CFF_Face */
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
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
}
#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++;
}
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_
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;
} 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,
cff_kind_bool,
cff_kind_delta,
cff_kind_callback,
+ cff_kind_blend,
cff_kind_max /* do not remove */
};
#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
#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" )
#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 */
{
FT_Stream stream;
FT_ULong start;
+ FT_UInt hdr_size;
FT_UInt count;
FT_Byte off_size;
FT_ULong data_offset;
} 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;
FT_UShort num_designs;
FT_UShort num_axes;
+ /* fields for CFF2 */
+ FT_ULong vstore_offset;
+ FT_UInt maxstack;
+
} CFF_FontRecDictRec, *CFF_FontRecDict;
+ /* forward reference */
+ typedef struct CFF_SubFontRec_* CFF_SubFont;
+
+
typedef struct CFF_PrivateRec_
{
FT_Byte num_blue_values;
FT_Pos default_width;
FT_Pos nominal_width;
+ /* fields for CFF2 */
+ FT_UInt vsindex;
+ CFF_SubFont subfont;
+
} CFF_PrivateRec, *CFF_Private;
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
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;
/* since version 2.4.12 */
FT_Generic cf2_instance;
- } CFF_FontRec, *CFF_Font;
+ CFF_VStoreRec vstore; /* parsed vstore structure */
+
+ } CFF_FontRec;
FT_END_HEADER
{
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,
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;
}
}
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 */
};
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;
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 */
};
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 );
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 );
#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:
--- /dev/null
+/* 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 */
#ifndef _ZLIB_H
#define _ZLIB_H
-#include "zconf.h"
+#include "ftzconf.h"
#ifdef __cplusplus
extern "C" {
{
while ( state->stack_top > 0 )
{
- --state->stack_top;
+ state->stack_top--;
if ( buffer )
buffer[result] = state->stack[state->stack_top];
OTV_LIMIT_CHECK( GlyphCount * 2 ); /* GlyphArray */
- for ( i = 0; i < GlyphCount; ++i )
+ for ( i = 0; i < GlyphCount; i++ )
{
FT_UInt gid;
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 );
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 */
};
PCF_Metric metric;
FT_ULong bytes;
- FT_UNUSED( load_flags );
-
FT_TRACE1(( "PCF_Glyph_Load: glyph index %d\n", glyph_index ));
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;
}
}
- 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;
}
prop = pcf_find_property( face, prop_name );
- if ( prop != NULL )
+ if ( prop )
{
if ( prop->isString )
{
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 */
},
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 */
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 ) )
/* parsing normal metrics */
- fields = PCF_BYTE_ORDER( format ) == MSBFirst
+ fields = ( PCF_BYTE_ORDER( format ) == MSBFirst )
? pcf_metric_msb_header
: pcf_metric_header;
len = lengths[nn];
- if ( src == NULL )
+ if ( !src )
continue;
/* separate elements with a space */
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;
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 */
{
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 */
};
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 */
};
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 );
* 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;
}
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;
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
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 */
};
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 */
};
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 ));
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 */
};
( 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 */
{
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;
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 */
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;
#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 */
/* 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 */
+ ;
/*
#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 */
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 */
)
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 );
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
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 */
#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 );
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 );
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" ));
/*************************************************************************/
/* */
/* <Function> */
- /* tt_face_load_max_profile */
+ /* tt_face_load_maxp */
/* */
/* <Description> */
/* Loads the maximum profile into a face object. */
#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
}
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;
{
FT_Error error;
FT_ULong table_size;
+ FT_ULong table_start;
face->sbit_table = NULL;
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;
#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 :-) */
/* 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 ) )
TCoord cover;
int invalid;
+ PCell* ycells;
PCell cells;
FT_PtrDist max_cells;
FT_PtrDist num_cells;
FT_Raster_Span_Func render_span;
void* render_span_data;
- PCell* ycells;
-
} gray_TWorker, *gray_PWorker;
#if defined( _MSC_VER )
/* */
/* 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;
}
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;
}
/* 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 );
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 */
int y;
- if ( ras.num_cells == 0 )
- return;
-
FT_TRACE7(( "gray_sweep: start\n" ));
for ( y = ras.min_ey; y < ras.max_ey; y++ )
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
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 );
return 1;
}
- ReduceBands:
/* render pool overflow; we will reduce the render band by half */
width >>= 1;
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
*araster = (FT_Raster)&the_raster;
- FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
+ FT_ZERO( &the_raster );
return 0;
}
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 */
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 */
)
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 );
char temp[512];
- if ( dll_name == NULL )
+ if ( !dll_name )
{
fprintf( stderr,
"you must provide a DLL name with the -d option!\n" );
/* we must omit the .dll suffix from the library name */
dot = strchr( dll_name, '.' );
- if ( dot != NULL )
+ if ( dot )
{
int len = dot - dll_name;
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 );
arg += 2;
out = fopen( arg, "wt" );
- if ( out == NULL )
+ if ( !out )
{
fprintf( stderr, "could not open '%s' for writing\n", argv[2] );
exit(3);
{
FILE* file = fopen( argv[0], "rb" );
- if ( file == NULL )
+ if ( !file )
fprintf( stderr, "unable to open '%s'\n", argv[0] );
else
{
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 );
# 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
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 = ""
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
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 = " "
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
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 = " "
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 = ""
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():
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" )
#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 */
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 )
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 );
} 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> */
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] */
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,
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,
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
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_:
#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;
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
}
#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
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;
( (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 \
/* 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;
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;
(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 */
};
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 );
}
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 );
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 );
*cur == '\t' ||
(test_cr && *cur == '\r' ) ||
*cur == '\n' ) )
- ++cur;
+ cur++;
if ( cur >= limit )
{
FT_ERROR(( "T1_Get_Private_Dict:"
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 */
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;
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;
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 */