/**************************************************************************** * * ttcmap.c * * TrueType character mapping table (cmap) support (body). * * Copyright (C) 2002-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 "sferrors.h" /* must come before `ftvalid.h' */ #include <freetype/internal/ftvalid.h> #include <freetype/internal/ftstream.h> #include <freetype/internal/services/svpscmap.h> #include "ttload.h" #include "ttcmap.h" #include "ttpost.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 … #define TT_PEEK_SHORT … #define TT_PEEK_USHORT … #define TT_PEEK_UINT24 … #define TT_PEEK_LONG … #define TT_PEEK_ULONG … #define TT_NEXT_SHORT … #define TT_NEXT_USHORT … #define TT_NEXT_UINT24 … #define TT_NEXT_LONG … #define TT_NEXT_ULONG … /* Too large glyph index return values are caught in `FT_Get_Char_Index' */ /* and `FT_Get_Next_Char' (the latter calls the internal `next' function */ /* again in this case). To mark character code return values as invalid */ /* it is sufficient to set the corresponding glyph index return value to */ /* zero. */ FT_CALLBACK_DEF( FT_Error ) tt_cmap_init( FT_CMap cmap, /* TT_CMap */ void* table_ ) { … } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 0 *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * TABLE OVERVIEW * -------------- * * NAME OFFSET TYPE DESCRIPTION * * format 0 USHORT must be 0 * length 2 USHORT table length in bytes * language 4 USHORT Mac language code * glyph_ids 6 BYTE[256] array of glyph indices * 262 */ #ifdef TT_CONFIG_CMAP_FORMAT_0 FT_CALLBACK_DEF( FT_Error ) tt_cmap0_validate( FT_Byte* table, FT_Validator valid ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap0_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap0_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap0_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { … } FT_DEFINE_TT_CMAP( tt_cmap0_class_rec, sizeof ( TT_CMapRec ), (FT_CMap_InitFunc) tt_cmap_init, /* init */ (FT_CMap_DoneFunc) NULL, /* done */ (FT_CMap_CharIndexFunc)tt_cmap0_char_index, /* char_index */ (FT_CMap_CharNextFunc) tt_cmap0_char_next, /* char_next */ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ (FT_CMap_VariantListFunc) NULL, /* variant_list */ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ 0, (TT_CMap_ValidateFunc)tt_cmap0_validate, /* validate */ (TT_CMap_Info_GetFunc)tt_cmap0_get_info /* get_cmap_info */ ) #endif /* TT_CONFIG_CMAP_FORMAT_0 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 2 *****/ /***** *****/ /***** This is used for certain CJK encodings that encode text in a *****/ /***** mixed 8/16 bits encoding along the following lines. *****/ /***** *****/ /***** * Certain byte values correspond to an 8-bit character code *****/ /***** (typically in the range 0..127 for ASCII compatibility). *****/ /***** *****/ /***** * Certain byte values signal the first byte of a 2-byte *****/ /***** character code (but these values are also valid as the *****/ /***** second byte of a 2-byte character). *****/ /***** *****/ /***** The following charmap lookup and iteration functions all *****/ /***** assume that the value `charcode' fulfills the following. *****/ /***** *****/ /***** - For one-byte characters, `charcode' is simply the *****/ /***** character code. *****/ /***** *****/ /***** - For two-byte characters, `charcode' is the 2-byte *****/ /***** character code in big endian format. More precisely: *****/ /***** *****/ /***** (charcode >> 8) is the first byte value *****/ /***** (charcode & 0xFF) is the second byte value *****/ /***** *****/ /***** Note that not all values of `charcode' are valid according *****/ /***** to these rules, and the function moderately checks the *****/ /***** arguments. *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * TABLE OVERVIEW * -------------- * * NAME OFFSET TYPE DESCRIPTION * * format 0 USHORT must be 2 * length 2 USHORT table length in bytes * language 4 USHORT Mac language code * keys 6 USHORT[256] sub-header keys * subs 518 SUBHEAD[NSUBS] sub-headers array * glyph_ids 518+NSUB*8 USHORT[] glyph ID array * * The `keys' table is used to map charcode high bytes to sub-headers. * The value of `NSUBS' is the number of sub-headers defined in the * table and is computed by finding the maximum of the `keys' table. * * Note that for any `n', `keys[n]' is a byte offset within the `subs' * table, i.e., it is the corresponding sub-header index multiplied * by 8. * * Each sub-header has the following format. * * NAME OFFSET TYPE DESCRIPTION * * first 0 USHORT first valid low-byte * count 2 USHORT number of valid low-bytes * delta 4 SHORT see below * offset 6 USHORT see below * * A sub-header defines, for each high byte, the range of valid * low bytes within the charmap. Note that the range defined by `first' * and `count' must be completely included in the interval [0..255] * according to the specification. * * If a character code is contained within a given sub-header, then * mapping it to a glyph index is done as follows. * * - The value of `offset' is read. This is a _byte_ distance from the * location of the `offset' field itself into a slice of the * `glyph_ids' table. Let's call it `slice' (it is a USHORT[], too). * * - The value `slice[char.lo - first]' is read. If it is 0, there is * no glyph for the charcode. Otherwise, the value of `delta' is * added to it (modulo 65536) to form a new glyph index. * * It is up to the validation routine to check that all offsets fall * within the glyph IDs table (and not within the `subs' table itself or * outside of the CMap). */ #ifdef TT_CONFIG_CMAP_FORMAT_2 FT_CALLBACK_DEF( FT_Error ) tt_cmap2_validate( FT_Byte* table, FT_Validator valid ) { … } /* return sub header corresponding to a given character code */ /* NULL on invalid charcode */ static FT_Byte* tt_cmap2_get_subheader( FT_Byte* table, FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap2_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap2_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pcharcode ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap2_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { … } FT_DEFINE_TT_CMAP( tt_cmap2_class_rec, sizeof ( TT_CMapRec ), (FT_CMap_InitFunc) tt_cmap_init, /* init */ (FT_CMap_DoneFunc) NULL, /* done */ (FT_CMap_CharIndexFunc)tt_cmap2_char_index, /* char_index */ (FT_CMap_CharNextFunc) tt_cmap2_char_next, /* char_next */ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ (FT_CMap_VariantListFunc) NULL, /* variant_list */ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ 2, (TT_CMap_ValidateFunc)tt_cmap2_validate, /* validate */ (TT_CMap_Info_GetFunc)tt_cmap2_get_info /* get_cmap_info */ ) #endif /* TT_CONFIG_CMAP_FORMAT_2 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 4 *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * TABLE OVERVIEW * -------------- * * NAME OFFSET TYPE DESCRIPTION * * format 0 USHORT must be 4 * length 2 USHORT table length * in bytes * language 4 USHORT Mac language code * * segCountX2 6 USHORT 2*NUM_SEGS * searchRange 8 USHORT 2*(1 << LOG_SEGS) * entrySelector 10 USHORT LOG_SEGS * rangeShift 12 USHORT segCountX2 - * searchRange * * endCount 14 USHORT[NUM_SEGS] end charcode for * each segment; last * is 0xFFFF * * pad 14+NUM_SEGS*2 USHORT padding * * startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for * each segment * * idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each * segment * idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for * each segment; can be * zero * * glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID * ranges * * Character codes are modelled by a series of ordered (increasing) * intervals called segments. Each segment has start and end codes, * provided by the `startCount' and `endCount' arrays. Segments must * not overlap, and the last segment should always contain the value * 0xFFFF for `endCount'. * * The fields `searchRange', `entrySelector' and `rangeShift' are better * ignored (they are traces of over-engineering in the TrueType * specification). * * Each segment also has a signed `delta', as well as an optional offset * within the `glyphIds' table. * * If a segment's idOffset is 0, the glyph index corresponding to any * charcode within the segment is obtained by adding the value of * `idDelta' directly to the charcode, modulo 65536. * * Otherwise, a glyph index is taken from the glyph IDs sub-array for * the segment, and the value of `idDelta' is added to it. * * * Finally, note that a lot of fonts contain an invalid last segment, * where `start' and `end' are correctly set to 0xFFFF but both `delta' * and `offset' are incorrect (e.g., `opens___.ttf' which comes with * OpenOffice.org). We need special code to deal with them correctly. */ #ifdef TT_CONFIG_CMAP_FORMAT_4 TT_CMap4; FT_CALLBACK_DEF( FT_Error ) tt_cmap4_init( FT_CMap cmap, /* TT_CMap4 */ void* table_ ) { … } static FT_Int tt_cmap4_set_range( TT_CMap4 cmap, FT_UInt range_index ) { … } /* search the index of the charcode next to cmap->cur_charcode; */ /* caller should call tt_cmap4_set_range with proper range */ /* before calling this function */ /* */ static void tt_cmap4_next( TT_CMap4 cmap ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap4_validate( FT_Byte* table, FT_Validator valid ) { … } static FT_UInt tt_cmap4_char_map_linear( TT_CMap cmap, FT_UInt32* pcharcode, FT_Bool next ) { … } static FT_UInt tt_cmap4_char_map_binary( TT_CMap cmap, FT_UInt32* pcharcode, FT_Bool next ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap4_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap4_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap4_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { … } FT_DEFINE_TT_CMAP( tt_cmap4_class_rec, sizeof ( TT_CMap4Rec ), (FT_CMap_InitFunc) tt_cmap4_init, /* init */ (FT_CMap_DoneFunc) NULL, /* done */ (FT_CMap_CharIndexFunc)tt_cmap4_char_index, /* char_index */ (FT_CMap_CharNextFunc) tt_cmap4_char_next, /* char_next */ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ (FT_CMap_VariantListFunc) NULL, /* variant_list */ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ 4, (TT_CMap_ValidateFunc)tt_cmap4_validate, /* validate */ (TT_CMap_Info_GetFunc)tt_cmap4_get_info /* get_cmap_info */ ) #endif /* TT_CONFIG_CMAP_FORMAT_4 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 6 *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * TABLE OVERVIEW * -------------- * * NAME OFFSET TYPE DESCRIPTION * * format 0 USHORT must be 6 * length 2 USHORT table length in bytes * language 4 USHORT Mac language code * * first 6 USHORT first segment code * count 8 USHORT segment size in chars * glyphIds 10 USHORT[count] glyph IDs * * A very simplified segment mapping. */ #ifdef TT_CONFIG_CMAP_FORMAT_6 FT_CALLBACK_DEF( FT_Error ) tt_cmap6_validate( FT_Byte* table, FT_Validator valid ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap6_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap6_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap6_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { … } FT_DEFINE_TT_CMAP( tt_cmap6_class_rec, sizeof ( TT_CMapRec ), (FT_CMap_InitFunc) tt_cmap_init, /* init */ (FT_CMap_DoneFunc) NULL, /* done */ (FT_CMap_CharIndexFunc)tt_cmap6_char_index, /* char_index */ (FT_CMap_CharNextFunc) tt_cmap6_char_next, /* char_next */ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ (FT_CMap_VariantListFunc) NULL, /* variant_list */ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ 6, (TT_CMap_ValidateFunc)tt_cmap6_validate, /* validate */ (TT_CMap_Info_GetFunc)tt_cmap6_get_info /* get_cmap_info */ ) #endif /* TT_CONFIG_CMAP_FORMAT_6 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 8 *****/ /***** *****/ /***** It is hard to completely understand what the OpenType spec *****/ /***** says about this format, but here is my conclusion. *****/ /***** *****/ /***** The purpose of this format is to easily map UTF-16 text to *****/ /***** glyph indices. Basically, the `char_code' must be in one of *****/ /***** the following formats. *****/ /***** *****/ /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/ /***** Area (i.e. U+D800-U+DFFF). *****/ /***** *****/ /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/ /***** `char_code = (char_hi << 16) | char_lo', then both *****/ /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/ /***** Area. *****/ /***** *****/ /***** The `is32' table embedded in the charmap indicates whether a *****/ /***** given 16-bit value is in the surrogates area or not. *****/ /***** *****/ /***** So, for any given `char_code', we can assert the following. *****/ /***** *****/ /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/ /***** *****/ /***** If `char_hi != 0' then we must have both *****/ /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * TABLE OVERVIEW * -------------- * * NAME OFFSET TYPE DESCRIPTION * * format 0 USHORT must be 8 * reserved 2 USHORT reserved * length 4 ULONG length in bytes * language 8 ULONG Mac language code * is32 12 BYTE[8192] 32-bitness bitmap * count 8204 ULONG number of groups * * This header is followed by `count' groups of the following format: * * start 0 ULONG first charcode * end 4 ULONG last charcode * startId 8 ULONG start glyph ID for the group */ #ifdef TT_CONFIG_CMAP_FORMAT_8 FT_CALLBACK_DEF( FT_Error ) tt_cmap8_validate( FT_Byte* table, FT_Validator valid ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap8_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap8_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap8_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { … } FT_DEFINE_TT_CMAP( tt_cmap8_class_rec, sizeof ( TT_CMapRec ), (FT_CMap_InitFunc) tt_cmap_init, /* init */ (FT_CMap_DoneFunc) NULL, /* done */ (FT_CMap_CharIndexFunc)tt_cmap8_char_index, /* char_index */ (FT_CMap_CharNextFunc) tt_cmap8_char_next, /* char_next */ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ (FT_CMap_VariantListFunc) NULL, /* variant_list */ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ 8, (TT_CMap_ValidateFunc)tt_cmap8_validate, /* validate */ (TT_CMap_Info_GetFunc)tt_cmap8_get_info /* get_cmap_info */ ) #endif /* TT_CONFIG_CMAP_FORMAT_8 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 10 *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * TABLE OVERVIEW * -------------- * * NAME OFFSET TYPE DESCRIPTION * * format 0 USHORT must be 10 * reserved 2 USHORT reserved * length 4 ULONG length in bytes * language 8 ULONG Mac language code * * start 12 ULONG first char in range * count 16 ULONG number of chars in range * glyphIds 20 USHORT[count] glyph indices covered */ #ifdef TT_CONFIG_CMAP_FORMAT_10 FT_CALLBACK_DEF( FT_Error ) tt_cmap10_validate( FT_Byte* table, FT_Validator valid ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap10_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap10_char_next( FT_CMap cmap, /* TT_CMap */ FT_UInt32 *pchar_code ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap10_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { … } FT_DEFINE_TT_CMAP( tt_cmap10_class_rec, sizeof ( TT_CMapRec ), (FT_CMap_InitFunc) tt_cmap_init, /* init */ (FT_CMap_DoneFunc) NULL, /* done */ (FT_CMap_CharIndexFunc)tt_cmap10_char_index, /* char_index */ (FT_CMap_CharNextFunc) tt_cmap10_char_next, /* char_next */ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ (FT_CMap_VariantListFunc) NULL, /* variant_list */ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ 10, (TT_CMap_ValidateFunc)tt_cmap10_validate, /* validate */ (TT_CMap_Info_GetFunc)tt_cmap10_get_info /* get_cmap_info */ ) #endif /* TT_CONFIG_CMAP_FORMAT_10 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 12 *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * TABLE OVERVIEW * -------------- * * NAME OFFSET TYPE DESCRIPTION * * format 0 USHORT must be 12 * reserved 2 USHORT reserved * length 4 ULONG length in bytes * language 8 ULONG Mac language code * count 12 ULONG number of groups * 16 * * This header is followed by `count' groups of the following format: * * start 0 ULONG first charcode * end 4 ULONG last charcode * startId 8 ULONG start glyph ID for the group */ #ifdef TT_CONFIG_CMAP_FORMAT_12 TT_CMap12; FT_CALLBACK_DEF( FT_Error ) tt_cmap12_init( FT_CMap cmap, /* TT_CMap12 */ void* table_ ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap12_validate( FT_Byte* table, FT_Validator valid ) { … } /* search the index of the charcode next to cmap->cur_charcode */ /* cmap->cur_group should be set up properly by caller */ /* */ static void tt_cmap12_next( FT_CMap cmap ) /* TT_CMap12 */ { … } static FT_UInt tt_cmap12_char_map_binary( TT_CMap cmap, FT_UInt32* pchar_code, FT_Bool next ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap12_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap12_char_next( FT_CMap cmap, /* TT_CMap12 */ FT_UInt32 *pchar_code ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap12_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { … } FT_DEFINE_TT_CMAP( tt_cmap12_class_rec, sizeof ( TT_CMap12Rec ), (FT_CMap_InitFunc) tt_cmap12_init, /* init */ (FT_CMap_DoneFunc) NULL, /* done */ (FT_CMap_CharIndexFunc)tt_cmap12_char_index, /* char_index */ (FT_CMap_CharNextFunc) tt_cmap12_char_next, /* char_next */ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ (FT_CMap_VariantListFunc) NULL, /* variant_list */ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ 12, (TT_CMap_ValidateFunc)tt_cmap12_validate, /* validate */ (TT_CMap_Info_GetFunc)tt_cmap12_get_info /* get_cmap_info */ ) #endif /* TT_CONFIG_CMAP_FORMAT_12 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 13 *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * TABLE OVERVIEW * -------------- * * NAME OFFSET TYPE DESCRIPTION * * format 0 USHORT must be 13 * reserved 2 USHORT reserved * length 4 ULONG length in bytes * language 8 ULONG Mac language code * count 12 ULONG number of groups * 16 * * This header is followed by `count' groups of the following format: * * start 0 ULONG first charcode * end 4 ULONG last charcode * glyphId 8 ULONG glyph ID for the whole group */ #ifdef TT_CONFIG_CMAP_FORMAT_13 TT_CMap13; FT_CALLBACK_DEF( FT_Error ) tt_cmap13_init( FT_CMap cmap, /* TT_CMap13 */ void* table_ ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap13_validate( FT_Byte* table, FT_Validator valid ) { … } /* search the index of the charcode next to cmap->cur_charcode */ /* cmap->cur_group should be set up properly by caller */ /* */ static void tt_cmap13_next( FT_CMap cmap ) /* TT_CMap13 */ { … } static FT_UInt tt_cmap13_char_map_binary( TT_CMap cmap, FT_UInt32* pchar_code, FT_Bool next ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap13_char_index( FT_CMap cmap, /* TT_CMap */ FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap13_char_next( FT_CMap cmap, /* TT_CMap13 */ FT_UInt32 *pchar_code ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap13_get_info( FT_CharMap cmap, /* TT_CMap */ TT_CMapInfo *cmap_info ) { … } FT_DEFINE_TT_CMAP( tt_cmap13_class_rec, sizeof ( TT_CMap13Rec ), (FT_CMap_InitFunc) tt_cmap13_init, /* init */ (FT_CMap_DoneFunc) NULL, /* done */ (FT_CMap_CharIndexFunc)tt_cmap13_char_index, /* char_index */ (FT_CMap_CharNextFunc) tt_cmap13_char_next, /* char_next */ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ (FT_CMap_VariantListFunc) NULL, /* variant_list */ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ 13, (TT_CMap_ValidateFunc)tt_cmap13_validate, /* validate */ (TT_CMap_Info_GetFunc)tt_cmap13_get_info /* get_cmap_info */ ) #endif /* TT_CONFIG_CMAP_FORMAT_13 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 14 *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * TABLE OVERVIEW * -------------- * * NAME OFFSET TYPE DESCRIPTION * * format 0 USHORT must be 14 * length 2 ULONG table length in bytes * numSelector 6 ULONG number of variation sel. records * * Followed by numSelector records, each of which looks like * * varSelector 0 UINT24 Unicode codepoint of sel. * defaultOff 3 ULONG offset to a default UVS table * describing any variants to be found in * the normal Unicode subtable. * nonDefOff 7 ULONG offset to a non-default UVS table * describing any variants not in the * standard cmap, with GIDs here * (either offset may be 0 NULL) * * Selectors are sorted by code point. * * A default Unicode Variation Selector (UVS) subtable is just a list of * ranges of code points which are to be found in the standard cmap. No * glyph IDs (GIDs) here. * * numRanges 0 ULONG number of ranges following * * A range looks like * * uniStart 0 UINT24 code point of the first character in * this range * additionalCnt 3 UBYTE count of additional characters in this * range (zero means a range of a single * character) * * Ranges are sorted by `uniStart'. * * A non-default Unicode Variation Selector (UVS) subtable is a list of * mappings from codepoint to GID. * * numMappings 0 ULONG number of mappings * * A range looks like * * uniStart 0 UINT24 code point of the first character in * this range * GID 3 USHORT and its GID * * Ranges are sorted by `uniStart'. */ #ifdef TT_CONFIG_CMAP_FORMAT_14 TT_CMap14; FT_CALLBACK_DEF( void ) tt_cmap14_done( FT_CMap cmap ) /* TT_CMap14 */ { … } static FT_Error tt_cmap14_ensure( TT_CMap14 cmap, FT_UInt32 num_results, FT_Memory memory ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap14_init( FT_CMap cmap, /* TT_CMap14 */ void* table_ ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap14_validate( FT_Byte* table, FT_Validator valid ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap14_char_index( FT_CMap cmap, FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap14_char_next( FT_CMap cmap, FT_UInt32 *pchar_code ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap14_get_info( FT_CharMap cmap, TT_CMapInfo *cmap_info ) { … } static FT_UInt tt_cmap14_char_map_def_binary( FT_Byte *base, FT_UInt32 char_code ) { … } static FT_UInt tt_cmap14_char_map_nondef_binary( FT_Byte *base, FT_UInt32 char_code ) { … } static FT_Byte* tt_cmap14_find_variant( FT_Byte *base, FT_UInt32 variantCode ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap14_char_var_index( FT_CMap cmap, /* TT_CMap */ FT_CMap ucmap, /* TT_CMap */ FT_UInt32 charcode, FT_UInt32 variantSelector ) { … } FT_CALLBACK_DEF( FT_Int ) tt_cmap14_char_var_isdefault( FT_CMap cmap, /* TT_CMap */ FT_UInt32 charcode, FT_UInt32 variantSelector ) { … } FT_CALLBACK_DEF( FT_UInt32* ) tt_cmap14_variants( FT_CMap cmap, /* TT_CMap14 */ FT_Memory memory ) { … } FT_CALLBACK_DEF( FT_UInt32 * ) tt_cmap14_char_variants( FT_CMap cmap, /* TT_CMap14 */ FT_Memory memory, FT_UInt32 charCode ) { … } static FT_UInt tt_cmap14_def_char_count( FT_Byte *p ) { … } static FT_UInt32* tt_cmap14_get_def_chars( TT_CMap cmap, FT_Byte* p, FT_Memory memory ) { … } static FT_UInt32* tt_cmap14_get_nondef_chars( TT_CMap cmap, FT_Byte *p, FT_Memory memory ) { … } FT_CALLBACK_DEF( FT_UInt32 * ) tt_cmap14_variant_chars( FT_CMap cmap, /* TT_CMap */ FT_Memory memory, FT_UInt32 variantSelector ) { … } FT_DEFINE_TT_CMAP( tt_cmap14_class_rec, sizeof ( TT_CMap14Rec ), (FT_CMap_InitFunc) tt_cmap14_init, /* init */ (FT_CMap_DoneFunc) tt_cmap14_done, /* done */ (FT_CMap_CharIndexFunc)tt_cmap14_char_index, /* char_index */ (FT_CMap_CharNextFunc) tt_cmap14_char_next, /* char_next */ /* Format 14 extension functions */ (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index, (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault, (FT_CMap_VariantListFunc) tt_cmap14_variants, (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants, (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars, 14, (TT_CMap_ValidateFunc)tt_cmap14_validate, /* validate */ (TT_CMap_Info_GetFunc)tt_cmap14_get_info /* get_cmap_info */ ) #endif /* TT_CONFIG_CMAP_FORMAT_14 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** SYNTHETIC UNICODE *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /* This charmap is generated using postscript glyph names. */ #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES FT_CALLBACK_DEF( const char * ) tt_get_glyph_name( void* face_, /* TT_Face */ FT_UInt idx ) { … } FT_CALLBACK_DEF( FT_Error ) tt_cmap_unicode_init( FT_CMap cmap, /* PS_Unicodes */ FT_Pointer pointer ) { … } FT_CALLBACK_DEF( void ) tt_cmap_unicode_done( FT_CMap cmap ) /* PS_Unicodes */ { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap_unicode_char_index( FT_CMap cmap, /* PS_Unicodes */ FT_UInt32 char_code ) { … } FT_CALLBACK_DEF( FT_UInt ) tt_cmap_unicode_char_next( FT_CMap cmap, /* PS_Unicodes */ FT_UInt32 *pchar_code ) { … } FT_DEFINE_TT_CMAP( tt_cmap_unicode_class_rec, sizeof ( PS_UnicodesRec ), (FT_CMap_InitFunc) tt_cmap_unicode_init, /* init */ (FT_CMap_DoneFunc) tt_cmap_unicode_done, /* done */ (FT_CMap_CharIndexFunc)tt_cmap_unicode_char_index, /* char_index */ (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next, /* char_next */ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ (FT_CMap_VariantListFunc) NULL, /* variant_list */ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ ~0U, (TT_CMap_ValidateFunc)NULL, /* validate */ (TT_CMap_Info_GetFunc)NULL /* get_cmap_info */ ) #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ static const TT_CMap_Class tt_cmap_classes[] = …; /* parse the `cmap' table and build the corresponding TT_CMap objects */ /* in the current face */ /* */ FT_LOCAL_DEF( FT_Error ) tt_face_build_cmaps( TT_Face face ) { … } FT_LOCAL_DEF( FT_Error ) tt_get_cmap_info( FT_CharMap charmap, TT_CMapInfo *cmap_info ) { … } /* END */