/***************************************************************************/ | |
/* */ | |
/* aftypes.h */ | |
/* */ | |
/* Auto-fitter types (specification only). */ | |
/* */ | |
/* Copyright 2003-2015 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. */ | |
/* */ | |
/***************************************************************************/ | |
/************************************************************************* | |
* | |
* The auto-fitter is a complete rewrite of the old auto-hinter. | |
* Its main feature is the ability to differentiate between different | |
* writing systems and scripts in order to apply specific rules. | |
* | |
* The code has also been compartmentized into several entities that | |
* should make algorithmic experimentation easier than with the old | |
* code. | |
* | |
*************************************************************************/ | |
#ifndef __AFTYPES_H__ | |
#define __AFTYPES_H__ | |
#include <ft2build.h> | |
#include FT_FREETYPE_H | |
#include FT_OUTLINE_H | |
#include FT_INTERNAL_OBJECTS_H | |
#include FT_INTERNAL_DEBUG_H | |
#include "afblue.h" | |
#ifdef FT_DEBUG_AUTOFIT | |
#include FT_CONFIG_STANDARD_LIBRARY_H | |
#endif | |
FT_BEGIN_HEADER | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/***** *****/ | |
/***** D E B U G G I N G *****/ | |
/***** *****/ | |
/*************************************************************************/ | |
/*************************************************************************/ | |
#ifdef FT_DEBUG_AUTOFIT | |
extern int _af_debug_disable_horz_hints; | |
extern int _af_debug_disable_vert_hints; | |
extern int _af_debug_disable_blue_hints; | |
extern void* _af_debug_hints; | |
#endif /* FT_DEBUG_AUTOFIT */ | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/***** *****/ | |
/***** U T I L I T Y S T U F F *****/ | |
/***** *****/ | |
/*************************************************************************/ | |
/*************************************************************************/ | |
typedef struct AF_WidthRec_ | |
{ | |
FT_Pos org; /* original position/width in font units */ | |
FT_Pos cur; /* current/scaled position/width in device sub-pixels */ | |
FT_Pos fit; /* current/fitted position/width in device sub-pixels */ | |
} AF_WidthRec, *AF_Width; | |
FT_LOCAL( void ) | |
af_sort_pos( FT_UInt count, | |
FT_Pos* table ); | |
FT_LOCAL( void ) | |
af_sort_and_quantize_widths( FT_UInt* count, | |
AF_Width widths, | |
FT_Pos threshold ); | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/***** *****/ | |
/***** A N G L E T Y P E S *****/ | |
/***** *****/ | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/* | |
* The auto-fitter doesn't need a very high angular accuracy; | |
* this allows us to speed up some computations considerably with a | |
* light Cordic algorithm (see afangles.c). | |
*/ | |
typedef FT_Int AF_Angle; | |
#define AF_ANGLE_PI 256 | |
#define AF_ANGLE_2PI ( AF_ANGLE_PI * 2 ) | |
#define AF_ANGLE_PI2 ( AF_ANGLE_PI / 2 ) | |
#define AF_ANGLE_PI4 ( AF_ANGLE_PI / 4 ) | |
#if 0 | |
/* | |
* compute the angle of a given 2-D vector | |
*/ | |
FT_LOCAL( AF_Angle ) | |
af_angle_atan( FT_Pos dx, | |
FT_Pos dy ); | |
/* | |
* compute `angle2 - angle1'; the result is always within | |
* the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1] | |
*/ | |
FT_LOCAL( AF_Angle ) | |
af_angle_diff( AF_Angle angle1, | |
AF_Angle angle2 ); | |
#endif /* 0 */ | |
#define AF_ANGLE_DIFF( result, angle1, angle2 ) \ | |
FT_BEGIN_STMNT \ | |
AF_Angle _delta = (angle2) - (angle1); \ | |
\ | |
\ | |
while ( _delta <= -AF_ANGLE_PI ) \ | |
_delta += AF_ANGLE_2PI; \ | |
\ | |
while ( _delta > AF_ANGLE_PI ) \ | |
_delta -= AF_ANGLE_2PI; \ | |
\ | |
result = _delta; \ | |
FT_END_STMNT | |
/* opaque handle to glyph-specific hints -- see `afhints.h' for more | |
* details | |
*/ | |
typedef struct AF_GlyphHintsRec_* AF_GlyphHints; | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/***** *****/ | |
/***** S C A L E R S *****/ | |
/***** *****/ | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/* | |
* A scaler models the target pixel device that will receive the | |
* auto-hinted glyph image. | |
*/ | |
#define AF_SCALER_FLAG_NO_HORIZONTAL 1U /* disable horizontal hinting */ | |
#define AF_SCALER_FLAG_NO_VERTICAL 2U /* disable vertical hinting */ | |
#define AF_SCALER_FLAG_NO_ADVANCE 4U /* disable advance hinting */ | |
#define AF_SCALER_FLAG_NO_WARPER 8U /* disable warper */ | |
typedef struct AF_ScalerRec_ | |
{ | |
FT_Face face; /* source font face */ | |
FT_Fixed x_scale; /* from font units to 1/64th device pixels */ | |
FT_Fixed y_scale; /* from font units to 1/64th device pixels */ | |
FT_Pos x_delta; /* in 1/64th device pixels */ | |
FT_Pos y_delta; /* in 1/64th device pixels */ | |
FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc. */ | |
FT_UInt32 flags; /* additional control flags, see above */ | |
} AF_ScalerRec, *AF_Scaler; | |
#define AF_SCALER_EQUAL_SCALES( a, b ) \ | |
( (a)->x_scale == (b)->x_scale && \ | |
(a)->y_scale == (b)->y_scale && \ | |
(a)->x_delta == (b)->x_delta && \ | |
(a)->y_delta == (b)->y_delta ) | |
typedef struct AF_StyleMetricsRec_* AF_StyleMetrics; | |
/* This function parses an FT_Face to compute global metrics for | |
* a specific style. | |
*/ | |
typedef FT_Error | |
(*AF_WritingSystem_InitMetricsFunc)( AF_StyleMetrics metrics, | |
FT_Face face ); | |
typedef void | |
(*AF_WritingSystem_ScaleMetricsFunc)( AF_StyleMetrics metrics, | |
AF_Scaler scaler ); | |
typedef void | |
(*AF_WritingSystem_DoneMetricsFunc)( AF_StyleMetrics metrics ); | |
typedef void | |
(*AF_WritingSystem_GetStdWidthsFunc)( AF_StyleMetrics metrics, | |
FT_Pos* stdHW, | |
FT_Pos* stdVW ); | |
typedef FT_Error | |
(*AF_WritingSystem_InitHintsFunc)( AF_GlyphHints hints, | |
AF_StyleMetrics metrics ); | |
typedef void | |
(*AF_WritingSystem_ApplyHintsFunc)( FT_UInt glyph_index, | |
AF_GlyphHints hints, | |
FT_Outline* outline, | |
AF_StyleMetrics metrics ); | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/***** *****/ | |
/***** W R I T I N G S Y S T E M S *****/ | |
/***** *****/ | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/* | |
* For the auto-hinter, a writing system consists of multiple scripts that | |
* can be handled similarly *in a typographical way*; the relationship is | |
* not based on history. For example, both the Greek and the unrelated | |
* Armenian scripts share the same features like ascender, descender, | |
* x-height, etc. Essentially, a writing system is covered by a | |
* submodule of the auto-fitter; it contains | |
* | |
* - a specific global analyzer that computes global metrics specific to | |
* the script (based on script-specific characters to identify ascender | |
* height, x-height, etc.), | |
* | |
* - a specific glyph analyzer that computes segments and edges for each | |
* glyph covered by the script, | |
* | |
* - a specific grid-fitting algorithm that distorts the scaled glyph | |
* outline according to the results of the glyph analyzer. | |
*/ | |
#define __AFWRTSYS_H__ /* don't load header files */ | |
#undef WRITING_SYSTEM | |
#define WRITING_SYSTEM( ws, WS ) \ | |
AF_WRITING_SYSTEM_ ## WS, | |
/* The list of known writing systems. */ | |
typedef enum AF_WritingSystem_ | |
{ | |
#include "afwrtsys.h" | |
AF_WRITING_SYSTEM_MAX /* do not remove */ | |
} AF_WritingSystem; | |
#undef __AFWRTSYS_H__ | |
typedef struct AF_WritingSystemClassRec_ | |
{ | |
AF_WritingSystem writing_system; | |
FT_Offset style_metrics_size; | |
AF_WritingSystem_InitMetricsFunc style_metrics_init; | |
AF_WritingSystem_ScaleMetricsFunc style_metrics_scale; | |
AF_WritingSystem_DoneMetricsFunc style_metrics_done; | |
AF_WritingSystem_GetStdWidthsFunc style_metrics_getstdw; | |
AF_WritingSystem_InitHintsFunc style_hints_init; | |
AF_WritingSystem_ApplyHintsFunc style_hints_apply; | |
} AF_WritingSystemClassRec; | |
typedef const AF_WritingSystemClassRec* AF_WritingSystemClass; | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/***** *****/ | |
/***** S C R I P T S *****/ | |
/***** *****/ | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/* | |
* Each script is associated with two sets of Unicode ranges to test | |
* whether the font face supports the script, and which non-base | |
* characters the script contains. | |
* | |
* We use four-letter script tags from the OpenType specification, | |
* extended by `NONE', which indicates `no script'. | |
*/ | |
#undef SCRIPT | |
#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \ | |
AF_SCRIPT_ ## S, | |
/* The list of known scripts. */ | |
typedef enum AF_Script_ | |
{ | |
#include "afscript.h" | |
AF_SCRIPT_MAX /* do not remove */ | |
} AF_Script; | |
typedef struct AF_Script_UniRangeRec_ | |
{ | |
FT_UInt32 first; | |
FT_UInt32 last; | |
} AF_Script_UniRangeRec; | |
#define AF_UNIRANGE_REC( a, b ) { (FT_UInt32)(a), (FT_UInt32)(b) } | |
typedef const AF_Script_UniRangeRec* AF_Script_UniRange; | |
typedef struct AF_ScriptClassRec_ | |
{ | |
AF_Script script; | |
/* last element in the ranges must be { 0, 0 } */ | |
AF_Script_UniRange script_uni_ranges; | |
AF_Script_UniRange script_uni_nonbase_ranges; | |
FT_UInt32 standard_char1; /* for default width and height */ | |
FT_UInt32 standard_char2; /* ditto */ | |
FT_UInt32 standard_char3; /* ditto */ | |
} AF_ScriptClassRec; | |
typedef const AF_ScriptClassRec* AF_ScriptClass; | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/***** *****/ | |
/***** C O V E R A G E S *****/ | |
/***** *****/ | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/* | |
* Usually, a font contains more glyphs than can be addressed by its | |
* character map. | |
* | |
* In the PostScript font world, encoding vectors specific to a given | |
* task are used to select such glyphs, and these glyphs can be often | |
* recognized by having a suffix in its glyph names. For example, a | |
* superscript glyph `A' might be called `A.sup'. Unfortunately, this | |
* naming scheme is not standardized and thus unusable for us. | |
* | |
* In the OpenType world, a better solution was invented, namely | |
* `features', which cleanly separate a character's input encoding from | |
* the corresponding glyph's appearance, and which don't use glyph names | |
* at all. For our purposes, and slightly generalized, an OpenType | |
* feature is a name of a mapping that maps character codes to | |
* non-standard glyph indices (features get used for other things also). | |
* For example, the `sups' feature provides superscript glyphs, thus | |
* mapping character codes like `A' or `B' to superscript glyph | |
* representation forms. How this mapping happens is completely | |
* uninteresting to us. | |
* | |
* For the auto-hinter, a `coverage' represents all glyphs of an OpenType | |
* feature collected in a set (as listed below) that can be hinted | |
* together. To continue the above example, superscript glyphs must not | |
* be hinted together with normal glyphs because the blue zones | |
* completely differ. | |
* | |
* Note that FreeType itself doesn't compute coverages; it only provides | |
* the glyphs addressable by the default Unicode character map. Instead, | |
* we use the HarfBuzz library (if available), which has many functions | |
* exactly for this purpose. | |
* | |
* AF_COVERAGE_DEFAULT is special: It should cover everything that isn't | |
* listed separately (including the glyphs addressable by the character | |
* map). In case HarfBuzz isn't available, it exactly covers the glyphs | |
* addressable by the character map. | |
* | |
*/ | |
#undef COVERAGE | |
#define COVERAGE( name, NAME, description, \ | |
tag1, tag2, tag3, tag4 ) \ | |
AF_COVERAGE_ ## NAME, | |
typedef enum AF_Coverage_ | |
{ | |
#include "afcover.h" | |
AF_COVERAGE_DEFAULT | |
} AF_Coverage; | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/***** *****/ | |
/***** S T Y L E S *****/ | |
/***** *****/ | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/* | |
* The topmost structure for modelling the auto-hinter glyph input data | |
* is a `style class', grouping everything together. | |
*/ | |
#undef STYLE | |
#define STYLE( s, S, d, ws, sc, ss, c ) \ | |
AF_STYLE_ ## S, | |
/* The list of known styles. */ | |
typedef enum AF_Style_ | |
{ | |
#include "afstyles.h" | |
AF_STYLE_MAX /* do not remove */ | |
} AF_Style; | |
typedef struct AF_StyleClassRec_ | |
{ | |
AF_Style style; | |
AF_WritingSystem writing_system; | |
AF_Script script; | |
AF_Blue_Stringset blue_stringset; | |
AF_Coverage coverage; | |
} AF_StyleClassRec; | |
typedef const AF_StyleClassRec* AF_StyleClass; | |
/*************************************************************************/ | |
/*************************************************************************/ | |
/***** *****/ | |
/***** S T Y L E M E T R I C S *****/ | |
/***** *****/ | |
/*************************************************************************/ | |
/*************************************************************************/ | |
typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals; | |
/* This is the main structure that combines everything. Autofit modules */ | |
/* specific to writing systems derive their structures from it, for */ | |
/* example `AF_LatinMetrics'. */ | |
typedef struct AF_StyleMetricsRec_ | |
{ | |
AF_StyleClass style_class; | |
AF_ScalerRec scaler; | |
FT_Bool digits_have_same_width; | |
AF_FaceGlobals globals; /* to access properties */ | |
} AF_StyleMetricsRec; | |
/* Declare and define vtables for classes */ | |
#ifndef FT_CONFIG_OPTION_PIC | |
#define AF_DECLARE_WRITING_SYSTEM_CLASS( writing_system_class ) \ | |
FT_CALLBACK_TABLE const AF_WritingSystemClassRec \ | |
writing_system_class; | |
#define AF_DEFINE_WRITING_SYSTEM_CLASS( \ | |
writing_system_class, \ | |
system, \ | |
m_size, \ | |
m_init, \ | |
m_scale, \ | |
m_done, \ | |
m_stdw, \ | |
h_init, \ | |
h_apply ) \ | |
FT_CALLBACK_TABLE_DEF \ | |
const AF_WritingSystemClassRec writing_system_class = \ | |
{ \ | |
system, \ | |
\ | |
m_size, \ | |
\ | |
m_init, \ | |
m_scale, \ | |
m_done, \ | |
m_stdw, \ | |
\ | |
h_init, \ | |
h_apply \ | |
}; | |
#define AF_DECLARE_SCRIPT_CLASS( script_class ) \ | |
FT_CALLBACK_TABLE const AF_ScriptClassRec \ | |
script_class; | |
#define AF_DEFINE_SCRIPT_CLASS( \ | |
script_class, \ | |
script, \ | |
ranges, \ | |
nonbase_ranges, \ | |
std_char1, \ | |
std_char2, \ | |
std_char3 ) \ | |
FT_CALLBACK_TABLE_DEF \ | |
const AF_ScriptClassRec script_class = \ | |
{ \ | |
script, \ | |
ranges, \ | |
nonbase_ranges, \ | |
std_char1, \ | |
std_char2, \ | |
std_char3 \ | |
}; | |
#define AF_DECLARE_STYLE_CLASS( style_class ) \ | |
FT_CALLBACK_TABLE const AF_StyleClassRec \ | |
style_class; | |
#define AF_DEFINE_STYLE_CLASS( \ | |
style_class, \ | |
style, \ | |
writing_system, \ | |
script, \ | |
blue_stringset, \ | |
coverage ) \ | |
FT_CALLBACK_TABLE_DEF \ | |
const AF_StyleClassRec style_class = \ | |
{ \ | |
style, \ | |
writing_system, \ | |
script, \ | |
blue_stringset, \ | |
coverage \ | |
}; | |
#else /* FT_CONFIG_OPTION_PIC */ | |
#define AF_DECLARE_WRITING_SYSTEM_CLASS( writing_system_class ) \ | |
FT_LOCAL( void ) \ | |
FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec* ac ); | |
#define AF_DEFINE_WRITING_SYSTEM_CLASS( \ | |
writing_system_class, \ | |
system, \ | |
m_size, \ | |
m_init, \ | |
m_scale, \ | |
m_done, \ | |
h_init, \ | |
h_apply ) \ | |
FT_LOCAL_DEF( void ) \ | |
FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec* ac ) \ | |
{ \ | |
ac->writing_system = system; \ | |
\ | |
ac->style_metrics_size = m_size; \ | |
\ | |
ac->style_metrics_init = m_init; \ | |
ac->style_metrics_scale = m_scale; \ | |
ac->style_metrics_done = m_done; \ | |
ac->style_metrics_getstdw = m_stdw; \ | |
\ | |
ac->style_hints_init = h_init; \ | |
ac->style_hints_apply = h_apply; \ | |
} | |
#define AF_DECLARE_SCRIPT_CLASS( script_class ) \ | |
FT_LOCAL( void ) \ | |
FT_Init_Class_ ## script_class( AF_ScriptClassRec* ac ); | |
#define AF_DEFINE_SCRIPT_CLASS( \ | |
script_class, \ | |
script_, \ | |
ranges, \ | |
nonbase_ranges, \ | |
std_char1, \ | |
std_char2, \ | |
std_char3 ) \ | |
FT_LOCAL_DEF( void ) \ | |
FT_Init_Class_ ## script_class( AF_ScriptClassRec* ac ) \ | |
{ \ | |
ac->script = script_; \ | |
ac->script_uni_ranges = ranges; \ | |
ac->script_uni_nonbase_ranges = nonbase_ranges; \ | |
ac->standard_char1 = std_char1; \ | |
ac->standard_char2 = std_char2; \ | |
ac->standard_char3 = std_char3; \ | |
} | |
#define AF_DECLARE_STYLE_CLASS( style_class ) \ | |
FT_LOCAL( void ) \ | |
FT_Init_Class_ ## style_class( AF_StyleClassRec* ac ); | |
#define AF_DEFINE_STYLE_CLASS( \ | |
style_class, \ | |
style_, \ | |
writing_system_, \ | |
script_, \ | |
blue_stringset_, \ | |
coverage_ ) \ | |
FT_LOCAL_DEF( void ) \ | |
FT_Init_Class_ ## style_class( AF_StyleClassRec* ac ) \ | |
{ \ | |
ac->style = style_; \ | |
ac->writing_system = writing_system_; \ | |
ac->script = script_; \ | |
ac->blue_stringset = blue_stringset_; \ | |
ac->coverage = coverage_; \ | |
} | |
#endif /* FT_CONFIG_OPTION_PIC */ | |
/* */ | |
FT_END_HEADER | |
#endif /* __AFTYPES_H__ */ | |
/* END */ |