Begin 'preload' font driver (based on truetype)

This commit is contained in:
Anurag Thakur 2023-08-09 01:46:40 +05:30
parent 4769e58bbd
commit 3926f77efd
18 changed files with 19742 additions and 0 deletions

View File

@ -11,6 +11,7 @@
*/
FT_USE_MODULE( FT_Module_Class, autofit_module_class )
FT_USE_MODULE( FT_Driver_ClassRec, preload_driver_class )
FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class )
FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class )
FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class )

View File

@ -34,6 +34,12 @@
# This driver needs the `sfnt' module.
FONT_MODULES += truetype
# TrueType preload font driver.
#
# This driver needs the `sfnt' module.
FONT_MODULES += preload
# PostScript Type 1 font driver.
#
# This driver needs the `psaux', `pshinter', and `psnames' modules.

23
src/preload/module.mk Normal file
View File

@ -0,0 +1,23 @@
#
# FreeType 2 TrueType module definition
#
# Copyright (C) 1996-2023 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.
FTMODULE_H_COMMANDS += PRELOAD_DRIVER
define PRELOAD_DRIVER
$(OPEN_DRIVER) FT_Driver_ClassRec, preload_driver_class $(CLOSE_DRIVER)
$(ECHO_DRIVER)preload $(ECHO_DRIVER_DESC)Windows/Mac font files with extension *.ttf or *.ttc$(ECHO_DRIVER_DONE)
endef
# EOF

29
src/preload/preload.c Normal file
View File

@ -0,0 +1,29 @@
/****************************************************************************
*
* truetype.c
*
* FreeType TrueType driver component (body only).
*
* Copyright (C) 1996-2023 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 "ttdriver.c" /* driver interface */
#include "ttgload.c" /* glyph loader */
#include "ttgxvar.c" /* gx distortable font */
#include "ttinterp.c"
#include "ttobjs.c" /* object manager */
#include "ttpload.c" /* tables loader */
/* END */

75
src/preload/rules.mk Normal file
View File

