diff options
Diffstat (limited to 'testing/freetype-infinality/upstream-2014.10.08.patch')
-rw-r--r-- | testing/freetype-infinality/upstream-2014.10.08.patch | 6990 |
1 files changed, 6990 insertions, 0 deletions
diff --git a/testing/freetype-infinality/upstream-2014.10.08.patch b/testing/freetype-infinality/upstream-2014.10.08.patch new file mode 100644 index 000000000..a51911886 --- /dev/null +++ b/testing/freetype-infinality/upstream-2014.10.08.patch @@ -0,0 +1,6990 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a4e583d..df77d96 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -16,11 +16,16 @@ + # + # cmake CMakeLists.txt + # +-# to create a Makefile that builds a static version of the library. For a +-# dynamic library, use ++# to create a Makefile that builds a static version of the library. ++# ++# For a dynamic library, use + # + # cmake CMakeLists.txt -DBUILD_SHARED_LIBS:BOOL=true + # ++# For a framework on OS X, use ++# ++# cmake CMakeLists.txt -DBUILD_FRAMEWORK:BOOL=true -G Xcode ++# + # instead. Please refer to the cmake manual for further options, in + # particular, how to modify compilation and linking parameters. + # +@@ -39,6 +44,14 @@ cmake_minimum_required(VERSION 2.6) + + project(freetype) + ++if (BUILD_FRAMEWORK) ++ if (NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode") ++ message(FATAL_ERROR "You should use Xcode generator with BUILD_FRAMEWORK enabled") ++ endif () ++ set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)") ++ set(BUILD_SHARED_LIBS ON) ++endif () ++ + set(VERSION_MAJOR "2") + set(VERSION_MINOR "5") + set(VERSION_PATCH "3") +@@ -51,22 +64,27 @@ add_definitions(-DFT2_BUILD_LIBRARY) + include_directories("${PROJECT_SOURCE_DIR}/include") + + # Create the configuration file +-message(STATUS "Creating directory, ${PROJECT_BINARY_DIR}/include.") +-file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/include) ++message(STATUS "Creating directory, ${PROJECT_BINARY_DIR}/include/freetype2.") ++file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/include/freetype2) + + # For the auto-generated ftconfig.h file +-include_directories("${PROJECT_BINARY_DIR}/include") +-message(STATUS "Creating ${PROJECT_BINARY_DIR}/include/ftconfig.h.") ++include_directories(BEFORE "${PROJECT_BINARY_DIR}/include/freetype2") ++message(STATUS "Creating ${PROJECT_BINARY_DIR}/include/freetype2/ftconfig.h.") + execute_process( + COMMAND sed -e "s/FT_CONFIG_OPTIONS_H/<ftoption.h>/" -e "s/FT_CONFIG_STANDARD_LIBRARY_H/<ftstdlib.h>/" -e "s?/undef ?#undef ?" + INPUT_FILE ${PROJECT_SOURCE_DIR}/builds/unix/ftconfig.in +- OUTPUT_FILE ${PROJECT_BINARY_DIR}/include/ftconfig.h ++ OUTPUT_FILE ${PROJECT_BINARY_DIR}/include/freetype2/ftconfig.h + ) + ++file(GLOB PUBLIC_HEADERS "include/*.h") ++file(GLOB PUBLIC_CONFIG_HEADERS "include/config/*.h") ++file(GLOB PRIVATE_HEADERS "include/internal/*.h") ++ + set(BASE_SRCS + src/autofit/autofit.c + src/base/ftadvanc.c + src/base/ftbbox.c ++ src/base/ftbdf.c + src/base/ftbitmap.c + src/base/ftcalc.c + src/base/ftcid.c +@@ -125,7 +143,31 @@ include_directories("src/raster") + include_directories("src/psaux") + include_directories("src/psnames") + +-add_library(freetype ${BASE_SRCS}) ++if (BUILD_FRAMEWORK) ++ set(BASE_SRCS ++ ${BASE_SRCS} ++ builds/mac/freetype-Info.plist ++ ) ++endif () ++ ++add_library(freetype ++ ${PUBLIC_HEADERS} ++ ${PUBLIC_CONFIG_HEADERS} ++ ${PRIVATE_HEADERS} ++ ${BASE_SRCS} ++) ++ ++if (BUILD_FRAMEWORK) ++ set_property(SOURCE ${PUBLIC_CONFIG_HEADERS} ++ PROPERTY MACOSX_PACKAGE_LOCATION Headers/config ++ ) ++ set_target_properties(freetype PROPERTIES ++ FRAMEWORK TRUE ++ MACOSX_FRAMEWORK_INFO_PLIST builds/mac/freetype-Info.plist ++ PUBLIC_HEADER "${PUBLIC_HEADERS}" ++ XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" ++ ) ++endif () + + # Installations + # Note the trailing slash in the argument to the `DIRECTORY' directive +@@ -137,6 +179,7 @@ install(TARGETS freetype + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib ++ FRAMEWORK DESTINATION Library/Frameworks + ) + + # Packaging +diff --git a/ChangeLog b/ChangeLog +index ea1eb4a..4e17454 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,703 @@ ++2014-10-02 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Significant optimization of `ft_div64by32' ++ ++ We shift as many bits as we can into the high register, perform ++ 32-bit division with modulo there, then work through the remaining ++ bits with long division. This optimization is especially noticeable ++ for smaller dividends that barely use the high register. ++ ++ * src/base/ftcalc.c (ft_div64by32): Updated. ++ ++2014-10-02 Dave Arnold <darnold@adobe.com> ++ ++ [cff] Fix Savannah bug #43271. ++ ++ * src/cff/cf2font.c (cf2_computeDarkening): Change overflow ++ detection to use logarithms and clamp `scaledStem'. ++ ++2014-10-01 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ * src/base/ftcalc.c: Remove miscellaneous type casts. ++ ++2014-10-01 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Use more common `FT_MSB' implementation with masks. ++ ++ * src/base/ftcalc.c (FT_MSB): Updated. ++ ++2014-09-30 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Clean up. ++ ++ * src/base/ftcalc.c (FT_MOVE_SIGN): New macro for frequently used ++ code. ++ ++2014-09-25 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Avoid unnecessary long division. ++ ++ This applies to `FT_MulDiv' but not to `FT_DivFix', where overflows or ++ lack thereof are predicted accurately. ++ ++ * src/base/ftcalc.c (ft_div64by32): Improve readability. ++ (FT_MulDiv, FT_MulDiv_No_Round) [!FT_LONG64]: Use straight division ++ when multiplication stayed within 32 bits. ++ ++2014-09-24 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Minor clean-ups. ++ ++ * src/autofit/afhints.c (AF_FLAGS): Remove obsolete values. ++ ++ * src/autofit/afhints.c (af_glyph_hints_dump_points, ++ af_glyph_hints_align_strong_points): Updated. ++ ++ * src/autofit/aflatin.c (af_latin_hints_link_segments, ++ af_latin_hints_compute_segments), src/autofit/afcjk.c ++ (af_cjk_hints_link_segments), src/autofit/aflatin2.c ++ (af_latin2_hints_link_segments, af_latin2_hints_compute_segments): ++ There are no longer fake segments since more than 10 years... ++ ++2014-09-22 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Minor code streamlining. ++ ++ * src/autofit/afhints.c (af_axis_hints_new_edge): Remove redundant ++ initialization. ++ ++2014-09-19 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ * src/base/ftcalc.c: Harmonize code. ++ ++2014-09-15 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Tighten the overflow check in `FT_MulDiv'. ++ ++ * src/base/ftcalc.c (FT_MulDiv) [!FT_LONG64]: Updated. ++ ++2014-09-08 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ Fix Savannah bug #43153. ++ ++ * src/psaux/psconv.c (PS_Conv_ToFixed): Add protection against ++ overflow in `divider'. ++ ++2014-09-03 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Tighten the overflow check in `FT_DivFix'. ++ ++ This fixes a 13-year old bug. The original overflow check should have ++ been updated when rounding was introduced into this function ++ (c2cd00443b). ++ ++ * src/base/ftcalc.c (FT_DivFix) [!FT_LONG64]: Updated. ++ * include/freetype.h (FT_DivFix): Updated documentation. ++ ++2014-09-03 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Tighten the overflow check in `FT_MulFix'. ++ ++ * src/base/ftcalc.c (FT_MulFix) [!FT_LONG64]: Updated. ++ ++2014-09-02 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [truetype] Shortcut ppem calculations for square pixels. ++ ++ * src/truetype/ttinterp.h (TT_ExecContextRec): New field ++ `cur_ppem_func' with a function pointer. ++ * src/truetype/ttinterp.c (TT_RunIns): Initialize `cur_ppem_func' ++ depending on the pixel geometry to either... ++ (Current_Ppem_Stretched): ... this for stretched pixels. ++ (Current_Ppem): ... or this for square pixels. ++ (DO_MPPEM, DO_MPS, Ins_DELTAP, Ins_DELTAC): Use `cur_ppem_func'. ++ ++2014-08-31 Behdad Esfahbod <behdad@behdad.org> ++ ++ Don't use `register' keyword. Fixes compiler warnings. ++ ++ * src/base/ftcalc.c (FT_Add64) [!FT_LONG64]: Do it. ++ * src/gzip/inftrees.c (huft_build): Ditto. ++ * src/truetype/ttinterp.c (TT_MulFix14_arm): Ditto. ++ ++2014-08-24 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [truetype] Optimize DELTAP and DELTAC. ++ ++ * src/truetype/ttinterp.c (Ins_DELTAP, Ins_DELTAC): Move ppem ++ calculations outside of the loop. ++ ++2014-08-21 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ Fix Savannah bug #43033. ++ ++ * include/config/ftconfig.h, builds/unix/ftconfig.in, ++ builds/vms/ftconfig.h [FT_LONG64]: Do not disable the macro when ++ 64-bit type is `long'. ++ ++2014-08-20 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Small optimization of `FT_MulFix'. ++ ++ * src/base/ftcalc.c (FT_MulFix): Loosen up the condition for direct ++ 32-bit calculations. ++ ++2014-08-19 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Use unsigned calculation in `FT_MulDiv'. ++ ++ * src/base/ftcalc.c (FT_MulDiv): Updated to expand 32-bit range. ++ ++2014-08-18 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Remove truncation in `FT_DivFix'. ++ ++ * src/base/ftcalc.c (FT_DivFix): Updated. ++ ++2014-08-14 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ Minor refactoring. ++ ++ * src/base/ftcalc.c (FT_MulDiv, FT_MulDiv_No_Round): Updated. ++ ++2014-08-14 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ Turn FT_MSB into a macro when using gcc builtins. ++ ++ * src/base/ftcalc.c, include/internal/ftcalc.h: Updated. ++ ++2014-08-12 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Avoid undefined FT_MSB in `BBox_Cubic_Check'. ++ ++ * src/base/ftbbox.c (BBox_Cubic_Check): Update. ++ (update_cubic_max): Repalce with... ++ (cubic_peak): ... this, which now handles upscaling. ++ ++2014-08-11 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Handle collapsed outlines to avoid undefined FT_MSB. ++ ++ * src/base/ftoutln.c (FT_Outline_Get_Orientation): Update. ++ ++2014-08-11 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Restore FT_MulFix inlining. ++ ++ * include/freetype.h (FT_MulFix): Unconditionally defined. ++ ++ * src/base/ftcalc.c [FT_MULFIX_ASSEMBLER]: Move code from here... ++ ++ * include/internal/ftcalc.h [FT_MULFIX_ASSEMBLER]: ... to here, ++ which conditionally replaces the function with an inline version ++ through the macro. ++ ++2014-08-08 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): Refactor. ++ ++2014-07-26 Werner Lemberg <wl@gnu.org> ++ ++ [cff] Fix typo. ++ ++ * src/cff/cf2hints.c (cf2_glyphpath_computeOffset): Use correct ++ offsets in third quadrant. ++ ++ Reported by maks <maksqwe1@ukr.net>. ++ ++2014-07-17 Werner Lemberg <wl@gnu.org> ++ ++ Fix Savannah bug #42788. ++ ++ * src/pfr/pfrobjs.c: Include `ftcalc.h'. ++ ++2014-07-16 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ Replace `ft_highpow2' function. ++ ++ * src/pfr/pfrobjs.c (pfr_face_get_kerning): Use `FT_MSB' instead of ++ `ft_highpow2'. ++ ++ * src/base/ftutil.c, include/internal/ftobjs.h (ft_highpow2): Remove ++ it. ++ ++2014-07-15 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ * src/base/ftcalc.c (FT_MSB): Utilize gcc builtins. ++ ++2014-07-15 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Move assembler code back in the source file. ++ ++ FT_MulFix assembler used to reside in ftcalc.c before f47d263f1b. ++ ++ * include/config/ftconfig.h, builds/unix/ftconfig.in, ++ builds/vms/ftconfig.h [FT_MULFIX_ASSEMBLER]: Move code from here... ++ ++ * src/base/ftcalc.c [FT_MULFIX_ASSEMBLER]: ... to here. ++ ++2014-07-14 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Further clean up color bitmap conversion. ++ ++ * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): Stop ++ using FT_MulFix and FT_DivFix since all calculations fit into 32 bits. ++ ++2014-07-13 Werner Lemberg <wl@gnu.org> ++ ++ [truetype] Improve handling of buggy `prep' tables. ++ ++ In case of an error in the `prep' table, no longer try to execute it ++ again and again. This makes FreeType handle endless loops in buggy ++ fonts much faster. ++ ++ * src/truetype/ttobjs.h (TT_SizeRec): The fields `bytecode_ready' ++ and `cvt_ready' are now negative if not initialized yet, otherwise ++ they indicate the error code of the last run. ++ ++ * src/truetype/ttobjs.c (tt_size_run_fpgm, tt_size_run_prep, ++ tt_size_done_bytecode, tt_size_init_bytecode, ++ tt_size_ready_bytecode, tt_size_init, tt_size_done, tt_size_reset): ++ Updated. ++ ++ * src/truetype/ttgload.c (tt_loader_init): Updated. ++ * src/truetype/ttinterp.c (TT_RunIns): Force reexecution of `fpgm' ++ and `prep' only if we are in the `glyf' table. ++ ++2014-07-12 Werner Lemberg <wl@gnu.org> ++ ++ * builds/vms/ftconfig.h: Synchronize. ++ Problem reported by Alexei. ++ ++2014-07-11 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Clean up bitmap conversion. ++ ++ * src/base/ftbitmap.c (ft_gray_for_premultiplied_srgb_bgra): Use ++ appropriate FT_DivFix and remove superfluous upscaling. ++ ++2014-07-04 Alexei Podtelezhnikov <apodtele@gmail.com> ++ ++ [base] Small optimization of the ancient code. ++ ++ * src/base/ftcalc.c (FT_MulDiv, FT_MulDiv_No_Round): Loosen up the ++ condition for direct 32-bit calculations. ++ ++2014-06-27 Werner Lemberg <wl@gnu.org> ++ ++ Fix Apple standard glyph names. ++ ++ * src/sfnt/ttpost.c (tt_post_default_names): Synchronize with ++ `tools/glnames.py' ++ ++ Problem reported by Adam Twardoch <adam@fontlab.com>. ++ ++2014-06-17 Werner Lemberg <wl@gnu.org> ++ ++ Partially revert commit from 2014-06-13. ++ ++ * src/autofit/aflatin.c (af_latin_metrics_init_blues): Move ++ declaration of `p_first' and `p_last' out of the loop. ++ ++2014-06-17 Werner Lemberg <wl@gnu.org> ++ ++ * builds/unix/freetype2.m4: s/AC_PATH_PROG/AC_PATH_TOOL/. ++ ++ This simplifies cross-compiling. ++ ++2014-06-13 Werner Lemberg <wl@gnu.org> ++ ++ Fix more compiler warnings. ++ Reported by Wojciech Mamrak <wmamrak@gmail.com>. ++ ++ * src/autofit/afglobal.c (af_face_globals_compute_style_coverage): ++ Make integer constant unsigned. ++ ++ * src/sfnt/ttsbit.c (tt_face_load_strike_metrics) ++ <TT_SBIT_TABLE_TYPE_SBIX>: Fix types. ++ (tt_sbit_decoder_load_compound, tt_face_load_sbix_image): Add proper ++ casts. ++ ++2014-06-13 Werner Lemberg <wl@gnu.org> ++ ++ Fix compiler warnings. ++ Reported by Wojciech Mamrak <wmamrak@gmail.com>. ++ ++ * src/autofit/afglobal.c (af_face_globals_compute_style_coverage), ++ src/autofit/afmodule.c (af_property_set): Fix `signed' vs. ++ `unsigned' issues. ++ ++ * src/autofit/aflatin.c (af_latin_metrics_init_blues): Make compiler ++ happy. ++ ++ * src/base/ftlcdfil.c (_ft_lcd_filter_fir): Use only four elements ++ for `fir'. ++ Fix `signed' vs. `unsigned' issues. ++ ++ * src/sfnt/sfobjs.c (WRITE_BYTE): Removed, unused. ++ (WRITE_USHORT, WRITE_ULONG): Add proper casts. ++ ++ * src/truetype/ttgload.c (TT_Get_VMetrics): Add proper casts. ++ ++ * src/truetype/ttinterp.c (Ins_DELTAP): Add proper casts for `B1' ++ and `B2'. ++ ++2014-05-16 Alexey Petruchik <alexey.petruchik@gmail.com> ++ ++ [cmake] Add option to build OS X framework. ++ ++ * CMakeLists.txt: Update accordingly. ++ ++ * builds/mac/freetype-Info.plist: New file. ++ ++2014-05-13 Pavel Koshevoy <pkoshevoy@gmail.com> ++ ++ * CMakeLists.txt (BASE_SRCS): Add missing `ftbdf.c'. ++ ++2014-05-11 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Fix variable initializations. ++ ++ * src/autofit/afhints.c (af_glyph_hints_reload): Assign default ++ values to `in_dir' and `out_dir' for all points. ++ ++2014-05-11 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Fix crash with font `CabinSketch-Bold.ttf'. ++ ++ Problem reported by Ralf S. Engelschall <rse@engelschall.com>. ++ ++ * src/autofit/afhints.c (af_glyph_hints_reload): Fix threshold for ++ finding first non-near point. ++ Properly initialize non-near point deltas. ++ ++2014-05-01 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Add blue-zone support for Devanagari. ++ ++ This essentially moves the Devanagari script from the `Indic' hinter ++ to the `Latin' hinter. Thanks to Girish Dalvi ++ <girish.dalvi@gmail.com> for guidance with blue zone characters! ++ ++ * src/autofit/afblue.dat: Add blue zone data for Devanagari. ++ ++ * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. ++ ++ * src/autofit/afscript.h: Add Devanagari standard characters and ++ move data out of AF_CONFIG_OPTION_INDIC block. ++ ++ * src/autofit/afranges.c: Move Devanagari data out of ++ AF_CONFIG_OPTION_INDIC block. ++ Move U+20B9, (new) Rupee sign, from Latin to Devanagari. ++ ++ * src/autofit/afstyles.h: Update Devanagari data; in particular, use ++ AF_WRITING_SYSTEM_LATIN. ++ ++2014-05-01 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Fix handling of neutral blue zones in stems. ++ ++ * src/autofit/afhints.h (AF_Edge_Flags): New value ++ `AF_EDGE_NEUTRAL'. ++ ++ * src/autofit/aflatin.c (af_latin_hints_compute_blue_edges): Trace ++ neutral blue zones with AF_EDGE_NEUTRAL. ++ (af_latin_hint_edges): Skip neutral blue zones if necessary. ++ ++2014-04-28 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Introduce neutral blue zones to the latin module. ++ ++ Such blue zones match either the top or the bottom of a contour. We ++ need them for scripts where accent-like elements directly touch the ++ base character (for example, some vowel signs in Devanagari, cf. ++ U+0913 or U+0914). ++ ++ * src/autofit/afblue.hin (AF_BLUE_PROPERTY_LATIN_NEUTRAL): New ++ property. ++ ++ * src/autofit/afblue.h: Regenerated. ++ ++ * src/autofit/aflatin.h (AF_LATIN_IS_NEUTRAL_BLUE): New macro. ++ (AF_LATIN_BLUE_NEUTRAL): New enumeration value. ++ ++ * src/autofit/aflatin.c (af_latin_metrics_init_blues, ++ af_latin_hints_compute_blue_edges): Handle neutral blue zones. ++ ++2014-04-25 Werner Lemberg <wl@gnu.org> ++ ++ * src/autofit/hbshim.c: Partially revert commit from 2014-04-17. ++ ++ Using input glyph coverage data is simply wrong. ++ ++ Problem reported by Nikolaus Waxweiler <madigens@gmail.com> and ++ Mantas Mikulėnas <grawity@gmail.com>. ++ ++2014-04-23 Werner Lemberg <wl@gnu.org> ++ ++ * src/raster/ftraster.c (Vertical_Sweep_Span): Use drop-out mode. ++ ++ This spot has been missed while introducing support for various ++ drop-out modes years ago (including no drop-out mode, which this ++ commit fixes). ++ ++ Problem reported by Patrick Thomas <pthomas505@gmail.com>. ++ ++2014-04-22 Werner Lemberg <wl@gnu.org> ++ ++ * src/sfnt/pngshim.c (error_callback): s/longjmp/ft_longjmp/. ++ ++2014-04-20 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Fix Savannah bug #42148. ++ ++ The adaptation of the cjk auto-hinter module to blue stringsets in ++ 2013-08-25 had three severe bugs. Mea culpa. ++ ++ 1. Contrary to the latin auto-hinter, characters for reference and ++ overshoot values of a blue zone are specified separately. Due to ++ the screwed-up change it didn't work at all. ++ ++ 2. A boolean comparison was erroneously replaced with a cast, ++ causing invalid results with the `^' operator later on. The ++ visual artifact caused by this problem is the topic of the bug ++ report. ++ ++ 3. Two flag values were inverted, causing incorrect assignment of ++ reference and overshoot values. ++ ++ * src/autofit/afblue.dat: Fix CJK bluestrings, introducing a new ++ syntax to have both reference and overshoot characters in a single ++ string. This is error #1. ++ Add extensive comments. ++ ++ * src/autofit/afblue.hin (AF_BLUE_PROPERTY_CJK_FILL): Removed, no ++ longer used. ++ (AF_BLUE_PROPERTY_CJK_TOP, AF_BLUE_PROPERTY_CJK_HORIZ): Fix values. ++ This is error #3. ++ ++ * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated. ++ ++ * src/autofit/afcjk.c (af_cjk_metrics_init_blues): Correct error #1. ++ Use character `|' to separate characters for reference and overshoot ++ values. ++ Improve tracing messages, synchronizing them with the latin ++ auto-hinter. ++ (af_cjk_hints_compute_blue_edges): Fix value of `is_top_right_blue'. ++ This is error #2. ++ (af_cjk_align_linked_edge): Add tracing message. ++ ++ * src/autofit/afcjk.h (AF_CJK_IS_FILLED_BLUE): Removed, no longer ++ used. ++ ++2014-04-17 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] More coverage fixes for complex scripts. ++ ++ * src/autofit/hbshim.c (af_get_coverage): Merge input glyph coverage ++ of GSUB lookups into output coverage. Otherwise, ligatures are not ++ handled properly. ++ Don't check blue zone characters for default coverage. ++ ++2014-04-17 Werner Lemberg <wl@gnu.org> ++ ++ Make `FT_Get_SubGlyph_Info' actually work. ++ ++ * src/base/ftobjs.c (FT_Get_SubGlyph_Info): Return FT_Err_Ok ++ if there is no error. ++ ++2014-04-15 Werner Lemberg <wl@gnu.org> ++ ++ [afblue.pl]: Minor improvements. ++ ++ * src/tools/afblue.pl: Allow whitespace before comments. ++ Ignore whitespace in strings. ++ ++2014-04-14 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Improve coverage handling. ++ ++ * src/autofit/hbshim.c (af_get_coverage): Don't exclude glyphs ++ appearing in the GPOS table if we are processing the default ++ coverage. ++ ++2014-04-13 David Weber <weber.aulendorf@googlemail.com> ++ ++ [smooth] Fix stand-alone compilation. ++ ++ * src/smooth/ftgrays.c (FT_BEGIN_STMNT, FT_END_STMNT): Define. ++ ++2014-04-12 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Redesign the recognition algorithm of strong points. ++ ++ In particular, local extrema without horizontal or vertical segments ++ are better recognized: ++ ++ + A + D ++ \ / ++ \ / ++ \ / ++ \ / ++ \ + C ++ \ / ++ B +/ ++ ++ If the distances AB and CD are large, point B wasn't previously ++ detected as an extremum since the `ft_corner_is_flat' function ++ `swallowed' BC regardless of its direction, tagging point B as weak. ++ The next iteration started at B and made `ft_corner_is_flat' swallow ++ point C, tagging it as weak also, et voilà. ++ ++ To improve that, another pass gets now performed before calling ++ `ft_corner_is_flat' to improve the `topology' of an outline: A ++ sequence of non-horizontal or non-vertical vectors that point into ++ the same quadrant are handled as a single, large vector. ++ ++ Additionally, distances of near points are now accumulated, which ++ makes the auto-hinter handle them as if they were prepended to the ++ next non-near vector. ++ ++ This generally improves the auto-hinter's rendering results. ++ ++ * src/autofit/afhints.c (af_glyph_hints_reload): Implement it. ++ ++ * src/autofit/afhints.h (AF_FLAGS): Remove no longer used flag ++ `AF_FLAG_NEAR'. ++ ++2014-04-05 Werner Lemberg <wl@gnu.org> ++ ++ [autofit] Improve scoring algorithm for identifying stems. ++ ++ Problem reported by Karsten Lücke <karsten.luecke@kltf.de>. ++ ++ The new algorithm takes care of the width of stems: If the distance ++ between two segments is larger than the largest stem width, the ++ demerits quickly increase for larger distances. This improves ++ hinting of slanted fonts (especially if the inner parts of serifs ++ have non-horizontal `shoulders'), avoiding false stem links. ++ ++ * src/autofit/aflatin.c (af_latin_hints_link_segments): Use largest ++ stem width (if available) to compute better demerits for distances ++ between stems. ++ (af_latin_hints_detect_features): Pass stem width array and array ++ size. ++ (af_latin_metrics_init_widths): Updated to use original algorithm. ++ (af_latin_hints_apply): Updated to use new algorithm. ++ ++ * src/autofit/aflatin.h: Updated. ++ * src/autofit/afcjk.c: Updated. ++ ++2014-04-03 Werner Lemberg <wl@gnu.org> ++ ++ Don't require `gzip' module for `sfnt'. ++ ++ Reported by Preet <prismatic.project@gmail.com>. ++ ++ * src/sfnt/sfobjs.c (woff_open_font): Guard use of ++ FT_Gzip_Uncompress with FT_CONFIG_OPTION_USE_ZLIB. ++ ++2014-03-27 Werner Lemberg <wl@gnu.org> ++ ++ Fix Savannah bug #38235. ++ ++ Work around a bug in pkg-config version 0.28 and earlier: If a ++ variable value gets surrounded by doublequotes (in particular values ++ for the `prefix' variable), the prefix override mechanism fails. ++ ++ * builds/unix/freetype2.in: Don't use doublequotes. ++ * builds/unix/unix-def.in (freetype.pc): Escape spaces in directory ++ names with backslashes. ++ ++2014-03-24 Werner Lemberg <wl@gnu.org> ++ ++ Fix Savannah bug #41946. ++ ++ Based on a patch from Marek Kašík <mkasik@redhat.com>. ++ ++ * builds/unix/configure.raw (LIBS_CONFIG): Remove. ++ * builds/unix/freetype-config.in (libs): Hard-code value. ++ * builds/unix/unix-def.in: Updated. ++ ++2014-03-22 Werner Lemberg <wl@gnu.org> ++ ++ Another revert for the change from 2014-03-18. ++ ++ Problem reported by Nikolaus Waxweiler <madigens@gmail.com>. ++ ++ * src/base/ftcalc.c (FT_MulFix): Ensure that an `FT_MulFix' symbol ++ gets always exported. ++ ++2014-03-20 Werner Lemberg <wl@gnu.org> ++ ++ CMakeLists.txt: Another fix for include directories. ++ ++ Problem reported by Taylor Holberton <taylorcholberton@gmail.com>. ++ ++2014-03-19 Werner Lemberg <wl@gnu.org> ++ ++ CMakeLists.txt: Fix include directories. ++ ++ Problem reported by Taylor Holberton <taylorcholberton@gmail.com>. ++ ++2014-03-19 Werner Lemberg <wl@gnu.org> ++ ++ Partially revert last commit. ++ ++ Found by Alexei. ++ ++ * src/autofit/aflatin.c (af_latin_metrics_init_blues): Initializing ++ those variables is plain wrong, since we are in a loop. ++ ++2014-03-18 Sean McBride <sean@rogue-research.com> ++ Werner Lemberg <wl@gnu.org> ++ ++ Fix clang warnings. ++ ++ * src/autofit/aflatin.c (af_latin_metrics_init_blues): Initialize ++ some variables. ++ ++ * src/base/ftcalc.c (FT_MulFix): Only use code if ++ `FT_MULFIX_INLINED' is not defined. ++ ++ * src/bdf/bdfdrivr.c (bdf_cmap_class), src/cache/ftcbasic.c ++ (ftc_basic_image_family_class, ftc_basic_image_cache_class, ++ ftc_basic_sbit_family_class, ftc_basic_sbit_cache_class), ++ src/cache/ftccmap.c (ftc_cmap_cache_class), src/cache/ftcmanag.c ++ (ftc_size_list_class, ftc_face_list_class), src/pcf/pcfdrivr.c ++ (pcf_cmap_class), src/pfr/pfrdrivr.c (pfr_metrics_service_rec): Make ++ function static. ++ ++ * src/type1/t1driver.c (t1_ps_get_font_value): Remove redundant ++ code. ++ ++2014-03-17 Werner Lemberg <wl@gnu.org> ++ ++ Fix Savannah bug #41869. ++ ++ This works around a problem with HarfBuzz (<= 0.9.26), which doesn't ++ validate glyph indices returned by ++ `hb_ot_layout_lookup_collect_glyphs'. ++ ++ * src/autofit/hbshim.c (af_get_coverage): Guard `idx'. ++ ++ * docs/CHANGES: Updated. ++ ++2014-03-14 Werner Lemberg <wl@gnu.org> ++ ++ * builds/unix/configure.raw: Don't show error messages of `which'. ++ ++2014-03-09 Alan Coopersmith <alan.coopersmith@oracle.com> ++ ++ Fix cppcheck 1.64 warning. ++ ++ * src/autofit/afglobal.c (af_face_globals_new): Catch NULL pointer ++ dereference in case of error. ++ ++2014-03-09 Sean McBride <sean@rogue-research.com> ++ ++ * src/sfnt/ttcmap.c (tt_face_build_cmaps): Remove clang warning. ++ + 2014-03-06 Werner Lemberg <wl@gnu.org> + + * Version 2.5.3 released. +diff --git a/builds/mac/freetype-Info.plist b/builds/mac/freetype-Info.plist +new file mode 100644 +index 0000000..b3d114d +--- /dev/null ++++ b/builds/mac/freetype-Info.plist +@@ -0,0 +1,36 @@ ++<?xml version="1.0" encoding="UTF-8"?> ++<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ++ "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> ++ ++<plist version="1.0"> ++ ++<dict> ++ <key>CFBundleDevelopmentRegion</key> ++ <string>English</string> ++ ++ <key>CFBundleExecutable</key> ++ <string>FreeType</string> ++ ++ <key>CFBundleGetInfoString</key> ++ <string>FreeType ${PROJECT_VERSION}</string> ++ ++ <key>CFBundleInfoDictionaryVersion</key> ++ <string>6.0</string> ++ ++ <key>CFBundleName</key> ++ <string>FreeType</string> ++ ++ <key>CFBundlePackageType</key> ++ <string>FMWK</string> ++ ++ <key>CFBundleShortVersionString</key> ++ <string>${PROJECT_VERSION}</string> ++ ++ <key>CFBundleSignature</key> ++ <string>????</string> ++ ++ <key>CFBundleVersion</key> ++ <string>${PROJECT_VERSION}</string> ++</dict> ++ ++</plist> +diff --git a/builds/unix/configure.raw b/builds/unix/configure.raw +index dd7e576..8a17ffe 100644 +--- a/builds/unix/configure.raw ++++ b/builds/unix/configure.raw +@@ -437,7 +437,7 @@ if test x"$with_png" = xyes -o x"$with_png" = xauto; then + else + # fall back to config script. + AC_MSG_CHECKING([for libpng-config]) +- if which libpng-config > /dev/null; then ++ if which libpng-config > /dev/null 2>&1; then + LIBPNG_CFLAGS=`libpng-config --cflags` + LIBPNG_LIBS=`libpng-config --ldflags` + libpng_libpriv=`libpng-config --static --ldflags` +@@ -656,7 +656,7 @@ else + fi + + +-# Whether to use FileManager which is deprecated since Mac OS X 10.4. ++# Whether to use FileManager, which is deprecated since Mac OS X 10.4. + + AC_ARG_WITH([fsspec], + AS_HELP_STRING([--with-fsspec], +@@ -765,7 +765,7 @@ elif test x$with_old_mac_fonts = xyes -a x$with_fsref != x; then + fi + + +-# Whether to use QuickDraw API in ToolBox which is deprecated since ++# Whether to use QuickDraw API in ToolBox, which is deprecated since + # Mac OS X 10.4. + + AC_ARG_WITH([quickdraw-toolbox], +@@ -807,7 +807,7 @@ elif test x$with_old_mac_fonts = xyes -a x$with_quickdraw_toolbox != x; then + fi + + +-# Whether to use QuickDraw API in Carbon which is deprecated since ++# Whether to use QuickDraw API in Carbon, which is deprecated since + # Mac OS X 10.4. + + AC_ARG_WITH([quickdraw-carbon], +@@ -937,21 +937,6 @@ LIBS_PRIVATE=`echo "$LIBS_PRIVATE" \ + -e 's/ *$//' \ + -e 's/ */ /g'` + +-LIBS_CONFIG="-lfreetype \ +- $ZLIB_LIBS \ +- $BZIP2_LIBS \ +- $LIBPNG_LIBS \ +- $HARFBUZZ_LIBS \ +- $ft2_extra_libs" +-# remove -L/usr/lib and -L/usr/lib64 since `freetype-config' adds them later +-# on if necessary; also beautify +-LIBS_CONFIG=`echo "$LIBS_CONFIG" \ +- | sed -e 's|-L */usr/lib64/* | |g' \ +- -e 's|-L */usr/lib/* | |g' \ +- -e 's/^ *//' \ +- -e 's/ *$//' \ +- -e 's/ */ /g'` +- + LIBSSTATIC_CONFIG="-lfreetype \ + $zlib_libstaticconf \ + $bzip2_libstaticconf \ +@@ -971,7 +956,6 @@ LIBSSTATIC_CONFIG=`echo "$LIBSSTATIC_CONFIG" \ + AC_SUBST([ftmac_c]) + AC_SUBST([REQUIRES_PRIVATE]) + AC_SUBST([LIBS_PRIVATE]) +-AC_SUBST([LIBS_CONFIG]) + AC_SUBST([LIBSSTATIC_CONFIG]) + + AC_SUBST([hardcode_libdir_flag_spec]) +diff --git a/builds/unix/freetype-config.in b/builds/unix/freetype-config.in +index 41c3a88..ebc311f 100644 +--- a/builds/unix/freetype-config.in ++++ b/builds/unix/freetype-config.in +@@ -142,7 +142,7 @@ if test "$echo_cflags" = "yes" ; then + fi + + if test "$echo_libs" = "yes" ; then +- libs="%LIBS_CONFIG%" ++ libs="-lfreetype" + staticlibs="%LIBSSTATIC_CONFIG%" + if test "$show_static" = "yes" ; then + libs="$staticlibs" +diff --git a/builds/unix/freetype2.in b/builds/unix/freetype2.in +index 6e7fb10..a488d96 100644 +--- a/builds/unix/freetype2.in ++++ b/builds/unix/freetype2.in +@@ -1,7 +1,7 @@ +-prefix="%prefix%" +-exec_prefix="%exec_prefix%" +-libdir="%libdir%" +-includedir="%includedir%/freetype2" ++prefix=%prefix% ++exec_prefix=%exec_prefix% ++libdir=%libdir% ++includedir=%includedir%/freetype2 + + Name: FreeType 2 + URL: http://freetype.org +diff --git a/builds/unix/freetype2.m4 b/builds/unix/freetype2.m4 +index 3d0ecb3..3a806d9 100644 +--- a/builds/unix/freetype2.m4 ++++ b/builds/unix/freetype2.m4 +@@ -1,7 +1,7 @@ + # Configure paths for FreeType2 + # Marcelo Magallon 2001-10-26, based on gtk.m4 by Owen Taylor + # +-# Copyright 2001, 2003, 2007, 2009 by ++# Copyright 2001, 2003, 2007, 2009, 2014 by + # David Turner, Robert Wilhelm, and Werner Lemberg. + # + # This file is part of the FreeType project, and may only be used, modified, +@@ -15,7 +15,7 @@ + # generated by Autoconf, under the same distribution terms as the rest of + # that program. + # +-# serial 3 ++# serial 4 + + # AC_CHECK_FT2([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) + # Test for FreeType 2, and define FT2_CFLAGS and FT2_LIBS. +@@ -61,7 +61,7 @@ AC_DEFUN([AC_CHECK_FT2], + fi + + if test "x$FT2_CONFIG" = x ; then +- AC_PATH_PROG([FT2_CONFIG], [freetype-config], [no]) ++ AC_PATH_TOOL([FT2_CONFIG], [freetype-config], [no]) + fi + + min_ft_version=m4_if([$1], [], [7.0.1], [$1]) +diff --git a/builds/unix/ftconfig.in b/builds/unix/ftconfig.in +index 2cf6708..e66f3ea 100644 +--- a/builds/unix/ftconfig.in ++++ b/builds/unix/ftconfig.in +@@ -296,7 +296,16 @@ FT_BEGIN_HEADER + #define FT_INT64 long + #define FT_UINT64 unsigned long + +-#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ ++ /*************************************************************************/ ++ /* */ ++ /* A 64-bit data type may create compilation problems if you compile */ ++ /* in strict ANSI mode. To avoid them, we disable other 64-bit data */ ++ /* types if __STDC__ is defined. You can however ignore this rule */ ++ /* by defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */ ++ /* */ ++#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 ) ++ ++#if defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ + + /* this compiler provides the __int64 type */ + #define FT_LONG64 +@@ -330,30 +339,9 @@ FT_BEGIN_HEADER + #define FT_INT64 long long int + #define FT_UINT64 unsigned long long int + +-#endif /* FT_SIZEOF_LONG == 8 */ +- +- +- /*************************************************************************/ +- /* */ +- /* A 64-bit data type will create compilation problems if you compile */ +- /* in strict ANSI mode. To avoid them, we disable its use if __STDC__ */ +- /* is defined. You can however ignore this rule by defining the */ +- /* FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */ +- /* */ +-#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 ) +- +-#ifdef __STDC__ +- +- /* Undefine the 64-bit macros in strict ANSI compilation mode. */ +- /* Since `#undef' doesn't survive in configuration header files */ +- /* we use the postprocessing facility of AC_CONFIG_HEADERS to */ +- /* replace the leading `/' with `#'. */ +-/undef FT_LONG64 +-/undef FT_INT64 +- +-#endif /* __STDC__ */ ++#endif /* _MSC_VER */ + +-#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */ ++#endif /* FT_SIZEOF_LONG == 8 */ + + #ifdef FT_LONG64 + typedef FT_INT64 FT_Int64; +@@ -366,219 +354,6 @@ FT_BEGIN_HEADER + #define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT + + +-#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER +- /* Provide assembler fragments for performance-critical functions. */ +- /* These must be defined `static __inline__' with GCC. */ +- +-#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */ +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm +- +- /* documentation is in freetype.h */ +- +- static __inline FT_Int32 +- FT_MulFix_arm( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 t, t2; +- +- +- __asm +- { +- smull t2, t, b, a /* (lo=t2,hi=t) = a*b */ +- mov a, t, asr #31 /* a = (hi >> 31) */ +- add a, a, #0x8000 /* a += 0x8000 */ +- adds t2, t2, a /* t2 += a */ +- adc t, t, #0 /* t += carry */ +- mov a, t2, lsr #16 /* a = t2 >> 16 */ +- orr a, a, t, lsl #16 /* a |= t << 16 */ +- } +- return a; +- } +- +-#endif /* __CC_ARM || __ARMCC__ */ +- +- +-#ifdef __GNUC__ +- +-#if defined( __arm__ ) && \ +- ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \ +- !( defined( __CC_ARM ) || defined( __ARMCC__ ) ) +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm +- +- /* documentation is in freetype.h */ +- +- static __inline__ FT_Int32 +- FT_MulFix_arm( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 t, t2; +- +- +- __asm__ __volatile__ ( +- "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */ +- "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */ +-#if defined( __clang__ ) && defined( __thumb2__ ) +- "add.w %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ +-#else +- "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ +-#endif +- "adds %1, %1, %0\n\t" /* %1 += %0 */ +- "adc %2, %2, #0\n\t" /* %2 += carry */ +- "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */ +- "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */ +- : "=r"(a), "=&r"(t2), "=&r"(t) +- : "r"(a), "r"(b) +- : "cc" ); +- return a; +- } +- +-#endif /* __arm__ && */ +- /* ( __thumb2__ || !__thumb__ ) && */ +- /* !( __CC_ARM || __ARMCC__ ) */ +- +- +-#if defined( __i386__ ) +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 +- +- /* documentation is in freetype.h */ +- +- static __inline__ FT_Int32 +- FT_MulFix_i386( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 result; +- +- +- __asm__ __volatile__ ( +- "imul %%edx\n" +- "movl %%edx, %%ecx\n" +- "sarl $31, %%ecx\n" +- "addl $0x8000, %%ecx\n" +- "addl %%ecx, %%eax\n" +- "adcl $0, %%edx\n" +- "shrl $16, %%eax\n" +- "shll $16, %%edx\n" +- "addl %%edx, %%eax\n" +- : "=a"(result), "=d"(b) +- : "a"(a), "d"(b) +- : "%ecx", "cc" ); +- return result; +- } +- +-#endif /* i386 */ +- +-#endif /* __GNUC__ */ +- +- +-#ifdef _MSC_VER /* Visual C++ */ +- +-#ifdef _M_IX86 +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 +- +- /* documentation is in freetype.h */ +- +- static __inline FT_Int32 +- FT_MulFix_i386( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 result; +- +- __asm +- { +- mov eax, a +- mov edx, b +- imul edx +- mov ecx, edx +- sar ecx, 31 +- add ecx, 8000h +- add eax, ecx +- adc edx, 0 +- shr eax, 16 +- shl edx, 16 +- add eax, edx +- mov result, eax +- } +- return result; +- } +- +-#endif /* _M_IX86 */ +- +-#endif /* _MSC_VER */ +- +- +-#if defined( __GNUC__ ) && defined( __x86_64__ ) +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64 +- +- static __inline__ FT_Int32 +- FT_MulFix_x86_64( FT_Int32 a, +- FT_Int32 b ) +- { +- /* Temporarily disable the warning that C90 doesn't support */ +- /* `long long'. */ +-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) ) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wlong-long" +-#endif +- +-#if 1 +- /* Technically not an assembly fragment, but GCC does a really good */ +- /* job at inlining it and generating good machine code for it. */ +- long long ret, tmp; +- +- +- ret = (long long)a * b; +- tmp = ret >> 63; +- ret += 0x8000 + tmp; +- +- return (FT_Int32)( ret >> 16 ); +-#else +- +- /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */ +- /* code from the lines below. The main issue is that `wide_a' is not */ +- /* properly initialized by sign-extending `a'. Instead, the generated */ +- /* machine code assumes that the register that contains `a' on input */ +- /* can be used directly as a 64-bit value, which is wrong most of the */ +- /* time. */ +- long long wide_a = (long long)a; +- long long wide_b = (long long)b; +- long long result; +- +- +- __asm__ __volatile__ ( +- "imul %2, %1\n" +- "mov %1, %0\n" +- "sar $63, %0\n" +- "lea 0x8000(%1, %0), %0\n" +- "sar $16, %0\n" +- : "=&r"(result), "=&r"(wide_a) +- : "r"(wide_b) +- : "cc" ); +- +- return (FT_Int32)result; +-#endif +- +-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) ) +-#pragma GCC diagnostic pop +-#endif +- } +- +-#endif /* __GNUC__ && __x86_64__ */ +- +-#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ +- +- +-#ifdef FT_CONFIG_OPTION_INLINE_MULFIX +-#ifdef FT_MULFIX_ASSEMBLER +-#define FT_MULFIX_INLINED FT_MULFIX_ASSEMBLER +-#endif +-#endif +- +- + #ifdef FT_MAKE_OPTION_SINGLE_OBJECT + + #define FT_LOCAL( x ) static x +diff --git a/builds/unix/unix-def.in b/builds/unix/unix-def.in +index 35ea9c8..4c06a05 100644 +--- a/builds/unix/unix-def.in ++++ b/builds/unix/unix-def.in +@@ -64,7 +64,6 @@ version_info := @version_info@ + # + REQUIRES_PRIVATE := @REQUIRES_PRIVATE@ + LIBS_PRIVATE := @LIBS_PRIVATE@ +-LIBS_CONFIG := @LIBS_CONFIG@ + LIBSSTATIC_CONFIG := @LIBSSTATIC_CONFIG@ + build_libtool_libs := @build_libtool_libs@ + ft_version := @ft_version@ +@@ -102,8 +101,7 @@ NO_OUTPUT := 2> /dev/null + + $(OBJ_BUILD)/freetype-config: $(TOP_DIR)/builds/unix/freetype-config.in + rm -f $@ $@.tmp +- sed -e 's|%LIBS_CONFIG%|$(LIBS_CONFIG)|' \ +- -e 's|%LIBSSTATIC_CONFIG%|$(LIBSSTATIC_CONFIG)|' \ ++ sed -e 's|%LIBSSTATIC_CONFIG%|$(LIBSSTATIC_CONFIG)|' \ + -e 's|%build_libtool_libs%|$(build_libtool_libs)|' \ + -e 's|%exec_prefix%|$(exec_prefix)|' \ + -e 's|%ft_version%|$(ft_version)|' \ +@@ -116,16 +114,29 @@ $(OBJ_BUILD)/freetype-config: $(TOP_DIR)/builds/unix/freetype-config.in + chmod a-w $@.tmp + mv $@.tmp $@ + ++# To support directory names with spaces (as might easily happen on Windows ++# platforms), the right solution would be to surround the pkg-variables in ++# `freetype2.pc' with double quotes. However, doing so ironically disables ++# the prefix override mechanism especially written for Windows. This is a ++# bug in pkg-config version 0.28 and earlier. ++# ++# For this reason, we escape spaces with backslashes. ++ ++exec_prefix_x := $(subst $(space),\\$(space),$(exec_prefix)) ++includedir_x := $(subst $(space),\\$(space),$(includedir)) ++libdir_x := $(subst $(space),\\$(space),$(libdir)) ++prefix_x := $(subst $(space),\\$(space),$(prefix)) ++ + $(OBJ_BUILD)/freetype2.pc: $(TOP_DIR)/builds/unix/freetype2.in + rm -f $@ $@.tmp + sed -e 's|%REQUIRES_PRIVATE%|$(REQUIRES_PRIVATE)|' \ + -e 's|%LIBS_PRIVATE%|$(LIBS_PRIVATE)|' \ + -e 's|%build_libtool_libs%|$(build_libtool_libs)|' \ +- -e 's|%exec_prefix%|$(exec_prefix)|' \ ++ -e 's|%exec_prefix%|$(exec_prefix_x)|' \ + -e 's|%ft_version%|$(ft_version)|' \ +- -e 's|%includedir%|$(includedir)|' \ +- -e 's|%libdir%|$(libdir)|' \ +- -e 's|%prefix%|$(prefix)|' \ ++ -e 's|%includedir%|$(includedir_x)|' \ ++ -e 's|%libdir%|$(libdir_x)|' \ ++ -e 's|%prefix%|$(prefix_x)|' \ + $< \ + > $@.tmp + chmod a-w $@.tmp +diff --git a/builds/vms/ftconfig.h b/builds/vms/ftconfig.h +index 3fb8f84..b309651 100644 +--- a/builds/vms/ftconfig.h ++++ b/builds/vms/ftconfig.h +@@ -4,7 +4,7 @@ + /* */ + /* VMS-specific configuration file (specification only). */ + /* */ +-/* Copyright 1996-2004, 2006-2008, 2011, 2013 by */ ++/* Copyright 1996-2004, 2006-2008, 2011, 2013, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -239,7 +239,16 @@ FT_BEGIN_HEADER + #define FT_INT64 long + #define FT_UINT64 unsigned long + +-#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ ++ /*************************************************************************/ ++ /* */ ++ /* A 64-bit data type may create compilation problems if you compile */ ++ /* in strict ANSI mode. To avoid them, we disable other 64-bit data */ ++ /* types if __STDC__ is defined. You can however ignore this rule */ ++ /* by defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */ ++ /* */ ++#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 ) ++ ++#if defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ + + /* this compiler provides the __int64 type */ + #define FT_LONG64 +@@ -273,27 +282,9 @@ FT_BEGIN_HEADER + #define FT_INT64 long long int + #define FT_UINT64 unsigned long long int + +-#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */ +- +- +- /*************************************************************************/ +- /* */ +- /* A 64-bit data type will create compilation problems if you compile */ +- /* in strict ANSI mode. To avoid them, we disable its use if __STDC__ */ +- /* is defined. You can however ignore this rule by defining the */ +- /* FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */ +- /* */ +-#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 ) +- +-#ifdef __STDC__ +- +- /* undefine the 64-bit macros in strict ANSI compilation mode */ +-#undef FT_LONG64 +-#undef FT_INT64 +- +-#endif /* __STDC__ */ ++#endif /* _MSC_VER */ + +-#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */ ++#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */ + + #ifdef FT_LONG64 + typedef FT_INT64 FT_Int64; +@@ -306,215 +297,6 @@ FT_BEGIN_HEADER + #define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT + + +-#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER +- /* Provide assembler fragments for performance-critical functions. */ +- /* These must be defined `static __inline__' with GCC. */ +- +-#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */ +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm +- +- /* documentation is in freetype.h */ +- +- static __inline FT_Int32 +- FT_MulFix_arm( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 t, t2; +- +- +- __asm +- { +- smull t2, t, b, a /* (lo=t2,hi=t) = a*b */ +- mov a, t, asr #31 /* a = (hi >> 31) */ +- add a, a, #0x8000 /* a += 0x8000 */ +- adds t2, t2, a /* t2 += a */ +- adc t, t, #0 /* t += carry */ +- mov a, t2, lsr #16 /* a = t2 >> 16 */ +- orr a, a, t, lsl #16 /* a |= t << 16 */ +- } +- return a; +- } +- +-#endif /* __CC_ARM || __ARMCC__ */ +- +- +-#ifdef __GNUC__ +- +-#if defined( __arm__ ) && \ +- ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \ +- !( defined( __CC_ARM ) || defined( __ARMCC__ ) ) +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm +- +- /* documentation is in freetype.h */ +- +- static __inline__ FT_Int32 +- FT_MulFix_arm( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 t, t2; +- +- +- __asm__ __volatile__ ( +- "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */ +- "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */ +- "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ +- "adds %1, %1, %0\n\t" /* %1 += %0 */ +- "adc %2, %2, #0\n\t" /* %2 += carry */ +- "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */ +- "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */ +- : "=r"(a), "=&r"(t2), "=&r"(t) +- : "r"(a), "r"(b) +- : "cc" ); +- return a; +- } +- +-#endif /* __arm__ && */ +- /* ( __thumb2__ || !__thumb__ ) && */ +- /* !( __CC_ARM || __ARMCC__ ) */ +- +- +-#if defined( __i386__ ) +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 +- +- /* documentation is in freetype.h */ +- +- static __inline__ FT_Int32 +- FT_MulFix_i386( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 result; +- +- +- __asm__ __volatile__ ( +- "imul %%edx\n" +- "movl %%edx, %%ecx\n" +- "sarl $31, %%ecx\n" +- "addl $0x8000, %%ecx\n" +- "addl %%ecx, %%eax\n" +- "adcl $0, %%edx\n" +- "shrl $16, %%eax\n" +- "shll $16, %%edx\n" +- "addl %%edx, %%eax\n" +- : "=a"(result), "=d"(b) +- : "a"(a), "d"(b) +- : "%ecx", "cc" ); +- return result; +- } +- +-#endif /* i386 */ +- +-#endif /* __GNUC__ */ +- +- +-#ifdef _MSC_VER /* Visual C++ */ +- +-#ifdef _M_IX86 +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 +- +- /* documentation is in freetype.h */ +- +- static __inline FT_Int32 +- FT_MulFix_i386( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 result; +- +- __asm +- { +- mov eax, a +- mov edx, b +- imul edx +- mov ecx, edx +- sar ecx, 31 +- add ecx, 8000h +- add eax, ecx +- adc edx, 0 +- shr eax, 16 +- shl edx, 16 +- add eax, edx +- mov result, eax +- } +- return result; +- } +- +-#endif /* _M_IX86 */ +- +-#endif /* _MSC_VER */ +- +- +-#if defined( __GNUC__ ) && defined( __x86_64__ ) +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64 +- +- static __inline__ FT_Int32 +- FT_MulFix_x86_64( FT_Int32 a, +- FT_Int32 b ) +- { +- /* Temporarily disable the warning that C90 doesn't support */ +- /* `long long'. */ +-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) ) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wlong-long" +-#endif +- +-#if 1 +- /* Technically not an assembly fragment, but GCC does a really good */ +- /* job at inlining it and generating good machine code for it. */ +- long long ret, tmp; +- +- +- ret = (long long)a * b; +- tmp = ret >> 63; +- ret += 0x8000 + tmp; +- +- return (FT_Int32)( ret >> 16 ); +-#else +- +- /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */ +- /* code from the lines below. The main issue is that `wide_a' is not */ +- /* properly initialized by sign-extending `a'. Instead, the generated */ +- /* machine code assumes that the register that contains `a' on input */ +- /* can be used directly as a 64-bit value, which is wrong most of the */ +- /* time. */ +- long long wide_a = (long long)a; +- long long wide_b = (long long)b; +- long long result; +- +- +- __asm__ __volatile__ ( +- "imul %2, %1\n" +- "mov %1, %0\n" +- "sar $63, %0\n" +- "lea 0x8000(%1, %0), %0\n" +- "sar $16, %0\n" +- : "=&r"(result), "=&r"(wide_a) +- : "r"(wide_b) +- : "cc" ); +- +- return (FT_Int32)result; +-#endif +- +-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) ) +-#pragma GCC diagnostic pop +-#endif +- } +- +-#endif /* __GNUC__ && __x86_64__ */ +- +-#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ +- +- +-#ifdef FT_CONFIG_OPTION_INLINE_MULFIX +-#ifdef FT_MULFIX_ASSEMBLER +-#define FT_MULFIX_INLINED FT_MULFIX_ASSEMBLER +-#endif +-#endif +- +- + #ifdef FT_MAKE_OPTION_SINGLE_OBJECT + + #define FT_LOCAL( x ) static x +diff --git a/docs/CHANGES b/docs/CHANGES +index 803f02d..51b829c 100644 +--- a/docs/CHANGES ++++ b/docs/CHANGES +@@ -1,11 +1,40 @@ + ++CHANGES BETWEEN 2.5.3 and 2.5.4 ++ ++ I. IMPORTANT BUG FIXES ++ ++ - The new auto-hinter code using HarfBuzz crashed for some invalid ++ fonts. ++ ++ ++ II. IMPORTANT CHANGES ++ ++ - Full auto-hinter support of the Devanagari script. ++ ++ ++ III. MISCELLANEOUS ++ ++ - Improvements to the auto-hinter's algorithm to recognize stems ++ and local extrema. ++ ++ - Function `FT_Get_SubGlyph_Info' always returned an error even in ++ case of success. ++ ++ - Version 2.5.1 introduced major bugs in the cjk part of the ++ auto-hinter, which are now fixed. ++ ++ - `cmake' now supports a build of FreeType as an OS X framework. ++ ++ ++====================================================================== ++ + CHANGES BETWEEN 2.5.2 and 2.5.3 + + I. IMPORTANT BUG FIXES + +- - A vulnerability was identified and fixed in the new CFF driver +- (cf. http://savannah.nongnu.org/bugs/?41697; it doesn't have a +- CVE number yet). All users should upgrade. ++ - A vulnerability (CVE-2014-2240) was identified and fixed in the ++ new CFF driver (cf. http://savannah.nongnu.org/bugs/?41697). ++ All users should upgrade. + + - More bug fixes related to correct positioning of composite + glyphs. +@@ -261,6 +290,9 @@ CHANGES BETWEEN 2.4.12 and 2.5 + it accepts a new command line option `-H' to select the hinting + engine. + ++ - `ftdump's verbose option has been renamed to `-V'. For all demo ++ programs, `-v' now shows version information. ++ + - Another round of TrueType subpixel hinting fixes. + + - The `apinames' tool can now create an import file for NetWare. +diff --git a/include/config/ftconfig.h b/include/config/ftconfig.h +index d98a311..22d70fd 100644 +--- a/include/config/ftconfig.h ++++ b/include/config/ftconfig.h +@@ -266,7 +266,16 @@ FT_BEGIN_HEADER + #define FT_INT64 long + #define FT_UINT64 unsigned long + +-#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ ++ /*************************************************************************/ ++ /* */ ++ /* A 64-bit data type may create compilation problems if you compile */ ++ /* in strict ANSI mode. To avoid them, we disable other 64-bit data */ ++ /* types if __STDC__ is defined. You can however ignore this rule */ ++ /* by defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */ ++ /* */ ++#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 ) ++ ++#if defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ + + /* this compiler provides the __int64 type */ + #define FT_LONG64 +@@ -300,27 +309,9 @@ FT_BEGIN_HEADER + #define FT_INT64 long long int + #define FT_UINT64 unsigned long long int + +-#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */ +- +- +- /*************************************************************************/ +- /* */ +- /* A 64-bit data type will create compilation problems if you compile */ +- /* in strict ANSI mode. To avoid them, we disable its use if __STDC__ */ +- /* is defined. You can however ignore this rule by defining the */ +- /* FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */ +- /* */ +-#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 ) +- +-#ifdef __STDC__ +- +- /* undefine the 64-bit macros in strict ANSI compilation mode */ +-#undef FT_LONG64 +-#undef FT_INT64 +- +-#endif /* __STDC__ */ ++#endif /* _MSC_VER */ + +-#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */ ++#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */ + + #ifdef FT_LONG64 + typedef FT_INT64 FT_Int64; +@@ -333,219 +324,6 @@ FT_BEGIN_HEADER + #define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT + + +-#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER +- /* Provide assembler fragments for performance-critical functions. */ +- /* These must be defined `static __inline__' with GCC. */ +- +-#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */ +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm +- +- /* documentation is in freetype.h */ +- +- static __inline FT_Int32 +- FT_MulFix_arm( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 t, t2; +- +- +- __asm +- { +- smull t2, t, b, a /* (lo=t2,hi=t) = a*b */ +- mov a, t, asr #31 /* a = (hi >> 31) */ +- add a, a, #0x8000 /* a += 0x8000 */ +- adds t2, t2, a /* t2 += a */ +- adc t, t, #0 /* t += carry */ +- mov a, t2, lsr #16 /* a = t2 >> 16 */ +- orr a, a, t, lsl #16 /* a |= t << 16 */ +- } +- return a; +- } +- +-#endif /* __CC_ARM || __ARMCC__ */ +- +- +-#ifdef __GNUC__ +- +-#if defined( __arm__ ) && \ +- ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \ +- !( defined( __CC_ARM ) || defined( __ARMCC__ ) ) +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm +- +- /* documentation is in freetype.h */ +- +- static __inline__ FT_Int32 +- FT_MulFix_arm( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 t, t2; +- +- +- __asm__ __volatile__ ( +- "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */ +- "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */ +-#if defined( __clang__ ) && defined( __thumb2__ ) +- "add.w %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ +-#else +- "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ +-#endif +- "adds %1, %1, %0\n\t" /* %1 += %0 */ +- "adc %2, %2, #0\n\t" /* %2 += carry */ +- "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */ +- "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */ +- : "=r"(a), "=&r"(t2), "=&r"(t) +- : "r"(a), "r"(b) +- : "cc" ); +- return a; +- } +- +-#endif /* __arm__ && */ +- /* ( __thumb2__ || !__thumb__ ) && */ +- /* !( __CC_ARM || __ARMCC__ ) */ +- +- +-#if defined( __i386__ ) +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 +- +- /* documentation is in freetype.h */ +- +- static __inline__ FT_Int32 +- FT_MulFix_i386( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 result; +- +- +- __asm__ __volatile__ ( +- "imul %%edx\n" +- "movl %%edx, %%ecx\n" +- "sarl $31, %%ecx\n" +- "addl $0x8000, %%ecx\n" +- "addl %%ecx, %%eax\n" +- "adcl $0, %%edx\n" +- "shrl $16, %%eax\n" +- "shll $16, %%edx\n" +- "addl %%edx, %%eax\n" +- : "=a"(result), "=d"(b) +- : "a"(a), "d"(b) +- : "%ecx", "cc" ); +- return result; +- } +- +-#endif /* i386 */ +- +-#endif /* __GNUC__ */ +- +- +-#ifdef _MSC_VER /* Visual C++ */ +- +-#ifdef _M_IX86 +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 +- +- /* documentation is in freetype.h */ +- +- static __inline FT_Int32 +- FT_MulFix_i386( FT_Int32 a, +- FT_Int32 b ) +- { +- register FT_Int32 result; +- +- __asm +- { +- mov eax, a +- mov edx, b +- imul edx +- mov ecx, edx +- sar ecx, 31 +- add ecx, 8000h +- add eax, ecx +- adc edx, 0 +- shr eax, 16 +- shl edx, 16 +- add eax, edx +- mov result, eax +- } +- return result; +- } +- +-#endif /* _M_IX86 */ +- +-#endif /* _MSC_VER */ +- +- +-#if defined( __GNUC__ ) && defined( __x86_64__ ) +- +-#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64 +- +- static __inline__ FT_Int32 +- FT_MulFix_x86_64( FT_Int32 a, +- FT_Int32 b ) +- { +- /* Temporarily disable the warning that C90 doesn't support */ +- /* `long long'. */ +-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) ) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wlong-long" +-#endif +- +-#if 1 +- /* Technically not an assembly fragment, but GCC does a really good */ +- /* job at inlining it and generating good machine code for it. */ +- long long ret, tmp; +- +- +- ret = (long long)a * b; +- tmp = ret >> 63; +- ret += 0x8000 + tmp; +- +- return (FT_Int32)( ret >> 16 ); +-#else +- +- /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */ +- /* code from the lines below. The main issue is that `wide_a' is not */ +- /* properly initialized by sign-extending `a'. Instead, the generated */ +- /* machine code assumes that the register that contains `a' on input */ +- /* can be used directly as a 64-bit value, which is wrong most of the */ +- /* time. */ +- long long wide_a = (long long)a; +- long long wide_b = (long long)b; +- long long result; +- +- +- __asm__ __volatile__ ( +- "imul %2, %1\n" +- "mov %1, %0\n" +- "sar $63, %0\n" +- "lea 0x8000(%1, %0), %0\n" +- "sar $16, %0\n" +- : "=&r"(result), "=&r"(wide_a) +- : "r"(wide_b) +- : "cc" ); +- +- return (FT_Int32)result; +-#endif +- +-#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) ) +-#pragma GCC diagnostic pop +-#endif +- } +- +-#endif /* __GNUC__ && __x86_64__ */ +- +-#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ +- +- +-#ifdef FT_CONFIG_OPTION_INLINE_MULFIX +-#ifdef FT_MULFIX_ASSEMBLER +-#define FT_MULFIX_INLINED FT_MULFIX_ASSEMBLER +-#endif +-#endif +- +- + #ifdef FT_MAKE_OPTION_SINGLE_OBJECT + + #define FT_LOCAL( x ) static x +diff --git a/include/freetype.h b/include/freetype.h +index fb62b62..6a31502 100644 +--- a/include/freetype.h ++++ b/include/freetype.h +@@ -1592,7 +1592,6 @@ FT_BEGIN_HEADER + /* This field is only valid for the composite */ + /* glyph format that should normally only be */ + /* loaded with the @FT_LOAD_NO_RECURSE flag. */ +- /* For now this is internal to FreeType. */ + /* */ + /* subglyphs :: An array of subglyph descriptors for */ + /* composite glyphs. There are `num_subglyphs' */ +@@ -2560,14 +2559,11 @@ FT_BEGIN_HEADER + * Ignored. Deprecated. + * + * FT_LOAD_NO_RECURSE :: +- * This flag is only used internally. It merely indicates that the +- * font driver should not load composite glyphs recursively. Instead, +- * it should set the `num_subglyph' and `subglyphs' values of the +- * glyph slot accordingly, and set `glyph->format' to +- * @FT_GLYPH_FORMAT_COMPOSITE. +- * +- * The description of sub-glyphs is not available to client +- * applications for now. ++ * Indicate that the font driver should not load composite glyphs ++ * recursively. Instead, it should set the `num_subglyph' and ++ * `subglyphs' values of the glyph slot accordingly, and set ++ * `glyph->format' to @FT_GLYPH_FORMAT_COMPOSITE. The description of ++ * subglyphs can then be accessed with @FT_Get_SubGlyph_Info. + * + * This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM. + * +@@ -3065,9 +3061,8 @@ FT_BEGIN_HEADER + /* glyph index~0 always corresponds to the `missing glyph' (called */ + /* `.notdef'). */ + /* */ +- /* This function is not compiled within the library if the config */ +- /* macro `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is defined in */ +- /* `ftoptions.h'. */ ++ /* This function always returns an error if the config macro */ ++ /* `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is not defined in `ftoptions.h'. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Glyph_Name( FT_Face face, +@@ -3767,12 +3762,6 @@ FT_BEGIN_HEADER + FT_Long c ); + + +- /* */ +- +- /* The following #if 0 ... #endif is for the documentation formatter, */ +- /* hiding the internal `FT_MULFIX_INLINED' macro. */ +- +-#if 0 + /*************************************************************************/ + /* */ + /* <Function> */ +@@ -3806,17 +3795,6 @@ FT_BEGIN_HEADER + FT_MulFix( FT_Long a, + FT_Long b ); + +- /* */ +-#endif +- +-#ifdef FT_MULFIX_INLINED +-#define FT_MulFix( a, b ) FT_MULFIX_INLINED( a, b ) +-#else +- FT_EXPORT( FT_Long ) +- FT_MulFix( FT_Long a, +- FT_Long b ); +-#endif +- + + /*************************************************************************/ + /* */ +@@ -3829,18 +3807,12 @@ FT_BEGIN_HEADER + /* used to divide a given value by a 16.16 fixed-point factor. */ + /* */ + /* <Input> */ +- /* a :: The first multiplier. */ +- /* b :: The second multiplier. Use a 16.16 factor here whenever */ +- /* possible (see note below). */ ++ /* a :: The numerator. */ ++ /* b :: The denominator. Use a 16.16 factor here. */ + /* */ + /* <Return> */ + /* The result of `(a*0x10000)/b'. */ + /* */ +- /* <Note> */ +- /* The optimization for FT_DivFix() is simple: If (a~<<~16) fits in */ +- /* 32~bits, then the division is computed directly. Otherwise, we */ +- /* use a specialized version of @FT_MulDiv. */ +- /* */ + FT_EXPORT( FT_Long ) + FT_DivFix( FT_Long a, + FT_Long b ); +diff --git a/include/fterrdef.h b/include/fterrdef.h +index 76c7b9e..99b2fad 100644 +--- a/include/fterrdef.h ++++ b/include/fterrdef.h +@@ -31,218 +31,218 @@ + + /* generic errors */ + +- FT_NOERRORDEF_( Ok, 0x00, \ ++ FT_NOERRORDEF_( Ok, 0x00, + "no error" ) + +- FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \ ++ FT_ERRORDEF_( Cannot_Open_Resource, 0x01, + "cannot open resource" ) +- FT_ERRORDEF_( Unknown_File_Format, 0x02, \ ++ FT_ERRORDEF_( Unknown_File_Format, 0x02, + "unknown file format" ) +- FT_ERRORDEF_( Invalid_File_Format, 0x03, \ ++ FT_ERRORDEF_( Invalid_File_Format, 0x03, + "broken file" ) +- FT_ERRORDEF_( Invalid_Version, 0x04, \ ++ FT_ERRORDEF_( Invalid_Version, 0x04, + "invalid FreeType version" ) +- FT_ERRORDEF_( Lower_Module_Version, 0x05, \ ++ FT_ERRORDEF_( Lower_Module_Version, 0x05, + "module version is too low" ) +- FT_ERRORDEF_( Invalid_Argument, 0x06, \ ++ FT_ERRORDEF_( Invalid_Argument, 0x06, + "invalid argument" ) +- FT_ERRORDEF_( Unimplemented_Feature, 0x07, \ ++ FT_ERRORDEF_( Unimplemented_Feature, 0x07, + "unimplemented feature" ) +- FT_ERRORDEF_( Invalid_Table, 0x08, \ ++ FT_ERRORDEF_( Invalid_Table, 0x08, + "broken table" ) +- FT_ERRORDEF_( Invalid_Offset, 0x09, \ ++ FT_ERRORDEF_( Invalid_Offset, 0x09, + "broken offset within table" ) +- FT_ERRORDEF_( Array_Too_Large, 0x0A, \ ++ FT_ERRORDEF_( Array_Too_Large, 0x0A, + "array allocation size too large" ) +- FT_ERRORDEF_( Missing_Module, 0x0B, \ ++ FT_ERRORDEF_( Missing_Module, 0x0B, + "missing module" ) +- FT_ERRORDEF_( Missing_Property, 0x0C, \ ++ FT_ERRORDEF_( Missing_Property, 0x0C, + "missing property" ) + + /* glyph/character errors */ + +- FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \ ++ FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, + "invalid glyph index" ) +- FT_ERRORDEF_( Invalid_Character_Code, 0x11, \ ++ FT_ERRORDEF_( Invalid_Character_Code, 0x11, + "invalid character code" ) +- FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \ ++ FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, + "unsupported glyph image format" ) +- FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \ ++ FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, + "cannot render this glyph format" ) +- FT_ERRORDEF_( Invalid_Outline, 0x14, \ ++ FT_ERRORDEF_( Invalid_Outline, 0x14, + "invalid outline" ) +- FT_ERRORDEF_( Invalid_Composite, 0x15, \ ++ FT_ERRORDEF_( Invalid_Composite, 0x15, + "invalid composite glyph" ) +- FT_ERRORDEF_( Too_Many_Hints, 0x16, \ ++ FT_ERRORDEF_( Too_Many_Hints, 0x16, + "too many hints" ) +- FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \ ++ FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, + "invalid pixel size" ) + + /* handle errors */ + +- FT_ERRORDEF_( Invalid_Handle, 0x20, \ ++ FT_ERRORDEF_( Invalid_Handle, 0x20, + "invalid object handle" ) +- FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \ ++ FT_ERRORDEF_( Invalid_Library_Handle, 0x21, + "invalid library handle" ) +- FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \ ++ FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, + "invalid module handle" ) +- FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \ ++ FT_ERRORDEF_( Invalid_Face_Handle, 0x23, + "invalid face handle" ) +- FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \ ++ FT_ERRORDEF_( Invalid_Size_Handle, 0x24, + "invalid size handle" ) +- FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \ ++ FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, + "invalid glyph slot handle" ) +- FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \ ++ FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, + "invalid charmap handle" ) +- FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \ ++ FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, + "invalid cache manager handle" ) +- FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \ ++ FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, + "invalid stream handle" ) + + /* driver errors */ + +- FT_ERRORDEF_( Too_Many_Drivers, 0x30, \ ++ FT_ERRORDEF_( Too_Many_Drivers, 0x30, + "too many modules" ) +- FT_ERRORDEF_( Too_Many_Extensions, 0x31, \ ++ FT_ERRORDEF_( Too_Many_Extensions, 0x31, + "too many extensions" ) + + /* memory errors */ + +- FT_ERRORDEF_( Out_Of_Memory, 0x40, \ ++ FT_ERRORDEF_( Out_Of_Memory, 0x40, + "out of memory" ) +- FT_ERRORDEF_( Unlisted_Object, 0x41, \ ++ FT_ERRORDEF_( Unlisted_Object, 0x41, + "unlisted object" ) + + /* stream errors */ + +- FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \ ++ FT_ERRORDEF_( Cannot_Open_Stream, 0x51, + "cannot open stream" ) +- FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \ ++ FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, + "invalid stream seek" ) +- FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \ ++ FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, + "invalid stream skip" ) +- FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \ ++ FT_ERRORDEF_( Invalid_Stream_Read, 0x54, + "invalid stream read" ) +- FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \ ++ FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, + "invalid stream operation" ) +- FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \ ++ FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, + "invalid frame operation" ) +- FT_ERRORDEF_( Nested_Frame_Access, 0x57, \ ++ FT_ERRORDEF_( Nested_Frame_Access, 0x57, + "nested frame access" ) +- FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \ ++ FT_ERRORDEF_( Invalid_Frame_Read, 0x58, + "invalid frame read" ) + + /* raster errors */ + +- FT_ERRORDEF_( Raster_Uninitialized, 0x60, \ ++ FT_ERRORDEF_( Raster_Uninitialized, 0x60, + "raster uninitialized" ) +- FT_ERRORDEF_( Raster_Corrupted, 0x61, \ ++ FT_ERRORDEF_( Raster_Corrupted, 0x61, + "raster corrupted" ) +- FT_ERRORDEF_( Raster_Overflow, 0x62, \ ++ FT_ERRORDEF_( Raster_Overflow, 0x62, + "raster overflow" ) +- FT_ERRORDEF_( Raster_Negative_Height, 0x63, \ ++ FT_ERRORDEF_( Raster_Negative_Height, 0x63, + "negative height while rastering" ) + + /* cache errors */ + +- FT_ERRORDEF_( Too_Many_Caches, 0x70, \ ++ FT_ERRORDEF_( Too_Many_Caches, 0x70, + "too many registered caches" ) + + /* TrueType and SFNT errors */ + +- FT_ERRORDEF_( Invalid_Opcode, 0x80, \ ++ FT_ERRORDEF_( Invalid_Opcode, 0x80, + "invalid opcode" ) +- FT_ERRORDEF_( Too_Few_Arguments, 0x81, \ ++ FT_ERRORDEF_( Too_Few_Arguments, 0x81, + "too few arguments" ) +- FT_ERRORDEF_( Stack_Overflow, 0x82, \ ++ FT_ERRORDEF_( Stack_Overflow, 0x82, + "stack overflow" ) +- FT_ERRORDEF_( Code_Overflow, 0x83, \ ++ FT_ERRORDEF_( Code_Overflow, 0x83, + "code overflow" ) +- FT_ERRORDEF_( Bad_Argument, 0x84, \ ++ FT_ERRORDEF_( Bad_Argument, 0x84, + "bad argument" ) +- FT_ERRORDEF_( Divide_By_Zero, 0x85, \ ++ FT_ERRORDEF_( Divide_By_Zero, 0x85, + "division by zero" ) +- FT_ERRORDEF_( Invalid_Reference, 0x86, \ ++ FT_ERRORDEF_( Invalid_Reference, 0x86, + "invalid reference" ) +- FT_ERRORDEF_( Debug_OpCode, 0x87, \ ++ FT_ERRORDEF_( Debug_OpCode, 0x87, + "found debug opcode" ) +- FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \ ++ FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, + "found ENDF opcode in execution stream" ) +- FT_ERRORDEF_( Nested_DEFS, 0x89, \ ++ FT_ERRORDEF_( Nested_DEFS, 0x89, + "nested DEFS" ) +- FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \ ++ FT_ERRORDEF_( Invalid_CodeRange, 0x8A, + "invalid code range" ) +- FT_ERRORDEF_( Execution_Too_Long, 0x8B, \ ++ FT_ERRORDEF_( Execution_Too_Long, 0x8B, + "execution context too long" ) +- FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \ ++ FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, + "too many function definitions" ) +- FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \ ++ FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, + "too many instruction definitions" ) +- FT_ERRORDEF_( Table_Missing, 0x8E, \ ++ FT_ERRORDEF_( Table_Missing, 0x8E, + "SFNT font table missing" ) +- FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \ ++ FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, + "horizontal header (hhea) table missing" ) +- FT_ERRORDEF_( Locations_Missing, 0x90, \ ++ FT_ERRORDEF_( Locations_Missing, 0x90, + "locations (loca) table missing" ) +- FT_ERRORDEF_( Name_Table_Missing, 0x91, \ ++ FT_ERRORDEF_( Name_Table_Missing, 0x91, + "name table missing" ) +- FT_ERRORDEF_( CMap_Table_Missing, 0x92, \ ++ FT_ERRORDEF_( CMap_Table_Missing, 0x92, + "character map (cmap) table missing" ) +- FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \ ++ FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, + "horizontal metrics (hmtx) table missing" ) +- FT_ERRORDEF_( Post_Table_Missing, 0x94, \ ++ FT_ERRORDEF_( Post_Table_Missing, 0x94, + "PostScript (post) table missing" ) +- FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \ ++ FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, + "invalid horizontal metrics" ) +- FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \ ++ FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, + "invalid character map (cmap) format" ) +- FT_ERRORDEF_( Invalid_PPem, 0x97, \ ++ FT_ERRORDEF_( Invalid_PPem, 0x97, + "invalid ppem value" ) +- FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \ ++ FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, + "invalid vertical metrics" ) +- FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \ ++ FT_ERRORDEF_( Could_Not_Find_Context, 0x99, + "could not find context" ) +- FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \ ++ FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, + "invalid PostScript (post) table format" ) +- FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \ ++ FT_ERRORDEF_( Invalid_Post_Table, 0x9B, + "invalid PostScript (post) table" ) + + /* CFF, CID, and Type 1 errors */ + +- FT_ERRORDEF_( Syntax_Error, 0xA0, \ ++ FT_ERRORDEF_( Syntax_Error, 0xA0, + "opcode syntax error" ) +- FT_ERRORDEF_( Stack_Underflow, 0xA1, \ ++ FT_ERRORDEF_( Stack_Underflow, 0xA1, + "argument stack underflow" ) +- FT_ERRORDEF_( Ignore, 0xA2, \ ++ FT_ERRORDEF_( Ignore, 0xA2, + "ignore" ) +- FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, \ ++ FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, + "no Unicode glyph name found" ) +- FT_ERRORDEF_( Glyph_Too_Big, 0xA4, \ ++ FT_ERRORDEF_( Glyph_Too_Big, 0xA4, + "glyph to big for hinting" ) + + /* BDF errors */ + +- FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \ ++ FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, + "`STARTFONT' field missing" ) +- FT_ERRORDEF_( Missing_Font_Field, 0xB1, \ ++ FT_ERRORDEF_( Missing_Font_Field, 0xB1, + "`FONT' field missing" ) +- FT_ERRORDEF_( Missing_Size_Field, 0xB2, \ ++ FT_ERRORDEF_( Missing_Size_Field, 0xB2, + "`SIZE' field missing" ) +- FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3, \ ++ FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3, + "`FONTBOUNDINGBOX' field missing" ) +- FT_ERRORDEF_( Missing_Chars_Field, 0xB4, \ ++ FT_ERRORDEF_( Missing_Chars_Field, 0xB4, + "`CHARS' field missing" ) +- FT_ERRORDEF_( Missing_Startchar_Field, 0xB5, \ ++ FT_ERRORDEF_( Missing_Startchar_Field, 0xB5, + "`STARTCHAR' field missing" ) +- FT_ERRORDEF_( Missing_Encoding_Field, 0xB6, \ ++ FT_ERRORDEF_( Missing_Encoding_Field, 0xB6, + "`ENCODING' field missing" ) +- FT_ERRORDEF_( Missing_Bbx_Field, 0xB7, \ ++ FT_ERRORDEF_( Missing_Bbx_Field, 0xB7, + "`BBX' field missing" ) +- FT_ERRORDEF_( Bbx_Too_Big, 0xB8, \ ++ FT_ERRORDEF_( Bbx_Too_Big, 0xB8, + "`BBX' too big" ) +- FT_ERRORDEF_( Corrupted_Font_Header, 0xB9, \ ++ FT_ERRORDEF_( Corrupted_Font_Header, 0xB9, + "Font header corrupted or missing fields" ) +- FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA, \ ++ FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA, + "Font glyphs corrupted or missing fields" ) + + +diff --git a/include/fttrigon.h b/include/fttrigon.h +index 65143cb..9c7b543 100644 +--- a/include/fttrigon.h ++++ b/include/fttrigon.h +@@ -237,7 +237,7 @@ FT_BEGIN_HEADER + * + * @input: + * angle :: +- * The address of angle. ++ * The input angle. + * + */ + FT_EXPORT( void ) +@@ -259,7 +259,7 @@ FT_BEGIN_HEADER + * + * @input: + * angle :: +- * The address of angle. ++ * The input angle. + * + */ + FT_EXPORT( void ) +diff --git a/include/internal/ftcalc.h b/include/internal/ftcalc.h +index 03bd68e..95165bf 100644 +--- a/include/internal/ftcalc.h ++++ b/include/internal/ftcalc.h +@@ -4,7 +4,7 @@ + /* */ + /* Arithmetic computations (specification). */ + /* */ +-/* Copyright 1996-2006, 2008, 2009, 2012-2013 by */ ++/* Copyright 1996-2006, 2008, 2009, 2012-2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -27,36 +27,223 @@ + FT_BEGIN_HEADER + + +-#if 0 +- + /*************************************************************************/ + /* */ +- /* <Function> */ +- /* FT_SqrtFixed */ +- /* */ +- /* <Description> */ +- /* Computes the square root of a 16.16 fixed-point value. */ +- /* */ +- /* <Input> */ +- /* x :: The value to compute the root for. */ +- /* */ +- /* <Return> */ +- /* The result of `sqrt(x)'. */ +- /* */ +- /* <Note> */ +- /* This function is not very fast. */ ++ /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */ + /* */ +- FT_BASE( FT_Int32 ) +- FT_SqrtFixed( FT_Int32 x ); ++ /*************************************************************************/ + +-#endif /* 0 */ ++#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER ++ /* Provide assembler fragments for performance-critical functions. */ ++ /* These must be defined `static __inline__' with GCC. */ + ++#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */ + +- /*************************************************************************/ +- /* */ +- /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */ +- /* */ +- /*************************************************************************/ ++#define FT_MULFIX_ASSEMBLER FT_MulFix_arm ++ ++ /* documentation is in freetype.h */ ++ ++ static __inline FT_Int32 ++ FT_MulFix_arm( FT_Int32 a, ++ FT_Int32 b ) ++ { ++ register FT_Int32 t, t2; ++ ++ ++ __asm ++ { ++ smull t2, t, b, a /* (lo=t2,hi=t) = a*b */ ++ mov a, t, asr #31 /* a = (hi >> 31) */ ++ add a, a, #0x8000 /* a += 0x8000 */ ++ adds t2, t2, a /* t2 += a */ ++ adc t, t, #0 /* t += carry */ ++ mov a, t2, lsr #16 /* a = t2 >> 16 */ ++ orr a, a, t, lsl #16 /* a |= t << 16 */ ++ } ++ return a; ++ } ++ ++#endif /* __CC_ARM || __ARMCC__ */ ++ ++ ++#ifdef __GNUC__ ++ ++#if defined( __arm__ ) && \ ++ ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \ ++ !( defined( __CC_ARM ) || defined( __ARMCC__ ) ) ++ ++#define FT_MULFIX_ASSEMBLER FT_MulFix_arm ++ ++ /* documentation is in freetype.h */ ++ ++ static __inline__ FT_Int32 ++ FT_MulFix_arm( FT_Int32 a, ++ FT_Int32 b ) ++ { ++ register FT_Int32 t, t2; ++ ++ ++ __asm__ __volatile__ ( ++ "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */ ++ "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */ ++#if defined( __clang__ ) && defined( __thumb2__ ) ++ "add.w %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ ++#else ++ "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ ++#endif ++ "adds %1, %1, %0\n\t" /* %1 += %0 */ ++ "adc %2, %2, #0\n\t" /* %2 += carry */ ++ "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */ ++ "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */ ++ : "=r"(a), "=&r"(t2), "=&r"(t) ++ : "r"(a), "r"(b) ++ : "cc" ); ++ return a; ++ } ++ ++#endif /* __arm__ && */ ++ /* ( __thumb2__ || !__thumb__ ) && */ ++ /* !( __CC_ARM || __ARMCC__ ) */ ++ ++ ++#if defined( __i386__ ) ++ ++#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 ++ ++ /* documentation is in freetype.h */ ++ ++ static __inline__ FT_Int32 ++ FT_MulFix_i386( FT_Int32 a, ++ FT_Int32 b ) ++ { ++ register FT_Int32 result; ++ ++ ++ __asm__ __volatile__ ( ++ "imul %%edx\n" ++ "movl %%edx, %%ecx\n" ++ "sarl $31, %%ecx\n" ++ "addl $0x8000, %%ecx\n" ++ "addl %%ecx, %%eax\n" ++ "adcl $0, %%edx\n" ++ "shrl $16, %%eax\n" ++ "shll $16, %%edx\n" ++ "addl %%edx, %%eax\n" ++ : "=a"(result), "=d"(b) ++ : "a"(a), "d"(b) ++ : "%ecx", "cc" ); ++ return result; ++ } ++ ++#endif /* i386 */ ++ ++#endif /* __GNUC__ */ ++ ++ ++#ifdef _MSC_VER /* Visual C++ */ ++ ++#ifdef _M_IX86 ++ ++#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 ++ ++ /* documentation is in freetype.h */ ++ ++ static __inline FT_Int32 ++ FT_MulFix_i386( FT_Int32 a, ++ FT_Int32 b ) ++ { ++ register FT_Int32 result; ++ ++ __asm ++ { ++ mov eax, a ++ mov edx, b ++ imul edx ++ mov ecx, edx ++ sar ecx, 31 ++ add ecx, 8000h ++ add eax, ecx ++ adc edx, 0 ++ shr eax, 16 ++ shl edx, 16 ++ add eax, edx ++ mov result, eax ++ } ++ return result; ++ } ++ ++#endif /* _M_IX86 */ ++ ++#endif /* _MSC_VER */ ++ ++ ++#if defined( __GNUC__ ) && defined( __x86_64__ ) ++ ++#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64 ++ ++ static __inline__ FT_Int32 ++ FT_MulFix_x86_64( FT_Int32 a, ++ FT_Int32 b ) ++ { ++ /* Temporarily disable the warning that C90 doesn't support */ ++ /* `long long'. */ ++#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) ) ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wlong-long" ++#endif ++ ++#if 1 ++ /* Technically not an assembly fragment, but GCC does a really good */ ++ /* job at inlining it and generating good machine code for it. */ ++ long long ret, tmp; ++ ++ ++ ret = (long long)a * b; ++ tmp = ret >> 63; ++ ret += 0x8000 + tmp; ++ ++ return (FT_Int32)( ret >> 16 ); ++#else ++ ++ /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */ ++ /* code from the lines below. The main issue is that `wide_a' is not */ ++ /* properly initialized by sign-extending `a'. Instead, the generated */ ++ /* machine code assumes that the register that contains `a' on input */ ++ /* can be used directly as a 64-bit value, which is wrong most of the */ ++ /* time. */ ++ long long wide_a = (long long)a; ++ long long wide_b = (long long)b; ++ long long result; ++ ++ ++ __asm__ __volatile__ ( ++ "imul %2, %1\n" ++ "mov %1, %0\n" ++ "sar $63, %0\n" ++ "lea 0x8000(%1, %0), %0\n" ++ "sar $16, %0\n" ++ : "=&r"(result), "=&r"(wide_a) ++ : "r"(wide_b) ++ : "cc" ); ++ ++ return (FT_Int32)result; ++#endif ++ ++#if ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 6 ) ) ++#pragma GCC diagnostic pop ++#endif ++ } ++ ++#endif /* __GNUC__ && __x86_64__ */ ++ ++#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ ++ ++ ++#ifdef FT_CONFIG_OPTION_INLINE_MULFIX ++#ifdef FT_MULFIX_ASSEMBLER ++#define FT_MulFix( a, b ) FT_MULFIX_ASSEMBLER( a, b ) ++#endif ++#endif + + + /*************************************************************************/ +@@ -139,9 +326,32 @@ FT_BEGIN_HEADER + /* + * Return the most significant bit index. + */ ++ ++#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER ++#if defined( __GNUC__ ) ++#if ( __GNUC__ > 3 ) || ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 4 ) ) ++ ++#if FT_SIZEOF_INT == 4 ++ ++#define FT_MSB( x ) ( 31 - __builtin_clz( x ) ) ++ ++#elif FT_SIZEOF_LONG == 4 ++ ++#define FT_MSB( x ) ( 31 - __builtin_clzl( x ) ) ++ ++#endif ++ ++#endif ++#endif /* __GNUC__ */ ++#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ ++ ++#ifndef FT_MSB ++ + FT_BASE( FT_Int ) + FT_MSB( FT_UInt32 z ); + ++#endif ++ + + /* + * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses +@@ -152,6 +362,31 @@ FT_BEGIN_HEADER + FT_Fixed y ); + + ++#if 0 ++ ++ /*************************************************************************/ ++ /* */ ++ /* <Function> */ ++ /* FT_SqrtFixed */ ++ /* */ ++ /* <Description> */ ++ /* Computes the square root of a 16.16 fixed-point value. */ ++ /* */ ++ /* <Input> */ ++ /* x :: The value to compute the root for. */ ++ /* */ ++ /* <Return> */ ++ /* The result of `sqrt(x)'. */ ++ /* */ ++ /* <Note> */ ++ /* This function is not very fast. */ ++ /* */ ++ FT_BASE( FT_Int32 ) ++ FT_SqrtFixed( FT_Int32 x ); ++ ++#endif /* 0 */ ++ ++ + #define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 ) + #define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 ) + #define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 ) +diff --git a/include/internal/ftobjs.h b/include/internal/ftobjs.h +index 701c850..faa37f8 100644 +--- a/include/internal/ftobjs.h ++++ b/include/internal/ftobjs.h +@@ -83,14 +83,6 @@ FT_BEGIN_HEADER + + + /* +- * Return the highest power of 2 that is <= value; this correspond to +- * the highest bit in a given 32-bit value. +- */ +- FT_BASE( FT_UInt32 ) +- ft_highpow2( FT_UInt32 value ); +- +- +- /* + * character classification functions -- since these are used to parse + * font files, we must not use those in <ctypes.h> which are + * locale-dependent +diff --git a/src/autofit/afblue.c b/src/autofit/afblue.c +index 6e214c8..f3526bf 100644 +--- a/src/autofit/afblue.c ++++ b/src/autofit/afblue.c +@@ -26,15 +26,21 @@ + af_blue_strings[] = + { + /* */ +- 'T', 'H', 'E', 'Z', 'O', 'C', 'Q', 'S', /* THEZOCQS */ ++ '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\x9F', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕПЗОСЭ */ + '\0', +- 'H', 'E', 'Z', 'L', 'O', 'C', 'U', 'S', /* HEZLOCUS */ ++ '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\xA8', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕШЗОСЭ */ + '\0', +- 'f', 'i', 'j', 'k', 'd', 'b', 'h', /* fijkdbh */ ++ '\xD1', '\x85', '\xD0', '\xBF', '\xD0', '\xBD', '\xD1', '\x88', '\xD0', '\xB5', '\xD0', '\xB7', '\xD0', '\xBE', '\xD1', '\x81', /* хпншезос */ + '\0', +- 'x', 'z', 'r', 'o', 'e', 's', 'c', /* xzroesc */ ++ '\xD1', '\x80', '\xD1', '\x83', '\xD1', '\x84', /* руф */ + '\0', +- 'p', 'q', 'g', 'j', 'y', /* pqgjy */ ++ '\xE0', '\xA4', '\x95', '\xE0', '\xA4', '\xAE', '\xE0', '\xA4', '\x85', '\xE0', '\xA4', '\x86', '\xE0', '\xA4', '\xA5', '\xE0', '\xA4', '\xA7', '\xE0', '\xA4', '\xAD', '\xE0', '\xA4', '\xB6', /* क म अ आ थ ध भ श */ ++ '\0', ++ '\xE0', '\xA4', '\x88', '\xE0', '\xA4', '\x90', '\xE0', '\xA4', '\x93', '\xE0', '\xA4', '\x94', '\xE0', '\xA4', '\xBF', '\xE0', '\xA5', '\x80', '\xE0', '\xA5', '\x8B', '\xE0', '\xA5', '\x8C', /* ई ऐ ओ औ ि ी ो ौ */ ++ '\0', ++ '\xE0', '\xA4', '\x95', '\xE0', '\xA4', '\xAE', '\xE0', '\xA4', '\x85', '\xE0', '\xA4', '\x86', '\xE0', '\xA4', '\xA5', '\xE0', '\xA4', '\xA7', '\xE0', '\xA4', '\xAD', '\xE0', '\xA4', '\xB6', /* क म अ आ थ ध भ श */ ++ '\0', ++ '\xE0', '\xA5', '\x81', '\xE0', '\xA5', '\x83', /* ु ृ */ + '\0', + '\xCE', '\x93', '\xCE', '\x92', '\xCE', '\x95', '\xCE', '\x96', '\xCE', '\x98', '\xCE', '\x9F', '\xCE', '\xA9', /* ΓΒΕΖΘΟΩ */ + '\0', +@@ -46,26 +52,27 @@ + '\0', + '\xCE', '\xB2', '\xCE', '\xB3', '\xCE', '\xB7', '\xCE', '\xBC', '\xCF', '\x81', '\xCF', '\x86', '\xCF', '\x87', '\xCF', '\x88', /* βγημρφχψ */ + '\0', +- '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\x9F', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕПЗОСЭ */ ++ '\xD7', '\x91', '\xD7', '\x93', '\xD7', '\x94', '\xD7', '\x97', '\xD7', '\x9A', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', /* בדהחךכםס */ + '\0', +- '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\xA8', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕШЗОСЭ */ ++ '\xD7', '\x91', '\xD7', '\x98', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', '\xD7', '\xA6', /* בטכםסצ */ + '\0', +- '\xD1', '\x85', '\xD0', '\xBF', '\xD0', '\xBD', '\xD1', '\x88', '\xD0', '\xB5', '\xD0', '\xB7', '\xD0', '\xBE', '\xD1', '\x81', /* хпншезос */ ++ '\xD7', '\xA7', '\xD7', '\x9A', '\xD7', '\x9F', '\xD7', '\xA3', '\xD7', '\xA5', /* קךןףץ */ + '\0', +- '\xD1', '\x80', '\xD1', '\x83', '\xD1', '\x84', /* руф */ ++ 'T', 'H', 'E', 'Z', 'O', 'C', 'Q', 'S', /* THEZOCQS */ + '\0', +- '\xD7', '\x91', '\xD7', '\x93', '\xD7', '\x94', '\xD7', '\x97', '\xD7', '\x9A', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', /* בדהחךכםס */ ++ 'H', 'E', 'Z', 'L', 'O', 'C', 'U', 'S', /* HEZLOCUS */ + '\0', +- '\xD7', '\x91', '\xD7', '\x98', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', '\xD7', '\xA6', /* בטכםסצ */ ++ 'f', 'i', 'j', 'k', 'd', 'b', 'h', /* fijkdbh */ + '\0', +- '\xD7', '\xA7', '\xD7', '\x9A', '\xD7', '\x9F', '\xD7', '\xA3', '\xD7', '\xA5', /* קךןףץ */ ++ 'x', 'z', 'r', 'o', 'e', 's', 'c', /* xzroesc */ ++ '\0', ++ 'p', 'q', 'g', 'j', 'y', /* pqgjy */ + #ifdef AF_CONFIG_OPTION_CJK + '\0', + '\xE4', '\xBB', '\x96', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\x9C', '\xB0', /* 他们你來們到和地 */ + '\xE5', '\xAF', '\xB9', '\xE5', '\xB0', '\x8D', '\xE5', '\xB0', '\xB1', '\xE5', '\xB8', '\xAD', '\xE6', '\x88', '\x91', '\xE6', '\x97', '\xB6', '\xE6', '\x99', '\x82', '\xE6', '\x9C', '\x83', /* 对對就席我时時會 */ + '\xE6', '\x9D', '\xA5', '\xE7', '\x82', '\xBA', '\xE8', '\x83', '\xBD', '\xE8', '\x88', '\xB0', '\xE8', '\xAA', '\xAA', '\xE8', '\xAF', '\xB4', '\xE8', '\xBF', '\x99', '\xE9', '\x80', '\x99', /* 来為能舰說说这這 */ +- '\xE9', '\xBD', '\x8A', /* 齊 */ +- '\0', ++ '\xE9', '\xBD', '\x8A', '|', /* 齊 | */ + '\xE5', '\x86', '\x9B', '\xE5', '\x90', '\x8C', '\xE5', '\xB7', '\xB2', '\xE6', '\x84', '\xBF', '\xE6', '\x97', '\xA2', '\xE6', '\x98', '\x9F', '\xE6', '\x98', '\xAF', '\xE6', '\x99', '\xAF', /* 军同已愿既星是景 */ + '\xE6', '\xB0', '\x91', '\xE7', '\x85', '\xA7', '\xE7', '\x8E', '\xB0', '\xE7', '\x8F', '\xBE', '\xE7', '\x90', '\x86', '\xE7', '\x94', '\xA8', '\xE7', '\xBD', '\xAE', '\xE8', '\xA6', '\x81', /* 民照现現理用置要 */ + '\xE8', '\xBB', '\x8D', '\xE9', '\x82', '\xA3', '\xE9', '\x85', '\x8D', '\xE9', '\x87', '\x8C', '\xE9', '\x96', '\x8B', '\xE9', '\x9B', '\xB7', '\xE9', '\x9C', '\xB2', '\xE9', '\x9D', '\xA2', /* 軍那配里開雷露面 */ +@@ -74,8 +81,7 @@ + '\xE4', '\xB8', '\xAA', '\xE4', '\xB8', '\xBA', '\xE4', '\xBA', '\xBA', '\xE4', '\xBB', '\x96', '\xE4', '\xBB', '\xA5', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', /* 个为人他以们你來 */ + '\xE5', '\x80', '\x8B', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\xA4', '\xA7', '\xE5', '\xAF', '\xB9', '\xE5', '\xB0', '\x8D', '\xE5', '\xB0', '\xB1', /* 個們到和大对對就 */ + '\xE6', '\x88', '\x91', '\xE6', '\x97', '\xB6', '\xE6', '\x99', '\x82', '\xE6', '\x9C', '\x89', '\xE6', '\x9D', '\xA5', '\xE7', '\x82', '\xBA', '\xE8', '\xA6', '\x81', '\xE8', '\xAA', '\xAA', /* 我时時有来為要說 */ +- '\xE8', '\xAF', '\xB4', /* 说 */ +- '\0', ++ '\xE8', '\xAF', '\xB4', '|', /* 说 | */ + '\xE4', '\xB8', '\xBB', '\xE4', '\xBA', '\x9B', '\xE5', '\x9B', '\xA0', '\xE5', '\xAE', '\x83', '\xE6', '\x83', '\xB3', '\xE6', '\x84', '\x8F', '\xE7', '\x90', '\x86', '\xE7', '\x94', '\x9F', /* 主些因它想意理生 */ + '\xE7', '\x95', '\xB6', '\xE7', '\x9C', '\x8B', '\xE7', '\x9D', '\x80', '\xE7', '\xBD', '\xAE', '\xE8', '\x80', '\x85', '\xE8', '\x87', '\xAA', '\xE8', '\x91', '\x97', '\xE8', '\xA3', '\xA1', /* 當看着置者自著裡 */ + '\xE8', '\xBF', '\x87', '\xE8', '\xBF', '\x98', '\xE8', '\xBF', '\x9B', '\xE9', '\x80', '\xB2', '\xE9', '\x81', '\x8E', '\xE9', '\x81', '\x93', '\xE9', '\x82', '\x84', '\xE9', '\x87', '\x8C', /* 过还进進過道還里 */ +@@ -85,8 +91,7 @@ + '\xE4', '\xBA', '\x9B', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\x9C', '\xB0', /* 些们你來們到和地 */ + '\xE5', '\xA5', '\xB9', '\xE5', '\xB0', '\x86', '\xE5', '\xB0', '\x87', '\xE5', '\xB0', '\xB1', '\xE5', '\xB9', '\xB4', '\xE5', '\xBE', '\x97', '\xE6', '\x83', '\x85', '\xE6', '\x9C', '\x80', /* 她将將就年得情最 */ + '\xE6', '\xA0', '\xB7', '\xE6', '\xA8', '\xA3', '\xE7', '\x90', '\x86', '\xE8', '\x83', '\xBD', '\xE8', '\xAA', '\xAA', '\xE8', '\xAF', '\xB4', '\xE8', '\xBF', '\x99', '\xE9', '\x80', '\x99', /* 样樣理能說说这這 */ +- '\xE9', '\x80', '\x9A', /* 通 */ +- '\0', ++ '\xE9', '\x80', '\x9A', '|', /* 通 | */ + '\xE5', '\x8D', '\xB3', '\xE5', '\x90', '\x97', '\xE5', '\x90', '\xA7', '\xE5', '\x90', '\xAC', '\xE5', '\x91', '\xA2', '\xE5', '\x93', '\x81', '\xE5', '\x93', '\x8D', '\xE5', '\x97', '\x8E', /* 即吗吧听呢品响嗎 */ + '\xE5', '\xB8', '\x88', '\xE5', '\xB8', '\xAB', '\xE6', '\x94', '\xB6', '\xE6', '\x96', '\xAD', '\xE6', '\x96', '\xB7', '\xE6', '\x98', '\x8E', '\xE7', '\x9C', '\xBC', '\xE9', '\x96', '\x93', /* 师師收断斷明眼間 */ + '\xE9', '\x97', '\xB4', '\xE9', '\x99', '\x85', '\xE9', '\x99', '\x88', '\xE9', '\x99', '\x90', '\xE9', '\x99', '\xA4', '\xE9', '\x99', '\xB3', '\xE9', '\x9A', '\x8F', '\xE9', '\x9A', '\x9B', /* 间际陈限除陳随際 */ +@@ -95,8 +100,7 @@ + '\xE4', '\xBA', '\x8B', '\xE5', '\x89', '\x8D', '\xE5', '\xAD', '\xB8', '\xE5', '\xB0', '\x86', '\xE5', '\xB0', '\x87', '\xE6', '\x83', '\x85', '\xE6', '\x83', '\xB3', '\xE6', '\x88', '\x96', /* 事前學将將情想或 */ + '\xE6', '\x94', '\xBF', '\xE6', '\x96', '\xAF', '\xE6', '\x96', '\xB0', '\xE6', '\xA0', '\xB7', '\xE6', '\xA8', '\xA3', '\xE6', '\xB0', '\x91', '\xE6', '\xB2', '\x92', '\xE6', '\xB2', '\xA1', /* 政斯新样樣民沒没 */ + '\xE7', '\x84', '\xB6', '\xE7', '\x89', '\xB9', '\xE7', '\x8E', '\xB0', '\xE7', '\x8F', '\xBE', '\xE7', '\x90', '\x83', '\xE7', '\xAC', '\xAC', '\xE7', '\xB6', '\x93', '\xE8', '\xB0', '\x81', /* 然特现現球第經谁 */ +- '\xE8', '\xB5', '\xB7', /* 起 */ +- '\0', ++ '\xE8', '\xB5', '\xB7', '|', /* 起 | */ + '\xE4', '\xBE', '\x8B', '\xE5', '\x88', '\xA5', '\xE5', '\x88', '\xAB', '\xE5', '\x88', '\xB6', '\xE5', '\x8A', '\xA8', '\xE5', '\x8B', '\x95', '\xE5', '\x90', '\x97', '\xE5', '\x97', '\x8E', /* 例別别制动動吗嗎 */ + '\xE5', '\xA2', '\x9E', '\xE6', '\x8C', '\x87', '\xE6', '\x98', '\x8E', '\xE6', '\x9C', '\x9D', '\xE6', '\x9C', '\x9F', '\xE6', '\x9E', '\x84', '\xE7', '\x89', '\xA9', '\xE7', '\xA1', '\xAE', /* 增指明朝期构物确 */ + '\xE7', '\xA7', '\x8D', '\xE8', '\xAA', '\xBF', '\xE8', '\xB0', '\x83', '\xE8', '\xB2', '\xBB', '\xE8', '\xB4', '\xB9', '\xE9', '\x82', '\xA3', '\xE9', '\x83', '\xBD', '\xE9', '\x96', '\x93', /* 种調调費费那都間 */ +@@ -113,14 +117,21 @@ + af_blue_stringsets[] = + { + /* */ +- { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, +- { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 }, +- { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, +- { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | +- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, +- { AF_BLUE_STRING_LATIN_SMALL, 0 }, +- { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }, +- { AF_BLUE_STRING_MAX, 0 }, ++ { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, ++ { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 }, ++ { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | ++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, ++ { AF_BLUE_STRING_CYRILLIC_SMALL, 0 }, ++ { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 }, ++ { AF_BLUE_STRING_MAX, 0 }, ++ { AF_BLUE_STRING_DEVANAGARI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, ++ { AF_BLUE_STRING_DEVANAGARI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP }, ++ { AF_BLUE_STRING_DEVANAGARI_BASE, AF_BLUE_PROPERTY_LATIN_TOP | ++ AF_BLUE_PROPERTY_LATIN_NEUTRAL | ++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, ++ { AF_BLUE_STRING_DEVANAGARI_BASE, 0 }, ++ { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 }, ++ { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, +@@ -129,35 +140,28 @@ + { AF_BLUE_STRING_GREEK_SMALL, 0 }, + { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, +- { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, +- { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 }, +- { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | +- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, +- { AF_BLUE_STRING_CYRILLIC_SMALL, 0 }, +- { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 }, +- { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_HEBREW_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_LONG }, + { AF_BLUE_STRING_HEBREW_BOTTOM, 0 }, + { AF_BLUE_STRING_HEBREW_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, ++ { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, ++ { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 }, ++ { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, ++ { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | ++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, ++ { AF_BLUE_STRING_LATIN_SMALL, 0 }, ++ { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }, ++ { AF_BLUE_STRING_MAX, 0 }, + #ifdef AF_CONFIG_OPTION_CJK +- { AF_BLUE_STRING_CJK_TOP_FILL, AF_BLUE_PROPERTY_CJK_TOP | +- AF_BLUE_PROPERTY_CJK_FILL }, +- { AF_BLUE_STRING_CJK_TOP_UNFILL, AF_BLUE_PROPERTY_CJK_TOP }, +- { AF_BLUE_STRING_CJK_BOTTOM_FILL, AF_BLUE_PROPERTY_CJK_FILL }, +- { AF_BLUE_STRING_CJK_BOTTOM_UNFILL, 0 }, ++ { AF_BLUE_STRING_CJK_TOP, AF_BLUE_PROPERTY_CJK_TOP }, ++ { AF_BLUE_STRING_CJK_BOTTOM, 0 }, + #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT +- { AF_BLUE_STRING_CJK_LEFT_FILL, AF_BLUE_PROPERTY_CJK_HORIZ | +- AF_BLUE_PROPERTY_CJK_FILL }, +- { AF_BLUE_STRING_CJK_LEFT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ }, +- { AF_BLUE_STRING_CJK_RIGHT_FILL, AF_BLUE_PROPERTY_CJK_HORIZ | +- AF_BLUE_PROPERTY_CJK_RIGHT | +- AF_BLUE_PROPERTY_CJK_FILL }, +- { AF_BLUE_STRING_CJK_RIGHT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ | +- AF_BLUE_PROPERTY_CJK_RIGHT }, ++ { AF_BLUE_STRING_CJK_LEFT, AF_BLUE_PROPERTY_CJK_HORIZ }, ++ { AF_BLUE_STRING_CJK_RIGHT, AF_BLUE_PROPERTY_CJK_HORIZ | ++ AF_BLUE_PROPERTY_CJK_RIGHT }, + #endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */ +- { AF_BLUE_STRING_MAX, 0 }, ++ { AF_BLUE_STRING_MAX, 0 }, + #endif /* AF_CONFIG_OPTION_CJK */ + + }; +diff --git a/src/autofit/afblue.dat b/src/autofit/afblue.dat +index d488f3f..74a472d 100644 +--- a/src/autofit/afblue.dat ++++ b/src/autofit/afblue.dat +@@ -2,7 +2,7 @@ + // + // Auto-fitter data for blue strings. + // +-// Copyright 2013 by ++// Copyright 2013, 2014 by + // David Turner, Robert Wilhelm, and Werner Lemberg. + // + // This file is part of the FreeType project, and may only be used, +@@ -34,11 +34,11 @@ + // using C syntax. There can be only one string per line, thus the + // starting and ending double quote must be the first and last character + // in the line, respectively, ignoring whitespace before and after the +-// string. If there are multiple strings (in multiple lines), they are +-// concatenated to a single string. In the output, a string gets +-// represented as a series of singles bytes, followed by a zero byte. The +-// enumeration values simply hold byte offsets to the start of the +-// corresponding strings. ++// string. Space characters within the string are ignored too. If there ++// are multiple strings (in multiple lines), they are concatenated to a ++// single string. In the output, a string gets represented as a series of ++// singles bytes, followed by a zero byte. The enumeration values simply ++// hold byte offsets to the start of the corresponding strings. + // + // - Data blocks enclosed in balanced braces, which get copied verbatim and + // which can span multiple lines. The opening brace of a block must be +@@ -63,18 +63,32 @@ + // characters, not bytes. + + ++// The blue zone string data, to be used in the blue stringsets below. ++ + AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: + +- AF_BLUE_STRING_LATIN_CAPITAL_TOP +- "THEZOCQS" +- AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM +- "HEZLOCUS" +- AF_BLUE_STRING_LATIN_SMALL_F_TOP +- "fijkdbh" +- AF_BLUE_STRING_LATIN_SMALL +- "xzroesc" +- AF_BLUE_STRING_LATIN_SMALL_DESCENDER +- "pqgjy" ++ AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP ++ "БВЕПЗОСЭ" ++ AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM ++ "БВЕШЗОСЭ" ++ AF_BLUE_STRING_CYRILLIC_SMALL ++ "хпншезос" ++ AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER ++ "руф" ++ ++ // we separate the letters with spaces to avoid ligatures; ++ // this is just for convenience to simplify reading ++ AF_BLUE_STRING_DEVANAGARI_BASE ++ "क म अ आ थ ध भ श" ++ AF_BLUE_STRING_DEVANAGARI_TOP ++ "ई ऐ ओ औ ि ी ो ौ" ++ // note that some fonts have extreme variation in the height of the ++ // round head elements; for this reason we also define the `base' ++ // blue zone, which must be always present ++ AF_BLUE_STRING_DEVANAGARI_HEAD ++ "क म अ आ थ ध भ श" ++ AF_BLUE_STRING_DEVANAGARI_BOTTOM ++ "ु ृ" + + AF_BLUE_STRING_GREEK_CAPITAL_TOP + "ΓΒΕΖΘΟΩ" +@@ -87,15 +101,6 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: + AF_BLUE_STRING_GREEK_SMALL_DESCENDER + "βγημρφχψ" + +- AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP +- "БВЕПЗОСЭ" +- AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM +- "БВЕШЗОСЭ" +- AF_BLUE_STRING_CYRILLIC_SMALL +- "хпншезос" +- AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER +- "руф" +- + AF_BLUE_STRING_HEBREW_TOP + "בדהחךכםס" + AF_BLUE_STRING_HEBREW_BOTTOM +@@ -103,24 +108,33 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: + AF_BLUE_STRING_HEBREW_DESCENDER + "קךןףץ" + ++ AF_BLUE_STRING_LATIN_CAPITAL_TOP ++ "THEZOCQS" ++ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM ++ "HEZLOCUS" ++ AF_BLUE_STRING_LATIN_SMALL_F_TOP ++ "fijkdbh" ++ AF_BLUE_STRING_LATIN_SMALL ++ "xzroesc" ++ AF_BLUE_STRING_LATIN_SMALL_DESCENDER ++ "pqgjy" ++ + #ifdef AF_CONFIG_OPTION_CJK + +- AF_BLUE_STRING_CJK_TOP_FILL ++ AF_BLUE_STRING_CJK_TOP + "他们你來們到和地" + "对對就席我时時會" + "来為能舰說说这這" +- "齊" +- AF_BLUE_STRING_CJK_TOP_UNFILL ++ "齊 |" + "军同已愿既星是景" + "民照现現理用置要" + "軍那配里開雷露面" + "顾" +- AF_BLUE_STRING_CJK_BOTTOM_FILL ++ AF_BLUE_STRING_CJK_BOTTOM + "个为人他以们你來" + "個們到和大对對就" + "我时時有来為要說" +- "说" +- AF_BLUE_STRING_CJK_BOTTOM_UNFILL ++ "说 |" + "主些因它想意理生" + "當看着置者自著裡" + "过还进進過道還里" +@@ -128,22 +142,20 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: + + #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT + +- AF_BLUE_STRING_CJK_LEFT_FILL ++ AF_BLUE_STRING_CJK_LEFT + "些们你來們到和地" + "她将將就年得情最" + "样樣理能說说这這" +- "通" +- AF_BLUE_STRING_CJK_LEFT_UNFILL ++ "通 |" + "即吗吧听呢品响嗎" + "师師收断斷明眼間" + "间际陈限除陳随際" + "隨" +- AF_BLUE_STRING_CJK_RIGHT_FILL ++ AF_BLUE_STRING_CJK_RIGHT + "事前學将將情想或" + "政斯新样樣民沒没" + "然特现現球第經谁" +- "起" +- AF_BLUE_STRING_CJK_RIGHT_UNFILL ++ "起 |" + "例別别制动動吗嗎" + "增指明朝期构物确" + "种調调費费那都間" +@@ -154,17 +166,118 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: + #endif /* AF_CONFIG_OPTION_CJK */ + + ++// The blue zone stringsets, as used in the script styles, cf. `afstyles.h'. ++// ++// The AF_BLUE_PROPERTY_XXX flags are defined in `afblue.h'; here some ++// explanations. ++// ++// A blue zone in general is defined by a reference and an overshoot line. ++// During the hinting process, all coordinate values between those two lines ++// are set equal to the reference value, provided that the blue zone is not ++// wider than 0.75 pixels (otherwise the blue zone gets ignored). All ++// entries must have `AF_BLUE_STRING_MAX' as the final line. ++// ++// During the glyph analysis, edges are sorted from bottom to top, and then ++// sequentially checked, edge by edge, against the blue zones in the order ++// given below. ++// ++// ++// latin auto-hinter ++// ----------------- ++// ++// Characters in a blue string are automatically classified as having a flat ++// (reference) or a round (overshoot) extremum. The blue zone is then set ++// up by the mean values of all flat extrema and all round extrema, ++// respectively. Only horizontal blue zones (i.e., adjusting vertical ++// coordinate values) are supported. ++// ++// For the latin auto-hinter, the overshoot should be larger than the ++// reference for top zones, and vice versa for bottom zones. ++// ++// LATIN_TOP ++// Take the maximum flat and round coordinate values of the blue string ++// characters for computing the blue zone's reference and overshoot ++// values. ++// ++// If not set, take the minimum values. ++// ++// LATIN_NEUTRAL ++// Ignore round extrema and define the blue zone with flat values only. ++// Both top and bottom of contours can match. This is useful for ++// scripts like Devanagari where vowel signs attach to the base ++// character and are implemented as components of composite glyphs. ++// ++// If not set, both round and flat extrema are taken into account. ++// Additionally, only the top or the bottom of a contour can match, ++// depending on the LATIN_TOP flag. ++// ++// Neutral blue zones should always follow non-neutral blue zones. ++// ++// LATIN_X_HEIGHT ++// Scale all glyphs vertically from the corresponding script to make the ++// reference line of this blue zone align on the grid. The scaling ++// takes place before all other blue zones get aligned to the grid. ++// Only one blue character string of a script style can have this flag. ++// ++// LATIN_LONG ++// Apply an additional constraint for blue zone values: Don't ++// necessarily use the extremum as-is but a segment of the topmost (or ++// bottommost) contour that is longer than a heuristic threshold, and ++// which is not too far away vertically from the real extremum. This ++// ensures that small bumps in the outline are ignored (for example, the ++// `vertical serifs' found in many Hebrew glyph designs). ++// ++// The segment must be at least EM/25 font units long, and the distance ++// to the extremum must be smaller than EM/4. ++// ++// ++// cjk auto-hinter ++// --------------- ++// ++// Characters in a blue string are *not* automatically classified. Instead, ++// first come the characters used for the overshoot value, then the ++// character `|', then the characters used for the reference value. The ++// blue zone is then set up by the mean values of all reference values and ++// all overshoot values, respectively. Both horizontal and vertical blue ++// zones (i.e., adjusting vertical and horizontal coordinate values, ++// respectively) are supported. ++// ++// For the cjk auto-hinter, the overshoot should be smaller than the ++// reference for top zones, and vice versa for bottom zones. ++// ++// CJK_TOP ++// Take the maximum flat and round coordinate values of the blue string ++// characters. If not set, take the minimum values. ++// ++// CJK_RIGHT ++// A synonym for CJK_TOP. If CJK_HORIZ is set, this flag indicates the ++// right blue zone, taking horizontal maximum values. ++// ++// CJK_HORIZ ++// Define a blue zone for horizontal hinting (i.e., vertical blue ++// zones). If not set, this is a blue zone for vertical hinting. ++ ++ + AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: + +- AF_BLUE_STRINGSET_LATN +- { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } +- { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 } +- { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } +- { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | +- AF_BLUE_PROPERTY_LATIN_X_HEIGHT } +- { AF_BLUE_STRING_LATIN_SMALL, 0 } +- { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 } +- { AF_BLUE_STRING_MAX, 0 } ++ AF_BLUE_STRINGSET_CYRL ++ { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } ++ { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 } ++ { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | ++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT } ++ { AF_BLUE_STRING_CYRILLIC_SMALL, 0 } ++ { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 } ++ { AF_BLUE_STRING_MAX, 0 } ++ ++ AF_BLUE_STRINGSET_DEVA ++ { AF_BLUE_STRING_DEVANAGARI_TOP, AF_BLUE_PROPERTY_LATIN_TOP } ++ { AF_BLUE_STRING_DEVANAGARI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP } ++ { AF_BLUE_STRING_DEVANAGARI_BASE, AF_BLUE_PROPERTY_LATIN_TOP | ++ AF_BLUE_PROPERTY_LATIN_NEUTRAL | ++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT } ++ { AF_BLUE_STRING_DEVANAGARI_BASE, 0 } ++ { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 } ++ { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_GREK + { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } +@@ -176,15 +289,6 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: + { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } + +- AF_BLUE_STRINGSET_CYRL +- { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } +- { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 } +- { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | +- AF_BLUE_PROPERTY_LATIN_X_HEIGHT } +- { AF_BLUE_STRING_CYRILLIC_SMALL, 0 } +- { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 } +- { AF_BLUE_STRING_MAX, 0 } +- + AF_BLUE_STRINGSET_HEBR + { AF_BLUE_STRING_HEBREW_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_LONG } +@@ -192,25 +296,27 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: + { AF_BLUE_STRING_HEBREW_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } + ++ AF_BLUE_STRINGSET_LATN ++ { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } ++ { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 } ++ { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } ++ { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | ++ AF_BLUE_PROPERTY_LATIN_X_HEIGHT } ++ { AF_BLUE_STRING_LATIN_SMALL, 0 } ++ { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 } ++ { AF_BLUE_STRING_MAX, 0 } ++ + #ifdef AF_CONFIG_OPTION_CJK + + AF_BLUE_STRINGSET_HANI +- { AF_BLUE_STRING_CJK_TOP_FILL, AF_BLUE_PROPERTY_CJK_TOP | +- AF_BLUE_PROPERTY_CJK_FILL } +- { AF_BLUE_STRING_CJK_TOP_UNFILL, AF_BLUE_PROPERTY_CJK_TOP } +- { AF_BLUE_STRING_CJK_BOTTOM_FILL, AF_BLUE_PROPERTY_CJK_FILL } +- { AF_BLUE_STRING_CJK_BOTTOM_UNFILL, 0 } ++ { AF_BLUE_STRING_CJK_TOP, AF_BLUE_PROPERTY_CJK_TOP } ++ { AF_BLUE_STRING_CJK_BOTTOM, 0 } + #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT +- { AF_BLUE_STRING_CJK_LEFT_FILL, AF_BLUE_PROPERTY_CJK_HORIZ | +- AF_BLUE_PROPERTY_CJK_FILL } +- { AF_BLUE_STRING_CJK_LEFT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ } +- { AF_BLUE_STRING_CJK_RIGHT_FILL, AF_BLUE_PROPERTY_CJK_HORIZ | +- AF_BLUE_PROPERTY_CJK_RIGHT | +- AF_BLUE_PROPERTY_CJK_FILL } +- { AF_BLUE_STRING_CJK_RIGHT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ | +- AF_BLUE_PROPERTY_CJK_RIGHT } ++ { AF_BLUE_STRING_CJK_LEFT, AF_BLUE_PROPERTY_CJK_HORIZ } ++ { AF_BLUE_STRING_CJK_RIGHT, AF_BLUE_PROPERTY_CJK_HORIZ | ++ AF_BLUE_PROPERTY_CJK_RIGHT } + #endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */ +- { AF_BLUE_STRING_MAX, 0 } ++ { AF_BLUE_STRING_MAX, 0 } + + #endif /* AF_CONFIG_OPTION_CJK */ + +diff --git a/src/autofit/afblue.h b/src/autofit/afblue.h +index 6f336ab..d239e8e 100644 +--- a/src/autofit/afblue.h ++++ b/src/autofit/afblue.h +@@ -7,7 +7,7 @@ + /* */ + /* Auto-fitter data for blue strings (specification). */ + /* */ +-/* Copyright 2013 by */ ++/* Copyright 2013, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -67,42 +67,42 @@ FT_BEGIN_HEADER + /* At the bottommost level, we define strings for finding blue zones. */ + + +-#define AF_BLUE_STRING_MAX_LEN 25 ++#define AF_BLUE_STRING_MAX_LEN 51 + + /* The AF_Blue_String enumeration values are offsets into the */ + /* `af_blue_strings' array. */ + + typedef enum AF_Blue_String_ + { +- AF_BLUE_STRING_LATIN_CAPITAL_TOP = 0, +- AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 9, +- AF_BLUE_STRING_LATIN_SMALL_F_TOP = 18, +- AF_BLUE_STRING_LATIN_SMALL = 26, +- AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 34, +- AF_BLUE_STRING_GREEK_CAPITAL_TOP = 40, +- AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 55, +- AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 68, +- AF_BLUE_STRING_GREEK_SMALL = 81, +- AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 98, +- AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 115, +- AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 132, +- AF_BLUE_STRING_CYRILLIC_SMALL = 149, +- AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 166, +- AF_BLUE_STRING_HEBREW_TOP = 173, +- AF_BLUE_STRING_HEBREW_BOTTOM = 190, +- AF_BLUE_STRING_HEBREW_DESCENDER = 203, +- af_blue_1_1 = 213, ++ AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 0, ++ AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 17, ++ AF_BLUE_STRING_CYRILLIC_SMALL = 34, ++ AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 51, ++ AF_BLUE_STRING_DEVANAGARI_BASE = 58, ++ AF_BLUE_STRING_DEVANAGARI_TOP = 83, ++ AF_BLUE_STRING_DEVANAGARI_HEAD = 108, ++ AF_BLUE_STRING_DEVANAGARI_BOTTOM = 133, ++ AF_BLUE_STRING_GREEK_CAPITAL_TOP = 140, ++ AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 155, ++ AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 168, ++ AF_BLUE_STRING_GREEK_SMALL = 181, ++ AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 198, ++ AF_BLUE_STRING_HEBREW_TOP = 215, ++ AF_BLUE_STRING_HEBREW_BOTTOM = 232, ++ AF_BLUE_STRING_HEBREW_DESCENDER = 245, ++ AF_BLUE_STRING_LATIN_CAPITAL_TOP = 256, ++ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 265, ++ AF_BLUE_STRING_LATIN_SMALL_F_TOP = 274, ++ AF_BLUE_STRING_LATIN_SMALL = 282, ++ AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 290, ++ af_blue_1_1 = 295, + #ifdef AF_CONFIG_OPTION_CJK +- AF_BLUE_STRING_CJK_TOP_FILL = af_blue_1_1 + 1, +- AF_BLUE_STRING_CJK_TOP_UNFILL = af_blue_1_1 + 77, +- AF_BLUE_STRING_CJK_BOTTOM_FILL = af_blue_1_1 + 153, +- AF_BLUE_STRING_CJK_BOTTOM_UNFILL = af_blue_1_1 + 229, ++ AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1, ++ AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 153, + af_blue_1_1_1 = af_blue_1_1 + 304, + #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT +- AF_BLUE_STRING_CJK_LEFT_FILL = af_blue_1_1_1 + 1, +- AF_BLUE_STRING_CJK_LEFT_UNFILL = af_blue_1_1_1 + 77, +- AF_BLUE_STRING_CJK_RIGHT_FILL = af_blue_1_1_1 + 153, +- AF_BLUE_STRING_CJK_RIGHT_UNFILL = af_blue_1_1_1 + 229, ++ AF_BLUE_STRING_CJK_LEFT = af_blue_1_1_1 + 1, ++ AF_BLUE_STRING_CJK_RIGHT = af_blue_1_1_1 + 153, + af_blue_1_1_2 = af_blue_1_1_1 + 304, + #else + af_blue_1_1_2 = af_blue_1_1_1 + 0, +@@ -136,33 +136,34 @@ FT_BEGIN_HEADER + /* Properties are specific to a writing system. We assume that a given */ + /* blue string can't be used in more than a single writing system, which */ + /* is a safe bet. */ +-#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) +-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 1 ) +-#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 2 ) ++#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) /* must have value 1 */ ++#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1 << 1 ) ++#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 2 ) ++#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 3 ) + +-#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 0 ) +-#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 1 ) +-#define AF_BLUE_PROPERTY_CJK_FILL ( 1 << 2 ) ++#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 0 ) /* must have value 1 */ ++#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 1 ) /* must have value 2 */ + #define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP + + +-#define AF_BLUE_STRINGSET_MAX_LEN 9 ++#define AF_BLUE_STRINGSET_MAX_LEN 7 + + /* The AF_Blue_Stringset enumeration values are offsets into the */ + /* `af_blue_stringsets' array. */ + + typedef enum AF_Blue_Stringset_ + { +- AF_BLUE_STRINGSET_LATN = 0, +- AF_BLUE_STRINGSET_GREK = 7, +- AF_BLUE_STRINGSET_CYRL = 14, +- AF_BLUE_STRINGSET_HEBR = 20, +- af_blue_2_1 = 24, ++ AF_BLUE_STRINGSET_CYRL = 0, ++ AF_BLUE_STRINGSET_DEVA = 6, ++ AF_BLUE_STRINGSET_GREK = 12, ++ AF_BLUE_STRINGSET_HEBR = 19, ++ AF_BLUE_STRINGSET_LATN = 23, ++ af_blue_2_1 = 30, + #ifdef AF_CONFIG_OPTION_CJK + AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0, +- af_blue_2_1_1 = af_blue_2_1 + 4, ++ af_blue_2_1_1 = af_blue_2_1 + 2, + #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT +- af_blue_2_1_2 = af_blue_2_1_1 + 4, ++ af_blue_2_1_2 = af_blue_2_1_1 + 2, + #else + af_blue_2_1_2 = af_blue_2_1_1 + 0, + #endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */ +diff --git a/src/autofit/afblue.hin b/src/autofit/afblue.hin +index 4fc9917..0b4b48d 100644 +--- a/src/autofit/afblue.hin ++++ b/src/autofit/afblue.hin +@@ -4,7 +4,7 @@ + /* */ + /* Auto-fitter data for blue strings (specification). */ + /* */ +-/* Copyright 2013 by */ ++/* Copyright 2013, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -96,13 +96,13 @@ FT_BEGIN_HEADER + /* Properties are specific to a writing system. We assume that a given */ + /* blue string can't be used in more than a single writing system, which */ + /* is a safe bet. */ +-#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) +-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 1 ) +-#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 2 ) ++#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) /* must have value 1 */ ++#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1 << 1 ) ++#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 2 ) ++#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 3 ) + +-#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 0 ) +-#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 1 ) +-#define AF_BLUE_PROPERTY_CJK_FILL ( 1 << 2 ) ++#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 0 ) /* must have value 1 */ ++#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 1 ) /* must have value 2 */ + #define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP + + +diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c +index 3a65fc5..048e0e7 100644 +--- a/src/autofit/afcjk.c ++++ b/src/autofit/afcjk.c +@@ -4,7 +4,7 @@ + /* */ + /* Auto-fitter hinting routines for CJK writing system (body). */ + /* */ +-/* Copyright 2006-2013 by */ ++/* Copyright 2006-2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -178,6 +178,8 @@ + goto Exit; + + af_latin_hints_link_segments( hints, ++ 0, ++ NULL, + (AF_Dimension)dim ); + + seg = axhints->segments; +@@ -261,6 +263,8 @@ + FT_Int num_fills; + FT_Int num_flats; + ++ FT_Bool fill; ++ + AF_CJKBlue blue; + FT_Error error; + AF_CJKAxis axis; +@@ -271,22 +275,6 @@ + AF_Blue_Stringset bss = sc->blue_stringset; + const AF_Blue_StringRec* bs = &af_blue_stringsets[bss]; + +-#ifdef FT_DEBUG_LEVEL_TRACE +- FT_String* cjk_blue_name[4] = +- { +- (FT_String*)"bottom", /* -- , -- */ +- (FT_String*)"top", /* -- , TOP */ +- (FT_String*)"left", /* HORIZ, -- */ +- (FT_String*)"right" /* HORIZ, TOP */ +- }; +- +- FT_String* cjk_blue_type_name[2] = +- { +- (FT_String*)"unfilled", /* -- */ +- (FT_String*)"filled" /* FILL */ +- }; +-#endif +- + + /* we walk over the blue character strings as specified in the */ + /* style's entry in the `af_blue_stringset' array, computing its */ +@@ -308,15 +296,29 @@ + else + axis = &metrics->axis[AF_DIMENSION_VERT]; + +- FT_TRACE5(( "blue zone %d:\n", axis->blue_count )); ++#ifdef FT_DEBUG_LEVEL_TRACE ++ { ++ FT_String* cjk_blue_name[4] = ++ { ++ (FT_String*)"bottom", /* -- , -- */ ++ (FT_String*)"top", /* -- , TOP */ ++ (FT_String*)"left", /* HORIZ, -- */ ++ (FT_String*)"right" /* HORIZ, TOP */ ++ }; ++ ++ ++ FT_TRACE5(( "blue zone %d (%s):\n", ++ axis->blue_count, ++ cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) | ++ AF_CJK_IS_TOP_BLUE( bs ) ] )); ++ } ++#endif /* FT_DEBUG_LEVEL_TRACE */ + + num_fills = 0; + num_flats = 0; + +- FT_TRACE5(( " cjk blue %s/%s\n", +- cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) | +- AF_CJK_IS_TOP_BLUE( bs ) ], +- cjk_blue_type_name[!!AF_CJK_IS_FILLED_BLUE( bs )] )); ++ fill = 1; /* start with characters that define fill values */ ++ FT_TRACE5(( " [overshoot values]\n" )); + + while ( *p ) + { +@@ -330,6 +332,14 @@ + + GET_UTF8_CHAR( ch, p ); + ++ /* switch to characters that define flat values */ ++ if ( ch == '|' ) ++ { ++ fill = 0; ++ FT_TRACE5(( " [reference values]\n" )); ++ continue; ++ } ++ + /* load the character in the face -- skip unknown or empty ones */ + af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset ); + if ( glyph_index == 0 ) +@@ -417,7 +427,7 @@ + FT_TRACE5(( " U+%04lX: best_pos = %5ld\n", ch, best_pos )); + } + +- if ( AF_CJK_IS_FILLED_BLUE( bs ) ) ++ if ( fill ) + fills[num_fills++] = best_pos; + else + flats[num_flats++] = best_pos; +@@ -429,15 +439,15 @@ + * we couldn't find a single glyph to compute this blue zone, + * we will simply ignore it then + */ +- FT_TRACE5(( " empty\n" )); ++ FT_TRACE5(( " empty\n" )); + continue; + } + +- /* we have computed the contents of the `fill' and `flats' tables, */ +- /* now determine the reference position of the blue zone -- */ +- /* we simply take the median value after a simple sort */ +- af_sort_pos( num_flats, flats ); ++ /* we have computed the contents of the `fill' and `flats' tables, */ ++ /* now determine the reference and overshoot position of the blue -- */ ++ /* we simply take the median value after a simple sort */ + af_sort_pos( num_fills, fills ); ++ af_sort_pos( num_flats, flats ); + + blue = &axis->blues[axis->blue_count]; + blue_ref = &blue->ref.org; +@@ -476,7 +486,7 @@ + *blue_ref = + *blue_shoot = ( shoot + ref ) / 2; + +- FT_TRACE5(( " [overshoot smaller than reference," ++ FT_TRACE5(( " [reference smaller than overshoot," + " taking mean value]\n" )); + } + } +@@ -755,10 +765,6 @@ + /* now compare each segment to the others */ + for ( seg1 = segments; seg1 < segment_limit; seg1++ ) + { +- /* the fake segments are for metrics hinting only */ +- if ( seg1->first == seg1->last ) +- continue; +- + if ( seg1->dir != major_dir ) + continue; + +@@ -1018,10 +1024,11 @@ + + edge->first = seg; + edge->last = seg; ++ edge->dir = seg->dir; + edge->fpos = seg->pos; +- edge->opos = edge->pos = FT_MulFix( seg->pos, scale ); ++ edge->opos = FT_MulFix( seg->pos, scale ); ++ edge->pos = edge->opos; + seg->edge_next = seg; +- edge->dir = seg->dir; + } + else + { +@@ -1230,8 +1237,10 @@ + /* zone, check for left edges */ + /* */ + /* of course, that's for TrueType */ +- is_top_right_blue = FT_BOOL( blue->flags & AF_CJK_BLUE_TOP ); +- is_major_dir = FT_BOOL( edge->dir == axis->major_dir ); ++ is_top_right_blue = ++ (FT_Byte)( ( blue->flags & AF_CJK_BLUE_TOP ) != 0 ); ++ is_major_dir = ++ FT_BOOL( edge->dir == axis->major_dir ); + + /* if it is a top zone, the edge must be against the major */ + /* direction; if it is a bottom zone, it must be in the major */ +@@ -1528,6 +1537,12 @@ + + + stem_edge->pos = base_edge->pos + fitted_width; ++ ++ FT_TRACE5(( " CJKLINK: edge %d @%d (opos=%.2f) linked to %.2f," ++ " dist was %.2f, now %.2f\n", ++ stem_edge - hints->axis[dim].edges, stem_edge->fpos, ++ stem_edge->opos / 64.0, stem_edge->pos / 64.0, ++ dist / 64.0, fitted_width / 64.0 )); + } + + +diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h +index a260b09..4dd4f39 100644 +--- a/src/autofit/afcjk.h ++++ b/src/autofit/afcjk.h +@@ -4,7 +4,7 @@ + /* */ + /* Auto-fitter hinting routines for CJK writing system (specification). */ + /* */ +-/* Copyright 2006, 2007, 2011-2013 by */ ++/* Copyright 2006, 2007, 2011-2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -50,8 +50,6 @@ FT_BEGIN_HEADER + ( (b)->properties & AF_BLUE_PROPERTY_CJK_TOP ) + #define AF_CJK_IS_HORIZ_BLUE( b ) \ + ( (b)->properties & AF_BLUE_PROPERTY_CJK_HORIZ ) +-#define AF_CJK_IS_FILLED_BLUE( b ) \ +- ( (b)->properties & AF_BLUE_PROPERTY_CJK_FILL ) + #define AF_CJK_IS_RIGHT_BLUE AF_CJK_IS_TOP_BLUE + + #define AF_CJK_MAX_WIDTHS 16 +diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c +index 7aa2e11..a54c20c 100644 +--- a/src/autofit/afglobal.c ++++ b/src/autofit/afglobal.c +@@ -138,7 +138,7 @@ + FT_Byte* gstyles = globals->glyph_styles; + FT_UInt ss; + FT_UInt i; +- FT_UInt dflt = -1; ++ FT_UInt dflt = ~0U; /* a non-valid value */ + + + /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */ +@@ -176,7 +176,8 @@ + */ + if ( style_class->coverage == AF_COVERAGE_DEFAULT ) + { +- if ( style_class->script == globals->module->default_script ) ++ if ( (FT_UInt)style_class->script == ++ globals->module->default_script ) + dflt = ss; + + for ( range = script_class->script_uni_ranges; +@@ -332,8 +333,8 @@ + af_face_globals_free( globals ); + globals = NULL; + } +- +- globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX; ++ else ++ globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX; + + Exit: + *aglobals = globals; +diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h +index d2da40e..38d8d69 100644 +--- a/src/autofit/afglobal.h ++++ b/src/autofit/afglobal.h +@@ -66,16 +66,16 @@ FT_BEGIN_HEADER + + /* index of fallback style in `af_style_classes' */ + #ifdef AF_CONFIG_OPTION_CJK +-#define AF_STYLE_FALLBACK AF_STYLE_HANI_DFLT ++#define AF_STYLE_FALLBACK AF_STYLE_HANI_DFLT + #else +-#define AF_STYLE_FALLBACK AF_STYLE_NONE_DFLT ++#define AF_STYLE_FALLBACK AF_STYLE_NONE_DFLT + #endif + /* default script for OpenType; ignored if HarfBuzz isn't used */ +-#define AF_SCRIPT_DEFAULT AF_SCRIPT_LATN ++#define AF_SCRIPT_DEFAULT AF_SCRIPT_LATN + /* a bit mask indicating an uncovered glyph */ + #define AF_STYLE_UNASSIGNED 0x7F + /* if this flag is set, we have an ASCII digit */ +-#define AF_DIGIT 0x80 ++#define AF_DIGIT 0x80 + + /* `increase-x-height' property */ + #define AF_PROP_INCREASE_X_HEIGHT_MIN 6 +diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c +index 270a06b..9fbc541 100644 +--- a/src/autofit/afhints.c ++++ b/src/autofit/afhints.c +@@ -74,7 +74,8 @@ + } + + +- /* Get new edge for given axis, direction, and position. */ ++ /* Get new edge for given axis, direction, and position, */ ++ /* without initializing the edge itself. */ + + FT_LOCAL( FT_Error ) + af_axis_hints_new_edge( AF_AxisHints axis, +@@ -130,10 +131,6 @@ + + axis->num_edges++; + +- FT_ZERO( edge ); +- edge->fpos = (FT_Short)fpos; +- edge->dir = (FT_Char)dir; +- + Exit: + *anedge = edge; + return error; +@@ -204,7 +201,7 @@ + + for ( point = points; point < limit; point++ ) + AF_DUMP(( " [ %5d | %5d | %5d | %6.2f | %6.2f" +- " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n", ++ " | %5.2f | %5.2f | %c ]\n", + point - points, + point->fx, + point->fy, +@@ -212,12 +209,7 @@ + point->oy / 64.0, + point->x / 64.0, + point->y / 64.0, +- ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ', +- ( point->flags & AF_FLAG_INFLECTION ) ? 'i' : ' ', +- ( point->flags & AF_FLAG_EXTREMA_X ) ? '<' : ' ', +- ( point->flags & AF_FLAG_EXTREMA_Y ) ? 'v' : ' ', +- ( point->flags & AF_FLAG_ROUND_X ) ? '(' : ' ', +- ( point->flags & AF_FLAG_ROUND_Y ) ? 'u' : ' ')); ++ ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ')); + AF_DUMP(( "\n" )); + } + #ifdef __cplusplus +@@ -651,6 +643,9 @@ + + for ( point = points; point < point_limit; point++, vec++, tag++ ) + { ++ point->in_dir = (FT_Char)AF_DIR_NONE; ++ point->out_dir = (FT_Char)AF_DIR_NONE; ++ + point->fx = (FT_Short)vec->x; + point->fy = (FT_Short)vec->y; + point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta; +@@ -698,91 +693,186 @@ + } + } + +- /* compute directions of in & out vectors */ + { +- AF_Point first = points; +- AF_Point prev = NULL; +- FT_Pos in_x = 0; +- FT_Pos in_y = 0; +- AF_Direction in_dir = AF_DIR_NONE; +- +- FT_Pos last_good_in_x = 0; +- FT_Pos last_good_in_y = 0; +- ++ /* ++ * Compute directions of `in' and `out' vectors. ++ * ++ * Note that distances between points that are very near to each ++ * other are accumulated. In other words, the auto-hinter ++ * prepends the small vectors between near points to the first ++ * non-near vector. All intermediate points are tagged as ++ * weak; the directions are adjusted also to be equal to the ++ * accumulated one. ++ */ ++ ++ /* value 20 in `near_limit' is heuristic */ + FT_UInt units_per_em = hints->metrics->scaler.face->units_per_EM; + FT_Int near_limit = 20 * units_per_em / 2048; ++ FT_Int near_limit2 = 2 * near_limit - 1; + ++ AF_Point* contour; ++ AF_Point* contour_limit = hints->contours + hints->num_contours; + +- for ( point = points; point < point_limit; point++ ) ++ ++ for ( contour = hints->contours; contour < contour_limit; contour++ ) + { +- AF_Point next; +- FT_Pos out_x, out_y; ++ AF_Point first = *contour; ++ AF_Point next, prev, curr; ++ ++ FT_Pos out_x, out_y; + ++ FT_Bool is_first; + +- if ( point == first ) ++ ++ /* since the first point of a contour could be part of a */ ++ /* series of near points, go backwards to find the first */ ++ /* non-near point and adjust `first' */ ++ ++ point = first; ++ prev = first->prev; ++ ++ while ( prev != first ) + { +- prev = first->prev; ++ out_x = point->fx - prev->fx; ++ out_y = point->fy - prev->fy; ++ ++ /* ++ * We use Taxicab metrics to measure the vector length. ++ * ++ * Note that the accumulated distances so far could have the ++ * opposite direction of the distance measured here. For this ++ * reason we use `near_limit2' for the comparison to get a ++ * non-near point even in the worst case. ++ */ ++ if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit2 ) ++ break; ++ ++ point = prev; ++ prev = prev->prev; ++ } + +- in_x = first->fx - prev->fx; +- in_y = first->fy - prev->fy; ++ /* adjust first point */ ++ first = point; + +- last_good_in_x = in_x; +- last_good_in_y = in_y; ++ /* now loop over all points of the contour to get */ ++ /* `in' and `out' vector directions */ + +- if ( FT_ABS( in_x ) + FT_ABS( in_y ) < near_limit ) +- { +- /* search first non-near point to get a good `in_dir' value */ ++ curr = first; + +- AF_Point point_ = prev; ++ /* ++ * We abuse the `u' and `v' fields to store index deltas to the ++ * next and previous non-near point, respectively. ++ * ++ * To avoid problems with not having non-near points, we point to ++ * `first' by default as the next non-near point. ++ * ++ */ ++ curr->u = (FT_Pos)( first - curr ); ++ first->v = -curr->u; + ++ out_x = 0; ++ out_y = 0; + +- while ( point_ != first ) +- { +- AF_Point prev_ = point_->prev; ++ is_first = 1; + +- FT_Pos in_x_ = point_->fx - prev_->fx; +- FT_Pos in_y_ = point_->fy - prev_->fy; ++ for ( point = first; ++ point != first || is_first; ++ point = point->next ) ++ { ++ AF_Direction out_dir; + + +- if ( FT_ABS( in_x_ ) + FT_ABS( in_y_ ) >= near_limit ) +- { +- last_good_in_x = in_x_; +- last_good_in_y = in_y_; ++ is_first = 0; + +- break; +- } ++ next = point->next; + +- point_ = prev_; +- } ++ out_x += next->fx - point->fx; ++ out_y += next->fy - point->fy; ++ ++ if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit ) ++ { ++ next->flags |= AF_FLAG_WEAK_INTERPOLATION; ++ continue; ++ } ++ ++ curr->u = (FT_Pos)( next - curr ); ++ next->v = -curr->u; ++ ++ out_dir = af_direction_compute( out_x, out_y ); ++ ++ /* adjust directions for all points inbetween; */ ++ /* the loop also updates position of `curr' */ ++ curr->out_dir = (FT_Char)out_dir; ++ for ( curr = curr->next; curr != next; curr = curr->next ) ++ { ++ curr->in_dir = (FT_Char)out_dir; ++ curr->out_dir = (FT_Char)out_dir; + } ++ next->in_dir = (FT_Char)out_dir; + +- in_dir = af_direction_compute( in_x, in_y ); +- first = prev + 1; ++ curr->u = (FT_Pos)( first - curr ); ++ first->v = -curr->u; ++ ++ out_x = 0; ++ out_y = 0; + } ++ } + +- point->in_dir = (FT_Char)in_dir; ++ /* ++ * The next step is to `simplify' an outline's topology so that we ++ * can identify local extrema more reliably: A series of ++ * non-horizontal or non-vertical vectors pointing into the same ++ * quadrant are handled as a single, long vector. From a ++ * topological point of the view, the intermediate points are of no ++ * interest and thus tagged as weak. ++ */ + +- /* check whether the current point is near to the previous one */ +- /* (value 20 in `near_limit' is heuristic; we use Taxicab */ +- /* metrics for the test) */ ++ for ( point = points; point < point_limit; point++ ) ++ { ++ if ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ++ continue; + +- if ( FT_ABS( in_x ) + FT_ABS( in_y ) < near_limit ) +- point->flags |= AF_FLAG_NEAR; +- else ++ if ( point->in_dir == AF_DIR_NONE && ++ point->out_dir == AF_DIR_NONE ) + { +- last_good_in_x = in_x; +- last_good_in_y = in_y; +- } ++ /* check whether both vectors point into the same quadrant */ ++ ++ FT_Pos in_x, in_y; ++ FT_Pos out_x, out_y; ++ ++ AF_Point next_u = point + point->u; ++ AF_Point prev_v = point + point->v; ++ + +- next = point->next; +- out_x = next->fx - point->fx; +- out_y = next->fy - point->fy; ++ in_x = point->fx - prev_v->fx; ++ in_y = point->fy - prev_v->fy; ++ ++ out_x = next_u->fx - point->fx; ++ out_y = next_u->fy - point->fy; ++ ++ if ( ( in_x ^ out_x ) >= 0 && ( in_y ^ out_y ) >= 0 ) ++ { ++ /* yes, so tag current point as weak */ ++ /* and update index deltas */ ++ ++ point->flags |= AF_FLAG_WEAK_INTERPOLATION; ++ ++ prev_v->u = (FT_Pos)( next_u - prev_v ); ++ next_u->v = -prev_v->u; ++ } ++ } ++ } + +- in_dir = af_direction_compute( out_x, out_y ); +- point->out_dir = (FT_Char)in_dir; ++ /* ++ * Finally, check for remaining weak points. Everything else not ++ * collected in edges so far is then implicitly classified as strong ++ * points. ++ */ + +- /* Check for weak points. The remaining points not collected */ +- /* in edges are then implicitly classified as strong points. */ ++ for ( point = points; point < point_limit; point++ ) ++ { ++ if ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ++ continue; + + if ( point->flags & AF_FLAG_CONTROL ) + { +@@ -799,18 +889,25 @@ + goto Is_Weak_Point; + } + +- /* test whether `in' and `out' direction is approximately */ +- /* the same (and use the last good `in' vector in case */ +- /* the current point is near to the previous one) */ +- if ( ft_corner_is_flat( +- point->flags & AF_FLAG_NEAR ? last_good_in_x : in_x, +- point->flags & AF_FLAG_NEAR ? last_good_in_y : in_y, +- out_x, +- out_y ) ) + { +- /* current point lies on a straight, diagonal line */ +- /* (more or less) */ +- goto Is_Weak_Point; ++ AF_Point next_u = point + point->u; ++ AF_Point prev_v = point + point->v; ++ ++ ++ if ( ft_corner_is_flat( point->fx - prev_v->fx, ++ point->fy - prev_v->fy, ++ next_u->fx - point->fx, ++ next_u->fy - point->fy ) ) ++ { ++ /* either the `in' or the `out' vector is much more */ ++ /* dominant than the other one, so tag current point */ ++ /* as weak and update index deltas */ ++ ++ prev_v->u = (FT_Pos)( next_u - prev_v ); ++ next_u->v = -prev_v->u; ++ ++ goto Is_Weak_Point; ++ } + } + } + else if ( point->in_dir == -point->out_dir ) +@@ -818,9 +915,6 @@ + /* current point forms a spike */ + goto Is_Weak_Point; + } +- +- in_x = out_x; +- in_y = out_y; + } + } + } +@@ -977,8 +1071,7 @@ + /* if this point is candidate to weak interpolation, we */ + /* interpolate it after all strong points have been processed */ + +- if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) && +- !( point->flags & AF_FLAG_INFLECTION ) ) ++ if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ) + continue; + + if ( dim == AF_DIMENSION_VERT ) +diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h +index 5f1507f..92101de 100644 +--- a/src/autofit/afhints.h ++++ b/src/autofit/afhints.h +@@ -4,7 +4,7 @@ + /* */ + /* Auto-fitter hinting routines (specification). */ + /* */ +-/* Copyright 2003-2008, 2010-2012 by */ ++/* Copyright 2003-2008, 2010-2012, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -72,13 +72,9 @@ FT_BEGIN_HEADER + * `af_{cjk,latin,...}_hints_compute_segments' are the functions to + * find segments in an outline. + * +- * A segment is a series of consecutive points that are approximately +- * aligned along a coordinate axis. The analysis to do so is specific +- * to a writing system. +- * +- * A segment must have at least two points, except in the case of +- * `fake' segments that are generated to hint metrics appropriately, +- * and which consist of a single point. ++ * A segment is a series of at least two consecutive points that are ++ * approximately aligned along a coordinate axis. The analysis to do ++ * so is specific to a writing system. + * + * + * Edges +@@ -148,7 +144,7 @@ FT_BEGIN_HEADER + * Serifs are detected by `af_{cjk,latin,...}_hint_edges'. + * + * In comparison to a stem, a serif (as handled by the auto-hinter +- * module which takes care of the `latin' writing system) has ++ * module that takes care of the `latin' writing system) has + * + * best segment_1 = segment_2 && best segment_2 != segment_1 + * +@@ -178,19 +174,19 @@ FT_BEGIN_HEADER + * + * Strong Points + * +- * Experience has shown that points which are not part of an edge need +- * to be interpolated linearly between their two closest edges, even if +- * these are not part of the contour of those particular points. +- * Typical candidates for this are ++ * Experience has shown that points not part of an edge need to be ++ * interpolated linearly between their two closest edges, even if these ++ * are not part of the contour of those particular points. Typical ++ * candidates for this are + * + * - angle points (i.e., points where the `in' and `out' direction + * differ greatly) + * + * - inflection points (i.e., where the `in' and `out' angles are the + * same, but the curvature changes sign) [currently, such points +- * aren't handled in the auto-hinter] ++ * aren't handled specially in the auto-hinter] + * +- * `af_glyph_hints_align_strong_points' is the function which takes ++ * `af_glyph_hints_align_strong_points' is the function that takes + * care of such situations; it is equivalent to the TrueType `IP' + * hinting instruction. + * +@@ -220,26 +216,12 @@ FT_BEGIN_HEADER + AF_FLAG_CUBIC = 1 << 1, + AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC, + +- /* point extremum flags */ +- AF_FLAG_EXTREMA_X = 1 << 2, +- AF_FLAG_EXTREMA_Y = 1 << 3, +- +- /* point roundness flags */ +- AF_FLAG_ROUND_X = 1 << 4, +- AF_FLAG_ROUND_Y = 1 << 5, +- + /* point touch flags */ +- AF_FLAG_TOUCH_X = 1 << 6, +- AF_FLAG_TOUCH_Y = 1 << 7, ++ AF_FLAG_TOUCH_X = 1 << 2, ++ AF_FLAG_TOUCH_Y = 1 << 3, + + /* candidates for weak interpolation have this flag set */ +- AF_FLAG_WEAK_INTERPOLATION = 1 << 8, +- +- /* all inflection points in the outline have this flag set */ +- AF_FLAG_INFLECTION = 1 << 9, +- +- /* the current point is very near to another one */ +- AF_FLAG_NEAR = 1 << 10 ++ AF_FLAG_WEAK_INTERPOLATION = 1 << 4 + + } AF_Flags; + +@@ -247,10 +229,11 @@ FT_BEGIN_HEADER + /* edge hint flags */ + typedef enum AF_Edge_Flags_ + { +- AF_EDGE_NORMAL = 0, +- AF_EDGE_ROUND = 1 << 0, +- AF_EDGE_SERIF = 1 << 1, +- AF_EDGE_DONE = 1 << 2 ++ AF_EDGE_NORMAL = 0, ++ AF_EDGE_ROUND = 1 << 0, ++ AF_EDGE_SERIF = 1 << 1, ++ AF_EDGE_DONE = 1 << 2, ++ AF_EDGE_NEUTRAL = 1 << 3 /* set if edge aligns to a neutral blue zone */ + + } AF_Edge_Flags; + +diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c +index e3a7742..36a3689 100644 +--- a/src/autofit/aflatin.c ++++ b/src/autofit/aflatin.c +@@ -171,7 +171,15 @@ + if ( error ) + goto Exit; + ++ /* ++ * We assume that the glyphs selected for the stem width ++ * computation are `featureless' enough so that the linking ++ * algorithm works fine without adjustments of its scoring ++ * function. ++ */ + af_latin_hints_link_segments( hints, ++ 0, ++ NULL, + (AF_Dimension)dim ); + + seg = axhints->segments; +@@ -298,6 +306,14 @@ + have_flag = 1; + } + ++ if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) ) ++ { ++ if ( have_flag ) ++ FT_TRACE5(( ", " )); ++ FT_TRACE5(( "neutral" )); ++ have_flag = 1; ++ } ++ + if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) ) + { + if ( have_flag ) +@@ -520,6 +536,13 @@ + FT_Int last; + FT_Bool hit; + ++ /* we intentionally declare these two variables */ ++ /* outside of the loop since various compilers emit */ ++ /* incorrect warning messages otherwise, talking about */ ++ /* `possibly uninitialized variables' */ ++ FT_Int p_first = 0; /* make compiler happy */ ++ FT_Int p_last = 0; ++ + FT_Bool left2right; + + +@@ -552,7 +575,6 @@ + { + FT_Bool l2r; + FT_Pos d; +- FT_Int p_first, p_last; + + + if ( !hit ) +@@ -688,6 +710,13 @@ + FT_CURVE_TAG( outline.tags[best_segment_last] ) != + FT_CURVE_TAG_ON ); + ++ if ( round && AF_LATIN_IS_NEUTRAL_BLUE( bs ) ) ++ { ++ /* only use flat segments for a neutral blue zone */ ++ FT_TRACE5(( " (round, skipped)\n" )); ++ continue; ++ } ++ + FT_TRACE5(( " (%s)\n", round ? "round" : "flat" )); + } + +@@ -758,6 +787,8 @@ + blue->flags = 0; + if ( AF_LATIN_IS_TOP_BLUE( bs ) ) + blue->flags |= AF_LATIN_BLUE_TOP; ++ if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) ) ++ blue->flags |= AF_LATIN_BLUE_NEUTRAL; + + /* + * The following flag is used later to adjust the y and x scales +@@ -1262,17 +1293,19 @@ + /* this is the start of a new segment! */ + segment_dir = (AF_Direction)point->out_dir; + +- /* clear all segment fields */ + error = af_axis_hints_new_segment( axis, memory, &segment ); + if ( error ) + goto Exit; + +- segment[0] = seg0; ++ /* clear all segment fields */ ++ segment[0] = seg0; ++ + segment->dir = (FT_Char)segment_dir; + min_pos = max_pos = point->u; + segment->first = point; + segment->last = point; +- on_edge = 1; ++ ++ on_edge = 1; + } + + point = point->next; +@@ -1296,9 +1329,6 @@ + FT_Pos last_v = last->v; + + +- if ( first == last ) +- continue; +- + if ( first_v < last_v ) + { + AF_Point p; +@@ -1337,31 +1367,44 @@ + } + + +- /* Link segments to form stems and serifs. */ ++ /* Link segments to form stems and serifs. If `width_count' and */ ++ /* `widths' are non-zero, use them to fine-tune the scoring function. */ + + FT_LOCAL_DEF( void ) + af_latin_hints_link_segments( AF_GlyphHints hints, ++ FT_UInt width_count, ++ AF_WidthRec* widths, + AF_Dimension dim ) + { + AF_AxisHints axis = &hints->axis[dim]; + AF_Segment segments = axis->segments; + AF_Segment segment_limit = segments + axis->num_segments; +- FT_Pos len_threshold, len_score; ++ FT_Pos len_threshold, len_score, dist_score, max_width; + AF_Segment seg1, seg2; + + ++ if ( width_count ) ++ max_width = widths[width_count - 1].org; ++ else ++ max_width = 0; ++ ++ /* a heuristic value to set up a minimum value for overlapping */ + len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 ); + if ( len_threshold == 0 ) + len_threshold = 1; + ++ /* a heuristic value to weight lengths */ + len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 ); + ++ /* a heuristic value to weight distances (no call to */ ++ /* AF_LATIN_CONSTANT needed, since we work on multiples */ ++ /* of the stem width) */ ++ dist_score = 3000; ++ + /* now compare each segment to the others */ + for ( seg1 = segments; seg1 < segment_limit; seg1++ ) + { +- /* the fake segments are introduced to hint the metrics -- */ +- /* we must never link them to anything */ +- if ( seg1->dir != axis->major_dir || seg1->first == seg1->last ) ++ if ( seg1->dir != axis->major_dir ) + continue; + + /* search for stems having opposite directions, */ +@@ -1375,10 +1418,9 @@ + if ( seg1->dir + seg2->dir == 0 && pos2 > pos1 ) + { + /* compute distance between the two segments */ +- FT_Pos dist = pos2 - pos1; +- FT_Pos min = seg1->min_coord; +- FT_Pos max = seg1->max_coord; +- FT_Pos len, score; ++ FT_Pos min = seg1->min_coord; ++ FT_Pos max = seg1->max_coord; ++ FT_Pos len; + + + if ( min < seg2->min_coord ) +@@ -1388,15 +1430,49 @@ + max = seg2->max_coord; + + /* compute maximum coordinate difference of the two segments */ ++ /* (this is, how much they overlap) */ + len = max - min; + if ( len >= len_threshold ) + { +- /* small coordinate differences cause a higher score, and */ +- /* segments with a greater distance cause a higher score also */ +- score = dist + len_score / len; ++ /* ++ * The score is the sum of two demerits indicating the ++ * `badness' of a fit, measured along the segments' main axis ++ * and orthogonal to it, respectively. ++ * ++ * o The less overlapping along the main axis, the worse it ++ * is, causing a larger demerit. ++ * ++ * o The nearer the orthogonal distance to a stem width, the ++ * better it is, causing a smaller demerit. For simplicity, ++ * however, we only increase the demerit for values that ++ * exceed the largest stem width. ++ */ ++ ++ FT_Pos dist = pos2 - pos1; ++ ++ FT_Pos dist_demerit, score; ++ ++ ++ if ( max_width ) ++ { ++ /* distance demerits are based on multiples of `max_width'; */ ++ /* we scale by 1024 for getting more precision */ ++ FT_Pos delta = ( dist << 10 ) / max_width - ( 1 << 10 ); ++ ++ ++ if ( delta > 10000 ) ++ dist_demerit = 32000; ++ else if ( delta > 0 ) ++ dist_demerit = delta * delta / dist_score; ++ else ++ dist_demerit = 0; ++ } ++ else ++ dist_demerit = dist; /* default if no widths available */ ++ ++ score = dist_demerit + len_score / len; + + /* and we search for the smallest score */ +- /* of the sum of the two values */ + if ( score < seg1->score ) + { + seg1->score = score; +@@ -1728,6 +1804,8 @@ + + FT_LOCAL_DEF( FT_Error ) + af_latin_hints_detect_features( AF_GlyphHints hints, ++ FT_UInt width_count, ++ AF_WidthRec* widths, + AF_Dimension dim ) + { + FT_Error error; +@@ -1736,7 +1814,7 @@ + error = af_latin_hints_compute_segments( hints, dim ); + if ( !error ) + { +- af_latin_hints_link_segments( hints, dim ); ++ af_latin_hints_link_segments( hints, width_count, widths, dim ); + + error = af_latin_hints_compute_edges( hints, dim ); + } +@@ -1765,8 +1843,9 @@ + for ( ; edge < edge_limit; edge++ ) + { + FT_UInt bb; +- AF_Width best_blue = NULL; +- FT_Pos best_dist; /* initial threshold */ ++ AF_Width best_blue = NULL; ++ FT_Bool best_blue_is_neutral = 0; ++ FT_Pos best_dist; /* initial threshold */ + + + /* compute the initial threshold as a fraction of the EM size */ +@@ -1780,24 +1859,26 @@ + for ( bb = 0; bb < latin->blue_count; bb++ ) + { + AF_LatinBlue blue = latin->blues + bb; +- FT_Bool is_top_blue, is_major_dir; ++ FT_Bool is_top_blue, is_neutral_blue, is_major_dir; + + + /* skip inactive blue zones (i.e., those that are too large) */ + if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) ) + continue; + +- /* if it is a top zone, check for right edges -- if it is a bottom */ +- /* zone, check for left edges */ +- /* */ +- /* of course, that's for TrueType */ +- is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 ); +- is_major_dir = FT_BOOL( edge->dir == axis->major_dir ); +- +- /* if it is a top zone, the edge must be against the major */ +- /* direction; if it is a bottom zone, it must be in the major */ +- /* direction */ +- if ( is_top_blue ^ is_major_dir ) ++ /* if it is a top zone, check for right edges (against the major */ ++ /* direction); if it is a bottom zone, check for left edges (in */ ++ /* the major direction) -- this assumes the TrueType convention */ ++ /* for the orientation of contours */ ++ is_top_blue = ++ (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 ); ++ is_neutral_blue = ++ (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_NEUTRAL ) != 0); ++ is_major_dir = ++ FT_BOOL( edge->dir == axis->major_dir ); ++ ++ /* neutral blue zones are handled for both directions */ ++ if ( is_top_blue ^ is_major_dir || is_neutral_blue ) + { + FT_Pos dist; + +@@ -1810,15 +1891,19 @@ + dist = FT_MulFix( dist, scale ); + if ( dist < best_dist ) + { +- best_dist = dist; +- best_blue = &blue->ref; ++ best_dist = dist; ++ best_blue = &blue->ref; ++ best_blue_is_neutral = is_neutral_blue; + } + + /* now compare it to the overshoot position and check whether */ + /* the edge is rounded, and whether the edge is over the */ + /* reference position of a top zone, or under the reference */ +- /* position of a bottom zone */ +- if ( edge->flags & AF_EDGE_ROUND && dist != 0 ) ++ /* position of a bottom zone (provided we don't have a */ ++ /* neutral blue zone) */ ++ if ( edge->flags & AF_EDGE_ROUND && ++ dist != 0 && ++ !is_neutral_blue ) + { + FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org ); + +@@ -1832,8 +1917,9 @@ + dist = FT_MulFix( dist, scale ); + if ( dist < best_dist ) + { +- best_dist = dist; +- best_blue = &blue->shoot; ++ best_dist = dist; ++ best_blue = &blue->shoot; ++ best_blue_is_neutral = is_neutral_blue; + } + } + } +@@ -1841,7 +1927,11 @@ + } + + if ( best_blue ) ++ { + edge->blue_edge = best_blue; ++ if ( best_blue_is_neutral ) ++ edge->flags |= AF_EDGE_NEUTRAL; ++ } + } + } + +@@ -2159,7 +2249,7 @@ + + FT_TRACE5(( " LINK: edge %d (opos=%.2f) linked to %.2f," + " dist was %.2f, now %.2f\n", +- stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0, ++ stem_edge - hints->axis[dim].edges, stem_edge->opos / 64.0, + stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 )); + } + +@@ -2226,14 +2316,41 @@ + if ( edge->flags & AF_EDGE_DONE ) + continue; + +- blue = edge->blue_edge; + edge1 = NULL; + edge2 = edge->link; + ++ /* ++ * If a stem contains both a neutral and a non-neutral blue zone, ++ * skip the neutral one. Otherwise, outlines with different ++ * directions might be incorrectly aligned at the same vertical ++ * position. ++ * ++ * If we have two neutral blue zones, skip one of them. ++ * ++ */ ++ if ( edge->blue_edge && edge2 && edge2->blue_edge ) ++ { ++ FT_Byte neutral = edge->flags & AF_EDGE_NEUTRAL; ++ FT_Byte neutral2 = edge2->flags & AF_EDGE_NEUTRAL; ++ ++ ++ if ( ( neutral && neutral2 ) || neutral2 ) ++ { ++ edge2->blue_edge = NULL; ++ edge2->flags &= ~AF_EDGE_NEUTRAL; ++ } ++ else if ( neutral ) ++ { ++ edge->blue_edge = NULL; ++ edge->flags &= ~AF_EDGE_NEUTRAL; ++ } ++ } ++ ++ blue = edge->blue_edge; + if ( blue ) + edge1 = edge; + +- /* flip edges if the other stem is aligned to a blue zone */ ++ /* flip edges if the other edge is aligned to a blue zone */ + else if ( edge2 && edge2->blue_edge ) + { + blue = edge2->blue_edge; +@@ -2300,7 +2417,7 @@ + /* this should not happen, but it's better to be safe */ + if ( edge2->blue_edge ) + { +- FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2-edges )); ++ FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2 - edges )); + + af_latin_align_linked_edge( hints, dim, edge2, edge ); + edge->flags |= AF_EDGE_DONE; +@@ -2689,6 +2806,8 @@ + FT_Error error; + int dim; + ++ AF_LatinAxis axis; ++ + + error = af_glyph_hints_reload( hints, outline ); + if ( error ) +@@ -2702,14 +2821,22 @@ + if ( AF_HINTS_DO_HORIZONTAL( hints ) ) + #endif + { +- error = af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ ); ++ axis = &metrics->axis[AF_DIMENSION_HORZ]; ++ error = af_latin_hints_detect_features( hints, ++ axis->width_count, ++ axis->widths, ++ AF_DIMENSION_HORZ ); + if ( error ) + goto Exit; + } + + if ( AF_HINTS_DO_VERTICAL( hints ) ) + { +- error = af_latin_hints_detect_features( hints, AF_DIMENSION_VERT ); ++ axis = &metrics->axis[AF_DIMENSION_VERT]; ++ error = af_latin_hints_detect_features( hints, ++ axis->width_count, ++ axis->widths, ++ AF_DIMENSION_VERT ); + if ( error ) + goto Exit; + +diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h +index a958af3..2c0bfca 100644 +--- a/src/autofit/aflatin.h ++++ b/src/autofit/aflatin.h +@@ -5,7 +5,7 @@ + /* Auto-fitter hinting routines for latin writing system */ + /* (specification). */ + /* */ +-/* Copyright 2003-2007, 2009, 2011-2013 by */ ++/* Copyright 2003-2007, 2009, 2011-2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -53,6 +53,8 @@ FT_BEGIN_HEADER + + #define AF_LATIN_IS_TOP_BLUE( b ) \ + ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP ) ++#define AF_LATIN_IS_NEUTRAL_BLUE( b ) \ ++ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL ) + #define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \ + ( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT ) + #define AF_LATIN_IS_LONG_BLUE( b ) \ +@@ -63,10 +65,11 @@ FT_BEGIN_HEADER + + enum + { +- AF_LATIN_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */ +- AF_LATIN_BLUE_TOP = 1 << 1, /* result of AF_LATIN_IS_TOP_BLUE */ +- AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */ +- /* optimization */ ++ AF_LATIN_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */ ++ AF_LATIN_BLUE_TOP = 1 << 1, /* set if we have a top blue zone */ ++ AF_LATIN_BLUE_NEUTRAL = 1 << 2, /* set if we have neutral blue zone */ ++ AF_LATIN_BLUE_ADJUSTMENT = 1 << 3, /* used for scale adjustment */ ++ /* optimization */ + AF_LATIN_BLUE_FLAG_MAX + }; + +@@ -169,6 +172,8 @@ FT_BEGIN_HEADER + + FT_LOCAL( void ) + af_latin_hints_link_segments( AF_GlyphHints hints, ++ FT_UInt width_count, ++ AF_WidthRec* widths, + AF_Dimension dim ); + + FT_LOCAL( FT_Error ) +@@ -177,6 +182,8 @@ FT_BEGIN_HEADER + + FT_LOCAL( FT_Error ) + af_latin_hints_detect_features( AF_GlyphHints hints, ++ FT_UInt width_count, ++ AF_WidthRec* widths, + AF_Dimension dim ); + + /* */ +diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c +index 930fa98..07590b3 100644 +--- a/src/autofit/aflatin2.c ++++ b/src/autofit/aflatin2.c +@@ -4,7 +4,7 @@ + /* */ + /* Auto-fitter hinting routines for latin writing system (body). */ + /* */ +-/* Copyright 2003-2013 by */ ++/* Copyright 2003-2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -890,9 +890,6 @@ + FT_Pos last_v = last->v; + + +- if ( first == last ) +- continue; +- + if ( first_v < last_v ) + { + p = first->prev; +@@ -984,7 +981,7 @@ + #ifdef AF_SORT_SEGMENTS + for ( seg1 = segments; seg1 < segment_mid; seg1++ ) + { +- if ( seg1->dir != axis->major_dir || seg1->first == seg1->last ) ++ if ( seg1->dir != axis->major_dir ) + continue; + + for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ ) +@@ -992,9 +989,7 @@ + /* now compare each segment to the others */ + for ( seg1 = segments; seg1 < segment_limit; seg1++ ) + { +- /* the fake segments are introduced to hint the metrics -- */ +- /* we must never link them to anything */ +- if ( seg1->dir != axis->major_dir || seg1->first == seg1->last ) ++ if ( seg1->dir != axis->major_dir ) + continue; + + for ( seg2 = segments; seg2 < segment_limit; seg2++ ) +@@ -1194,9 +1189,10 @@ + + edge->first = seg; + edge->last = seg; +- edge->fpos = seg->pos; + edge->dir = seg->dir; +- edge->opos = edge->pos = FT_MulFix( seg->pos, scale ); ++ edge->fpos = seg->pos; ++ edge->opos = FT_MulFix( seg->pos, scale ); ++ edge->pos = edge->opos; + seg->edge_next = seg; + } + else +diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c +index 73bf832..181cf55 100644 +--- a/src/autofit/afmodule.c ++++ b/src/autofit/afmodule.c +@@ -103,8 +103,8 @@ + AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss]; + + +- if ( style_class->script == *fallback_script && +- style_class->coverage == AF_COVERAGE_DEFAULT ) ++ if ( (FT_UInt)style_class->script == *fallback_script && ++ style_class->coverage == AF_COVERAGE_DEFAULT ) + { + module->fallback_style = ss; + break; +diff --git a/src/autofit/afranges.c b/src/autofit/afranges.c +index 3d919b5..139a4c1 100644 +--- a/src/autofit/afranges.c ++++ b/src/autofit/afranges.c +@@ -21,51 +21,59 @@ + + const AF_Script_UniRangeRec af_cyrl_uniranges[] = + { +- AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */ ++ AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */ + AF_UNIRANGE_REC( 0x0500UL, 0x052FUL ), /* Cyrillic Supplement */ + AF_UNIRANGE_REC( 0x2DE0UL, 0x2DFFUL ), /* Cyrillic Extended-A */ + AF_UNIRANGE_REC( 0xA640UL, 0xA69FUL ), /* Cyrillic Extended-B */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + ++ const AF_Script_UniRangeRec af_deva_uniranges[] = ++ { ++ AF_UNIRANGE_REC( 0x0900UL, 0x097FUL ), /* Devanagari */ ++ AF_UNIRANGE_REC( 0x20B9UL, 0x20B9UL ), /* (new) Rupee sign */ ++ AF_UNIRANGE_REC( 0UL, 0UL ) ++ }; ++ + const AF_Script_UniRangeRec af_grek_uniranges[] = + { + AF_UNIRANGE_REC( 0x0370UL, 0x03FFUL ), /* Greek and Coptic */ +- AF_UNIRANGE_REC( 0x1F00UL, 0x1FFFUL ), /* Greek Extended */ ++ AF_UNIRANGE_REC( 0x1F00UL, 0x1FFFUL ), /* Greek Extended */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_hebr_uniranges[] = + { +- AF_UNIRANGE_REC( 0x0590UL, 0x05FFUL ), /* Hebrew */ ++ AF_UNIRANGE_REC( 0x0590UL, 0x05FFUL ), /* Hebrew */ + AF_UNIRANGE_REC( 0xFB1DUL, 0xFB4FUL ), /* Alphab. Present. Forms (Hebrew) */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_latn_uniranges[] = + { +- AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */ +- AF_UNIRANGE_REC( 0x00A0UL, 0x00FFUL ), /* Latin-1 Supplement (no control chars) */ +- AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */ +- AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */ +- AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */ +- AF_UNIRANGE_REC( 0x02B0UL, 0x02FFUL ), /* Spacing Modifier Letters */ +- AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */ +- AF_UNIRANGE_REC( 0x1D00UL, 0x1D7FUL ), /* Phonetic Extensions */ +- AF_UNIRANGE_REC( 0x1D80UL, 0x1DBFUL ), /* Phonetic Extensions Supplement */ ++ AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */ ++ AF_UNIRANGE_REC( 0x00A0UL, 0x00FFUL ), /* Latin-1 Supplement (no control chars) */ ++ AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */ ++ AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */ ++ AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */ ++ AF_UNIRANGE_REC( 0x02B0UL, 0x02FFUL ), /* Spacing Modifier Letters */ ++ AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */ ++ AF_UNIRANGE_REC( 0x1D00UL, 0x1D7FUL ), /* Phonetic Extensions */ ++ AF_UNIRANGE_REC( 0x1D80UL, 0x1DBFUL ), /* Phonetic Extensions Supplement */ + AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ), /* Combining Diacritical Marks Supplement */ +- AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */ +- AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */ +- AF_UNIRANGE_REC( 0x2070UL, 0x209FUL ), /* Superscripts and Subscripts */ +- AF_UNIRANGE_REC( 0x20A0UL, 0x20CFUL ), /* Currency Symbols */ +- AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */ +- AF_UNIRANGE_REC( 0x2460UL, 0x24FFUL ), /* Enclosed Alphanumerics */ +- AF_UNIRANGE_REC( 0x2C60UL, 0x2C7FUL ), /* Latin Extended-C */ +- AF_UNIRANGE_REC( 0x2E00UL, 0x2E7FUL ), /* Supplemental Punctuation */ +- AF_UNIRANGE_REC( 0xA720UL, 0xA7FFUL ), /* Latin Extended-D */ +- AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */ +- AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */ +- AF_UNIRANGE_REC( 0x1F100UL, 0x1F1FFUL ), /* Enclosed Alphanumeric Supplement */ ++ AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */ ++ AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */ ++ AF_UNIRANGE_REC( 0x2070UL, 0x209FUL ), /* Superscripts and Subscripts */ ++ AF_UNIRANGE_REC( 0x20A0UL, 0x20B8UL ), /* Currency Symbols ... */ ++ AF_UNIRANGE_REC( 0x20BAUL, 0x20CFUL ), /* ... except new Rupee sign */ ++ AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */ ++ AF_UNIRANGE_REC( 0x2460UL, 0x24FFUL ), /* Enclosed Alphanumerics */ ++ AF_UNIRANGE_REC( 0x2C60UL, 0x2C7FUL ), /* Latin Extended-C */ ++ AF_UNIRANGE_REC( 0x2E00UL, 0x2E7FUL ), /* Supplemental Punctuation */ ++ AF_UNIRANGE_REC( 0xA720UL, 0xA7FFUL ), /* Latin Extended-D */ ++ AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */ ++ AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */ ++ AF_UNIRANGE_REC( 0x1F100UL, 0x1F1FFUL ), /* Enclosed Alphanumeric Supplement */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + +@@ -82,12 +90,6 @@ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + +- const AF_Script_UniRangeRec af_deva_uniranges[] = +- { +- AF_UNIRANGE_REC( 0x0900UL, 0x097FUL ), /* Devanagari */ +- AF_UNIRANGE_REC( 0UL, 0UL ) +- }; +- + const AF_Script_UniRangeRec af_gujr_uniranges[] = + { + AF_UNIRANGE_REC( 0x0A80UL, 0x0AFFUL ), /* Gujarati */ +diff --git a/src/autofit/afscript.h b/src/autofit/afscript.h +index ae20932..a418b05 100644 +--- a/src/autofit/afscript.h ++++ b/src/autofit/afscript.h +@@ -31,6 +31,11 @@ + HB_SCRIPT_CYRILLIC, + 0x43E, 0x41E, 0x0 ) /* оО */ + ++ SCRIPT( deva, DEVA, ++ "Devanagari", ++ HB_SCRIPT_DEVANAGARI, ++ 0x920, 0x935, 0x91F ) /* ठ व ट */ ++ + SCRIPT( grek, GREK, + "Greek", + HB_SCRIPT_GREEK, +@@ -58,11 +63,6 @@ + HB_SCRIPT_BENGALI, + 'o', 0x0, 0x0 ) /* XXX */ + +- SCRIPT( deva, DEVA, +- "Devanagari", +- HB_SCRIPT_DEVANAGARI, +- 'o', 0x0, 0x0 ) /* XXX */ +- + SCRIPT( gujr, GUJR, + "Gujarati", + HB_SCRIPT_GUJARATI, +diff --git a/src/autofit/afstyles.h b/src/autofit/afstyles.h +index 429da76..27fdd2e 100644 +--- a/src/autofit/afstyles.h ++++ b/src/autofit/afstyles.h +@@ -81,7 +81,9 @@ + DEFAULT ) + + META_STYLE_LATIN( cyrl, CYRL, "Cyrillic" ) ++ + META_STYLE_LATIN( grek, GREK, "Greek" ) ++ + STYLE( hebr_dflt, HEBR_DFLT, + "Hebrew default style", + AF_WRITING_SYSTEM_LATIN, +@@ -90,6 +92,13 @@ + AF_COVERAGE_DEFAULT ) + META_STYLE_LATIN( latn, LATN, "Latin" ) + ++ STYLE( deva_dflt, DEVA_DFLT, ++ "Devanagari default style", ++ AF_WRITING_SYSTEM_LATIN, ++ AF_SCRIPT_DEVA, ++ AF_BLUE_STRINGSET_DEVA, ++ AF_COVERAGE_DEFAULT ) ++ + #ifdef FT_OPTION_AUTOFIT2 + STYLE( ltn2_dflt, LTN2_DFLT, + "Latin 2 default style", +@@ -119,7 +128,6 @@ + AF_COVERAGE_DEFAULT ) + + STYLE_DEFAULT_INDIC( beng, BENG, "Bengali" ) +- STYLE_DEFAULT_INDIC( deva, DEVA, "Devanagari" ) + STYLE_DEFAULT_INDIC( gujr, GUJR, "Gujarati" ) + STYLE_DEFAULT_INDIC( guru, GURU, "Gurmukhi" ) + STYLE_DEFAULT_INDIC( knda, KNDA, "Kannada" ) +diff --git a/src/autofit/hbshim.c b/src/autofit/hbshim.c +index 11fb743..cc04815 100644 +--- a/src/autofit/hbshim.c ++++ b/src/autofit/hbshim.c +@@ -247,6 +247,7 @@ + * (this is, not a single character is covered), we skip this coverage. + * + */ ++ if ( style_class->coverage != AF_COVERAGE_DEFAULT ) + { + AF_Blue_Stringset bss = style_class->blue_stringset; + const AF_Blue_StringRec* bs = &af_blue_stringsets[bss]; +@@ -328,8 +329,15 @@ + * out whether a glyph gets shifted vertically, but this is something I + * would like to avoid if not really necessary. + * ++ * Note that we don't follow this logic for the default coverage. ++ * Complex scripts like Devanagari have mandatory GPOS features to ++ * position many glyph elements, using mark-to-base or mark-to-ligature ++ * tables; the number of glyphs missed due to condition (b) would be far ++ * too large. ++ * + */ +- hb_set_subtract( gsub_glyphs, gpos_glyphs ); ++ if ( style_class->coverage != AF_COVERAGE_DEFAULT ) ++ hb_set_subtract( gsub_glyphs, gpos_glyphs ); + + #ifdef FT_DEBUG_LEVEL_TRACE + FT_TRACE4(( " glyphs without GPOS data (`*' means already assigned)" )); +@@ -347,6 +355,12 @@ + count++; + #endif + ++ /* glyph indices returned by `hb_ot_layout_lookup_collect_glyphs' */ ++ /* can be arbitrary: some fonts use fake indices for processing */ ++ /* internal to GSUB or GPOS, which is fully valid */ ++ if ( idx >= (hb_codepoint_t)globals->glyph_count ) ++ continue; ++ + if ( gstyles[idx] == AF_STYLE_UNASSIGNED ) + gstyles[idx] = (FT_Byte)style_class->style; + #ifdef FT_DEBUG_LEVEL_TRACE +diff --git a/src/base/ftbbox.c b/src/base/ftbbox.c +index 8d3f383..349cb95 100644 +--- a/src/base/ftbbox.c ++++ b/src/base/ftbbox.c +@@ -203,15 +203,48 @@ + /* max :: The address of the current maximum. */ + /* */ + static FT_Pos +- update_cubic_max( FT_Pos q1, +- FT_Pos q2, +- FT_Pos q3, +- FT_Pos q4, +- FT_Pos max ) ++ cubic_peak( FT_Pos q1, ++ FT_Pos q2, ++ FT_Pos q3, ++ FT_Pos q4 ) + { +- /* for a cubic segment to possibly reach new maximum, at least */ +- /* one of its off-points must stay above the current value */ +- while ( q2 > max || q3 > max ) ++ FT_Pos peak = 0; ++ FT_Int shift; ++ ++ /* This function finds a peak of a cubic segment if it is above 0 */ ++ /* using iterative bisection of the segment, or returns 0. */ ++ /* The fixed-point arithmetic of bisection is inherently stable */ ++ /* but may loose accuracy in the two lowest bits. To compensate, */ ++ /* we upscale the segment if there is room. Large values may need */ ++ /* to be downscaled to avoid overflows during bisection. */ ++ /* It is called with either q2 or q3 positive, which is necessary */ ++ /* for the peak to exist and avoids undefined FT_MSB. */ ++ ++ shift = 27 - ++ FT_MSB( FT_ABS( q1 ) | FT_ABS( q2 ) | FT_ABS( q3 ) | FT_ABS( q4 ) ); ++ ++ if ( shift > 0 ) ++ { ++ /* upscaling too much just wastes time */ ++ if ( shift > 2 ) ++ shift = 2; ++ ++ q1 <<= shift; ++ q2 <<= shift; ++ q3 <<= shift; ++ q4 <<= shift; ++ } ++ else ++ { ++ q1 >>= -shift; ++ q2 >>= -shift; ++ q3 >>= -shift; ++ q4 >>= -shift; ++ } ++ ++ /* for a peak to exist above 0, the cubic segment must have */ ++ /* at least one of its control off-points above 0. */ ++ while ( q2 > 0 || q3 > 0 ) + { + /* determine which half contains the maximum and split */ + if ( q1 + q2 > q3 + q4 ) /* first half */ +@@ -240,17 +273,22 @@ + /* check whether either end reached the maximum */ + if ( q1 == q2 && q1 >= q3 ) + { +- max = q1; ++ peak = q1; + break; + } + if ( q3 == q4 && q2 <= q4 ) + { +- max = q4; ++ peak = q4; + break; + } + } + +- return max; ++ if ( shift > 0 ) ++ peak >>= shift; ++ else ++ peak <<= -shift; ++ ++ return peak; + } + + +@@ -262,65 +300,17 @@ + FT_Pos* min, + FT_Pos* max ) + { +- FT_Pos nmin, nmax; +- FT_Int shift; +- +- + /* This function is only called when a control off-point is outside */ +- /* the bbox that contains all on-points. It finds a local extremum */ +- /* within the segment using iterative bisection of the segment. */ +- /* The fixed-point arithmetic of bisection is inherently stable */ +- /* but may loose accuracy in the two lowest bits. To compensate, */ +- /* we upscale the segment if there is room. Large values may need */ +- /* to be downscaled to avoid overflows during bisection. */ +- /* The control off-point outside the bbox is likely to have the top */ +- /* absolute value among arguments. */ +- +- shift = 27 - FT_MSB( FT_ABS( p2 ) | FT_ABS( p3 ) ); +- +- if ( shift > 0 ) +- { +- /* upscaling too much just wastes time */ +- if ( shift > 2 ) +- shift = 2; +- +- p1 <<= shift; +- p2 <<= shift; +- p3 <<= shift; +- p4 <<= shift; +- nmin = *min << shift; +- nmax = *max << shift; +- } +- else +- { +- p1 >>= -shift; +- p2 >>= -shift; +- p3 >>= -shift; +- p4 >>= -shift; +- nmin = *min >> -shift; +- nmax = *max >> -shift; +- } ++ /* the bbox that contains all on-points. So at least one of the */ ++ /* conditions below holds and cubic_peak is called with at least one */ ++ /* non-zero argument. */ + +- nmax = update_cubic_max( p1, p2, p3, p4, nmax ); ++ if ( p2 > *max || p3 > *max ) ++ *max += cubic_peak( p1 - *max, p2 - *max, p3 - *max, p4 - *max ); + + /* now flip the signs to update the minimum */ +- nmin = -update_cubic_max( -p1, -p2, -p3, -p4, -nmin ); +- +- if ( shift > 0 ) +- { +- nmin >>= shift; +- nmax >>= shift; +- } +- else +- { +- nmin <<= -shift; +- nmax <<= -shift; +- } +- +- if ( nmin < *min ) +- *min = nmin; +- if ( nmax > *max ) +- *max = nmax; ++ if ( p2 < *min || p3 < *min ) ++ *min -= cubic_peak( *min - p1, *min - p2, *min - p3, *min - p4 ); + } + + +diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c +index 5606745..158a428 100644 +--- a/src/base/ftbitmap.c ++++ b/src/base/ftbitmap.c +@@ -378,11 +378,8 @@ + static FT_Byte + ft_gray_for_premultiplied_srgb_bgra( const FT_Byte* bgra ) + { +- FT_Long a = bgra[3]; +- FT_Long b = bgra[0]; +- FT_Long g = bgra[1]; +- FT_Long r = bgra[2]; +- FT_Long l; ++ FT_UInt a = bgra[3]; ++ FT_UInt l; + + + /* Short-circuit transparent color to avoid div-by-zero. */ +@@ -397,38 +394,30 @@ + * + * http://accessibility.kde.org/hsl-adjusted.php + * +- * We do the computation with integers only. ++ * We do the computation with integers only, applying a gamma of 2.0. ++ * We guarantee 32-bit arithmetic to avoid overflow but the resulting ++ * luminosity fits into 16 bits. ++ * + */ + +- /* Undo premultification, get the number in a 16.16 form. */ +- b = FT_MulDiv( b, 65536, a ); +- g = FT_MulDiv( g, 65536, a ); +- r = FT_MulDiv( r, 65536, a ); +- a = a * 256; +- +- /* Apply gamma of 2.0 instead of 2.2. */ +- b = FT_MulFix( b, b ); +- g = FT_MulFix( g, g ); +- r = FT_MulFix( r, r ); +- +- /* Apply coefficients. */ +- b = FT_MulFix( b, 4731 /* 0.0722 * 65536 */ ); +- g = FT_MulFix( g, 46871 /* 0.7152 * 65536 */ ); +- r = FT_MulFix( r, 13933 /* 0.2126 * 65536 */ ); +- +- l = r + g + b; ++ l = ( 4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] + ++ 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] + ++ 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16; + + /* +- * Final transparency can be determined this way: ++ * Final transparency can be determined as follows. + * + * - If alpha is zero, we want 0. + * - If alpha is zero and luminosity is zero, we want 255. + * - If alpha is zero and luminosity is one, we want 0. + * +- * So the formula is a * (1 - l). ++ * So the formula is a * (1 - l) = a - l * a. ++ * ++ * We still need to undo premultiplication by dividing l by a*a. ++ * + */ + +- return (FT_Byte)( FT_MulFix( 65535 - l, a ) >> 8 ); ++ return (FT_Byte)( a - l / a ); + } + + +diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c +index 6e65583..d0c43e0 100644 +--- a/src/base/ftcalc.c ++++ b/src/base/ftcalc.c +@@ -39,7 +39,8 @@ + #include FT_INTERNAL_DEBUG_H + #include FT_INTERNAL_OBJECTS_H + +-#ifdef FT_MULFIX_INLINED ++ ++#ifdef FT_MULFIX_ASSEMBLER + #undef FT_MulFix + #endif + +@@ -67,6 +68,16 @@ + #define FT_COMPONENT trace_calc + + ++ /* transfer sign leaving a positive number */ ++#define FT_MOVE_SIGN( x, s ) \ ++ FT_BEGIN_STMNT \ ++ if ( x < 0 ) \ ++ { \ ++ x = -x; \ ++ s = -s; \ ++ } \ ++ FT_END_STMNT ++ + /* The following three functions are available regardless of whether */ + /* FT_LONG64 is defined. */ + +@@ -99,6 +110,7 @@ + : -((-a) & ~0xFFFFL ); + } + ++#ifndef FT_MSB + + FT_BASE_DEF ( FT_Int ) + FT_MSB( FT_UInt32 z ) +@@ -106,27 +118,27 @@ + FT_Int shift = 0; + + /* determine msb bit index in `shift' */ +- if ( z >= ( 1L << 16 ) ) ++ if ( z & 0xFFFF0000U ) + { + z >>= 16; + shift += 16; + } +- if ( z >= ( 1L << 8 ) ) ++ if ( z & 0x0000FF00U ) + { + z >>= 8; + shift += 8; + } +- if ( z >= ( 1L << 4 ) ) ++ if ( z & 0x000000F0U ) + { + z >>= 4; + shift += 4; + } +- if ( z >= ( 1L << 2 ) ) ++ if ( z & 0x0000000CU ) + { + z >>= 2; + shift += 2; + } +- if ( z >= ( 1L << 1 ) ) ++ if ( z & 0x00000002U ) + { + /* z >>= 1; */ + shift += 1; +@@ -135,6 +147,8 @@ + return shift; + } + ++#endif /* !FT_MSB */ ++ + + /* documentation is in ftcalc.h */ + +@@ -162,14 +176,13 @@ + FT_Long b, + FT_Long c ) + { +- FT_Int s; ++ FT_Int s = 1; + FT_Long d; + + +- s = 1; +- if ( a < 0 ) { a = -a; s = -1; } +- if ( b < 0 ) { b = -b; s = -s; } +- if ( c < 0 ) { c = -c; s = -s; } ++ FT_MOVE_SIGN( a, s ); ++ FT_MOVE_SIGN( b, s ); ++ FT_MOVE_SIGN( c, s ); + + d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c + : 0x7FFFFFFFL ); +@@ -185,14 +198,13 @@ + FT_Long b, + FT_Long c ) + { +- FT_Int s; ++ FT_Int s = 1; + FT_Long d; + + +- s = 1; +- if ( a < 0 ) { a = -a; s = -1; } +- if ( b < 0 ) { b = -b; s = -s; } +- if ( c < 0 ) { c = -c; s = -s; } ++ FT_MOVE_SIGN( a, s ); ++ FT_MOVE_SIGN( b, s ); ++ FT_MOVE_SIGN( c, s ); + + d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c + : 0x7FFFFFFFL ); +@@ -217,17 +229,8 @@ + FT_Long c; + + +- if ( a < 0 ) +- { +- a = -a; +- s = -1; +- } +- +- if ( b < 0 ) +- { +- b = -b; +- s = -s; +- } ++ FT_MOVE_SIGN( a, s ); ++ FT_MOVE_SIGN( b, s ); + + c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 ); + +@@ -243,30 +246,17 @@ + FT_DivFix( FT_Long a, + FT_Long b ) + { +- FT_Int32 s; +- FT_UInt32 q; ++ FT_Int s = 1; ++ FT_Long q; + + +- s = 1; +- if ( a < 0 ) +- { +- a = -a; +- s = -1; +- } +- if ( b < 0 ) +- { +- b = -b; +- s = -s; +- } ++ FT_MOVE_SIGN( a, s ); ++ FT_MOVE_SIGN( b, s ); + +- if ( b == 0 ) +- /* check for division by 0 */ +- q = 0x7FFFFFFFL; +- else +- /* compute result directly */ +- q = (FT_UInt32)( ( ( (FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b ); ++ q = (FT_Long)( b > 0 ? ( ( (FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b ++ : 0x7FFFFFFFL ); + +- return ( s < 0 ? -(FT_Long)q : (FT_Long)q ); ++ return ( s < 0 ? -q : q ); + } + + +@@ -314,25 +304,30 @@ + FT_Int i; + + +- q = 0; +- r = hi; +- +- if ( r >= y ) ++ if ( hi >= y ) + return (FT_UInt32)0x7FFFFFFFL; + +- i = 32; ++ /* We shift as many bits as we can into the high register, perform */ ++ /* 32-bit division with modulo there, then work through the remaining */ ++ /* bits with long division. This optimization is especially noticeable */ ++ /* for smaller dividends that barely use the high register. */ ++ ++ i = 31 - FT_MSB( hi ); ++ r = ( hi << i ) | ( lo >> ( 32 - i ) ); lo <<= i; /* left 64-bit shift */ ++ q = r / y; ++ r -= q * y; /* remainder */ ++ ++ i = 32 - i; /* bits remaining in low register */ + do + { +- r <<= 1; + q <<= 1; +- r |= lo >> 31; ++ r = ( r << 1 ) | ( lo >> 31 ); lo <<= 1; + + if ( r >= y ) + { + r -= y; + q |= 1; + } +- lo <<= 1; + } while ( --i ); + + return q; +@@ -344,7 +339,7 @@ + FT_Int64* y, + FT_Int64 *z ) + { +- register FT_UInt32 lo, hi; ++ FT_UInt32 lo, hi; + + + lo = x->lo + y->lo; +@@ -355,58 +350,93 @@ + } + + +- /* documentation is in freetype.h */ +- +- /* The FT_MulDiv function has been optimized thanks to ideas from */ +- /* Graham Asher. The trick is to optimize computation when everything */ +- /* fits within 32-bits (a rather common case). */ ++ /* The FT_MulDiv function has been optimized thanks to ideas from */ ++ /* Graham Asher and Alexei Podtelezhnikov. The trick is to optimize */ ++ /* a rather common case when everything fits within 32-bits. */ ++ /* */ ++ /* We compute 'a*b+c/2', then divide it by 'c' (all positive values). */ ++ /* */ ++ /* The product of two positive numbers never exceeds the square of */ ++ /* its mean values. Therefore, we always avoid the overflow by */ ++ /* imposing */ ++ /* */ ++ /* (a + b) / 2 <= sqrt(X - c/2) , */ + /* */ +- /* we compute 'a*b+c/2', then divide it by 'c'. (positive values) */ ++ /* where X = 2^32 - 1, the maximum unsigned 32-bit value, and using */ ++ /* unsigned arithmetic. Now we replace `sqrt' with a linear function */ ++ /* that is smaller or equal for all values of c in the interval */ ++ /* [0;X/2]; it should be equal to sqrt(X) and sqrt(3X/4) at the */ ++ /* endpoints. Substituting the linear solution and explicit numbers */ ++ /* we get */ + /* */ +- /* 46340 is FLOOR(SQRT(2^31-1)). */ ++ /* a + b <= 131071.99 - c / 122291.84 . */ + /* */ +- /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */ ++ /* In practice, we should use a faster and even stronger inequality */ + /* */ +- /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */ ++ /* a + b <= 131071 - (c >> 16) */ + /* */ +- /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */ ++ /* or, alternatively, */ + /* */ +- /* and 2*0x157F0 = 176096 */ ++ /* a + b <= 129894 - (c >> 17) . */ + /* */ ++ /* FT_MulFix, on the other hand, is optimized for a small value of */ ++ /* the first argument, when the second argument can be much larger. */ ++ /* This can be achieved by scaling the second argument and the limit */ ++ /* in the above inequalities. For example, */ ++ /* */ ++ /* a + (b >> 8) <= (131071 >> 4) */ ++ /* */ ++ /* covers the practical range of use. The actual test below is a bit */ ++ /* tighter to avoid the border case overflows. */ ++ /* */ ++ /* In the case of FT_DivFix, the exact overflow check */ ++ /* */ ++ /* a << 16 <= X - c/2 */ ++ /* */ ++ /* is scaled down by 2^16 and we use */ ++ /* */ ++ /* a <= 65535 - (c >> 17) . */ ++ ++ /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Long ) + FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ) + { +- long s; ++ FT_Int s = 1; + + + /* XXX: this function does not allow 64-bit arguments */ + if ( a == 0 || b == c ) + return a; + +- s = a; a = FT_ABS( a ); +- s ^= b; b = FT_ABS( b ); +- s ^= c; c = FT_ABS( c ); ++ FT_MOVE_SIGN( a, s ); ++ FT_MOVE_SIGN( b, s ); ++ FT_MOVE_SIGN( c, s ); + +- if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 ) +- a = ( a * b + ( c >> 1 ) ) / c; ++ if ( c == 0 ) ++ a = 0x7FFFFFFFL; ++ ++ else if ( (FT_ULong)a + b <= 129894UL - ( c >> 17 ) ) ++ a = ( (FT_ULong)a * b + ( c >> 1 ) ) / c; + +- else if ( (FT_Int32)c > 0 ) ++ else + { + FT_Int64 temp, temp2; + + +- ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp ); ++ ft_multo64( a, b, &temp ); + + temp2.hi = 0; +- temp2.lo = (FT_UInt32)(c >> 1); ++ temp2.lo = c >> 1; ++ + FT_Add64( &temp, &temp2, &temp ); +- a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c ); ++ ++ /* last attempt to ditch long division */ ++ a = temp.hi == 0 ? temp.lo / c ++ : ft_div64by32( temp.hi, temp.lo, c ); + } +- else +- a = 0x7FFFFFFFL; + + return ( s < 0 ? -a : a ); + } +@@ -417,29 +447,33 @@ + FT_Long b, + FT_Long c ) + { +- long s; ++ FT_Int s = 1; + + + if ( a == 0 || b == c ) + return a; + +- s = a; a = FT_ABS( a ); +- s ^= b; b = FT_ABS( b ); +- s ^= c; c = FT_ABS( c ); ++ FT_MOVE_SIGN( a, s ); ++ FT_MOVE_SIGN( b, s ); ++ FT_MOVE_SIGN( c, s ); + +- if ( a <= 46340L && b <= 46340L && c > 0 ) +- a = a * b / c; ++ if ( c == 0 ) ++ a = 0x7FFFFFFFL; ++ ++ else if ( (FT_ULong)a + b <= 131071UL ) ++ a = (FT_ULong)a * b / c; + +- else if ( (FT_Int32)c > 0 ) ++ else + { + FT_Int64 temp; + + +- ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp ); +- a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c ); ++ 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 ); + } +- else +- a = 0x7FFFFFFFL; + + return ( s < 0 ? -a : a ); + } +@@ -497,7 +531,7 @@ + ua = (FT_ULong)a; + ub = (FT_ULong)b; + +- if ( ua <= 2048 && ub <= 1048576L ) ++ if ( ua + ( ub >> 8 ) <= 8190UL ) + ua = ( ua * ub + 0x8000U ) >> 16; + else + { +@@ -515,20 +549,20 @@ + + #else /* 0 */ + +- FT_Long s; ++ FT_Int s = 1; + FT_ULong ua, ub; + + + if ( a == 0 || b == 0x10000L ) + return a; + +- s = a; a = FT_ABS( a ); +- s ^= b; b = FT_ABS( b ); ++ FT_MOVE_SIGN( a, s ); ++ FT_MOVE_SIGN( b, s ); + + ua = (FT_ULong)a; + ub = (FT_ULong)b; + +- if ( ua <= 2048 && ub <= 1048576L ) ++ if ( ua + ( ub >> 8 ) <= 8190UL ) + ua = ( ua * ub + 0x8000UL ) >> 16; + else + { +@@ -552,23 +586,24 @@ + FT_DivFix( FT_Long a, + FT_Long b ) + { +- FT_Int32 s; +- FT_UInt32 q; ++ FT_Int s = 1; ++ FT_Long q; + + + /* XXX: this function does not allow 64-bit arguments */ +- s = (FT_Int32)a; a = FT_ABS( a ); +- s ^= (FT_Int32)b; b = FT_ABS( b ); + +- if ( (FT_UInt32)b == 0 ) ++ FT_MOVE_SIGN( a, s ); ++ FT_MOVE_SIGN( b, s ); ++ ++ if ( b == 0 ) + { + /* check for division by 0 */ +- q = (FT_UInt32)0x7FFFFFFFL; ++ q = 0x7FFFFFFFL; + } +- else if ( ( a >> 16 ) == 0 ) ++ else if ( a <= 65535L - ( b >> 17 ) ) + { + /* compute result directly */ +- q = (FT_UInt32)( ( (FT_ULong)a << 16 ) + ( b >> 1 ) ) / (FT_UInt32)b; ++ q = (FT_Long)( ( ( (FT_ULong)a << 16 ) + ( b >> 1 ) ) / b ); + } + else + { +@@ -576,138 +611,18 @@ + FT_Int64 temp, temp2; + + +- temp.hi = (FT_Int32)( a >> 16 ); +- temp.lo = (FT_UInt32)a << 16; ++ temp.hi = a >> 16; ++ temp.lo = a << 16; + temp2.hi = 0; +- temp2.lo = (FT_UInt32)( b >> 1 ); +- FT_Add64( &temp, &temp2, &temp ); +- q = ft_div64by32( temp.hi, temp.lo, (FT_Int32)b ); +- } +- +- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); +- } ++ temp2.lo = b >> 1; + +- +-#if 0 +- +- /* documentation is in ftcalc.h */ +- +- FT_EXPORT_DEF( void ) +- FT_MulTo64( FT_Int32 x, +- FT_Int32 y, +- FT_Int64 *z ) +- { +- FT_Int32 s; +- +- +- s = x; x = FT_ABS( x ); +- s ^= y; y = FT_ABS( y ); +- +- ft_multo64( x, y, z ); +- +- if ( s < 0 ) +- { +- z->lo = (FT_UInt32)-(FT_Int32)z->lo; +- z->hi = ~z->hi + !( z->lo ); +- } +- } +- +- +- /* apparently, the second version of this code is not compiled correctly */ +- /* on Mac machines with the MPW C compiler.. tsk, tsk, tsk... */ +- +-#if 1 +- +- FT_EXPORT_DEF( FT_Int32 ) +- FT_Div64by32( FT_Int64* x, +- FT_Int32 y ) +- { +- FT_Int32 s; +- FT_UInt32 q, r, i, lo; +- +- +- s = x->hi; +- if ( s < 0 ) +- { +- x->lo = (FT_UInt32)-(FT_Int32)x->lo; +- x->hi = ~x->hi + !x->lo; +- } +- s ^= y; y = FT_ABS( y ); +- +- /* Shortcut */ +- if ( x->hi == 0 ) +- { +- if ( y > 0 ) +- q = x->lo / y; +- else +- q = 0x7FFFFFFFL; +- +- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); +- } +- +- r = x->hi; +- lo = x->lo; +- +- if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */ +- return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL ); +- /* Return Max/Min Int32 if division overflow. */ +- /* This includes division by zero! */ +- q = 0; +- for ( i = 0; i < 32; i++ ) +- { +- r <<= 1; +- q <<= 1; +- r |= lo >> 31; +- +- if ( r >= (FT_UInt32)y ) +- { +- r -= y; +- q |= 1; +- } +- lo <<= 1; +- } +- +- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); +- } +- +-#else /* 0 */ +- +- FT_EXPORT_DEF( FT_Int32 ) +- FT_Div64by32( FT_Int64* x, +- FT_Int32 y ) +- { +- FT_Int32 s; +- FT_UInt32 q; +- +- +- s = x->hi; +- if ( s < 0 ) +- { +- x->lo = (FT_UInt32)-(FT_Int32)x->lo; +- x->hi = ~x->hi + !x->lo; +- } +- s ^= y; y = FT_ABS( y ); +- +- /* Shortcut */ +- if ( x->hi == 0 ) +- { +- if ( y > 0 ) +- q = ( x->lo + ( y >> 1 ) ) / y; +- else +- q = 0x7FFFFFFFL; +- +- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); ++ FT_Add64( &temp, &temp2, &temp ); ++ q = (FT_Long)ft_div64by32( temp.hi, temp.lo, b ); + } + +- q = ft_div64by32( x->hi, x->lo, y ); +- +- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); ++ return ( s < 0 ? -q : q ); + } + +-#endif /* 0 */ +- +-#endif /* 0 */ +- + + #endif /* FT_LONG64 */ + +diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c +index 852fb32..4aefb68 100644 +--- a/src/base/ftlcdfil.c ++++ b/src/base/ftlcdfil.c +@@ -4,7 +4,7 @@ + /* */ + /* FreeType API for color filtering of subpixel bitmap glyphs (body). */ + /* */ +-/* Copyright 2006, 2008-2010, 2013 by */ ++/* Copyright 2006, 2008-2010, 2013, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -46,9 +46,12 @@ + FT_Byte* line = bitmap->buffer; + + ++ /* `fir' and `pix' must be at least 32 bit wide, since the sum of */ ++ /* the values in `weights' can exceed 0xFF */ ++ + for ( ; height > 0; height--, line += bitmap->pitch ) + { +- FT_UInt fir[5]; ++ FT_UInt fir[4]; /* below, `pix' is used as the 5th element */ + FT_UInt val1, xx; + + +@@ -57,7 +60,6 @@ + fir[1] = weights[3] * val1; + fir[2] = weights[4] * val1; + fir[3] = 0; +- fir[4] = 0; + + val1 = line[1]; + fir[0] += weights[1] * val1; +@@ -78,7 +80,7 @@ + fir[3] = weights[4] * val; + + pix >>= 8; +- pix |= -( pix >> 8 ); ++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); + line[xx - 2] = (FT_Byte)pix; + } + +@@ -87,11 +89,11 @@ + + + pix = fir[0] >> 8; +- pix |= -( pix >> 8 ); ++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); + line[xx - 2] = (FT_Byte)pix; + + pix = fir[1] >> 8; +- pix |= -( pix >> 8 ); ++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); + line[xx - 1] = (FT_Byte)pix; + } + } +@@ -107,7 +109,7 @@ + for ( ; width > 0; width--, column++ ) + { + FT_Byte* col = column; +- FT_UInt fir[5]; ++ FT_UInt fir[4]; /* below, `pix' is used as the 5th element */ + FT_UInt val1, yy; + + +@@ -116,7 +118,6 @@ + fir[1] = weights[3] * val1; + fir[2] = weights[4] * val1; + fir[3] = 0; +- fir[4] = 0; + col += pitch; + + val1 = col[0]; +@@ -139,7 +140,7 @@ + fir[3] = weights[4] * val; + + pix >>= 8; +- pix |= -( pix >> 8 ); ++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); + col[-2 * pitch] = (FT_Byte)pix; + col += pitch; + } +@@ -149,11 +150,11 @@ + + + pix = fir[0] >> 8; +- pix |= -( pix >> 8 ); ++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); + col[-2 * pitch] = (FT_Byte)pix; + + pix = fir[1] >> 8; +- pix |= -( pix >> 8 ); ++ pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); + col[-pitch] = (FT_Byte)pix; + } + } +diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c +index 6f32336..cc56105 100644 +--- a/src/base/ftobjs.c ++++ b/src/base/ftobjs.c +@@ -4881,6 +4881,8 @@ + *p_arg1 = subg->arg1; + *p_arg2 = subg->arg2; + *p_transform = subg->transform; ++ ++ error = FT_Err_Ok; + } + + return error; +diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c +index 4a39dcd..632b6d2 100644 +--- a/src/base/ftoutln.c ++++ b/src/base/ftoutln.c +@@ -1045,6 +1045,10 @@ + + FT_Outline_Get_CBox( outline, &cbox ); + ++ /* Handle collapsed outlines to avoid undefined FT_MSB. */ ++ if ( cbox.xMin == cbox.xMax || cbox.yMin == cbox.yMax ) ++ return FT_ORIENTATION_NONE; ++ + xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14; + xshift = FT_MAX( xshift, 0 ); + +diff --git a/src/base/fttrigon.c b/src/base/fttrigon.c +index 4ffdcb7..e3ce8a6 100644 +--- a/src/base/fttrigon.c ++++ b/src/base/fttrigon.c +@@ -111,6 +111,7 @@ + #endif /* !FT_LONG64 */ + + ++ /* undefined and never called for zero vector */ + static FT_Int + ft_trig_prenorm( FT_Vector* vec ) + { +diff --git a/src/base/ftutil.c b/src/base/ftutil.c +index 879d027..9f37189 100644 +--- a/src/base/ftutil.c ++++ b/src/base/ftutil.c +@@ -411,26 +411,4 @@ + } + + +- FT_BASE_DEF( FT_UInt32 ) +- ft_highpow2( FT_UInt32 value ) +- { +- FT_UInt32 value2; +- +- +- /* +- * We simply clear the lowest bit in each iteration. When +- * we reach 0, we know that the previous value was our result. +- */ +- for ( ;; ) +- { +- value2 = value & (value - 1); /* clear lowest bit */ +- if ( value2 == 0 ) +- break; +- +- value = value2; +- } +- return value; +- } +- +- + /* END */ +diff --git a/src/bdf/bdfdrivr.c b/src/bdf/bdfdrivr.c +index 5a1c296..d7649ab 100644 +--- a/src/bdf/bdfdrivr.c ++++ b/src/bdf/bdfdrivr.c +@@ -182,7 +182,7 @@ THE SOFTWARE. + } + + +- FT_CALLBACK_TABLE_DEF ++ static + const FT_CMap_ClassRec bdf_cmap_class = + { + sizeof ( BDF_CMapRec ), +diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c +index 84d336d..01be88c 100644 +--- a/src/cache/ftcbasic.c ++++ b/src/cache/ftcbasic.c +@@ -4,7 +4,7 @@ + /* */ + /* The FreeType basic cache interface (body). */ + /* */ +-/* Copyright 2003-2007, 2009-2011, 2013 by */ ++/* Copyright 2003-2007, 2009-2011, 2013, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -229,7 +229,7 @@ + * + */ + +- FT_CALLBACK_TABLE_DEF ++ static + const FTC_IFamilyClassRec ftc_basic_image_family_class = + { + { +@@ -243,7 +243,7 @@ + }; + + +- FT_CALLBACK_TABLE_DEF ++ static + const FTC_GCacheClassRec ftc_basic_image_cache_class = + { + { +@@ -415,7 +415,7 @@ + * + */ + +- FT_CALLBACK_TABLE_DEF ++ static + const FTC_SFamilyClassRec ftc_basic_sbit_family_class = + { + { +@@ -430,7 +430,7 @@ + }; + + +- FT_CALLBACK_TABLE_DEF ++ static + const FTC_GCacheClassRec ftc_basic_sbit_cache_class = + { + { +diff --git a/src/cache/ftccmap.c b/src/cache/ftccmap.c +index 848349b..b2e9609 100644 +--- a/src/cache/ftccmap.c ++++ b/src/cache/ftccmap.c +@@ -4,7 +4,7 @@ + /* */ + /* FreeType CharMap cache (body) */ + /* */ +-/* Copyright 2000-2013 by */ ++/* Copyright 2000-2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -202,7 +202,7 @@ + /*************************************************************************/ + + +- FT_CALLBACK_TABLE_DEF ++ static + const FTC_CacheClassRec ftc_cmap_cache_class = + { + ftc_cmap_node_new, +diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c +index 4eb2c5b..a65f94d 100644 +--- a/src/cache/ftcmanag.c ++++ b/src/cache/ftcmanag.c +@@ -4,7 +4,7 @@ + /* */ + /* FreeType Cache Manager (body). */ + /* */ +-/* Copyright 2000-2006, 2008-2010, 2013 by */ ++/* Copyright 2000-2006, 2008-2010, 2013, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -151,7 +151,7 @@ + } + + +- FT_CALLBACK_TABLE_DEF ++ static + const FTC_MruListClassRec ftc_size_list_class = + { + sizeof ( FTC_SizeNodeRec ), +@@ -290,7 +290,7 @@ + } + + +- FT_CALLBACK_TABLE_DEF ++ static + const FTC_MruListClassRec ftc_face_list_class = + { + sizeof ( FTC_FaceNodeRec), +diff --git a/src/cff/cf2font.c b/src/cff/cf2font.c +index 6e99dc2..3d2c22a 100644 +--- a/src/cff/cf2font.c ++++ b/src/cff/cf2font.c +@@ -105,6 +105,7 @@ + /* adjusting for emRatio converts darkenAmount to character */ + /* space (font units). */ + CF2_Fixed stemWidthPer1000, scaledStem; ++ FT_Int logBase2; + + + *darkenAmount = 0; +@@ -131,26 +132,33 @@ + /* convert from true character space to 1000 unit character space; */ + /* add synthetic emboldening effect */ + +- /* we have to assure that the computation of `scaledStem' */ +- /* and `stemWidthPer1000' don't overflow */ ++ /* `stemWidthPer1000' will not overflow for a legitimate font */ + + stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio ); + +- if ( emRatio > CF2_FIXED_ONE && +- stemWidthPer1000 <= ( stemWidth + boldenAmount ) ) +- { +- stemWidthPer1000 = 0; /* to pacify compiler */ +- scaledStem = cf2_intToFixed( x4 ); +- } ++ /* `scaledStem' can easily overflow, so we must clamp its maximum */ ++ /* value; the test doesn't need to be precise, but must be */ ++ /* conservative. The clamp value (default 2333) where */ ++ /* `darkenAmount' is zero is well below the overflow value of */ ++ /* 32767. */ ++ /* */ ++ /* FT_MSB computes the integer part of the base 2 logarithm. The */ ++ /* number of bits for the product is 1 or 2 more than the sum of */ ++ /* logarithms; remembering that the 16 lowest bits of the fraction */ ++ /* are dropped this is correct to within a factor of almost 4. */ ++ /* For example, 0x80.0000 * 0x80.0000 = 0x4000.0000 is 23+23 and */ ++ /* is flagged as possible overflow because 0xff.ffff * 0xff.ffff = */ ++ /* 0xffff.fe00 is also 23+23. */ ++ ++ logBase2 = FT_MSB( (FT_UInt32)stemWidthPer1000 ) + ++ FT_MSB( (FT_UInt32)ppem ); ++ ++ if ( logBase2 >= 46 ) ++ /* possible overflow */ ++ scaledStem = cf2_intToFixed( x4 ); + else +- { + scaledStem = FT_MulFix( stemWidthPer1000, ppem ); + +- if ( ppem > CF2_FIXED_ONE && +- scaledStem <= stemWidthPer1000 ) +- scaledStem = cf2_intToFixed( x4 ); +- } +- + /* now apply the darkening parameters */ + + if ( scaledStem < cf2_intToFixed( x1 ) ) +diff --git a/src/cff/cf2hints.c b/src/cff/cf2hints.c +index 5853d77..81049f4 100644 +--- a/src/cff/cf2hints.c ++++ b/src/cff/cf2hints.c +@@ -1560,7 +1560,7 @@ + { + /* -y */ + *x = -glyphpath->xOffset; +- *y = glyphpath->xOffset; ++ *y = glyphpath->yOffset; + } + else + { +diff --git a/src/gzip/inftrees.c b/src/gzip/inftrees.c +index ef53652..56f52b1 100644 +--- a/src/gzip/inftrees.c ++++ b/src/gzip/inftrees.c +@@ -115,16 +115,16 @@ uIntf *v /* working area: values in order of bit length */ + uInt f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ +- register uInt i; /* counter, current code */ +- register uInt j; /* counter */ +- register int k; /* number of bits in current code */ ++ uInt i; /* counter, current code */ ++ uInt j; /* counter */ ++ int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ +- register uIntf *p; /* pointer into c[], b[], or v[] */ ++ uIntf *p; /* pointer into c[], b[], or v[] */ + inflate_huft *q; /* points to current table */ + struct inflate_huft_s r; /* table entry for structure assignment */ + inflate_huft *u[BMAX]; /* table stack */ +- register int w; /* bits before this table == (l * h) */ ++ int w; /* bits before this table == (l * h) */ + uInt x[BMAX+1]; /* bit offsets, then code stack */ + uIntf *xp; /* pointer into x */ + int y; /* number of dummy codes added */ +diff --git a/src/pcf/pcfdrivr.c b/src/pcf/pcfdrivr.c +index 748cbca..5183f6f 100644 +--- a/src/pcf/pcfdrivr.c ++++ b/src/pcf/pcfdrivr.c +@@ -2,7 +2,7 @@ + + FreeType font driver for pcf files + +- Copyright (C) 2000-2004, 2006-2011, 2013 by ++ Copyright (C) 2000-2004, 2006-2011, 2013, 2014 by + Francesco Zappa Nardelli + + Permission is hereby granted, free of charge, to any person obtaining a copy +@@ -189,7 +189,7 @@ THE SOFTWARE. + } + + +- FT_CALLBACK_TABLE_DEF ++ static + const FT_CMap_ClassRec pcf_cmap_class = + { + sizeof ( PCF_CMapRec ), +diff --git a/src/pfr/pfrdrivr.c b/src/pfr/pfrdrivr.c +index 4c43947..188aa0d 100644 +--- a/src/pfr/pfrdrivr.c ++++ b/src/pfr/pfrdrivr.c +@@ -4,7 +4,7 @@ + /* */ + /* FreeType PFR driver interface (body). */ + /* */ +-/* Copyright 2002-2004, 2006, 2008, 2010, 2011, 2013 by */ ++/* Copyright 2002-2004, 2006, 2008, 2010, 2011, 2013, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -134,7 +134,7 @@ + } + + +- FT_CALLBACK_TABLE_DEF ++ static + const FT_Service_PfrMetricsRec pfr_metrics_service_rec = + { + pfr_get_metrics, +diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c +index 194d2df..0c89242 100644 +--- a/src/pfr/pfrobjs.c ++++ b/src/pfr/pfrobjs.c +@@ -4,7 +4,7 @@ + /* */ + /* FreeType PFR object methods (body). */ + /* */ +-/* Copyright 2002-2008, 2010-2011, 2013 by */ ++/* Copyright 2002-2008, 2010-2011, 2013, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -23,6 +23,7 @@ + #include "pfrsbit.h" + #include FT_OUTLINE_H + #include FT_INTERNAL_DEBUG_H ++#include FT_INTERNAL_CALC_H + #include FT_TRUETYPE_IDS_H + + #include "pfrerror.h" +@@ -515,7 +516,7 @@ + { + FT_UInt count = item->pair_count; + FT_UInt size = item->pair_size; +- FT_UInt power = (FT_UInt)ft_highpow2( (FT_UInt32)count ); ++ FT_UInt power = 1 << FT_MSB( count ); + FT_UInt probe = power * size; + FT_UInt extra = count - power; + FT_Byte* base = stream->cursor; +diff --git a/src/psaux/psconv.c b/src/psaux/psconv.c +index d0d8861..7792a62 100644 +--- a/src/psaux/psconv.c ++++ b/src/psaux/psconv.c +@@ -250,7 +250,8 @@ + if ( c < 0 || c >= 10 ) + break; + +- if ( decimal < 0xCCCCCCCL ) ++ /* only add digit if we don't overflow */ ++ if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL ) + { + decimal = decimal * 10 + c; + +diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c +index ddecc80..abbecb7 100644 +--- a/src/raster/ftraster.c ++++ b/src/raster/ftraster.c +@@ -2284,6 +2284,8 @@ + Long e1, e2; + Byte* target; + ++ Int dropOutControl = left->flags & 7; ++ + FT_UNUSED( y ); + FT_UNUSED( left ); + FT_UNUSED( right ); +@@ -2293,7 +2295,8 @@ + + e1 = TRUNC( CEILING( x1 ) ); + +- if ( x2 - x1 - ras.precision <= ras.precision_jitter ) ++ if ( dropOutControl != 2 && ++ x2 - x1 - ras.precision <= ras.precision_jitter ) + e2 = e1; + else + e2 = TRUNC( FLOOR( x2 ) ); +diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c +index 878de1f..9afbe5a 100644 +--- a/src/sfnt/pngshim.c ++++ b/src/sfnt/pngshim.c +@@ -4,7 +4,7 @@ + /* */ + /* PNG Bitmap glyph support. */ + /* */ +-/* Copyright 2013 by Google, Inc. */ ++/* Copyright 2013, 2014 by Google, Inc. */ + /* Written by Stuart Gill and Behdad Esfahbod. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -129,7 +129,7 @@ + + *error = FT_THROW( Out_Of_Memory ); + #ifdef PNG_SETJMP_SUPPORTED +- longjmp( png_jmpbuf( png ), 1 ); ++ ft_longjmp( png_jmpbuf( png ), 1 ); + #endif + /* if we get here, then we have no choice but to abort ... */ + } +diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c +index a31c77c..44aa467 100644 +--- a/src/sfnt/sfobjs.c ++++ b/src/sfnt/sfobjs.c +@@ -4,7 +4,7 @@ + /* */ + /* SFNT object management (base). */ + /* */ +-/* Copyright 1996-2008, 2010-2013 by */ ++/* Copyright 1996-2008, 2010-2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -348,29 +348,22 @@ + } + + +-#define WRITE_BYTE( p, v ) \ +- do \ +- { \ +- *(p)++ = (v) >> 0; \ +- \ ++#define WRITE_USHORT( p, v ) \ ++ do \ ++ { \ ++ *(p)++ = (FT_Byte)( (v) >> 8 ); \ ++ *(p)++ = (FT_Byte)( (v) >> 0 ); \ ++ \ + } while ( 0 ) + +-#define WRITE_USHORT( p, v ) \ +- do \ +- { \ +- *(p)++ = (v) >> 8; \ +- *(p)++ = (v) >> 0; \ +- \ +- } while ( 0 ) +- +-#define WRITE_ULONG( p, v ) \ +- do \ +- { \ +- *(p)++ = (v) >> 24; \ +- *(p)++ = (v) >> 16; \ +- *(p)++ = (v) >> 8; \ +- *(p)++ = (v) >> 0; \ +- \ ++#define WRITE_ULONG( p, v ) \ ++ do \ ++ { \ ++ *(p)++ = (FT_Byte)( (v) >> 24 ); \ ++ *(p)++ = (FT_Byte)( (v) >> 16 ); \ ++ *(p)++ = (FT_Byte)( (v) >> 8 ); \ ++ *(p)++ = (FT_Byte)( (v) >> 0 ); \ ++ \ + } while ( 0 ) + + +@@ -661,6 +654,8 @@ + } + else + { ++#ifdef FT_CONFIG_OPTION_USE_ZLIB ++ + /* Uncompress with zlib. */ + FT_ULong output_len = table->OrigLength; + +@@ -675,6 +670,13 @@ + error = FT_THROW( Invalid_Table ); + goto Exit; + } ++ ++#else /* !FT_CONFIG_OPTION_USE_ZLIB */ ++ ++ error = FT_THROW( Unimplemented_Feature ); ++ goto Exit; ++ ++#endif /* !FT_CONFIG_OPTION_USE_ZLIB */ + } + + FT_FRAME_EXIT(); +@@ -717,7 +719,6 @@ + } + + +-#undef WRITE_BYTE + #undef WRITE_USHORT + #undef WRITE_ULONG + +diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c +index c717f5f..f9acf5d 100644 +--- a/src/sfnt/ttcmap.c ++++ b/src/sfnt/ttcmap.c +@@ -3473,10 +3473,9 @@ + /* only recognize format 0 */ + if ( TT_NEXT_USHORT( p ) != 0 ) + { +- p -= 2; + FT_ERROR(( "tt_face_build_cmaps:" + " unsupported `cmap' table format = %d\n", +- TT_PEEK_USHORT( p ) )); ++ TT_PEEK_USHORT( p - 2) )); + return FT_THROW( Invalid_Table ); + } + +diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c +index 47a85c0..99d8005 100644 +--- a/src/sfnt/ttpost.c ++++ b/src/sfnt/ttpost.c +@@ -5,7 +5,7 @@ + /* Postcript name table processing for TrueType and OpenType fonts */ + /* (body). */ + /* */ +-/* Copyright 1996-2003, 2006-2010, 2013 by */ ++/* Copyright 1996-2003, 2006-2010, 2013, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -64,12 +64,12 @@ + + #define MAC_NAME( x ) ( (FT_String*)tt_post_default_names[x] ) + +- /* the 258 default Mac PS glyph names */ ++ /* the 258 default Mac PS glyph names; see file `tools/glnames.py' */ + + static const FT_String* const tt_post_default_names[258] = + { + /* 0 */ +- ".notdef", ".null", "CR", "space", "exclam", ++ ".notdef", ".null", "nonmarkingreturn", "space", "exclam", + "quotedbl", "numbersign", "dollar", "percent", "ampersand", + /* 10 */ + "quotesingle", "parenleft", "parenright", "asterisk", "plus", +@@ -120,7 +120,7 @@ + "ae", "oslash", "questiondown", "exclamdown", "logicalnot", + "radical", "florin", "approxequal", "Delta", "guillemotleft", + /* 170 */ +- "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde", ++ "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde", + "Otilde", "OE", "oe", "endash", "emdash", + /* 180 */ + "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", +@@ -144,8 +144,8 @@ + "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", + "onequarter", "threequarters", "franc", "Gbreve", "gbreve", + /* 250 */ +- "Idot", "Scedilla", "scedilla", "Cacute", "cacute", +- "Ccaron", "ccaron", "dmacron", ++ "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", ++ "Ccaron", "ccaron", "dcroat", + }; + + +diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c +index 8ff7b9d..180d559 100644 +--- a/src/sfnt/ttsbit.c ++++ b/src/sfnt/ttsbit.c +@@ -256,7 +256,8 @@ + case TT_SBIT_TABLE_TYPE_SBIX: + { + FT_Stream stream = face->root.stream; +- FT_UInt offset, ppem, resolution, upem; ++ FT_UInt offset, upem; ++ FT_UShort ppem, resolution; + TT_HoriHeader *hori; + FT_ULong table_size; + +@@ -800,12 +801,12 @@ + FT_Error error = FT_Err_Ok; + FT_UInt num_components, nn; + +- FT_Char horiBearingX = decoder->metrics->horiBearingX; +- FT_Char horiBearingY = decoder->metrics->horiBearingY; +- FT_Byte horiAdvance = decoder->metrics->horiAdvance; +- FT_Char vertBearingX = decoder->metrics->vertBearingX; +- FT_Char vertBearingY = decoder->metrics->vertBearingY; +- FT_Byte vertAdvance = decoder->metrics->vertAdvance; ++ FT_Char horiBearingX = (FT_Char)decoder->metrics->horiBearingX; ++ FT_Char horiBearingY = (FT_Char)decoder->metrics->horiBearingY; ++ FT_Byte horiAdvance = (FT_Byte)decoder->metrics->horiAdvance; ++ FT_Char vertBearingX = (FT_Char)decoder->metrics->vertBearingX; ++ FT_Char vertBearingY = (FT_Char)decoder->metrics->vertBearingY; ++ FT_Byte vertAdvance = (FT_Byte)decoder->metrics->vertAdvance; + + + if ( p + 2 > limit ) +@@ -1352,10 +1353,11 @@ + + tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance ); + +- metrics->horiBearingX = originOffsetX; +- metrics->horiBearingY = -originOffsetY + metrics->height; +- metrics->horiAdvance = aadvance * face->root.size->metrics.x_ppem / +- face->header.Units_Per_EM; ++ metrics->horiBearingX = (FT_Short)originOffsetX; ++ metrics->horiBearingY = (FT_Short)( -originOffsetY + metrics->height ); ++ metrics->horiAdvance = (FT_Short)( aadvance * ++ face->root.size->metrics.x_ppem / ++ face->header.Units_Per_EM ); + } + + return error; +diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c +index 425911a..27be966 100644 +--- a/src/smooth/ftgrays.c ++++ b/src/smooth/ftgrays.c +@@ -98,6 +98,9 @@ + #define FT_ERR_XCAT( x, y ) x ## y + #define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y ) + ++#define FT_BEGIN_STMNT do { ++#define FT_END_STMNT } while ( 0 ) ++ + + /* define this to dump debugging information */ + /* #define FT_DEBUG_LEVEL_TRACE */ +diff --git a/src/tools/afblue.pl b/src/tools/afblue.pl +index 58aa2a0..60fe696 100644 +--- a/src/tools/afblue.pl ++++ b/src/tools/afblue.pl +@@ -63,8 +63,8 @@ my $enum_element_re = qr/ ^ \s* ( [A-Za-z0-9_]+ ) \s* $ /x; + # '#' <preprocessor directive> '\n' + my $preprocessor_re = qr/ ^ \# /x; + +-# '/' '/' <comment> '\n' +-my $comment_re = qr| ^ // |x; ++# [<ws>] '/' '/' <comment> '\n' ++my $comment_re = qr| ^ \s* // |x; + + # empty line + my $whitespace_only_re = qr/ ^ \s* $ /x; +@@ -159,6 +159,9 @@ sub convert_ascii_chars + # A series of ASCII characters in the printable range. + my $s = shift; + ++ # We ignore spaces. ++ $s =~ s/ //g; ++ + my $count = $s =~ s/\G(.)/'$1', /g; + $curr_offset += $count; + $curr_elem_size += $count; +diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c +index 5f676a2..ff2b339 100644 +--- a/src/truetype/ttgload.c ++++ b/src/truetype/ttgload.c +@@ -4,7 +4,7 @@ + /* */ + /* TrueType Glyph Loader (body). */ + /* */ +-/* Copyright 1996-2013 */ ++/* Copyright 1996-2014 */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -99,13 +99,13 @@ + + else if ( face->os2.version != 0xFFFFU ) + { +- *tsb = face->os2.sTypoAscender - yMax; ++ *tsb = (FT_Short)( face->os2.sTypoAscender - yMax ); + *ah = face->os2.sTypoAscender - face->os2.sTypoDescender; + } + + else + { +- *tsb = face->horizontal.Ascender - yMax; ++ *tsb = (FT_Short)( face->horizontal.Ascender - yMax ); + *ah = face->horizontal.Ascender - face->horizontal.Descender; + } + +@@ -2120,7 +2120,7 @@ + FT_Bool reexecute = FALSE; + + +- if ( !size->cvt_ready ) ++ if ( size->bytecode_ready < 0 || size->cvt_ready < 0 ) + { + FT_Error error = tt_size_ready_bytecode( size, pedantic ); + +@@ -2128,6 +2128,10 @@ + if ( error ) + return error; + } ++ else if ( size->bytecode_ready ) ++ return size->bytecode_ready; ++ else if ( size->cvt_ready ) ++ return size->cvt_ready; + + /* query new execution context */ + exec = size->debug ? size->context +@@ -2238,12 +2242,15 @@ + + if ( reexecute ) + { +- FT_UInt i; ++ FT_UInt i; ++ FT_Error error; + + + for ( i = 0; i < size->cvt_size; i++ ) + size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); +- tt_size_run_prep( size, pedantic ); ++ error = tt_size_run_prep( size, pedantic ); ++ if ( error ) ++ return error; + } + + /* see whether the cvt program has disabled hinting */ +diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c +index 56e8fa7..7d0248b 100644 +--- a/src/truetype/ttinterp.c ++++ b/src/truetype/ttinterp.c +@@ -172,6 +172,9 @@ + #define CUR_Func_round( d, c ) \ + CUR.func_round( EXEC_ARG_ d, c ) + ++#define CUR_Func_cur_ppem() \ ++ CUR.func_cur_ppem( EXEC_ARG ) ++ + #define CUR_Func_read_cvt( index ) \ + CUR.func_read_cvt( EXEC_ARG_ index ) + +@@ -184,12 +187,6 @@ + #define CURRENT_Ratio() \ + Current_Ratio( EXEC_ARG ) + +-#define CURRENT_Ppem() \ +- Current_Ppem( EXEC_ARG ) +- +-#define CUR_Ppem() \ +- Cur_PPEM( EXEC_ARG ) +- + #define INS_SxVTL( a, b, c, d ) \ + Ins_SxVTL( EXEC_ARG_ a, b, c, d ) + +@@ -1446,7 +1443,7 @@ + TT_MulFix14_arm( FT_Int32 a, + FT_Int b ) + { +- register FT_Int32 t, t2; ++ FT_Int32 t, t2; + + + #if defined( __CC_ARM ) || defined( __ARMCC__ ) +@@ -1706,9 +1703,16 @@ + } + + +- static FT_Long ++ FT_CALLBACK_DEF( FT_Long ) + Current_Ppem( EXEC_OP ) + { ++ return CUR.tt_metrics.ppem; ++ } ++ ++ ++ FT_CALLBACK_DEF( FT_Long ) ++ Current_Ppem_Stretched( EXEC_OP ) ++ { + return FT_MulFix( CUR.tt_metrics.ppem, CURRENT_Ratio() ); + } + +@@ -3089,7 +3093,7 @@ + + + #define DO_MPPEM \ +- args[0] = CURRENT_Ppem(); ++ args[0] = CUR_Func_cur_ppem(); + + + /* Note: The pointSize should be irrelevant in a given font program; */ +@@ -3102,7 +3106,7 @@ + #else + + #define DO_MPS \ +- args[0] = CURRENT_Ppem(); ++ args[0] = CUR_Func_cur_ppem(); + + #endif /* 0 */ + +@@ -7487,9 +7491,9 @@ + static void + Ins_DELTAP( INS_ARG ) + { +- FT_ULong k, nump; ++ FT_ULong nump, k; + FT_UShort A; +- FT_ULong C; ++ FT_ULong C, P; + FT_Long B; + #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING + FT_UShort B1, B2; +@@ -7523,6 +7527,7 @@ + } + #endif + ++ P = (FT_ULong)CUR_Func_cur_ppem(); + nump = (FT_ULong)args[0]; /* some points theoretically may occur more + than once, thus UShort isn't enough */ + +@@ -7567,7 +7572,7 @@ + + C += CUR.GS.delta_base; + +- if ( CURRENT_Ppem() == (FT_Long)C ) ++ if ( P == C ) + { + B = ( (FT_ULong)B & 0xF ) - 8; + if ( B >= 0 ) +@@ -7596,9 +7601,9 @@ + else if ( CUR.ignore_x_mode ) + { + if ( CUR.GS.freeVector.y != 0 ) +- B1 = CUR.zp0.cur[A].y; ++ B1 = (FT_UShort)CUR.zp0.cur[A].y; + else +- B1 = CUR.zp0.cur[A].x; ++ B1 = (FT_UShort)CUR.zp0.cur[A].x; + + #if 0 + /* Standard Subpixel Hinting: Allow y move. */ +@@ -7615,7 +7620,7 @@ + !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) ) + { + /* save the y value of the point now; compare after move */ +- B1 = CUR.zp0.cur[A].y; ++ B1 = (FT_UShort)CUR.zp0.cur[A].y; + + if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) + B = FT_PIX_ROUND( B1 + B ) - B1; +@@ -7627,7 +7632,7 @@ + CUR_Func_move( &CUR.zp0, A, B ); + } + +- B2 = CUR.zp0.cur[A].y; ++ B2 = (FT_UShort)CUR.zp0.cur[A].y; + + /* Reverse this move if it results in a disallowed move */ + if ( CUR.GS.freeVector.y != 0 && +@@ -7667,7 +7672,7 @@ + Ins_DELTAC( INS_ARG ) + { + FT_ULong nump, k; +- FT_ULong A, C; ++ FT_ULong A, C, P; + FT_Long B; + + +@@ -7691,6 +7696,7 @@ + } + #endif + ++ P = (FT_ULong)CUR_Func_cur_ppem(); + nump = (FT_ULong)args[0]; + + for ( k = 1; k <= nump; k++ ) +@@ -7736,7 +7742,7 @@ + + C += CUR.GS.delta_base; + +- if ( CURRENT_Ppem() == (FT_Long)C ) ++ if ( P == C ) + { + B = ( (FT_ULong)B & 0xF ) - 8; + if ( B >= 0 ) +@@ -8269,11 +8275,12 @@ + CUR.iup_called = FALSE; + #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ + +- /* set CVT functions */ ++ /* set PPEM and CVT functions */ + CUR.tt_metrics.ratio = 0; + if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem ) + { + /* non-square pixels, use the stretched routines */ ++ CUR.func_cur_ppem = Current_Ppem_Stretched; + CUR.func_read_cvt = Read_CVT_Stretched; + CUR.func_write_cvt = Write_CVT_Stretched; + CUR.func_move_cvt = Move_CVT_Stretched; +@@ -8281,6 +8288,7 @@ + else + { + /* square pixels, use normal routines */ ++ CUR.func_cur_ppem = Current_Ppem; + CUR.func_read_cvt = Read_CVT; + CUR.func_write_cvt = Write_CVT; + CUR.func_move_cvt = Move_CVT; +@@ -9035,10 +9043,13 @@ + /* If any errors have occurred, function tables may be broken. */ + /* Force a re-execution of `prep' and `fpgm' tables if no */ + /* bytecode debugger is run. */ +- if ( CUR.error && !CUR.instruction_trap ) ++ if ( CUR.error ++ && !CUR.instruction_trap ++ && CUR.curRange == tt_coderange_glyph ) + { + FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error )); +- exc->size->cvt_ready = FALSE; ++ exc->size->bytecode_ready = -1; ++ exc->size->cvt_ready = -1; + } + + return CUR.error; +diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h +index 1d8825d..3cfc859 100644 +--- a/src/truetype/ttinterp.h ++++ b/src/truetype/ttinterp.h +@@ -4,7 +4,7 @@ + /* */ + /* TrueType bytecode interpreter (specification). */ + /* */ +-/* Copyright 1996-2007, 2010, 2012-2013 by */ ++/* Copyright 1996-2007, 2010, 2012-2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -81,6 +81,10 @@ FT_BEGIN_HEADER + (*TT_Project_Func)( EXEC_OP_ FT_Pos dx, + FT_Pos dy ); + ++ /* getting current ppem. Take care of non-square pixels if necessary */ ++ typedef FT_Long ++ (*TT_Cur_Ppem_Func)( EXEC_OP ); ++ + /* reading a cvt value. Take care of non-square pixels if necessary */ + typedef FT_F26Dot6 + (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong idx ); +@@ -228,11 +232,6 @@ FT_BEGIN_HEADER + FT_F26Dot6 phase; /* `SuperRounding' */ + FT_F26Dot6 threshold; + +-#if 0 +- /* this seems to be unused */ +- FT_Int cur_ppem; /* ppem along the current proj vector */ +-#endif +- + FT_Bool instruction_trap; /* If `True', the interpreter will */ + /* exit after each instruction */ + +@@ -254,6 +253,8 @@ FT_BEGIN_HEADER + TT_Move_Func func_move; /* current point move function */ + TT_Move_Func func_move_orig; /* move original position function */ + ++ TT_Cur_Ppem_Func func_cur_ppem; /* get current proj. ppem value */ ++ + TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */ + TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */ + TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */ +diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c +index 4adba58..05a121c 100644 +--- a/src/truetype/ttobjs.c ++++ b/src/truetype/ttobjs.c +@@ -813,6 +813,8 @@ + else + error = FT_Err_Ok; + ++ size->bytecode_ready = error; ++ + if ( !error ) + TT_Save_Context( exec, size ); + +@@ -884,6 +886,8 @@ + else + error = FT_Err_Ok; + ++ size->cvt_ready = error; ++ + /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ + /* graphics state variables to be modified by the CVT program. */ + +@@ -912,10 +916,6 @@ + return error; + } + +-#endif /* TT_USE_BYTECODE_INTERPRETER */ +- +- +-#ifdef TT_USE_BYTECODE_INTERPRETER + + static void + tt_size_done_bytecode( FT_Size ftsize ) +@@ -953,8 +953,8 @@ + size->max_func = 0; + size->max_ins = 0; + +- size->bytecode_ready = 0; +- size->cvt_ready = 0; ++ size->bytecode_ready = -1; ++ size->cvt_ready = -1; + } + + +@@ -974,8 +974,8 @@ + TT_MaxProfile* maxp = &face->max_profile; + + +- size->bytecode_ready = 1; +- size->cvt_ready = 0; ++ size->bytecode_ready = -1; ++ size->cvt_ready = -1; + + size->max_function_defs = maxp->maxFunctionDefs; + size->max_instruction_defs = maxp->maxInstructionDefs; +@@ -1052,15 +1052,14 @@ + FT_Error error = FT_Err_Ok; + + +- if ( !size->bytecode_ready ) +- { ++ if ( size->bytecode_ready < 0 ) + error = tt_size_init_bytecode( (FT_Size)size, pedantic ); +- if ( error ) +- goto Exit; +- } ++ ++ if ( error || size->bytecode_ready ) ++ goto Exit; + + /* rescale CVT when needed */ +- if ( !size->cvt_ready ) ++ if ( size->cvt_ready < 0 ) + { + FT_UInt i; + TT_Face face = (TT_Face)size->root.face; +@@ -1087,8 +1086,6 @@ + size->GS = tt_default_graphics_state; + + error = tt_size_run_prep( size, pedantic ); +- if ( !error ) +- size->cvt_ready = 1; + } + + Exit: +@@ -1119,8 +1116,8 @@ + FT_Error error = FT_Err_Ok; + + #ifdef TT_USE_BYTECODE_INTERPRETER +- size->bytecode_ready = 0; +- size->cvt_ready = 0; ++ size->bytecode_ready = -1; ++ size->cvt_ready = -1; + #endif + + size->ttmetrics.valid = FALSE; +@@ -1148,7 +1145,7 @@ + + + #ifdef TT_USE_BYTECODE_INTERPRETER +- if ( size->bytecode_ready ) ++ if ( size->bytecode_ready >= 0 ) + tt_size_done_bytecode( ttsize ); + #endif + +@@ -1229,7 +1226,7 @@ + } + + #ifdef TT_USE_BYTECODE_INTERPRETER +- size->cvt_ready = 0; ++ size->cvt_ready = -1; + #endif /* TT_USE_BYTECODE_INTERPRETER */ + + if ( !error ) +diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h +index a11dd37..47d50d9 100644 +--- a/src/truetype/ttobjs.h ++++ b/src/truetype/ttobjs.h +@@ -4,7 +4,7 @@ + /* */ + /* Objects manager (specification). */ + /* */ +-/* Copyright 1996-2009, 2011-2013 by */ ++/* Copyright 1996-2009, 2011-2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -333,8 +333,10 @@ FT_BEGIN_HEADER + FT_Bool debug; + TT_ExecContext context; + +- FT_Bool bytecode_ready; +- FT_Bool cvt_ready; ++ /* if negative, `fpgm' (resp. `prep'), wasn't executed yet; */ ++ /* otherwise it is the returned error code */ ++ FT_Error bytecode_ready; ++ FT_Error cvt_ready; + + #endif /* TT_USE_BYTECODE_INTERPRETER */ + +diff --git a/src/truetype/ttsubpix.c b/src/truetype/ttsubpix.c +index 28470ad..9871994 100644 +--- a/src/truetype/ttsubpix.c ++++ b/src/truetype/ttsubpix.c +@@ -956,7 +956,7 @@ + if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 ) + { + loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; +- loader->exec->size->cvt_ready = FALSE; ++ loader->exec->size->cvt_ready = -1; + + tt_size_ready_bytecode( + loader->exec->size, +@@ -971,7 +971,7 @@ + SPH_OPTION_SET_RASTERIZER_VERSION ) + { + loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; +- loader->exec->size->cvt_ready = FALSE; ++ loader->exec->size->cvt_ready = -1; + + tt_size_ready_bytecode( + loader->exec->size, +diff --git a/src/type1/t1driver.c b/src/type1/t1driver.c +index 697288d..2602bdb 100644 +--- a/src/type1/t1driver.c ++++ b/src/type1/t1driver.c +@@ -4,7 +4,7 @@ + /* */ + /* Type 1 driver interface (body). */ + /* */ +-/* Copyright 1996-2004, 2006, 2007, 2009, 2011, 2013 by */ ++/* Copyright 1996-2004, 2006, 2007, 2009, 2011, 2013, 2014 by */ + /* David Turner, Robert Wilhelm, and Werner Lemberg. */ + /* */ + /* This file is part of the FreeType project, and may only be used, */ +@@ -557,9 +557,6 @@ + if ( value && value_len >= retval ) + *((FT_Long *)value) = type1->font_info.italic_angle; + break; +- +- default: +- break; + } + + return retval; |