summaryrefslogtreecommitdiff
path: root/third_party/freetype/src/truetype
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/freetype/src/truetype')
-rw-r--r--third_party/freetype/src/truetype/truetype.c38
-rw-r--r--third_party/freetype/src/truetype/ttdriver.c657
-rw-r--r--third_party/freetype/src/truetype/ttdriver.h38
-rw-r--r--third_party/freetype/src/truetype/tterrors.h42
-rw-r--r--third_party/freetype/src/truetype/ttgload.c2751
-rw-r--r--third_party/freetype/src/truetype/ttgload.h62
-rw-r--r--third_party/freetype/src/truetype/ttinterp.c8416
-rw-r--r--third_party/freetype/src/truetype/ttinterp.h523
-rw-r--r--third_party/freetype/src/truetype/ttobjs.c1363
-rw-r--r--third_party/freetype/src/truetype/ttobjs.h424
-rw-r--r--third_party/freetype/src/truetype/ttpic.c101
-rw-r--r--third_party/freetype/src/truetype/ttpic.h88
-rw-r--r--third_party/freetype/src/truetype/ttpload.c642
-rw-r--r--third_party/freetype/src/truetype/ttpload.h75
-rw-r--r--third_party/freetype/src/truetype/ttsubpix.c1011
-rw-r--r--third_party/freetype/src/truetype/ttsubpix.h111
16 files changed, 0 insertions, 16342 deletions
diff --git a/third_party/freetype/src/truetype/truetype.c b/third_party/freetype/src/truetype/truetype.c
deleted file mode 100644
index 4866103a7f..0000000000
--- a/third_party/freetype/src/truetype/truetype.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/***************************************************************************/
-/* */
-/* truetype.c */
-/* */
-/* FreeType TrueType driver component (body only). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#define FT_MAKE_OPTION_SINGLE_OBJECT
-
-#include <ft2build.h>
-#include "ttpic.c"
-#include "ttdriver.c" /* driver interface */
-#include "ttpload.c" /* tables loader */
-#include "ttgload.c" /* glyph loader */
-#include "ttobjs.c" /* object manager */
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-#include "ttinterp.c"
-#include "ttsubpix.c"
-#endif
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#include "ttgxvar.c" /* gx distortable font */
-#endif
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttdriver.c b/third_party/freetype/src/truetype/ttdriver.c
deleted file mode 100644
index 19f7858b3e..0000000000
--- a/third_party/freetype/src/truetype/ttdriver.c
+++ /dev/null
@@ -1,657 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttdriver.c */
-/* */
-/* TrueType font driver implementation (body). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_STREAM_H
-#include FT_INTERNAL_SFNT_H
-#include FT_SERVICE_FONT_FORMAT_H
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#include FT_MULTIPLE_MASTERS_H
-#include FT_SERVICE_MULTIPLE_MASTERS_H
-#include FT_SERVICE_METRICS_VARIATIONS_H
-#endif
-
-#include FT_SERVICE_TRUETYPE_ENGINE_H
-#include FT_SERVICE_TRUETYPE_GLYF_H
-#include FT_SERVICE_PROPERTIES_H
-#include FT_TRUETYPE_DRIVER_H
-
-#include "ttdriver.h"
-#include "ttgload.h"
-#include "ttpload.h"
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#include "ttgxvar.h"
-#endif
-
-#include "tterrors.h"
-
-#include "ttpic.h"
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttdriver
-
-
- /*
- * PROPERTY SERVICE
- *
- */
- static FT_Error
- tt_property_set( FT_Module module, /* TT_Driver */
- const char* property_name,
- const void* value,
- FT_Bool value_is_string )
- {
- FT_Error error = FT_Err_Ok;
- TT_Driver driver = (TT_Driver)module;
-
-#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
- FT_UNUSED( value_is_string );
-#endif
-
-
- if ( !ft_strcmp( property_name, "interpreter-version" ) )
- {
- FT_UInt interpreter_version;
-
-
-#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
- if ( value_is_string )
- {
- const char* s = (const char*)value;
-
-
- interpreter_version = (FT_UInt)ft_strtol( s, NULL, 10 );
- }
- else
-#endif
- {
- FT_UInt* iv = (FT_UInt*)value;
-
-
- interpreter_version = *iv;
- }
-
- if ( interpreter_version == TT_INTERPRETER_VERSION_35
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- || interpreter_version == TT_INTERPRETER_VERSION_38
-#endif
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- || interpreter_version == TT_INTERPRETER_VERSION_40
-#endif
- )
- driver->interpreter_version = interpreter_version;
- else
- error = FT_ERR( Unimplemented_Feature );
-
- return error;
- }
-
- FT_TRACE0(( "tt_property_set: missing property `%s'\n",
- property_name ));
- return FT_THROW( Missing_Property );
- }
-
-
- static FT_Error
- tt_property_get( FT_Module module, /* TT_Driver */
- const char* property_name,
- const void* value )
- {
- FT_Error error = FT_Err_Ok;
- TT_Driver driver = (TT_Driver)module;
-
- FT_UInt interpreter_version = driver->interpreter_version;
-
-
- if ( !ft_strcmp( property_name, "interpreter-version" ) )
- {
- FT_UInt* val = (FT_UInt*)value;
-
-
- *val = interpreter_version;
-
- return error;
- }
-
- FT_TRACE0(( "tt_property_get: missing property `%s'\n",
- property_name ));
- return FT_THROW( Missing_Property );
- }
-
-
- FT_DEFINE_SERVICE_PROPERTIESREC(
- tt_service_properties,
-
- (FT_Properties_SetFunc)tt_property_set, /* set_property */
- (FT_Properties_GetFunc)tt_property_get /* get_property */
- )
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** F A C E S ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_get_kerning */
- /* */
- /* <Description> */
- /* A driver method used to return the kerning vector between two */
- /* glyphs of the same face. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* left_glyph :: The index of the left glyph in the kern pair. */
- /* */
- /* right_glyph :: The index of the right glyph in the kern pair. */
- /* */
- /* <Output> */
- /* kerning :: The kerning vector. This is in font units for */
- /* scalable formats, and in pixels for fixed-sizes */
- /* formats. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Only horizontal layouts (left-to-right & right-to-left) are */
- /* supported by this function. Other layouts, or more sophisticated */
- /* kernings, are out of scope of this method (the basic driver */
- /* interface is meant to be simple). */
- /* */
- /* They can be implemented by format-specific interfaces. */
- /* */
- static FT_Error
- tt_get_kerning( FT_Face ttface, /* TT_Face */
- FT_UInt left_glyph,
- FT_UInt right_glyph,
- FT_Vector* kerning )
- {
- TT_Face face = (TT_Face)ttface;
- SFNT_Service sfnt = (SFNT_Service)face->sfnt;
-
-
- kerning->x = 0;
- kerning->y = 0;
-
- if ( sfnt )
- kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
-
- return 0;
- }
-
-
- static FT_Error
- tt_get_advances( FT_Face ttface,
- FT_UInt start,
- FT_UInt count,
- FT_Int32 flags,
- FT_Fixed *advances )
- {
- FT_UInt nn;
- TT_Face face = (TT_Face)ttface;
-
-
- /* XXX: TODO: check for sbits */
-
- if ( flags & FT_LOAD_VERTICAL_LAYOUT )
- {
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /* no fast retrieval for blended MM fonts without VVAR table */
- if ( !face->is_default_instance &&
- !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
- return FT_THROW( Unimplemented_Feature );
-#endif
-
- for ( nn = 0; nn < count; nn++ )
- {
- FT_Short tsb;
- FT_UShort ah;
-
-
- /* since we don't need `tsb', we use zero for `yMax' parameter */
- TT_Get_VMetrics( face, start + nn, 0, &tsb, &ah );
- advances[nn] = ah;
- }
- }
- else
- {
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /* no fast retrieval for blended MM fonts without HVAR table */
- if ( !face->is_default_instance &&
- !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
- return FT_THROW( Unimplemented_Feature );
-#endif
-
- for ( nn = 0; nn < count; nn++ )
- {
- FT_Short lsb;
- FT_UShort aw;
-
-
- TT_Get_HMetrics( face, start + nn, &lsb, &aw );
- advances[nn] = aw;
- }
- }
-
- return FT_Err_Ok;
- }
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** S I Z E S ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
-#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
-
- static FT_Error
- tt_size_select( FT_Size size,
- FT_ULong strike_index )
- {
- TT_Face ttface = (TT_Face)size->face;
- TT_Size ttsize = (TT_Size)size;
- FT_Error error = FT_Err_Ok;
-
-
- ttsize->strike_index = strike_index;
-
- if ( FT_IS_SCALABLE( size->face ) )
- {
- /* use the scaled metrics, even when tt_size_reset fails */
- FT_Select_Metrics( size->face, strike_index );
-
- tt_size_reset( ttsize, 0 ); /* ignore return value */
- }
- else
- {
- SFNT_Service sfnt = (SFNT_Service)ttface->sfnt;
- FT_Size_Metrics* metrics = &size->metrics;
-
-
- error = sfnt->load_strike_metrics( ttface, strike_index, metrics );
- if ( error )
- ttsize->strike_index = 0xFFFFFFFFUL;
- }
-
- return error;
- }
-
-#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
-
-
- static FT_Error
- tt_size_request( FT_Size size,
- FT_Size_Request req )
- {
- TT_Size ttsize = (TT_Size)size;
- FT_Error error = FT_Err_Ok;
-
-
-#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
-
- if ( FT_HAS_FIXED_SIZES( size->face ) )
- {
- TT_Face ttface = (TT_Face)size->face;
- SFNT_Service sfnt = (SFNT_Service)ttface->sfnt;
- FT_ULong strike_index;
-
-
- error = sfnt->set_sbit_strike( ttface, req, &strike_index );
-
- if ( error )
- ttsize->strike_index = 0xFFFFFFFFUL;
- else
- return tt_size_select( size, strike_index );
- }
-
-#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
-
- FT_Request_Metrics( size->face, req );
-
- if ( FT_IS_SCALABLE( size->face ) )
- {
- error = tt_size_reset( ttsize, 0 );
- ttsize->root.metrics = ttsize->metrics;
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
- /* for the `MPS' bytecode instruction we need the point size */
- {
- FT_UInt resolution = ttsize->metrics.x_ppem > ttsize->metrics.y_ppem
- ? req->horiResolution
- : req->vertResolution;
-
-
- /* if we don't have a resolution value, assume 72dpi */
- if ( req->type == FT_SIZE_REQUEST_TYPE_SCALES ||
- !resolution )
- resolution = 72;
-
- ttsize->point_size = FT_MulDiv( ttsize->ttmetrics.ppem,
- 64 * 72,
- resolution );
- }
-#endif
- }
-
- return error;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_glyph_load */
- /* */
- /* <Description> */
- /* A driver method used to load a glyph within a given glyph slot. */
- /* */
- /* <Input> */
- /* slot :: A handle to the target slot object where the glyph */
- /* will be loaded. */
- /* */
- /* size :: A handle to the source face size at which the glyph */
- /* must be scaled, loaded, etc. */
- /* */
- /* glyph_index :: The index of the glyph in the font file. */
- /* */
- /* load_flags :: A flag indicating what to load for this glyph. The */
- /* FT_LOAD_XXX constants can be used to control the */
- /* glyph loading process (e.g., whether the outline */
- /* should be scaled, whether to load bitmaps or not, */
- /* whether to hint the outline, etc). */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- static FT_Error
- tt_glyph_load( FT_GlyphSlot ttslot, /* TT_GlyphSlot */
- FT_Size ttsize, /* TT_Size */
- FT_UInt glyph_index,
- FT_Int32 load_flags )
- {
- TT_GlyphSlot slot = (TT_GlyphSlot)ttslot;
- TT_Size size = (TT_Size)ttsize;
- FT_Face face = ttslot->face;
- FT_Error error;
-
-
- if ( !slot )
- return FT_THROW( Invalid_Slot_Handle );
-
- if ( !size )
- return FT_THROW( Invalid_Size_Handle );
-
- if ( !face )
- return FT_THROW( Invalid_Face_Handle );
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- if ( glyph_index >= (FT_UInt)face->num_glyphs &&
- !face->internal->incremental_interface )
-#else
- if ( glyph_index >= (FT_UInt)face->num_glyphs )
-#endif
- return FT_THROW( Invalid_Argument );
-
- if ( load_flags & FT_LOAD_NO_HINTING )
- {
- /* both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT */
- /* are necessary to disable hinting for tricky fonts */
-
- if ( FT_IS_TRICKY( face ) )
- load_flags &= ~FT_LOAD_NO_HINTING;
-
- if ( load_flags & FT_LOAD_NO_AUTOHINT )
- load_flags |= FT_LOAD_NO_HINTING;
- }
-
- if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) )
- {
- load_flags |= FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE;
-
- if ( !FT_IS_TRICKY( face ) )
- load_flags |= FT_LOAD_NO_HINTING;
- }
-
- /* now load the glyph outline if necessary */
- error = TT_Load_Glyph( size, slot, glyph_index, load_flags );
-
- /* force drop-out mode to 2 - irrelevant now */
- /* slot->outline.dropout_mode = 2; */
-
- return error;
- }
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** D R I V E R I N T E R F A C E ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-
- FT_DEFINE_SERVICE_MULTIMASTERSREC(
- tt_service_gx_multi_masters,
-
- (FT_Get_MM_Func) NULL, /* get_mm */
- (FT_Set_MM_Design_Func) NULL, /* set_mm_design */
- (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, /* set_mm_blend */
- (FT_Get_MM_Blend_Func) TT_Get_MM_Blend, /* get_mm_blend */
- (FT_Get_MM_Var_Func) TT_Get_MM_Var, /* get_mm_var */
- (FT_Set_Var_Design_Func)TT_Set_Var_Design, /* set_var_design */
- (FT_Get_Var_Design_Func)TT_Get_Var_Design, /* get_var_design */
-
- (FT_Get_Var_Blend_Func) tt_get_var_blend, /* get_var_blend */
- (FT_Done_Blend_Func) tt_done_blend /* done_blend */
- )
-
- FT_DEFINE_SERVICE_METRICSVARIATIONSREC(
- tt_service_metrics_variations,
-
- (FT_HAdvance_Adjust_Func)tt_hadvance_adjust, /* hadvance_adjust */
- (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */
- (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */
-
- (FT_VAdvance_Adjust_Func)NULL, /* vadvance_adjust */
- (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */
- (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */
- (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */
-
- (FT_Metrics_Adjust_Func) tt_apply_mvar /* metrics_adjust */
- )
-
-#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
-
-
- static const FT_Service_TrueTypeEngineRec tt_service_truetype_engine =
- {
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- FT_TRUETYPE_ENGINE_TYPE_PATENTED
-
-#else /* !TT_USE_BYTECODE_INTERPRETER */
-
- FT_TRUETYPE_ENGINE_TYPE_NONE
-
-#endif /* TT_USE_BYTECODE_INTERPRETER */
- };
-
-
- FT_DEFINE_SERVICE_TTGLYFREC(
- tt_service_truetype_glyf,
-
- (TT_Glyf_GetLocationFunc)tt_face_get_location /* get_location */
- )
-
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- FT_DEFINE_SERVICEDESCREC6(
- tt_services,
-
- FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TRUETYPE,
- FT_SERVICE_ID_MULTI_MASTERS, &TT_SERVICE_GX_MULTI_MASTERS_GET,
- FT_SERVICE_ID_METRICS_VARIATIONS, &TT_SERVICE_METRICS_VARIATIONS_GET,
- FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
- FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET,
- FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET )
-#else
- FT_DEFINE_SERVICEDESCREC4(
- tt_services,
-
- FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TRUETYPE,
- FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
- FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET,
- FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET )
-#endif
-
-
- FT_CALLBACK_DEF( FT_Module_Interface )
- tt_get_interface( FT_Module driver, /* TT_Driver */
- const char* tt_interface )
- {
- FT_Library library;
- FT_Module_Interface result;
- FT_Module sfntd;
- SFNT_Service sfnt;
-
-
- /* TT_SERVICES_GET dereferences `library' in PIC mode */
-#ifdef FT_CONFIG_OPTION_PIC
- if ( !driver )
- return NULL;
- library = driver->library;
- if ( !library )
- return NULL;
-#endif
-
- result = ft_service_list_lookup( TT_SERVICES_GET, tt_interface );
- if ( result )
- return result;
-
-#ifndef FT_CONFIG_OPTION_PIC
- if ( !driver )
- return NULL;
- library = driver->library;
- if ( !library )
- return NULL;
-#endif
-
- /* only return the default interface from the SFNT module */
- sfntd = FT_Get_Module( library, "sfnt" );
- if ( sfntd )
- {
- sfnt = (SFNT_Service)( sfntd->clazz->module_interface );
- if ( sfnt )
- return sfnt->get_interface( driver, tt_interface );
- }
-
- return 0;
- }
-
-
- /* The FT_DriverInterface structure is defined in ftdriver.h. */
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-#define TT_HINTER_FLAG FT_MODULE_DRIVER_HAS_HINTER
-#else
-#define TT_HINTER_FLAG 0
-#endif
-
-#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
-#define TT_SIZE_SELECT tt_size_select
-#else
-#define TT_SIZE_SELECT 0
-#endif
-
- FT_DEFINE_DRIVER(
- tt_driver_class,
-
- FT_MODULE_FONT_DRIVER |
- FT_MODULE_DRIVER_SCALABLE |
- TT_HINTER_FLAG,
-
- sizeof ( TT_DriverRec ),
-
- "truetype", /* driver name */
- 0x10000L, /* driver version == 1.0 */
- 0x20000L, /* driver requires FreeType 2.0 or above */
-
- NULL, /* module-specific interface */
-
- tt_driver_init, /* FT_Module_Constructor module_init */
- tt_driver_done, /* FT_Module_Destructor module_done */
- tt_get_interface, /* FT_Module_Requester get_interface */
-
- sizeof ( TT_FaceRec ),
- sizeof ( TT_SizeRec ),
- sizeof ( FT_GlyphSlotRec ),
-
- tt_face_init, /* FT_Face_InitFunc init_face */
- tt_face_done, /* FT_Face_DoneFunc done_face */
- tt_size_init, /* FT_Size_InitFunc init_size */
- tt_size_done, /* FT_Size_DoneFunc done_size */
- tt_slot_init, /* FT_Slot_InitFunc init_slot */
- NULL, /* FT_Slot_DoneFunc done_slot */
-
- tt_glyph_load, /* FT_Slot_LoadFunc load_glyph */
-
- tt_get_kerning, /* FT_Face_GetKerningFunc get_kerning */
- NULL, /* FT_Face_AttachFunc attach_file */
- tt_get_advances, /* FT_Face_GetAdvancesFunc get_advances */
-
- tt_size_request, /* FT_Size_RequestFunc request_size */
- TT_SIZE_SELECT /* FT_Size_SelectFunc select_size */
- )
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttdriver.h b/third_party/freetype/src/truetype/ttdriver.h
deleted file mode 100644
index 3bcba7f745..0000000000
--- a/third_party/freetype/src/truetype/ttdriver.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttdriver.h */
-/* */
-/* High-level TrueType driver interface (specification). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef TTDRIVER_H_
-#define TTDRIVER_H_
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_DRIVER_H
-
-
-FT_BEGIN_HEADER
-
-
- FT_DECLARE_DRIVER( tt_driver_class )
-
-
-FT_END_HEADER
-
-#endif /* TTDRIVER_H_ */
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/tterrors.h b/third_party/freetype/src/truetype/tterrors.h
deleted file mode 100644
index a49f205156..0000000000
--- a/third_party/freetype/src/truetype/tterrors.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/***************************************************************************/
-/* */
-/* tterrors.h */
-/* */
-/* TrueType error codes (specification only). */
-/* */
-/* Copyright 2001-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This file is used to define the TrueType error enumeration */
- /* constants. */
- /* */
- /*************************************************************************/
-
-#ifndef TTERRORS_H_
-#define TTERRORS_H_
-
-#include FT_MODULE_ERRORS_H
-
-#undef FTERRORS_H_
-
-#undef FT_ERR_PREFIX
-#define FT_ERR_PREFIX TT_Err_
-#define FT_ERR_BASE FT_Mod_Err_TrueType
-
-#include FT_ERRORS_H
-
-#endif /* TTERRORS_H_ */
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttgload.c b/third_party/freetype/src/truetype/ttgload.c
deleted file mode 100644
index 64dc05c1c9..0000000000
--- a/third_party/freetype/src/truetype/ttgload.c
+++ /dev/null
@@ -1,2751 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttgload.c */
-/* */
-/* TrueType Glyph Loader (body). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_CALC_H
-#include FT_INTERNAL_STREAM_H
-#include FT_INTERNAL_SFNT_H
-#include FT_TRUETYPE_TAGS_H
-#include FT_OUTLINE_H
-#include FT_TRUETYPE_DRIVER_H
-#include FT_LIST_H
-
-#include "ttgload.h"
-#include "ttpload.h"
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#include "ttgxvar.h"
-#endif
-
-#include "tterrors.h"
-#include "ttsubpix.h"
-
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttgload
-
-
- /*************************************************************************/
- /* */
- /* Composite glyph flags. */
- /* */
-#define ARGS_ARE_WORDS 0x0001
-#define ARGS_ARE_XY_VALUES 0x0002
-#define ROUND_XY_TO_GRID 0x0004
-#define WE_HAVE_A_SCALE 0x0008
-/* reserved 0x0010 */
-#define MORE_COMPONENTS 0x0020
-#define WE_HAVE_AN_XY_SCALE 0x0040
-#define WE_HAVE_A_2X2 0x0080
-#define WE_HAVE_INSTR 0x0100
-#define USE_MY_METRICS 0x0200
-#define OVERLAP_COMPOUND 0x0400
-#define SCALED_COMPONENT_OFFSET 0x0800
-#define UNSCALED_COMPONENT_OFFSET 0x1000
-
-
- /*************************************************************************/
- /* */
- /* Return the horizontal metrics in font units for a given glyph. */
- /* */
- FT_LOCAL_DEF( void )
- TT_Get_HMetrics( TT_Face face,
- FT_UInt idx,
- FT_Short* lsb,
- FT_UShort* aw )
- {
- ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
-
- FT_TRACE5(( " advance width (font units): %d\n", *aw ));
- FT_TRACE5(( " left side bearing (font units): %d\n", *lsb ));
- }
-
-
- /*************************************************************************/
- /* */
- /* Return the vertical metrics in font units for a given glyph. */
- /* See macro `TT_LOADER_SET_PP' below for explanations. */
- /* */
- FT_LOCAL_DEF( void )
- TT_Get_VMetrics( TT_Face face,
- FT_UInt idx,
- FT_Pos yMax,
- FT_Short* tsb,
- FT_UShort* ah )
- {
- if ( face->vertical_info )
- ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
-
- else if ( face->os2.version != 0xFFFFU )
- {
- *tsb = (FT_Short)( face->os2.sTypoAscender - yMax );
- *ah = (FT_UShort)FT_ABS( face->os2.sTypoAscender -
- face->os2.sTypoDescender );
- }
-
- else
- {
- *tsb = (FT_Short)( face->horizontal.Ascender - yMax );
- *ah = (FT_UShort)FT_ABS( face->horizontal.Ascender -
- face->horizontal.Descender );
- }
-
- FT_TRACE5(( " advance height (font units): %d\n", *ah ));
- FT_TRACE5(( " top side bearing (font units): %d\n", *tsb ));
- }
-
-
- static FT_Error
- tt_get_metrics( TT_Loader loader,
- FT_UInt glyph_index )
- {
- TT_Face face = loader->face;
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
-#endif
-
- FT_Error error;
- FT_Stream stream = loader->stream;
-
- FT_Short left_bearing = 0, top_bearing = 0;
- FT_UShort advance_width = 0, advance_height = 0;
-
- /* we must preserve the stream position */
- /* (which gets altered by the metrics functions) */
- FT_ULong pos = FT_STREAM_POS();
-
-
- TT_Get_HMetrics( face, glyph_index,
- &left_bearing,
- &advance_width );
- TT_Get_VMetrics( face, glyph_index,
- loader->bbox.yMax,
- &top_bearing,
- &advance_height );
-
- if ( FT_STREAM_SEEK( pos ) )
- return error;
-
- loader->left_bearing = left_bearing;
- loader->advance = advance_width;
- loader->top_bearing = top_bearing;
- loader->vadvance = advance_height;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
- loader->exec )
- {
- loader->exec->sph_tweak_flags = 0;
-
- /* This may not be the right place for this, but it works... */
- /* Note that we have to unconditionally load the tweaks since */
- /* it is possible that glyphs individually switch ClearType's */
- /* backwards compatibility mode on and off. */
- sph_set_tweaks( loader, glyph_index );
- }
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- if ( !loader->linear_def )
- {
- loader->linear_def = 1;
- loader->linear = advance_width;
- }
-
- return FT_Err_Ok;
- }
-
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
-
- static void
- tt_get_metrics_incr_overrides( TT_Loader loader,
- FT_UInt glyph_index )
- {
- TT_Face face = loader->face;
-
- FT_Short left_bearing = 0, top_bearing = 0;
- FT_UShort advance_width = 0, advance_height = 0;
-
-
- /* If this is an incrementally loaded font check whether there are */
- /* overriding metrics for this glyph. */
- if ( face->root.internal->incremental_interface &&
- face->root.internal->incremental_interface->funcs->get_glyph_metrics )
- {
- FT_Incremental_MetricsRec metrics;
- FT_Error error;
-
-
- metrics.bearing_x = loader->left_bearing;
- metrics.bearing_y = 0;
- metrics.advance = loader->advance;
- metrics.advance_v = 0;
-
- error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
- face->root.internal->incremental_interface->object,
- glyph_index, FALSE, &metrics );
- if ( error )
- goto Exit;
-
- left_bearing = (FT_Short)metrics.bearing_x;
- advance_width = (FT_UShort)metrics.advance;
-
-#if 0
-
- /* GWW: Do I do the same for vertical metrics? */
- metrics.bearing_x = 0;
- metrics.bearing_y = loader->top_bearing;
- metrics.advance = loader->vadvance;
-
- error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
- face->root.internal->incremental_interface->object,
- glyph_index, TRUE, &metrics );
- if ( error )
- goto Exit;
-
- top_bearing = (FT_Short)metrics.bearing_y;
- advance_height = (FT_UShort)metrics.advance;
-
-#endif /* 0 */
-
- loader->left_bearing = left_bearing;
- loader->advance = advance_width;
- loader->top_bearing = top_bearing;
- loader->vadvance = advance_height;
-
- if ( !loader->linear_def )
- {
- loader->linear_def = 1;
- loader->linear = advance_width;
- }
- }
-
- Exit:
- return;
- }
-
-#endif /* FT_CONFIG_OPTION_INCREMENTAL */
-
-
- /*************************************************************************/
- /* */
- /* The following functions are used by default with TrueType fonts. */
- /* However, they can be replaced by alternatives if we need to support */
- /* TrueType-compressed formats (like MicroType) in the future. */
- /* */
- /*************************************************************************/
-
- FT_CALLBACK_DEF( FT_Error )
- TT_Access_Glyph_Frame( TT_Loader loader,
- FT_UInt glyph_index,
- FT_ULong offset,
- FT_UInt byte_count )
- {
- FT_Error error;
- FT_Stream stream = loader->stream;
-
- /* for non-debug mode */
- FT_UNUSED( glyph_index );
-
-
- FT_TRACE4(( "Glyph %ld\n", glyph_index ));
-
- /* the following line sets the `error' variable through macros! */
- if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
- return error;
-
- loader->cursor = stream->cursor;
- loader->limit = stream->limit;
-
- return FT_Err_Ok;
- }
-
-
- FT_CALLBACK_DEF( void )
- TT_Forget_Glyph_Frame( TT_Loader loader )
- {
- FT_Stream stream = loader->stream;
-
-
- FT_FRAME_EXIT();
- }
-
-
- FT_CALLBACK_DEF( FT_Error )
- TT_Load_Glyph_Header( TT_Loader loader )
- {
- FT_Byte* p = loader->cursor;
- FT_Byte* limit = loader->limit;
-
-
- if ( p + 10 > limit )
- return FT_THROW( Invalid_Outline );
-
- loader->n_contours = FT_NEXT_SHORT( p );
-
- loader->bbox.xMin = FT_NEXT_SHORT( p );
- loader->bbox.yMin = FT_NEXT_SHORT( p );
- loader->bbox.xMax = FT_NEXT_SHORT( p );
- loader->bbox.yMax = FT_NEXT_SHORT( p );
-
- FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
- FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
- loader->bbox.xMax ));
- FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
- loader->bbox.yMax ));
- loader->cursor = p;
-
- return FT_Err_Ok;
- }
-
-
- FT_CALLBACK_DEF( FT_Error )
- TT_Load_Simple_Glyph( TT_Loader load )
- {
- FT_Error error;
- FT_Byte* p = load->cursor;
- FT_Byte* limit = load->limit;
- FT_GlyphLoader gloader = load->gloader;
- FT_Int n_contours = load->n_contours;
- FT_Outline* outline;
- FT_UShort n_ins;
- FT_Int n_points;
- FT_ULong tmp;
-
- FT_Byte *flag, *flag_limit;
- FT_Byte c, count;
- FT_Vector *vec, *vec_limit;
- FT_Pos x;
- FT_Short *cont, *cont_limit, prev_cont;
- FT_Int xy_size = 0;
-
-
- /* check that we can add the contours to the glyph */
- error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
- if ( error )
- goto Fail;
-
- /* reading the contours' endpoints & number of points */
- cont = gloader->current.outline.contours;
- cont_limit = cont + n_contours;
-
- /* check space for contours array + instructions count */
- if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
- goto Invalid_Outline;
-
- prev_cont = FT_NEXT_SHORT( p );
-
- if ( n_contours > 0 )
- cont[0] = prev_cont;
-
- if ( prev_cont < 0 )
- goto Invalid_Outline;
-
- for ( cont++; cont < cont_limit; cont++ )
- {
- cont[0] = FT_NEXT_SHORT( p );
- if ( cont[0] <= prev_cont )
- {
- /* unordered contours: this is invalid */
- goto Invalid_Outline;
- }
- prev_cont = cont[0];
- }
-
- n_points = 0;
- if ( n_contours > 0 )
- {
- n_points = cont[-1] + 1;
- if ( n_points < 0 )
- goto Invalid_Outline;
- }
-
- /* note that we will add four phantom points later */
- error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
- if ( error )
- goto Fail;
-
- /* reading the bytecode instructions */
- load->glyph->control_len = 0;
- load->glyph->control_data = NULL;
-
- if ( p + 2 > limit )
- goto Invalid_Outline;
-
- n_ins = FT_NEXT_USHORT( p );
-
- FT_TRACE5(( " Instructions size: %u\n", n_ins ));
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- if ( IS_HINTED( load->load_flags ) )
- {
- /* check instructions size */
- if ( ( limit - p ) < n_ins )
- {
- FT_TRACE1(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
- error = FT_THROW( Too_Many_Hints );
- goto Fail;
- }
-
- /* we don't trust `maxSizeOfInstructions' in the `maxp' table */
- /* and thus update the bytecode array size by ourselves */
-
- tmp = load->exec->glyphSize;
- error = Update_Max( load->exec->memory,
- &tmp,
- sizeof ( FT_Byte ),
- (void*)&load->exec->glyphIns,
- n_ins );
-
- load->exec->glyphSize = (FT_UShort)tmp;
- if ( error )
- return error;
-
- load->glyph->control_len = n_ins;
- load->glyph->control_data = load->exec->glyphIns;
-
- if ( n_ins )
- FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
- }
-
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
- p += n_ins;
-
- outline = &gloader->current.outline;
-
- /* reading the point tags */
- flag = (FT_Byte*)outline->tags;
- flag_limit = flag + n_points;
-
- FT_ASSERT( flag );
-
- while ( flag < flag_limit )
- {
- if ( p + 1 > limit )
- goto Invalid_Outline;
-
- *flag++ = c = FT_NEXT_BYTE( p );
- if ( c & 8 )
- {
- if ( p + 1 > limit )
- goto Invalid_Outline;
-
- count = FT_NEXT_BYTE( p );
- if ( flag + (FT_Int)count > flag_limit )
- goto Invalid_Outline;
-
- for ( ; count > 0; count-- )
- *flag++ = c;
- }
- }
-
- /* reading the X coordinates */
-
- vec = outline->points;
- vec_limit = vec + n_points;
- flag = (FT_Byte*)outline->tags;
- x = 0;
-
- if ( p + xy_size > limit )
- goto Invalid_Outline;
-
- for ( ; vec < vec_limit; vec++, flag++ )
- {
- FT_Pos y = 0;
- FT_Byte f = *flag;
-
-
- if ( f & 2 )
- {
- if ( p + 1 > limit )
- goto Invalid_Outline;
-
- y = (FT_Pos)FT_NEXT_BYTE( p );
- if ( ( f & 16 ) == 0 )
- y = -y;
- }
- else if ( ( f & 16 ) == 0 )
- {
- if ( p + 2 > limit )
- goto Invalid_Outline;
-
- y = (FT_Pos)FT_NEXT_SHORT( p );
- }
-
- x += y;
- vec->x = x;
- /* the cast is for stupid compilers */
- *flag = (FT_Byte)( f & ~( 2 | 16 ) );
- }
-
- /* reading the Y coordinates */
-
- vec = gloader->current.outline.points;
- vec_limit = vec + n_points;
- flag = (FT_Byte*)outline->tags;
- x = 0;
-
- for ( ; vec < vec_limit; vec++, flag++ )
- {
- FT_Pos y = 0;
- FT_Byte f = *flag;
-
-
- if ( f & 4 )
- {
- if ( p + 1 > limit )
- goto Invalid_Outline;
-
- y = (FT_Pos)FT_NEXT_BYTE( p );
- if ( ( f & 32 ) == 0 )
- y = -y;
- }
- else if ( ( f & 32 ) == 0 )
- {
- if ( p + 2 > limit )
- goto Invalid_Outline;
-
- y = (FT_Pos)FT_NEXT_SHORT( p );
- }
-
- x += y;
- vec->y = x;
- /* the cast is for stupid compilers */
- *flag = (FT_Byte)( f & FT_CURVE_TAG_ON );
- }
-
- outline->n_points = (FT_Short)n_points;
- outline->n_contours = (FT_Short)n_contours;
-
- load->cursor = p;
-
- Fail:
- return error;
-
- Invalid_Outline:
- error = FT_THROW( Invalid_Outline );
- goto Fail;
- }
-
-
- FT_CALLBACK_DEF( FT_Error )
- TT_Load_Composite_Glyph( TT_Loader loader )
- {
- FT_Error error;
- FT_Byte* p = loader->cursor;
- FT_Byte* limit = loader->limit;
- FT_GlyphLoader gloader = loader->gloader;
- FT_SubGlyph subglyph;
- FT_UInt num_subglyphs;
-
-
- num_subglyphs = 0;
-
- do
- {
- FT_Fixed xx, xy, yy, yx;
- FT_UInt count;
-
-
- /* check that we can load a new subglyph */
- error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
- if ( error )
- goto Fail;
-
- /* check space */
- if ( p + 4 > limit )
- goto Invalid_Composite;
-
- subglyph = gloader->current.subglyphs + num_subglyphs;
-
- subglyph->arg1 = subglyph->arg2 = 0;
-
- subglyph->flags = FT_NEXT_USHORT( p );
- subglyph->index = FT_NEXT_USHORT( p );
-
- /* check space */
- count = 2;
- if ( subglyph->flags & ARGS_ARE_WORDS )
- count += 2;
- if ( subglyph->flags & WE_HAVE_A_SCALE )
- count += 2;
- else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
- count += 4;
- else if ( subglyph->flags & WE_HAVE_A_2X2 )
- count += 8;
-
- if ( p + count > limit )
- goto Invalid_Composite;
-
- /* read arguments */
- if ( subglyph->flags & ARGS_ARE_XY_VALUES )
- {
- if ( subglyph->flags & ARGS_ARE_WORDS )
- {
- subglyph->arg1 = FT_NEXT_SHORT( p );
- subglyph->arg2 = FT_NEXT_SHORT( p );
- }
- else
- {
- subglyph->arg1 = FT_NEXT_CHAR( p );
- subglyph->arg2 = FT_NEXT_CHAR( p );
- }
- }
- else
- {
- if ( subglyph->flags & ARGS_ARE_WORDS )
- {
- subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p );
- subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p );
- }
- else
- {
- subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p );
- subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p );
- }
- }
-
- /* read transform */
- xx = yy = 0x10000L;
- xy = yx = 0;
-
- if ( subglyph->flags & WE_HAVE_A_SCALE )
- {
- xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
- yy = xx;
- }
- else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
- {
- xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
- yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
- }
- else if ( subglyph->flags & WE_HAVE_A_2X2 )
- {
- xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
- yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
- xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
- yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
- }
-
- subglyph->transform.xx = xx;
- subglyph->transform.xy = xy;
- subglyph->transform.yx = yx;
- subglyph->transform.yy = yy;
-
- num_subglyphs++;
-
- } while ( subglyph->flags & MORE_COMPONENTS );
-
- gloader->current.num_subglyphs = num_subglyphs;
- FT_TRACE5(( " %d components\n", num_subglyphs ));
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- {
- FT_Stream stream = loader->stream;
-
-
- /* we must undo the FT_FRAME_ENTER in order to point */
- /* to the composite instructions, if we find some. */
- /* We will process them later. */
- /* */
- loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
- p - limit );
- }
-
-#endif
-
- loader->cursor = p;
-
- Fail:
- return error;
-
- Invalid_Composite:
- error = FT_THROW( Invalid_Composite );
- goto Fail;
- }
-
-
- FT_LOCAL_DEF( void )
- TT_Init_Glyph_Loading( TT_Face face )
- {
- face->access_glyph_frame = TT_Access_Glyph_Frame;
- face->read_glyph_header = TT_Load_Glyph_Header;
- face->read_simple_glyph = TT_Load_Simple_Glyph;
- face->read_composite_glyph = TT_Load_Composite_Glyph;
- face->forget_glyph_frame = TT_Forget_Glyph_Frame;
- }
-
-
- static void
- tt_prepare_zone( TT_GlyphZone zone,
- FT_GlyphLoad load,
- FT_UInt start_point,
- FT_UInt start_contour )
- {
- zone->n_points = (FT_UShort)load->outline.n_points -
- (FT_UShort)start_point;
- zone->n_contours = load->outline.n_contours -
- (FT_Short)start_contour;
- zone->org = load->extra_points + start_point;
- zone->cur = load->outline.points + start_point;
- zone->orus = load->extra_points2 + start_point;
- zone->tags = (FT_Byte*)load->outline.tags + start_point;
- zone->contours = (FT_UShort*)load->outline.contours + start_contour;
- zone->first_point = (FT_UShort)start_point;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Hint_Glyph */
- /* */
- /* <Description> */
- /* Hint the glyph using the zone prepared by the caller. Note that */
- /* the zone is supposed to include four phantom points. */
- /* */
- static FT_Error
- TT_Hint_Glyph( TT_Loader loader,
- FT_Bool is_composite )
- {
-#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
- defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- TT_Face face = loader->face;
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
-#endif
-
- TT_GlyphZone zone = &loader->zone;
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
- FT_Long n_ins;
-#else
- FT_UNUSED( is_composite );
-#endif
-
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
- if ( loader->glyph->control_len > 0xFFFFL )
- {
- FT_TRACE1(( "TT_Hint_Glyph: too long instructions" ));
- FT_TRACE1(( " (0x%lx byte) is truncated\n",
- loader->glyph->control_len ));
- }
- n_ins = loader->glyph->control_len;
-
- /* save original point position in org */
- if ( n_ins > 0 )
- FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
-
- /* Reset graphics state. */
- loader->exec->GS = loader->size->GS;
-
- /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
- /* completely refer to the (already) hinted subglyphs. */
- if ( is_composite )
- {
- loader->exec->metrics.x_scale = 1 << 16;
- loader->exec->metrics.y_scale = 1 << 16;
-
- FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
- }
- else
- {
- loader->exec->metrics.x_scale = loader->size->metrics.x_scale;
- loader->exec->metrics.y_scale = loader->size->metrics.y_scale;
- }
-#endif
-
- /* round phantom points */
- zone->cur[zone->n_points - 4].x =
- FT_PIX_ROUND( zone->cur[zone->n_points - 4].x );
- zone->cur[zone->n_points - 3].x =
- FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
- zone->cur[zone->n_points - 2].y =
- FT_PIX_ROUND( zone->cur[zone->n_points - 2].y );
- zone->cur[zone->n_points - 1].y =
- FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- if ( n_ins > 0 )
- {
- FT_Error error;
-
- FT_GlyphLoader gloader = loader->gloader;
- FT_Outline current_outline = gloader->current.outline;
-
-
- TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
- loader->exec->glyphIns, n_ins );
-
- loader->exec->is_composite = is_composite;
- loader->exec->pts = *zone;
-
- error = TT_Run_Context( loader->exec );
- if ( error && loader->exec->pedantic_hinting )
- return error;
-
- /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
- current_outline.tags[0] |=
- ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
- }
-
-#endif
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* Save possibly modified glyph phantom points unless in v40 backwards */
- /* compatibility mode, where no movement on the x axis means no reason */
- /* to change bearings or advance widths. */
- if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
- !loader->exec->backwards_compatibility ) )
- {
-#endif
- loader->pp1 = zone->cur[zone->n_points - 4];
- loader->pp2 = zone->cur[zone->n_points - 3];
- loader->pp3 = zone->cur[zone->n_points - 2];
- loader->pp4 = zone->cur[zone->n_points - 1];
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- }
-#endif
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
- {
- if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
- FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 );
-
- else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
- FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
- }
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- return FT_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Process_Simple_Glyph */
- /* */
- /* <Description> */
- /* Once a simple glyph has been loaded, it needs to be processed. */
- /* Usually, this means scaling and hinting through bytecode */
- /* interpretation. */
- /* */
- static FT_Error
- TT_Process_Simple_Glyph( TT_Loader loader )
- {
- FT_GlyphLoader gloader = loader->gloader;
- FT_Error error = FT_Err_Ok;
- FT_Outline* outline;
- FT_Int n_points;
-
-
- outline = &gloader->current.outline;
- n_points = outline->n_points;
-
- /* set phantom points */
-
- outline->points[n_points ] = loader->pp1;
- outline->points[n_points + 1] = loader->pp2;
- outline->points[n_points + 2] = loader->pp3;
- outline->points[n_points + 3] = loader->pp4;
-
- outline->tags[n_points ] = 0;
- outline->tags[n_points + 1] = 0;
- outline->tags[n_points + 2] = 0;
- outline->tags[n_points + 3] = 0;
-
- n_points += 4;
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-
- if ( loader->face->doblend && !loader->face->is_default_instance )
- {
- /* Deltas apply to the unscaled data. */
- error = TT_Vary_Apply_Glyph_Deltas( loader->face,
- loader->glyph_index,
- outline,
- (FT_UInt)n_points );
-
- /* recalculate linear horizontal and vertical advances */
- /* if we don't have HVAR and VVAR, respectively */
- if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
- loader->linear = outline->points[n_points - 3].x -
- outline->points[n_points - 4].x;
- if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
- loader->vadvance = outline->points[n_points - 1].x -
- outline->points[n_points - 2].x;
-
- if ( error )
- return error;
- }
-
-#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
-
- if ( IS_HINTED( loader->load_flags ) )
- {
- tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
-
- FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
- loader->zone.n_points + 4 );
- }
-
- {
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- TT_Face face = loader->face;
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
-
- FT_String* family = face->root.family_name;
- FT_UInt ppem = loader->size->metrics.x_ppem;
- FT_String* style = face->root.style_name;
- FT_UInt x_scale_factor = 1000;
-#endif
-
- FT_Vector* vec = outline->points;
- FT_Vector* limit = outline->points + n_points;
-
- FT_Fixed x_scale = 0; /* pacify compiler */
- FT_Fixed y_scale = 0;
-
- FT_Bool do_scale = FALSE;
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
- {
- /* scale, but only if enabled and only if TT hinting is being used */
- if ( IS_HINTED( loader->load_flags ) )
- x_scale_factor = sph_test_tweak_x_scaling( face,
- family,
- ppem,
- style,
- loader->glyph_index );
- /* scale the glyph */
- if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
- x_scale_factor != 1000 )
- {
- x_scale = FT_MulDiv( loader->size->metrics.x_scale,
- (FT_Long)x_scale_factor, 1000 );
- y_scale = loader->size->metrics.y_scale;
-
- /* compensate for any scaling by de/emboldening; */
- /* the amount was determined via experimentation */
- if ( x_scale_factor != 1000 && ppem > 11 )
- FT_Outline_EmboldenXY( outline,
- FT_MulFix( 1280 * ppem,
- 1000 - x_scale_factor ),
- 0 );
- do_scale = TRUE;
- }
- }
- else
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- {
- /* scale the glyph */
- if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
- {
- x_scale = loader->size->metrics.x_scale;
- y_scale = loader->size->metrics.y_scale;
-
- do_scale = TRUE;
- }
- }
-
- if ( do_scale )
- {
- for ( ; vec < limit; vec++ )
- {
- vec->x = FT_MulFix( vec->x, x_scale );
- vec->y = FT_MulFix( vec->y, y_scale );
- }
-
- loader->pp1 = outline->points[n_points - 4];
- loader->pp2 = outline->points[n_points - 3];
- loader->pp3 = outline->points[n_points - 2];
- loader->pp4 = outline->points[n_points - 1];
- }
- }
-
- if ( IS_HINTED( loader->load_flags ) )
- {
- loader->zone.n_points += 4;
-
- error = TT_Hint_Glyph( loader, 0 );
- }
-
- return error;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Process_Composite_Component */
- /* */
- /* <Description> */
- /* Once a composite component has been loaded, it needs to be */
- /* processed. Usually, this means transforming and translating. */
- /* */
- static FT_Error
- TT_Process_Composite_Component( TT_Loader loader,
- FT_SubGlyph subglyph,
- FT_UInt start_point,
- FT_UInt num_base_points )
- {
- FT_GlyphLoader gloader = loader->gloader;
- FT_Outline current;
- FT_Bool have_scale;
- FT_Pos x, y;
-
-
- current.points = gloader->base.outline.points +
- num_base_points;
- current.n_points = gloader->base.outline.n_points -
- (short)num_base_points;
-
- have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
- WE_HAVE_AN_XY_SCALE |
- WE_HAVE_A_2X2 ) );
-
- /* perform the transform required for this subglyph */
- if ( have_scale )
- FT_Outline_Transform( &current, &subglyph->transform );
-
- /* get offset */
- if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
- {
- FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points;
- FT_UInt k = (FT_UInt)subglyph->arg1;
- FT_UInt l = (FT_UInt)subglyph->arg2;
- FT_Vector* p1;
- FT_Vector* p2;
-
-
- /* match l-th point of the newly loaded component to the k-th point */
- /* of the previously loaded components. */
-
- /* change to the point numbers used by our outline */
- k += start_point;
- l += num_base_points;
- if ( k >= num_base_points ||
- l >= num_points )
- return FT_THROW( Invalid_Composite );
-
- p1 = gloader->base.outline.points + k;
- p2 = gloader->base.outline.points + l;
-
- x = p1->x - p2->x;
- y = p1->y - p2->y;
- }
- else
- {
- x = subglyph->arg1;
- y = subglyph->arg2;
-
- if ( !x && !y )
- return FT_Err_Ok;
-
- /* Use a default value dependent on */
- /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old */
- /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit. */
-
- if ( have_scale &&
-#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
- !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
-#else
- ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
-#endif
- {
-
-#if 0
-
- /*******************************************************************/
- /* */
- /* This algorithm is what Apple documents. But it doesn't work. */
- /* */
- int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
- : -subglyph->transform.xx;
- int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
- : -subglyph->transform.yx;
- int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
- : -subglyph->transform.xy;
- int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
- : -subglyph->transform.yy;
- int m = a > b ? a : b;
- int n = c > d ? c : d;
-
-
- if ( a - b <= 33 && a - b >= -33 )
- m *= 2;
- if ( c - d <= 33 && c - d >= -33 )
- n *= 2;
- x = FT_MulFix( x, m );
- y = FT_MulFix( y, n );
-
-#else /* 1 */
-
- /*******************************************************************/
- /* */
- /* This algorithm is a guess and works much better than the above. */
- /* */
- FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx,
- subglyph->transform.xy );
- FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy,
- subglyph->transform.yx );
-
-
- x = FT_MulFix( x, mac_xscale );
- y = FT_MulFix( y, mac_yscale );
-
-#endif /* 1 */
-
- }
-
- if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
- {
- FT_Fixed x_scale = loader->size->metrics.x_scale;
- FT_Fixed y_scale = loader->size->metrics.y_scale;
-
-
- x = FT_MulFix( x, x_scale );
- y = FT_MulFix( y, y_scale );
-
- if ( subglyph->flags & ROUND_XY_TO_GRID )
- {
- x = FT_PIX_ROUND( x );
- y = FT_PIX_ROUND( y );
- }
- }
- }
-
- if ( x || y )
- FT_Outline_Translate( &current, x, y );
-
- return FT_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Process_Composite_Glyph */
- /* */
- /* <Description> */
- /* This is slightly different from TT_Process_Simple_Glyph, in that */
- /* its sole purpose is to hint the glyph. Thus this function is */
- /* only available when bytecode interpreter is enabled. */
- /* */
- static FT_Error
- TT_Process_Composite_Glyph( TT_Loader loader,
- FT_UInt start_point,
- FT_UInt start_contour )
- {
- FT_Error error;
- FT_Outline* outline;
- FT_UInt i;
-
-
- outline = &loader->gloader->base.outline;
-
- /* make room for phantom points */
- error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
- outline->n_points + 4,
- 0 );
- if ( error )
- return error;
-
- outline->points[outline->n_points ] = loader->pp1;
- outline->points[outline->n_points + 1] = loader->pp2;
- outline->points[outline->n_points + 2] = loader->pp3;
- outline->points[outline->n_points + 3] = loader->pp4;
-
- outline->tags[outline->n_points ] = 0;
- outline->tags[outline->n_points + 1] = 0;
- outline->tags[outline->n_points + 2] = 0;
- outline->tags[outline->n_points + 3] = 0;
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- {
- FT_Stream stream = loader->stream;
- FT_UShort n_ins, max_ins;
- FT_ULong tmp;
-
-
- /* TT_Load_Composite_Glyph only gives us the offset of instructions */
- /* so we read them here */
- if ( FT_STREAM_SEEK( loader->ins_pos ) ||
- FT_READ_USHORT( n_ins ) )
- return error;
-
- FT_TRACE5(( " Instructions size = %d\n", n_ins ));
-
- /* check it */
- max_ins = loader->face->max_profile.maxSizeOfInstructions;
- if ( n_ins > max_ins )
- {
- /* don't trust `maxSizeOfInstructions'; */
- /* only do a rough safety check */
- if ( (FT_Int)n_ins > loader->byte_len )
- {
- FT_TRACE1(( "TT_Process_Composite_Glyph:"
- " too many instructions (%d) for glyph with length %d\n",
- n_ins, loader->byte_len ));
- return FT_THROW( Too_Many_Hints );
- }
-
- tmp = loader->exec->glyphSize;
- error = Update_Max( loader->exec->memory,
- &tmp,
- sizeof ( FT_Byte ),
- (void*)&loader->exec->glyphIns,
- n_ins );
-
- loader->exec->glyphSize = (FT_UShort)tmp;
- if ( error )
- return error;
- }
- else if ( n_ins == 0 )
- return FT_Err_Ok;
-
- if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
- return error;
-
- loader->glyph->control_data = loader->exec->glyphIns;
- loader->glyph->control_len = n_ins;
- }
-
-#endif
-
- tt_prepare_zone( &loader->zone, &loader->gloader->base,
- start_point, start_contour );
-
- /* Some points are likely touched during execution of */
- /* instructions on components. So let's untouch them. */
- for ( i = 0; i < loader->zone.n_points; i++ )
- loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
-
- loader->zone.n_points += 4;
-
- return TT_Hint_Glyph( loader, 1 );
- }
-
-
- /*
- * Calculate the phantom points
- *
- * Defining the right side bearing (rsb) as
- *
- * rsb = aw - (lsb + xmax - xmin)
- *
- * (with `aw' the advance width, `lsb' the left side bearing, and `xmin'
- * and `xmax' the glyph's minimum and maximum x value), the OpenType
- * specification defines the initial position of horizontal phantom points
- * as
- *
- * pp1 = (round(xmin - lsb), 0) ,
- * pp2 = (round(pp1 + aw), 0) .
- *
- * Note that the rounding to the grid (in the device space) is not
- * documented currently in the specification.
- *
- * However, the specification lacks the precise definition of vertical
- * phantom points. Greg Hitchcock provided the following explanation.
- *
- * - a `vmtx' table is present
- *
- * For any glyph, the minimum and maximum y values (`ymin' and `ymax')
- * are given in the `glyf' table, the top side bearing (tsb) and advance
- * height (ah) are given in the `vmtx' table. The bottom side bearing
- * (bsb) is then calculated as
- *
- * bsb = ah - (tsb + ymax - ymin) ,
- *
- * and the initial position of vertical phantom points is
- *
- * pp3 = (x, round(ymax + tsb)) ,
- * pp4 = (x, round(pp3 - ah)) .
- *
- * See below for value `x'.
- *
- * - no `vmtx' table in the font
- *
- * If there is an `OS/2' table, we set
- *
- * DefaultAscender = sTypoAscender ,
- * DefaultDescender = sTypoDescender ,
- *
- * otherwise we use data from the `hhea' table:
- *
- * DefaultAscender = Ascender ,
- * DefaultDescender = Descender .
- *
- * With these two variables we can now set
- *
- * ah = DefaultAscender - sDefaultDescender ,
- * tsb = DefaultAscender - yMax ,
- *
- * and proceed as if a `vmtx' table was present.
- *
- * Usually we have
- *
- * x = aw / 2 , (1)
- *
- * but there is one compatibility case where it can be set to
- *
- * x = -DefaultDescender -
- * ((DefaultAscender - DefaultDescender - aw) / 2) . (2)
- *
- * and another one with
- *
- * x = 0 . (3)
- *
- * In Windows, the history of those values is quite complicated,
- * depending on the hinting engine (that is, the graphics framework).
- *
- * framework from to formula
- * ----------------------------------------------------------
- * GDI Windows 98 current (1)
- * (Windows 2000 for NT)
- * GDI+ Windows XP Windows 7 (2)
- * GDI+ Windows 8 current (3)
- * DWrite Windows 7 current (3)
- *
- * For simplicity, FreeType uses (1) for grayscale subpixel hinting and
- * (3) for everything else.
- *
- */
- static void
- tt_loader_set_pp( TT_Loader loader )
- {
- FT_Bool subpixel_hinting = 0;
- FT_Bool grayscale = 0;
- FT_Bool use_aw_2 = 0;
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
-#endif
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
- {
- subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting
- : 0;
- grayscale = loader->exec ? loader->exec->grayscale
- : 0;
- }
-#endif
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
- {
- subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting_lean
- : 0;
- grayscale = loader->exec ? loader->exec->grayscale_cleartype
- : 0;
- }
-#endif
-
- use_aw_2 = (FT_Bool)( subpixel_hinting && grayscale );
-
- loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
- loader->pp1.y = 0;
- loader->pp2.x = loader->pp1.x + loader->advance;
- loader->pp2.y = 0;
-
- loader->pp3.x = use_aw_2 ? loader->advance / 2 : 0;
- loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
- loader->pp4.x = use_aw_2 ? loader->advance / 2 : 0;
- loader->pp4.y = loader->pp3.y - loader->vadvance;
- }
-
-
- /* a utility function to retrieve i-th node from given FT_List */
- static FT_ListNode
- ft_list_get_node_at( FT_List list,
- FT_UInt index )
- {
- FT_ListNode cur;
-
-
- if ( !list )
- return NULL;
-
- for ( cur = list->head; cur; cur = cur->next )
- {
- if ( !index )
- return cur;
-
- index--;
- }
-
- return NULL;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* load_truetype_glyph */
- /* */
- /* <Description> */
- /* Loads a given truetype glyph. Handles composites and uses a */
- /* TT_Loader object. */
- /* */
- static FT_Error
- load_truetype_glyph( TT_Loader loader,
- FT_UInt glyph_index,
- FT_UInt recurse_count,
- FT_Bool header_only )
- {
- FT_Error error = FT_Err_Ok;
- FT_Fixed x_scale, y_scale;
- FT_ULong offset;
- TT_Face face = loader->face;
- FT_GlyphLoader gloader = loader->gloader;
- FT_Bool opened_frame = 0;
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- FT_StreamRec inc_stream;
- FT_Data glyph_data;
- FT_Bool glyph_data_loaded = 0;
-#endif
-
-
-#ifdef FT_DEBUG_LEVEL_TRACE
- if ( recurse_count )
- FT_TRACE5(( " nesting level: %d\n", recurse_count ));
-#endif
-
- /* some fonts have an incorrect value of `maxComponentDepth' */
- if ( recurse_count > face->max_profile.maxComponentDepth )
- {
- FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %d\n",
- recurse_count ));
- face->max_profile.maxComponentDepth = (FT_UShort)recurse_count;
- }
-
-#ifndef FT_CONFIG_OPTION_INCREMENTAL
- /* check glyph index */
- if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
- {
- error = FT_THROW( Invalid_Glyph_Index );
- goto Exit;
- }
-#endif
-
- loader->glyph_index = glyph_index;
-
- if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
- {
- x_scale = loader->size->metrics.x_scale;
- y_scale = loader->size->metrics.y_scale;
- }
- else
- {
- x_scale = 0x10000L;
- y_scale = 0x10000L;
- }
-
- /* Set `offset' to the start of the glyph relative to the start of */
- /* the `glyf' table, and `byte_len' to the length of the glyph in */
- /* bytes. */
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
-
- /* If we are loading glyph data via the incremental interface, set */
- /* the loader stream to a memory stream reading the data returned */
- /* by the interface. */
- if ( face->root.internal->incremental_interface )
- {
- error = face->root.internal->incremental_interface->funcs->get_glyph_data(
- face->root.internal->incremental_interface->object,
- glyph_index, &glyph_data );
- if ( error )
- goto Exit;
-
- glyph_data_loaded = 1;
- offset = 0;
- loader->byte_len = glyph_data.length;
-
- FT_ZERO( &inc_stream );
- FT_Stream_OpenMemory( &inc_stream,
- glyph_data.pointer,
- (FT_ULong)glyph_data.length );
-
- loader->stream = &inc_stream;
- }
- else
-
-#endif /* FT_CONFIG_OPTION_INCREMENTAL */
-
- offset = tt_face_get_location( face, glyph_index,
- (FT_UInt*)&loader->byte_len );
-
- if ( loader->byte_len > 0 )
- {
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- /* for the incremental interface, `glyf_offset' is always zero */
- if ( !face->glyf_offset &&
- !face->root.internal->incremental_interface )
-#else
- if ( !face->glyf_offset )
-#endif /* FT_CONFIG_OPTION_INCREMENTAL */
- {
- FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
- error = FT_THROW( Invalid_Table );
- goto Exit;
- }
-
- error = face->access_glyph_frame( loader, glyph_index,
- face->glyf_offset + offset,
- (FT_UInt)loader->byte_len );
- if ( error )
- goto Exit;
-
- opened_frame = 1;
-
- /* read glyph header first */
- error = face->read_glyph_header( loader );
- if ( error )
- goto Exit;
-
- /* the metrics must be computed after loading the glyph header */
- /* since we need the glyph's `yMax' value in case the vertical */
- /* metrics must be emulated */
- error = tt_get_metrics( loader, glyph_index );
- if ( error )
- goto Exit;
-
- if ( header_only )
- goto Exit;
- }
-
- if ( loader->byte_len == 0 || loader->n_contours == 0 )
- {
- loader->bbox.xMin = 0;
- loader->bbox.xMax = 0;
- loader->bbox.yMin = 0;
- loader->bbox.yMax = 0;
-
- error = tt_get_metrics( loader, glyph_index );
- if ( error )
- goto Exit;
-
- if ( header_only )
- goto Exit;
-
- /* must initialize points before (possibly) overriding */
- /* glyph metrics from the incremental interface */
- tt_loader_set_pp( loader );
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- tt_get_metrics_incr_overrides( loader, glyph_index );
-#endif
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-
- if ( loader->face->doblend && !loader->face->is_default_instance )
- {
- /* a small outline structure with four elements for */
- /* communication with `TT_Vary_Apply_Glyph_Deltas' */
- FT_Vector points[4];
- char tags[4] = { 1, 1, 1, 1 };
- short contours[4] = { 0, 1, 2, 3 };
- FT_Outline outline;
-
-
- points[0].x = loader->pp1.x;
- points[0].y = loader->pp1.y;
- points[1].x = loader->pp2.x;
- points[1].y = loader->pp2.y;
-
- points[2].x = loader->pp3.x;
- points[2].y = loader->pp3.y;
- points[3].x = loader->pp4.x;
- points[3].y = loader->pp4.y;
-
- outline.n_points = 4;
- outline.n_contours = 4;
- outline.points = points;
- outline.tags = tags;
- outline.contours = contours;
-
- /* this must be done before scaling */
- error = TT_Vary_Apply_Glyph_Deltas( loader->face,
- glyph_index,
- &outline,
- (FT_UInt)outline.n_points );
- if ( error )
- goto Exit;
-
- loader->pp1.x = points[0].x;
- loader->pp1.y = points[0].y;
- loader->pp2.x = points[1].x;
- loader->pp2.y = points[1].y;
-
- loader->pp3.x = points[2].x;
- loader->pp3.y = points[2].y;
- loader->pp4.x = points[3].x;
- loader->pp4.y = points[3].y;
-
-
- /* recalculate linear horizontal and vertical advances */
- /* if we don't have HVAR and VVAR, respectively */
- if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
- loader->linear = loader->pp2.x - loader->pp1.x;
- if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
- loader->vadvance = loader->pp4.x - loader->pp3.x;
- }
-
-#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
-
- /* scale phantom points, if necessary; */
- /* they get rounded in `TT_Hint_Glyph' */
- if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
- {
- loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
- loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
- /* pp1.y and pp2.y are always zero */
-
- loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
- loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
- loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
- loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
- }
-
- error = FT_Err_Ok;
- goto Exit;
- }
-
- /* must initialize phantom points before (possibly) overriding */
- /* glyph metrics from the incremental interface */
- tt_loader_set_pp( loader );
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- tt_get_metrics_incr_overrides( loader, glyph_index );
-#endif
-
- /***********************************************************************/
- /***********************************************************************/
- /***********************************************************************/
-
- /* if it is a simple glyph, load it */
-
- if ( loader->n_contours > 0 )
- {
- error = face->read_simple_glyph( loader );
- if ( error )
- goto Exit;
-
- /* all data have been read */
- face->forget_glyph_frame( loader );
- opened_frame = 0;
-
- error = TT_Process_Simple_Glyph( loader );
- if ( error )
- goto Exit;
-
- FT_GlyphLoader_Add( gloader );
- }
-
- /***********************************************************************/
- /***********************************************************************/
- /***********************************************************************/
-
- /* otherwise, load a composite! */
- else if ( loader->n_contours == -1 )
- {
- FT_Memory memory = face->root.memory;
-
- FT_UInt start_point;
- FT_UInt start_contour;
- FT_ULong ins_pos; /* position of composite instructions, if any */
-
- FT_ListNode node, node2;
-
-
- /*
- * We store the glyph index directly in the `node->data' pointer,
- * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
- * double cast to make this portable. Note, however, that this needs
- * pointers with a width of at least 32 bits.
- */
-
-
- /* clear the nodes filled by sibling chains */
- node = ft_list_get_node_at( &loader->composites, recurse_count );
- for ( node2 = node; node2; node2 = node2->next )
- node2->data = (void*)ULONG_MAX;
-
- /* check whether we already have a composite glyph with this index */
- if ( FT_List_Find( &loader->composites,
- (void*)(unsigned long)glyph_index ) )
- {
- FT_TRACE1(( "TT_Load_Composite_Glyph:"
- " infinite recursion detected\n" ));
- error = FT_THROW( Invalid_Composite );
- goto Exit;
- }
-
- else if ( node )
- node->data = (void*)(unsigned long)glyph_index;
-
- else
- {
- if ( FT_NEW( node ) )
- goto Exit;
- node->data = (void*)(unsigned long)glyph_index;
- FT_List_Add( &loader->composites, node );
- }
-
- start_point = (FT_UInt)gloader->base.outline.n_points;
- start_contour = (FT_UInt)gloader->base.outline.n_contours;
-
- /* for each subglyph, read composite header */
- error = face->read_composite_glyph( loader );
- if ( error )
- goto Exit;
-
- /* store the offset of instructions */
- ins_pos = loader->ins_pos;
-
- /* all data we need are read */
- face->forget_glyph_frame( loader );
- opened_frame = 0;
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-
- if ( face->doblend && !face->is_default_instance )
- {
- short i, limit;
- FT_SubGlyph subglyph;
-
- FT_Outline outline;
- FT_Vector* points = NULL;
- char* tags = NULL;
- short* contours = NULL;
-
-
- limit = (short)gloader->current.num_subglyphs;
-
- /* construct an outline structure for */
- /* communication with `TT_Vary_Apply_Glyph_Deltas' */
- outline.n_points = (short)( gloader->current.num_subglyphs + 4 );
- outline.n_contours = outline.n_points;
-
- outline.points = NULL;
- outline.tags = NULL;
- outline.contours = NULL;
-
- if ( FT_NEW_ARRAY( points, outline.n_points ) ||
- FT_NEW_ARRAY( tags, outline.n_points ) ||
- FT_NEW_ARRAY( contours, outline.n_points ) )
- goto Exit1;
-
- subglyph = gloader->current.subglyphs;
-
- for ( i = 0; i < limit; i++, subglyph++ )
- {
- /* applying deltas for anchor points doesn't make sense, */
- /* but we don't have to specially check this since */
- /* unused delta values are zero anyways */
- points[i].x = subglyph->arg1;
- points[i].y = subglyph->arg2;
- tags[i] = 1;
- contours[i] = i;
- }
-
- points[i].x = loader->pp1.x;
- points[i].y = loader->pp1.y;
- tags[i] = 1;
- contours[i] = i;
-
- i++;
- points[i].x = loader->pp2.x;
- points[i].y = loader->pp2.y;
- tags[i] = 1;
- contours[i] = i;
-
- i++;
- points[i].x = loader->pp3.x;
- points[i].y = loader->pp3.y;
- tags[i] = 1;
- contours[i] = i;
-
- i++;
- points[i].x = loader->pp4.x;
- points[i].y = loader->pp4.y;
- tags[i] = 1;
- contours[i] = i;
-
- outline.points = points;
- outline.tags = tags;
- outline.contours = contours;
-
- /* this call provides additional offsets */
- /* for each component's translation */
- if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas(
- face,
- glyph_index,
- &outline,
- (FT_UInt)outline.n_points ) ) )
- goto Exit1;
-
- subglyph = gloader->current.subglyphs;
-
- for ( i = 0; i < limit; i++, subglyph++ )
- {
- if ( subglyph->flags & ARGS_ARE_XY_VALUES )
- {
- subglyph->arg1 = (FT_Int16)points[i].x;
- subglyph->arg2 = (FT_Int16)points[i].y;
- }
- }
-
- loader->pp1.x = points[i + 0].x;
- loader->pp1.y = points[i + 0].y;
- loader->pp2.x = points[i + 1].x;
- loader->pp2.y = points[i + 1].y;
-
- loader->pp3.x = points[i + 2].x;
- loader->pp3.y = points[i + 2].y;
- loader->pp4.x = points[i + 3].x;
- loader->pp4.y = points[i + 3].y;
-
- /* recalculate linear horizontal and vertical advances */
- /* if we don't have HVAR and VVAR, respectively */
- if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
- loader->linear = loader->pp2.x - loader->pp1.x;
- if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
- loader->vadvance = loader->pp4.x - loader->pp3.x;
-
- Exit1:
- FT_FREE( outline.points );
- FT_FREE( outline.tags );
- FT_FREE( outline.contours );
-
- if ( error )
- goto Exit;
- }
-
-#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
-
- /* scale phantom points, if necessary; */
- /* they get rounded in `TT_Hint_Glyph' */
- if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
- {
- loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
- loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
- /* pp1.y and pp2.y are always zero */
-
- loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
- loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
- loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
- loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
- }
-
- /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
- /* `as is' in the glyph slot (the client application will be */
- /* responsible for interpreting these data)... */
- if ( loader->load_flags & FT_LOAD_NO_RECURSE )
- {
- FT_GlyphLoader_Add( gloader );
- loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
-
- goto Exit;
- }
-
- /*********************************************************************/
- /*********************************************************************/
- /*********************************************************************/
-
- {
- FT_UInt n, num_base_points;
- FT_SubGlyph subglyph = NULL;
-
- FT_UInt num_points = start_point;
- FT_UInt num_subglyphs = gloader->current.num_subglyphs;
- FT_UInt num_base_subgs = gloader->base.num_subglyphs;
-
- FT_Stream old_stream = loader->stream;
- FT_Int old_byte_len = loader->byte_len;
-
-
- FT_GlyphLoader_Add( gloader );
-
- /* read each subglyph independently */
- for ( n = 0; n < num_subglyphs; n++ )
- {
- FT_Vector pp[4];
-
- FT_Int linear_hadvance;
- FT_Int linear_vadvance;
-
-
- /* Each time we call load_truetype_glyph in this loop, the */
- /* value of `gloader.base.subglyphs' can change due to table */
- /* reallocations. We thus need to recompute the subglyph */
- /* pointer on each iteration. */
- subglyph = gloader->base.subglyphs + num_base_subgs + n;
-
- pp[0] = loader->pp1;
- pp[1] = loader->pp2;
- pp[2] = loader->pp3;
- pp[3] = loader->pp4;
-
- linear_hadvance = loader->linear;
- linear_vadvance = loader->vadvance;
-
- num_base_points = (FT_UInt)gloader->base.outline.n_points;
-
- error = load_truetype_glyph( loader,
- (FT_UInt)subglyph->index,
- recurse_count + 1,
- FALSE );
- if ( error )
- goto Exit;
-
- /* restore subglyph pointer */
- subglyph = gloader->base.subglyphs + num_base_subgs + n;
-
- /* restore phantom points if necessary */
- if ( !( subglyph->flags & USE_MY_METRICS ) )
- {
- loader->pp1 = pp[0];
- loader->pp2 = pp[1];
- loader->pp3 = pp[2];
- loader->pp4 = pp[3];
-
- loader->linear = linear_hadvance;
- loader->vadvance = linear_vadvance;
- }
-
- num_points = (FT_UInt)gloader->base.outline.n_points;
-
- if ( num_points == num_base_points )
- continue;
-
- /* gloader->base.outline consists of three parts: */
- /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
- /* */
- /* (1): exists from the beginning */
- /* (2): components that have been loaded so far */
- /* (3): the newly loaded component */
- error = TT_Process_Composite_Component( loader,
- subglyph,
- start_point,
- num_base_points );
- if ( error )
- goto Exit;
- }
-
- loader->stream = old_stream;
- loader->byte_len = old_byte_len;
-
- /* process the glyph */
- loader->ins_pos = ins_pos;
- if ( IS_HINTED( loader->load_flags ) &&
-#ifdef TT_USE_BYTECODE_INTERPRETER
- subglyph->flags & WE_HAVE_INSTR &&
-#endif
- num_points > start_point )
- {
- error = TT_Process_Composite_Glyph( loader,
- start_point,
- start_contour );
- if ( error )
- goto Exit;
- }
- }
- }
- else
- {
- /* invalid composite count (negative but not -1) */
- error = FT_THROW( Invalid_Outline );
- goto Exit;
- }
-
- /***********************************************************************/
- /***********************************************************************/
- /***********************************************************************/
-
- Exit:
-
- if ( opened_frame )
- face->forget_glyph_frame( loader );
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
-
- if ( glyph_data_loaded )
- face->root.internal->incremental_interface->funcs->free_glyph_data(
- face->root.internal->incremental_interface->object,
- &glyph_data );
-
-#endif
-
- return error;
- }
-
-
- static FT_Error
- compute_glyph_metrics( TT_Loader loader,
- FT_UInt glyph_index )
- {
- TT_Face face = loader->face;
-#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
- defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
-#endif
-
- FT_BBox bbox;
- FT_Fixed y_scale;
- TT_GlyphSlot glyph = loader->glyph;
- TT_Size size = loader->size;
-
-
- y_scale = 0x10000L;
- if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
- y_scale = size->root.metrics.y_scale;
-
- if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
- FT_Outline_Get_CBox( &glyph->outline, &bbox );
- else
- bbox = loader->bbox;
-
- /* get the device-independent horizontal advance; it is scaled later */
- /* by the base layer. */
- glyph->linearHoriAdvance = loader->linear;
-
- glyph->metrics.horiBearingX = bbox.xMin;
- glyph->metrics.horiBearingY = bbox.yMax;
- glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
-
- /* Adjust advance width to the value contained in the hdmx table */
- /* unless FT_LOAD_COMPUTE_METRICS is set or backwards compatibility */
- /* mode of the v40 interpreter is active. See `ttinterp.h' for */
- /* details on backwards compatibility mode. */
- if (
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
- ( loader->exec && loader->exec->backwards_compatibility ) ) &&
-#endif
- !face->postscript.isFixedPitch &&
- IS_HINTED( loader->load_flags ) &&
- !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
- {
- FT_Byte* widthp;
-
-
- widthp = tt_face_get_device_metrics( face,
- size->root.metrics.x_ppem,
- glyph_index );
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
- {
- FT_Bool ignore_x_mode;
-
-
- ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) !=
- FT_RENDER_MODE_MONO );
-
- if ( widthp &&
- ( ( ignore_x_mode && loader->exec->compatible_widths ) ||
- !ignore_x_mode ||
- SPH_OPTION_BITMAP_WIDTHS ) )
- glyph->metrics.horiAdvance = *widthp * 64;
- }
- else
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- {
- if ( widthp )
- glyph->metrics.horiAdvance = *widthp * 64;
- }
- }
-
- /* set glyph dimensions */
- glyph->metrics.width = bbox.xMax - bbox.xMin;
- glyph->metrics.height = bbox.yMax - bbox.yMin;
-
- /* Now take care of vertical metrics. In the case where there is */
- /* no vertical information within the font (relatively common), */
- /* create some metrics manually */
- {
- FT_Pos top; /* scaled vertical top side bearing */
- FT_Pos advance; /* scaled vertical advance height */
-
-
- /* Get the unscaled top bearing and advance height. */
- if ( face->vertical_info &&
- face->vertical.number_Of_VMetrics > 0 )
- {
- top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
- y_scale );
-
- if ( loader->pp3.y <= loader->pp4.y )
- advance = 0;
- else
- advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
- y_scale );
- }
- else
- {
- FT_Pos height;
-
-
- /* XXX Compute top side bearing and advance height in */
- /* Get_VMetrics instead of here. */
-
- /* NOTE: The OS/2 values are the only `portable' ones, */
- /* which is why we use them, if there is an OS/2 */
- /* table in the font. Otherwise, we use the */
- /* values defined in the horizontal header. */
-
- height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
- y_scale );
- if ( face->os2.version != 0xFFFFU )
- advance = (FT_Pos)( face->os2.sTypoAscender -
- face->os2.sTypoDescender );
- else
- advance = (FT_Pos)( face->horizontal.Ascender -
- face->horizontal.Descender );
-
- top = ( advance - height ) / 2;
- }
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- {
- FT_Incremental_InterfaceRec* incr;
- FT_Incremental_MetricsRec metrics;
- FT_Error error;
-
-
- incr = face->root.internal->incremental_interface;
-
- /* If this is an incrementally loaded font see if there are */
- /* overriding metrics for this glyph. */
- if ( incr && incr->funcs->get_glyph_metrics )
- {
- metrics.bearing_x = 0;
- metrics.bearing_y = top;
- metrics.advance = advance;
-
- error = incr->funcs->get_glyph_metrics( incr->object,
- glyph_index,
- TRUE,
- &metrics );
- if ( error )
- return error;
-
- top = metrics.bearing_y;
- advance = metrics.advance;
- }
- }
-
- /* GWW: Do vertical metrics get loaded incrementally too? */
-
-#endif /* FT_CONFIG_OPTION_INCREMENTAL */
-
- glyph->linearVertAdvance = advance;
-
- /* scale the metrics */
- if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
- {
- top = FT_MulFix( top, y_scale );
- advance = FT_MulFix( advance, y_scale );
- }
-
- /* XXX: for now, we have no better algorithm for the lsb, but it */
- /* should work fine. */
- /* */
- glyph->metrics.vertBearingX = glyph->metrics.horiBearingX -
- glyph->metrics.horiAdvance / 2;
- glyph->metrics.vertBearingY = top;
- glyph->metrics.vertAdvance = advance;
- }
-
- return 0;
- }
-
-
-#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
-
- static FT_Error
- load_sbit_image( TT_Size size,
- TT_GlyphSlot glyph,
- FT_UInt glyph_index,
- FT_Int32 load_flags )
- {
- TT_Face face;
- SFNT_Service sfnt;
- FT_Stream stream;
- FT_Error error;
- TT_SBit_MetricsRec metrics;
-
-
- face = (TT_Face)glyph->face;
- sfnt = (SFNT_Service)face->sfnt;
- stream = face->root.stream;
-
- error = sfnt->load_sbit_image( face,
- size->strike_index,
- glyph_index,
- (FT_UInt)load_flags,
- stream,
- &glyph->bitmap,
- &metrics );
- if ( !error )
- {
- glyph->outline.n_points = 0;
- glyph->outline.n_contours = 0;
-
- glyph->metrics.width = (FT_Pos)metrics.width * 64;
- glyph->metrics.height = (FT_Pos)metrics.height * 64;
-
- glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX * 64;
- glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY * 64;
- glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance * 64;
-
- glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX * 64;
- glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY * 64;
- glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance * 64;
-
- glyph->format = FT_GLYPH_FORMAT_BITMAP;
-
- if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
- {
- glyph->bitmap_left = metrics.vertBearingX;
- glyph->bitmap_top = metrics.vertBearingY;
- }
- else
- {
- glyph->bitmap_left = metrics.horiBearingX;
- glyph->bitmap_top = metrics.horiBearingY;
- }
- }
-
- return error;
- }
-
-#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
-
-
- static FT_Error
- tt_loader_init( TT_Loader loader,
- TT_Size size,
- TT_GlyphSlot glyph,
- FT_Int32 load_flags,
- FT_Bool glyf_table_only )
- {
- FT_Error error;
-
- TT_Face face;
- FT_Stream stream;
-#ifdef TT_USE_BYTECODE_INTERPRETER
- FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
-#endif
-#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
- defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
-#endif
-
-
- face = (TT_Face)glyph->face;
- stream = face->root.stream;
-
- FT_ZERO( loader );
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- /* load execution context */
- if ( IS_HINTED( load_flags ) && !glyf_table_only )
- {
- TT_ExecContext exec;
- FT_Bool grayscale = TRUE;
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- FT_Bool subpixel_hinting_lean;
- FT_Bool grayscale_cleartype;
-#endif
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- FT_Bool subpixel_hinting = FALSE;
-
-#if 0
- /* not used yet */
- FT_Bool compatible_widths;
- FT_Bool symmetrical_smoothing;
- FT_Bool bgr;
- FT_Bool vertical_lcd;
- FT_Bool subpixel_positioned;
- FT_Bool gray_cleartype;
-#endif
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- FT_Bool reexecute = FALSE;
-
-
- if ( size->bytecode_ready < 0 || size->cvt_ready < 0 )
- {
- error = tt_size_ready_bytecode( size, pedantic );
- 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->context;
- if ( !exec )
- return FT_THROW( Could_Not_Find_Context );
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
- {
- subpixel_hinting_lean = TRUE;
- grayscale_cleartype = !FT_BOOL( load_flags &
- FT_LOAD_TARGET_LCD ||
- load_flags &
- FT_LOAD_TARGET_LCD_V );
- exec->vertical_lcd_lean = FT_BOOL( load_flags &
- FT_LOAD_TARGET_LCD_V );
- }
- else
- {
- subpixel_hinting_lean = FALSE;
- grayscale_cleartype = FALSE;
- exec->vertical_lcd_lean = FALSE;
- }
-#endif
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
- {
- subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
- FT_RENDER_MODE_MONO ) &&
- SPH_OPTION_SET_SUBPIXEL );
-
- if ( subpixel_hinting )
- grayscale = FALSE;
- else if ( SPH_OPTION_SET_GRAYSCALE )
- {
- grayscale = TRUE;
- subpixel_hinting = FALSE;
- }
- else
- grayscale = FALSE;
-
- if ( FT_IS_TRICKY( glyph->face ) )
- subpixel_hinting = FALSE;
-
- exec->ignore_x_mode = subpixel_hinting || grayscale;
- exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
- if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
- exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
-
-#if 1
- exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS;
- exec->symmetrical_smoothing = TRUE;
- exec->bgr = FALSE;
- exec->vertical_lcd = FALSE;
- exec->subpixel_positioned = TRUE;
- exec->gray_cleartype = FALSE;
-#else /* 0 */
- exec->compatible_widths =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- TT_LOAD_COMPATIBLE_WIDTHS );
- exec->symmetrical_smoothing =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- TT_LOAD_SYMMETRICAL_SMOOTHING );
- exec->bgr =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- TT_LOAD_BGR );
- exec->vertical_lcd =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- TT_LOAD_VERTICAL_LCD );
- exec->subpixel_positioned =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- TT_LOAD_SUBPIXEL_POSITIONED );
- exec->gray_cleartype =
- FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- TT_LOAD_GRAY_CLEARTYPE );
-#endif /* 0 */
-
- }
- else
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
- grayscale = FT_BOOL( !subpixel_hinting_lean &&
- FT_LOAD_TARGET_MODE( load_flags ) !=
- FT_RENDER_MODE_MONO );
- else
-#endif
- grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- FT_RENDER_MODE_MONO );
-
- error = TT_Load_Context( exec, face, size );
- if ( error )
- return error;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
- {
- /* a change from mono to subpixel rendering (and vice versa) */
- /* requires a re-execution of the CVT program */
- if ( subpixel_hinting != exec->subpixel_hinting )
- {
- FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
- " re-executing `prep' table\n" ));
-
- exec->subpixel_hinting = subpixel_hinting;
- reexecute = TRUE;
- }
-
- /* a change from mono to grayscale rendering (and vice versa) */
- /* requires a re-execution of the CVT program */
- if ( grayscale != exec->grayscale )
- {
- FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
- " re-executing `prep' table\n" ));
-
- exec->grayscale = grayscale;
- reexecute = TRUE;
- }
- }
- else
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- {
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
- {
- /* a change from mono to subpixel rendering (and vice versa) */
- /* requires a re-execution of the CVT program */
- if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
- {
- FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
- " re-executing `prep' table\n" ));
-
- exec->subpixel_hinting_lean = subpixel_hinting_lean;
- reexecute = TRUE;
- }
-
- /* a change from colored to grayscale subpixel rendering (and */
- /* vice versa) requires a re-execution of the CVT program */
- if ( grayscale_cleartype != exec->grayscale_cleartype )
- {
- FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
- " re-executing `prep' table\n" ));
-
- exec->grayscale_cleartype = grayscale_cleartype;
- reexecute = TRUE;
- }
- }
-#endif
-
- /* a change from mono to grayscale rendering (and vice versa) */
- /* requires a re-execution of the CVT program */
- if ( grayscale != exec->grayscale )
- {
- FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
- " re-executing `prep' table\n" ));
-
- exec->grayscale = grayscale;
- reexecute = TRUE;
- }
- }
-
- if ( reexecute )
- {
- FT_UInt i;
-
-
- for ( i = 0; i < size->cvt_size; i++ )
- size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
- error = tt_size_run_prep( size, pedantic );
- if ( error )
- return error;
- }
-
- /* check whether the cvt program has disabled hinting */
- if ( exec->GS.instruct_control & 1 )
- load_flags |= FT_LOAD_NO_HINTING;
-
- /* load default graphics state -- if needed */
- if ( exec->GS.instruct_control & 2 )
- exec->GS = tt_default_graphics_state;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /* check whether we have a font hinted for ClearType -- */
- /* note that this flag can also be modified in a glyph's bytecode */
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
- exec->GS.instruct_control & 4 )
- exec->ignore_x_mode = 0;
-#endif
-
- exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
- loader->exec = exec;
- loader->instructions = exec->glyphIns;
- }
-
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
- /* get face's glyph loader */
- if ( !glyf_table_only )
- {
- FT_GlyphLoader gloader = glyph->internal->loader;
-
-
- FT_GlyphLoader_Rewind( gloader );
- loader->gloader = gloader;
- }
-
- loader->load_flags = (FT_ULong)load_flags;
-
- loader->face = face;
- loader->size = size;
- loader->glyph = (FT_GlyphSlot)glyph;
- loader->stream = stream;
-
- loader->composites.head = NULL;
- loader->composites.tail = NULL;
-
- return FT_Err_Ok;
- }
-
-
- static void
- tt_loader_done( TT_Loader loader )
- {
- FT_List_Finalize( &loader->composites,
- NULL,
- loader->face->root.memory,
- NULL );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Load_Glyph */
- /* */
- /* <Description> */
- /* A function used to load a single glyph within a given glyph slot, */
- /* for a given size. */
- /* */
- /* <Input> */
- /* glyph :: A handle to a target slot object where the glyph */
- /* will be loaded. */
- /* */
- /* size :: A handle to the source face size at which the glyph */
- /* must be scaled/loaded. */
- /* */
- /* glyph_index :: The index of the glyph in the font file. */
- /* */
- /* load_flags :: A flag indicating what to load for this glyph. The */
- /* FT_LOAD_XXX constants can be used to control the */
- /* glyph loading process (e.g., whether the outline */
- /* should be scaled, whether to load bitmaps or not, */
- /* whether to hint the outline, etc). */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- TT_Load_Glyph( TT_Size size,
- TT_GlyphSlot glyph,
- FT_UInt glyph_index,
- FT_Int32 load_flags )
- {
- FT_Error error;
- TT_LoaderRec loader;
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#define IS_DEFAULT_INSTANCE ( ( (TT_Face)glyph->face )->is_default_instance )
-#else
-#define IS_DEFAULT_INSTANCE 1
-#endif
-
-
- FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
-
-#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
-
- /* try to load embedded bitmap (if any) */
- if ( size->strike_index != 0xFFFFFFFFUL &&
- ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
- IS_DEFAULT_INSTANCE )
- {
- error = load_sbit_image( size, glyph, glyph_index, load_flags );
- if ( !error )
- {
- if ( FT_IS_SCALABLE( glyph->face ) )
- {
- /* for the bbox we need the header only */
- (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
- (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
- tt_loader_done( &loader );
- glyph->linearHoriAdvance = loader.linear;
- glyph->linearVertAdvance = loader.vadvance;
-
- /* sanity checks: if `xxxAdvance' in the sbit metric */
- /* structure isn't set, use `linearXXXAdvance' */
- if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
- glyph->metrics.horiAdvance =
- FT_MulFix( glyph->linearHoriAdvance,
- size->root.metrics.x_scale );
- if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
- glyph->metrics.vertAdvance =
- FT_MulFix( glyph->linearVertAdvance,
- size->root.metrics.y_scale );
- }
-
- return FT_Err_Ok;
- }
- }
-
-#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
-
- /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
- if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
- {
- error = FT_THROW( Invalid_Size_Handle );
- goto Exit;
- }
-
- if ( load_flags & FT_LOAD_SBITS_ONLY )
- {
- error = FT_THROW( Invalid_Argument );
- goto Exit;
- }
-
- error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
- if ( error )
- goto Exit;
-
- glyph->format = FT_GLYPH_FORMAT_OUTLINE;
- glyph->num_subglyphs = 0;
- glyph->outline.flags = 0;
-
- /* main loading loop */
- error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
- if ( !error )
- {
- if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
- {
- glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
- glyph->subglyphs = loader.gloader->base.subglyphs;
- }
- else
- {
- glyph->outline = loader.gloader->base.outline;
- glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
-
- /* Translate array so that (0,0) is the glyph's origin. Note */
- /* that this behaviour is independent on the value of bit 1 of */
- /* the `flags' field in the `head' table -- at least major */
- /* applications like Acroread indicate that. */
- if ( loader.pp1.x )
- FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
- }
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- if ( IS_HINTED( load_flags ) )
- {
- if ( loader.exec->GS.scan_control )
- {
- /* convert scan conversion mode to FT_OUTLINE_XXX flags */
- switch ( loader.exec->GS.scan_type )
- {
- case 0: /* simple drop-outs including stubs */
- glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
- break;
- case 1: /* simple drop-outs excluding stubs */
- /* nothing; it's the default rendering mode */
- break;
- case 4: /* smart drop-outs including stubs */
- glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
- FT_OUTLINE_INCLUDE_STUBS;
- break;
- case 5: /* smart drop-outs excluding stubs */
- glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
- break;
-
- default: /* no drop-out control */
- glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
- break;
- }
- }
- else
- glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
- }
-
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
- error = compute_glyph_metrics( &loader, glyph_index );
- }
-
- tt_loader_done( &loader );
-
- /* Set the `high precision' bit flag. */
- /* This is _critical_ to get correct output for monochrome */
- /* TrueType glyphs at all sizes using the bytecode interpreter. */
- /* */
- if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
- size->root.metrics.y_ppem < 24 )
- glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
-
- Exit:
-#ifdef FT_DEBUG_LEVEL_TRACE
- if ( error )
- FT_TRACE1(( " failed (error code 0x%x)\n",
- error ));
-#endif
-
- return error;
- }
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttgload.h b/third_party/freetype/src/truetype/ttgload.h
deleted file mode 100644
index 1dd6c841db..0000000000
--- a/third_party/freetype/src/truetype/ttgload.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttgload.h */
-/* */
-/* TrueType Glyph Loader (specification). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef TTGLOAD_H_
-#define TTGLOAD_H_
-
-
-#include <ft2build.h>
-#include "ttobjs.h"
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-#include "ttinterp.h"
-#endif
-
-
-FT_BEGIN_HEADER
-
-
- FT_LOCAL( void )
- TT_Init_Glyph_Loading( TT_Face face );
-
- FT_LOCAL( void )
- TT_Get_HMetrics( TT_Face face,
- FT_UInt idx,
- FT_Short* lsb,
- FT_UShort* aw );
-
- FT_LOCAL( void )
- TT_Get_VMetrics( TT_Face face,
- FT_UInt idx,
- FT_Pos yMax,
- FT_Short* tsb,
- FT_UShort* ah );
-
- FT_LOCAL( FT_Error )
- TT_Load_Glyph( TT_Size size,
- TT_GlyphSlot glyph,
- FT_UInt glyph_index,
- FT_Int32 load_flags );
-
-
-FT_END_HEADER
-
-#endif /* TTGLOAD_H_ */
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttinterp.c b/third_party/freetype/src/truetype/ttinterp.c
deleted file mode 100644
index 6ea1a80bb1..0000000000
--- a/third_party/freetype/src/truetype/ttinterp.c
+++ /dev/null
@@ -1,8416 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttinterp.c */
-/* */
-/* TrueType bytecode interpreter (body). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-/* Greg Hitchcock from Microsoft has helped a lot in resolving unclear */
-/* issues; many thanks! */
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_CALC_H
-#include FT_TRIGONOMETRY_H
-#include FT_SYSTEM_H
-#include FT_TRUETYPE_DRIVER_H
-#include FT_MULTIPLE_MASTERS_H
-
-#include "ttinterp.h"
-#include "tterrors.h"
-#include "ttsubpix.h"
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#include "ttgxvar.h"
-#endif
-
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttinterp
-
-
-#define NO_SUBPIXEL_HINTING \
- ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
- TT_INTERPRETER_VERSION_35 )
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-#define SUBPIXEL_HINTING_INFINALITY \
- ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
- TT_INTERPRETER_VERSION_38 )
-#endif
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
-#define SUBPIXEL_HINTING_MINIMAL \
- ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
- TT_INTERPRETER_VERSION_40 )
-#endif
-
-#define PROJECT( v1, v2 ) \
- exc->func_project( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
-
-#define DUALPROJ( v1, v2 ) \
- exc->func_dualproj( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
-
-#define FAST_PROJECT( v ) \
- exc->func_project( exc, (v)->x, (v)->y )
-
-#define FAST_DUALPROJ( v ) \
- exc->func_dualproj( exc, (v)->x, (v)->y )
-
-
- /*************************************************************************/
- /* */
- /* Two simple bounds-checking macros. */
- /* */
-#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
-#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )
-
-
-#undef SUCCESS
-#define SUCCESS 0
-
-#undef FAILURE
-#define FAILURE 1
-
-
- /*************************************************************************/
- /* */
- /* CODERANGE FUNCTIONS */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Goto_CodeRange */
- /* */
- /* <Description> */
- /* Switches to a new code range (updates the code related elements in */
- /* `exec', and `IP'). */
- /* */
- /* <Input> */
- /* range :: The new execution code range. */
- /* */
- /* IP :: The new IP in the new code range. */
- /* */
- /* <InOut> */
- /* exec :: The target execution context. */
- /* */
- FT_LOCAL_DEF( void )
- TT_Goto_CodeRange( TT_ExecContext exec,
- FT_Int range,
- FT_Long IP )
- {
- TT_CodeRange* coderange;
-
-
- FT_ASSERT( range >= 1 && range <= 3 );
-
- coderange = &exec->codeRangeTable[range - 1];
-
- FT_ASSERT( coderange->base );
-
- /* NOTE: Because the last instruction of a program may be a CALL */
- /* which will return to the first byte *after* the code */
- /* range, we test for IP <= Size instead of IP < Size. */
- /* */
- FT_ASSERT( IP <= coderange->size );
-
- exec->code = coderange->base;
- exec->codeSize = coderange->size;
- exec->IP = IP;
- exec->curRange = range;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Set_CodeRange */
- /* */
- /* <Description> */
- /* Sets a code range. */
- /* */
- /* <Input> */
- /* range :: The code range index. */
- /* */
- /* base :: The new code base. */
- /* */
- /* length :: The range size in bytes. */
- /* */
- /* <InOut> */
- /* exec :: The target execution context. */
- /* */
- FT_LOCAL_DEF( void )
- TT_Set_CodeRange( TT_ExecContext exec,
- FT_Int range,
- void* base,
- FT_Long length )
- {
- FT_ASSERT( range >= 1 && range <= 3 );
-
- exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
- exec->codeRangeTable[range - 1].size = length;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Clear_CodeRange */
- /* */
- /* <Description> */
- /* Clears a code range. */
- /* */
- /* <Input> */
- /* range :: The code range index. */
- /* */
- /* <InOut> */
- /* exec :: The target execution context. */
- /* */
- FT_LOCAL_DEF( void )
- TT_Clear_CodeRange( TT_ExecContext exec,
- FT_Int range )
- {
- FT_ASSERT( range >= 1 && range <= 3 );
-
- exec->codeRangeTable[range - 1].base = NULL;
- exec->codeRangeTable[range - 1].size = 0;
- }
-
-
- /*************************************************************************/
- /* */
- /* EXECUTION CONTEXT ROUTINES */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Done_Context */
- /* */
- /* <Description> */
- /* Destroys a given context. */
- /* */
- /* <Input> */
- /* exec :: A handle to the target execution context. */
- /* */
- /* memory :: A handle to the parent memory object. */
- /* */
- /* <Note> */
- /* Only the glyph loader and debugger should call this function. */
- /* */
- FT_LOCAL_DEF( void )
- TT_Done_Context( TT_ExecContext exec )
- {
- FT_Memory memory = exec->memory;
-
-
- /* points zone */
- exec->maxPoints = 0;
- exec->maxContours = 0;
-
- /* free stack */
- FT_FREE( exec->stack );
- exec->stackSize = 0;
-
- /* free call stack */
- FT_FREE( exec->callStack );
- exec->callSize = 0;
- exec->callTop = 0;
-
- /* free glyph code range */
- FT_FREE( exec->glyphIns );
- exec->glyphSize = 0;
-
- exec->size = NULL;
- exec->face = NULL;
-
- FT_FREE( exec );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Init_Context */
- /* */
- /* <Description> */
- /* Initializes a context object. */
- /* */
- /* <Input> */
- /* memory :: A handle to the parent memory object. */
- /* */
- /* <InOut> */
- /* exec :: A handle to the target execution context. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- static FT_Error
- Init_Context( TT_ExecContext exec,
- FT_Memory memory )
- {
- FT_Error error;
-
-
- FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
-
- exec->memory = memory;
- exec->callSize = 32;
-
- if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
- goto Fail_Memory;
-
- /* all values in the context are set to 0 already, but this is */
- /* here as a remainder */
- exec->maxPoints = 0;
- exec->maxContours = 0;
-
- exec->stackSize = 0;
- exec->glyphSize = 0;
-
- exec->stack = NULL;
- exec->glyphIns = NULL;
-
- exec->face = NULL;
- exec->size = NULL;
-
- return FT_Err_Ok;
-
- Fail_Memory:
- FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
- TT_Done_Context( exec );
-
- return error;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Update_Max */
- /* */
- /* <Description> */
- /* Checks the size of a buffer and reallocates it if necessary. */
- /* */
- /* <Input> */
- /* memory :: A handle to the parent memory object. */
- /* */
- /* multiplier :: The size in bytes of each element in the buffer. */
- /* */
- /* new_max :: The new capacity (size) of the buffer. */
- /* */
- /* <InOut> */
- /* size :: The address of the buffer's current size expressed */
- /* in elements. */
- /* */
- /* buff :: The address of the buffer base pointer. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- Update_Max( FT_Memory memory,
- FT_ULong* size,
- FT_ULong multiplier,
- void* _pbuff,
- FT_ULong new_max )
- {
- FT_Error error;
- void** pbuff = (void**)_pbuff;
-
-
- if ( *size < new_max )
- {
- if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
- return error;
- *size = new_max;
- }
-
- return FT_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Load_Context */
- /* */
- /* <Description> */
- /* Prepare an execution context for glyph hinting. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* size :: A handle to the source size object. */
- /* */
- /* <InOut> */
- /* exec :: A handle to the target execution context. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Only the glyph loader and debugger should call this function. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- TT_Load_Context( TT_ExecContext exec,
- TT_Face face,
- TT_Size size )
- {
- FT_Int i;
- FT_ULong tmp;
- TT_MaxProfile* maxp;
- FT_Error error;
-
-
- exec->face = face;
- maxp = &face->max_profile;
- exec->size = size;
-
- if ( size )
- {
- exec->numFDefs = size->num_function_defs;
- exec->maxFDefs = size->max_function_defs;
- exec->numIDefs = size->num_instruction_defs;
- exec->maxIDefs = size->max_instruction_defs;
- exec->FDefs = size->function_defs;
- exec->IDefs = size->instruction_defs;
- exec->pointSize = size->point_size;
- exec->tt_metrics = size->ttmetrics;
- exec->metrics = size->metrics;
-
- exec->maxFunc = size->max_func;
- exec->maxIns = size->max_ins;
-
- for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
- exec->codeRangeTable[i] = size->codeRangeTable[i];
-
- /* set graphics state */
- exec->GS = size->GS;
-
- exec->cvtSize = size->cvt_size;
- exec->cvt = size->cvt;
-
- exec->storeSize = size->storage_size;
- exec->storage = size->storage;
-
- exec->twilight = size->twilight;
-
- /* In case of multi-threading it can happen that the old size object */
- /* no longer exists, thus we must clear all glyph zone references. */
- FT_ZERO( &exec->zp0 );
- exec->zp1 = exec->zp0;
- exec->zp2 = exec->zp0;
- }
-
- /* XXX: We reserve a little more elements on the stack to deal safely */
- /* with broken fonts like arialbs, courbs, timesbs, etc. */
- tmp = (FT_ULong)exec->stackSize;
- error = Update_Max( exec->memory,
- &tmp,
- sizeof ( FT_F26Dot6 ),
- (void*)&exec->stack,
- maxp->maxStackElements + 32 );
- exec->stackSize = (FT_Long)tmp;
- if ( error )
- return error;
-
- tmp = exec->glyphSize;
- error = Update_Max( exec->memory,
- &tmp,
- sizeof ( FT_Byte ),
- (void*)&exec->glyphIns,
- maxp->maxSizeOfInstructions );
- exec->glyphSize = (FT_UShort)tmp;
- if ( error )
- return error;
-
- exec->pts.n_points = 0;
- exec->pts.n_contours = 0;
-
- exec->zp1 = exec->pts;
- exec->zp2 = exec->pts;
- exec->zp0 = exec->pts;
-
- exec->instruction_trap = FALSE;
-
- return FT_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Save_Context */
- /* */
- /* <Description> */
- /* Saves the code ranges in a `size' object. */
- /* */
- /* <Input> */
- /* exec :: A handle to the source execution context. */
- /* */
- /* <InOut> */
- /* size :: A handle to the target size object. */
- /* */
- /* <Note> */
- /* Only the glyph loader and debugger should call this function. */
- /* */
- FT_LOCAL_DEF( void )
- TT_Save_Context( TT_ExecContext exec,
- TT_Size size )
- {
- FT_Int i;
-
-
- /* XXX: Will probably disappear soon with all the code range */
- /* management, which is now rather obsolete. */
- /* */
- size->num_function_defs = exec->numFDefs;
- size->num_instruction_defs = exec->numIDefs;
-
- size->max_func = exec->maxFunc;
- size->max_ins = exec->maxIns;
-
- for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
- size->codeRangeTable[i] = exec->codeRangeTable[i];
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Run_Context */
- /* */
- /* <Description> */
- /* Executes one or more instructions in the execution context. */
- /* */
- /* <Input> */
- /* debug :: A Boolean flag. If set, the function sets some internal */
- /* variables and returns immediately, otherwise TT_RunIns() */
- /* is called. */
- /* */
- /* This is commented out currently. */
- /* */
- /* <Input> */
- /* exec :: A handle to the target execution context. */
- /* */
- /* <Return> */
- /* TrueType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- TT_Run_Context( TT_ExecContext exec )
- {
- TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 );
-
- exec->zp0 = exec->pts;
- exec->zp1 = exec->pts;
- exec->zp2 = exec->pts;
-
- exec->GS.gep0 = 1;
- exec->GS.gep1 = 1;
- exec->GS.gep2 = 1;
-
- exec->GS.projVector.x = 0x4000;
- exec->GS.projVector.y = 0x0000;
-
- exec->GS.freeVector = exec->GS.projVector;
- exec->GS.dualVector = exec->GS.projVector;
-
- exec->GS.round_state = 1;
- exec->GS.loop = 1;
-
- /* some glyphs leave something on the stack. so we clean it */
- /* before a new execution. */
- exec->top = 0;
- exec->callTop = 0;
-
- return exec->face->interpreter( exec );
- }
-
-
- /* The default value for `scan_control' is documented as FALSE in the */
- /* TrueType specification. This is confusing since it implies a */
- /* Boolean value. However, this is not the case, thus both the */
- /* default values of our `scan_type' and `scan_control' fields (which */
- /* the documentation's `scan_control' variable is split into) are */
- /* zero. */
-
- const TT_GraphicsState tt_default_graphics_state =
- {
- 0, 0, 0,
- { 0x4000, 0 },
- { 0x4000, 0 },
- { 0x4000, 0 },
-
- 1, 64, 1,
- TRUE, 68, 0, 0, 9, 3,
- 0, FALSE, 0, 1, 1, 1
- };
-
-
- /* documentation is in ttinterp.h */
-
- FT_EXPORT_DEF( TT_ExecContext )
- TT_New_Context( TT_Driver driver )
- {
- FT_Memory memory;
- FT_Error error;
-
- TT_ExecContext exec = NULL;
-
-
- if ( !driver )
- goto Fail;
-
- memory = driver->root.root.memory;
-
- /* allocate object */
- if ( FT_NEW( exec ) )
- goto Fail;
-
- /* initialize it; in case of error this deallocates `exec' too */
- error = Init_Context( exec, memory );
- if ( error )
- goto Fail;
-
- return exec;
-
- Fail:
- return NULL;
- }
-
-
- /*************************************************************************/
- /* */
- /* Before an opcode is executed, the interpreter verifies that there are */
- /* enough arguments on the stack, with the help of the `Pop_Push_Count' */
- /* table. */
- /* */
- /* For each opcode, the first column gives the number of arguments that */
- /* are popped from the stack; the second one gives the number of those */
- /* that are pushed in result. */
- /* */
- /* Opcodes which have a varying number of parameters in the data stream */
- /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */
- /* the `opcode_length' table, and the value in `Pop_Push_Count' is set */
- /* to zero. */
- /* */
- /*************************************************************************/
-
-
-#undef PACK
-#define PACK( x, y ) ( ( x << 4 ) | y )
-
-
- static
- const FT_Byte Pop_Push_Count[256] =
- {
- /* opcodes are gathered in groups of 16 */
- /* please keep the spaces as they are */
-
- /* SVTCA y */ PACK( 0, 0 ),
- /* SVTCA x */ PACK( 0, 0 ),
- /* SPvTCA y */ PACK( 0, 0 ),
- /* SPvTCA x */ PACK( 0, 0 ),
- /* SFvTCA y */ PACK( 0, 0 ),
- /* SFvTCA x */ PACK( 0, 0 ),
- /* SPvTL // */ PACK( 2, 0 ),
- /* SPvTL + */ PACK( 2, 0 ),
- /* SFvTL // */ PACK( 2, 0 ),
- /* SFvTL + */ PACK( 2, 0 ),
- /* SPvFS */ PACK( 2, 0 ),
- /* SFvFS */ PACK( 2, 0 ),
- /* GPv */ PACK( 0, 2 ),
- /* GFv */ PACK( 0, 2 ),
- /* SFvTPv */ PACK( 0, 0 ),
- /* ISECT */ PACK( 5, 0 ),
-
- /* SRP0 */ PACK( 1, 0 ),
- /* SRP1 */ PACK( 1, 0 ),
- /* SRP2 */ PACK( 1, 0 ),
- /* SZP0 */ PACK( 1, 0 ),
- /* SZP1 */ PACK( 1, 0 ),
- /* SZP2 */ PACK( 1, 0 ),
- /* SZPS */ PACK( 1, 0 ),
- /* SLOOP */ PACK( 1, 0 ),
- /* RTG */ PACK( 0, 0 ),
- /* RTHG */ PACK( 0, 0 ),
- /* SMD */ PACK( 1, 0 ),
- /* ELSE */ PACK( 0, 0 ),
- /* JMPR */ PACK( 1, 0 ),
- /* SCvTCi */ PACK( 1, 0 ),
- /* SSwCi */ PACK( 1, 0 ),
- /* SSW */ PACK( 1, 0 ),
-
- /* DUP */ PACK( 1, 2 ),
- /* POP */ PACK( 1, 0 ),
- /* CLEAR */ PACK( 0, 0 ),
- /* SWAP */ PACK( 2, 2 ),
- /* DEPTH */ PACK( 0, 1 ),
- /* CINDEX */ PACK( 1, 1 ),
- /* MINDEX */ PACK( 1, 0 ),
- /* AlignPTS */ PACK( 2, 0 ),
- /* INS_$28 */ PACK( 0, 0 ),
- /* UTP */ PACK( 1, 0 ),
- /* LOOPCALL */ PACK( 2, 0 ),
- /* CALL */ PACK( 1, 0 ),
- /* FDEF */ PACK( 1, 0 ),
- /* ENDF */ PACK( 0, 0 ),
- /* MDAP[0] */ PACK( 1, 0 ),
- /* MDAP[1] */ PACK( 1, 0 ),
-
- /* IUP[0] */ PACK( 0, 0 ),
- /* IUP[1] */ PACK( 0, 0 ),
- /* SHP[0] */ PACK( 0, 0 ), /* loops */
- /* SHP[1] */ PACK( 0, 0 ), /* loops */
- /* SHC[0] */ PACK( 1, 0 ),
- /* SHC[1] */ PACK( 1, 0 ),
- /* SHZ[0] */ PACK( 1, 0 ),
- /* SHZ[1] */ PACK( 1, 0 ),
- /* SHPIX */ PACK( 1, 0 ), /* loops */
- /* IP */ PACK( 0, 0 ), /* loops */
- /* MSIRP[0] */ PACK( 2, 0 ),
- /* MSIRP[1] */ PACK( 2, 0 ),
- /* AlignRP */ PACK( 0, 0 ), /* loops */
- /* RTDG */ PACK( 0, 0 ),
- /* MIAP[0] */ PACK( 2, 0 ),
- /* MIAP[1] */ PACK( 2, 0 ),
-
- /* NPushB */ PACK( 0, 0 ),
- /* NPushW */ PACK( 0, 0 ),
- /* WS */ PACK( 2, 0 ),
- /* RS */ PACK( 1, 1 ),
- /* WCvtP */ PACK( 2, 0 ),
- /* RCvt */ PACK( 1, 1 ),
- /* GC[0] */ PACK( 1, 1 ),
- /* GC[1] */ PACK( 1, 1 ),
- /* SCFS */ PACK( 2, 0 ),
- /* MD[0] */ PACK( 2, 1 ),
- /* MD[1] */ PACK( 2, 1 ),
- /* MPPEM */ PACK( 0, 1 ),
- /* MPS */ PACK( 0, 1 ),
- /* FlipON */ PACK( 0, 0 ),
- /* FlipOFF */ PACK( 0, 0 ),
- /* DEBUG */ PACK( 1, 0 ),
-
- /* LT */ PACK( 2, 1 ),
- /* LTEQ */ PACK( 2, 1 ),
- /* GT */ PACK( 2, 1 ),
- /* GTEQ */ PACK( 2, 1 ),
- /* EQ */ PACK( 2, 1 ),
- /* NEQ */ PACK( 2, 1 ),
- /* ODD */ PACK( 1, 1 ),
- /* EVEN */ PACK( 1, 1 ),
- /* IF */ PACK( 1, 0 ),
- /* EIF */ PACK( 0, 0 ),
- /* AND */ PACK( 2, 1 ),
- /* OR */ PACK( 2, 1 ),
- /* NOT */ PACK( 1, 1 ),
- /* DeltaP1 */ PACK( 1, 0 ),
- /* SDB */ PACK( 1, 0 ),
- /* SDS */ PACK( 1, 0 ),
-
- /* ADD */ PACK( 2, 1 ),
- /* SUB */ PACK( 2, 1 ),
- /* DIV */ PACK( 2, 1 ),
- /* MUL */ PACK( 2, 1 ),
- /* ABS */ PACK( 1, 1 ),
- /* NEG */ PACK( 1, 1 ),
- /* FLOOR */ PACK( 1, 1 ),
- /* CEILING */ PACK( 1, 1 ),
- /* ROUND[0] */ PACK( 1, 1 ),
- /* ROUND[1] */ PACK( 1, 1 ),
- /* ROUND[2] */ PACK( 1, 1 ),
- /* ROUND[3] */ PACK( 1, 1 ),
- /* NROUND[0] */ PACK( 1, 1 ),
- /* NROUND[1] */ PACK( 1, 1 ),
- /* NROUND[2] */ PACK( 1, 1 ),
- /* NROUND[3] */ PACK( 1, 1 ),
-
- /* WCvtF */ PACK( 2, 0 ),
- /* DeltaP2 */ PACK( 1, 0 ),
- /* DeltaP3 */ PACK( 1, 0 ),
- /* DeltaCn[0] */ PACK( 1, 0 ),
- /* DeltaCn[1] */ PACK( 1, 0 ),
- /* DeltaCn[2] */ PACK( 1, 0 ),
- /* SROUND */ PACK( 1, 0 ),
- /* S45Round */ PACK( 1, 0 ),
- /* JROT */ PACK( 2, 0 ),
- /* JROF */ PACK( 2, 0 ),
- /* ROFF */ PACK( 0, 0 ),
- /* INS_$7B */ PACK( 0, 0 ),
- /* RUTG */ PACK( 0, 0 ),
- /* RDTG */ PACK( 0, 0 ),
- /* SANGW */ PACK( 1, 0 ),
- /* AA */ PACK( 1, 0 ),
-
- /* FlipPT */ PACK( 0, 0 ), /* loops */
- /* FlipRgON */ PACK( 2, 0 ),
- /* FlipRgOFF */ PACK( 2, 0 ),
- /* INS_$83 */ PACK( 0, 0 ),
- /* INS_$84 */ PACK( 0, 0 ),
- /* ScanCTRL */ PACK( 1, 0 ),
- /* SDPvTL[0] */ PACK( 2, 0 ),
- /* SDPvTL[1] */ PACK( 2, 0 ),
- /* GetINFO */ PACK( 1, 1 ),
- /* IDEF */ PACK( 1, 0 ),
- /* ROLL */ PACK( 3, 3 ),
- /* MAX */ PACK( 2, 1 ),
- /* MIN */ PACK( 2, 1 ),
- /* ScanTYPE */ PACK( 1, 0 ),
- /* InstCTRL */ PACK( 2, 0 ),
- /* INS_$8F */ PACK( 0, 0 ),
-
- /* INS_$90 */ PACK( 0, 0 ),
- /* GETVAR */ PACK( 0, 0 ), /* will be handled specially */
- /* GETDATA */ PACK( 0, 1 ),
- /* INS_$93 */ PACK( 0, 0 ),
- /* INS_$94 */ PACK( 0, 0 ),
- /* INS_$95 */ PACK( 0, 0 ),
- /* INS_$96 */ PACK( 0, 0 ),
- /* INS_$97 */ PACK( 0, 0 ),
- /* INS_$98 */ PACK( 0, 0 ),
- /* INS_$99 */ PACK( 0, 0 ),
- /* INS_$9A */ PACK( 0, 0 ),
- /* INS_$9B */ PACK( 0, 0 ),
- /* INS_$9C */ PACK( 0, 0 ),
- /* INS_$9D */ PACK( 0, 0 ),
- /* INS_$9E */ PACK( 0, 0 ),
- /* INS_$9F */ PACK( 0, 0 ),
-
- /* INS_$A0 */ PACK( 0, 0 ),
- /* INS_$A1 */ PACK( 0, 0 ),
- /* INS_$A2 */ PACK( 0, 0 ),
- /* INS_$A3 */ PACK( 0, 0 ),
- /* INS_$A4 */ PACK( 0, 0 ),
- /* INS_$A5 */ PACK( 0, 0 ),
- /* INS_$A6 */ PACK( 0, 0 ),
- /* INS_$A7 */ PACK( 0, 0 ),
- /* INS_$A8 */ PACK( 0, 0 ),
- /* INS_$A9 */ PACK( 0, 0 ),
- /* INS_$AA */ PACK( 0, 0 ),
- /* INS_$AB */ PACK( 0, 0 ),
- /* INS_$AC */ PACK( 0, 0 ),
- /* INS_$AD */ PACK( 0, 0 ),
- /* INS_$AE */ PACK( 0, 0 ),
- /* INS_$AF */ PACK( 0, 0 ),
-
- /* PushB[0] */ PACK( 0, 1 ),
- /* PushB[1] */ PACK( 0, 2 ),
- /* PushB[2] */ PACK( 0, 3 ),
- /* PushB[3] */ PACK( 0, 4 ),
- /* PushB[4] */ PACK( 0, 5 ),
- /* PushB[5] */ PACK( 0, 6 ),
- /* PushB[6] */ PACK( 0, 7 ),
- /* PushB[7] */ PACK( 0, 8 ),
- /* PushW[0] */ PACK( 0, 1 ),
- /* PushW[1] */ PACK( 0, 2 ),
- /* PushW[2] */ PACK( 0, 3 ),
- /* PushW[3] */ PACK( 0, 4 ),
- /* PushW[4] */ PACK( 0, 5 ),
- /* PushW[5] */ PACK( 0, 6 ),
- /* PushW[6] */ PACK( 0, 7 ),
- /* PushW[7] */ PACK( 0, 8 ),
-
- /* MDRP[00] */ PACK( 1, 0 ),
- /* MDRP[01] */ PACK( 1, 0 ),
- /* MDRP[02] */ PACK( 1, 0 ),
- /* MDRP[03] */ PACK( 1, 0 ),
- /* MDRP[04] */ PACK( 1, 0 ),
- /* MDRP[05] */ PACK( 1, 0 ),
- /* MDRP[06] */ PACK( 1, 0 ),
- /* MDRP[07] */ PACK( 1, 0 ),
- /* MDRP[08] */ PACK( 1, 0 ),
- /* MDRP[09] */ PACK( 1, 0 ),
- /* MDRP[10] */ PACK( 1, 0 ),
- /* MDRP[11] */ PACK( 1, 0 ),
- /* MDRP[12] */ PACK( 1, 0 ),
- /* MDRP[13] */ PACK( 1, 0 ),
- /* MDRP[14] */ PACK( 1, 0 ),
- /* MDRP[15] */ PACK( 1, 0 ),
-
- /* MDRP[16] */ PACK( 1, 0 ),
- /* MDRP[17] */ PACK( 1, 0 ),
- /* MDRP[18] */ PACK( 1, 0 ),
- /* MDRP[19] */ PACK( 1, 0 ),
- /* MDRP[20] */ PACK( 1, 0 ),
- /* MDRP[21] */ PACK( 1, 0 ),
- /* MDRP[22] */ PACK( 1, 0 ),
- /* MDRP[23] */ PACK( 1, 0 ),
- /* MDRP[24] */ PACK( 1, 0 ),
- /* MDRP[25] */ PACK( 1, 0 ),
- /* MDRP[26] */ PACK( 1, 0 ),
- /* MDRP[27] */ PACK( 1, 0 ),
- /* MDRP[28] */ PACK( 1, 0 ),
- /* MDRP[29] */ PACK( 1, 0 ),
- /* MDRP[30] */ PACK( 1, 0 ),
- /* MDRP[31] */ PACK( 1, 0 ),
-
- /* MIRP[00] */ PACK( 2, 0 ),
- /* MIRP[01] */ PACK( 2, 0 ),
- /* MIRP[02] */ PACK( 2, 0 ),
- /* MIRP[03] */ PACK( 2, 0 ),
- /* MIRP[04] */ PACK( 2, 0 ),
- /* MIRP[05] */ PACK( 2, 0 ),
- /* MIRP[06] */ PACK( 2, 0 ),
- /* MIRP[07] */ PACK( 2, 0 ),
- /* MIRP[08] */ PACK( 2, 0 ),
- /* MIRP[09] */ PACK( 2, 0 ),
- /* MIRP[10] */ PACK( 2, 0 ),
- /* MIRP[11] */ PACK( 2, 0 ),
- /* MIRP[12] */ PACK( 2, 0 ),
- /* MIRP[13] */ PACK( 2, 0 ),
- /* MIRP[14] */ PACK( 2, 0 ),
- /* MIRP[15] */ PACK( 2, 0 ),
-
- /* MIRP[16] */ PACK( 2, 0 ),
- /* MIRP[17] */ PACK( 2, 0 ),
- /* MIRP[18] */ PACK( 2, 0 ),
- /* MIRP[19] */ PACK( 2, 0 ),
- /* MIRP[20] */ PACK( 2, 0 ),
- /* MIRP[21] */ PACK( 2, 0 ),
- /* MIRP[22] */ PACK( 2, 0 ),
- /* MIRP[23] */ PACK( 2, 0 ),
- /* MIRP[24] */ PACK( 2, 0 ),
- /* MIRP[25] */ PACK( 2, 0 ),
- /* MIRP[26] */ PACK( 2, 0 ),
- /* MIRP[27] */ PACK( 2, 0 ),
- /* MIRP[28] */ PACK( 2, 0 ),
- /* MIRP[29] */ PACK( 2, 0 ),
- /* MIRP[30] */ PACK( 2, 0 ),
- /* MIRP[31] */ PACK( 2, 0 )
- };
-
-
-#ifdef FT_DEBUG_LEVEL_TRACE
-
- /* the first hex digit gives the length of the opcode name; the space */
- /* after the digit is here just to increase readability of the source */
- /* code */
-
- static
- const char* const opcode_name[256] =
- {
- "7 SVTCA y",
- "7 SVTCA x",
- "8 SPvTCA y",
- "8 SPvTCA x",
- "8 SFvTCA y",
- "8 SFvTCA x",
- "8 SPvTL ||",
- "7 SPvTL +",
- "8 SFvTL ||",
- "7 SFvTL +",
- "5 SPvFS",
- "5 SFvFS",
- "3 GPv",
- "3 GFv",
- "6 SFvTPv",
- "5 ISECT",
-
- "4 SRP0",
- "4 SRP1",
- "4 SRP2",
- "4 SZP0",
- "4 SZP1",
- "4 SZP2",
- "4 SZPS",
- "5 SLOOP",
- "3 RTG",
- "4 RTHG",
- "3 SMD",
- "4 ELSE",
- "4 JMPR",
- "6 SCvTCi",
- "5 SSwCi",
- "3 SSW",
-
- "3 DUP",
- "3 POP",
- "5 CLEAR",
- "4 SWAP",
- "5 DEPTH",
- "6 CINDEX",
- "6 MINDEX",
- "8 AlignPTS",
- "7 INS_$28",
- "3 UTP",
- "8 LOOPCALL",
- "4 CALL",
- "4 FDEF",
- "4 ENDF",
- "7 MDAP[0]",
- "7 MDAP[1]",
-
- "6 IUP[0]",
- "6 IUP[1]",
- "6 SHP[0]",
- "6 SHP[1]",
- "6 SHC[0]",
- "6 SHC[1]",
- "6 SHZ[0]",
- "6 SHZ[1]",
- "5 SHPIX",
- "2 IP",
- "8 MSIRP[0]",
- "8 MSIRP[1]",
- "7 AlignRP",
- "4 RTDG",
- "7 MIAP[0]",
- "7 MIAP[1]",
-
- "6 NPushB",
- "6 NPushW",
- "2 WS",
- "2 RS",
- "5 WCvtP",
- "4 RCvt",
- "5 GC[0]",
- "5 GC[1]",
- "4 SCFS",
- "5 MD[0]",
- "5 MD[1]",
- "5 MPPEM",
- "3 MPS",
- "6 FlipON",
- "7 FlipOFF",
- "5 DEBUG",
-
- "2 LT",
- "4 LTEQ",
- "2 GT",
- "4 GTEQ",
- "2 EQ",
- "3 NEQ",
- "3 ODD",
- "4 EVEN",
- "2 IF",
- "3 EIF",
- "3 AND",
- "2 OR",
- "3 NOT",
- "7 DeltaP1",
- "3 SDB",
- "3 SDS",
-
- "3 ADD",
- "3 SUB",
- "3 DIV",
- "3 MUL",
- "3 ABS",
- "3 NEG",
- "5 FLOOR",
- "7 CEILING",
- "8 ROUND[0]",
- "8 ROUND[1]",
- "8 ROUND[2]",
- "8 ROUND[3]",
- "9 NROUND[0]",
- "9 NROUND[1]",
- "9 NROUND[2]",
- "9 NROUND[3]",
-
- "5 WCvtF",
- "7 DeltaP2",
- "7 DeltaP3",
- "A DeltaCn[0]",
- "A DeltaCn[1]",
- "A DeltaCn[2]",
- "6 SROUND",
- "8 S45Round",
- "4 JROT",
- "4 JROF",
- "4 ROFF",
- "7 INS_$7B",
- "4 RUTG",
- "4 RDTG",
- "5 SANGW",
- "2 AA",
-
- "6 FlipPT",
- "8 FlipRgON",
- "9 FlipRgOFF",
- "7 INS_$83",
- "7 INS_$84",
- "8 ScanCTRL",
- "9 SDPvTL[0]",
- "9 SDPvTL[1]",
- "7 GetINFO",
- "4 IDEF",
- "4 ROLL",
- "3 MAX",
- "3 MIN",
- "8 ScanTYPE",
- "8 InstCTRL",
- "7 INS_$8F",
-
- "7 INS_$90",
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- "6 GETVAR",
- "7 GETDATA",
-#else
- "7 INS_$91",
- "7 INS_$92",
-#endif
- "7 INS_$93",
- "7 INS_$94",
- "7 INS_$95",
- "7 INS_$96",
- "7 INS_$97",
- "7 INS_$98",
- "7 INS_$99",
- "7 INS_$9A",
- "7 INS_$9B",
- "7 INS_$9C",
- "7 INS_$9D",
- "7 INS_$9E",
- "7 INS_$9F",
-
- "7 INS_$A0",
- "7 INS_$A1",
- "7 INS_$A2",
- "7 INS_$A3",
- "7 INS_$A4",
- "7 INS_$A5",
- "7 INS_$A6",
- "7 INS_$A7",
- "7 INS_$A8",
- "7 INS_$A9",
- "7 INS_$AA",
- "7 INS_$AB",
- "7 INS_$AC",
- "7 INS_$AD",
- "7 INS_$AE",
- "7 INS_$AF",
-
- "8 PushB[0]",
- "8 PushB[1]",
- "8 PushB[2]",
- "8 PushB[3]",
- "8 PushB[4]",
- "8 PushB[5]",
- "8 PushB[6]",
- "8 PushB[7]",
- "8 PushW[0]",
- "8 PushW[1]",
- "8 PushW[2]",
- "8 PushW[3]",
- "8 PushW[4]",
- "8 PushW[5]",
- "8 PushW[6]",
- "8 PushW[7]",
-
- "8 MDRP[00]",
- "8 MDRP[01]",
- "8 MDRP[02]",
- "8 MDRP[03]",
- "8 MDRP[04]",
- "8 MDRP[05]",
- "8 MDRP[06]",
- "8 MDRP[07]",
- "8 MDRP[08]",
- "8 MDRP[09]",
- "8 MDRP[10]",
- "8 MDRP[11]",
- "8 MDRP[12]",
- "8 MDRP[13]",
- "8 MDRP[14]",
- "8 MDRP[15]",
-
- "8 MDRP[16]",
- "8 MDRP[17]",
- "8 MDRP[18]",
- "8 MDRP[19]",
- "8 MDRP[20]",
- "8 MDRP[21]",
- "8 MDRP[22]",
- "8 MDRP[23]",
- "8 MDRP[24]",
- "8 MDRP[25]",
- "8 MDRP[26]",
- "8 MDRP[27]",
- "8 MDRP[28]",
- "8 MDRP[29]",
- "8 MDRP[30]",
- "8 MDRP[31]",
-
- "8 MIRP[00]",
- "8 MIRP[01]",
- "8 MIRP[02]",
- "8 MIRP[03]",
- "8 MIRP[04]",
- "8 MIRP[05]",
- "8 MIRP[06]",
- "8 MIRP[07]",
- "8 MIRP[08]",
- "8 MIRP[09]",
- "8 MIRP[10]",
- "8 MIRP[11]",
- "8 MIRP[12]",
- "8 MIRP[13]",
- "8 MIRP[14]",
- "8 MIRP[15]",
-
- "8 MIRP[16]",
- "8 MIRP[17]",
- "8 MIRP[18]",
- "8 MIRP[19]",
- "8 MIRP[20]",
- "8 MIRP[21]",
- "8 MIRP[22]",
- "8 MIRP[23]",
- "8 MIRP[24]",
- "8 MIRP[25]",
- "8 MIRP[26]",
- "8 MIRP[27]",
- "8 MIRP[28]",
- "8 MIRP[29]",
- "8 MIRP[30]",
- "8 MIRP[31]"
- };
-
-#endif /* FT_DEBUG_LEVEL_TRACE */
-
-
- static
- const FT_Char opcode_length[256] =
- {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
- -1,-2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17,
-
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
- };
-
-#undef PACK
-
-
-#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
-
-#if defined( __arm__ ) && \
- ( defined( __thumb2__ ) || !defined( __thumb__ ) )
-
-#define TT_MulFix14 TT_MulFix14_arm
-
- static FT_Int32
- TT_MulFix14_arm( FT_Int32 a,
- FT_Int b )
- {
- FT_Int32 t, t2;
-
-
-#if defined( __CC_ARM ) || defined( __ARMCC__ )
-
- __asm
- {
- smull t2, t, b, a /* (lo=t2,hi=t) = a*b */
- mov a, t, asr #31 /* a = (hi >> 31) */
- add a, a, #0x2000 /* a += 0x2000 */
- adds t2, t2, a /* t2 += a */
- adc t, t, #0 /* t += carry */
- mov a, t2, lsr #14 /* a = t2 >> 14 */
- orr a, a, t, lsl #18 /* a |= t << 18 */
- }
-
-#elif defined( __GNUC__ )
-
- __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, #0x2000\n\t" /* %0 += 0x2000 */
-#else
- "add %0, %0, #0x2000\n\t" /* %0 += 0x2000 */
-#endif
- "adds %1, %1, %0\n\t" /* %1 += %0 */
- "adc %2, %2, #0\n\t" /* %2 += carry */
- "mov %0, %1, lsr #14\n\t" /* %0 = %1 >> 16 */
- "orr %0, %0, %2, lsl #18\n\t" /* %0 |= %2 << 16 */
- : "=r"(a), "=&r"(t2), "=&r"(t)
- : "r"(a), "r"(b)
- : "cc" );
-
-#endif
-
- return a;
- }
-
-#endif /* __arm__ && ( __thumb2__ || !__thumb__ ) */
-
-#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
-
-
-#if defined( __GNUC__ ) && \
- ( defined( __i386__ ) || defined( __x86_64__ ) )
-
-#define TT_MulFix14 TT_MulFix14_long_long
-
- /* Temporarily disable the warning that C90 doesn't support `long long'. */
-#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
-#pragma GCC diagnostic push
-#endif
-#pragma GCC diagnostic ignored "-Wlong-long"
-
- /* This is declared `noinline' because inlining the function results */
- /* in slower code. The `pure' attribute indicates that the result */
- /* only depends on the parameters. */
- static __attribute__(( noinline ))
- __attribute__(( pure )) FT_Int32
- TT_MulFix14_long_long( FT_Int32 a,
- FT_Int b )
- {
-
- long long ret = (long long)a * b;
-
- /* The following line assumes that right shifting of signed values */
- /* will actually preserve the sign bit. The exact behaviour is */
- /* undefined, but this is true on x86 and x86_64. */
- long long tmp = ret >> 63;
-
-
- ret += 0x2000 + tmp;
-
- return (FT_Int32)( ret >> 14 );
- }
-
-#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
-#pragma GCC diagnostic pop
-#endif
-
-#endif /* __GNUC__ && ( __i386__ || __x86_64__ ) */
-
-
-#ifndef TT_MulFix14
-
- /* Compute (a*b)/2^14 with maximum accuracy and rounding. */
- /* This is optimized to be faster than calling FT_MulFix() */
- /* for platforms where sizeof(int) == 2. */
- static FT_Int32
- TT_MulFix14( FT_Int32 a,
- FT_Int b )
- {
- FT_Int32 sign;
- FT_UInt32 ah, al, mid, lo, hi;
-
-
- sign = a ^ b;
-
- if ( a < 0 )
- a = -a;
- if ( b < 0 )
- b = -b;
-
- ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );
- al = (FT_UInt32)( a & 0xFFFFU );
-
- lo = al * b;
- mid = ah * b;
- hi = mid >> 16;
- mid = ( mid << 16 ) + ( 1 << 13 ); /* rounding */
- lo += mid;
- if ( lo < mid )
- hi += 1;
-
- mid = ( lo >> 14 ) | ( hi << 18 );
-
- return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
- }
-
-#endif /* !TT_MulFix14 */
-
-
-#if defined( __GNUC__ ) && \
- ( defined( __i386__ ) || \
- defined( __x86_64__ ) || \
- defined( __arm__ ) )
-
-#define TT_DotFix14 TT_DotFix14_long_long
-
-#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
-#pragma GCC diagnostic push
-#endif
-#pragma GCC diagnostic ignored "-Wlong-long"
-
- static __attribute__(( pure )) FT_Int32
- TT_DotFix14_long_long( FT_Int32 ax,
- FT_Int32 ay,
- FT_Int bx,
- FT_Int by )
- {
- /* Temporarily disable the warning that C90 doesn't support */
- /* `long long'. */
-
- long long temp1 = (long long)ax * bx;
- long long temp2 = (long long)ay * by;
-
-
- temp1 += temp2;
- temp2 = temp1 >> 63;
- temp1 += 0x2000 + temp2;
-
- return (FT_Int32)( temp1 >> 14 );
-
- }
-
-#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
-#pragma GCC diagnostic pop
-#endif
-
-#endif /* __GNUC__ && (__arm__ || __i386__ || __x86_64__) */
-
-
-#ifndef TT_DotFix14
-
- /* compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding */
- static FT_Int32
- TT_DotFix14( FT_Int32 ax,
- FT_Int32 ay,
- FT_Int bx,
- FT_Int by )
- {
- FT_Int32 m, s, hi1, hi2, hi;
- FT_UInt32 l, lo1, lo2, lo;
-
-
- /* compute ax*bx as 64-bit value */
- l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
- m = ( ax >> 16 ) * bx;
-
- lo1 = l + ( (FT_UInt32)m << 16 );
- hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
-
- /* compute ay*by as 64-bit value */
- l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
- m = ( ay >> 16 ) * by;
-
- lo2 = l + ( (FT_UInt32)m << 16 );
- hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
-
- /* add them */
- lo = lo1 + lo2;
- hi = hi1 + hi2 + ( lo < lo1 );
-
- /* divide the result by 2^14 with rounding */
- s = hi >> 31;
- l = lo + (FT_UInt32)s;
- hi += s + ( l < lo );
- lo = l;
-
- l = lo + 0x2000U;
- hi += ( l < lo );
-
- return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
- }
-
-#endif /* TT_DotFix14 */
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Current_Ratio */
- /* */
- /* <Description> */
- /* Returns the current aspect ratio scaling factor depending on the */
- /* projection vector's state and device resolutions. */
- /* */
- /* <Return> */
- /* The aspect ratio in 16.16 format, always <= 1.0 . */
- /* */
- static FT_Long
- Current_Ratio( TT_ExecContext exc )
- {
- if ( !exc->tt_metrics.ratio )
- {
- if ( exc->GS.projVector.y == 0 )
- exc->tt_metrics.ratio = exc->tt_metrics.x_ratio;
-
- else if ( exc->GS.projVector.x == 0 )
- exc->tt_metrics.ratio = exc->tt_metrics.y_ratio;
-
- else
- {
- FT_F26Dot6 x, y;
-
-
- x = TT_MulFix14( exc->tt_metrics.x_ratio,
- exc->GS.projVector.x );
- y = TT_MulFix14( exc->tt_metrics.y_ratio,
- exc->GS.projVector.y );
- exc->tt_metrics.ratio = FT_Hypot( x, y );
- }
- }
- return exc->tt_metrics.ratio;
- }
-
-
- FT_CALLBACK_DEF( FT_Long )
- Current_Ppem( TT_ExecContext exc )
- {
- return exc->tt_metrics.ppem;
- }
-
-
- FT_CALLBACK_DEF( FT_Long )
- Current_Ppem_Stretched( TT_ExecContext exc )
- {
- return FT_MulFix( exc->tt_metrics.ppem, Current_Ratio( exc ) );
- }
-
-
- /*************************************************************************/
- /* */
- /* Functions related to the control value table (CVT). */
- /* */
- /*************************************************************************/
-
-
- FT_CALLBACK_DEF( FT_F26Dot6 )
- Read_CVT( TT_ExecContext exc,
- FT_ULong idx )
- {
- return exc->cvt[idx];
- }
-
-
- FT_CALLBACK_DEF( FT_F26Dot6 )
- Read_CVT_Stretched( TT_ExecContext exc,
- FT_ULong idx )
- {
- return FT_MulFix( exc->cvt[idx], Current_Ratio( exc ) );
- }
-
-
- FT_CALLBACK_DEF( void )
- Write_CVT( TT_ExecContext exc,
- FT_ULong idx,
- FT_F26Dot6 value )
- {
- exc->cvt[idx] = value;
- }
-
-
- FT_CALLBACK_DEF( void )
- Write_CVT_Stretched( TT_ExecContext exc,
- FT_ULong idx,
- FT_F26Dot6 value )
- {
- exc->cvt[idx] = FT_DivFix( value, Current_Ratio( exc ) );
- }
-
-
- FT_CALLBACK_DEF( void )
- Move_CVT( TT_ExecContext exc,
- FT_ULong idx,
- FT_F26Dot6 value )
- {
- exc->cvt[idx] += value;
- }
-
-
- FT_CALLBACK_DEF( void )
- Move_CVT_Stretched( TT_ExecContext exc,
- FT_ULong idx,
- FT_F26Dot6 value )
- {
- exc->cvt[idx] += FT_DivFix( value, Current_Ratio( exc ) );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* GetShortIns */
- /* */
- /* <Description> */
- /* Returns a short integer taken from the instruction stream at */
- /* address IP. */
- /* */
- /* <Return> */
- /* Short read at code[IP]. */
- /* */
- /* <Note> */
- /* This one could become a macro. */
- /* */
- static FT_Short
- GetShortIns( TT_ExecContext exc )
- {
- /* Reading a byte stream so there is no endianness (DaveP) */
- exc->IP += 2;
- return (FT_Short)( ( exc->code[exc->IP - 2] << 8 ) +
- exc->code[exc->IP - 1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Ins_Goto_CodeRange */
- /* */
- /* <Description> */
- /* Goes to a certain code range in the instruction stream. */
- /* */
- /* <Input> */
- /* aRange :: The index of the code range. */
- /* */
- /* aIP :: The new IP address in the code range. */
- /* */
- /* <Return> */
- /* SUCCESS or FAILURE. */
- /* */
- static FT_Bool
- Ins_Goto_CodeRange( TT_ExecContext exc,
- FT_Int aRange,
- FT_Long aIP )
- {
- TT_CodeRange* range;
-
-
- if ( aRange < 1 || aRange > 3 )
- {
- exc->error = FT_THROW( Bad_Argument );
- return FAILURE;
- }
-
- range = &exc->codeRangeTable[aRange - 1];
-
- if ( !range->base ) /* invalid coderange */
- {
- exc->error = FT_THROW( Invalid_CodeRange );
- return FAILURE;
- }
-
- /* NOTE: Because the last instruction of a program may be a CALL */
- /* which will return to the first byte *after* the code */
- /* range, we test for aIP <= Size, instead of aIP < Size. */
-
- if ( aIP > range->size )
- {
- exc->error = FT_THROW( Code_Overflow );
- return FAILURE;
- }
-
- exc->code = range->base;
- exc->codeSize = range->size;
- exc->IP = aIP;
- exc->curRange = aRange;
-
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Direct_Move */
- /* */
- /* <Description> */
- /* Moves a point by a given distance along the freedom vector. The */
- /* point will be `touched'. */
- /* */
- /* <Input> */
- /* point :: The index of the point to move. */
- /* */
- /* distance :: The distance to apply. */
- /* */
- /* <InOut> */
- /* zone :: The affected glyph zone. */
- /* */
- /* <Note> */
- /* See `ttinterp.h' for details on backwards compatibility mode. */
- /* `Touches' the point. */
- /* */
- static void
- Direct_Move( TT_ExecContext exc,
- TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
- {
- FT_F26Dot6 v;
-
-
- v = exc->GS.freeVector.x;
-
- if ( v != 0 )
- {
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- ( !exc->ignore_x_mode ||
- ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
- zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
- else
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* Exception to the post-IUP curfew: Allow the x component of */
- /* diagonal moves, but only post-IUP. DejaVu tries to adjust */
- /* diagonal stems like on `Z' and `z' post-IUP. */
- if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility )
- zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
- else
-#endif
-
- if ( NO_SUBPIXEL_HINTING )
- zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
-
- zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
- }
-
- v = exc->GS.freeVector.y;
-
- if ( v != 0 )
- {
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( !( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called &&
- exc->iupy_called ) )
-#endif
- zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
-
- zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Direct_Move_Orig */
- /* */
- /* <Description> */
- /* Moves the *original* position of a point by a given distance along */
- /* the freedom vector. Obviously, the point will not be `touched'. */
- /* */
- /* <Input> */
- /* point :: The index of the point to move. */
- /* */
- /* distance :: The distance to apply. */
- /* */
- /* <InOut> */
- /* zone :: The affected glyph zone. */
- /* */
- static void
- Direct_Move_Orig( TT_ExecContext exc,
- TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
- {
- FT_F26Dot6 v;
-
-
- v = exc->GS.freeVector.x;
-
- if ( v != 0 )
- zone->org[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
-
- v = exc->GS.freeVector.y;
-
- if ( v != 0 )
- zone->org[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
- }
-
-
- /*************************************************************************/
- /* */
- /* Special versions of Direct_Move() */
- /* */
- /* The following versions are used whenever both vectors are both */
- /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
- /* See `ttinterp.h' for details on backwards compatibility mode. */
- /* */
- /*************************************************************************/
-
-
- static void
- Direct_Move_X( TT_ExecContext exc,
- TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
- {
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode )
- zone->cur[point].x += distance;
- else
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility )
- zone->cur[point].x += distance;
- else
-#endif
-
- if ( NO_SUBPIXEL_HINTING )
- zone->cur[point].x += distance;
-
- zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
- }
-
-
- static void
- Direct_Move_Y( TT_ExecContext exc,
- TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
- {
- FT_UNUSED( exc );
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( !( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called && exc->iupy_called ) )
-#endif
- zone->cur[point].y += distance;
-
- zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
- }
-
-
- /*************************************************************************/
- /* */
- /* Special versions of Direct_Move_Orig() */
- /* */
- /* The following versions are used whenever both vectors are both */
- /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */
- /* */
- /*************************************************************************/
-
-
- static void
- Direct_Move_Orig_X( TT_ExecContext exc,
- TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
- {
- FT_UNUSED( exc );
-
- zone->org[point].x += distance;
- }
-
-
- static void
- Direct_Move_Orig_Y( TT_ExecContext exc,
- TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
- {
- FT_UNUSED( exc );
-
- zone->org[point].y += distance;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_None */
- /* */
- /* <Description> */
- /* Does not round, but adds engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance (not) to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* The compensated distance. */
- /* */
- /* <Note> */
- /* The TrueType specification says very few about the relationship */
- /* between rounding and engine compensation. However, it seems from */
- /* the description of super round that we should add the compensation */
- /* before rounding. */
- /* */
- static FT_F26Dot6
- Round_None( TT_ExecContext exc,
- FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
- {
- FT_F26Dot6 val;
-
- FT_UNUSED( exc );
-
-
- if ( distance >= 0 )
- {
- val = distance + compensation;
- if ( val < 0 )
- val = 0;
- }
- else
- {
- val = distance - compensation;
- if ( val > 0 )
- val = 0;
- }
- return val;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_To_Grid */
- /* */
- /* <Description> */
- /* Rounds value to grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
- static FT_F26Dot6
- Round_To_Grid( TT_ExecContext exc,
- FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
- {
- FT_F26Dot6 val;
-
- FT_UNUSED( exc );
-
-
- if ( distance >= 0 )
- {
- val = FT_PIX_ROUND( distance + compensation );
- if ( val < 0 )
- val = 0;
- }
- else
- {
- val = -FT_PIX_ROUND( compensation - distance );
- if ( val > 0 )
- val = 0;
- }
-
- return val;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_To_Half_Grid */
- /* */
- /* <Description> */
- /* Rounds value to half grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
- static FT_F26Dot6
- Round_To_Half_Grid( TT_ExecContext exc,
- FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
- {
- FT_F26Dot6 val;
-
- FT_UNUSED( exc );
-
-
- if ( distance >= 0 )
- {
- val = FT_PIX_FLOOR( distance + compensation ) + 32;
- if ( val < 0 )
- val = 32;
- }
- else
- {
- val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
- if ( val > 0 )
- val = -32;
- }
-
- return val;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_Down_To_Grid */
- /* */
- /* <Description> */
- /* Rounds value down to grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
- static FT_F26Dot6
- Round_Down_To_Grid( TT_ExecContext exc,
- FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
- {
- FT_F26Dot6 val;
-
- FT_UNUSED( exc );
-
-
- if ( distance >= 0 )
- {
- val = FT_PIX_FLOOR( distance + compensation );
- if ( val < 0 )
- val = 0;
- }
- else
- {
- val = -FT_PIX_FLOOR( compensation - distance );
- if ( val > 0 )
- val = 0;
- }
-
- return val;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_Up_To_Grid */
- /* */
- /* <Description> */
- /* Rounds value up to grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
- static FT_F26Dot6
- Round_Up_To_Grid( TT_ExecContext exc,
- FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
- {
- FT_F26Dot6 val;
-
- FT_UNUSED( exc );
-
-
- if ( distance >= 0 )
- {
- val = FT_PIX_CEIL( distance + compensation );
- if ( val < 0 )
- val = 0;
- }
- else
- {
- val = -FT_PIX_CEIL( compensation - distance );
- if ( val > 0 )
- val = 0;
- }
-
- return val;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_To_Double_Grid */
- /* */
- /* <Description> */
- /* Rounds value to double grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
- static FT_F26Dot6
- Round_To_Double_Grid( TT_ExecContext exc,
- FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
- {
- FT_F26Dot6 val;
-
- FT_UNUSED( exc );
-
-
- if ( distance >= 0 )
- {
- val = FT_PAD_ROUND( distance + compensation, 32 );
- if ( val < 0 )
- val = 0;
- }
- else
- {
- val = -FT_PAD_ROUND( compensation - distance, 32 );
- if ( val > 0 )
- val = 0;
- }
-
- return val;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_Super */
- /* */
- /* <Description> */
- /* Super-rounds value to grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
- /* <Note> */
- /* The TrueType specification says very little about the relationship */
- /* between rounding and engine compensation. However, it seems from */
- /* the description of super round that we should add the compensation */
- /* before rounding. */
- /* */
- static FT_F26Dot6
- Round_Super( TT_ExecContext exc,
- FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
- {
- FT_F26Dot6 val;
-
-
- if ( distance >= 0 )
- {
- val = ( distance - exc->phase + exc->threshold + compensation ) &
- -exc->period;
- val += exc->phase;
- if ( val < 0 )
- val = exc->phase;
- }
- else
- {
- val = -( ( exc->threshold - exc->phase - distance + compensation ) &
- -exc->period );
- val -= exc->phase;
- if ( val > 0 )
- val = -exc->phase;
- }
-
- return val;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Round_Super_45 */
- /* */
- /* <Description> */
- /* Super-rounds value to grid after adding engine compensation. */
- /* */
- /* <Input> */
- /* distance :: The distance to round. */
- /* */
- /* compensation :: The engine compensation. */
- /* */
- /* <Return> */
- /* Rounded distance. */
- /* */
- /* <Note> */
- /* There is a separate function for Round_Super_45() as we may need */
- /* greater precision. */
- /* */
- static FT_F26Dot6
- Round_Super_45( TT_ExecContext exc,
- FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
- {
- FT_F26Dot6 val;
-
-
- if ( distance >= 0 )
- {
- val = ( ( distance - exc->phase + exc->threshold + compensation ) /
- exc->period ) * exc->period;
- val += exc->phase;
- if ( val < 0 )
- val = exc->phase;
- }
- else
- {
- val = -( ( ( exc->threshold - exc->phase - distance + compensation ) /
- exc->period ) * exc->period );
- val -= exc->phase;
- if ( val > 0 )
- val = -exc->phase;
- }
-
- return val;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Compute_Round */
- /* */
- /* <Description> */
- /* Sets the rounding mode. */
- /* */
- /* <Input> */
- /* round_mode :: The rounding mode to be used. */
- /* */
- static void
- Compute_Round( TT_ExecContext exc,
- FT_Byte round_mode )
- {
- switch ( round_mode )
- {
- case TT_Round_Off:
- exc->func_round = (TT_Round_Func)Round_None;
- break;
-
- case TT_Round_To_Grid:
- exc->func_round = (TT_Round_Func)Round_To_Grid;
- break;
-
- case TT_Round_Up_To_Grid:
- exc->func_round = (TT_Round_Func)Round_Up_To_Grid;
- break;
-
- case TT_Round_Down_To_Grid:
- exc->func_round = (TT_Round_Func)Round_Down_To_Grid;
- break;
-
- case TT_Round_To_Half_Grid:
- exc->func_round = (TT_Round_Func)Round_To_Half_Grid;
- break;
-
- case TT_Round_To_Double_Grid:
- exc->func_round = (TT_Round_Func)Round_To_Double_Grid;
- break;
-
- case TT_Round_Super:
- exc->func_round = (TT_Round_Func)Round_Super;
- break;
-
- case TT_Round_Super_45:
- exc->func_round = (TT_Round_Func)Round_Super_45;
- break;
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* SetSuperRound */
- /* */
- /* <Description> */
- /* Sets Super Round parameters. */
- /* */
- /* <Input> */
- /* GridPeriod :: The grid period. */
- /* */
- /* selector :: The SROUND opcode. */
- /* */
- static void
- SetSuperRound( TT_ExecContext exc,
- FT_F2Dot14 GridPeriod,
- FT_Long selector )
- {
- switch ( (FT_Int)( selector & 0xC0 ) )
- {
- case 0:
- exc->period = GridPeriod / 2;
- break;
-
- case 0x40:
- exc->period = GridPeriod;
- break;
-
- case 0x80:
- exc->period = GridPeriod * 2;
- break;
-
- /* This opcode is reserved, but... */
- case 0xC0:
- exc->period = GridPeriod;
- break;
- }
-
- switch ( (FT_Int)( selector & 0x30 ) )
- {
- case 0:
- exc->phase = 0;
- break;
-
- case 0x10:
- exc->phase = exc->period / 4;
- break;
-
- case 0x20:
- exc->phase = exc->period / 2;
- break;
-
- case 0x30:
- exc->phase = exc->period * 3 / 4;
- break;
- }
-
- if ( ( selector & 0x0F ) == 0 )
- exc->threshold = exc->period - 1;
- else
- exc->threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * exc->period / 8;
-
- /* convert to F26Dot6 format */
- exc->period >>= 8;
- exc->phase >>= 8;
- exc->threshold >>= 8;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Project */
- /* */
- /* <Description> */
- /* Computes the projection of vector given by (v2-v1) along the */
- /* current projection vector. */
- /* */
- /* <Input> */
- /* v1 :: First input vector. */
- /* v2 :: Second input vector. */
- /* */
- /* <Return> */
- /* The distance in F26dot6 format. */
- /* */
- static FT_F26Dot6
- Project( TT_ExecContext exc,
- FT_Pos dx,
- FT_Pos dy )
- {
- return TT_DotFix14( dx, dy,
- exc->GS.projVector.x,
- exc->GS.projVector.y );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Dual_Project */
- /* */
- /* <Description> */
- /* Computes the projection of the vector given by (v2-v1) along the */
- /* current dual vector. */
- /* */
- /* <Input> */
- /* v1 :: First input vector. */
- /* v2 :: Second input vector. */
- /* */
- /* <Return> */
- /* The distance in F26dot6 format. */
- /* */
- static FT_F26Dot6
- Dual_Project( TT_ExecContext exc,
- FT_Pos dx,
- FT_Pos dy )
- {
- return TT_DotFix14( dx, dy,
- exc->GS.dualVector.x,
- exc->GS.dualVector.y );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Project_x */
- /* */
- /* <Description> */
- /* Computes the projection of the vector given by (v2-v1) along the */
- /* horizontal axis. */
- /* */
- /* <Input> */
- /* v1 :: First input vector. */
- /* v2 :: Second input vector. */
- /* */
- /* <Return> */
- /* The distance in F26dot6 format. */
- /* */
- static FT_F26Dot6
- Project_x( TT_ExecContext exc,
- FT_Pos dx,
- FT_Pos dy )
- {
- FT_UNUSED( exc );
- FT_UNUSED( dy );
-
- return dx;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Project_y */
- /* */
- /* <Description> */
- /* Computes the projection of the vector given by (v2-v1) along the */
- /* vertical axis. */
- /* */
- /* <Input> */
- /* v1 :: First input vector. */
- /* v2 :: Second input vector. */
- /* */
- /* <Return> */
- /* The distance in F26dot6 format. */
- /* */
- static FT_F26Dot6
- Project_y( TT_ExecContext exc,
- FT_Pos dx,
- FT_Pos dy )
- {
- FT_UNUSED( exc );
- FT_UNUSED( dx );
-
- return dy;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Compute_Funcs */
- /* */
- /* <Description> */
- /* Computes the projection and movement function pointers according */
- /* to the current graphics state. */
- /* */
- static void
- Compute_Funcs( TT_ExecContext exc )
- {
- if ( exc->GS.freeVector.x == 0x4000 )
- exc->F_dot_P = exc->GS.projVector.x;
- else if ( exc->GS.freeVector.y == 0x4000 )
- exc->F_dot_P = exc->GS.projVector.y;
- else
- exc->F_dot_P =
- ( (FT_Long)exc->GS.projVector.x * exc->GS.freeVector.x +
- (FT_Long)exc->GS.projVector.y * exc->GS.freeVector.y ) >> 14;
-
- if ( exc->GS.projVector.x == 0x4000 )
- exc->func_project = (TT_Project_Func)Project_x;
- else if ( exc->GS.projVector.y == 0x4000 )
- exc->func_project = (TT_Project_Func)Project_y;
- else
- exc->func_project = (TT_Project_Func)Project;
-
- if ( exc->GS.dualVector.x == 0x4000 )
- exc->func_dualproj = (TT_Project_Func)Project_x;
- else if ( exc->GS.dualVector.y == 0x4000 )
- exc->func_dualproj = (TT_Project_Func)Project_y;
- else
- exc->func_dualproj = (TT_Project_Func)Dual_Project;
-
- exc->func_move = (TT_Move_Func)Direct_Move;
- exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig;
-
- if ( exc->F_dot_P == 0x4000L )
- {
- if ( exc->GS.freeVector.x == 0x4000 )
- {
- exc->func_move = (TT_Move_Func)Direct_Move_X;
- exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
- }
- else if ( exc->GS.freeVector.y == 0x4000 )
- {
- exc->func_move = (TT_Move_Func)Direct_Move_Y;
- exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
- }
- }
-
- /* at small sizes, F_dot_P can become too small, resulting */
- /* in overflows and `spikes' in a number of glyphs like `w'. */
-
- if ( FT_ABS( exc->F_dot_P ) < 0x400L )
- exc->F_dot_P = 0x4000L;
-
- /* Disable cached aspect ratio */
- exc->tt_metrics.ratio = 0;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Normalize */
- /* */
- /* <Description> */
- /* Norms a vector. */
- /* */
- /* <Input> */
- /* Vx :: The horizontal input vector coordinate. */
- /* Vy :: The vertical input vector coordinate. */
- /* */
- /* <Output> */
- /* R :: The normed unit vector. */
- /* */
- /* <Return> */
- /* Returns FAILURE if a vector parameter is zero. */
- /* */
- /* <Note> */
- /* In case Vx and Vy are both zero, `Normalize' returns SUCCESS, and */
- /* R is undefined. */
- /* */
- static FT_Bool
- Normalize( FT_F26Dot6 Vx,
- FT_F26Dot6 Vy,
- FT_UnitVector* R )
- {
- FT_Vector V;
-
-
- if ( Vx == 0 && Vy == 0 )
- {
- /* XXX: UNDOCUMENTED! It seems that it is possible to try */
- /* to normalize the vector (0,0). Return immediately. */
- return SUCCESS;
- }
-
- V.x = Vx;
- V.y = Vy;
-
- FT_Vector_NormLen( &V );
-
- R->x = (FT_F2Dot14)( V.x / 4 );
- R->y = (FT_F2Dot14)( V.y / 4 );
-
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* Here we start with the implementation of the various opcodes. */
- /* */
- /*************************************************************************/
-
-
-#define ARRAY_BOUND_ERROR \
- do \
- { \
- exc->error = FT_THROW( Invalid_Reference ); \
- return; \
- } while (0)
-
-
- /*************************************************************************/
- /* */
- /* MPPEM[]: Measure Pixel Per EM */
- /* Opcode range: 0x4B */
- /* Stack: --> Euint16 */
- /* */
- static void
- Ins_MPPEM( TT_ExecContext exc,
- FT_Long* args )
- {
- args[0] = exc->func_cur_ppem( exc );
- }
-
-
- /*************************************************************************/
- /* */
- /* MPS[]: Measure Point Size */
- /* Opcode range: 0x4C */
- /* Stack: --> Euint16 */
- /* */
- static void
- Ins_MPS( TT_ExecContext exc,
- FT_Long* args )
- {
- if ( NO_SUBPIXEL_HINTING )
- {
- /* Microsoft's GDI bytecode interpreter always returns value 12; */
- /* we return the current PPEM value instead. */
- args[0] = exc->func_cur_ppem( exc );
- }
- else
- {
- /* A possible practical application of the MPS instruction is to */
- /* implement optical scaling and similar features, which should be */
- /* based on perceptual attributes, thus independent of the */
- /* resolution. */
- args[0] = exc->pointSize;
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* DUP[]: DUPlicate the stack's top element */
- /* Opcode range: 0x20 */
- /* Stack: StkElt --> StkElt StkElt */
- /* */
- static void
- Ins_DUP( FT_Long* args )
- {
- args[1] = args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* POP[]: POP the stack's top element */
- /* Opcode range: 0x21 */
- /* Stack: StkElt --> */
- /* */
- static void
- Ins_POP( void )
- {
- /* nothing to do */
- }
-
-
- /*************************************************************************/
- /* */
- /* CLEAR[]: CLEAR the entire stack */
- /* Opcode range: 0x22 */
- /* Stack: StkElt... --> */
- /* */
- static void
- Ins_CLEAR( TT_ExecContext exc )
- {
- exc->new_top = 0;
- }
-
-
- /*************************************************************************/
- /* */
- /* SWAP[]: SWAP the stack's top two elements */
- /* Opcode range: 0x23 */
- /* Stack: 2 * StkElt --> 2 * StkElt */
- /* */
- static void
- Ins_SWAP( FT_Long* args )
- {
- FT_Long L;
-
-
- L = args[0];
- args[0] = args[1];
- args[1] = L;
- }
-
-
- /*************************************************************************/
- /* */
- /* DEPTH[]: return the stack DEPTH */
- /* Opcode range: 0x24 */
- /* Stack: --> uint32 */
- /* */
- static void
- Ins_DEPTH( TT_ExecContext exc,
- FT_Long* args )
- {
- args[0] = exc->top;
- }
-
-
- /*************************************************************************/
- /* */
- /* LT[]: Less Than */
- /* Opcode range: 0x50 */
- /* Stack: int32? int32? --> bool */
- /* */
- static void
- Ins_LT( FT_Long* args )
- {
- args[0] = ( args[0] < args[1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* LTEQ[]: Less Than or EQual */
- /* Opcode range: 0x51 */
- /* Stack: int32? int32? --> bool */
- /* */
- static void
- Ins_LTEQ( FT_Long* args )
- {
- args[0] = ( args[0] <= args[1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* GT[]: Greater Than */
- /* Opcode range: 0x52 */
- /* Stack: int32? int32? --> bool */
- /* */
- static void
- Ins_GT( FT_Long* args )
- {
- args[0] = ( args[0] > args[1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* GTEQ[]: Greater Than or EQual */
- /* Opcode range: 0x53 */
- /* Stack: int32? int32? --> bool */
- /* */
- static void
- Ins_GTEQ( FT_Long* args )
- {
- args[0] = ( args[0] >= args[1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* EQ[]: EQual */
- /* Opcode range: 0x54 */
- /* Stack: StkElt StkElt --> bool */
- /* */
- static void
- Ins_EQ( FT_Long* args )
- {
- args[0] = ( args[0] == args[1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* NEQ[]: Not EQual */
- /* Opcode range: 0x55 */
- /* Stack: StkElt StkElt --> bool */
- /* */
- static void
- Ins_NEQ( FT_Long* args )
- {
- args[0] = ( args[0] != args[1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* ODD[]: Is ODD */
- /* Opcode range: 0x56 */
- /* Stack: f26.6 --> bool */
- /* */
- static void
- Ins_ODD( TT_ExecContext exc,
- FT_Long* args )
- {
- args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 127 ) == 64 );
- }
-
-
- /*************************************************************************/
- /* */
- /* EVEN[]: Is EVEN */
- /* Opcode range: 0x57 */
- /* Stack: f26.6 --> bool */
- /* */
- static void
- Ins_EVEN( TT_ExecContext exc,
- FT_Long* args )
- {
- args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 127 ) == 0 );
- }
-
-
- /*************************************************************************/
- /* */
- /* AND[]: logical AND */
- /* Opcode range: 0x5A */
- /* Stack: uint32 uint32 --> uint32 */
- /* */
- static void
- Ins_AND( FT_Long* args )
- {
- args[0] = ( args[0] && args[1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* OR[]: logical OR */
- /* Opcode range: 0x5B */
- /* Stack: uint32 uint32 --> uint32 */
- /* */
- static void
- Ins_OR( FT_Long* args )
- {
- args[0] = ( args[0] || args[1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* NOT[]: logical NOT */
- /* Opcode range: 0x5C */
- /* Stack: StkElt --> uint32 */
- /* */
- static void
- Ins_NOT( FT_Long* args )
- {
- args[0] = !args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* ADD[]: ADD */
- /* Opcode range: 0x60 */
- /* Stack: f26.6 f26.6 --> f26.6 */
- /* */
- static void
- Ins_ADD( FT_Long* args )
- {
- args[0] += args[1];
- }
-
-
- /*************************************************************************/
- /* */
- /* SUB[]: SUBtract */
- /* Opcode range: 0x61 */
- /* Stack: f26.6 f26.6 --> f26.6 */
- /* */
- static void
- Ins_SUB( FT_Long* args )
- {
- args[0] -= args[1];
- }
-
-
- /*************************************************************************/
- /* */
- /* DIV[]: DIVide */
- /* Opcode range: 0x62 */
- /* Stack: f26.6 f26.6 --> f26.6 */
- /* */
- static void
- Ins_DIV( TT_ExecContext exc,
- FT_Long* args )
- {
- if ( args[1] == 0 )
- exc->error = FT_THROW( Divide_By_Zero );
- else
- args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* MUL[]: MULtiply */
- /* Opcode range: 0x63 */
- /* Stack: f26.6 f26.6 --> f26.6 */
- /* */
- static void
- Ins_MUL( FT_Long* args )
- {
- args[0] = FT_MulDiv( args[0], args[1], 64L );
- }
-
-
- /*************************************************************************/
- /* */
- /* ABS[]: ABSolute value */
- /* Opcode range: 0x64 */
- /* Stack: f26.6 --> f26.6 */
- /* */
- static void
- Ins_ABS( FT_Long* args )
- {
- args[0] = FT_ABS( args[0] );
- }
-
-
- /*************************************************************************/
- /* */
- /* NEG[]: NEGate */
- /* Opcode range: 0x65 */
- /* Stack: f26.6 --> f26.6 */
- /* */
- static void
- Ins_NEG( FT_Long* args )
- {
- args[0] = -args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* FLOOR[]: FLOOR */
- /* Opcode range: 0x66 */
- /* Stack: f26.6 --> f26.6 */
- /* */
- static void
- Ins_FLOOR( FT_Long* args )
- {
- args[0] = FT_PIX_FLOOR( args[0] );
- }
-
-
- /*************************************************************************/
- /* */
- /* CEILING[]: CEILING */
- /* Opcode range: 0x67 */
- /* Stack: f26.6 --> f26.6 */
- /* */
- static void
- Ins_CEILING( FT_Long* args )
- {
- args[0] = FT_PIX_CEIL( args[0] );
- }
-
-
- /*************************************************************************/
- /* */
- /* RS[]: Read Store */
- /* Opcode range: 0x43 */
- /* Stack: uint32 --> uint32 */
- /* */
- static void
- Ins_RS( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong I = (FT_ULong)args[0];
-
-
- if ( BOUNDSL( I, exc->storeSize ) )
- {
- if ( exc->pedantic_hinting )
- ARRAY_BOUND_ERROR;
- else
- args[0] = 0;
- }
- else
- {
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /* subpixel hinting - avoid Typeman Dstroke and */
- /* IStroke and Vacuform rounds */
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- ( ( I == 24 &&
- ( exc->face->sph_found_func_flags &
- ( SPH_FDEF_SPACING_1 |
- SPH_FDEF_SPACING_2 ) ) ) ||
- ( I == 22 &&
- ( exc->sph_in_func_flags &
- SPH_FDEF_TYPEMAN_STROKES ) ) ||
- ( I == 8 &&
- ( exc->face->sph_found_func_flags &
- SPH_FDEF_VACUFORM_ROUND_1 ) &&
- exc->iup_called ) ) )
- args[0] = 0;
- else
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
- args[0] = exc->storage[I];
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* WS[]: Write Store */
- /* Opcode range: 0x42 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_WS( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong I = (FT_ULong)args[0];
-
-
- if ( BOUNDSL( I, exc->storeSize ) )
- {
- if ( exc->pedantic_hinting )
- ARRAY_BOUND_ERROR;
- }
- else
- exc->storage[I] = args[1];
- }
-
-
- /*************************************************************************/
- /* */
- /* WCVTP[]: Write CVT in Pixel units */
- /* Opcode range: 0x44 */
- /* Stack: f26.6 uint32 --> */
- /* */
- static void
- Ins_WCVTP( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong I = (FT_ULong)args[0];
-
-
- if ( BOUNDSL( I, exc->cvtSize ) )
- {
- if ( exc->pedantic_hinting )
- ARRAY_BOUND_ERROR;
- }
- else
- exc->func_write_cvt( exc, I, args[1] );
- }
-
-
- /*************************************************************************/
- /* */
- /* WCVTF[]: Write CVT in Funits */
- /* Opcode range: 0x70 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_WCVTF( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong I = (FT_ULong)args[0];
-
-
- if ( BOUNDSL( I, exc->cvtSize ) )
- {
- if ( exc->pedantic_hinting )
- ARRAY_BOUND_ERROR;
- }
- else
- exc->cvt[I] = FT_MulFix( args[1], exc->tt_metrics.scale );
- }
-
-
- /*************************************************************************/
- /* */
- /* RCVT[]: Read CVT */
- /* Opcode range: 0x45 */
- /* Stack: uint32 --> f26.6 */
- /* */
- static void
- Ins_RCVT( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong I = (FT_ULong)args[0];
-
-
- if ( BOUNDSL( I, exc->cvtSize ) )
- {
- if ( exc->pedantic_hinting )
- ARRAY_BOUND_ERROR;
- else
- args[0] = 0;
- }
- else
- args[0] = exc->func_read_cvt( exc, I );
- }
-
-
- /*************************************************************************/
- /* */
- /* AA[]: Adjust Angle */
- /* Opcode range: 0x7F */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_AA( void )
- {
- /* intentionally no longer supported */
- }
-
-
- /*************************************************************************/
- /* */
- /* DEBUG[]: DEBUG. Unsupported. */
- /* Opcode range: 0x4F */
- /* Stack: uint32 --> */
- /* */
- /* Note: The original instruction pops a value from the stack. */
- /* */
- static void
- Ins_DEBUG( TT_ExecContext exc )
- {
- exc->error = FT_THROW( Debug_OpCode );
- }
-
-
- /*************************************************************************/
- /* */
- /* ROUND[ab]: ROUND value */
- /* Opcode range: 0x68-0x6B */
- /* Stack: f26.6 --> f26.6 */
- /* */
- static void
- Ins_ROUND( TT_ExecContext exc,
- FT_Long* args )
- {
- args[0] = exc->func_round(
- exc,
- args[0],
- exc->tt_metrics.compensations[exc->opcode - 0x68] );
- }
-
-
- /*************************************************************************/
- /* */
- /* NROUND[ab]: No ROUNDing of value */
- /* Opcode range: 0x6C-0x6F */
- /* Stack: f26.6 --> f26.6 */
- /* */
- static void
- Ins_NROUND( TT_ExecContext exc,
- FT_Long* args )
- {
- args[0] = Round_None(
- exc,
- args[0],
- exc->tt_metrics.compensations[exc->opcode - 0x6C] );
- }
-
-
- /*************************************************************************/
- /* */
- /* MAX[]: MAXimum */
- /* Opcode range: 0x8B */
- /* Stack: int32? int32? --> int32 */
- /* */
- static void
- Ins_MAX( FT_Long* args )
- {
- if ( args[1] > args[0] )
- args[0] = args[1];
- }
-
-
- /*************************************************************************/
- /* */
- /* MIN[]: MINimum */
- /* Opcode range: 0x8C */
- /* Stack: int32? int32? --> int32 */
- /* */
- static void
- Ins_MIN( FT_Long* args )
- {
- if ( args[1] < args[0] )
- args[0] = args[1];
- }
-
-
- /*************************************************************************/
- /* */
- /* MINDEX[]: Move INDEXed element */
- /* Opcode range: 0x26 */
- /* Stack: int32? --> StkElt */
- /* */
- static void
- Ins_MINDEX( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_Long L, K;
-
-
- L = args[0];
-
- if ( L <= 0 || L > exc->args )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- }
- else
- {
- K = exc->stack[exc->args - L];
-
- FT_ARRAY_MOVE( &exc->stack[exc->args - L ],
- &exc->stack[exc->args - L + 1],
- ( L - 1 ) );
-
- exc->stack[exc->args - 1] = K;
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* CINDEX[]: Copy INDEXed element */
- /* Opcode range: 0x25 */
- /* Stack: int32 --> StkElt */
- /* */
- static void
- Ins_CINDEX( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_Long L;
-
-
- L = args[0];
-
- if ( L <= 0 || L > exc->args )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- args[0] = 0;
- }
- else
- args[0] = exc->stack[exc->args - L];
- }
-
-
- /*************************************************************************/
- /* */
- /* ROLL[]: ROLL top three elements */
- /* Opcode range: 0x8A */
- /* Stack: 3 * StkElt --> 3 * StkElt */
- /* */
- static void
- Ins_ROLL( FT_Long* args )
- {
- FT_Long A, B, C;
-
-
- A = args[2];
- B = args[1];
- C = args[0];
-
- args[2] = C;
- args[1] = A;
- args[0] = B;
- }
-
-
- /*************************************************************************/
- /* */
- /* MANAGING THE FLOW OF CONTROL */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* SLOOP[]: Set LOOP variable */
- /* Opcode range: 0x17 */
- /* Stack: int32? --> */
- /* */
- static void
- Ins_SLOOP( TT_ExecContext exc,
- FT_Long* args )
- {
- if ( args[0] < 0 )
- exc->error = FT_THROW( Bad_Argument );
- else
- exc->GS.loop = args[0];
- }
-
-
- static FT_Bool
- SkipCode( TT_ExecContext exc )
- {
- exc->IP += exc->length;
-
- if ( exc->IP < exc->codeSize )
- {
- exc->opcode = exc->code[exc->IP];
-
- exc->length = opcode_length[exc->opcode];
- if ( exc->length < 0 )
- {
- if ( exc->IP + 1 >= exc->codeSize )
- goto Fail_Overflow;
- exc->length = 2 - exc->length * exc->code[exc->IP + 1];
- }
-
- if ( exc->IP + exc->length <= exc->codeSize )
- return SUCCESS;
- }
-
- Fail_Overflow:
- exc->error = FT_THROW( Code_Overflow );
- return FAILURE;
- }
-
-
- /*************************************************************************/
- /* */
- /* IF[]: IF test */
- /* Opcode range: 0x58 */
- /* Stack: StkElt --> */
- /* */
- static void
- Ins_IF( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_Int nIfs;
- FT_Bool Out;
-
-
- if ( args[0] != 0 )
- return;
-
- nIfs = 1;
- Out = 0;
-
- do
- {
- if ( SkipCode( exc ) == FAILURE )
- return;
-
- switch ( exc->opcode )
- {
- case 0x58: /* IF */
- nIfs++;
- break;
-
- case 0x1B: /* ELSE */
- Out = FT_BOOL( nIfs == 1 );
- break;
-
- case 0x59: /* EIF */
- nIfs--;
- Out = FT_BOOL( nIfs == 0 );
- break;
- }
- } while ( Out == 0 );
- }
-
-
- /*************************************************************************/
- /* */
- /* ELSE[]: ELSE */
- /* Opcode range: 0x1B */
- /* Stack: --> */
- /* */
- static void
- Ins_ELSE( TT_ExecContext exc )
- {
- FT_Int nIfs;
-
-
- nIfs = 1;
-
- do
- {
- if ( SkipCode( exc ) == FAILURE )
- return;
-
- switch ( exc->opcode )
- {
- case 0x58: /* IF */
- nIfs++;
- break;
-
- case 0x59: /* EIF */
- nIfs--;
- break;
- }
- } while ( nIfs != 0 );
- }
-
-
- /*************************************************************************/
- /* */
- /* EIF[]: End IF */
- /* Opcode range: 0x59 */
- /* Stack: --> */
- /* */
- static void
- Ins_EIF( void )
- {
- /* nothing to do */
- }
-
-
- /*************************************************************************/
- /* */
- /* JMPR[]: JuMP Relative */
- /* Opcode range: 0x1C */
- /* Stack: int32 --> */
- /* */
- static void
- Ins_JMPR( TT_ExecContext exc,
- FT_Long* args )
- {
- if ( args[0] == 0 && exc->args == 0 )
- {
- exc->error = FT_THROW( Bad_Argument );
- return;
- }
-
- exc->IP += args[0];
- if ( exc->IP < 0 ||
- ( exc->callTop > 0 &&
- exc->IP > exc->callStack[exc->callTop - 1].Def->end ) )
- {
- exc->error = FT_THROW( Bad_Argument );
- return;
- }
-
- exc->step_ins = FALSE;
-
- if ( args[0] < 0 )
- {
- if ( ++exc->neg_jump_counter > exc->neg_jump_counter_max )
- exc->error = FT_THROW( Execution_Too_Long );
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* JROT[]: Jump Relative On True */
- /* Opcode range: 0x78 */
- /* Stack: StkElt int32 --> */
- /* */
- static void
- Ins_JROT( TT_ExecContext exc,
- FT_Long* args )
- {
- if ( args[1] != 0 )
- Ins_JMPR( exc, args );
- }
-
-
- /*************************************************************************/
- /* */
- /* JROF[]: Jump Relative On False */
- /* Opcode range: 0x79 */
- /* Stack: StkElt int32 --> */
- /* */
- static void
- Ins_JROF( TT_ExecContext exc,
- FT_Long* args )
- {
- if ( args[1] == 0 )
- Ins_JMPR( exc, args );
- }
-
-
- /*************************************************************************/
- /* */
- /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* FDEF[]: Function DEFinition */
- /* Opcode range: 0x2C */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_FDEF( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong n;
- TT_DefRecord* rec;
- TT_DefRecord* limit;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /* arguments to opcodes are skipped by `SKIP_Code' */
- FT_Byte opcode_pattern[9][12] = {
- /* #0 inline delta function 1 */
- {
- 0x4B, /* PPEM */
- 0x53, /* GTEQ */
- 0x23, /* SWAP */
- 0x4B, /* PPEM */
- 0x51, /* LTEQ */
- 0x5A, /* AND */
- 0x58, /* IF */
- 0x38, /* SHPIX */
- 0x1B, /* ELSE */
- 0x21, /* POP */
- 0x21, /* POP */
- 0x59 /* EIF */
- },
- /* #1 inline delta function 2 */
- {
- 0x4B, /* PPEM */
- 0x54, /* EQ */
- 0x58, /* IF */
- 0x38, /* SHPIX */
- 0x1B, /* ELSE */
- 0x21, /* POP */
- 0x21, /* POP */
- 0x59 /* EIF */
- },
- /* #2 diagonal stroke function */
- {
- 0x20, /* DUP */
- 0x20, /* DUP */
- 0xB0, /* PUSHB_1 */
- /* 1 */
- 0x60, /* ADD */
- 0x46, /* GC_cur */
- 0xB0, /* PUSHB_1 */
- /* 64 */
- 0x23, /* SWAP */
- 0x42 /* WS */
- },
- /* #3 VacuFormRound function */
- {
- 0x45, /* RCVT */
- 0x23, /* SWAP */
- 0x46, /* GC_cur */
- 0x60, /* ADD */
- 0x20, /* DUP */
- 0xB0 /* PUSHB_1 */
- /* 38 */
- },
- /* #4 TTFautohint bytecode (old) */
- {
- 0x20, /* DUP */
- 0x64, /* ABS */
- 0xB0, /* PUSHB_1 */
- /* 32 */
- 0x60, /* ADD */
- 0x66, /* FLOOR */
- 0x23, /* SWAP */
- 0xB0 /* PUSHB_1 */
- },
- /* #5 spacing function 1 */
- {
- 0x01, /* SVTCA_x */
- 0xB0, /* PUSHB_1 */
- /* 24 */
- 0x43, /* RS */
- 0x58 /* IF */
- },
- /* #6 spacing function 2 */
- {
- 0x01, /* SVTCA_x */
- 0x18, /* RTG */
- 0xB0, /* PUSHB_1 */
- /* 24 */
- 0x43, /* RS */
- 0x58 /* IF */
- },
- /* #7 TypeMan Talk DiagEndCtrl function */
- {
- 0x01, /* SVTCA_x */
- 0x20, /* DUP */
- 0xB0, /* PUSHB_1 */
- /* 3 */
- 0x25, /* CINDEX */
- },
- /* #8 TypeMan Talk Align */
- {
- 0x06, /* SPVTL */
- 0x7D, /* RDTG */
- },
- };
- FT_UShort opcode_patterns = 9;
- FT_UShort opcode_pointer[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- FT_UShort opcode_size[9] = { 12, 8, 8, 6, 7, 4, 5, 4, 2 };
- FT_UShort i;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-
- /* some font programs are broken enough to redefine functions! */
- /* We will then parse the current table. */
-
- rec = exc->FDefs;
- limit = rec + exc->numFDefs;
- n = (FT_ULong)args[0];
-
- for ( ; rec < limit; rec++ )
- {
- if ( rec->opc == n )
- break;
- }
-
- if ( rec == limit )
- {
- /* check that there is enough room for new functions */
- if ( exc->numFDefs >= exc->maxFDefs )
- {
- exc->error = FT_THROW( Too_Many_Function_Defs );
- return;
- }
- exc->numFDefs++;
- }
-
- /* Although FDEF takes unsigned 32-bit integer, */
- /* func # must be within unsigned 16-bit integer */
- if ( n > 0xFFFFU )
- {
- exc->error = FT_THROW( Too_Many_Function_Defs );
- return;
- }
-
- rec->range = exc->curRange;
- rec->opc = (FT_UInt16)n;
- rec->start = exc->IP + 1;
- rec->active = TRUE;
- rec->inline_delta = FALSE;
- rec->sph_fdef_flags = 0x0000;
-
- if ( n > exc->maxFunc )
- exc->maxFunc = (FT_UInt16)n;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /* We don't know for sure these are typeman functions, */
- /* however they are only active when RS 22 is called */
- if ( n >= 64 && n <= 66 )
- rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_STROKES;
-#endif
-
- /* Now skip the whole function definition. */
- /* We don't allow nested IDEFS & FDEFs. */
-
- while ( SkipCode( exc ) == SUCCESS )
- {
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- if ( SUBPIXEL_HINTING_INFINALITY )
- {
- for ( i = 0; i < opcode_patterns; i++ )
- {
- if ( opcode_pointer[i] < opcode_size[i] &&
- exc->opcode == opcode_pattern[i][opcode_pointer[i]] )
- {
- opcode_pointer[i] += 1;
-
- if ( opcode_pointer[i] == opcode_size[i] )
- {
- FT_TRACE6(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
- i, n,
- exc->face->root.family_name,
- exc->face->root.style_name ));
-
- switch ( i )
- {
- case 0:
- rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1;
- exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
- break;
-
- case 1:
- rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_2;
- exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
- break;
-
- case 2:
- switch ( n )
- {
- /* needs to be implemented still */
- case 58:
- rec->sph_fdef_flags |= SPH_FDEF_DIAGONAL_STROKE;
- exc->face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
- }
- break;
-
- case 3:
- switch ( n )
- {
- case 0:
- rec->sph_fdef_flags |= SPH_FDEF_VACUFORM_ROUND_1;
- exc->face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
- }
- break;
-
- case 4:
- /* probably not necessary to detect anymore */
- rec->sph_fdef_flags |= SPH_FDEF_TTFAUTOHINT_1;
- exc->face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
- break;
-
- case 5:
- switch ( n )
- {
- case 0:
- case 1:
- case 2:
- case 4:
- case 7:
- case 8:
- rec->sph_fdef_flags |= SPH_FDEF_SPACING_1;
- exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
- }
- break;
-
- case 6:
- switch ( n )
- {
- case 0:
- case 1:
- case 2:
- case 4:
- case 7:
- case 8:
- rec->sph_fdef_flags |= SPH_FDEF_SPACING_2;
- exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
- }
- break;
-
- case 7:
- rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
- exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
- break;
-
- case 8:
-#if 0
- rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
- exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
-#endif
- break;
- }
- opcode_pointer[i] = 0;
- }
- }
-
- else
- opcode_pointer[i] = 0;
- }
-
- /* Set sph_compatibility_mode only when deltas are detected */
- exc->face->sph_compatibility_mode =
- ( ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
- ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
- }
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- switch ( exc->opcode )
- {
- case 0x89: /* IDEF */
- case 0x2C: /* FDEF */
- exc->error = FT_THROW( Nested_DEFS );
- return;
-
- case 0x2D: /* ENDF */
- rec->end = exc->IP;
- return;
- }
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* ENDF[]: END Function definition */
- /* Opcode range: 0x2D */
- /* Stack: --> */
- /* */
- static void
- Ins_ENDF( TT_ExecContext exc )
- {
- TT_CallRec* pRec;
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- exc->sph_in_func_flags = 0x0000;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- if ( exc->callTop <= 0 ) /* We encountered an ENDF without a call */
- {
- exc->error = FT_THROW( ENDF_In_Exec_Stream );
- return;
- }
-
- exc->callTop--;
-
- pRec = &exc->callStack[exc->callTop];
-
- pRec->Cur_Count--;
-
- exc->step_ins = FALSE;
-
- if ( pRec->Cur_Count > 0 )
- {
- exc->callTop++;
- exc->IP = pRec->Def->start;
- }
- else
- /* Loop through the current function */
- Ins_Goto_CodeRange( exc, pRec->Caller_Range, pRec->Caller_IP );
-
- /* Exit the current call frame. */
-
- /* NOTE: If the last instruction of a program is a */
- /* CALL or LOOPCALL, the return address is */
- /* always out of the code range. This is a */
- /* valid address, and it is why we do not test */
- /* the result of Ins_Goto_CodeRange() here! */
- }
-
-
- /*************************************************************************/
- /* */
- /* CALL[]: CALL function */
- /* Opcode range: 0x2B */
- /* Stack: uint32? --> */
- /* */
- static void
- Ins_CALL( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong F;
- TT_CallRec* pCrec;
- TT_DefRecord* def;
-
-
- /* first of all, check the index */
-
- F = (FT_ULong)args[0];
- if ( BOUNDSL( F, exc->maxFunc + 1 ) )
- goto Fail;
-
- /* Except for some old Apple fonts, all functions in a TrueType */
- /* font are defined in increasing order, starting from 0. This */
- /* means that we normally have */
- /* */
- /* exc->maxFunc+1 == exc->numFDefs */
- /* exc->FDefs[n].opc == n for n in 0..exc->maxFunc */
- /* */
- /* If this isn't true, we need to look up the function table. */
-
- def = exc->FDefs + F;
- if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
- {
- /* look up the FDefs table */
- TT_DefRecord* limit;
-
-
- def = exc->FDefs;
- limit = def + exc->numFDefs;
-
- while ( def < limit && def->opc != F )
- def++;
-
- if ( def == limit )
- goto Fail;
- }
-
- /* check that the function is active */
- if ( !def->active )
- goto Fail;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- ( ( exc->iup_called &&
- ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
- ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) )
- goto Fail;
- else
- exc->sph_in_func_flags = def->sph_fdef_flags;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- /* check the call stack */
- if ( exc->callTop >= exc->callSize )
- {
- exc->error = FT_THROW( Stack_Overflow );
- return;
- }
-
- pCrec = exc->callStack + exc->callTop;
-
- pCrec->Caller_Range = exc->curRange;
- pCrec->Caller_IP = exc->IP + 1;
- pCrec->Cur_Count = 1;
- pCrec->Def = def;
-
- exc->callTop++;
-
- Ins_Goto_CodeRange( exc, def->range, def->start );
-
- exc->step_ins = FALSE;
-
- return;
-
- Fail:
- exc->error = FT_THROW( Invalid_Reference );
- }
-
-
- /*************************************************************************/
- /* */
- /* LOOPCALL[]: LOOP and CALL function */
- /* Opcode range: 0x2A */
- /* Stack: uint32? Eint16? --> */
- /* */
- static void
- Ins_LOOPCALL( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong F;
- TT_CallRec* pCrec;
- TT_DefRecord* def;
-
-
- /* first of all, check the index */
- F = (FT_ULong)args[1];
- if ( BOUNDSL( F, exc->maxFunc + 1 ) )
- goto Fail;
-
- /* Except for some old Apple fonts, all functions in a TrueType */
- /* font are defined in increasing order, starting from 0. This */
- /* means that we normally have */
- /* */
- /* exc->maxFunc+1 == exc->numFDefs */
- /* exc->FDefs[n].opc == n for n in 0..exc->maxFunc */
- /* */
- /* If this isn't true, we need to look up the function table. */
-
- def = exc->FDefs + F;
- if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
- {
- /* look up the FDefs table */
- TT_DefRecord* limit;
-
-
- def = exc->FDefs;
- limit = def + exc->numFDefs;
-
- while ( def < limit && def->opc != F )
- def++;
-
- if ( def == limit )
- goto Fail;
- }
-
- /* check that the function is active */
- if ( !def->active )
- goto Fail;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) )
- goto Fail;
- else
- exc->sph_in_func_flags = def->sph_fdef_flags;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- /* check stack */
- if ( exc->callTop >= exc->callSize )
- {
- exc->error = FT_THROW( Stack_Overflow );
- return;
- }
-
- if ( args[0] > 0 )
- {
- pCrec = exc->callStack + exc->callTop;
-
- pCrec->Caller_Range = exc->curRange;
- pCrec->Caller_IP = exc->IP + 1;
- pCrec->Cur_Count = (FT_Int)args[0];
- pCrec->Def = def;
-
- exc->callTop++;
-
- Ins_Goto_CodeRange( exc, def->range, def->start );
-
- exc->step_ins = FALSE;
-
- exc->loopcall_counter += (FT_ULong)args[0];
- if ( exc->loopcall_counter > exc->loopcall_counter_max )
- exc->error = FT_THROW( Execution_Too_Long );
- }
-
- return;
-
- Fail:
- exc->error = FT_THROW( Invalid_Reference );
- }
-
-
- /*************************************************************************/
- /* */
- /* IDEF[]: Instruction DEFinition */
- /* Opcode range: 0x89 */
- /* Stack: Eint8 --> */
- /* */
- static void
- Ins_IDEF( TT_ExecContext exc,
- FT_Long* args )
- {
- TT_DefRecord* def;
- TT_DefRecord* limit;
-
-
- /* First of all, look for the same function in our table */
-
- def = exc->IDefs;
- limit = def + exc->numIDefs;
-
- for ( ; def < limit; def++ )
- if ( def->opc == (FT_ULong)args[0] )
- break;
-
- if ( def == limit )
- {
- /* check that there is enough room for a new instruction */
- if ( exc->numIDefs >= exc->maxIDefs )
- {
- exc->error = FT_THROW( Too_Many_Instruction_Defs );
- return;
- }
- exc->numIDefs++;
- }
-
- /* opcode must be unsigned 8-bit integer */
- if ( 0 > args[0] || args[0] > 0x00FF )
- {
- exc->error = FT_THROW( Too_Many_Instruction_Defs );
- return;
- }
-
- def->opc = (FT_Byte)args[0];
- def->start = exc->IP + 1;
- def->range = exc->curRange;
- def->active = TRUE;
-
- if ( (FT_ULong)args[0] > exc->maxIns )
- exc->maxIns = (FT_Byte)args[0];
-
- /* Now skip the whole function definition. */
- /* We don't allow nested IDEFs & FDEFs. */
-
- while ( SkipCode( exc ) == SUCCESS )
- {
- switch ( exc->opcode )
- {
- case 0x89: /* IDEF */
- case 0x2C: /* FDEF */
- exc->error = FT_THROW( Nested_DEFS );
- return;
- case 0x2D: /* ENDF */
- def->end = exc->IP;
- return;
- }
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* PUSHING DATA ONTO THE INTERPRETER STACK */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* NPUSHB[]: PUSH N Bytes */
- /* Opcode range: 0x40 */
- /* Stack: --> uint32... */
- /* */
- static void
- Ins_NPUSHB( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort L, K;
-
-
- L = (FT_UShort)exc->code[exc->IP + 1];
-
- if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
- {
- exc->error = FT_THROW( Stack_Overflow );
- return;
- }
-
- for ( K = 1; K <= L; K++ )
- args[K - 1] = exc->code[exc->IP + K + 1];
-
- exc->new_top += L;
- }
-
-
- /*************************************************************************/
- /* */
- /* NPUSHW[]: PUSH N Words */
- /* Opcode range: 0x41 */
- /* Stack: --> int32... */
- /* */
- static void
- Ins_NPUSHW( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort L, K;
-
-
- L = (FT_UShort)exc->code[exc->IP + 1];
-
- if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
- {
- exc->error = FT_THROW( Stack_Overflow );
- return;
- }
-
- exc->IP += 2;
-
- for ( K = 0; K < L; K++ )
- args[K] = GetShortIns( exc );
-
- exc->step_ins = FALSE;
- exc->new_top += L;
- }
-
-
- /*************************************************************************/
- /* */
- /* PUSHB[abc]: PUSH Bytes */
- /* Opcode range: 0xB0-0xB7 */
- /* Stack: --> uint32... */
- /* */
- static void
- Ins_PUSHB( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort L, K;
-
-
- L = (FT_UShort)( exc->opcode - 0xB0 + 1 );
-
- if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
- {
- exc->error = FT_THROW( Stack_Overflow );
- return;
- }
-
- for ( K = 1; K <= L; K++ )
- args[K - 1] = exc->code[exc->IP + K];
- }
-
-
- /*************************************************************************/
- /* */
- /* PUSHW[abc]: PUSH Words */
- /* Opcode range: 0xB8-0xBF */
- /* Stack: --> int32... */
- /* */
- static void
- Ins_PUSHW( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort L, K;
-
-
- L = (FT_UShort)( exc->opcode - 0xB8 + 1 );
-
- if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
- {
- exc->error = FT_THROW( Stack_Overflow );
- return;
- }
-
- exc->IP++;
-
- for ( K = 0; K < L; K++ )
- args[K] = GetShortIns( exc );
-
- exc->step_ins = FALSE;
- }
-
-
- /*************************************************************************/
- /* */
- /* MANAGING THE GRAPHICS STATE */
- /* */
- /*************************************************************************/
-
-
- static FT_Bool
- Ins_SxVTL( TT_ExecContext exc,
- FT_UShort aIdx1,
- FT_UShort aIdx2,
- FT_UnitVector* Vec )
- {
- FT_Long A, B, C;
- FT_Vector* p1;
- FT_Vector* p2;
-
- FT_Byte opcode = exc->opcode;
-
-
- if ( BOUNDS( aIdx1, exc->zp2.n_points ) ||
- BOUNDS( aIdx2, exc->zp1.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return FAILURE;
- }
-
- p1 = exc->zp1.cur + aIdx2;
- p2 = exc->zp2.cur + aIdx1;
-
- A = p1->x - p2->x;
- B = p1->y - p2->y;
-
- /* If p1 == p2, SPvTL and SFvTL behave the same as */
- /* SPvTCA[X] and SFvTCA[X], respectively. */
- /* */
- /* Confirmed by Greg Hitchcock. */
-
- if ( A == 0 && B == 0 )
- {
- A = 0x4000;
- opcode = 0;
- }
-
- if ( ( opcode & 1 ) != 0 )
- {
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
- }
-
- Normalize( A, B, Vec );
-
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
- /* Opcode range: 0x00-0x01 */
- /* Stack: --> */
- /* */
- /* SPvTCA[a]: Set PVector to Coordinate Axis */
- /* Opcode range: 0x02-0x03 */
- /* Stack: --> */
- /* */
- /* SFvTCA[a]: Set FVector to Coordinate Axis */
- /* Opcode range: 0x04-0x05 */
- /* Stack: --> */
- /* */
- static void
- Ins_SxyTCA( TT_ExecContext exc )
- {
- FT_Short AA, BB;
-
- FT_Byte opcode = exc->opcode;
-
-
- AA = (FT_Short)( ( opcode & 1 ) << 14 );
- BB = (FT_Short)( AA ^ 0x4000 );
-
- if ( opcode < 4 )
- {
- exc->GS.projVector.x = AA;
- exc->GS.projVector.y = BB;
-
- exc->GS.dualVector.x = AA;
- exc->GS.dualVector.y = BB;
- }
-
- if ( ( opcode & 2 ) == 0 )
- {
- exc->GS.freeVector.x = AA;
- exc->GS.freeVector.y = BB;
- }
-
- Compute_Funcs( exc );
- }
-
-
- /*************************************************************************/
- /* */
- /* SPvTL[a]: Set PVector To Line */
- /* Opcode range: 0x06-0x07 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_SPVTL( TT_ExecContext exc,
- FT_Long* args )
- {
- if ( Ins_SxVTL( exc,
- (FT_UShort)args[1],
- (FT_UShort)args[0],
- &exc->GS.projVector ) == SUCCESS )
- {
- exc->GS.dualVector = exc->GS.projVector;
- Compute_Funcs( exc );
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* SFvTL[a]: Set FVector To Line */
- /* Opcode range: 0x08-0x09 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_SFVTL( TT_ExecContext exc,
- FT_Long* args )
- {
- if ( Ins_SxVTL( exc,
- (FT_UShort)args[1],
- (FT_UShort)args[0],
- &exc->GS.freeVector ) == SUCCESS )
- {
- Compute_Funcs( exc );
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* SFvTPv[]: Set FVector To PVector */
- /* Opcode range: 0x0E */
- /* Stack: --> */
- /* */
- static void
- Ins_SFVTPV( TT_ExecContext exc )
- {
- exc->GS.freeVector = exc->GS.projVector;
- Compute_Funcs( exc );
- }
-
-
- /*************************************************************************/
- /* */
- /* SPvFS[]: Set PVector From Stack */
- /* Opcode range: 0x0A */
- /* Stack: f2.14 f2.14 --> */
- /* */
- static void
- Ins_SPVFS( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_Short S;
- FT_Long X, Y;
-
-
- /* Only use low 16bits, then sign extend */
- S = (FT_Short)args[1];
- Y = (FT_Long)S;
- S = (FT_Short)args[0];
- X = (FT_Long)S;
-
- Normalize( X, Y, &exc->GS.projVector );
-
- exc->GS.dualVector = exc->GS.projVector;
- Compute_Funcs( exc );
- }
-
-
- /*************************************************************************/
- /* */
- /* SFvFS[]: Set FVector From Stack */
- /* Opcode range: 0x0B */
- /* Stack: f2.14 f2.14 --> */
- /* */
- static void
- Ins_SFVFS( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_Short S;
- FT_Long X, Y;
-
-
- /* Only use low 16bits, then sign extend */
- S = (FT_Short)args[1];
- Y = (FT_Long)S;
- S = (FT_Short)args[0];
- X = S;
-
- Normalize( X, Y, &exc->GS.freeVector );
- Compute_Funcs( exc );
- }
-
-
- /*************************************************************************/
- /* */
- /* GPv[]: Get Projection Vector */
- /* Opcode range: 0x0C */
- /* Stack: ef2.14 --> ef2.14 */
- /* */
- static void
- Ins_GPV( TT_ExecContext exc,
- FT_Long* args )
- {
- args[0] = exc->GS.projVector.x;
- args[1] = exc->GS.projVector.y;
- }
-
-
- /*************************************************************************/
- /* */
- /* GFv[]: Get Freedom Vector */
- /* Opcode range: 0x0D */
- /* Stack: ef2.14 --> ef2.14 */
- /* */
- static void
- Ins_GFV( TT_ExecContext exc,
- FT_Long* args )
- {
- args[0] = exc->GS.freeVector.x;
- args[1] = exc->GS.freeVector.y;
- }
-
-
- /*************************************************************************/
- /* */
- /* SRP0[]: Set Reference Point 0 */
- /* Opcode range: 0x10 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SRP0( TT_ExecContext exc,
- FT_Long* args )
- {
- exc->GS.rp0 = (FT_UShort)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* SRP1[]: Set Reference Point 1 */
- /* Opcode range: 0x11 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SRP1( TT_ExecContext exc,
- FT_Long* args )
- {
- exc->GS.rp1 = (FT_UShort)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* SRP2[]: Set Reference Point 2 */
- /* Opcode range: 0x12 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SRP2( TT_ExecContext exc,
- FT_Long* args )
- {
- exc->GS.rp2 = (FT_UShort)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* SMD[]: Set Minimum Distance */
- /* Opcode range: 0x1A */
- /* Stack: f26.6 --> */
- /* */
- static void
- Ins_SMD( TT_ExecContext exc,
- FT_Long* args )
- {
- exc->GS.minimum_distance = args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* SCVTCI[]: Set Control Value Table Cut In */
- /* Opcode range: 0x1D */
- /* Stack: f26.6 --> */
- /* */
- static void
- Ins_SCVTCI( TT_ExecContext exc,
- FT_Long* args )
- {
- exc->GS.control_value_cutin = (FT_F26Dot6)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* SSWCI[]: Set Single Width Cut In */
- /* Opcode range: 0x1E */
- /* Stack: f26.6 --> */
- /* */
- static void
- Ins_SSWCI( TT_ExecContext exc,
- FT_Long* args )
- {
- exc->GS.single_width_cutin = (FT_F26Dot6)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* SSW[]: Set Single Width */
- /* Opcode range: 0x1F */
- /* Stack: int32? --> */
- /* */
- static void
- Ins_SSW( TT_ExecContext exc,
- FT_Long* args )
- {
- exc->GS.single_width_value = FT_MulFix( args[0],
- exc->tt_metrics.scale );
- }
-
-
- /*************************************************************************/
- /* */
- /* FLIPON[]: Set auto-FLIP to ON */
- /* Opcode range: 0x4D */
- /* Stack: --> */
- /* */
- static void
- Ins_FLIPON( TT_ExecContext exc )
- {
- exc->GS.auto_flip = TRUE;
- }
-
-
- /*************************************************************************/
- /* */
- /* FLIPOFF[]: Set auto-FLIP to OFF */
- /* Opcode range: 0x4E */
- /* Stack: --> */
- /* */
- static void
- Ins_FLIPOFF( TT_ExecContext exc )
- {
- exc->GS.auto_flip = FALSE;
- }
-
-
- /*************************************************************************/
- /* */
- /* SANGW[]: Set ANGle Weight */
- /* Opcode range: 0x7E */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SANGW( void )
- {
- /* instruction not supported anymore */
- }
-
-
- /*************************************************************************/
- /* */
- /* SDB[]: Set Delta Base */
- /* Opcode range: 0x5E */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SDB( TT_ExecContext exc,
- FT_Long* args )
- {
- exc->GS.delta_base = (FT_UShort)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* SDS[]: Set Delta Shift */
- /* Opcode range: 0x5F */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SDS( TT_ExecContext exc,
- FT_Long* args )
- {
- if ( (FT_ULong)args[0] > 6UL )
- exc->error = FT_THROW( Bad_Argument );
- else
- exc->GS.delta_shift = (FT_UShort)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* RTHG[]: Round To Half Grid */
- /* Opcode range: 0x19 */
- /* Stack: --> */
- /* */
- static void
- Ins_RTHG( TT_ExecContext exc )
- {
- exc->GS.round_state = TT_Round_To_Half_Grid;
- exc->func_round = (TT_Round_Func)Round_To_Half_Grid;
- }
-
-
- /*************************************************************************/
- /* */
- /* RTG[]: Round To Grid */
- /* Opcode range: 0x18 */
- /* Stack: --> */
- /* */
- static void
- Ins_RTG( TT_ExecContext exc )
- {
- exc->GS.round_state = TT_Round_To_Grid;
- exc->func_round = (TT_Round_Func)Round_To_Grid;
- }
-
-
- /*************************************************************************/
- /* RTDG[]: Round To Double Grid */
- /* Opcode range: 0x3D */
- /* Stack: --> */
- /* */
- static void
- Ins_RTDG( TT_ExecContext exc )
- {
- exc->GS.round_state = TT_Round_To_Double_Grid;
- exc->func_round = (TT_Round_Func)Round_To_Double_Grid;
- }
-
-
- /*************************************************************************/
- /* RUTG[]: Round Up To Grid */
- /* Opcode range: 0x7C */
- /* Stack: --> */
- /* */
- static void
- Ins_RUTG( TT_ExecContext exc )
- {
- exc->GS.round_state = TT_Round_Up_To_Grid;
- exc->func_round = (TT_Round_Func)Round_Up_To_Grid;
- }
-
-
- /*************************************************************************/
- /* */
- /* RDTG[]: Round Down To Grid */
- /* Opcode range: 0x7D */
- /* Stack: --> */
- /* */
- static void
- Ins_RDTG( TT_ExecContext exc )
- {
- exc->GS.round_state = TT_Round_Down_To_Grid;
- exc->func_round = (TT_Round_Func)Round_Down_To_Grid;
- }
-
-
- /*************************************************************************/
- /* */
- /* ROFF[]: Round OFF */
- /* Opcode range: 0x7A */
- /* Stack: --> */
- /* */
- static void
- Ins_ROFF( TT_ExecContext exc )
- {
- exc->GS.round_state = TT_Round_Off;
- exc->func_round = (TT_Round_Func)Round_None;
- }
-
-
- /*************************************************************************/
- /* */
- /* SROUND[]: Super ROUND */
- /* Opcode range: 0x76 */
- /* Stack: Eint8 --> */
- /* */
- static void
- Ins_SROUND( TT_ExecContext exc,
- FT_Long* args )
- {
- SetSuperRound( exc, 0x4000, args[0] );
-
- exc->GS.round_state = TT_Round_Super;
- exc->func_round = (TT_Round_Func)Round_Super;
- }
-
-
- /*************************************************************************/
- /* */
- /* S45ROUND[]: Super ROUND 45 degrees */
- /* Opcode range: 0x77 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_S45ROUND( TT_ExecContext exc,
- FT_Long* args )
- {
- SetSuperRound( exc, 0x2D41, args[0] );
-
- exc->GS.round_state = TT_Round_Super_45;
- exc->func_round = (TT_Round_Func)Round_Super_45;
- }
-
-
- /*************************************************************************/
- /* */
- /* GC[a]: Get Coordinate projected onto */
- /* Opcode range: 0x46-0x47 */
- /* Stack: uint32 --> f26.6 */
- /* */
- /* XXX: UNDOCUMENTED: Measures from the original glyph must be taken */
- /* along the dual projection vector! */
- /* */
- static void
- Ins_GC( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong L;
- FT_F26Dot6 R;
-
-
- L = (FT_ULong)args[0];
-
- if ( BOUNDSL( L, exc->zp2.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- R = 0;
- }
- else
- {
- if ( exc->opcode & 1 )
- R = FAST_DUALPROJ( &exc->zp2.org[L] );
- else
- R = FAST_PROJECT( &exc->zp2.cur[L] );
- }
-
- args[0] = R;
- }
-
-
- /*************************************************************************/
- /* */
- /* SCFS[]: Set Coordinate From Stack */
- /* Opcode range: 0x48 */
- /* Stack: f26.6 uint32 --> */
- /* */
- /* Formula: */
- /* */
- /* OA := OA + ( value - OA.p )/( f.p ) * f */
- /* */
- static void
- Ins_SCFS( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_Long K;
- FT_UShort L;
-
-
- L = (FT_UShort)args[0];
-
- if ( BOUNDS( L, exc->zp2.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- K = FAST_PROJECT( &exc->zp2.cur[L] );
-
- exc->func_move( exc, &exc->zp2, L, args[1] - K );
-
- /* UNDOCUMENTED! The MS rasterizer does that with */
- /* twilight points (confirmed by Greg Hitchcock) */
- if ( exc->GS.gep2 == 0 )
- exc->zp2.org[L] = exc->zp2.cur[L];
- }
-
-
- /*************************************************************************/
- /* */
- /* MD[a]: Measure Distance */
- /* Opcode range: 0x49-0x4A */
- /* Stack: uint32 uint32 --> f26.6 */
- /* */
- /* XXX: UNDOCUMENTED: Measure taken in the original glyph must be along */
- /* the dual projection vector. */
- /* */
- /* XXX: UNDOCUMENTED: Flag attributes are inverted! */
- /* 0 => measure distance in original outline */
- /* 1 => measure distance in grid-fitted outline */
- /* */
- /* XXX: UNDOCUMENTED: `zp0 - zp1', and not `zp2 - zp1! */
- /* */
- static void
- Ins_MD( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort K, L;
- FT_F26Dot6 D;
-
-
- K = (FT_UShort)args[1];
- L = (FT_UShort)args[0];
-
- if ( BOUNDS( L, exc->zp0.n_points ) ||
- BOUNDS( K, exc->zp1.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- D = 0;
- }
- else
- {
- if ( exc->opcode & 1 )
- D = PROJECT( exc->zp0.cur + L, exc->zp1.cur + K );
- else
- {
- /* XXX: UNDOCUMENTED: twilight zone special case */
-
- if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 )
- {
- FT_Vector* vec1 = exc->zp0.org + L;
- FT_Vector* vec2 = exc->zp1.org + K;
-
-
- D = DUALPROJ( vec1, vec2 );
- }
- else
- {
- FT_Vector* vec1 = exc->zp0.orus + L;
- FT_Vector* vec2 = exc->zp1.orus + K;
-
-
- if ( exc->metrics.x_scale == exc->metrics.y_scale )
- {
- /* this should be faster */
- D = DUALPROJ( vec1, vec2 );
- D = FT_MulFix( D, exc->metrics.x_scale );
- }
- else
- {
- FT_Vector vec;
-
-
- vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale );
- vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale );
-
- D = FAST_DUALPROJ( &vec );
- }
- }
- }
- }
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- FT_ABS( D ) == 64 )
- D += 1;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- args[0] = D;
- }
-
-
- /*************************************************************************/
- /* */
- /* SDPvTL[a]: Set Dual PVector to Line */
- /* Opcode range: 0x86-0x87 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_SDPVTL( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_Long A, B, C;
- FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
-
- FT_Byte opcode = exc->opcode;
-
-
- p1 = (FT_UShort)args[1];
- p2 = (FT_UShort)args[0];
-
- if ( BOUNDS( p2, exc->zp1.n_points ) ||
- BOUNDS( p1, exc->zp2.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- {
- FT_Vector* v1 = exc->zp1.org + p2;
- FT_Vector* v2 = exc->zp2.org + p1;
-
-
- A = v1->x - v2->x;
- B = v1->y - v2->y;
-
- /* If v1 == v2, SDPvTL behaves the same as */
- /* SVTCA[X], respectively. */
- /* */
- /* Confirmed by Greg Hitchcock. */
-
- if ( A == 0 && B == 0 )
- {
- A = 0x4000;
- opcode = 0;
- }
- }
-
- if ( ( opcode & 1 ) != 0 )
- {
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
- }
-
- Normalize( A, B, &exc->GS.dualVector );
-
- {
- FT_Vector* v1 = exc->zp1.cur + p2;
- FT_Vector* v2 = exc->zp2.cur + p1;
-
-
- A = v1->x - v2->x;
- B = v1->y - v2->y;
-
- if ( A == 0 && B == 0 )
- {
- A = 0x4000;
- opcode = 0;
- }
- }
-
- if ( ( opcode & 1 ) != 0 )
- {
- C = B; /* counter clockwise rotation */
- B = A;
- A = -C;
- }
-
- Normalize( A, B, &exc->GS.projVector );
- Compute_Funcs( exc );
- }
-
-
- /*************************************************************************/
- /* */
- /* SZP0[]: Set Zone Pointer 0 */
- /* Opcode range: 0x13 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SZP0( TT_ExecContext exc,
- FT_Long* args )
- {
- switch ( (FT_Int)args[0] )
- {
- case 0:
- exc->zp0 = exc->twilight;
- break;
-
- case 1:
- exc->zp0 = exc->pts;
- break;
-
- default:
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- exc->GS.gep0 = (FT_UShort)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* SZP1[]: Set Zone Pointer 1 */
- /* Opcode range: 0x14 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SZP1( TT_ExecContext exc,
- FT_Long* args )
- {
- switch ( (FT_Int)args[0] )
- {
- case 0:
- exc->zp1 = exc->twilight;
- break;
-
- case 1:
- exc->zp1 = exc->pts;
- break;
-
- default:
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- exc->GS.gep1 = (FT_UShort)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* SZP2[]: Set Zone Pointer 2 */
- /* Opcode range: 0x15 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SZP2( TT_ExecContext exc,
- FT_Long* args )
- {
- switch ( (FT_Int)args[0] )
- {
- case 0:
- exc->zp2 = exc->twilight;
- break;
-
- case 1:
- exc->zp2 = exc->pts;
- break;
-
- default:
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- exc->GS.gep2 = (FT_UShort)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* SZPS[]: Set Zone PointerS */
- /* Opcode range: 0x16 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SZPS( TT_ExecContext exc,
- FT_Long* args )
- {
- switch ( (FT_Int)args[0] )
- {
- case 0:
- exc->zp0 = exc->twilight;
- break;
-
- case 1:
- exc->zp0 = exc->pts;
- break;
-
- default:
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- exc->zp1 = exc->zp0;
- exc->zp2 = exc->zp0;
-
- exc->GS.gep0 = (FT_UShort)args[0];
- exc->GS.gep1 = (FT_UShort)args[0];
- exc->GS.gep2 = (FT_UShort)args[0];
- }
-
-
- /*************************************************************************/
- /* */
- /* INSTCTRL[]: INSTruction ConTRoL */
- /* Opcode range: 0x8E */
- /* Stack: int32 int32 --> */
- /* */
- static void
- Ins_INSTCTRL( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong K, L, Kf;
-
-
- K = (FT_ULong)args[1];
- L = (FT_ULong)args[0];
-
- /* selector values cannot be `OR'ed; */
- /* they are indices starting with index 1, not flags */
- if ( K < 1 || K > 3 )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- /* convert index to flag value */
- Kf = 1 << ( K - 1 );
-
- if ( L != 0 )
- {
- /* arguments to selectors look like flag values */
- if ( L != Kf )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
- }
-
- exc->GS.instruct_control &= ~(FT_Byte)Kf;
- exc->GS.instruct_control |= (FT_Byte)L;
-
- if ( K == 3 )
- {
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /* INSTCTRL modifying flag 3 also has an effect */
- /* outside of the CVT program */
- if ( SUBPIXEL_HINTING_INFINALITY )
- exc->ignore_x_mode = FT_BOOL( L == 4 );
-#endif
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* Native ClearType fonts sign a waiver that turns off all backwards */
- /* compatibility hacks and lets them program points to the grid like */
- /* it's 1996. They might sign a waiver for just one glyph, though. */
- if ( SUBPIXEL_HINTING_MINIMAL )
- exc->backwards_compatibility = !FT_BOOL( L == 4 );
-#endif
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* SCANCTRL[]: SCAN ConTRoL */
- /* Opcode range: 0x85 */
- /* Stack: uint32? --> */
- /* */
- static void
- Ins_SCANCTRL( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_Int A;
-
-
- /* Get Threshold */
- A = (FT_Int)( args[0] & 0xFF );
-
- if ( A == 0xFF )
- {
- exc->GS.scan_control = TRUE;
- return;
- }
- else if ( A == 0 )
- {
- exc->GS.scan_control = FALSE;
- return;
- }
-
- if ( ( args[0] & 0x100 ) != 0 && exc->tt_metrics.ppem <= A )
- exc->GS.scan_control = TRUE;
-
- if ( ( args[0] & 0x200 ) != 0 && exc->tt_metrics.rotated )
- exc->GS.scan_control = TRUE;
-
- if ( ( args[0] & 0x400 ) != 0 && exc->tt_metrics.stretched )
- exc->GS.scan_control = TRUE;
-
- if ( ( args[0] & 0x800 ) != 0 && exc->tt_metrics.ppem > A )
- exc->GS.scan_control = FALSE;
-
- if ( ( args[0] & 0x1000 ) != 0 && exc->tt_metrics.rotated )
- exc->GS.scan_control = FALSE;
-
- if ( ( args[0] & 0x2000 ) != 0 && exc->tt_metrics.stretched )
- exc->GS.scan_control = FALSE;
- }
-
-
- /*************************************************************************/
- /* */
- /* SCANTYPE[]: SCAN TYPE */
- /* Opcode range: 0x8D */
- /* Stack: uint16 --> */
- /* */
- static void
- Ins_SCANTYPE( TT_ExecContext exc,
- FT_Long* args )
- {
- if ( args[0] >= 0 )
- exc->GS.scan_type = (FT_Int)args[0] & 0xFFFF;
- }
-
-
- /*************************************************************************/
- /* */
- /* MANAGING OUTLINES */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* FLIPPT[]: FLIP PoinT */
- /* Opcode range: 0x80 */
- /* Stack: uint32... --> */
- /* */
- static void
- Ins_FLIPPT( TT_ExecContext exc )
- {
- FT_UShort point;
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* See `ttinterp.h' for details on backwards compatibility mode. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called &&
- exc->iupy_called )
- goto Fail;
-#endif
-
- if ( exc->top < exc->GS.loop )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Too_Few_Arguments );
- goto Fail;
- }
-
- while ( exc->GS.loop > 0 )
- {
- exc->args--;
-
- point = (FT_UShort)exc->stack[exc->args];
-
- if ( BOUNDS( point, exc->pts.n_points ) )
- {
- if ( exc->pedantic_hinting )
- {
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
- }
- else
- exc->pts.tags[point] ^= FT_CURVE_TAG_ON;
-
- exc->GS.loop--;
- }
-
- Fail:
- exc->GS.loop = 1;
- exc->new_top = exc->args;
- }
-
-
- /*************************************************************************/
- /* */
- /* FLIPRGON[]: FLIP RanGe ON */
- /* Opcode range: 0x81 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_FLIPRGON( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort I, K, L;
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* See `ttinterp.h' for details on backwards compatibility mode. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called &&
- exc->iupy_called )
- return;
-#endif
-
- K = (FT_UShort)args[1];
- L = (FT_UShort)args[0];
-
- if ( BOUNDS( K, exc->pts.n_points ) ||
- BOUNDS( L, exc->pts.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- for ( I = L; I <= K; I++ )
- exc->pts.tags[I] |= FT_CURVE_TAG_ON;
- }
-
-
- /*************************************************************************/
- /* */
- /* FLIPRGOFF: FLIP RanGe OFF */
- /* Opcode range: 0x82 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_FLIPRGOFF( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort I, K, L;
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* See `ttinterp.h' for details on backwards compatibility mode. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called &&
- exc->iupy_called )
- return;
-#endif
-
- K = (FT_UShort)args[1];
- L = (FT_UShort)args[0];
-
- if ( BOUNDS( K, exc->pts.n_points ) ||
- BOUNDS( L, exc->pts.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- for ( I = L; I <= K; I++ )
- exc->pts.tags[I] &= ~FT_CURVE_TAG_ON;
- }
-
-
- static FT_Bool
- Compute_Point_Displacement( TT_ExecContext exc,
- FT_F26Dot6* x,
- FT_F26Dot6* y,
- TT_GlyphZone zone,
- FT_UShort* refp )
- {
- TT_GlyphZoneRec zp;
- FT_UShort p;
- FT_F26Dot6 d;
-
-
- if ( exc->opcode & 1 )
- {
- zp = exc->zp0;
- p = exc->GS.rp1;
- }
- else
- {
- zp = exc->zp1;
- p = exc->GS.rp2;
- }
-
- if ( BOUNDS( p, zp.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- *refp = 0;
- return FAILURE;
- }
-
- *zone = zp;
- *refp = p;
-
- d = PROJECT( zp.cur + p, zp.org + p );
-
- *x = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.x, exc->F_dot_P );
- *y = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.y, exc->F_dot_P );
-
- return SUCCESS;
- }
-
-
- /* See `ttinterp.h' for details on backwards compatibility mode. */
- static void
- Move_Zp2_Point( TT_ExecContext exc,
- FT_UShort point,
- FT_F26Dot6 dx,
- FT_F26Dot6 dy,
- FT_Bool touch )
- {
- if ( exc->GS.freeVector.x != 0 )
- {
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( !( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility ) )
-#endif
- exc->zp2.cur[point].x += dx;
-
- if ( touch )
- exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
- }
-
- if ( exc->GS.freeVector.y != 0 )
- {
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( !( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility &&
- exc->iupx_called &&
- exc->iupy_called ) )
-#endif
- exc->zp2.cur[point].y += dy;
-
- if ( touch )
- exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* SHP[a]: SHift Point by the last point */
- /* Opcode range: 0x32-0x33 */
- /* Stack: uint32... --> */
- /* */
- static void
- Ins_SHP( TT_ExecContext exc )
- {
- TT_GlyphZoneRec zp;
- FT_UShort refp;
-
- FT_F26Dot6 dx, dy;
- FT_UShort point;
-
-
- if ( exc->top < exc->GS.loop )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- goto Fail;
- }
-
- if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
- return;
-
- while ( exc->GS.loop > 0 )
- {
- exc->args--;
- point = (FT_UShort)exc->stack[exc->args];
-
- if ( BOUNDS( point, exc->zp2.n_points ) )
- {
- if ( exc->pedantic_hinting )
- {
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
- }
- else
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /* doesn't follow Cleartype spec but produces better result */
- if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode )
- Move_Zp2_Point( exc, point, 0, dy, TRUE );
- else
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
- Move_Zp2_Point( exc, point, dx, dy, TRUE );
-
- exc->GS.loop--;
- }
-
- Fail:
- exc->GS.loop = 1;
- exc->new_top = exc->args;
- }
-
-
- /*************************************************************************/
- /* */
- /* SHC[a]: SHift Contour */
- /* Opcode range: 0x34-35 */
- /* Stack: uint32 --> */
- /* */
- /* UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual) */
- /* contour in the twilight zone, namely contour number */
- /* zero which includes all points of it. */
- /* */
- static void
- Ins_SHC( TT_ExecContext exc,
- FT_Long* args )
- {
- TT_GlyphZoneRec zp;
- FT_UShort refp;
- FT_F26Dot6 dx, dy;
-
- FT_Short contour, bounds;
- FT_UShort start, limit, i;
-
-
- contour = (FT_Short)args[0];
- bounds = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours;
-
- if ( BOUNDS( contour, bounds ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
- return;
-
- if ( contour == 0 )
- start = 0;
- else
- start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 -
- exc->zp2.first_point );
-
- /* we use the number of points if in the twilight zone */
- if ( exc->GS.gep2 == 0 )
- limit = exc->zp2.n_points;
- else
- limit = (FT_UShort)( exc->zp2.contours[contour] -
- exc->zp2.first_point + 1 );
-
- for ( i = start; i < limit; i++ )
- {
- if ( zp.cur != exc->zp2.cur || refp != i )
- Move_Zp2_Point( exc, i, dx, dy, TRUE );
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* SHZ[a]: SHift Zone */
- /* Opcode range: 0x36-37 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SHZ( TT_ExecContext exc,
- FT_Long* args )
- {
- TT_GlyphZoneRec zp;
- FT_UShort refp;
- FT_F26Dot6 dx,
- dy;
-
- FT_UShort limit, i;
-
-
- if ( BOUNDS( args[0], 2 ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
- return;
-
- /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */
- /* Twilight zone has no real contours, so use `n_points'. */
- /* Normal zone's `n_points' includes phantoms, so must */
- /* use end of last contour. */
- if ( exc->GS.gep2 == 0 )
- limit = (FT_UShort)exc->zp2.n_points;
- else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 )
- limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 );
- else
- limit = 0;
-
- /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
- for ( i = 0; i < limit; i++ )
- {
- if ( zp.cur != exc->zp2.cur || refp != i )
- Move_Zp2_Point( exc, i, dx, dy, FALSE );
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* SHPIX[]: SHift points by a PIXel amount */
- /* Opcode range: 0x38 */
- /* Stack: f26.6 uint32... --> */
- /* */
- static void
- Ins_SHPIX( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_F26Dot6 dx, dy;
- FT_UShort point;
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- FT_Int B1, B2;
-#endif
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- FT_Bool in_twilight = FT_BOOL( exc->GS.gep0 == 0 ||
- exc->GS.gep1 == 0 ||
- exc->GS.gep2 == 0 );
-#endif
-
-
-
- if ( exc->top < exc->GS.loop + 1 )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- goto Fail;
- }
-
- dx = TT_MulFix14( args[0], exc->GS.freeVector.x );
- dy = TT_MulFix14( args[0], exc->GS.freeVector.y );
-
- while ( exc->GS.loop > 0 )
- {
- exc->args--;
-
- point = (FT_UShort)exc->stack[exc->args];
-
- if ( BOUNDS( point, exc->zp2.n_points ) )
- {
- if ( exc->pedantic_hinting )
- {
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
- }
- else
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY )
- {
- /* If not using ignore_x_mode rendering, allow ZP2 move. */
- /* If inline deltas aren't allowed, skip ZP2 move. */
- /* If using ignore_x_mode rendering, allow ZP2 point move if: */
- /* - freedom vector is y and sph_compatibility_mode is off */
- /* - the glyph is composite and the move is in the Y direction */
- /* - the glyph is specifically set to allow SHPIX moves */
- /* - the move is on a previously Y-touched point */
-
- if ( exc->ignore_x_mode )
- {
- /* save point for later comparison */
- if ( exc->GS.freeVector.y != 0 )
- B1 = exc->zp2.cur[point].y;
- else
- B1 = exc->zp2.cur[point].x;
-
- if ( !exc->face->sph_compatibility_mode &&
- exc->GS.freeVector.y != 0 )
- {
- Move_Zp2_Point( exc, point, dx, dy, TRUE );
-
- /* save new point */
- if ( exc->GS.freeVector.y != 0 )
- {
- B2 = exc->zp2.cur[point].y;
-
- /* reverse any disallowed moves */
- if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
- ( B1 & 63 ) != 0 &&
- ( B2 & 63 ) != 0 &&
- B1 != B2 )
- Move_Zp2_Point( exc, point, -dx, -dy, TRUE );
- }
- }
- else if ( exc->face->sph_compatibility_mode )
- {
- if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
- {
- dx = FT_PIX_ROUND( B1 + dx ) - B1;
- dy = FT_PIX_ROUND( B1 + dy ) - B1;
- }
-
- /* skip post-iup deltas */
- if ( exc->iup_called &&
- ( ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) ||
- ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) )
- goto Skip;
-
- if ( !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) &&
- ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
- ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ||
- ( exc->sph_tweak_flags & SPH_TWEAK_DO_SHPIX ) ) )
- Move_Zp2_Point( exc, point, 0, dy, TRUE );
-
- /* save new point */
- if ( exc->GS.freeVector.y != 0 )
- {
- B2 = exc->zp2.cur[point].y;
-
- /* reverse any disallowed moves */
- if ( ( B1 & 63 ) == 0 &&
- ( B2 & 63 ) != 0 &&
- B1 != B2 )
- Move_Zp2_Point( exc, point, 0, -dy, TRUE );
- }
- }
- else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
- Move_Zp2_Point( exc, point, dx, dy, TRUE );
- }
- else
- Move_Zp2_Point( exc, point, dx, dy, TRUE );
- }
- else
-#endif
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility )
- {
- /* Special case: allow SHPIX to move points in the twilight zone. */
- /* Otherwise, treat SHPIX the same as DELTAP. Unbreaks various */
- /* fonts such as older versions of Rokkitt and DTL Argo T Light */
- /* that would glitch severly after calling ALIGNRP after a blocked */
- /* SHPIX. */
- if ( in_twilight ||
- ( !( exc->iupx_called && exc->iupy_called ) &&
- ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
- ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ) ) )
- Move_Zp2_Point( exc, point, 0, dy, TRUE );
- }
- else
-#endif
- Move_Zp2_Point( exc, point, dx, dy, TRUE );
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- Skip:
-#endif
- exc->GS.loop--;
- }
-
- Fail:
- exc->GS.loop = 1;
- exc->new_top = exc->args;
- }
-
-
- /*************************************************************************/
- /* */
- /* MSIRP[a]: Move Stack Indirect Relative Position */
- /* Opcode range: 0x3A-0x3B */
- /* Stack: f26.6 uint32 --> */
- /* */
- static void
- Ins_MSIRP( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort point = 0;
- FT_F26Dot6 distance;
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- FT_F26Dot6 control_value_cutin = 0;
-
-
- if ( SUBPIXEL_HINTING_INFINALITY )
- {
- control_value_cutin = exc->GS.control_value_cutin;
-
- if ( exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 &&
- !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
- control_value_cutin = 0;
- }
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- point = (FT_UShort)args[0];
-
- if ( BOUNDS( point, exc->zp1.n_points ) ||
- BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- /* UNDOCUMENTED! The MS rasterizer does that with */
- /* twilight points (confirmed by Greg Hitchcock) */
- if ( exc->GS.gep1 == 0 )
- {
- exc->zp1.org[point] = exc->zp0.org[exc->GS.rp0];
- exc->func_move_orig( exc, &exc->zp1, point, args[1] );
- exc->zp1.cur[point] = exc->zp1.org[point];
- }
-
- distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /* subpixel hinting - make MSIRP respect CVT cut-in; */
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 &&
- FT_ABS( distance - args[1] ) >= control_value_cutin )
- distance = args[1];
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- exc->func_move( exc, &exc->zp1, point, args[1] - distance );
-
- exc->GS.rp1 = exc->GS.rp0;
- exc->GS.rp2 = point;
-
- if ( ( exc->opcode & 1 ) != 0 )
- exc->GS.rp0 = point;
- }
-
-
- /*************************************************************************/
- /* */
- /* MDAP[a]: Move Direct Absolute Point */
- /* Opcode range: 0x2E-0x2F */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_MDAP( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort point;
- FT_F26Dot6 cur_dist;
- FT_F26Dot6 distance;
-
-
- point = (FT_UShort)args[0];
-
- if ( BOUNDS( point, exc->zp0.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- if ( ( exc->opcode & 1 ) != 0 )
- {
- cur_dist = FAST_PROJECT( &exc->zp0.cur[point] );
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 )
- distance = Round_None(
- exc,
- cur_dist,
- exc->tt_metrics.compensations[0] ) - cur_dist;
- else
-#endif
- distance = exc->func_round(
- exc,
- cur_dist,
- exc->tt_metrics.compensations[0] ) - cur_dist;
- }
- else
- distance = 0;
-
- exc->func_move( exc, &exc->zp0, point, distance );
-
- exc->GS.rp0 = point;
- exc->GS.rp1 = point;
- }
-
-
- /*************************************************************************/
- /* */
- /* MIAP[a]: Move Indirect Absolute Point */
- /* Opcode range: 0x3E-0x3F */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_MIAP( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong cvtEntry;
- FT_UShort point;
- FT_F26Dot6 distance;
- FT_F26Dot6 org_dist;
- FT_F26Dot6 control_value_cutin;
-
-
- control_value_cutin = exc->GS.control_value_cutin;
- cvtEntry = (FT_ULong)args[1];
- point = (FT_UShort)args[0];
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 &&
- exc->GS.freeVector.y == 0 &&
- !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
- control_value_cutin = 0;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- if ( BOUNDS( point, exc->zp0.n_points ) ||
- BOUNDSL( cvtEntry, exc->cvtSize ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- goto Fail;
- }
-
- /* UNDOCUMENTED! */
- /* */
- /* The behaviour of an MIAP instruction is quite different when used */
- /* in the twilight zone. */
- /* */
- /* First, no control value cut-in test is performed as it would fail */
- /* anyway. Second, the original point, i.e. (org_x,org_y) of */
- /* zp0.point, is set to the absolute, unrounded distance found in the */
- /* CVT. */
- /* */
- /* This is used in the CVT programs of the Microsoft fonts Arial, */
- /* Times, etc., in order to re-adjust some key font heights. It */
- /* allows the use of the IP instruction in the twilight zone, which */
- /* otherwise would be invalid according to the specification. */
- /* */
- /* We implement it with a special sequence for the twilight zone. */
- /* This is a bad hack, but it seems to work. */
- /* */
- /* Confirmed by Greg Hitchcock. */
-
- distance = exc->func_read_cvt( exc, cvtEntry );
-
- if ( exc->GS.gep0 == 0 ) /* If in twilight zone */
- {
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */
- /* Determined via experimentation and may be incorrect... */
- if ( !( SUBPIXEL_HINTING_INFINALITY &&
- ( exc->ignore_x_mode &&
- exc->face->sph_compatibility_mode ) ) )
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
- exc->zp0.org[point].x = TT_MulFix14( distance,
- exc->GS.freeVector.x );
- exc->zp0.org[point].y = TT_MulFix14( distance,
- exc->GS.freeVector.y ),
- exc->zp0.cur[point] = exc->zp0.org[point];
- }
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
- distance > 0 &&
- exc->GS.freeVector.y != 0 )
- distance = 0;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- org_dist = FAST_PROJECT( &exc->zp0.cur[point] );
-
- if ( ( exc->opcode & 1 ) != 0 ) /* rounding and control cut-in flag */
- {
- if ( FT_ABS( distance - org_dist ) > control_value_cutin )
- distance = org_dist;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 )
- distance = Round_None( exc,
- distance,
- exc->tt_metrics.compensations[0] );
- else
-#endif
- distance = exc->func_round( exc,
- distance,
- exc->tt_metrics.compensations[0] );
- }
-
- exc->func_move( exc, &exc->zp0, point, distance - org_dist );
-
- Fail:
- exc->GS.rp0 = point;
- exc->GS.rp1 = point;
- }
-
-
- /*************************************************************************/
- /* */
- /* MDRP[abcde]: Move Direct Relative Point */
- /* Opcode range: 0xC0-0xDF */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_MDRP( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort point = 0;
- FT_F26Dot6 org_dist, distance, minimum_distance;
-
-
- minimum_distance = exc->GS.minimum_distance;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 &&
- !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
- minimum_distance = 0;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- point = (FT_UShort)args[0];
-
- if ( BOUNDS( point, exc->zp1.n_points ) ||
- BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- goto Fail;
- }
-
- /* XXX: Is there some undocumented feature while in the */
- /* twilight zone? */
-
- /* XXX: UNDOCUMENTED: twilight zone special case */
-
- if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 )
- {
- FT_Vector* vec1 = &exc->zp1.org[point];
- FT_Vector* vec2 = &exc->zp0.org[exc->GS.rp0];
-
-
- org_dist = DUALPROJ( vec1, vec2 );
- }
- else
- {
- FT_Vector* vec1 = &exc->zp1.orus[point];
- FT_Vector* vec2 = &exc->zp0.orus[exc->GS.rp0];
-
-
- if ( exc->metrics.x_scale == exc->metrics.y_scale )
- {
- /* this should be faster */
- org_dist = DUALPROJ( vec1, vec2 );
- org_dist = FT_MulFix( org_dist, exc->metrics.x_scale );
- }
- else
- {
- FT_Vector vec;
-
-
- vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale );
- vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale );
-
- org_dist = FAST_DUALPROJ( &vec );
- }
- }
-
- /* single width cut-in test */
-
- if ( FT_ABS( org_dist - exc->GS.single_width_value ) <
- exc->GS.single_width_cutin )
- {
- if ( org_dist >= 0 )
- org_dist = exc->GS.single_width_value;
- else
- org_dist = -exc->GS.single_width_value;
- }
-
- /* round flag */
-
- if ( ( exc->opcode & 4 ) != 0 )
- {
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 )
- distance = Round_None(
- exc,
- org_dist,
- exc->tt_metrics.compensations[exc->opcode & 3] );
- else
-#endif
- distance = exc->func_round(
- exc,
- org_dist,
- exc->tt_metrics.compensations[exc->opcode & 3] );
- }
- else
- distance = Round_None(
- exc,
- org_dist,
- exc->tt_metrics.compensations[exc->opcode & 3] );
-
- /* minimum distance flag */
-
- if ( ( exc->opcode & 8 ) != 0 )
- {
- if ( org_dist >= 0 )
- {
- if ( distance < minimum_distance )
- distance = minimum_distance;
- }
- else
- {
- if ( distance > -minimum_distance )
- distance = -minimum_distance;
- }
- }
-
- /* now move the point */
-
- org_dist = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
-
- exc->func_move( exc, &exc->zp1, point, distance - org_dist );
-
- Fail:
- exc->GS.rp1 = exc->GS.rp0;
- exc->GS.rp2 = point;
-
- if ( ( exc->opcode & 16 ) != 0 )
- exc->GS.rp0 = point;
- }
-
-
- /*************************************************************************/
- /* */
- /* MIRP[abcde]: Move Indirect Relative Point */
- /* Opcode range: 0xE0-0xFF */
- /* Stack: int32? uint32 --> */
- /* */
- static void
- Ins_MIRP( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort point;
- FT_ULong cvtEntry;
-
- FT_F26Dot6 cvt_dist,
- distance,
- cur_dist,
- org_dist,
- control_value_cutin,
- minimum_distance;
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- FT_Int B1 = 0; /* pacify compiler */
- FT_Int B2 = 0;
- FT_Bool reverse_move = FALSE;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-
- minimum_distance = exc->GS.minimum_distance;
- control_value_cutin = exc->GS.control_value_cutin;
- point = (FT_UShort)args[0];
- cvtEntry = (FT_ULong)( args[1] + 1 );
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 &&
- !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
- control_value_cutin = minimum_distance = 0;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
-
- if ( BOUNDS( point, exc->zp1.n_points ) ||
- BOUNDSL( cvtEntry, exc->cvtSize + 1 ) ||
- BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- goto Fail;
- }
-
- if ( !cvtEntry )
- cvt_dist = 0;
- else
- cvt_dist = exc->func_read_cvt( exc, cvtEntry - 1 );
-
- /* single width test */
-
- if ( FT_ABS( cvt_dist - exc->GS.single_width_value ) <
- exc->GS.single_width_cutin )
- {
- if ( cvt_dist >= 0 )
- cvt_dist = exc->GS.single_width_value;
- else
- cvt_dist = -exc->GS.single_width_value;
- }
-
- /* UNDOCUMENTED! The MS rasterizer does that with */
- /* twilight points (confirmed by Greg Hitchcock) */
- if ( exc->GS.gep1 == 0 )
- {
- exc->zp1.org[point].x = exc->zp0.org[exc->GS.rp0].x +
- TT_MulFix14( cvt_dist,
- exc->GS.freeVector.x );
- exc->zp1.org[point].y = exc->zp0.org[exc->GS.rp0].y +
- TT_MulFix14( cvt_dist,
- exc->GS.freeVector.y );
- exc->zp1.cur[point] = exc->zp1.org[point];
- }
-
- org_dist = DUALPROJ( &exc->zp1.org[point], &exc->zp0.org[exc->GS.rp0] );
- cur_dist = PROJECT ( &exc->zp1.cur[point], &exc->zp0.cur[exc->GS.rp0] );
-
- /* auto-flip test */
-
- if ( exc->GS.auto_flip )
- {
- if ( ( org_dist ^ cvt_dist ) < 0 )
- cvt_dist = -cvt_dist;
- }
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.y != 0 &&
- ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
- {
- if ( cur_dist < -64 )
- cvt_dist -= 16;
- else if ( cur_dist > 64 && cur_dist < 84 )
- cvt_dist += 32;
- }
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- /* control value cut-in and round */
-
- if ( ( exc->opcode & 4 ) != 0 )
- {
- /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */
- /* refer to the same zone. */
-
- if ( exc->GS.gep0 == exc->GS.gep1 )
- {
- /* XXX: According to Greg Hitchcock, the following wording is */
- /* the right one: */
- /* */
- /* When the absolute difference between the value in */
- /* the table [CVT] and the measurement directly from */
- /* the outline is _greater_ than the cut_in value, the */
- /* outline measurement is used. */
- /* */
- /* This is from `instgly.doc'. The description in */
- /* `ttinst2.doc', version 1.66, is thus incorrect since */
- /* it implies `>=' instead of `>'. */
-
- if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
- cvt_dist = org_dist;
- }
-
- distance = exc->func_round(
- exc,
- cvt_dist,
- exc->tt_metrics.compensations[exc->opcode & 3] );
- }
- else
- {
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /* do cvt cut-in always in MIRP for sph */
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.gep0 == exc->GS.gep1 )
- {
- if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
- cvt_dist = org_dist;
- }
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- distance = Round_None(
- exc,
- cvt_dist,
- exc->tt_metrics.compensations[exc->opcode & 3] );
- }
-
- /* minimum distance test */
-
- if ( ( exc->opcode & 8 ) != 0 )
- {
- if ( org_dist >= 0 )
- {
- if ( distance < minimum_distance )
- distance = minimum_distance;
- }
- else
- {
- if ( distance > -minimum_distance )
- distance = -minimum_distance;
- }
- }
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY )
- {
- B1 = exc->zp1.cur[point].y;
-
- /* Round moves if necessary */
- if ( exc->ignore_x_mode &&
- exc->GS.freeVector.y != 0 &&
- ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
- distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist;
-
- if ( exc->ignore_x_mode &&
- exc->GS.freeVector.y != 0 &&
- ( exc->opcode & 16 ) == 0 &&
- ( exc->opcode & 8 ) == 0 &&
- ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
- distance += 64;
- }
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- exc->func_move( exc, &exc->zp1, point, distance - cur_dist );
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY )
- {
- B2 = exc->zp1.cur[point].y;
-
- /* Reverse move if necessary */
- if ( exc->ignore_x_mode )
- {
- if ( exc->face->sph_compatibility_mode &&
- exc->GS.freeVector.y != 0 &&
- ( B1 & 63 ) == 0 &&
- ( B2 & 63 ) != 0 )
- reverse_move = TRUE;
-
- if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
- exc->GS.freeVector.y != 0 &&
- ( B2 & 63 ) != 0 &&
- ( B1 & 63 ) != 0 )
- reverse_move = TRUE;
- }
-
- if ( reverse_move )
- exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) );
- }
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- Fail:
- exc->GS.rp1 = exc->GS.rp0;
-
- if ( ( exc->opcode & 16 ) != 0 )
- exc->GS.rp0 = point;
-
- exc->GS.rp2 = point;
- }
-
-
- /*************************************************************************/
- /* */
- /* ALIGNRP[]: ALIGN Relative Point */
- /* Opcode range: 0x3C */
- /* Stack: uint32 uint32... --> */
- /* */
- static void
- Ins_ALIGNRP( TT_ExecContext exc )
- {
- FT_UShort point;
- FT_F26Dot6 distance;
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->iup_called &&
- ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
- {
- exc->error = FT_THROW( Invalid_Reference );
- goto Fail;
- }
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- if ( exc->top < exc->GS.loop ||
- BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- goto Fail;
- }
-
- while ( exc->GS.loop > 0 )
- {
- exc->args--;
-
- point = (FT_UShort)exc->stack[exc->args];
-
- if ( BOUNDS( point, exc->zp1.n_points ) )
- {
- if ( exc->pedantic_hinting )
- {
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
- }
- else
- {
- distance = PROJECT( exc->zp1.cur + point,
- exc->zp0.cur + exc->GS.rp0 );
-
- exc->func_move( exc, &exc->zp1, point, -distance );
- }
-
- exc->GS.loop--;
- }
-
- Fail:
- exc->GS.loop = 1;
- exc->new_top = exc->args;
- }
-
-
- /*************************************************************************/
- /* */
- /* ISECT[]: moves point to InterSECTion */
- /* Opcode range: 0x0F */
- /* Stack: 5 * uint32 --> */
- /* */
- static void
- Ins_ISECT( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort point,
- a0, a1,
- b0, b1;
-
- FT_F26Dot6 discriminant, dotproduct;
-
- FT_F26Dot6 dx, dy,
- dax, day,
- dbx, dby;
-
- FT_F26Dot6 val;
-
- FT_Vector R;
-
-
- point = (FT_UShort)args[0];
-
- a0 = (FT_UShort)args[1];
- a1 = (FT_UShort)args[2];
- b0 = (FT_UShort)args[3];
- b1 = (FT_UShort)args[4];
-
- if ( BOUNDS( b0, exc->zp0.n_points ) ||
- BOUNDS( b1, exc->zp0.n_points ) ||
- BOUNDS( a0, exc->zp1.n_points ) ||
- BOUNDS( a1, exc->zp1.n_points ) ||
- BOUNDS( point, exc->zp2.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- /* Cramer's rule */
-
- dbx = exc->zp0.cur[b1].x - exc->zp0.cur[b0].x;
- dby = exc->zp0.cur[b1].y - exc->zp0.cur[b0].y;
-
- dax = exc->zp1.cur[a1].x - exc->zp1.cur[a0].x;
- day = exc->zp1.cur[a1].y - exc->zp1.cur[a0].y;
-
- dx = exc->zp0.cur[b0].x - exc->zp1.cur[a0].x;
- dy = exc->zp0.cur[b0].y - exc->zp1.cur[a0].y;
-
- discriminant = FT_MulDiv( dax, -dby, 0x40 ) +
- FT_MulDiv( day, dbx, 0x40 );
- dotproduct = FT_MulDiv( dax, dbx, 0x40 ) +
- FT_MulDiv( day, dby, 0x40 );
-
- /* The discriminant above is actually a cross product of vectors */
- /* da and db. Together with the dot product, they can be used as */
- /* surrogates for sine and cosine of the angle between the vectors. */
- /* Indeed, */
- /* dotproduct = |da||db|cos(angle) */
- /* discriminant = |da||db|sin(angle) . */
- /* We use these equations to reject grazing intersections by */
- /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */
- if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) )
- {
- val = FT_MulDiv( dx, -dby, 0x40 ) + FT_MulDiv( dy, dbx, 0x40 );
-
- R.x = FT_MulDiv( val, dax, discriminant );
- R.y = FT_MulDiv( val, day, discriminant );
-
- /* XXX: Block in backwards_compatibility and/or post-IUP? */
- exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x;
- exc->zp2.cur[point].y = exc->zp1.cur[a0].y + R.y;
- }
- else
- {
- /* else, take the middle of the middles of A and B */
-
- /* XXX: Block in backwards_compatibility and/or post-IUP? */
- exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x +
- exc->zp1.cur[a1].x +
- exc->zp0.cur[b0].x +
- exc->zp0.cur[b1].x ) / 4;
- exc->zp2.cur[point].y = ( exc->zp1.cur[a0].y +
- exc->zp1.cur[a1].y +
- exc->zp0.cur[b0].y +
- exc->zp0.cur[b1].y ) / 4;
- }
-
- exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
- }
-
-
- /*************************************************************************/
- /* */
- /* ALIGNPTS[]: ALIGN PoinTS */
- /* Opcode range: 0x27 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_ALIGNPTS( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort p1, p2;
- FT_F26Dot6 distance;
-
-
- p1 = (FT_UShort)args[0];
- p2 = (FT_UShort)args[1];
-
- if ( BOUNDS( p1, exc->zp1.n_points ) ||
- BOUNDS( p2, exc->zp0.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- distance = PROJECT( exc->zp0.cur + p2, exc->zp1.cur + p1 ) / 2;
-
- exc->func_move( exc, &exc->zp1, p1, distance );
- exc->func_move( exc, &exc->zp0, p2, -distance );
- }
-
-
- /*************************************************************************/
- /* */
- /* IP[]: Interpolate Point */
- /* Opcode range: 0x39 */
- /* Stack: uint32... --> */
- /* */
-
- /* SOMETIMES, DUMBER CODE IS BETTER CODE */
-
- static void
- Ins_IP( TT_ExecContext exc )
- {
- FT_F26Dot6 old_range, cur_range;
- FT_Vector* orus_base;
- FT_Vector* cur_base;
- FT_Int twilight;
-
-
- if ( exc->top < exc->GS.loop )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- goto Fail;
- }
-
- /*
- * We need to deal in a special way with the twilight zone.
- * Otherwise, by definition, the value of exc->twilight.orus[n] is (0,0),
- * for every n.
- */
- twilight = ( exc->GS.gep0 == 0 ||
- exc->GS.gep1 == 0 ||
- exc->GS.gep2 == 0 );
-
- if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- goto Fail;
- }
-
- if ( twilight )
- orus_base = &exc->zp0.org[exc->GS.rp1];
- else
- orus_base = &exc->zp0.orus[exc->GS.rp1];
-
- cur_base = &exc->zp0.cur[exc->GS.rp1];
-
- /* XXX: There are some glyphs in some braindead but popular */
- /* fonts out there (e.g. [aeu]grave in monotype.ttf) */
- /* calling IP[] with bad values of rp[12]. */
- /* Do something sane when this odd thing happens. */
- if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) ||
- BOUNDS( exc->GS.rp2, exc->zp1.n_points ) )
- {
- old_range = 0;
- cur_range = 0;
- }
- else
- {
- if ( twilight )
- old_range = DUALPROJ( &exc->zp1.org[exc->GS.rp2], orus_base );
- else if ( exc->metrics.x_scale == exc->metrics.y_scale )
- old_range = DUALPROJ( &exc->zp1.orus[exc->GS.rp2], orus_base );
- else
- {
- FT_Vector vec;
-
-
- vec.x = FT_MulFix( exc->zp1.orus[exc->GS.rp2].x - orus_base->x,
- exc->metrics.x_scale );
- vec.y = FT_MulFix( exc->zp1.orus[exc->GS.rp2].y - orus_base->y,
- exc->metrics.y_scale );
-
- old_range = FAST_DUALPROJ( &vec );
- }
-
- cur_range = PROJECT( &exc->zp1.cur[exc->GS.rp2], cur_base );
- }
-
- for ( ; exc->GS.loop > 0; exc->GS.loop-- )
- {
- FT_UInt point = (FT_UInt)exc->stack[--exc->args];
- FT_F26Dot6 org_dist, cur_dist, new_dist;
-
-
- /* check point bounds */
- if ( BOUNDS( point, exc->zp2.n_points ) )
- {
- if ( exc->pedantic_hinting )
- {
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
- continue;
- }
-
- if ( twilight )
- org_dist = DUALPROJ( &exc->zp2.org[point], orus_base );
- else if ( exc->metrics.x_scale == exc->metrics.y_scale )
- org_dist = DUALPROJ( &exc->zp2.orus[point], orus_base );
- else
- {
- FT_Vector vec;
-
-
- vec.x = FT_MulFix( exc->zp2.orus[point].x - orus_base->x,
- exc->metrics.x_scale );
- vec.y = FT_MulFix( exc->zp2.orus[point].y - orus_base->y,
- exc->metrics.y_scale );
-
- org_dist = FAST_DUALPROJ( &vec );
- }
-
- cur_dist = PROJECT( &exc->zp2.cur[point], cur_base );
-
- if ( org_dist )
- {
- if ( old_range )
- new_dist = FT_MulDiv( org_dist, cur_range, old_range );
- else
- {
- /* This is the same as what MS does for the invalid case: */
- /* */
- /* delta = (Original_Pt - Original_RP1) - */
- /* (Current_Pt - Current_RP1) ; */
- /* */
- /* In FreeType speak: */
- /* */
- /* delta = org_dist - cur_dist . */
- /* */
- /* We move `point' by `new_dist - cur_dist' after leaving */
- /* this block, thus we have */
- /* */
- /* new_dist - cur_dist = delta , */
- /* new_dist - cur_dist = org_dist - cur_dist , */
- /* new_dist = org_dist . */
-
- new_dist = org_dist;
- }
- }
- else
- new_dist = 0;
-
- exc->func_move( exc,
- &exc->zp2,
- (FT_UShort)point,
- new_dist - cur_dist );
- }
-
- Fail:
- exc->GS.loop = 1;
- exc->new_top = exc->args;
- }
-
-
- /*************************************************************************/
- /* */
- /* UTP[a]: UnTouch Point */
- /* Opcode range: 0x29 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_UTP( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UShort point;
- FT_Byte mask;
-
-
- point = (FT_UShort)args[0];
-
- if ( BOUNDS( point, exc->zp0.n_points ) )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
-
- mask = 0xFF;
-
- if ( exc->GS.freeVector.x != 0 )
- mask &= ~FT_CURVE_TAG_TOUCH_X;
-
- if ( exc->GS.freeVector.y != 0 )
- mask &= ~FT_CURVE_TAG_TOUCH_Y;
-
- exc->zp0.tags[point] &= mask;
- }
-
-
- /* Local variables for Ins_IUP: */
- typedef struct IUP_WorkerRec_
- {
- FT_Vector* orgs; /* original and current coordinate */
- FT_Vector* curs; /* arrays */
- FT_Vector* orus;
- FT_UInt max_points;
-
- } IUP_WorkerRec, *IUP_Worker;
-
-
- static void
- _iup_worker_shift( IUP_Worker worker,
- FT_UInt p1,
- FT_UInt p2,
- FT_UInt p )
- {
- FT_UInt i;
- FT_F26Dot6 dx;
-
-
- dx = worker->curs[p].x - worker->orgs[p].x;
- if ( dx != 0 )
- {
- for ( i = p1; i < p; i++ )
- worker->curs[i].x += dx;
-
- for ( i = p + 1; i <= p2; i++ )
- worker->curs[i].x += dx;
- }
- }
-
-
- static void
- _iup_worker_interpolate( IUP_Worker worker,
- FT_UInt p1,
- FT_UInt p2,
- FT_UInt ref1,
- FT_UInt ref2 )
- {
- FT_UInt i;
- FT_F26Dot6 orus1, orus2, org1, org2, cur1, cur2, delta1, delta2;
-
-
- if ( p1 > p2 )
- return;
-
- if ( BOUNDS( ref1, worker->max_points ) ||
- BOUNDS( ref2, worker->max_points ) )
- return;
-
- orus1 = worker->orus[ref1].x;
- orus2 = worker->orus[ref2].x;
-
- if ( orus1 > orus2 )
- {
- FT_F26Dot6 tmp_o;
- FT_UInt tmp_r;
-
-
- tmp_o = orus1;
- orus1 = orus2;
- orus2 = tmp_o;
-
- tmp_r = ref1;
- ref1 = ref2;
- ref2 = tmp_r;
- }
-
- org1 = worker->orgs[ref1].x;
- org2 = worker->orgs[ref2].x;
- cur1 = worker->curs[ref1].x;
- cur2 = worker->curs[ref2].x;
- delta1 = cur1 - org1;
- delta2 = cur2 - org2;
-
- if ( cur1 == cur2 || orus1 == orus2 )
- {
-
- /* trivial snap or shift of untouched points */
- for ( i = p1; i <= p2; i++ )
- {
- FT_F26Dot6 x = worker->orgs[i].x;
-
-
- if ( x <= org1 )
- x += delta1;
-
- else if ( x >= org2 )
- x += delta2;
-
- else
- x = cur1;
-
- worker->curs[i].x = x;
- }
- }
- else
- {
- FT_Fixed scale = 0;
- FT_Bool scale_valid = 0;
-
-
- /* interpolation */
- for ( i = p1; i <= p2; i++ )
- {
- FT_F26Dot6 x = worker->orgs[i].x;
-
-
- if ( x <= org1 )
- x += delta1;
-
- else if ( x >= org2 )
- x += delta2;
-
- else
- {
- if ( !scale_valid )
- {
- scale_valid = 1;
- scale = FT_DivFix( cur2 - cur1, orus2 - orus1 );
- }
-
- x = cur1 + FT_MulFix( worker->orus[i].x - orus1, scale );
- }
- worker->curs[i].x = x;
- }
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* IUP[a]: Interpolate Untouched Points */
- /* Opcode range: 0x30-0x31 */
- /* Stack: --> */
- /* */
- static void
- Ins_IUP( TT_ExecContext exc )
- {
- IUP_WorkerRec V;
- FT_Byte mask;
-
- FT_UInt first_point; /* first point of contour */
- FT_UInt end_point; /* end point (last+1) of contour */
-
- FT_UInt first_touched; /* first touched point in contour */
- FT_UInt cur_touched; /* current touched point in contour */
-
- FT_UInt point; /* current point */
- FT_Short contour; /* current contour */
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* See `ttinterp.h' for details on backwards compatibility mode. */
- /* Allow IUP until it has been called on both axes. Immediately */
- /* return on subsequent ones. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility )
- {
- if ( exc->iupx_called && exc->iupy_called )
- return;
-
- if ( exc->opcode & 1 )
- exc->iupx_called = TRUE;
- else
- exc->iupy_called = TRUE;
- }
-#endif
-
- /* ignore empty outlines */
- if ( exc->pts.n_contours == 0 )
- return;
-
- if ( exc->opcode & 1 )
- {
- mask = FT_CURVE_TAG_TOUCH_X;
- V.orgs = exc->pts.org;
- V.curs = exc->pts.cur;
- V.orus = exc->pts.orus;
- }
- else
- {
- mask = FT_CURVE_TAG_TOUCH_Y;
- V.orgs = (FT_Vector*)( (FT_Pos*)exc->pts.org + 1 );
- V.curs = (FT_Vector*)( (FT_Pos*)exc->pts.cur + 1 );
- V.orus = (FT_Vector*)( (FT_Pos*)exc->pts.orus + 1 );
- }
- V.max_points = exc->pts.n_points;
-
- contour = 0;
- point = 0;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode )
- {
- exc->iup_called = TRUE;
- if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
- return;
- }
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- do
- {
- end_point = exc->pts.contours[contour] - exc->pts.first_point;
- first_point = point;
-
- if ( BOUNDS( end_point, exc->pts.n_points ) )
- end_point = exc->pts.n_points - 1;
-
- while ( point <= end_point && ( exc->pts.tags[point] & mask ) == 0 )
- point++;
-
- if ( point <= end_point )
- {
- first_touched = point;
- cur_touched = point;
-
- point++;
-
- while ( point <= end_point )
- {
- if ( ( exc->pts.tags[point] & mask ) != 0 )
- {
- _iup_worker_interpolate( &V,
- cur_touched + 1,
- point - 1,
- cur_touched,
- point );
- cur_touched = point;
- }
-
- point++;
- }
-
- if ( cur_touched == first_touched )
- _iup_worker_shift( &V, first_point, end_point, cur_touched );
- else
- {
- _iup_worker_interpolate( &V,
- (FT_UShort)( cur_touched + 1 ),
- end_point,
- cur_touched,
- first_touched );
-
- if ( first_touched > 0 )
- _iup_worker_interpolate( &V,
- first_point,
- first_touched - 1,
- cur_touched,
- first_touched );
- }
- }
- contour++;
- } while ( contour < exc->pts.n_contours );
- }
-
-
- /*************************************************************************/
- /* */
- /* DELTAPn[]: DELTA exceptions P1, P2, P3 */
- /* Opcode range: 0x5D,0x71,0x72 */
- /* Stack: uint32 (2 * uint32)... --> */
- /* */
- static void
- Ins_DELTAP( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong nump, k;
- FT_UShort A;
- FT_ULong C, P;
- FT_Long B;
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- FT_UShort B1, B2;
-
-
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->iup_called &&
- ( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
- goto Fail;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- P = (FT_ULong)exc->func_cur_ppem( exc );
- nump = (FT_ULong)args[0]; /* some points theoretically may occur more
- than once, thus UShort isn't enough */
-
- for ( k = 1; k <= nump; k++ )
- {
- if ( exc->args < 2 )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Too_Few_Arguments );
- exc->args = 0;
- goto Fail;
- }
-
- exc->args -= 2;
-
- A = (FT_UShort)exc->stack[exc->args + 1];
- B = exc->stack[exc->args];
-
- /* XXX: Because some popular fonts contain some invalid DeltaP */
- /* instructions, we simply ignore them when the stacked */
- /* point reference is off limit, rather than returning an */
- /* error. As a delta instruction doesn't change a glyph */
- /* in great ways, this shouldn't be a problem. */
-
- if ( !BOUNDS( A, exc->zp0.n_points ) )
- {
- C = ( (FT_ULong)B & 0xF0 ) >> 4;
-
- switch ( exc->opcode )
- {
- case 0x5D:
- break;
-
- case 0x71:
- C += 16;
- break;
-
- case 0x72:
- C += 32;
- break;
- }
-
- C += exc->GS.delta_base;
-
- if ( P == C )
- {
- B = ( (FT_ULong)B & 0xF ) - 8;
- if ( B >= 0 )
- B++;
- B *= 1L << ( 6 - exc->GS.delta_shift );
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- if ( SUBPIXEL_HINTING_INFINALITY )
- {
- /*
- * Allow delta move if
- *
- * - not using ignore_x_mode rendering,
- * - glyph is specifically set to allow it, or
- * - glyph is composite and freedom vector is not in subpixel
- * direction.
- */
- if ( !exc->ignore_x_mode ||
- ( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
- ( exc->is_composite && exc->GS.freeVector.y != 0 ) )
- exc->func_move( exc, &exc->zp0, A, B );
-
- /* Otherwise, apply subpixel hinting and compatibility mode */
- /* rules, always skipping deltas in subpixel direction. */
- else if ( exc->ignore_x_mode && exc->GS.freeVector.y != 0 )
- {
- /* save the y value of the point now; compare after move */
- B1 = (FT_UShort)exc->zp0.cur[A].y;
-
- /* Standard subpixel hinting: Allow y move for y-touched */
- /* points. This messes up DejaVu ... */
- if ( !exc->face->sph_compatibility_mode &&
- ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
- exc->func_move( exc, &exc->zp0, A, B );
-
- /* compatibility mode */
- else if ( exc->face->sph_compatibility_mode &&
- !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
- {
- if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
- B = FT_PIX_ROUND( B1 + B ) - B1;
-
- /* Allow delta move if using sph_compatibility_mode, */
- /* IUP has not been called, and point is touched on Y. */
- if ( !exc->iup_called &&
- ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
- exc->func_move( exc, &exc->zp0, A, B );
- }
-
- B2 = (FT_UShort)exc->zp0.cur[A].y;
-
- /* Reverse this move if it results in a disallowed move */
- if ( exc->GS.freeVector.y != 0 &&
- ( ( exc->face->sph_compatibility_mode &&
- ( B1 & 63 ) == 0 &&
- ( B2 & 63 ) != 0 ) ||
- ( ( exc->sph_tweak_flags &
- SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) &&
- ( B1 & 63 ) != 0 &&
- ( B2 & 63 ) != 0 ) ) )
- exc->func_move( exc, &exc->zp0, A, -B );
- }
- }
- else
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- {
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* See `ttinterp.h' for details on backwards compatibility */
- /* mode. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->backwards_compatibility )
- {
- if ( !( exc->iupx_called && exc->iupy_called ) &&
- ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
- ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) )
- exc->func_move( exc, &exc->zp0, A, B );
- }
- else
-#endif
- exc->func_move( exc, &exc->zp0, A, B );
- }
- }
- }
- else
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Invalid_Reference );
- }
-
- Fail:
- exc->new_top = exc->args;
- }
-
-
- /*************************************************************************/
- /* */
- /* DELTACn[]: DELTA exceptions C1, C2, C3 */
- /* Opcode range: 0x73,0x74,0x75 */
- /* Stack: uint32 (2 * uint32)... --> */
- /* */
- static void
- Ins_DELTAC( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_ULong nump, k;
- FT_ULong A, C, P;
- FT_Long B;
-
-
- P = (FT_ULong)exc->func_cur_ppem( exc );
- nump = (FT_ULong)args[0];
-
- for ( k = 1; k <= nump; k++ )
- {
- if ( exc->args < 2 )
- {
- if ( exc->pedantic_hinting )
- exc->error = FT_THROW( Too_Few_Arguments );
- exc->args = 0;
- goto Fail;
- }
-
- exc->args -= 2;
-
- A = (FT_ULong)exc->stack[exc->args + 1];
- B = exc->stack[exc->args];
-
- if ( BOUNDSL( A, exc->cvtSize ) )
- {
- if ( exc->pedantic_hinting )
- {
- exc->error = FT_THROW( Invalid_Reference );
- return;
- }
- }
- else
- {
- C = ( (FT_ULong)B & 0xF0 ) >> 4;
-
- switch ( exc->opcode )
- {
- case 0x73:
- break;
-
- case 0x74:
- C += 16;
- break;
-
- case 0x75:
- C += 32;
- break;
- }
-
- C += exc->GS.delta_base;
-
- if ( P == C )
- {
- B = ( (FT_ULong)B & 0xF ) - 8;
- if ( B >= 0 )
- B++;
- B *= 1L << ( 6 - exc->GS.delta_shift );
-
- exc->func_move_cvt( exc, A, B );
- }
- }
- }
-
- Fail:
- exc->new_top = exc->args;
- }
-
-
- /*************************************************************************/
- /* */
- /* MISC. INSTRUCTIONS */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* GETINFO[]: GET INFOrmation */
- /* Opcode range: 0x88 */
- /* Stack: uint32 --> uint32 */
- /* */
- /* XXX: UNDOCUMENTED: Selector bits higher than 9 are currently (May */
- /* 2015) not documented in the OpenType specification. */
- /* */
- /* Selector bit 11 is incorrectly described as bit 8, while the */
- /* real meaning of bit 8 (vertical LCD subpixels) stays */
- /* undocumented. The same mistake can be found in Greg Hitchcock's */
- /* whitepaper. */
- /* */
- static void
- Ins_GETINFO( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_Long K;
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( exc->face );
-
-
- K = 0;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- /********************************/
- /* RASTERIZER VERSION */
- /* Selector Bit: 0 */
- /* Return Bit(s): 0-7 */
- /* */
- if ( SUBPIXEL_HINTING_INFINALITY &&
- ( args[0] & 1 ) != 0 &&
- exc->subpixel_hinting )
- {
- if ( exc->ignore_x_mode )
- {
- /* if in ClearType backwards compatibility mode, */
- /* we sometimes change the TrueType version dynamically */
- K = exc->rasterizer_version;
- FT_TRACE6(( "Setting rasterizer version %d\n",
- exc->rasterizer_version ));
- }
- else
- K = TT_INTERPRETER_VERSION_38;
- }
- else
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
- if ( ( args[0] & 1 ) != 0 )
- K = driver->interpreter_version;
-
- /********************************/
- /* GLYPH ROTATED */
- /* Selector Bit: 1 */
- /* Return Bit(s): 8 */
- /* */
- if ( ( args[0] & 2 ) != 0 && exc->tt_metrics.rotated )
- K |= 1 << 8;
-
- /********************************/
- /* GLYPH STRETCHED */
- /* Selector Bit: 2 */
- /* Return Bit(s): 9 */
- /* */
- if ( ( args[0] & 4 ) != 0 && exc->tt_metrics.stretched )
- K |= 1 << 9;
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- /********************************/
- /* VARIATION GLYPH */
- /* Selector Bit: 3 */
- /* Return Bit(s): 10 */
- /* */
- /* XXX: UNDOCUMENTED! */
- if ( (args[0] & 8 ) != 0 && exc->face->blend )
- K |= 1 << 10;
-#endif
-
- /********************************/
- /* BI-LEVEL HINTING AND */
- /* GRAYSCALE RENDERING */
- /* Selector Bit: 5 */
- /* Return Bit(s): 12 */
- /* */
- if ( ( args[0] & 32 ) != 0 && exc->grayscale )
- K |= 1 << 12;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- if ( SUBPIXEL_HINTING_MINIMAL )
- {
- /********************************/
- /* HINTING FOR SUBPIXEL */
- /* Selector Bit: 6 */
- /* Return Bit(s): 13 */
- /* */
- /* v40 does subpixel hinting by default. */
- if ( ( args[0] & 64 ) != 0 )
- K |= 1 << 13;
-
- /********************************/
- /* VERTICAL LCD SUBPIXELS? */
- /* Selector Bit: 8 */
- /* Return Bit(s): 15 */
- /* */
- if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd_lean )
- K |= 1 << 15;
-
- /********************************/
- /* SUBPIXEL POSITIONED? */
- /* Selector Bit: 10 */
- /* Return Bit(s): 17 */
- /* */
- /* XXX: FreeType supports it, dependent on what client does? */
- if ( ( args[0] & 1024 ) != 0 )
- K |= 1 << 17;
-
- /********************************/
- /* SYMMETRICAL SMOOTHING */
- /* Selector Bit: 11 */
- /* Return Bit(s): 18 */
- /* */
- /* The only smoothing method FreeType supports unless someone sets */
- /* FT_LOAD_TARGET_MONO. */
- if ( ( args[0] & 2048 ) != 0 )
- K |= 1 << 18;
-
- /********************************/
- /* CLEARTYPE HINTING AND */
- /* GRAYSCALE RENDERING */
- /* Selector Bit: 12 */
- /* Return Bit(s): 19 */
- /* */
- /* Grayscale rendering is what FreeType does anyway unless someone */
- /* sets FT_LOAD_TARGET_MONO or FT_LOAD_TARGET_LCD(_V) */
- if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype )
- K |= 1 << 19;
- }
-#endif
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 )
- {
-
- if ( exc->rasterizer_version >= 37 )
- {
- /********************************/
- /* HINTING FOR SUBPIXEL */
- /* Selector Bit: 6 */
- /* Return Bit(s): 13 */
- /* */
- if ( ( args[0] & 64 ) != 0 && exc->subpixel_hinting )
- K |= 1 << 13;
-
- /********************************/
- /* COMPATIBLE WIDTHS ENABLED */
- /* Selector Bit: 7 */
- /* Return Bit(s): 14 */
- /* */
- /* Functionality still needs to be added */
- if ( ( args[0] & 128 ) != 0 && exc->compatible_widths )
- K |= 1 << 14;
-
- /********************************/
- /* VERTICAL LCD SUBPIXELS? */
- /* Selector Bit: 8 */
- /* Return Bit(s): 15 */
- /* */
- /* Functionality still needs to be added */
- if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd )
- K |= 1 << 15;
-
- /********************************/
- /* HINTING FOR BGR? */
- /* Selector Bit: 9 */
- /* Return Bit(s): 16 */
- /* */
- /* Functionality still needs to be added */
- if ( ( args[0] & 512 ) != 0 && exc->bgr )
- K |= 1 << 16;
-
- if ( exc->rasterizer_version >= 38 )
- {
- /********************************/
- /* SUBPIXEL POSITIONED? */
- /* Selector Bit: 10 */
- /* Return Bit(s): 17 */
- /* */
- /* Functionality still needs to be added */
- if ( ( args[0] & 1024 ) != 0 && exc->subpixel_positioned )
- K |= 1 << 17;
-
- /********************************/
- /* SYMMETRICAL SMOOTHING */
- /* Selector Bit: 11 */
- /* Return Bit(s): 18 */
- /* */
- /* Functionality still needs to be added */
- if ( ( args[0] & 2048 ) != 0 && exc->symmetrical_smoothing )
- K |= 1 << 18;
-
- /********************************/
- /* GRAY CLEARTYPE */
- /* Selector Bit: 12 */
- /* Return Bit(s): 19 */
- /* */
- /* Functionality still needs to be added */
- if ( ( args[0] & 4096 ) != 0 && exc->gray_cleartype )
- K |= 1 << 19;
- }
- }
- }
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- args[0] = K;
- }
-
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-
- /*************************************************************************/
- /* */
- /* GETVARIATION[]: get normalized variation (blend) coordinates */
- /* Opcode range: 0x91 */
- /* Stack: --> f2.14... */
- /* */
- /* XXX: UNDOCUMENTED! There is no official documentation from Apple for */
- /* this bytecode instruction. Active only if a font has GX */
- /* variation axes. */
- /* */
- static void
- Ins_GETVARIATION( TT_ExecContext exc,
- FT_Long* args )
- {
- FT_UInt num_axes = exc->face->blend->num_axis;
- FT_Fixed* coords = exc->face->blend->normalizedcoords;
-
- FT_UInt i;
-
-
- if ( BOUNDS( num_axes, exc->stackSize + 1 - exc->top ) )
- {
- exc->error = FT_THROW( Stack_Overflow );
- return;
- }
-
- for ( i = 0; i < num_axes; i++ )
- args[i] = coords[i] >> 2; /* convert 16.16 to 2.14 format */
- }
-
-
- /*************************************************************************/
- /* */
- /* GETDATA[]: no idea what this is good for */
- /* Opcode range: 0x92 */
- /* Stack: --> 17 */
- /* */
- /* XXX: UNDOCUMENTED! There is no documentation from Apple for this */
- /* very weird bytecode instruction. */
- /* */
- static void
- Ins_GETDATA( FT_Long* args )
- {
- args[0] = 17;
- }
-
-#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
-
-
- static void
- Ins_UNKNOWN( TT_ExecContext exc )
- {
- TT_DefRecord* def = exc->IDefs;
- TT_DefRecord* limit = def + exc->numIDefs;
-
-
- for ( ; def < limit; def++ )
- {
- if ( (FT_Byte)def->opc == exc->opcode && def->active )
- {
- TT_CallRec* call;
-
-
- if ( exc->callTop >= exc->callSize )
- {
- exc->error = FT_THROW( Stack_Overflow );
- return;
- }
-
- call = exc->callStack + exc->callTop++;
-
- call->Caller_Range = exc->curRange;
- call->Caller_IP = exc->IP + 1;
- call->Cur_Count = 1;
- call->Def = def;
-
- Ins_Goto_CodeRange( exc, def->range, def->start );
-
- exc->step_ins = FALSE;
- return;
- }
- }
-
- exc->error = FT_THROW( Invalid_Opcode );
- }
-
-
- /*************************************************************************/
- /* */
- /* RUN */
- /* */
- /* This function executes a run of opcodes. It will exit in the */
- /* following cases: */
- /* */
- /* - Errors (in which case it returns FALSE). */
- /* */
- /* - Reaching the end of the main code range (returns TRUE). */
- /* Reaching the end of a code range within a function call is an */
- /* error. */
- /* */
- /* - After executing one single opcode, if the flag `Instruction_Trap' */
- /* is set to TRUE (returns TRUE). */
- /* */
- /* On exit with TRUE, test IP < CodeSize to know whether it comes from */
- /* an instruction trap or a normal termination. */
- /* */
- /* */
- /* Note: The documented DEBUG opcode pops a value from the stack. This */
- /* behaviour is unsupported; here a DEBUG opcode is always an */
- /* error. */
- /* */
- /* */
- /* THIS IS THE INTERPRETER'S MAIN LOOP. */
- /* */
- /*************************************************************************/
-
-
- /* documentation is in ttinterp.h */
-
- FT_EXPORT_DEF( FT_Error )
- TT_RunIns( TT_ExecContext exc )
- {
- FT_ULong ins_counter = 0; /* executed instructions counter */
- FT_ULong num_twilight_points;
- FT_UShort i;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- FT_Byte opcode_pattern[1][2] = {
- /* #8 TypeMan Talk Align */
- {
- 0x06, /* SPVTL */
- 0x7D, /* RDTG */
- },
- };
- FT_UShort opcode_patterns = 1;
- FT_UShort opcode_pointer[1] = { 0 };
- FT_UShort opcode_size[1] = { 1 };
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- exc->iup_called = FALSE;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /* Toggle backwards compatibility according to what font says, except */
- /* when it's a `tricky' font that heavily relies on the interpreter to */
- /* render glyphs correctly, e.g. DFKai-SB. Backwards compatibility */
- /* hacks may break it. */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- !FT_IS_TRICKY( &exc->face->root ) )
- exc->backwards_compatibility = !( exc->GS.instruct_control & 4 );
- else
- exc->backwards_compatibility = FALSE;
-
- exc->iupx_called = FALSE;
- exc->iupy_called = FALSE;
-#endif
-
- /* We restrict the number of twilight points to a reasonable, */
- /* heuristic value to avoid slow execution of malformed bytecode. */
- num_twilight_points = FT_MAX( 30,
- 2 * ( exc->pts.n_points + exc->cvtSize ) );
- if ( exc->twilight.n_points > num_twilight_points )
- {
- if ( num_twilight_points > 0xFFFFU )
- num_twilight_points = 0xFFFFU;
-
- FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n"
- " from %d to the more reasonable value %d\n",
- exc->twilight.n_points,
- num_twilight_points ));
- exc->twilight.n_points = (FT_UShort)num_twilight_points;
- }
-
- /* Set up loop detectors. We restrict the number of LOOPCALL loops */
- /* and the number of JMPR, JROT, and JROF calls with a negative */
- /* argument to values that depend on the size of the CVT table and */
- /* the number of points in the current glyph (if applicable). */
- /* */
- /* The idea is that in real-world bytecode you either iterate over */
- /* all CVT entries, or over all points (or contours) of a glyph, and */
- /* such iterations don't happen very often. */
- exc->loopcall_counter = 0;
- exc->neg_jump_counter = 0;
-
- /* The maximum values are heuristic. */
- exc->loopcall_counter_max = FT_MAX( 100,
- 10 * ( exc->pts.n_points +
- exc->cvtSize ) );
- FT_TRACE5(( "TT_RunIns: Limiting total number of loops in LOOPCALL"
- " to %d\n", exc->loopcall_counter_max ));
-
- exc->neg_jump_counter_max = exc->loopcall_counter_max;
- FT_TRACE5(( "TT_RunIns: Limiting total number of backward jumps"
- " to %d\n", exc->neg_jump_counter_max ));
-
- /* set PPEM and CVT functions */
- exc->tt_metrics.ratio = 0;
- if ( exc->metrics.x_ppem != exc->metrics.y_ppem )
- {
- /* non-square pixels, use the stretched routines */
- exc->func_cur_ppem = Current_Ppem_Stretched;
- exc->func_read_cvt = Read_CVT_Stretched;
- exc->func_write_cvt = Write_CVT_Stretched;
- exc->func_move_cvt = Move_CVT_Stretched;
- }
- else
- {
- /* square pixels, use normal routines */
- exc->func_cur_ppem = Current_Ppem;
- exc->func_read_cvt = Read_CVT;
- exc->func_write_cvt = Write_CVT;
- exc->func_move_cvt = Move_CVT;
- }
-
- Compute_Funcs( exc );
- Compute_Round( exc, (FT_Byte)exc->GS.round_state );
-
- do
- {
- exc->opcode = exc->code[exc->IP];
-
-#ifdef FT_DEBUG_LEVEL_TRACE
- {
- FT_Long cnt = FT_MIN( 8, exc->top );
- FT_Long n;
-
-
- /* if tracing level is 7, show current code position */
- /* and the first few stack elements also */
- FT_TRACE6(( " " ));
- FT_TRACE7(( "%06d ", exc->IP ));
- FT_TRACE6(( opcode_name[exc->opcode] + 2 ));
- FT_TRACE7(( "%*s", *opcode_name[exc->opcode] == 'A'
- ? 2
- : 12 - ( *opcode_name[exc->opcode] - '0' ),
- "#" ));
- for ( n = 1; n <= cnt; n++ )
- FT_TRACE7(( " %d", exc->stack[exc->top - n] ));
- FT_TRACE6(( "\n" ));
- }
-#endif /* FT_DEBUG_LEVEL_TRACE */
-
- if ( ( exc->length = opcode_length[exc->opcode] ) < 0 )
- {
- if ( exc->IP + 1 >= exc->codeSize )
- goto LErrorCodeOverflow_;
-
- exc->length = 2 - exc->length * exc->code[exc->IP + 1];
- }
-
- if ( exc->IP + exc->length > exc->codeSize )
- goto LErrorCodeOverflow_;
-
- /* First, let's check for empty stack and overflow */
- exc->args = exc->top - ( Pop_Push_Count[exc->opcode] >> 4 );
-
- /* `args' is the top of the stack once arguments have been popped. */
- /* One can also interpret it as the index of the last argument. */
- if ( exc->args < 0 )
- {
- if ( exc->pedantic_hinting )
- {
- exc->error = FT_THROW( Too_Few_Arguments );
- goto LErrorLabel_;
- }
-
- /* push zeroes onto the stack */
- for ( i = 0; i < Pop_Push_Count[exc->opcode] >> 4; i++ )
- exc->stack[i] = 0;
- exc->args = 0;
- }
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( exc->opcode == 0x91 )
- {
- /* this is very special: GETVARIATION returns */
- /* a variable number of arguments */
-
- /* it is the job of the application to `activate' GX handling, */
- /* this is, calling any of the GX API functions on the current */
- /* font to select a variation instance */
- if ( exc->face->blend )
- exc->new_top = exc->args + exc->face->blend->num_axis;
- }
- else
-#endif
- exc->new_top = exc->args + ( Pop_Push_Count[exc->opcode] & 15 );
-
- /* `new_top' is the new top of the stack, after the instruction's */
- /* execution. `top' will be set to `new_top' after the `switch' */
- /* statement. */
- if ( exc->new_top > exc->stackSize )
- {
- exc->error = FT_THROW( Stack_Overflow );
- goto LErrorLabel_;
- }
-
- exc->step_ins = TRUE;
- exc->error = FT_Err_Ok;
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- if ( SUBPIXEL_HINTING_INFINALITY )
- {
- for ( i = 0; i < opcode_patterns; i++ )
- {
- if ( opcode_pointer[i] < opcode_size[i] &&
- exc->opcode == opcode_pattern[i][opcode_pointer[i]] )
- {
- opcode_pointer[i] += 1;
-
- if ( opcode_pointer[i] == opcode_size[i] )
- {
- FT_TRACE6(( "sph: opcode ptrn: %d, %s %s\n",
- i,
- exc->face->root.family_name,
- exc->face->root.style_name ));
-
- switch ( i )
- {
- case 0:
- break;
- }
- opcode_pointer[i] = 0;
- }
- }
- else
- opcode_pointer[i] = 0;
- }
- }
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- {
- FT_Long* args = exc->stack + exc->args;
- FT_Byte opcode = exc->opcode;
-
-
- switch ( opcode )
- {
- case 0x00: /* SVTCA y */
- case 0x01: /* SVTCA x */
- case 0x02: /* SPvTCA y */
- case 0x03: /* SPvTCA x */
- case 0x04: /* SFvTCA y */
- case 0x05: /* SFvTCA x */
- Ins_SxyTCA( exc );
- break;
-
- case 0x06: /* SPvTL // */
- case 0x07: /* SPvTL + */
- Ins_SPVTL( exc, args );
- break;
-
- case 0x08: /* SFvTL // */
- case 0x09: /* SFvTL + */
- Ins_SFVTL( exc, args );
- break;
-
- case 0x0A: /* SPvFS */
- Ins_SPVFS( exc, args );
- break;
-
- case 0x0B: /* SFvFS */
- Ins_SFVFS( exc, args );
- break;
-
- case 0x0C: /* GPv */
- Ins_GPV( exc, args );
- break;
-
- case 0x0D: /* GFv */
- Ins_GFV( exc, args );
- break;
-
- case 0x0E: /* SFvTPv */
- Ins_SFVTPV( exc );
- break;
-
- case 0x0F: /* ISECT */
- Ins_ISECT( exc, args );
- break;
-
- case 0x10: /* SRP0 */
- Ins_SRP0( exc, args );
- break;
-
- case 0x11: /* SRP1 */
- Ins_SRP1( exc, args );
- break;
-
- case 0x12: /* SRP2 */
- Ins_SRP2( exc, args );
- break;
-
- case 0x13: /* SZP0 */
- Ins_SZP0( exc, args );
- break;
-
- case 0x14: /* SZP1 */
- Ins_SZP1( exc, args );
- break;
-
- case 0x15: /* SZP2 */
- Ins_SZP2( exc, args );
- break;
-
- case 0x16: /* SZPS */
- Ins_SZPS( exc, args );
- break;
-
- case 0x17: /* SLOOP */
- Ins_SLOOP( exc, args );
- break;
-
- case 0x18: /* RTG */
- Ins_RTG( exc );
- break;
-
- case 0x19: /* RTHG */
- Ins_RTHG( exc );
- break;
-
- case 0x1A: /* SMD */
- Ins_SMD( exc, args );
- break;
-
- case 0x1B: /* ELSE */
- Ins_ELSE( exc );
- break;
-
- case 0x1C: /* JMPR */
- Ins_JMPR( exc, args );
- break;
-
- case 0x1D: /* SCVTCI */
- Ins_SCVTCI( exc, args );
- break;
-
- case 0x1E: /* SSWCI */
- Ins_SSWCI( exc, args );
- break;
-
- case 0x1F: /* SSW */
- Ins_SSW( exc, args );
- break;
-
- case 0x20: /* DUP */
- Ins_DUP( args );
- break;
-
- case 0x21: /* POP */
- Ins_POP();
- break;
-
- case 0x22: /* CLEAR */
- Ins_CLEAR( exc );
- break;
-
- case 0x23: /* SWAP */
- Ins_SWAP( args );
- break;
-
- case 0x24: /* DEPTH */
- Ins_DEPTH( exc, args );
- break;
-
- case 0x25: /* CINDEX */
- Ins_CINDEX( exc, args );
- break;
-
- case 0x26: /* MINDEX */
- Ins_MINDEX( exc, args );
- break;
-
- case 0x27: /* ALIGNPTS */
- Ins_ALIGNPTS( exc, args );
- break;
-
- case 0x28: /* RAW */
- Ins_UNKNOWN( exc );
- break;
-
- case 0x29: /* UTP */
- Ins_UTP( exc, args );
- break;
-
- case 0x2A: /* LOOPCALL */
- Ins_LOOPCALL( exc, args );
- break;
-
- case 0x2B: /* CALL */
- Ins_CALL( exc, args );
- break;
-
- case 0x2C: /* FDEF */
- Ins_FDEF( exc, args );
- break;
-
- case 0x2D: /* ENDF */
- Ins_ENDF( exc );
- break;
-
- case 0x2E: /* MDAP */
- case 0x2F: /* MDAP */
- Ins_MDAP( exc, args );
- break;
-
- case 0x30: /* IUP */
- case 0x31: /* IUP */
- Ins_IUP( exc );
- break;
-
- case 0x32: /* SHP */
- case 0x33: /* SHP */
- Ins_SHP( exc );
- break;
-
- case 0x34: /* SHC */
- case 0x35: /* SHC */
- Ins_SHC( exc, args );
- break;
-
- case 0x36: /* SHZ */
- case 0x37: /* SHZ */
- Ins_SHZ( exc, args );
- break;
-
- case 0x38: /* SHPIX */
- Ins_SHPIX( exc, args );
- break;
-
- case 0x39: /* IP */
- Ins_IP( exc );
- break;
-
- case 0x3A: /* MSIRP */
- case 0x3B: /* MSIRP */
- Ins_MSIRP( exc, args );
- break;
-
- case 0x3C: /* AlignRP */
- Ins_ALIGNRP( exc );
- break;
-
- case 0x3D: /* RTDG */
- Ins_RTDG( exc );
- break;
-
- case 0x3E: /* MIAP */
- case 0x3F: /* MIAP */
- Ins_MIAP( exc, args );
- break;
-
- case 0x40: /* NPUSHB */
- Ins_NPUSHB( exc, args );
- break;
-
- case 0x41: /* NPUSHW */
- Ins_NPUSHW( exc, args );
- break;
-
- case 0x42: /* WS */
- Ins_WS( exc, args );
- break;
-
- case 0x43: /* RS */
- Ins_RS( exc, args );
- break;
-
- case 0x44: /* WCVTP */
- Ins_WCVTP( exc, args );
- break;
-
- case 0x45: /* RCVT */
- Ins_RCVT( exc, args );
- break;
-
- case 0x46: /* GC */
- case 0x47: /* GC */
- Ins_GC( exc, args );
- break;
-
- case 0x48: /* SCFS */
- Ins_SCFS( exc, args );
- break;
-
- case 0x49: /* MD */
- case 0x4A: /* MD */
- Ins_MD( exc, args );
- break;
-
- case 0x4B: /* MPPEM */
- Ins_MPPEM( exc, args );
- break;
-
- case 0x4C: /* MPS */
- Ins_MPS( exc, args );
- break;
-
- case 0x4D: /* FLIPON */
- Ins_FLIPON( exc );
- break;
-
- case 0x4E: /* FLIPOFF */
- Ins_FLIPOFF( exc );
- break;
-
- case 0x4F: /* DEBUG */
- Ins_DEBUG( exc );
- break;
-
- case 0x50: /* LT */
- Ins_LT( args );
- break;
-
- case 0x51: /* LTEQ */
- Ins_LTEQ( args );
- break;
-
- case 0x52: /* GT */
- Ins_GT( args );
- break;
-
- case 0x53: /* GTEQ */
- Ins_GTEQ( args );
- break;
-
- case 0x54: /* EQ */
- Ins_EQ( args );
- break;
-
- case 0x55: /* NEQ */
- Ins_NEQ( args );
- break;
-
- case 0x56: /* ODD */
- Ins_ODD( exc, args );
- break;
-
- case 0x57: /* EVEN */
- Ins_EVEN( exc, args );
- break;
-
- case 0x58: /* IF */
- Ins_IF( exc, args );
- break;
-
- case 0x59: /* EIF */
- Ins_EIF();
- break;
-
- case 0x5A: /* AND */
- Ins_AND( args );
- break;
-
- case 0x5B: /* OR */
- Ins_OR( args );
- break;
-
- case 0x5C: /* NOT */
- Ins_NOT( args );
- break;
-
- case 0x5D: /* DELTAP1 */
- Ins_DELTAP( exc, args );
- break;
-
- case 0x5E: /* SDB */
- Ins_SDB( exc, args );
- break;
-
- case 0x5F: /* SDS */
- Ins_SDS( exc, args );
- break;
-
- case 0x60: /* ADD */
- Ins_ADD( args );
- break;
-
- case 0x61: /* SUB */
- Ins_SUB( args );
- break;
-
- case 0x62: /* DIV */
- Ins_DIV( exc, args );
- break;
-
- case 0x63: /* MUL */
- Ins_MUL( args );
- break;
-
- case 0x64: /* ABS */
- Ins_ABS( args );
- break;
-
- case 0x65: /* NEG */
- Ins_NEG( args );
- break;
-
- case 0x66: /* FLOOR */
- Ins_FLOOR( args );
- break;
-
- case 0x67: /* CEILING */
- Ins_CEILING( args );
- break;
-
- case 0x68: /* ROUND */
- case 0x69: /* ROUND */
- case 0x6A: /* ROUND */
- case 0x6B: /* ROUND */
- Ins_ROUND( exc, args );
- break;
-
- case 0x6C: /* NROUND */
- case 0x6D: /* NROUND */
- case 0x6E: /* NRRUND */
- case 0x6F: /* NROUND */
- Ins_NROUND( exc, args );
- break;
-
- case 0x70: /* WCVTF */
- Ins_WCVTF( exc, args );
- break;
-
- case 0x71: /* DELTAP2 */
- case 0x72: /* DELTAP3 */
- Ins_DELTAP( exc, args );
- break;
-
- case 0x73: /* DELTAC0 */
- case 0x74: /* DELTAC1 */
- case 0x75: /* DELTAC2 */
- Ins_DELTAC( exc, args );
- break;
-
- case 0x76: /* SROUND */
- Ins_SROUND( exc, args );
- break;
-
- case 0x77: /* S45Round */
- Ins_S45ROUND( exc, args );
- break;
-
- case 0x78: /* JROT */
- Ins_JROT( exc, args );
- break;
-
- case 0x79: /* JROF */
- Ins_JROF( exc, args );
- break;
-
- case 0x7A: /* ROFF */
- Ins_ROFF( exc );
- break;
-
- case 0x7B: /* ???? */
- Ins_UNKNOWN( exc );
- break;
-
- case 0x7C: /* RUTG */
- Ins_RUTG( exc );
- break;
-
- case 0x7D: /* RDTG */
- Ins_RDTG( exc );
- break;
-
- case 0x7E: /* SANGW */
- Ins_SANGW();
- break;
-
- case 0x7F: /* AA */
- Ins_AA();
- break;
-
- case 0x80: /* FLIPPT */
- Ins_FLIPPT( exc );
- break;
-
- case 0x81: /* FLIPRGON */
- Ins_FLIPRGON( exc, args );
- break;
-
- case 0x82: /* FLIPRGOFF */
- Ins_FLIPRGOFF( exc, args );
- break;
-
- case 0x83: /* UNKNOWN */
- case 0x84: /* UNKNOWN */
- Ins_UNKNOWN( exc );
- break;
-
- case 0x85: /* SCANCTRL */
- Ins_SCANCTRL( exc, args );
- break;
-
- case 0x86: /* SDPvTL */
- case 0x87: /* SDPvTL */
- Ins_SDPVTL( exc, args );
- break;
-
- case 0x88: /* GETINFO */
- Ins_GETINFO( exc, args );
- break;
-
- case 0x89: /* IDEF */
- Ins_IDEF( exc, args );
- break;
-
- case 0x8A: /* ROLL */
- Ins_ROLL( args );
- break;
-
- case 0x8B: /* MAX */
- Ins_MAX( args );
- break;
-
- case 0x8C: /* MIN */
- Ins_MIN( args );
- break;
-
- case 0x8D: /* SCANTYPE */
- Ins_SCANTYPE( exc, args );
- break;
-
- case 0x8E: /* INSTCTRL */
- Ins_INSTCTRL( exc, args );
- break;
-
- case 0x8F: /* ADJUST */
- case 0x90: /* ADJUST */
- Ins_UNKNOWN( exc );
- break;
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- case 0x91:
- /* it is the job of the application to `activate' GX handling, */
- /* this is, calling any of the GX API functions on the current */
- /* font to select a variation instance */
- if ( exc->face->blend )
- Ins_GETVARIATION( exc, args );
- else
- Ins_UNKNOWN( exc );
- break;
-
- case 0x92:
- /* there is at least one MS font (LaoUI.ttf version 5.01) that */
- /* uses IDEFs for 0x91 and 0x92; for this reason we activate */
- /* GETDATA for GX fonts only, similar to GETVARIATION */
- if ( exc->face->blend )
- Ins_GETDATA( args );
- else
- Ins_UNKNOWN( exc );
- break;
-#endif
-
- default:
- if ( opcode >= 0xE0 )
- Ins_MIRP( exc, args );
- else if ( opcode >= 0xC0 )
- Ins_MDRP( exc, args );
- else if ( opcode >= 0xB8 )
- Ins_PUSHW( exc, args );
- else if ( opcode >= 0xB0 )
- Ins_PUSHB( exc, args );
- else
- Ins_UNKNOWN( exc );
- }
- }
-
- if ( exc->error )
- {
- switch ( exc->error )
- {
- /* looking for redefined instructions */
- case FT_ERR( Invalid_Opcode ):
- {
- TT_DefRecord* def = exc->IDefs;
- TT_DefRecord* limit = def + exc->numIDefs;
-
-
- for ( ; def < limit; def++ )
- {
- if ( def->active && exc->opcode == (FT_Byte)def->opc )
- {
- TT_CallRec* callrec;
-
-
- if ( exc->callTop >= exc->callSize )
- {
- exc->error = FT_THROW( Invalid_Reference );
- goto LErrorLabel_;
- }
-
- callrec = &exc->callStack[exc->callTop];
-
- callrec->Caller_Range = exc->curRange;
- callrec->Caller_IP = exc->IP + 1;
- callrec->Cur_Count = 1;
- callrec->Def = def;
-
- if ( Ins_Goto_CodeRange( exc,
- def->range,
- def->start ) == FAILURE )
- goto LErrorLabel_;
-
- goto LSuiteLabel_;
- }
- }
- }
-
- exc->error = FT_THROW( Invalid_Opcode );
- goto LErrorLabel_;
-
-#if 0
- break; /* Unreachable code warning suppression. */
- /* Leave to remind in case a later change the editor */
- /* to consider break; */
-#endif
-
- default:
- goto LErrorLabel_;
-
-#if 0
- break;
-#endif
- }
- }
-
- exc->top = exc->new_top;
-
- if ( exc->step_ins )
- exc->IP += exc->length;
-
- /* increment instruction counter and check if we didn't */
- /* run this program for too long (e.g. infinite loops). */
- if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES )
- return FT_THROW( Execution_Too_Long );
-
- LSuiteLabel_:
- if ( exc->IP >= exc->codeSize )
- {
- if ( exc->callTop > 0 )
- {
- exc->error = FT_THROW( Code_Overflow );
- goto LErrorLabel_;
- }
- else
- goto LNo_Error_;
- }
- } while ( !exc->instruction_trap );
-
- LNo_Error_:
- FT_TRACE4(( " %d instructions executed\n", ins_counter ));
- return FT_Err_Ok;
-
- LErrorCodeOverflow_:
- exc->error = FT_THROW( Code_Overflow );
-
- LErrorLabel_:
- /* 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 ( exc->error &&
- !exc->instruction_trap &&
- exc->curRange == tt_coderange_glyph )
- {
- FT_TRACE1(( " The interpreter returned error 0x%x\n", exc->error ));
- exc->size->bytecode_ready = -1;
- exc->size->cvt_ready = -1;
- }
-
- return exc->error;
- }
-
-
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttinterp.h b/third_party/freetype/src/truetype/ttinterp.h
deleted file mode 100644
index 6625e16c76..0000000000
--- a/third_party/freetype/src/truetype/ttinterp.h
+++ /dev/null
@@ -1,523 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttinterp.h */
-/* */
-/* TrueType bytecode interpreter (specification). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef TTINTERP_H_
-#define TTINTERP_H_
-
-#include <ft2build.h>
-#include "ttobjs.h"
-
-
-FT_BEGIN_HEADER
-
-
- /*************************************************************************/
- /* */
- /* Rounding mode constants. */
- /* */
-#define TT_Round_Off 5
-#define TT_Round_To_Half_Grid 0
-#define TT_Round_To_Grid 1
-#define TT_Round_To_Double_Grid 2
-#define TT_Round_Up_To_Grid 4
-#define TT_Round_Down_To_Grid 3
-#define TT_Round_Super 6
-#define TT_Round_Super_45 7
-
-
- /*************************************************************************/
- /* */
- /* Function types used by the interpreter, depending on various modes */
- /* (e.g. the rounding mode, whether to render a vertical or horizontal */
- /* line etc). */
- /* */
- /*************************************************************************/
-
- /* Rounding function */
- typedef FT_F26Dot6
- (*TT_Round_Func)( TT_ExecContext exc,
- FT_F26Dot6 distance,
- FT_F26Dot6 compensation );
-
- /* Point displacement along the freedom vector routine */
- typedef void
- (*TT_Move_Func)( TT_ExecContext exc,
- TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance );
-
- /* Distance projection along one of the projection vectors */
- typedef FT_F26Dot6
- (*TT_Project_Func)( TT_ExecContext exc,
- FT_Pos dx,
- FT_Pos dy );
-
- /* getting current ppem. Take care of non-square pixels if necessary */
- typedef FT_Long
- (*TT_Cur_Ppem_Func)( TT_ExecContext exc );
-
- /* reading a cvt value. Take care of non-square pixels if necessary */
- typedef FT_F26Dot6
- (*TT_Get_CVT_Func)( TT_ExecContext exc,
- FT_ULong idx );
-
- /* setting or moving a cvt value. Take care of non-square pixels */
- /* if necessary */
- typedef void
- (*TT_Set_CVT_Func)( TT_ExecContext exc,
- FT_ULong idx,
- FT_F26Dot6 value );
-
-
- /*************************************************************************/
- /* */
- /* This structure defines a call record, used to manage function calls. */
- /* */
- typedef struct TT_CallRec_
- {
- FT_Int Caller_Range;
- FT_Long Caller_IP;
- FT_Long Cur_Count;
-
- TT_DefRecord *Def; /* either FDEF or IDEF */
-
- } TT_CallRec, *TT_CallStack;
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- /*************************************************************************/
- /* */
- /* These structures define rules used to tweak subpixel hinting for */
- /* various fonts. "", 0, "", NULL value indicates to match any value. */
- /* */
-
-#define SPH_MAX_NAME_SIZE 32
-#define SPH_MAX_CLASS_MEMBERS 100
-
- typedef struct SPH_TweakRule_
- {
- const char family[SPH_MAX_NAME_SIZE];
- const FT_UInt ppem;
- const char style[SPH_MAX_NAME_SIZE];
- const FT_ULong glyph;
-
- } SPH_TweakRule;
-
-
- typedef struct SPH_ScaleRule_
- {
- const char family[SPH_MAX_NAME_SIZE];
- const FT_UInt ppem;
- const char style[SPH_MAX_NAME_SIZE];
- const FT_ULong glyph;
- const FT_ULong scale;
-
- } SPH_ScaleRule;
-
-
- typedef struct SPH_Font_Class_
- {
- const char name[SPH_MAX_NAME_SIZE];
- const char member[SPH_MAX_CLASS_MEMBERS][SPH_MAX_NAME_SIZE];
-
- } SPH_Font_Class;
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-
- /*************************************************************************/
- /* */
- /* The main structure for the interpreter which collects all necessary */
- /* variables and states. */
- /* */
- typedef struct TT_ExecContextRec_
- {
- TT_Face face;
- TT_Size size;
- FT_Memory memory;
-
- /* instructions state */
-
- FT_Error error; /* last execution error */
-
- FT_Long top; /* top of exec. stack */
-
- FT_Long stackSize; /* size of exec. stack */
- FT_Long* stack; /* current exec. stack */
-
- FT_Long args;
- FT_Long new_top; /* new top after exec. */
-
- TT_GlyphZoneRec zp0, /* zone records */
- zp1,
- zp2,
- pts,
- twilight;
-
- FT_Long pointSize; /* in 26.6 format */
- FT_Size_Metrics metrics;
- TT_Size_Metrics tt_metrics; /* size metrics */
-
- TT_GraphicsState GS; /* current graphics state */
-
- FT_Int curRange; /* current code range number */
- FT_Byte* code; /* current code range */
- FT_Long IP; /* current instruction pointer */
- FT_Long codeSize; /* size of current range */
-
- FT_Byte opcode; /* current opcode */
- FT_Int length; /* length of current opcode */
-
- FT_Bool step_ins; /* true if the interpreter must */
- /* increment IP after ins. exec */
- FT_ULong cvtSize;
- FT_Long* cvt;
-
- FT_UInt glyphSize; /* glyph instructions buffer size */
- FT_Byte* glyphIns; /* glyph instructions buffer */
-
- FT_UInt numFDefs; /* number of function defs */
- FT_UInt maxFDefs; /* maximum number of function defs */
- TT_DefArray FDefs; /* table of FDefs entries */
-
- FT_UInt numIDefs; /* number of instruction defs */
- FT_UInt maxIDefs; /* maximum number of ins defs */
- TT_DefArray IDefs; /* table of IDefs entries */
-
- FT_UInt maxFunc; /* maximum function index */
- FT_UInt maxIns; /* maximum instruction index */
-
- FT_Int callTop, /* top of call stack during execution */
- callSize; /* size of call stack */
- TT_CallStack callStack; /* call stack */
-
- FT_UShort maxPoints; /* capacity of this context's `pts' */
- FT_Short maxContours; /* record, expressed in points and */
- /* contours. */
-
- TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */
- /* useful for the debugger */
-
- FT_UShort storeSize; /* size of current storage */
- FT_Long* storage; /* storage area */
-
- FT_F26Dot6 period; /* values used for the */
- FT_F26Dot6 phase; /* `SuperRounding' */
- FT_F26Dot6 threshold;
-
- FT_Bool instruction_trap; /* If `True', the interpreter will */
- /* exit after each instruction */
-
- TT_GraphicsState default_GS; /* graphics state resulting from */
- /* the prep program */
- FT_Bool is_composite; /* true if the glyph is composite */
- FT_Bool pedantic_hinting; /* true if pedantic interpretation */
-
- /* latest interpreter additions */
-
- FT_Long F_dot_P; /* dot product of freedom and projection */
- /* vectors */
- TT_Round_Func func_round; /* current rounding function */
-
- TT_Project_Func func_project, /* current projection function */
- func_dualproj, /* current dual proj. function */
- func_freeProj; /* current freedom proj. func */
-
- 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) */
-
- FT_Bool grayscale; /* bi-level hinting and */
- /* grayscale rendering */
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /*
- * Modern TrueType fonts are usually rendered through Microsoft's
- * collection of rendering techniques called ClearType (e.g., subpixel
- * rendering and subpixel hinting). When ClearType was introduced, most
- * fonts were not ready. Microsoft decided to implement a backwards
- * compatibility mode that employed several simple to complicated
- * assumptions and tricks that modified the interpretation of the
- * bytecode contained in these fonts to make them look ClearType-y
- * somehow. Most (web)fonts that were released since then have come to
- * rely on these hacks to render correctly, even some of Microsoft's
- * flagship ClearType fonts (Calibri, Cambria, Segoe UI).
- *
- * The minimal subpixel hinting code (interpreter version 40) employs a
- * small list of font-agnostic hacks to bludgeon non-native-ClearType
- * fonts (except tricky ones[1]) into submission. It will not try to
- * toggle hacks for specific fonts for performance and complexity
- * reasons. The focus is on modern (web)fonts rather than legacy fonts
- * that were made for black-and-white rendering.
- *
- * Major hacks
- *
- * - Any point movement on the x axis is ignored (cf. `Direct_Move' and
- * `Direct_Move_X'). This has the smallest code footprint and single
- * biggest effect. The ClearType way to increase resolution is
- * supersampling the x axis, the FreeType way is ignoring instructions
- * on the x axis, which gives the same result in the majority of
- * cases.
- *
- * - Points are not moved post-IUP (neither on the x nor on the y axis),
- * except the x component of diagonal moves post-IUP (cf.
- * `Direct_Move', `Direct_Move_Y', `Move_Zp2_Point'). Post-IUP
- * changes are commonly used to `fix' pixel patterns which has little
- * use outside monochrome rendering.
- *
- * - SHPIX and DELTAP don't execute unless moving a composite on the
- * y axis or moving a previously y touched point. SHPIX additionally
- * denies movement on the x axis (cf. `Ins_SHPIX' and `Ins_DELTAP').
- * Both instructions are commonly used to `fix' pixel patterns for
- * monochrome or Windows's GDI rendering but make little sense for
- * FreeType rendering. Both can distort the outline. See [2] for
- * details.
- *
- * - The hdmx table and modifications to phantom points are ignored.
- * Bearings and advance widths remain unchanged (except rounding them
- * outside the interpreter!), cf. `compute_glyph_metrics' and
- * `TT_Hint_Glyph'. Letting non-native-ClearType fonts modify spacing
- * might mess up spacing.
- *
- * Minor hacks
- *
- * - FLIPRGON, FLIPRGOFF, and FLIPPT don't execute post-IUP. This
- * prevents dents in e.g. Arial-Regular's `D' and `G' glyphs at
- * various sizes.
- *
- * (Post-IUP is the state after both IUP[x] and IUP[y] have been
- * executed.)
- *
- * The best results are achieved for fonts that were from the outset
- * designed with ClearType in mind, meaning they leave the x axis mostly
- * alone and don't mess with the `final' outline to produce more
- * pleasing pixel patterns. The harder the designer tried to produce
- * very specific patterns (`superhinting') for pre-ClearType-displays,
- * the worse the results.
- *
- * Microsoft defines a way to turn off backwards compatibility and
- * interpret instructions as before (called `native ClearType')[2][3].
- * The font designer then regains full control and is responsible for
- * making the font work correctly with ClearType without any
- * hand-holding by the interpreter or rasterizer[4]. The v40
- * interpreter assumes backwards compatibility by default, which can be
- * turned off the same way by executing the following in the control
- * program (cf. `Ins_INSTCTRL').
- *
- * #PUSH 4,3
- * INSTCTRL[]
- *
- * [1] Tricky fonts as FreeType defines them rely on the bytecode
- * interpreter to display correctly. Hacks can interfere with them,
- * so they get treated like native ClearType fonts (v40 with
- * backwards compatibility turned off). Cf. `TT_RunIns'.
- *
- * [2] Proposed by Microsoft's Greg Hitchcock in
- * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
- *
- * [3] Beat Stamm describes it in more detail:
- * http://www.beatstamm.com/typography/RTRCh4.htm#Sec12
- *
- * [4] The list of `native ClearType' fonts is small at the time of this
- * writing; I found the following on a Windows 10 Update 1511
- * installation: Constantia, Corbel, Sitka, Malgun Gothic, Microsoft
- * JhengHei (Bold and UI Bold), Microsoft YaHei (Bold and UI Bold),
- * SimSun, NSimSun, and Yu Gothic.
- *
- */
-
- /* Using v40 implies subpixel hinting. Used to detect interpreter */
- /* version switches. `_lean' to differentiate from the Infinality */
- /* `subpixel_hinting', which is managed differently. */
- FT_Bool subpixel_hinting_lean;
-
- /* Long side of a LCD subpixel is vertical (e.g., screen is rotated). */
- /* `_lean' to differentiate from the Infinality `vertical_lcd', which */
- /* is managed differently. */
- FT_Bool vertical_lcd_lean;
-
- /* Default to backwards compatibility mode in v40 interpreter. If */
- /* this is false, it implies the interpreter is in v35 or in native */
- /* ClearType mode. */
- FT_Bool backwards_compatibility;
-
- /* Useful for detecting and denying post-IUP trickery that is usually */
- /* used to fix pixel patterns (`superhinting'). */
- FT_Bool iupx_called;
- FT_Bool iupy_called;
-
- /* ClearType hinting and grayscale rendering, as used by Universal */
- /* Windows Platform apps (Windows 8 and above). Like the standard */
- /* colorful ClearType mode, it utilizes a vastly increased virtual */
- /* resolution on the x axis. Different from bi-level hinting and */
- /* grayscale rendering, the old mode from Win9x days that roughly */
- /* adheres to the physical pixel grid on both axes. */
- FT_Bool grayscale_cleartype;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- TT_Round_Func func_round_sphn; /* subpixel rounding function */
-
- FT_Bool subpixel_hinting; /* Using subpixel hinting? */
- FT_Bool ignore_x_mode; /* Standard rendering mode for */
- /* subpixel hinting. On if gray */
- /* or subpixel hinting is on. */
-
- /* The following 6 aren't fully implemented but here for MS rasterizer */
- /* compatibility. */
- FT_Bool compatible_widths; /* compatible widths? */
- FT_Bool symmetrical_smoothing; /* symmetrical_smoothing? */
- FT_Bool bgr; /* bgr instead of rgb? */
- FT_Bool vertical_lcd; /* long side of LCD subpixel */
- /* rectangles is horizontal */
- FT_Bool subpixel_positioned; /* subpixel positioned */
- /* (DirectWrite ClearType)? */
- FT_Bool gray_cleartype; /* ClearType hinting but */
- /* grayscale rendering */
-
- FT_Int rasterizer_version; /* MS rasterizer version */
-
- FT_Bool iup_called; /* IUP called for glyph? */
-
- FT_ULong sph_tweak_flags; /* flags to control */
- /* hint tweaks */
-
- FT_ULong sph_in_func_flags; /* flags to indicate if in */
- /* special functions */
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- /* We maintain two counters (in addition to the instruction counter) */
- /* that act as loop detectors for LOOPCALL and jump opcodes with */
- /* negative arguments. */
- FT_ULong loopcall_counter;
- FT_ULong loopcall_counter_max;
- FT_ULong neg_jump_counter;
- FT_ULong neg_jump_counter_max;
-
- } TT_ExecContextRec;
-
-
- extern const TT_GraphicsState tt_default_graphics_state;
-
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
- FT_LOCAL( void )
- TT_Goto_CodeRange( TT_ExecContext exec,
- FT_Int range,
- FT_Long IP );
-
- FT_LOCAL( void )
- TT_Set_CodeRange( TT_ExecContext exec,
- FT_Int range,
- void* base,
- FT_Long length );
-
- FT_LOCAL( void )
- TT_Clear_CodeRange( TT_ExecContext exec,
- FT_Int range );
-
-
- FT_LOCAL( FT_Error )
- Update_Max( FT_Memory memory,
- FT_ULong* size,
- FT_ULong multiplier,
- void* _pbuff,
- FT_ULong new_max );
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_New_Context */
- /* */
- /* <Description> */
- /* Queries the face context for a given font. Note that there is */
- /* now a _single_ execution context in the TrueType driver which is */
- /* shared among faces. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* <Return> */
- /* A handle to the execution context. Initialized for `face'. */
- /* */
- /* <Note> */
- /* Only the glyph loader and debugger should call this function. */
- /* (And right now only the glyph loader uses it.) */
- /* */
- FT_EXPORT( TT_ExecContext )
- TT_New_Context( TT_Driver driver );
-
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
- FT_LOCAL( void )
- TT_Done_Context( TT_ExecContext exec );
-
- FT_LOCAL( FT_Error )
- TT_Load_Context( TT_ExecContext exec,
- TT_Face face,
- TT_Size size );
-
- FT_LOCAL( void )
- TT_Save_Context( TT_ExecContext exec,
- TT_Size ins );
-
- FT_LOCAL( FT_Error )
- TT_Run_Context( TT_ExecContext exec );
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_RunIns */
- /* */
- /* <Description> */
- /* Executes one or more instruction in the execution context. This */
- /* is the main function of the TrueType opcode interpreter. */
- /* */
- /* <Input> */
- /* exec :: A handle to the target execution context. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Only the object manager and debugger should call this function. */
- /* */
- /* This function is publicly exported because it is directly */
- /* invoked by the TrueType debugger. */
- /* */
- FT_EXPORT( FT_Error )
- TT_RunIns( TT_ExecContext exec );
-
-
-FT_END_HEADER
-
-#endif /* TTINTERP_H_ */
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttobjs.c b/third_party/freetype/src/truetype/ttobjs.c
deleted file mode 100644
index 18aa48a93f..0000000000
--- a/third_party/freetype/src/truetype/ttobjs.c
+++ /dev/null
@@ -1,1363 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttobjs.c */
-/* */
-/* Objects manager (body). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_STREAM_H
-#include FT_TRUETYPE_TAGS_H
-#include FT_INTERNAL_SFNT_H
-#include FT_TRUETYPE_DRIVER_H
-
-#include "ttgload.h"
-#include "ttpload.h"
-
-#include "tterrors.h"
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-#include "ttinterp.h"
-#endif
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#include "ttgxvar.h"
-#endif
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttobjs
-
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- /*************************************************************************/
- /* */
- /* GLYPH ZONE FUNCTIONS */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_glyphzone_done */
- /* */
- /* <Description> */
- /* Deallocate a glyph zone. */
- /* */
- /* <Input> */
- /* zone :: A pointer to the target glyph zone. */
- /* */
- FT_LOCAL_DEF( void )
- tt_glyphzone_done( TT_GlyphZone zone )
- {
- FT_Memory memory = zone->memory;
-
-
- if ( memory )
- {
- FT_FREE( zone->contours );
- FT_FREE( zone->tags );
- FT_FREE( zone->cur );
- FT_FREE( zone->org );
- FT_FREE( zone->orus );
-
- zone->max_points = zone->n_points = 0;
- zone->max_contours = zone->n_contours = 0;
- zone->memory = NULL;
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_glyphzone_new */
- /* */
- /* <Description> */
- /* Allocate a new glyph zone. */
- /* */
- /* <Input> */
- /* memory :: A handle to the current memory object. */
- /* */
- /* maxPoints :: The capacity of glyph zone in points. */
- /* */
- /* maxContours :: The capacity of glyph zone in contours. */
- /* */
- /* <Output> */
- /* zone :: A pointer to the target glyph zone record. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_glyphzone_new( FT_Memory memory,
- FT_UShort maxPoints,
- FT_Short maxContours,
- TT_GlyphZone zone )
- {
- FT_Error error;
-
-
- FT_ZERO( zone );
- zone->memory = memory;
-
- if ( FT_NEW_ARRAY( zone->org, maxPoints ) ||
- FT_NEW_ARRAY( zone->cur, maxPoints ) ||
- FT_NEW_ARRAY( zone->orus, maxPoints ) ||
- FT_NEW_ARRAY( zone->tags, maxPoints ) ||
- FT_NEW_ARRAY( zone->contours, maxContours ) )
- {
- tt_glyphzone_done( zone );
- }
- else
- {
- zone->max_points = maxPoints;
- zone->max_contours = maxContours;
- }
-
- return error;
- }
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
-
- /* Compare the face with a list of well-known `tricky' fonts. */
- /* This list shall be expanded as we find more of them. */
-
- static FT_Bool
- tt_check_trickyness_family( FT_String* name )
- {
-
-#define TRICK_NAMES_MAX_CHARACTERS 19
-#define TRICK_NAMES_COUNT 9
-
- static const char trick_names[TRICK_NAMES_COUNT]
- [TRICK_NAMES_MAX_CHARACTERS + 1] =
- {
- "DFKaiSho-SB", /* dfkaisb.ttf */
- "DFKaiShu",
- "DFKai-SB", /* kaiu.ttf */
- "HuaTianKaiTi?", /* htkt2.ttf */
- "HuaTianSongTi?", /* htst3.ttf */
- "Ming(for ISO10646)", /* hkscsiic.ttf & iicore.ttf */
- "MingLiU", /* mingliu.ttf & mingliu.ttc */
- "PMingLiU", /* mingliu.ttc */
- "MingLi43", /* mingli.ttf */
- };
-
- int nn;
-
-
- for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ )
- if ( ft_strstr( name, trick_names[nn] ) )
- return TRUE;
-
- return FALSE;
- }
-
-
- /* XXX: This function should be in the `sfnt' module. */
-
- /* Some PDF generators clear the checksums in the TrueType header table. */
- /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF */
- /* Printer clears the entries for subsetted subtables. We thus have to */
- /* recalculate the checksums where necessary. */
-
- static FT_UInt32
- tt_synth_sfnt_checksum( FT_Stream stream,
- FT_ULong length )
- {
- FT_Error error;
- FT_UInt32 checksum = 0;
- FT_UInt i;
-
-
- if ( FT_FRAME_ENTER( length ) )
- return 0;
-
- for ( ; length > 3; length -= 4 )
- checksum += (FT_UInt32)FT_GET_ULONG();
-
- for ( i = 3; length > 0; length--, i-- )
- checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
-
- FT_FRAME_EXIT();
-
- return checksum;
- }
-
-
- /* XXX: This function should be in the `sfnt' module. */
-
- static FT_ULong
- tt_get_sfnt_checksum( TT_Face face,
- FT_UShort i )
- {
-#if 0 /* if we believe the written value, use following part. */
- if ( face->dir_tables[i].CheckSum )
- return face->dir_tables[i].CheckSum;
-#endif
-
- if ( !face->goto_table )
- return 0;
-
- if ( face->goto_table( face,
- face->dir_tables[i].Tag,
- face->root.stream,
- NULL ) )
- return 0;
-
- return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
- face->dir_tables[i].Length );
- }
-
-
- typedef struct tt_sfnt_id_rec_
- {
- FT_ULong CheckSum;
- FT_ULong Length;
-
- } tt_sfnt_id_rec;
-
-
- static FT_Bool
- tt_check_trickyness_sfnt_ids( TT_Face face )
- {
-#define TRICK_SFNT_IDS_PER_FACE 3
-#define TRICK_SFNT_IDS_NUM_FACES 18
-
- static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
- [TRICK_SFNT_IDS_PER_FACE] = {
-
-#define TRICK_SFNT_ID_cvt 0
-#define TRICK_SFNT_ID_fpgm 1
-#define TRICK_SFNT_ID_prep 2
-
- { /* MingLiU 1995 */
- { 0x05BCF058UL, 0x000002E4UL }, /* cvt */
- { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
- { 0xA344A1EAUL, 0x000001E1UL } /* prep */
- },
- { /* MingLiU 1996- */
- { 0x05BCF058UL, 0x000002E4UL }, /* cvt */
- { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
- { 0xA344A1EBUL, 0x000001E1UL } /* prep */
- },
- { /* DFKaiShu */
- { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
- { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */
- { 0x13A42602UL, 0x0000007EUL } /* prep */
- },
- { /* DFKaiShu2 */
- { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
- { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */
- { 0x13A42602UL, 0x0000007EUL } /* prep */
- },
- { /* HuaTianKaiTi */
- { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */
- { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */
- { 0x70020112UL, 0x00000008UL } /* prep */
- },
- { /* HuaTianSongTi */
- { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */
- { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */
- { 0x70020112UL, 0x00000008UL } /* prep */
- },
- { /* NEC fadpop7.ttf */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
- { 0xA39B58E3UL, 0x0000117CUL } /* prep */
- },
- { /* NEC fadrei5.ttf */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0x33C41652UL, 0x000000E5UL }, /* fpgm */
- { 0x26D6C52AUL, 0x00000F6AUL } /* prep */
- },
- { /* NEC fangot7.ttf */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */
- { 0x6C6E4B03UL, 0x00002492UL } /* prep */
- },
- { /* NEC fangyo5.ttf */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
- { 0xDE51FAD0UL, 0x0000117CUL } /* prep */
- },
- { /* NEC fankyo5.ttf */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0x85E47664UL, 0x000000E5UL }, /* fpgm */
- { 0xA6C62831UL, 0x00001CAAUL } /* prep */
- },
- { /* NEC fanrgo5.ttf */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */
- { 0xA0604633UL, 0x00001DE8UL } /* prep */
- },
- { /* NEC fangot5.ttc */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */
- { 0x9B5CAA96UL, 0x00001F9AUL } /* prep */
- },
- { /* NEC fanmin3.ttc */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */
- { 0xD4127766UL, 0x00002280UL } /* prep */
- },
- { /* NEC FA-Gothic, 1996 */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0x4A692698UL, 0x000001F0UL }, /* fpgm */
- { 0x340D4346UL, 0x00001FCAUL } /* prep */
- },
- { /* NEC FA-Minchou, 1996 */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0xCD34C604UL, 0x00000166UL }, /* fpgm */
- { 0x6CF31046UL, 0x000022B0UL } /* prep */
- },
- { /* NEC FA-RoundGothicB, 1996 */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */
- { 0x40745A5FUL, 0x000022E0UL } /* prep */
- },
- { /* NEC FA-RoundGothicM, 1996 */
- { 0x00000000UL, 0x00000000UL }, /* cvt */
- { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */
- { 0x3900DED3UL, 0x00001E18UL } /* prep */
- }
- };
-
- FT_ULong checksum;
- int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
- FT_Bool has_cvt, has_fpgm, has_prep;
- FT_UShort i;
- int j, k;
-
-
- FT_MEM_SET( num_matched_ids, 0,
- sizeof ( int ) * TRICK_SFNT_IDS_NUM_FACES );
- has_cvt = FALSE;
- has_fpgm = FALSE;
- has_prep = FALSE;
-
- for ( i = 0; i < face->num_tables; i++ )
- {
- checksum = 0;
-
- switch( face->dir_tables[i].Tag )
- {
- case TTAG_cvt:
- k = TRICK_SFNT_ID_cvt;
- has_cvt = TRUE;
- break;
-
- case TTAG_fpgm:
- k = TRICK_SFNT_ID_fpgm;
- has_fpgm = TRUE;
- break;
-
- case TTAG_prep:
- k = TRICK_SFNT_ID_prep;
- has_prep = TRUE;
- break;
-
- default:
- continue;
- }
-
- for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
- if ( face->dir_tables[i].Length == sfnt_id[j][k].Length )
- {
- if ( !checksum )
- checksum = tt_get_sfnt_checksum( face, i );
-
- if ( sfnt_id[j][k].CheckSum == checksum )
- num_matched_ids[j]++;
-
- if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
- return TRUE;
- }
- }
-
- for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
- {
- if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
- num_matched_ids[j]++;
- if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
- num_matched_ids[j]++;
- if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
- num_matched_ids[j]++;
- if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
- return TRUE;
- }
-
- return FALSE;
- }
-
-
- static FT_Bool
- tt_check_trickyness( FT_Face face )
- {
- if ( !face )
- return FALSE;
-
- /* For first, check the face name for quick check. */
- if ( face->family_name &&
- tt_check_trickyness_family( face->family_name ) )
- return TRUE;
-
- /* Type42 fonts may lack `name' tables, we thus try to identify */
- /* tricky fonts by checking the checksums of Type42-persistent */
- /* sfnt tables (`cvt', `fpgm', and `prep'). */
- if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) )
- return TRUE;
-
- return FALSE;
- }
-
-
- /* Check whether `.notdef' is the only glyph in the `loca' table. */
- static FT_Bool
- tt_check_single_notdef( FT_Face ttface )
- {
- FT_Bool result = FALSE;
-
- TT_Face face = (TT_Face)ttface;
- FT_UInt asize;
- FT_ULong i;
- FT_ULong glyph_index = 0;
- FT_UInt count = 0;
-
-
- for( i = 0; i < face->num_locations; i++ )
- {
- tt_face_get_location( face, i, &asize );
- if ( asize > 0 )
- {
- count += 1;
- if ( count > 1 )
- break;
- glyph_index = i;
- }
- }
-
- /* Only have a single outline. */
- if ( count == 1 )
- {
- if ( glyph_index == 0 )
- result = TRUE;
- else
- {
- /* FIXME: Need to test glyphname == .notdef ? */
- FT_Error error;
- char buf[8];
-
-
- error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 );
- if ( !error &&
- buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) )
- result = TRUE;
- }
- }
-
- return result;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_init */
- /* */
- /* <Description> */
- /* Initialize a given TrueType face object. */
- /* */
- /* <Input> */
- /* stream :: The source font stream. */
- /* */
- /* face_index :: The index of the TrueType font, if we are opening a */
- /* collection, in bits 0-15. The numbered instance */
- /* index~+~1 of a GX (sub)font, if applicable, in bits */
- /* 16-30. */
- /* */
- /* num_params :: Number of additional generic parameters. Ignored. */
- /* */
- /* params :: Additional generic parameters. Ignored. */
- /* */
- /* <InOut> */
- /* face :: The newly built face object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_init( FT_Stream stream,
- FT_Face ttface, /* TT_Face */
- FT_Int face_index,
- FT_Int num_params,
- FT_Parameter* params )
- {
- FT_Error error;
- FT_Library library;
- SFNT_Service sfnt;
- TT_Face face = (TT_Face)ttface;
-
-
- FT_TRACE2(( "TTF driver\n" ));
-
- library = ttface->driver->root.library;
-
- sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
- if ( !sfnt )
- {
- FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" ));
- error = FT_THROW( Missing_Module );
- goto Exit;
- }
-
- /* create input stream from resource */
- if ( FT_STREAM_SEEK( 0 ) )
- goto Exit;
-
- /* check that we have a valid TrueType file */
- FT_TRACE2(( " " ));
- error = sfnt->init_face( stream, face, face_index, num_params, params );
-
- /* Stream may have changed. */
- stream = face->root.stream;
-
- if ( error )
- goto Exit;
-
- /* We must also be able to accept Mac/GX fonts, as well as OT ones. */
- /* The 0x00020000 tag is completely undocumented; some fonts from */
- /* Arphic made for Chinese Windows 3.1 have this. */
- if ( face->format_tag != 0x00010000L && /* MS fonts */
- face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */
- face->format_tag != TTAG_true ) /* Mac fonts */
- {
- FT_TRACE2(( " not a TTF font\n" ));
- goto Bad_Format;
- }
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
- ttface->face_flags |= FT_FACE_FLAG_HINTER;
-#endif
-
- /* If we are performing a simple font format check, exit immediately. */
- if ( face_index < 0 )
- return FT_Err_Ok;
-
- /* Load font directory */
- error = sfnt->load_face( stream, face, face_index, num_params, params );
- if ( error )
- goto Exit;
-
- if ( tt_check_trickyness( ttface ) )
- ttface->face_flags |= FT_FACE_FLAG_TRICKY;
-
- error = tt_face_load_hdmx( face, stream );
- if ( error )
- goto Exit;
-
- if ( FT_IS_SCALABLE( ttface ) )
- {
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- if ( !ttface->internal->incremental_interface )
-#endif
- {
- error = tt_face_load_loca( face, stream );
-
- /* having a (non-zero) `glyf' table without */
- /* a `loca' table is not valid */
- if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) )
- goto Exit;
- if ( error )
- goto Exit;
- }
-
- /* `fpgm', `cvt', and `prep' are optional */
- error = tt_face_load_cvt( face, stream );
- if ( error && FT_ERR_NEQ( error, Table_Missing ) )
- goto Exit;
-
- error = tt_face_load_fpgm( face, stream );
- if ( error && FT_ERR_NEQ( error, Table_Missing ) )
- goto Exit;
-
- error = tt_face_load_prep( face, stream );
- if ( error && FT_ERR_NEQ( error, Table_Missing ) )
- goto Exit;
-
- /* Check the scalable flag based on `loca'. */
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- if ( !ttface->internal->incremental_interface )
-#endif
- {
- if ( ttface->num_fixed_sizes &&
- face->glyph_locations &&
- tt_check_single_notdef( ttface ) )
- {
- FT_TRACE5(( "tt_face_init:"
- " Only the `.notdef' glyph has an outline.\n"
- " "
- " Resetting scalable flag to FALSE.\n" ));
-
- ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
- }
- }
- }
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-
- {
- FT_Int instance_index = face_index >> 16;
-
-
- if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
- instance_index > 0 )
- {
- error = TT_Get_MM_Var( face, NULL );
- if ( error )
- goto Exit;
-
- if ( face->blend->mmvar->namedstyle )
- {
- FT_Memory memory = ttface->memory;
-
- FT_Var_Named_Style* named_style;
- FT_String* style_name;
-
-
- /* in `face_index', the instance index starts with value 1 */
- named_style = face->blend->mmvar->namedstyle + instance_index - 1;
- error = sfnt->get_name( face,
- (FT_UShort)named_style->strid,
- &style_name );
- if ( error )
- goto Exit;
-
- /* set style name; if already set, replace it */
- if ( face->root.style_name )
- FT_FREE( face->root.style_name );
- face->root.style_name = style_name;
-
- /* finally, select the named instance */
- error = TT_Set_Var_Design( face,
- face->blend->mmvar->num_axis,
- named_style->coords );
- if ( error )
- goto Exit;
-
- tt_apply_mvar( face );
- }
- }
- }
-
-#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
-
- /* initialize standard glyph loading routines */
- TT_Init_Glyph_Loading( face );
-
- Exit:
- return error;
-
- Bad_Format:
- error = FT_THROW( Unknown_File_Format );
- goto Exit;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_done */
- /* */
- /* <Description> */
- /* Finalize a given face object. */
- /* */
- /* <Input> */
- /* face :: A pointer to the face object to destroy. */
- /* */
- FT_LOCAL_DEF( void )
- tt_face_done( FT_Face ttface ) /* TT_Face */
- {
- TT_Face face = (TT_Face)ttface;
- FT_Memory memory;
- FT_Stream stream;
- SFNT_Service sfnt;
-
-
- if ( !face )
- return;
-
- memory = ttface->memory;
- stream = ttface->stream;
- sfnt = (SFNT_Service)face->sfnt;
-
- /* for `extended TrueType formats' (i.e. compressed versions) */
- if ( face->extra.finalizer )
- face->extra.finalizer( face->extra.data );
-
- if ( sfnt )
- sfnt->done_face( face );
-
- /* freeing the locations table */
- tt_face_done_loca( face );
-
- tt_face_free_hdmx( face );
-
- /* freeing the CVT */
- FT_FREE( face->cvt );
- face->cvt_size = 0;
-
- /* freeing the programs */
- FT_FRAME_RELEASE( face->font_program );
- FT_FRAME_RELEASE( face->cvt_program );
- face->font_program_size = 0;
- face->cvt_program_size = 0;
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- tt_done_blend( face );
- face->blend = NULL;
-#endif
- }
-
-
- /*************************************************************************/
- /* */
- /* SIZE FUNCTIONS */
- /* */
- /*************************************************************************/
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_size_run_fpgm */
- /* */
- /* <Description> */
- /* Run the font program. */
- /* */
- /* <Input> */
- /* size :: A handle to the size object. */
- /* */
- /* pedantic :: Set if bytecode execution should be pedantic. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_size_run_fpgm( TT_Size size,
- FT_Bool pedantic )
- {
- TT_Face face = (TT_Face)size->root.face;
- TT_ExecContext exec;
- FT_Error error;
-
-
- exec = size->context;
-
- error = TT_Load_Context( exec, face, size );
- if ( error )
- return error;
-
- exec->callTop = 0;
- exec->top = 0;
-
- exec->period = 64;
- exec->phase = 0;
- exec->threshold = 0;
-
- exec->instruction_trap = FALSE;
- exec->F_dot_P = 0x4000L;
-
- exec->pedantic_hinting = pedantic;
-
- {
- FT_Size_Metrics* metrics = &exec->metrics;
- TT_Size_Metrics* tt_metrics = &exec->tt_metrics;
-
-
- metrics->x_ppem = 0;
- metrics->y_ppem = 0;
- metrics->x_scale = 0;
- metrics->y_scale = 0;
-
- tt_metrics->ppem = 0;
- tt_metrics->scale = 0;
- tt_metrics->ratio = 0x10000L;
- }
-
- /* allow font program execution */
- TT_Set_CodeRange( exec,
- tt_coderange_font,
- face->font_program,
- (FT_Long)face->font_program_size );
-
- /* disable CVT and glyph programs coderange */
- TT_Clear_CodeRange( exec, tt_coderange_cvt );
- TT_Clear_CodeRange( exec, tt_coderange_glyph );
-
- if ( face->font_program_size > 0 )
- {
- TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
-
- FT_TRACE4(( "Executing `fpgm' table.\n" ));
- error = face->interpreter( exec );
-#ifdef FT_DEBUG_LEVEL_TRACE
- if ( error )
- FT_TRACE4(( " interpretation failed with error code 0x%x\n",
- error ));
-#endif
- }
- else
- error = FT_Err_Ok;
-
- size->bytecode_ready = error;
-
- if ( !error )
- TT_Save_Context( exec, size );
-
- return error;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_size_run_prep */
- /* */
- /* <Description> */
- /* Run the control value program. */
- /* */
- /* <Input> */
- /* size :: A handle to the size object. */
- /* */
- /* pedantic :: Set if bytecode execution should be pedantic. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_size_run_prep( TT_Size size,
- FT_Bool pedantic )
- {
- TT_Face face = (TT_Face)size->root.face;
- TT_ExecContext exec;
- FT_Error error;
-
-
- exec = size->context;
-
- error = TT_Load_Context( exec, face, size );
- if ( error )
- return error;
-
- exec->callTop = 0;
- exec->top = 0;
-
- exec->instruction_trap = FALSE;
-
- exec->pedantic_hinting = pedantic;
-
- TT_Set_CodeRange( exec,
- tt_coderange_cvt,
- face->cvt_program,
- (FT_Long)face->cvt_program_size );
-
- TT_Clear_CodeRange( exec, tt_coderange_glyph );
-
- if ( face->cvt_program_size > 0 )
- {
- TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
-
- FT_TRACE4(( "Executing `prep' table.\n" ));
- error = face->interpreter( exec );
-#ifdef FT_DEBUG_LEVEL_TRACE
- if ( error )
- FT_TRACE4(( " interpretation failed with error code 0x%x\n",
- error ));
-#endif
- }
- 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. */
-
- exec->GS.dualVector.x = 0x4000;
- exec->GS.dualVector.y = 0;
- exec->GS.projVector.x = 0x4000;
- exec->GS.projVector.y = 0x0;
- exec->GS.freeVector.x = 0x4000;
- exec->GS.freeVector.y = 0x0;
-
- exec->GS.rp0 = 0;
- exec->GS.rp1 = 0;
- exec->GS.rp2 = 0;
-
- exec->GS.gep0 = 1;
- exec->GS.gep1 = 1;
- exec->GS.gep2 = 1;
-
- exec->GS.loop = 1;
-
- /* save as default graphics state */
- size->GS = exec->GS;
-
- TT_Save_Context( exec, size );
-
- return error;
- }
-
-
- static void
- tt_size_done_bytecode( FT_Size ftsize )
- {
- TT_Size size = (TT_Size)ftsize;
- TT_Face face = (TT_Face)ftsize->face;
- FT_Memory memory = face->root.memory;
-
- if ( size->context )
- {
- TT_Done_Context( size->context );
- size->context = NULL;
- }
-
- FT_FREE( size->cvt );
- size->cvt_size = 0;
-
- /* free storage area */
- FT_FREE( size->storage );
- size->storage_size = 0;
-
- /* twilight zone */
- tt_glyphzone_done( &size->twilight );
-
- FT_FREE( size->function_defs );
- FT_FREE( size->instruction_defs );
-
- size->num_function_defs = 0;
- size->max_function_defs = 0;
- size->num_instruction_defs = 0;
- size->max_instruction_defs = 0;
-
- size->max_func = 0;
- size->max_ins = 0;
-
- size->bytecode_ready = -1;
- size->cvt_ready = -1;
- }
-
-
- /* Initialize bytecode-related fields in the size object. */
- /* We do this only if bytecode interpretation is really needed. */
- static FT_Error
- tt_size_init_bytecode( FT_Size ftsize,
- FT_Bool pedantic )
- {
- FT_Error error;
- TT_Size size = (TT_Size)ftsize;
- TT_Face face = (TT_Face)ftsize->face;
- FT_Memory memory = face->root.memory;
-
- FT_UShort n_twilight;
- TT_MaxProfile* maxp = &face->max_profile;
-
-
- /* clean up bytecode related data */
- FT_FREE( size->function_defs );
- FT_FREE( size->instruction_defs );
- FT_FREE( size->cvt );
- FT_FREE( size->storage );
-
- if ( size->context )
- TT_Done_Context( size->context );
- tt_glyphzone_done( &size->twilight );
-
- size->bytecode_ready = -1;
- size->cvt_ready = -1;
-
- size->context = TT_New_Context( (TT_Driver)face->root.driver );
-
- size->max_function_defs = maxp->maxFunctionDefs;
- size->max_instruction_defs = maxp->maxInstructionDefs;
-
- size->num_function_defs = 0;
- size->num_instruction_defs = 0;
-
- size->max_func = 0;
- size->max_ins = 0;
-
- size->cvt_size = face->cvt_size;
- size->storage_size = maxp->maxStorage;
-
- /* Set default metrics */
- {
- TT_Size_Metrics* metrics = &size->ttmetrics;
-
-
- metrics->rotated = FALSE;
- metrics->stretched = FALSE;
-
- /* set default engine compensation */
- metrics->compensations[0] = 0; /* gray */
- metrics->compensations[1] = 0; /* black */
- metrics->compensations[2] = 0; /* white */
- metrics->compensations[3] = 0; /* reserved */
- }
-
- /* allocate function defs, instruction defs, cvt, and storage area */
- if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) ||
- FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) ||
- FT_NEW_ARRAY( size->cvt, size->cvt_size ) ||
- FT_NEW_ARRAY( size->storage, size->storage_size ) )
- goto Exit;
-
- /* reserve twilight zone */
- n_twilight = maxp->maxTwilightPoints;
-
- /* there are 4 phantom points (do we need this?) */
- n_twilight += 4;
-
- error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );
- if ( error )
- goto Exit;
-
- size->twilight.n_points = n_twilight;
-
- size->GS = tt_default_graphics_state;
-
- /* set `face->interpreter' according to the debug hook present */
- {
- FT_Library library = face->root.driver->root.library;
-
-
- face->interpreter = (TT_Interpreter)
- library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
- if ( !face->interpreter )
- face->interpreter = (TT_Interpreter)TT_RunIns;
- }
-
- /* Fine, now run the font program! */
-
- /* In case of an error while executing `fpgm', we intentionally don't */
- /* clean up immediately – bugs in the `fpgm' are so fundamental that */
- /* all following hinting calls should fail. Additionally, `fpgm' is */
- /* to be executed just once; calling it again is completely useless */
- /* and might even lead to extremely slow behaviour if it is malformed */
- /* (containing an infinite loop, for example). */
- error = tt_size_run_fpgm( size, pedantic );
- return error;
-
- Exit:
- if ( error )
- tt_size_done_bytecode( ftsize );
-
- return error;
- }
-
-
- FT_LOCAL_DEF( FT_Error )
- tt_size_ready_bytecode( TT_Size size,
- FT_Bool pedantic )
- {
- FT_Error error = FT_Err_Ok;
-
-
- if ( size->bytecode_ready < 0 )
- error = tt_size_init_bytecode( (FT_Size)size, pedantic );
- else
- error = size->bytecode_ready;
-
- if ( error )
- goto Exit;
-
- /* rescale CVT when needed */
- if ( size->cvt_ready < 0 )
- {
- FT_UInt i;
- TT_Face face = (TT_Face)size->root.face;
-
-
- /* Scale the cvt values to the new ppem. */
- /* We use by default the y ppem to scale the CVT. */
- for ( i = 0; i < size->cvt_size; i++ )
- size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
-
- /* all twilight points are originally zero */
- for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )
- {
- size->twilight.org[i].x = 0;
- size->twilight.org[i].y = 0;
- size->twilight.cur[i].x = 0;
- size->twilight.cur[i].y = 0;
- }
-
- /* clear storage area */
- for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
- size->storage[i] = 0;
-
- size->GS = tt_default_graphics_state;
-
- error = tt_size_run_prep( size, pedantic );
- }
- else
- error = size->cvt_ready;
-
- Exit:
- return error;
- }
-
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_size_init */
- /* */
- /* <Description> */
- /* Initialize a new TrueType size object. */
- /* */
- /* <InOut> */
- /* size :: A handle to the size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_size_init( FT_Size ttsize ) /* TT_Size */
- {
- TT_Size size = (TT_Size)ttsize;
- FT_Error error = FT_Err_Ok;
-
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
- size->bytecode_ready = -1;
- size->cvt_ready = -1;
-#endif
-
- size->ttmetrics.valid = FALSE;
- size->strike_index = 0xFFFFFFFFUL;
-
- return error;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_size_done */
- /* */
- /* <Description> */
- /* The TrueType size object finalizer. */
- /* */
- /* <Input> */
- /* size :: A handle to the target size object. */
- /* */
- FT_LOCAL_DEF( void )
- tt_size_done( FT_Size ttsize ) /* TT_Size */
- {
- TT_Size size = (TT_Size)ttsize;
-
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
- tt_size_done_bytecode( ttsize );
-#endif
-
- size->ttmetrics.valid = FALSE;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_size_reset */
- /* */
- /* <Description> */
- /* Reset a TrueType size when resolutions and character dimensions */
- /* have been changed. */
- /* */
- /* <Input> */
- /* size :: A handle to the target size object. */
- /* */
- /* only_height :: Only recompute ascender, descender, and height. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_size_reset( TT_Size size,
- FT_Bool only_height )
- {
- TT_Face face;
- FT_Size_Metrics* metrics;
-
-
- size->ttmetrics.valid = FALSE;
-
- face = (TT_Face)size->root.face;
-
- metrics = &size->metrics;
-
- /* copy the result from base layer */
- *metrics = size->root.metrics;
-
- if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
- return FT_THROW( Invalid_PPem );
-
- /* This bit flag, if set, indicates that the ppems must be */
- /* rounded to integers. Nearly all TrueType fonts have this bit */
- /* set, as hinting won't work really well otherwise. */
- /* */
- if ( face->header.Flags & 8 )
- {
- metrics->ascender =
- FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) );
- metrics->descender =
- FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) );
- metrics->height =
- FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) );
- }
-
- size->ttmetrics.valid = TRUE;
-
- if ( only_height )
- return FT_Err_Ok;
-
- if ( face->header.Flags & 8 )
- {
- metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
- face->root.units_per_EM );
- metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
- face->root.units_per_EM );
-
- metrics->max_advance =
- FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width,
- metrics->x_scale ) );
- }
-
- /* compute new transformation */
- if ( metrics->x_ppem >= metrics->y_ppem )
- {
- size->ttmetrics.scale = metrics->x_scale;
- size->ttmetrics.ppem = metrics->x_ppem;
- size->ttmetrics.x_ratio = 0x10000L;
- size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem,
- metrics->x_ppem );
- }
- else
- {
- size->ttmetrics.scale = metrics->y_scale;
- size->ttmetrics.ppem = metrics->y_ppem;
- size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem,
- metrics->y_ppem );
- size->ttmetrics.y_ratio = 0x10000L;
- }
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
- size->cvt_ready = -1;
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
- return FT_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_driver_init */
- /* */
- /* <Description> */
- /* Initialize a given TrueType driver object. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target driver object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_driver_init( FT_Module ttdriver ) /* TT_Driver */
- {
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- TT_Driver driver = (TT_Driver)ttdriver;
-
- driver->interpreter_version = TT_INTERPRETER_VERSION_35;
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- driver->interpreter_version = TT_INTERPRETER_VERSION_38;
-#endif
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- driver->interpreter_version = TT_INTERPRETER_VERSION_40;
-#endif
-
-#else /* !TT_USE_BYTECODE_INTERPRETER */
-
- FT_UNUSED( ttdriver );
-
-#endif /* !TT_USE_BYTECODE_INTERPRETER */
-
- return FT_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_driver_done */
- /* */
- /* <Description> */
- /* Finalize a given TrueType driver. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target TrueType driver. */
- /* */
- FT_LOCAL_DEF( void )
- tt_driver_done( FT_Module ttdriver ) /* TT_Driver */
- {
- FT_UNUSED( ttdriver );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_slot_init */
- /* */
- /* <Description> */
- /* Initialize a new slot object. */
- /* */
- /* <InOut> */
- /* slot :: A handle to the slot object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_slot_init( FT_GlyphSlot slot )
- {
- return FT_GlyphLoader_CreateExtra( slot->internal->loader );
- }
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttobjs.h b/third_party/freetype/src/truetype/ttobjs.h
deleted file mode 100644
index 65929e5928..0000000000
--- a/third_party/freetype/src/truetype/ttobjs.h
+++ /dev/null
@@ -1,424 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttobjs.h */
-/* */
-/* Objects manager (specification). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef TTOBJS_H_
-#define TTOBJS_H_
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_OBJECTS_H
-#include FT_INTERNAL_TRUETYPE_TYPES_H
-
-
-FT_BEGIN_HEADER
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* TT_Driver */
- /* */
- /* <Description> */
- /* A handle to a TrueType driver object. */
- /* */
- typedef struct TT_DriverRec_* TT_Driver;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* TT_GlyphSlot */
- /* */
- /* <Description> */
- /* A handle to a TrueType glyph slot object. */
- /* */
- /* <Note> */
- /* This is a direct typedef of FT_GlyphSlot, as there is nothing */
- /* specific about the TrueType glyph slot. */
- /* */
- typedef FT_GlyphSlot TT_GlyphSlot;
-
-
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* TT_GraphicsState */
- /* */
- /* <Description> */
- /* The TrueType graphics state used during bytecode interpretation. */
- /* */
- typedef struct TT_GraphicsState_
- {
- FT_UShort rp0;
- FT_UShort rp1;
- FT_UShort rp2;
-
- FT_UnitVector dualVector;
- FT_UnitVector projVector;
- FT_UnitVector freeVector;
-
- FT_Long loop;
- FT_F26Dot6 minimum_distance;
- FT_Int round_state;
-
- FT_Bool auto_flip;
- FT_F26Dot6 control_value_cutin;
- FT_F26Dot6 single_width_cutin;
- FT_F26Dot6 single_width_value;
- FT_UShort delta_base;
- FT_UShort delta_shift;
-
- FT_Byte instruct_control;
- /* According to Greg Hitchcock from Microsoft, the `scan_control' */
- /* variable as documented in the TrueType specification is a 32-bit */
- /* integer; the high-word part holds the SCANTYPE value, the low-word */
- /* part the SCANCTRL value. We separate it into two fields. */
- FT_Bool scan_control;
- FT_Int scan_type;
-
- FT_UShort gep0;
- FT_UShort gep1;
- FT_UShort gep2;
-
- } TT_GraphicsState;
-
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- FT_LOCAL( void )
- tt_glyphzone_done( TT_GlyphZone zone );
-
- FT_LOCAL( FT_Error )
- tt_glyphzone_new( FT_Memory memory,
- FT_UShort maxPoints,
- FT_Short maxContours,
- TT_GlyphZone zone );
-
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
-
-
- /*************************************************************************/
- /* */
- /* EXECUTION SUBTABLES */
- /* */
- /* These sub-tables relate to instruction execution. */
- /* */
- /*************************************************************************/
-
-
-#define TT_MAX_CODE_RANGES 3
-
-
- /*************************************************************************/
- /* */
- /* There can only be 3 active code ranges at once: */
- /* - the Font Program */
- /* - the CVT Program */
- /* - a glyph's instructions set */
- /* */
- typedef enum TT_CodeRange_Tag_
- {
- tt_coderange_none = 0,
- tt_coderange_font,
- tt_coderange_cvt,
- tt_coderange_glyph
-
- } TT_CodeRange_Tag;
-
-
- typedef struct TT_CodeRange_
- {
- FT_Byte* base;
- FT_Long size;
-
- } TT_CodeRange;
-
- typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES];
-
-
- /*************************************************************************/
- /* */
- /* Defines a function/instruction definition record. */
- /* */
- typedef struct TT_DefRecord_
- {
- FT_Int range; /* in which code range is it located? */
- FT_Long start; /* where does it start? */
- FT_Long end; /* where does it end? */
- FT_UInt opc; /* function #, or instruction code */
- FT_Bool active; /* is it active? */
- FT_Bool inline_delta; /* is function that defines inline delta? */
- FT_ULong sph_fdef_flags; /* flags to identify special functions */
-
- } TT_DefRecord, *TT_DefArray;
-
-
- /*************************************************************************/
- /* */
- /* Subglyph transformation record. */
- /* */
- typedef struct TT_Transform_
- {
- FT_Fixed xx, xy; /* transformation matrix coefficients */
- FT_Fixed yx, yy;
- FT_F26Dot6 ox, oy; /* offsets */
-
- } TT_Transform;
-
-
- /*************************************************************************/
- /* */
- /* A note regarding non-squared pixels: */
- /* */
- /* (This text will probably go into some docs at some time; for now, it */
- /* is kept here to explain some definitions in the TT_Size_Metrics */
- /* record). */
- /* */
- /* The CVT is a one-dimensional array containing values that control */
- /* certain important characteristics in a font, like the height of all */
- /* capitals, all lowercase letter, default spacing or stem width/height. */
- /* */
- /* These values are found in FUnits in the font file, and must be scaled */
- /* to pixel coordinates before being used by the CVT and glyph programs. */
- /* Unfortunately, when using distinct x and y resolutions (or distinct x */
- /* and y pointsizes), there are two possible scalings. */
- /* */
- /* A first try was to implement a `lazy' scheme where all values were */
- /* scaled when first used. However, while some values are always used */
- /* in the same direction, some others are used under many different */
- /* circumstances and orientations. */
- /* */
- /* I have found a simpler way to do the same, and it even seems to work */
- /* in most of the cases: */
- /* */
- /* - All CVT values are scaled to the maximum ppem size. */
- /* */
- /* - When performing a read or write in the CVT, a ratio factor is used */
- /* to perform adequate scaling. Example: */
- /* */
- /* x_ppem = 14 */
- /* y_ppem = 10 */
- /* */
- /* We choose ppem = x_ppem = 14 as the CVT scaling size. All cvt */
- /* entries are scaled to it. */
- /* */
- /* x_ratio = 1.0 */
- /* y_ratio = y_ppem/ppem (< 1.0) */
- /* */
- /* We compute the current ratio like: */
- /* */
- /* - If projVector is horizontal, */
- /* ratio = x_ratio = 1.0 */
- /* */
- /* - if projVector is vertical, */
- /* ratio = y_ratio */
- /* */
- /* - else, */
- /* ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */
- /* */
- /* Reading a cvt value returns */
- /* ratio * cvt[index] */
- /* */
- /* Writing a cvt value in pixels: */
- /* cvt[index] / ratio */
- /* */
- /* The current ppem is simply */
- /* ratio * ppem */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* Metrics used by the TrueType size and context objects. */
- /* */
- typedef struct TT_Size_Metrics_
- {
- /* for non-square pixels */
- FT_Long x_ratio;
- FT_Long y_ratio;
-
- FT_UShort ppem; /* maximum ppem size */
- FT_Long ratio; /* current ratio */
- FT_Fixed scale;
-
- FT_F26Dot6 compensations[4]; /* device-specific compensations */
-
- FT_Bool valid;
-
- FT_Bool rotated; /* `is the glyph rotated?'-flag */
- FT_Bool stretched; /* `is the glyph stretched?'-flag */
-
- } TT_Size_Metrics;
-
-
- /*************************************************************************/
- /* */
- /* TrueType size class. */
- /* */
- typedef struct TT_SizeRec_
- {
- FT_SizeRec root;
-
- /* we have our own copy of metrics so that we can modify */
- /* it without affecting auto-hinting (when used) */
- FT_Size_Metrics metrics;
-
- TT_Size_Metrics ttmetrics;
-
- FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- FT_Long point_size; /* for the `MPS' bytecode instruction */
-
- FT_UInt num_function_defs; /* number of function definitions */
- FT_UInt max_function_defs;
- TT_DefArray function_defs; /* table of function definitions */
-
- FT_UInt num_instruction_defs; /* number of ins. definitions */
- FT_UInt max_instruction_defs;
- TT_DefArray instruction_defs; /* table of ins. definitions */
-
- FT_UInt max_func;
- FT_UInt max_ins;
-
- TT_CodeRangeTable codeRangeTable;
-
- TT_GraphicsState GS;
-
- FT_ULong cvt_size; /* the scaled control value table */
- FT_Long* cvt;
-
- FT_UShort storage_size; /* The storage area is now part of */
- FT_Long* storage; /* the instance */
-
- TT_GlyphZoneRec twilight; /* The instance's twilight zone */
-
- TT_ExecContext context;
-
- /* 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 */
-
- } TT_SizeRec;
-
-
- /*************************************************************************/
- /* */
- /* TrueType driver class. */
- /* */
- typedef struct TT_DriverRec_
- {
- FT_DriverRec root;
-
- TT_GlyphZoneRec zone; /* glyph loader points zone */
-
- FT_UInt interpreter_version;
-
- } TT_DriverRec;
-
-
- /* Note: All of the functions below (except tt_size_reset()) are used */
- /* as function pointers in a FT_Driver_ClassRec. Therefore their */
- /* parameters are of types FT_Face, FT_Size, etc., rather than TT_Face, */
- /* TT_Size, etc., so that the compiler can confirm that the types and */
- /* number of parameters are correct. In all cases the FT_xxx types are */
- /* cast to their TT_xxx counterparts inside the functions since FreeType */
- /* will always use the TT driver to create them. */
-
-
- /*************************************************************************/
- /* */
- /* Face functions */
- /* */
- FT_LOCAL( FT_Error )
- tt_face_init( FT_Stream stream,
- FT_Face ttface, /* TT_Face */
- FT_Int face_index,
- FT_Int num_params,
- FT_Parameter* params );
-
- FT_LOCAL( void )
- tt_face_done( FT_Face ttface ); /* TT_Face */
-
-
- /*************************************************************************/
- /* */
- /* Size functions */
- /* */
- FT_LOCAL( FT_Error )
- tt_size_init( FT_Size ttsize ); /* TT_Size */
-
- FT_LOCAL( void )
- tt_size_done( FT_Size ttsize ); /* TT_Size */
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- FT_LOCAL( FT_Error )
- tt_size_run_fpgm( TT_Size size,
- FT_Bool pedantic );
-
- FT_LOCAL( FT_Error )
- tt_size_run_prep( TT_Size size,
- FT_Bool pedantic );
-
- FT_LOCAL( FT_Error )
- tt_size_ready_bytecode( TT_Size size,
- FT_Bool pedantic );
-
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
- FT_LOCAL( FT_Error )
- tt_size_reset( TT_Size size,
- FT_Bool only_height );
-
-
- /*************************************************************************/
- /* */
- /* Driver functions */
- /* */
- FT_LOCAL( FT_Error )
- tt_driver_init( FT_Module ttdriver ); /* TT_Driver */
-
- FT_LOCAL( void )
- tt_driver_done( FT_Module ttdriver ); /* TT_Driver */
-
-
- /*************************************************************************/
- /* */
- /* Slot functions */
- /* */
- FT_LOCAL( FT_Error )
- tt_slot_init( FT_GlyphSlot slot );
-
-
- /* auxiliary */
-#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
-
-
-FT_END_HEADER
-
-#endif /* TTOBJS_H_ */
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttpic.c b/third_party/freetype/src/truetype/ttpic.c
deleted file mode 100644
index 66bd7e1934..0000000000
--- a/third_party/freetype/src/truetype/ttpic.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttpic.c */
-/* */
-/* The FreeType position independent code services for truetype module. */
-/* */
-/* Copyright 2009-2017 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
-#include "ttpic.h"
-#include "tterrors.h"
-
-
-#ifdef FT_CONFIG_OPTION_PIC
-
- /* forward declaration of PIC init functions from ttdriver.c */
- FT_Error
- FT_Create_Class_tt_services( FT_Library library,
- FT_ServiceDescRec** output_class );
- void
- FT_Destroy_Class_tt_services( FT_Library library,
- FT_ServiceDescRec* clazz );
- void
- FT_Init_Class_tt_service_gx_multi_masters(
- FT_Service_MultiMastersRec* sv_mm );
- void
- FT_Init_Class_tt_service_truetype_glyf(
- FT_Service_TTGlyfRec* sv_ttglyf );
-
-
- void
- tt_driver_class_pic_free( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
-
-
- if ( pic_container->truetype )
- {
- TTModulePIC* container = (TTModulePIC*)pic_container->truetype;
-
-
- if ( container->tt_services )
- FT_Destroy_Class_tt_services( library, container->tt_services );
- container->tt_services = NULL;
- FT_FREE( container );
- pic_container->truetype = NULL;
- }
- }
-
-
- FT_Error
- tt_driver_class_pic_init( FT_Library library )
- {
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
- TTModulePIC* container = NULL;
- FT_Memory memory = library->memory;
-
-
- /* allocate pointer, clear and set global container pointer */
- if ( FT_ALLOC( container, sizeof ( *container ) ) )
- return error;
- FT_MEM_SET( container, 0, sizeof ( *container ) );
- pic_container->truetype = container;
-
- /* initialize pointer table - this is how the module usually */
- /* expects this data */
- error = FT_Create_Class_tt_services( library,
- &container->tt_services );
- if ( error )
- goto Exit;
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- FT_Init_Class_tt_service_gx_multi_masters(
- &container->tt_service_gx_multi_masters );
-#endif
- FT_Init_Class_tt_service_truetype_glyf(
- &container->tt_service_truetype_glyf );
-
- Exit:
- if ( error )
- tt_driver_class_pic_free( library );
- return error;
- }
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttpic.h b/third_party/freetype/src/truetype/ttpic.h
deleted file mode 100644
index 1410cd73c3..0000000000
--- a/third_party/freetype/src/truetype/ttpic.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttpic.h */
-/* */
-/* The FreeType position independent code services for truetype module. */
-/* */
-/* Copyright 2009-2017 by */
-/* Oran Agra and Mickey Gabel. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef TTPIC_H_
-#define TTPIC_H_
-
-
-#include FT_INTERNAL_PIC_H
-
-
-#ifndef FT_CONFIG_OPTION_PIC
-
-#define TT_SERVICES_GET tt_services
-#define TT_SERVICE_GX_MULTI_MASTERS_GET tt_service_gx_multi_masters
-#define TT_SERVICE_METRICS_VARIATIONS_GET tt_service_metrics_variations
-#define TT_SERVICE_TRUETYPE_GLYF_GET tt_service_truetype_glyf
-#define TT_SERVICE_PROPERTIES_GET tt_service_properties
-
-#else /* FT_CONFIG_OPTION_PIC */
-
-#include FT_MULTIPLE_MASTERS_H
-#include FT_SERVICE_MULTIPLE_MASTERS_H
-#include FT_SERVICE_METRICS_VARIATIONS_H
-#include FT_SERVICE_TRUETYPE_GLYF_H
-#include FT_SERVICE_PROPERTIES_H
-
-
-FT_BEGIN_HEADER
-
- typedef struct TTModulePIC_
- {
- FT_ServiceDescRec* tt_services;
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- FT_Service_MultiMastersRec tt_service_gx_multi_masters;
- FT_Service_MetricsVariationsRec tt_service_metrics_variations;
-#endif
- FT_Service_TTGlyfRec tt_service_truetype_glyf;
- FT_Service_PropertiesRec tt_service_properties;
-
- } TTModulePIC;
-
-
-#define GET_PIC( lib ) \
- ( (TTModulePIC*)((lib)->pic_container.truetype) )
-#define TT_SERVICES_GET \
- ( GET_PIC( library )->tt_services )
-#define TT_SERVICE_METRICS_VARIATIONS_GET \
- ( GET_PIC( library )->tt_service_metrics_variations )
-#define TT_SERVICE_GX_MULTI_MASTERS_GET \
- ( GET_PIC( library )->tt_service_gx_multi_masters )
-#define TT_SERVICE_TRUETYPE_GLYF_GET \
- ( GET_PIC( library )->tt_service_truetype_glyf )
-#define TT_SERVICE_PROPERTIES_GET \
- ( GET_PIC( library )->tt_service_properties )
-
-
- /* see ttpic.c for the implementation */
- void
- tt_driver_class_pic_free( FT_Library library );
-
- FT_Error
- tt_driver_class_pic_init( FT_Library library );
-
-FT_END_HEADER
-
-#endif /* FT_CONFIG_OPTION_PIC */
-
- /* */
-
-#endif /* TTPIC_H_ */
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttpload.c b/third_party/freetype/src/truetype/ttpload.c
deleted file mode 100644
index 70ac15da4a..0000000000
--- a/third_party/freetype/src/truetype/ttpload.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttpload.c */
-/* */
-/* TrueType-specific tables loader (body). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_OBJECTS_H
-#include FT_INTERNAL_STREAM_H
-#include FT_TRUETYPE_TAGS_H
-
-#include "ttpload.h"
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#include "ttgxvar.h"
-#endif
-
-#include "tterrors.h"
-
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_ttpload
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_loca */
- /* */
- /* <Description> */
- /* Load the locations table. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* stream :: The input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_loca( TT_Face face,
- FT_Stream stream )
- {
- FT_Error error;
- FT_ULong table_len;
- FT_Int shift;
-
-
- /* we need the size of the `glyf' table for malformed `loca' tables */
- error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
-
- /* it is possible that a font doesn't have a glyf table at all */
- /* or its size is zero */
- if ( FT_ERR_EQ( error, Table_Missing ) )
- {
- face->glyf_len = 0;
- face->glyf_offset = 0;
- }
- else if ( error )
- goto Exit;
- else
- {
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- if ( face->root.internal->incremental_interface )
- face->glyf_offset = 0;
- else
-#endif
- face->glyf_offset = FT_STREAM_POS();
- }
-
- FT_TRACE2(( "Locations " ));
- error = face->goto_table( face, TTAG_loca, stream, &table_len );
- if ( error )
- {
- error = FT_THROW( Locations_Missing );
- goto Exit;
- }
-
- if ( face->header.Index_To_Loc_Format != 0 )
- {
- shift = 2;
-
- if ( table_len >= 0x40000L )
- {
- FT_TRACE2(( "table too large\n" ));
- table_len = 0x3FFFFL;
- }
- face->num_locations = table_len >> shift;
- }
- else
- {
- shift = 1;
-
- if ( table_len >= 0x20000L )
- {
- FT_TRACE2(( "table too large\n" ));
- table_len = 0x1FFFFL;
- }
- face->num_locations = table_len >> shift;
- }
-
- if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
- {
- FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
- face->num_locations - 1, face->root.num_glyphs ));
-
- /* we only handle the case where `maxp' gives a larger value */
- if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
- {
- FT_ULong new_loca_len =
- ( (FT_ULong)face->root.num_glyphs + 1 ) << shift;
-
- TT_Table entry = face->dir_tables;
- TT_Table limit = entry + face->num_tables;
-
- FT_Long pos = (FT_Long)FT_STREAM_POS();
- FT_Long dist = 0x7FFFFFFFL;
- FT_Bool found = 0;
-
-
- /* compute the distance to next table in font file */
- for ( ; entry < limit; entry++ )
- {
- FT_Long diff = (FT_Long)entry->Offset - pos;
-
-
- if ( diff > 0 && diff < dist )
- {
- dist = diff;
- found = 1;
- }
- }
-
- if ( !found )
- {
- /* `loca' is the last table */
- dist = (FT_Long)stream->size - pos;
- }
-
- if ( new_loca_len <= (FT_ULong)dist )
- {
- face->num_locations = (FT_ULong)face->root.num_glyphs + 1;
- table_len = new_loca_len;
-
- FT_TRACE2(( "adjusting num_locations to %d\n",
- face->num_locations ));
- }
- else
- {
- face->root.num_glyphs = face->num_locations
- ? (FT_Long)face->num_locations - 1 : 0;
-
- FT_TRACE2(( "adjusting num_glyphs to %d\n",
- face->root.num_glyphs ));
- }
- }
- }
-
- /*
- * Extract the frame. We don't need to decompress it since
- * we are able to parse it directly.
- */
- if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
- goto Exit;
-
- FT_TRACE2(( "loaded\n" ));
-
- Exit:
- return error;
- }
-
-
- FT_LOCAL_DEF( FT_ULong )
- tt_face_get_location( TT_Face face,
- FT_UInt gindex,
- FT_UInt *asize )
- {
- FT_ULong pos1, pos2;
- FT_Byte* p;
- FT_Byte* p_limit;
-
-
- pos1 = pos2 = 0;
-
- if ( gindex < face->num_locations )
- {
- if ( face->header.Index_To_Loc_Format != 0 )
- {
- p = face->glyph_locations + gindex * 4;
- p_limit = face->glyph_locations + face->num_locations * 4;
-
- pos1 = FT_NEXT_ULONG( p );
- pos2 = pos1;
-
- if ( p + 4 <= p_limit )
- pos2 = FT_NEXT_ULONG( p );
- }
- else
- {
- p = face->glyph_locations + gindex * 2;
- p_limit = face->glyph_locations + face->num_locations * 2;
-
- pos1 = FT_NEXT_USHORT( p );
- pos2 = pos1;
-
- if ( p + 2 <= p_limit )
- pos2 = FT_NEXT_USHORT( p );
-
- pos1 <<= 1;
- pos2 <<= 1;
- }
- }
-
- /* Check broken location data. */
- if ( pos1 > face->glyf_len )
- {
- FT_TRACE1(( "tt_face_get_location:"
- " too large offset (0x%08lx) found for glyph index %ld,\n"
- " "
- " exceeding the end of `glyf' table (0x%08lx)\n",
- pos1, gindex, face->glyf_len ));
- *asize = 0;
- return 0;
- }
-
- if ( pos2 > face->glyf_len )
- {
- /* We try to sanitize the last `loca' entry. */
- if ( gindex == face->num_locations - 1 )
- {
- FT_TRACE1(( "tt_face_get_location:"
- " too large offset (0x%08lx) found for glyph index %ld,\n"
- " "
- " truncating at the end of `glyf' table (0x%08lx)\n",
- pos2, gindex + 1, face->glyf_len ));
- pos2 = face->glyf_len;
- }
- else
- {
- FT_TRACE1(( "tt_face_get_location:"
- " too large offset (0x%08lx) found for glyph index %ld,\n"
- " "
- " exceeding the end of `glyf' table (0x%08lx)\n",
- pos2, gindex + 1, face->glyf_len ));
- *asize = 0;
- return 0;
- }
- }
-
- /* The `loca' table must be ordered; it refers to the length of */
- /* an entry as the difference between the current and the next */
- /* position. However, there do exist (malformed) fonts which */
- /* don't obey this rule, so we are only able to provide an */
- /* upper bound for the size. */
- /* */
- /* We get (intentionally) a wrong, non-zero result in case the */
- /* `glyf' table is missing. */
- if ( pos2 >= pos1 )
- *asize = (FT_UInt)( pos2 - pos1 );
- else
- *asize = (FT_UInt)( face->glyf_len - pos1 );
-
- return pos1;
- }
-
-
- FT_LOCAL_DEF( void )
- tt_face_done_loca( TT_Face face )
- {
- FT_Stream stream = face->root.stream;
-
-
- FT_FRAME_RELEASE( face->glyph_locations );
- face->num_locations = 0;
- }
-
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_cvt */
- /* */
- /* <Description> */
- /* Load the control value table into a face object. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_cvt( TT_Face face,
- FT_Stream stream )
- {
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_ULong table_len;
-
-
- FT_TRACE2(( "CVT " ));
-
- error = face->goto_table( face, TTAG_cvt, stream, &table_len );
- if ( error )
- {
- FT_TRACE2(( "is missing\n" ));
-
- face->cvt_size = 0;
- face->cvt = NULL;
- error = FT_Err_Ok;
-
- goto Exit;
- }
-
- face->cvt_size = table_len / 2;
-
- if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
- goto Exit;
-
- if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
- goto Exit;
-
- {
- FT_Short* cur = face->cvt;
- FT_Short* limit = cur + face->cvt_size;
-
-
- for ( ; cur < limit; cur++ )
- *cur = FT_GET_SHORT();
- }
-
- FT_FRAME_EXIT();
- FT_TRACE2(( "loaded\n" ));
-
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( face->doblend )
- error = tt_face_vary_cvt( face, stream );
-#endif
-
- Exit:
- return error;
-
-#else /* !TT_USE_BYTECODE_INTERPRETER */
-
- FT_UNUSED( face );
- FT_UNUSED( stream );
-
- return FT_Err_Ok;
-
-#endif
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_fpgm */
- /* */
- /* <Description> */
- /* Load the font program. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_fpgm( TT_Face face,
- FT_Stream stream )
- {
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- FT_Error error;
- FT_ULong table_len;
-
-
- FT_TRACE2(( "Font program " ));
-
- /* The font program is optional */
- error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
- if ( error )
- {
- face->font_program = NULL;
- face->font_program_size = 0;
- error = FT_Err_Ok;
-
- FT_TRACE2(( "is missing\n" ));
- }
- else
- {
- face->font_program_size = table_len;
- if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
- goto Exit;
-
- FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
- }
-
- Exit:
- return error;
-
-#else /* !TT_USE_BYTECODE_INTERPRETER */
-
- FT_UNUSED( face );
- FT_UNUSED( stream );
-
- return FT_Err_Ok;
-
-#endif
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_prep */
- /* */
- /* <Description> */
- /* Load the cvt program. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Input> */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_prep( TT_Face face,
- FT_Stream stream )
- {
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
- FT_Error error;
- FT_ULong table_len;
-
-
- FT_TRACE2(( "Prep program " ));
-
- error = face->goto_table( face, TTAG_prep, stream, &table_len );
- if ( error )
- {
- face->cvt_program = NULL;
- face->cvt_program_size = 0;
- error = FT_Err_Ok;
-
- FT_TRACE2(( "is missing\n" ));
- }
- else
- {
- face->cvt_program_size = table_len;
- if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
- goto Exit;
-
- FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
- }
-
- Exit:
- return error;
-
-#else /* !TT_USE_BYTECODE_INTERPRETER */
-
- FT_UNUSED( face );
- FT_UNUSED( stream );
-
- return FT_Err_Ok;
-
-#endif
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_load_hdmx */
- /* */
- /* <Description> */
- /* Load the `hdmx' table into the face object. */
- /* */
- /* <Input> */
- /* face :: A handle to the target face object. */
- /* */
- /* stream :: A handle to the input stream. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
-
- FT_LOCAL_DEF( FT_Error )
- tt_face_load_hdmx( TT_Face face,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_UInt nn, num_records;
- FT_ULong table_size, record_size;
- FT_Byte* p;
- FT_Byte* limit;
-
-
- /* this table is optional */
- error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
- if ( error || table_size < 8 )
- return FT_Err_Ok;
-
- if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
- goto Exit;
-
- p = face->hdmx_table;
- limit = p + table_size;
-
- /* Given that `hdmx' tables are losing its importance (for example, */
- /* variation fonts introduced in OpenType 1.8 must not have this */
- /* table) we no longer test for a correct `version' field. */
- p += 2;
- num_records = FT_NEXT_USHORT( p );
- record_size = FT_NEXT_ULONG( p );
-
- /* The maximum number of bytes in an hdmx device record is the */
- /* maximum number of glyphs + 2; this is 0xFFFF + 2, thus */
- /* explaining why `record_size' is a long (which we read as */
- /* unsigned long for convenience). In practice, two bytes are */
- /* sufficient to hold the size value. */
- /* */
- /* There are at least two fonts, HANNOM-A and HANNOM-B version */
- /* 2.0 (2005), which get this wrong: The upper two bytes of */
- /* the size value are set to 0xFF instead of 0x00. We catch */
- /* and fix this. */
-
- if ( record_size >= 0xFFFF0000UL )
- record_size &= 0xFFFFU;
-
- /* The limit for `num_records' is a heuristic value. */
- if ( num_records > 255 ||
- ( num_records > 0 &&
- ( record_size > 0x10001L ||
- record_size < 4 ) ) )
- {
- error = FT_THROW( Invalid_File_Format );
- goto Fail;
- }
-
- if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
- goto Fail;
-
- for ( nn = 0; nn < num_records; nn++ )
- {
- if ( p + record_size > limit )
- break;
-
- face->hdmx_record_sizes[nn] = p[0];
- p += record_size;
- }
-
- face->hdmx_record_count = nn;
- face->hdmx_table_size = table_size;
- face->hdmx_record_size = record_size;
-
- Exit:
- return error;
-
- Fail:
- FT_FRAME_RELEASE( face->hdmx_table );
- face->hdmx_table_size = 0;
- goto Exit;
- }
-
-
- FT_LOCAL_DEF( void )
- tt_face_free_hdmx( TT_Face face )
- {
- FT_Stream stream = face->root.stream;
- FT_Memory memory = stream->memory;
-
-
- FT_FREE( face->hdmx_record_sizes );
- FT_FRAME_RELEASE( face->hdmx_table );
- }
-
-
- /*************************************************************************/
- /* */
- /* Return the advance width table for a given pixel size if it is found */
- /* in the font's `hdmx' table (if any). */
- /* */
- FT_LOCAL_DEF( FT_Byte* )
- tt_face_get_device_metrics( TT_Face face,
- FT_UInt ppem,
- FT_UInt gindex )
- {
- FT_UInt nn;
- FT_Byte* result = NULL;
- FT_ULong record_size = face->hdmx_record_size;
- FT_Byte* record = face->hdmx_table + 8;
-
-
- for ( nn = 0; nn < face->hdmx_record_count; nn++ )
- if ( face->hdmx_record_sizes[nn] == ppem )
- {
- gindex += 2;
- if ( gindex < record_size )
- result = record + nn * record_size + gindex;
- break;
- }
-
- return result;
- }
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttpload.h b/third_party/freetype/src/truetype/ttpload.h
deleted file mode 100644
index 79079f345a..0000000000
--- a/third_party/freetype/src/truetype/ttpload.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttpload.h */
-/* */
-/* TrueType-specific tables loader (specification). */
-/* */
-/* Copyright 1996-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef TTPLOAD_H_
-#define TTPLOAD_H_
-
-
-#include <ft2build.h>
-#include FT_INTERNAL_TRUETYPE_TYPES_H
-
-
-FT_BEGIN_HEADER
-
-
- FT_LOCAL( FT_Error )
- tt_face_load_loca( TT_Face face,
- FT_Stream stream );
-
- FT_LOCAL( FT_ULong )
- tt_face_get_location( TT_Face face,
- FT_UInt gindex,
- FT_UInt *asize );
-
- FT_LOCAL( void )
- tt_face_done_loca( TT_Face face );
-
- FT_LOCAL( FT_Error )
- tt_face_load_cvt( TT_Face face,
- FT_Stream stream );
-
- FT_LOCAL( FT_Error )
- tt_face_load_fpgm( TT_Face face,
- FT_Stream stream );
-
-
- FT_LOCAL( FT_Error )
- tt_face_load_prep( TT_Face face,
- FT_Stream stream );
-
-
- FT_LOCAL( FT_Error )
- tt_face_load_hdmx( TT_Face face,
- FT_Stream stream );
-
-
- FT_LOCAL( void )
- tt_face_free_hdmx( TT_Face face );
-
-
- FT_LOCAL( FT_Byte* )
- tt_face_get_device_metrics( TT_Face face,
- FT_UInt ppem,
- FT_UInt gindex );
-
-FT_END_HEADER
-
-#endif /* TTPLOAD_H_ */
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttsubpix.c b/third_party/freetype/src/truetype/ttsubpix.c
deleted file mode 100644
index 5d803cde14..0000000000
--- a/third_party/freetype/src/truetype/ttsubpix.c
+++ /dev/null
@@ -1,1011 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttsubpix.c */
-/* */
-/* TrueType Subpixel Hinting. */
-/* */
-/* Copyright 2010-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-#include <ft2build.h>
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_CALC_H
-#include FT_INTERNAL_STREAM_H
-#include FT_INTERNAL_SFNT_H
-#include FT_TRUETYPE_TAGS_H
-#include FT_OUTLINE_H
-#include FT_TRUETYPE_DRIVER_H
-
-#include "ttsubpix.h"
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- /*************************************************************************/
- /* */
- /* These rules affect how the TT Interpreter does hinting, with the */
- /* goal of doing subpixel hinting by (in general) ignoring x moves. */
- /* Some of these rules are fixes that go above and beyond the */
- /* stated techniques in the MS whitepaper on Cleartype, due to */
- /* artifacts in many glyphs. So, these rules make some glyphs render */
- /* better than they do in the MS rasterizer. */
- /* */
- /* "" string or 0 int/char indicates to apply to all glyphs. */
- /* "-" used as dummy placeholders, but any non-matching string works. */
- /* */
- /* Some of this could arguably be implemented in fontconfig, however: */
- /* */
- /* - Fontconfig can't set things on a glyph-by-glyph basis. */
- /* - The tweaks that happen here are very low-level, from an average */
- /* user's point of view and are best implemented in the hinter. */
- /* */
- /* The goal is to make the subpixel hinting techniques as generalized */
- /* as possible across all fonts to prevent the need for extra rules such */
- /* as these. */
- /* */
- /* The rule structure is designed so that entirely new rules can easily */
- /* be added when a new compatibility feature is discovered. */
- /* */
- /* The rule structures could also use some enhancement to handle ranges. */
- /* */
- /* ****************** WORK IN PROGRESS ******************* */
- /* */
-
- /* These are `classes' of fonts that can be grouped together and used in */
- /* rules below. A blank entry "" is required at the end of these! */
-#define FAMILY_CLASS_RULES_SIZE 7
-
- static const SPH_Font_Class FAMILY_CLASS_Rules
- [FAMILY_CLASS_RULES_SIZE] =
- {
- { "MS Legacy Fonts",
- { "Aharoni",
- "Andale Mono",
- "Andalus",
- "Angsana New",
- "AngsanaUPC",
- "Arabic Transparent",
- "Arial Black",
- "Arial Narrow",
- "Arial Unicode MS",
- "Arial",
- "Batang",
- "Browallia New",
- "BrowalliaUPC",
- "Comic Sans MS",
- "Cordia New",
- "CordiaUPC",
- "Courier New",
- "DFKai-SB",
- "David Transparent",
- "David",
- "DilleniaUPC",
- "Estrangelo Edessa",
- "EucrosiaUPC",
- "FangSong_GB2312",
- "Fixed Miriam Transparent",
- "FrankRuehl",
- "Franklin Gothic Medium",
- "FreesiaUPC",
- "Garamond",
- "Gautami",
- "Georgia",
- "Gulim",
- "Impact",
- "IrisUPC",
- "JasmineUPC",
- "KaiTi_GB2312",
- "KodchiangUPC",
- "Latha",
- "Levenim MT",
- "LilyUPC",
- "Lucida Console",
- "Lucida Sans Unicode",
- "MS Gothic",
- "MS Mincho",
- "MV Boli",
- "Mangal",
- "Marlett",
- "Microsoft Sans Serif",
- "Mingliu",
- "Miriam Fixed",
- "Miriam Transparent",
- "Miriam",
- "Narkisim",
- "Palatino Linotype",
- "Raavi",
- "Rod Transparent",
- "Rod",
- "Shruti",
- "SimHei",
- "Simplified Arabic Fixed",
- "Simplified Arabic",
- "Simsun",
- "Sylfaen",
- "Symbol",
- "Tahoma",
- "Times New Roman",
- "Traditional Arabic",
- "Trebuchet MS",
- "Tunga",
- "Verdana",
- "Webdings",
- "Wingdings",
- "",
- },
- },
- { "Core MS Legacy Fonts",
- { "Arial Black",
- "Arial Narrow",
- "Arial Unicode MS",
- "Arial",
- "Comic Sans MS",
- "Courier New",
- "Garamond",
- "Georgia",
- "Impact",
- "Lucida Console",
- "Lucida Sans Unicode",
- "Microsoft Sans Serif",
- "Palatino Linotype",
- "Tahoma",
- "Times New Roman",
- "Trebuchet MS",
- "Verdana",
- "",
- },
- },
- { "Apple Legacy Fonts",
- { "Geneva",
- "Times",
- "Monaco",
- "Century",
- "Chalkboard",
- "Lobster",
- "Century Gothic",
- "Optima",
- "Lucida Grande",
- "Gill Sans",
- "Baskerville",
- "Helvetica",
- "Helvetica Neue",
- "",
- },
- },
- { "Legacy Sans Fonts",
- { "Andale Mono",
- "Arial Unicode MS",
- "Arial",
- "Century Gothic",
- "Comic Sans MS",
- "Franklin Gothic Medium",
- "Geneva",
- "Lucida Console",
- "Lucida Grande",
- "Lucida Sans Unicode",
- "Lucida Sans Typewriter",
- "Microsoft Sans Serif",
- "Monaco",
- "Tahoma",
- "Trebuchet MS",
- "Verdana",
- "",
- },
- },
-
- { "Misc Legacy Fonts",
- { "Dark Courier", "", }, },
- { "Verdana Clones",
- { "DejaVu Sans",
- "Bitstream Vera Sans", "", }, },
- { "Verdana and Clones",
- { "DejaVu Sans",
- "Bitstream Vera Sans",
- "Verdana", "", }, },
- };
-
-
- /* Define this to force natural (i.e. not bitmap-compatible) widths. */
- /* The default leans strongly towards natural widths except for a few */
- /* legacy fonts where a selective combination produces nicer results. */
-/* #define FORCE_NATURAL_WIDTHS */
-
-
- /* Define `classes' of styles that can be grouped together and used in */
- /* rules below. A blank entry "" is required at the end of these! */
-#define STYLE_CLASS_RULES_SIZE 5
-
- static const SPH_Font_Class STYLE_CLASS_Rules
- [STYLE_CLASS_RULES_SIZE] =
- {
- { "Regular Class",
- { "Regular",
- "Book",
- "Medium",
- "Roman",
- "Normal",
- "",
- },
- },
- { "Regular/Italic Class",
- { "Regular",
- "Book",
- "Medium",
- "Italic",
- "Oblique",
- "Roman",
- "Normal",
- "",
- },
- },
- { "Bold/BoldItalic Class",
- { "Bold",
- "Bold Italic",
- "Black",
- "",
- },
- },
- { "Bold/Italic/BoldItalic Class",
- { "Bold",
- "Bold Italic",
- "Black",
- "Italic",
- "Oblique",
- "",
- },
- },
- { "Regular/Bold Class",
- { "Regular",
- "Book",
- "Medium",
- "Normal",
- "Roman",
- "Bold",
- "Black",
- "",
- },
- },
- };
-
-
- /* Force special legacy fixes for fonts. */
-#define COMPATIBILITY_MODE_RULES_SIZE 1
-
- static const SPH_TweakRule COMPATIBILITY_MODE_Rules
- [COMPATIBILITY_MODE_RULES_SIZE] =
- {
- { "Verdana Clones", 0, "", 0 },
- };
-
-
- /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting. */
-#define PIXEL_HINTING_RULES_SIZE 2
-
- static const SPH_TweakRule PIXEL_HINTING_Rules
- [PIXEL_HINTING_RULES_SIZE] =
- {
- /* these characters are almost always safe */
- { "Courier New", 12, "Italic", 'z' },
- { "Courier New", 11, "Italic", 'z' },
- };
-
-
- /* Subpixel hinting ignores SHPIX rules on X. Force SHPIX for these. */
-#define DO_SHPIX_RULES_SIZE 1
-
- static const SPH_TweakRule DO_SHPIX_Rules
- [DO_SHPIX_RULES_SIZE] =
- {
- { "-", 0, "", 0 },
- };
-
-
- /* Skip Y moves that start with a point that is not on a Y pixel */
- /* boundary and don't move that point to a Y pixel boundary. */
-#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 4
-
- static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules
- [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] =
- {
- /* fix vwxyz thinness*/
- { "Consolas", 0, "", 0 },
- /* Fix thin middle stems */
- { "Core MS Legacy Fonts", 0, "Regular", 0 },
- /* Cyrillic small letter I */
- { "Legacy Sans Fonts", 0, "", 0 },
- /* Fix artifacts with some Regular & Bold */
- { "Verdana Clones", 0, "", 0 },
- };
-
-
-#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1
-
- static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions
- [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
- {
- /* Fixes < and > */
- { "Courier New", 0, "Regular", 0 },
- };
-
-
- /* Skip Y moves that start with a point that is not on a Y pixel */
- /* boundary and don't move that point to a Y pixel boundary. */
-#define SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE 2
-
- static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules
- [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] =
- {
- /* Maintain thickness of diagonal in 'N' */
- { "Times New Roman", 0, "Regular/Bold Class", 'N' },
- { "Georgia", 0, "Regular/Bold Class", 'N' },
- };
-
-
- /* Skip Y moves that move a point off a Y pixel boundary. */
-#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE 1
-
- static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules
- [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] =
- {
- { "-", 0, "", 0 },
- };
-
-
-#define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1
-
- static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions
- [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
- {
- { "-", 0, "", 0 },
- };
-
-
- /* Round moves that don't move a point to a Y pixel boundary. */
-#define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE 2
-
- static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules
- [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] =
- {
- /* Droid font instructions don't snap Y to pixels */
- { "Droid Sans", 0, "Regular/Italic Class", 0 },
- { "Droid Sans Mono", 0, "", 0 },
- };
-
-
-#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1
-
- static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions
- [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
- {
- { "-", 0, "", 0 },
- };
-
-
- /* Allow a Direct_Move along X freedom vector if matched. */
-#define ALLOW_X_DMOVE_RULES_SIZE 1
-
- static const SPH_TweakRule ALLOW_X_DMOVE_Rules
- [ALLOW_X_DMOVE_RULES_SIZE] =
- {
- /* Fixes vanishing diagonal in 4 */
- { "Verdana", 0, "Regular", '4' },
- };
-
-
- /* Return MS rasterizer version 35 if matched. */
-#define RASTERIZER_35_RULES_SIZE 8
-
- static const SPH_TweakRule RASTERIZER_35_Rules
- [RASTERIZER_35_RULES_SIZE] =
- {
- /* This seems to be the only way to make these look good */
- { "Times New Roman", 0, "Regular", 'i' },
- { "Times New Roman", 0, "Regular", 'j' },
- { "Times New Roman", 0, "Regular", 'm' },
- { "Times New Roman", 0, "Regular", 'r' },
- { "Times New Roman", 0, "Regular", 'a' },
- { "Times New Roman", 0, "Regular", 'n' },
- { "Times New Roman", 0, "Regular", 'p' },
- { "Times", 0, "", 0 },
- };
-
-
- /* Don't round to the subpixel grid. Round to pixel grid. */
-#define NORMAL_ROUND_RULES_SIZE 1
-
- static const SPH_TweakRule NORMAL_ROUND_Rules
- [NORMAL_ROUND_RULES_SIZE] =
- {
- /* Fix serif thickness for certain ppems */
- /* Can probably be generalized somehow */
- { "Courier New", 0, "", 0 },
- };
-
-
- /* Skip IUP instructions if matched. */
-#define SKIP_IUP_RULES_SIZE 1
-
- static const SPH_TweakRule SKIP_IUP_Rules
- [SKIP_IUP_RULES_SIZE] =
- {
- { "Arial", 13, "Regular", 'a' },
- };
-
-
- /* Skip MIAP Twilight hack if matched. */
-#define MIAP_HACK_RULES_SIZE 1
-
- static const SPH_TweakRule MIAP_HACK_Rules
- [MIAP_HACK_RULES_SIZE] =
- {
- { "Geneva", 12, "", 0 },
- };
-
-
- /* Skip DELTAP instructions if matched. */
-#define ALWAYS_SKIP_DELTAP_RULES_SIZE 23
-
- static const SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules
- [ALWAYS_SKIP_DELTAP_RULES_SIZE] =
- {
- { "Georgia", 0, "Regular", 'k' },
- /* fix various problems with e in different versions */
- { "Trebuchet MS", 14, "Regular", 'e' },
- { "Trebuchet MS", 13, "Regular", 'e' },
- { "Trebuchet MS", 15, "Regular", 'e' },
- { "Trebuchet MS", 0, "Italic", 'v' },
- { "Trebuchet MS", 0, "Italic", 'w' },
- { "Trebuchet MS", 0, "Regular", 'Y' },
- { "Arial", 11, "Regular", 's' },
- /* prevent problems with '3' and others */
- { "Verdana", 10, "Regular", 0 },
- { "Verdana", 9, "Regular", 0 },
- /* Cyrillic small letter short I */
- { "Legacy Sans Fonts", 0, "", 0x438 },
- { "Legacy Sans Fonts", 0, "", 0x439 },
- { "Arial", 10, "Regular", '6' },
- { "Arial", 0, "Bold/BoldItalic Class", 'a' },
- /* Make horizontal stems consistent with the rest */
- { "Arial", 24, "Bold", 'a' },
- { "Arial", 25, "Bold", 'a' },
- { "Arial", 24, "Bold", 's' },
- { "Arial", 25, "Bold", 's' },
- { "Arial", 34, "Bold", 's' },
- { "Arial", 35, "Bold", 's' },
- { "Arial", 36, "Bold", 's' },
- { "Arial", 25, "Regular", 's' },
- { "Arial", 26, "Regular", 's' },
- };
-
-
- /* Always do DELTAP instructions if matched. */
-#define ALWAYS_DO_DELTAP_RULES_SIZE 1
-
- static const SPH_TweakRule ALWAYS_DO_DELTAP_Rules
- [ALWAYS_DO_DELTAP_RULES_SIZE] =
- {
- { "-", 0, "", 0 },
- };
-
-
- /* Don't allow ALIGNRP after IUP. */
-#define NO_ALIGNRP_AFTER_IUP_RULES_SIZE 1
-
- static const SPH_TweakRule NO_ALIGNRP_AFTER_IUP_Rules
- [NO_ALIGNRP_AFTER_IUP_RULES_SIZE] =
- {
- /* Prevent creation of dents in outline */
- { "-", 0, "", 0 },
- };
-
-
- /* Don't allow DELTAP after IUP. */
-#define NO_DELTAP_AFTER_IUP_RULES_SIZE 1
-
- static const SPH_TweakRule NO_DELTAP_AFTER_IUP_Rules
- [NO_DELTAP_AFTER_IUP_RULES_SIZE] =
- {
- { "-", 0, "", 0 },
- };
-
-
- /* Don't allow CALL after IUP. */
-#define NO_CALL_AFTER_IUP_RULES_SIZE 1
-
- static const SPH_TweakRule NO_CALL_AFTER_IUP_Rules
- [NO_CALL_AFTER_IUP_RULES_SIZE] =
- {
- /* Prevent creation of dents in outline */
- { "-", 0, "", 0 },
- };
-
-
- /* De-embolden these glyphs slightly. */
-#define DEEMBOLDEN_RULES_SIZE 9
-
- static const SPH_TweakRule DEEMBOLDEN_Rules
- [DEEMBOLDEN_RULES_SIZE] =
- {
- { "Courier New", 0, "Bold", 'A' },
- { "Courier New", 0, "Bold", 'W' },
- { "Courier New", 0, "Bold", 'w' },
- { "Courier New", 0, "Bold", 'M' },
- { "Courier New", 0, "Bold", 'X' },
- { "Courier New", 0, "Bold", 'K' },
- { "Courier New", 0, "Bold", 'x' },
- { "Courier New", 0, "Bold", 'z' },
- { "Courier New", 0, "Bold", 'v' },
- };
-
-
- /* Embolden these glyphs slightly. */
-#define EMBOLDEN_RULES_SIZE 2
-
- static const SPH_TweakRule EMBOLDEN_Rules
- [EMBOLDEN_RULES_SIZE] =
- {
- { "Courier New", 0, "Regular", 0 },
- { "Courier New", 0, "Italic", 0 },
- };
-
-
- /* This is a CVT hack that makes thick horizontal stems on 2, 5, 7 */
- /* similar to Windows XP. */
-#define TIMES_NEW_ROMAN_HACK_RULES_SIZE 12
-
- static const SPH_TweakRule TIMES_NEW_ROMAN_HACK_Rules
- [TIMES_NEW_ROMAN_HACK_RULES_SIZE] =
- {
- { "Times New Roman", 16, "Italic", '2' },
- { "Times New Roman", 16, "Italic", '5' },
- { "Times New Roman", 16, "Italic", '7' },
- { "Times New Roman", 16, "Regular", '2' },
- { "Times New Roman", 16, "Regular", '5' },
- { "Times New Roman", 16, "Regular", '7' },
- { "Times New Roman", 17, "Italic", '2' },
- { "Times New Roman", 17, "Italic", '5' },
- { "Times New Roman", 17, "Italic", '7' },
- { "Times New Roman", 17, "Regular", '2' },
- { "Times New Roman", 17, "Regular", '5' },
- { "Times New Roman", 17, "Regular", '7' },
- };
-
-
- /* This fudges distance on 2 to get rid of the vanishing stem issue. */
- /* A real solution to this is certainly welcome. */
-#define COURIER_NEW_2_HACK_RULES_SIZE 15
-
- static const SPH_TweakRule COURIER_NEW_2_HACK_Rules
- [COURIER_NEW_2_HACK_RULES_SIZE] =
- {
- { "Courier New", 10, "Regular", '2' },
- { "Courier New", 11, "Regular", '2' },
- { "Courier New", 12, "Regular", '2' },
- { "Courier New", 13, "Regular", '2' },
- { "Courier New", 14, "Regular", '2' },
- { "Courier New", 15, "Regular", '2' },
- { "Courier New", 16, "Regular", '2' },
- { "Courier New", 17, "Regular", '2' },
- { "Courier New", 18, "Regular", '2' },
- { "Courier New", 19, "Regular", '2' },
- { "Courier New", 20, "Regular", '2' },
- { "Courier New", 21, "Regular", '2' },
- { "Courier New", 22, "Regular", '2' },
- { "Courier New", 23, "Regular", '2' },
- { "Courier New", 24, "Regular", '2' },
- };
-
-
-#ifndef FORCE_NATURAL_WIDTHS
-
- /* Use compatible widths with these glyphs. Compatible widths is always */
- /* on when doing B/W TrueType instructing, but is used selectively here, */
- /* typically on glyphs with 3 or more vertical stems. */
-#define COMPATIBLE_WIDTHS_RULES_SIZE 38
-
- static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules
- [COMPATIBLE_WIDTHS_RULES_SIZE] =
- {
- { "Arial Unicode MS", 12, "Regular Class", 'm' },
- { "Arial Unicode MS", 14, "Regular Class", 'm' },
- /* Cyrillic small letter sha */
- { "Arial", 10, "Regular Class", 0x448 },
- { "Arial", 11, "Regular Class", 'm' },
- { "Arial", 12, "Regular Class", 'm' },
- /* Cyrillic small letter sha */
- { "Arial", 12, "Regular Class", 0x448 },
- { "Arial", 13, "Regular Class", 0x448 },
- { "Arial", 14, "Regular Class", 'm' },
- /* Cyrillic small letter sha */
- { "Arial", 14, "Regular Class", 0x448 },
- { "Arial", 15, "Regular Class", 0x448 },
- { "Arial", 17, "Regular Class", 'm' },
- { "DejaVu Sans", 15, "Regular Class", 0 },
- { "Microsoft Sans Serif", 11, "Regular Class", 0 },
- { "Microsoft Sans Serif", 12, "Regular Class", 0 },
- { "Segoe UI", 11, "Regular Class", 0 },
- { "Monaco", 0, "Regular Class", 0 },
- { "Segoe UI", 12, "Regular Class", 'm' },
- { "Segoe UI", 14, "Regular Class", 'm' },
- { "Tahoma", 11, "Regular Class", 0 },
- { "Times New Roman", 16, "Regular Class", 'c' },
- { "Times New Roman", 16, "Regular Class", 'm' },
- { "Times New Roman", 16, "Regular Class", 'o' },
- { "Times New Roman", 16, "Regular Class", 'w' },
- { "Trebuchet MS", 11, "Regular Class", 0 },
- { "Trebuchet MS", 12, "Regular Class", 0 },
- { "Trebuchet MS", 14, "Regular Class", 0 },
- { "Trebuchet MS", 15, "Regular Class", 0 },
- { "Ubuntu", 12, "Regular Class", 'm' },
- /* Cyrillic small letter sha */
- { "Verdana", 10, "Regular Class", 0x448 },
- { "Verdana", 11, "Regular Class", 0x448 },
- { "Verdana and Clones", 12, "Regular Class", 'i' },
- { "Verdana and Clones", 12, "Regular Class", 'j' },
- { "Verdana and Clones", 12, "Regular Class", 'l' },
- { "Verdana and Clones", 12, "Regular Class", 'm' },
- { "Verdana and Clones", 13, "Regular Class", 'i' },
- { "Verdana and Clones", 13, "Regular Class", 'j' },
- { "Verdana and Clones", 13, "Regular Class", 'l' },
- { "Verdana and Clones", 14, "Regular Class", 'm' },
- };
-
-
- /* Scaling slightly in the x-direction prior to hinting results in */
- /* more visually pleasing glyphs in certain cases. */
- /* This sometimes needs to be coordinated with compatible width rules. */
- /* A value of 1000 corresponds to a scaled value of 1.0. */
-
-#define X_SCALING_RULES_SIZE 50
-
- static const SPH_ScaleRule X_SCALING_Rules[X_SCALING_RULES_SIZE] =
- {
- { "DejaVu Sans", 12, "Regular Class", 'm', 950 },
- { "Verdana and Clones", 12, "Regular Class", 'a', 1100 },
- { "Verdana and Clones", 13, "Regular Class", 'a', 1050 },
- { "Arial", 11, "Regular Class", 'm', 975 },
- { "Arial", 12, "Regular Class", 'm', 1050 },
- /* Cyrillic small letter el */
- { "Arial", 13, "Regular Class", 0x43B, 950 },
- { "Arial", 13, "Regular Class", 'o', 950 },
- { "Arial", 13, "Regular Class", 'e', 950 },
- { "Arial", 14, "Regular Class", 'm', 950 },
- /* Cyrillic small letter el */
- { "Arial", 15, "Regular Class", 0x43B, 925 },
- { "Bitstream Vera Sans", 10, "Regular/Italic Class", 0, 1100 },
- { "Bitstream Vera Sans", 12, "Regular/Italic Class", 0, 1050 },
- { "Bitstream Vera Sans", 16, "Regular Class", 0, 1050 },
- { "Bitstream Vera Sans", 9, "Regular/Italic Class", 0, 1050 },
- { "DejaVu Sans", 12, "Regular Class", 'l', 975 },
- { "DejaVu Sans", 12, "Regular Class", 'i', 975 },
- { "DejaVu Sans", 12, "Regular Class", 'j', 975 },
- { "DejaVu Sans", 13, "Regular Class", 'l', 950 },
- { "DejaVu Sans", 13, "Regular Class", 'i', 950 },
- { "DejaVu Sans", 13, "Regular Class", 'j', 950 },
- { "DejaVu Sans", 10, "Regular/Italic Class", 0, 1100 },
- { "DejaVu Sans", 12, "Regular/Italic Class", 0, 1050 },
- { "Georgia", 10, "", 0, 1050 },
- { "Georgia", 11, "", 0, 1100 },
- { "Georgia", 12, "", 0, 1025 },
- { "Georgia", 13, "", 0, 1050 },
- { "Georgia", 16, "", 0, 1050 },
- { "Georgia", 17, "", 0, 1030 },
- { "Liberation Sans", 12, "Regular Class", 'm', 1100 },
- { "Lucida Grande", 11, "Regular Class", 'm', 1100 },
- { "Microsoft Sans Serif", 11, "Regular Class", 'm', 950 },
- { "Microsoft Sans Serif", 12, "Regular Class", 'm', 1050 },
- { "Segoe UI", 12, "Regular Class", 'H', 1050 },
- { "Segoe UI", 12, "Regular Class", 'm', 1050 },
- { "Segoe UI", 14, "Regular Class", 'm', 1050 },
- { "Tahoma", 11, "Regular Class", 'i', 975 },
- { "Tahoma", 11, "Regular Class", 'l', 975 },
- { "Tahoma", 11, "Regular Class", 'j', 900 },
- { "Tahoma", 11, "Regular Class", 'm', 918 },
- { "Verdana", 10, "Regular/Italic Class", 0, 1100 },
- { "Verdana", 12, "Regular Class", 'm', 975 },
- { "Verdana", 12, "Regular/Italic Class", 0, 1050 },
- { "Verdana", 13, "Regular/Italic Class", 'i', 950 },
- { "Verdana", 13, "Regular/Italic Class", 'j', 950 },
- { "Verdana", 13, "Regular/Italic Class", 'l', 950 },
- { "Verdana", 16, "Regular Class", 0, 1050 },
- { "Verdana", 9, "Regular/Italic Class", 0, 1050 },
- { "Times New Roman", 16, "Regular Class", 'm', 918 },
- { "Trebuchet MS", 11, "Regular Class", 'm', 800 },
- { "Trebuchet MS", 12, "Regular Class", 'm', 800 },
- };
-
-#else
-
-#define COMPATIBLE_WIDTHS_RULES_SIZE 1
-
- static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules
- [COMPATIBLE_WIDTHS_RULES_SIZE] =
- {
- { "-", 0, "", 0 },
- };
-
-
-#define X_SCALING_RULES_SIZE 1
-
- static const SPH_ScaleRule X_SCALING_Rules
- [X_SCALING_RULES_SIZE] =
- {
- { "-", 0, "", 0, 1000 },
- };
-
-#endif /* FORCE_NATURAL_WIDTHS */
-
-
- static FT_Bool
- is_member_of_family_class( const FT_String* detected_font_name,
- const FT_String* rule_font_name )
- {
- FT_UInt i, j;
-
-
- /* Does font name match rule family? */
- if ( strcmp( detected_font_name, rule_font_name ) == 0 )
- return TRUE;
-
- /* Is font name a wildcard ""? */
- if ( strcmp( rule_font_name, "" ) == 0 )
- return TRUE;
-
- /* Is font name contained in a class list? */
- for ( i = 0; i < FAMILY_CLASS_RULES_SIZE; i++ )
- {
- if ( strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 )
- {
- for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ )
- {
- if ( strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 )
- continue;
- if ( strcmp( FAMILY_CLASS_Rules[i].member[j],
- detected_font_name ) == 0 )
- return TRUE;
- }
- }
- }
-
- return FALSE;
- }
-
-
- static FT_Bool
- is_member_of_style_class( const FT_String* detected_font_style,
- const FT_String* rule_font_style )
- {
- FT_UInt i, j;
-
-
- /* Does font style match rule style? */
- if ( strcmp( detected_font_style, rule_font_style ) == 0 )
- return TRUE;
-
- /* Is font style a wildcard ""? */
- if ( strcmp( rule_font_style, "" ) == 0 )
- return TRUE;
-
- /* Is font style contained in a class list? */
- for ( i = 0; i < STYLE_CLASS_RULES_SIZE; i++ )
- {
- if ( strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 )
- {
- for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ )
- {
- if ( strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 )
- continue;
- if ( strcmp( STYLE_CLASS_Rules[i].member[j],
- detected_font_style ) == 0 )
- return TRUE;
- }
- }
- }
-
- return FALSE;
- }
-
-
- FT_LOCAL_DEF( FT_Bool )
- sph_test_tweak( TT_Face face,
- const FT_String* family,
- FT_UInt ppem,
- const FT_String* style,
- FT_UInt glyph_index,
- const SPH_TweakRule* rule,
- FT_UInt num_rules )
- {
- FT_UInt i;
-
-
- /* rule checks may be able to be optimized further */
- for ( i = 0; i < num_rules; i++ )
- {
- if ( family &&
- ( is_member_of_family_class ( family, rule[i].family ) ) )
- if ( rule[i].ppem == 0 ||
- rule[i].ppem == ppem )
- if ( style &&
- is_member_of_style_class ( style, rule[i].style ) )
- if ( rule[i].glyph == 0 ||
- FT_Get_Char_Index( (FT_Face)face,
- rule[i].glyph ) == glyph_index )
- return TRUE;
- }
-
- return FALSE;
- }
-
-
- static FT_UInt
- scale_test_tweak( TT_Face face,
- const FT_String* family,
- FT_UInt ppem,
- const FT_String* style,
- FT_UInt glyph_index,
- const SPH_ScaleRule* rule,
- FT_UInt num_rules )
- {
- FT_UInt i;
-
-
- /* rule checks may be able to be optimized further */
- for ( i = 0; i < num_rules; i++ )
- {
- if ( family &&
- ( is_member_of_family_class ( family, rule[i].family ) ) )
- if ( rule[i].ppem == 0 ||
- rule[i].ppem == ppem )
- if ( style &&
- is_member_of_style_class( style, rule[i].style ) )
- if ( rule[i].glyph == 0 ||
- FT_Get_Char_Index( (FT_Face)face,
- rule[i].glyph ) == glyph_index )
- return rule[i].scale;
- }
-
- return 1000;
- }
-
-
- FT_LOCAL_DEF( FT_UInt )
- sph_test_tweak_x_scaling( TT_Face face,
- const FT_String* family,
- FT_UInt ppem,
- const FT_String* style,
- FT_UInt glyph_index )
- {
- return scale_test_tweak( face, family, ppem, style, glyph_index,
- X_SCALING_Rules, X_SCALING_RULES_SIZE );
- }
-
-
-#define TWEAK_RULES( x ) \
- if ( sph_test_tweak( face, family, ppem, style, glyph_index, \
- x##_Rules, x##_RULES_SIZE ) ) \
- loader->exec->sph_tweak_flags |= SPH_TWEAK_##x;
-
-#define TWEAK_RULES_EXCEPTIONS( x ) \
- if ( sph_test_tweak( face, family, ppem, style, glyph_index, \
- x##_Rules_Exceptions, x##_RULES_EXCEPTIONS_SIZE ) ) \
- loader->exec->sph_tweak_flags &= ~SPH_TWEAK_##x;
-
-
- FT_LOCAL_DEF( void )
- sph_set_tweaks( TT_Loader loader,
- FT_UInt glyph_index )
- {
- TT_Face face = loader->face;
- FT_String* family = face->root.family_name;
- FT_UInt ppem = loader->size->metrics.x_ppem;
- FT_String* style = face->root.style_name;
-
-
- /* don't apply rules if style isn't set */
- if ( !face->root.style_name )
- return;
-
-#ifdef SPH_DEBUG_MORE_VERBOSE
- printf( "%s,%d,%s,%c=%d ",
- family, ppem, style, glyph_index, glyph_index );
-#endif
-
- TWEAK_RULES( PIXEL_HINTING );
-
- if ( loader->exec->sph_tweak_flags & SPH_TWEAK_PIXEL_HINTING )
- {
- loader->exec->ignore_x_mode = FALSE;
- return;
- }
-
- TWEAK_RULES( ALLOW_X_DMOVE );
- TWEAK_RULES( ALWAYS_DO_DELTAP );
- TWEAK_RULES( ALWAYS_SKIP_DELTAP );
- TWEAK_RULES( DEEMBOLDEN );
- TWEAK_RULES( DO_SHPIX );
- TWEAK_RULES( EMBOLDEN );
- TWEAK_RULES( MIAP_HACK );
- TWEAK_RULES( NORMAL_ROUND );
- TWEAK_RULES( NO_ALIGNRP_AFTER_IUP );
- TWEAK_RULES( NO_CALL_AFTER_IUP );
- TWEAK_RULES( NO_DELTAP_AFTER_IUP );
- TWEAK_RULES( RASTERIZER_35 );
- TWEAK_RULES( SKIP_IUP );
-
- TWEAK_RULES( SKIP_OFFPIXEL_Y_MOVES );
- TWEAK_RULES_EXCEPTIONS( SKIP_OFFPIXEL_Y_MOVES );
-
- TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES_DELTAP );
-
- TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES );
- TWEAK_RULES_EXCEPTIONS( SKIP_NONPIXEL_Y_MOVES );
-
- TWEAK_RULES( ROUND_NONPIXEL_Y_MOVES );
- TWEAK_RULES_EXCEPTIONS( ROUND_NONPIXEL_Y_MOVES );
-
- if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
- {
- if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 )
- {
- loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
- loader->exec->size->cvt_ready = -1;
-
- tt_size_ready_bytecode(
- loader->exec->size,
- FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) );
- }
- else
- loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
- }
- else
- {
- if ( loader->exec->rasterizer_version !=
- SPH_OPTION_SET_RASTERIZER_VERSION )
- {
- loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
- loader->exec->size->cvt_ready = -1;
-
- tt_size_ready_bytecode(
- loader->exec->size,
- FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) );
- }
- else
- loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
- }
-
- if ( IS_HINTED( loader->load_flags ) )
- {
- TWEAK_RULES( TIMES_NEW_ROMAN_HACK );
- TWEAK_RULES( COURIER_NEW_2_HACK );
- }
-
- if ( sph_test_tweak( face, family, ppem, style, glyph_index,
- COMPATIBILITY_MODE_Rules, COMPATIBILITY_MODE_RULES_SIZE ) )
- loader->exec->face->sph_compatibility_mode = TRUE;
-
-
- if ( IS_HINTED( loader->load_flags ) )
- {
- if ( sph_test_tweak( face, family, ppem, style, glyph_index,
- COMPATIBLE_WIDTHS_Rules, COMPATIBLE_WIDTHS_RULES_SIZE ) )
- loader->exec->compatible_widths |= TRUE;
- }
- }
-
-#else /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- /* ANSI C doesn't like empty source files */
- typedef int _tt_subpix_dummy;
-
-#endif /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-
-/* END */
diff --git a/third_party/freetype/src/truetype/ttsubpix.h b/third_party/freetype/src/truetype/ttsubpix.h
deleted file mode 100644
index c68f97ff07..0000000000
--- a/third_party/freetype/src/truetype/ttsubpix.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/***************************************************************************/
-/* */
-/* ttsubpix.h */
-/* */
-/* TrueType Subpixel Hinting. */
-/* */
-/* Copyright 2010-2017 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#ifndef TTSUBPIX_H_
-#define TTSUBPIX_H_
-
-#include <ft2build.h>
-#include "ttobjs.h"
-#include "ttinterp.h"
-
-
-FT_BEGIN_HEADER
-
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- /*************************************************************************/
- /* */
- /* ID flags to identify special functions at FDEF and runtime. */
- /* */
- /* */
-#define SPH_FDEF_INLINE_DELTA_1 0x0000001
-#define SPH_FDEF_INLINE_DELTA_2 0x0000002
-#define SPH_FDEF_DIAGONAL_STROKE 0x0000004
-#define SPH_FDEF_VACUFORM_ROUND_1 0x0000008
-#define SPH_FDEF_TTFAUTOHINT_1 0x0000010
-#define SPH_FDEF_SPACING_1 0x0000020
-#define SPH_FDEF_SPACING_2 0x0000040
-#define SPH_FDEF_TYPEMAN_STROKES 0x0000080
-#define SPH_FDEF_TYPEMAN_DIAGENDCTRL 0x0000100
-
-
- /*************************************************************************/
- /* */
- /* Tweak flags that are set for each glyph by the below rules. */
- /* */
- /* */
-#define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001UL
-#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002UL
-#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004UL
-#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000008UL
-#define SPH_TWEAK_DEEMBOLDEN 0x0000010UL
-#define SPH_TWEAK_DO_SHPIX 0x0000020UL
-#define SPH_TWEAK_EMBOLDEN 0x0000040UL
-#define SPH_TWEAK_MIAP_HACK 0x0000080UL
-#define SPH_TWEAK_NORMAL_ROUND 0x0000100UL
-#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0000200UL
-#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0000400UL
-#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0000800UL
-#define SPH_TWEAK_PIXEL_HINTING 0x0001000UL
-#define SPH_TWEAK_RASTERIZER_35 0x0002000UL
-#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0004000UL
-#define SPH_TWEAK_SKIP_IUP 0x0008000UL
-#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0010000UL
-#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0020000UL
-#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0040000UL
-#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP 0x0080000UL
-
-
- FT_LOCAL( FT_Bool )
- sph_test_tweak( TT_Face face,
- const FT_String* family,
- FT_UInt ppem,
- const FT_String* style,
- FT_UInt glyph_index,
- const SPH_TweakRule* rule,
- FT_UInt num_rules );
-
- FT_LOCAL( FT_UInt )
- sph_test_tweak_x_scaling( TT_Face face,
- const FT_String* family,
- FT_UInt ppem,
- const FT_String* style,
- FT_UInt glyph_index );
-
- FT_LOCAL( void )
- sph_set_tweaks( TT_Loader loader,
- FT_UInt glyph_index );
-
-
- /* These macros are defined absent a method for setting them */
-#define SPH_OPTION_BITMAP_WIDTHS FALSE
-#define SPH_OPTION_SET_SUBPIXEL TRUE
-#define SPH_OPTION_SET_GRAYSCALE FALSE
-#define SPH_OPTION_SET_COMPATIBLE_WIDTHS FALSE
-#define SPH_OPTION_SET_RASTERIZER_VERSION 38
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-
-FT_END_HEADER
-
-#endif /* TTSUBPIX_H_ */
-
-
-/* END */