@ -0,0 +1,75 @@
#
# FreeType 2 TrueType driver configuration rules
#
# Copyright (C) 1996-2023 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.
# TrueType driver directory
#
TT_DIR := $(SRC_DIR)/preload
# compilation flags for the driver
#
TT_COMPILE := $(CC) $(ANSIFLAGS) \
$I$(subst /,$(COMPILER_SEP),$(TT_DIR)) \
$(INCLUDE_FLAGS) \
$(FT_CFLAGS)
# TrueType driver sources (i.e., C files)
#
TT_DRV_SRC := $(TT_DIR)/ttdriver.c \
$(TT_DIR)/ttgload.c \
$(TT_DIR)/ttgxvar.c \
$(TT_DIR)/ttinterp.c \
$(TT_DIR)/ttobjs.c \
$(TT_DIR)/ttpload.c
# TrueType driver headers
#
TT_DRV_H := $(TT_DRV_SRC:%.c=%.h) \
$(TT_DIR)/tterrors.h
# TrueType driver object(s)
#
# TT_DRV_OBJ_M is used during `multi' builds
# TT_DRV_OBJ_S is used during `single' builds
#
TT_DRV_OBJ_M := $(TT_DRV_SRC:$(TT_DIR)/%.c=$(OBJ_DIR)/%.$O)
TT_DRV_OBJ_S := $(OBJ_DIR)/preload.$O
# TrueType driver source file for single build
#
TT_DRV_SRC_S := $(TT_DIR)/preload.c
# TrueType driver - single object
#
$(TT_DRV_OBJ_S): $(TT_DRV_SRC_S) $(TT_DRV_SRC) $(FREETYPE_H) $(TT_DRV_H)
$(TT_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(TT_DRV_SRC_S))
# driver - multiple objects
#
$(OBJ_DIR)/%.$O: $(TT_DIR)/%.c $(FREETYPE_H) $(TT_DRV_H)
$(TT_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
# update main driver object lists
#
DRV_OBJS_S += $(TT_DRV_OBJ_S)
DRV_OBJS_M += $(TT_DRV_OBJ_M)
# EOF

691
src/preload/ttdriver.c Normal file
View File

@ -0,0 +1,691 @@
/****************************************************************************
*
* ttdriver.c
*
* TrueType font driver implementation (body).
*
* Copyright (C) 1996-2023 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 <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>
#include <freetype/internal/sfnt.h>
#include <freetype/internal/services/svfntfmt.h>
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
#include <freetype/ftmm.h>
#include <freetype/internal/services/svmm.h>
#include <freetype/internal/services/svmetric.h>
#endif
#include <freetype/internal/services/svtteng.h>
#include <freetype/internal/services/svttglyf.h>
#include <freetype/internal/services/svprop.h>
#include <freetype/ftdriver.h>
#include "ttdriver.h"
#include "ttgload.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 ttdriver
/*
* PROPERTY SERVICE
*
*/
FT_CALLBACK_DEF( 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;
}
switch ( interpreter_version )
{
case TT_INTERPRETER_VERSION_35:
driver->interpreter_version = TT_INTERPRETER_VERSION_35;
break;
case TT_INTERPRETER_VERSION_38:
case TT_INTERPRETER_VERSION_40:
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
driver->interpreter_version = TT_INTERPRETER_VERSION_40;
break;
#endif
default:
error = FT_ERR( Unimplemented_Feature );
}
return error;
}
FT_TRACE2(( "tt_property_set: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
}
FT_CALLBACK_DEF( FT_Error )
tt_property_get( FT_Module module, /* TT_Driver */
const char* property_name,
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_TRACE2(( "tt_property_get: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
}
FT_DEFINE_SERVICE_PROPERTIESREC(
tt_service_properties,
tt_property_set, /* FT_Properties_SetFunc set_property */
tt_property_get /* FT_Properties_GetFunc 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.
*/
FT_CALLBACK_DEF( FT_Error )
tt_get_kerning( FT_Face face, /* TT_Face */
FT_UInt left_glyph,
FT_UInt right_glyph,
FT_Vector* kerning )
{
TT_Face ttface = (TT_Face)face;
SFNT_Service sfnt = (SFNT_Service)ttface->sfnt;
kerning->x = 0;
kerning->y = 0;
if ( sfnt )
kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph );
return 0;
}
FT_CALLBACK_DEF( FT_Error )
tt_get_advances( FT_Face face, /* TT_Face */
FT_UInt start,
FT_UInt count,
FT_Int32 flags,
FT_Fixed *advances )
{
FT_UInt nn;
TT_Face ttface = (TT_Face)face;
/* 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 ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) &&
!( ttface->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( ttface, 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 ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) &&
!( ttface->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( ttface, start + nn, &lsb, &aw );
advances[nn] = aw;
}
}
return FT_Err_Ok;
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** S I Z E S ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
FT_CALLBACK_DEF( 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 ); /* ignore return value */
}
else
{
SFNT_Service sfnt = (SFNT_Service)ttface->sfnt;
FT_Size_Metrics* size_metrics = &size->metrics;
error = sfnt->load_strike_metrics( ttface,
strike_index,
size_metrics );
if ( error )
ttsize->strike_index = 0xFFFFFFFFUL;
}
return error;
}
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
FT_CALLBACK_DEF( 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_Error err = FT_Request_Metrics( size->face, req );
if ( err )
{
error = err;
goto Exit;
}
}
if ( FT_IS_SCALABLE( size->face ) )
{
error = tt_size_reset( ttsize );
#ifdef TT_USE_BYTECODE_INTERPRETER
/* for the `MPS' bytecode instruction we need the point size */
if ( !error )
{
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
}
Exit:
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.
*/
FT_CALLBACK_DEF( FT_Error )
tt_glyph_load( FT_GlyphSlot slot, /* TT_GlyphSlot */
FT_Size size, /* TT_Size */
FT_UInt glyph_index,
FT_Int32 load_flags )
{
TT_GlyphSlot ttslot = (TT_GlyphSlot)slot;
TT_Size ttsize = (TT_Size)size;
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;
}
/* use hinted metrics only if we load a glyph with hinting */
ttsize->metrics = ( load_flags & FT_LOAD_NO_HINTING )
? &size->metrics
: &ttsize->hinted_metrics;
/* now fill in the glyph slot with outline/bitmap/layered */
error = TT_Load_Glyph( ttsize, ttslot, 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,
NULL, /* FT_Get_MM_Func get_mm */
NULL, /* FT_Set_MM_Design_Func set_mm_design */
TT_Set_MM_Blend, /* FT_Set_MM_Blend_Func set_mm_blend */
TT_Get_MM_Blend, /* FT_Get_MM_Blend_Func get_mm_blend */
TT_Get_MM_Var, /* FT_Get_MM_Var_Func get_mm_var */
TT_Set_Var_Design, /* FT_Set_Var_Design_Func set_var_design */
TT_Get_Var_Design, /* FT_Get_Var_Design_Func get_var_design */
TT_Set_Named_Instance, /* FT_Set_Named_Instance_Func set_named_instance */
TT_Get_Default_Named_Instance,
/* FT_Get_Default_Named_Instance_Func get_default_named_instance */
NULL, /* FT_Set_MM_WeightVector_Func set_mm_weightvector */
NULL, /* FT_Get_MM_WeightVector_Func get_mm_weightvector */
tt_construct_ps_name, /* FT_Construct_PS_Name_Func construct_ps_name */
tt_var_load_delta_set_index_mapping,
/* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */
tt_var_load_item_variation_store,
/* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */
tt_var_get_item_delta, /* FT_Var_Get_Item_Delta_Func get_item_delta */
tt_var_done_item_variation_store,
/* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */
tt_var_done_delta_set_index_map,
/* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */
tt_get_var_blend, /* FT_Get_Var_Blend_Func get_var_blend */
tt_done_blend /* FT_Done_Blend_Func done_blend */
)
FT_DEFINE_SERVICE_METRICSVARIATIONSREC(
tt_service_metrics_variations,
tt_hadvance_adjust, /* FT_HAdvance_Adjust_Func hadvance_adjust */
NULL, /* FT_LSB_Adjust_Func lsb_adjust */
NULL, /* FT_RSB_Adjust_Func rsb_adjust */
tt_vadvance_adjust, /* FT_VAdvance_Adjust_Func vadvance_adjust */
NULL, /* FT_TSB_Adjust_Func tsb_adjust */
NULL, /* FT_BSB_Adjust_Func bsb_adjust */
NULL, /* FT_VOrg_Adjust_Func vorg_adjust */
tt_apply_mvar, /* FT_Metrics_Adjust_Func metrics_adjust */
tt_size_reset_height /* FT_Size_Reset_Func size_reset */
)
#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,
FT_SERVICE_ID_METRICS_VARIATIONS, &tt_service_metrics_variations,
FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
FT_SERVICE_ID_TT_GLYF, &tt_service_truetype_glyf,
FT_SERVICE_ID_PROPERTIES, &tt_service_properties )
#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,
FT_SERVICE_ID_PROPERTIES, &tt_service_properties )
#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;
result = ft_service_list_lookup( tt_services, tt_interface );
if ( result )
return result;
if ( !driver )
return NULL;
library = driver->library;
if ( !library )
return NULL;
/* 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 */

35
src/preload/ttdriver.h Normal file
View File

@ -0,0 +1,35 @@
/****************************************************************************
*
* ttdriver.h
*
* High-level TrueType driver interface (specification).
*
* Copyright (C) 1996-2023 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 <freetype/internal/ftdrv.h>
FT_BEGIN_HEADER
FT_DECLARE_DRIVER( tt_driver_class )
FT_END_HEADER
#endif /* TTDRIVER_H_ */
/* END */

42
src/preload/tterrors.h Normal file
View File

@ -0,0 +1,42 @@
/****************************************************************************
*
* tterrors.h
*
* TrueType error codes (specification only).
*
* Copyright (C) 2001-2023 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 <freetype/ftmoderr.h>
#undef FTERRORS_H_
#undef FT_ERR_PREFIX
#define FT_ERR_PREFIX TT_Err_
#define FT_ERR_BASE FT_Mod_Err_TrueType
#include <freetype/fterrors.h>
#endif /* TTERRORS_H_ */
/* END */

2743
src/preload/ttgload.c Normal file

File diff suppressed because it is too large Load Diff

61
src/preload/ttgload.h Normal file
View File

@ -0,0 +1,61 @@
/****************************************************************************
*
* ttgload.h
*
* TrueType Glyph Loader (specification).
*
* Copyright (C) 1996-2023 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 "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 */

4661
src/preload/ttgxvar.c Normal file

File diff suppressed because it is too large Load Diff

453
src/preload/ttgxvar.h Normal file
View File

@ -0,0 +1,453 @@
/****************************************************************************
*
* ttgxvar.h
*
* TrueType GX Font Variation loader (specification)
*
* Copyright (C) 2004-2023 by
* David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
*
* 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 TTGXVAR_H_
#define TTGXVAR_H_
#include <freetype/internal/ftmmtypes.h>
#include "ttobjs.h"
FT_BEGIN_HEADER
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
/**************************************************************************
*
* @Struct:
* GX_AVarCorrespondenceRec
*
* @Description:
* A data structure representing `shortFracCorrespondence' in `avar'
* table according to the specifications from Apple.
*/
typedef struct GX_AVarCorrespondenceRec_
{
FT_Fixed fromCoord;
FT_Fixed toCoord;
} GX_AVarCorrespondenceRec_, *GX_AVarCorrespondence;
/**************************************************************************
*
* @Struct:
* GX_AVarRec
*
* @Description:
* Data from the segment field of `avar' table.
* There is one of these for each axis.
*/
typedef struct GX_AVarSegmentRec_
{
FT_UShort pairCount;
GX_AVarCorrespondence correspondence; /* array with pairCount entries */
} GX_AVarSegmentRec, *GX_AVarSegment;
/**************************************************************************
*
* @Struct:
* GX_AVarTableRec
*
* @Description:
* Data from the `avar' table.
*/
typedef struct GX_AVarTableRec_
{
GX_AVarSegment avar_segment; /* avar_segment[num_axis] */
GX_ItemVarStoreRec itemStore; /* Item Variation Store */
GX_DeltaSetIdxMapRec axisMap; /* Axis Mapping */
} GX_AVarTableRec, *GX_AVarTable;
/**************************************************************************
*
* @Struct:
* GX_HVVarTableRec
*
* @Description:
* Data from either the `HVAR' or `VVAR' table.
*/
typedef struct GX_HVVarTableRec_
{
GX_ItemVarStoreRec itemStore; /* Item Variation Store */
GX_DeltaSetIdxMapRec widthMap; /* Advance Width Mapping */
#if 0
GX_DeltaSetIdxMapRec lsbMap; /* not implemented */
GX_DeltaSetIdxMapRec rsbMap; /* not implemented */
GX_DeltaSetIdxMapRec tsbMap; /* not implemented */
GX_DeltaSetIdxMapRec bsbMap; /* not implemented */
GX_DeltaSetIdxMapRec vorgMap; /* not implemented */
#endif
} GX_HVVarTableRec, *GX_HVVarTable;
#define MVAR_TAG_GASP_0 FT_MAKE_TAG( 'g', 's', 'p', '0' )
#define MVAR_TAG_GASP_1 FT_MAKE_TAG( 'g', 's', 'p', '1' )
#define MVAR_TAG_GASP_2 FT_MAKE_TAG( 'g', 's', 'p', '2' )
#define MVAR_TAG_GASP_3 FT_MAKE_TAG( 'g', 's', 'p', '3' )
#define MVAR_TAG_GASP_4 FT_MAKE_TAG( 'g', 's', 'p', '4' )
#define MVAR_TAG_GASP_5 FT_MAKE_TAG( 'g', 's', 'p', '5' )
#define MVAR_TAG_GASP_6 FT_MAKE_TAG( 'g', 's', 'p', '6' )
#define MVAR_TAG_GASP_7 FT_MAKE_TAG( 'g', 's', 'p', '7' )
#define MVAR_TAG_GASP_8 FT_MAKE_TAG( 'g', 's', 'p', '8' )
#define MVAR_TAG_GASP_9 FT_MAKE_TAG( 'g', 's', 'p', '9' )
#define MVAR_TAG_CPHT FT_MAKE_TAG( 'c', 'p', 'h', 't' )
#define MVAR_TAG_HASC FT_MAKE_TAG( 'h', 'a', 's', 'c' )
#define MVAR_TAG_HCLA FT_MAKE_TAG( 'h', 'c', 'l', 'a' )
#define MVAR_TAG_HCLD FT_MAKE_TAG( 'h', 'c', 'l', 'd' )
#define MVAR_TAG_HCOF FT_MAKE_TAG( 'h', 'c', 'o', 'f' )
#define MVAR_TAG_HCRN FT_MAKE_TAG( 'h', 'c', 'r', 'n' )
#define MVAR_TAG_HCRS FT_MAKE_TAG( 'h', 'c', 'r', 's' )
#define MVAR_TAG_HDSC FT_MAKE_TAG( 'h', 'd', 's', 'c' )
#define MVAR_TAG_HLGP FT_MAKE_TAG( 'h', 'l', 'g', 'p' )
#define MVAR_TAG_SBXO FT_MAKE_TAG( 's', 'b', 'x', 'o' )
#define MVAR_TAG_SBXS FT_MAKE_TAG( 's', 'b', 'x', 's' )
#define MVAR_TAG_SBYO FT_MAKE_TAG( 's', 'b', 'y', 'o' )
#define MVAR_TAG_SBYS FT_MAKE_TAG( 's', 'b', 'y', 's' )
#define MVAR_TAG_SPXO FT_MAKE_TAG( 's', 'p', 'x', 'o' )
#define MVAR_TAG_SPXS FT_MAKE_TAG( 's', 'p', 'x', 's' )
#define MVAR_TAG_SPYO FT_MAKE_TAG( 's', 'p', 'y', 'o' )
#define MVAR_TAG_SPYS FT_MAKE_TAG( 's', 'p', 'y', 's' )
#define MVAR_TAG_STRO FT_MAKE_TAG( 's', 't', 'r', 'o' )
#define MVAR_TAG_STRS FT_MAKE_TAG( 's', 't', 'r', 's' )
#define MVAR_TAG_UNDO FT_MAKE_TAG( 'u', 'n', 'd', 'o' )
#define MVAR_TAG_UNDS FT_MAKE_TAG( 'u', 'n', 'd', 's' )
#define MVAR_TAG_VASC FT_MAKE_TAG( 'v', 'a', 's', 'c' )
#define MVAR_TAG_VCOF FT_MAKE_TAG( 'v', 'c', 'o', 'f' )
#define MVAR_TAG_VCRN FT_MAKE_TAG( 'v', 'c', 'r', 'n' )
#define MVAR_TAG_VCRS FT_MAKE_TAG( 'v', 'c', 'r', 's' )
#define MVAR_TAG_VDSC FT_MAKE_TAG( 'v', 'd', 's', 'c' )
#define MVAR_TAG_VLGP FT_MAKE_TAG( 'v', 'l', 'g', 'p' )
#define MVAR_TAG_XHGT FT_MAKE_TAG( 'x', 'h', 'g', 't' )
typedef struct GX_ValueRec_
{
FT_ULong tag;
FT_UShort outerIndex;
FT_UShort innerIndex;
FT_Short unmodified; /* values are either FT_Short or FT_UShort */
} GX_ValueRec, *GX_Value;
/**************************************************************************
*
* @Struct:
* GX_MVarTableRec
*
* @Description:
* Data from the `MVAR' table.
*/
typedef struct GX_MVarTableRec_
{
FT_UShort valueCount;
GX_ItemVarStoreRec itemStore; /* Item Variation Store */
GX_Value values; /* Value Records */
} GX_MVarTableRec, *GX_MVarTable;
/**************************************************************************
*
* @Struct:
* GX_BlendRec
*
* @Description:
* Data for interpolating a font from a distortable font specified
* by the GX *var tables ([fgcahvm]var).
*
* @Fields:
* num_axis ::
* The number of axes along which interpolation may happen.
*
* coords ::
* An array of design coordinates (in user space) indicating the
* contribution along each axis to the final interpolated font.
* `normalizedcoords' holds the same values.
*
* normalizedcoords ::
* An array of normalized values (between [-1,1]) indicating the
* contribution along each axis to the final interpolated font.
* `coords' holds the same values.
*
* mmvar ::
* Data from the `fvar' table.
*
* mmvar_len ::
* The length of the `mmvar' structure.
*
* normalized_stylecoords ::
* A two-dimensional array that holds the named instance data from
* `mmvar' as normalized values.
*
* avar_loaded ::
* A Boolean; if set, FreeType tried to load (and parse) the `avar'
* table.
*
* avar_table ::
* Data from the `avar' table.
*
* hvar_loaded ::
* A Boolean; if set, FreeType tried to load (and parse) the `hvar'
* table.
*
* hvar_checked ::
* A Boolean; if set, FreeType successfully loaded and parsed the
* `hvar' table.
*
* hvar_error ::
* If loading and parsing of the `hvar' table failed, this field
* holds the corresponding error code.
*
* hvar_table ::
* Data from the `hvar' table.
*
* vvar_loaded ::
* A Boolean; if set, FreeType tried to load (and parse) the `vvar'
* table.
*
* vvar_checked ::
* A Boolean; if set, FreeType successfully loaded and parsed the
* `vvar' table.
*
* vvar_error ::
* If loading and parsing of the `vvar' table failed, this field
* holds the corresponding error code.
*
* vvar_table ::
* Data from the `vvar' table.
*
* mvar_table ::
* Data from the `mvar' table.
*
* tuplecount ::
* The number of shared tuples in the `gvar' table.
*
* tuplecoords ::
* A two-dimensional array that holds the shared tuple coordinates
* in the `gvar' table.
*
* gv_glyphcnt ::
* The number of glyphs handled in the `gvar' table.
*
* glyphoffsets ::
* Offsets into the glyph variation data array.
*
* gvar_size ::
* The size of the `gvar' table.
*/
typedef struct GX_BlendRec_
{
FT_UInt num_axis;
FT_Fixed* coords;
FT_Fixed* normalizedcoords;
FT_MM_Var* mmvar;
FT_Offset mmvar_len;
FT_Fixed* normalized_stylecoords;
/* normalized_stylecoords[num_namedstyles][num_axis] */
FT_Bool avar_loaded;
GX_AVarTable avar_table;
FT_Bool hvar_loaded;
FT_Bool hvar_checked;
FT_Error hvar_error;
GX_HVVarTable hvar_table;
FT_Bool vvar_loaded;
FT_Bool vvar_checked;
FT_Error vvar_error;
GX_HVVarTable vvar_table;
GX_MVarTable mvar_table;
FT_UInt tuplecount;
FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */
FT_UInt gv_glyphcnt;
FT_ULong* glyphoffsets; /* glyphoffsets[gv_glyphcnt + 1] */
FT_ULong gvar_size;
} GX_BlendRec;
/**************************************************************************
*
* @enum:
* GX_TupleCountFlags
*
* @Description:
* Flags used within the `TupleCount' field of the `gvar' table.
*/
typedef enum GX_TupleCountFlags_
{
GX_TC_TUPLES_SHARE_POINT_NUMBERS = 0x8000,
GX_TC_RESERVED_TUPLE_FLAGS = 0x7000,
GX_TC_TUPLE_COUNT_MASK = 0x0FFF
} GX_TupleCountFlags;
/**************************************************************************
*
* @enum:
* GX_TupleIndexFlags
*
* @Description:
* Flags used within the `TupleIndex' field of the `gvar' and `cvar'
* tables.
*/
typedef enum GX_TupleIndexFlags_
{
GX_TI_EMBEDDED_TUPLE_COORD = 0x8000,
GX_TI_INTERMEDIATE_TUPLE = 0x4000,
GX_TI_PRIVATE_POINT_NUMBERS = 0x2000,
GX_TI_RESERVED_TUPLE_FLAG = 0x1000,
GX_TI_TUPLE_INDEX_MASK = 0x0FFF
} GX_TupleIndexFlags;
#define TTAG_wght FT_MAKE_TAG( 'w', 'g', 'h', 't' )
#define TTAG_wdth FT_MAKE_TAG( 'w', 'd', 't', 'h' )
#define TTAG_opsz FT_MAKE_TAG( 'o', 'p', 's', 'z' )
#define TTAG_slnt FT_MAKE_TAG( 's', 'l', 'n', 't' )
#define TTAG_ital FT_MAKE_TAG( 'i', 't', 'a', 'l' )
FT_LOCAL( FT_Error )
TT_Set_MM_Blend( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
FT_LOCAL( FT_Error )
TT_Get_MM_Blend( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
FT_LOCAL( FT_Error )
TT_Set_Var_Design( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
FT_LOCAL( FT_Error )
TT_Get_MM_Var( FT_Face face,
FT_MM_Var* *master );
FT_LOCAL( FT_Error )
TT_Get_Var_Design( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
FT_LOCAL( FT_Error )
TT_Set_Named_Instance( FT_Face face,
FT_UInt instance_index );
FT_LOCAL( FT_Error )
TT_Get_Default_Named_Instance( FT_Face face,
FT_UInt *instance_index );
FT_LOCAL( void )
tt_construct_ps_name( FT_Face face );
FT_LOCAL( FT_Error )
tt_face_vary_cvt( TT_Face face,
FT_Stream stream );
FT_LOCAL( FT_Error )
TT_Vary_Apply_Glyph_Deltas( TT_Loader loader,
FT_Outline* outline,
FT_Vector* unrounded );
FT_LOCAL( FT_Error )
tt_hadvance_adjust( FT_Face face,
FT_UInt gindex,
FT_Int *adelta );
FT_LOCAL( FT_Error )
tt_vadvance_adjust( FT_Face face,
FT_UInt gindex,
FT_Int *adelta );
FT_LOCAL( void )
tt_apply_mvar( FT_Face face );
FT_LOCAL( FT_Error )
tt_var_load_item_variation_store( FT_Face face,
FT_ULong offset,
GX_ItemVarStore itemStore );
FT_LOCAL( FT_Error )
tt_var_load_delta_set_index_mapping( FT_Face face,
FT_ULong offset,
GX_DeltaSetIdxMap map,
GX_ItemVarStore itemStore,
FT_ULong table_len );
FT_LOCAL( FT_ItemVarDelta )
tt_var_get_item_delta( FT_Face face,
GX_ItemVarStore itemStore,
FT_UInt outerIndex,
FT_UInt innerIndex );
FT_LOCAL( void )
tt_var_done_item_variation_store( FT_Face face,
GX_ItemVarStore itemStore );
FT_LOCAL( void )
tt_var_done_delta_set_index_map( FT_Face face,
GX_DeltaSetIdxMap deltaSetIdxMap );
FT_LOCAL( FT_Error )
tt_get_var_blend( FT_Face face,
FT_UInt *num_coords,
FT_Fixed* *coords,
FT_Fixed* *normalizedcoords,
FT_MM_Var* *mm_var );
FT_LOCAL( void )
tt_done_blend( FT_Face face );
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
FT_END_HEADER
#endif /* TTGXVAR_H_ */
/* END */

7753
src/preload/ttinterp.c Normal file

File diff suppressed because it is too large Load Diff

465
src/preload/ttinterp.h Normal file
View File

@ -0,0 +1,465 @@
/****************************************************************************
*
* ttinterp.h
*
* TrueType bytecode interpreter (specification).
*
* Copyright (C) 1996-2023 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 "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_Int color );
/* 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;
/**************************************************************************
*
* The main structure for the interpreter which collects all necessary
* variables and states.
*
* Members that are initialized by `TT_Load_Context` are marked with '!'.
* Members that are initialized by `TT_Run_Context` are marked with '@'.
*/
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 iniRange; /* initial code range number */
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_ULong glyfCvtSize;
FT_Long* glyfCvt; /* cvt working copy for glyph */
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_UShort glyfStoreSize;
FT_Long* glyfStorage; /* storage working copy for glyph */
FT_F26Dot6 period; /* values used for the */
FT_F26Dot6 phase; /* `SuperRounding' */
FT_F26Dot6 threshold;
FT_Bool instruction_trap; /* ! If `True', the interpreter */
/* exits 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
/*
* FreeType supports ClearType-like hinting of TrueType fonts through
* the version 40 interpreter. This is achieved through several hacks
* in the base (v35) interpreter, as detailed below.
*
* ClearType is an umbrella term for several rendering techniques
* employed by Microsoft's various GUI and rendering toolkit
* implementations, most importantly: subpixel rendering for using the
* RGB subpixels of LCDs to approximately triple the perceived
* resolution on the x-axis and subpixel hinting for positioning stems
* on subpixel borders. TrueType programming is explicit, i.e., fonts
* must be programmed to take advantage of ClearType's possibilities.
*
* When ClearType was introduced, it seemed unlikely that all fonts
* would be reprogrammed, so Microsoft decided to implement a backward
* compatibility mode. It employs several simple to complicated
* assumptions and tricks, many of them font-dependent, that modify the
* interpretation of the bytecode contained in these fonts to retrofit
* them into a ClearType-y look. The quality of the results varies.
* Most (web)fonts that were released since then have come to rely on
* these hacks to render correctly, even some of Microsoft's flagship
* fonts (e.g., Calibri, Cambria, Segoe UI).
*
* FreeType's minimal subpixel hinting code (interpreter version 40)
* employs a small list of font-agnostic hacks loosely based on the
* public information available on Microsoft's compatibility mode[2].
* The focus is on modern (web)fonts rather than legacy fonts that were
* made for monochrome rendering. It will not match ClearType rendering
* exactly. Unlike the `Infinality' code (interpreter version 38) that
* came before, it will not try to toggle hacks for specific fonts for
* performance and complexity reasons. It will fall back to version 35
* behavior for tricky fonts[1] or when monochrome rendering is
* requested.
*
* 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 backward 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 backward 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
* backward 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://rastertragedy.com/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, unless FT_RENDER_MODE_MONO has been
* requested. 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 backward compatibility mode in v40 interpreter. If */
/* this is false, it implies the interpreter is in v35 or in native */
/* ClearType mode. */
FT_Bool backward_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 */
/* 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 );
#endif /* TT_USE_BYTECODE_INTERPRETER */
/**************************************************************************
*
* @Function:
* TT_New_Context
*
* @Description:
* Create a `TT_ExecContext`. Note that there is now an execution
* context per `TT_Size` that is not shared among faces.
*
* @Input:
* driver ::
* A handle to the driver, used for memory allocation.
*
* @Return:
* A handle to a new empty execution context.
*
* @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( void* exec );
FT_END_HEADER
#endif /* TTINTERP_H_ */
/* END */

1539
src/preload/ttobjs.c Normal file

File diff suppressed because it is too large Load Diff

426
src/preload/ttobjs.h Normal file
View File

@ -0,0 +1,426 @@
/****************************************************************************
*
* ttobjs.h
*
* Objects manager (specification).
*
* Copyright (C) 1996-2023 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 <freetype/internal/ftobjs.h>
#include <freetype/internal/tttypes.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? */
} 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; /* for the current rendering mode */
FT_Size_Metrics hinted_metrics; /* for the hinted rendering mode */
TT_Size_Metrics ttmetrics;
FT_Byte* widthp; /* glyph widths from the hdmx table */
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_height( FT_Size size );
FT_LOCAL( FT_Error )
tt_size_reset( TT_Size size );
/**************************************************************************
*
* 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 */

665
src/preload/ttpload.c Normal file
View File

@ -0,0 +1,665 @@
/****************************************************************************
*
* ttpload.c
*
* TrueType-specific tables loader (body).
*
* Copyright (C) 1996-2023 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 <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftstream.h>
#include <freetype/tttags.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 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;
}
shift = face->header.Index_To_Loc_Format != 0 ? 2 : 1;
if ( table_len > 0x10000UL << shift )
{
FT_TRACE2(( "table too large\n" ));
table_len = 0x10000UL << shift;
}
face->num_locations = table_len >> shift;
if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
{
FT_TRACE2(( "glyph count mismatch! loca: %ld, maxp: %ld\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 + 1 )
{
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 %ld\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 %ld\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( FT_Face face, /* TT_Face */
FT_UInt gindex,
FT_ULong *asize )
{
TT_Face ttface = (TT_Face)face;
FT_ULong pos1, pos2;
FT_Byte* p;
FT_Byte* p_limit;
pos1 = pos2 = 0;
if ( gindex < ttface->num_locations )
{
if ( ttface->header.Index_To_Loc_Format != 0 )
{
p = ttface->glyph_locations + gindex * 4;
p_limit = ttface->glyph_locations + ttface->num_locations * 4;
pos1 = FT_NEXT_ULONG( p );
pos2 = pos1;
if ( p + 4 <= p_limit )
pos2 = FT_NEXT_ULONG( p );
}
else
{
p = ttface->glyph_locations + gindex * 2;
p_limit = ttface->glyph_locations + ttface->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 > ttface->glyf_len )
{
FT_TRACE1(( "tt_face_get_location:"
" too large offset (0x%08lx) found for glyph index %d,\n",
pos1, gindex ));
FT_TRACE1(( " "
" exceeding the end of `glyf' table (0x%08lx)\n",
ttface->glyf_len ));
*asize = 0;
return 0;
}
if ( pos2 > ttface->glyf_len )
{
/* We try to sanitize the last `loca' entry. */
if ( gindex == ttface->num_locations - 2 )
{
FT_TRACE1(( "tt_face_get_location:"
" too large size (%ld bytes) found for glyph index %d,\n",
pos2 - pos1, gindex ));
FT_TRACE1(( " "
" truncating at the end of `glyf' table to %ld bytes\n",
ttface->glyf_len - pos1 ));
pos2 = ttface->glyf_len;
}
else
{
FT_TRACE1(( "tt_face_get_location:"
" too large offset (0x%08lx) found for glyph index %d,\n",
pos2, gindex + 1 ));
FT_TRACE1(( " "
" exceeding the end of `glyf' table (0x%08lx)\n",
ttface->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_ULong)( pos2 - pos1 );
else
*asize = (FT_ULong)( ttface->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_QNEW_ARRAY( face->cvt, face->cvt_size ) )
goto Exit;
if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
goto Exit;
{
FT_Int32* cur = face->cvt;
FT_Int32* limit = cur + face->cvt_size;
for ( ; cur < limit; cur++ )
*cur = FT_GET_SHORT() * 64;
}
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, %12ld 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, %12ld 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
}
FT_COMPARE_DEF( int )
compare_ppem( const void* a,
const void* b )
{
return **(FT_Byte**)a - **(FT_Byte**)b;
}
/**************************************************************************
*
* @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 );
/* 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;
FT_TRACE2(( "Hdmx " ));
/* The limit for `num_records' is a heuristic value. */
if ( num_records > 255 || num_records == 0 )
{
FT_TRACE2(( "with unreasonable %u records rejected\n", num_records ));
goto Fail;
}
/* Out-of-spec tables are rejected. The record size must be */
/* equal to the number of glyphs + 2 + 32-bit padding. */
if ( (FT_Long)record_size != ( ( face->root.num_glyphs + 2 + 3 ) & ~3 ) )
{
FT_TRACE2(( "with record size off by %ld bytes rejected\n",
(FT_Long)record_size -
( ( face->root.num_glyphs + 2 + 3 ) & ~3 ) ));
goto Fail;
}
if ( FT_QNEW_ARRAY( face->hdmx_records, num_records ) )
goto Fail;
for ( nn = 0; nn < num_records; nn++ )
{
if ( p + record_size > limit )
break;
face->hdmx_records[nn] = p;
p += record_size;
}
/* The records must be already sorted by ppem but it does not */
/* hurt to make sure so that the binary search works later. */
ft_qsort( face->hdmx_records, nn, sizeof ( FT_Byte* ), compare_ppem );
face->hdmx_record_count = nn;
face->hdmx_table_size = table_size;
face->hdmx_record_size = record_size;
FT_TRACE2(( "%ux%lu loaded\n", num_records, 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_records );
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). The records must be sorted for
* the binary search to work properly.
*/
FT_LOCAL_DEF( FT_Byte* )
tt_face_get_device_metrics( TT_Face face,
FT_UInt ppem,
FT_UInt gindex )
{
FT_UInt min = 0;
FT_UInt max = face->hdmx_record_count;
FT_UInt mid;
FT_Byte* result = NULL;
while ( min < max )
{
mid = ( min + max ) >> 1;
if ( face->hdmx_records[mid][0] > ppem )
max = mid;
else if ( face->hdmx_records[mid][0] < ppem )
min = mid + 1;
else
{
result = face->hdmx_records[mid] + 2 + gindex;
break;
}
}
return result;
}
/* END */

74
src/preload/ttpload.h Normal file
View File

@ -0,0 +1,74 @@
/****************************************************************************
*
* ttpload.h
*
* TrueType-specific tables loader (specification).
*
* Copyright (C) 1996-2023 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 <freetype/internal/tttypes.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( FT_Face face,
FT_UInt gindex,
FT_ULong *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 */