diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /libfreetype/ttcmap.c | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'libfreetype/ttcmap.c')
| -rw-r--r-- | libfreetype/ttcmap.c | 1110 |
1 files changed, 1110 insertions, 0 deletions
diff --git a/libfreetype/ttcmap.c b/libfreetype/ttcmap.c new file mode 100644 index 00000000..f6aabfee --- /dev/null +++ b/libfreetype/ttcmap.c @@ -0,0 +1,1110 @@ +/***************************************************************************/ +/* */ +/* ttcmap.c */ +/* */ +/* TrueType character mapping table (cmap) support (body). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include "ttload.h" +#include "ttcmap.h" + +#include "sferrors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttcmap + + + FT_CALLBACK_DEF( FT_UInt ) + code_to_index0( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_ULong ) + code_to_next0( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_UInt ) + code_to_index2( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_ULong ) + code_to_next2( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_UInt ) + code_to_index4( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_ULong ) + code_to_next4( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_UInt ) + code_to_index6( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_ULong ) + code_to_next6( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_UInt ) + code_to_index8_12( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_ULong ) + code_to_next8_12( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_UInt ) + code_to_index10( TT_CMapTable charmap, + FT_ULong char_code ); + + FT_CALLBACK_DEF( FT_ULong ) + code_to_next10( TT_CMapTable charmap, + FT_ULong char_code ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_charmap */ + /* */ + /* <Description> */ + /* Loads a given TrueType character map into memory. */ + /* */ + /* <Input> */ + /* face :: A handle to the parent face object. */ + /* */ + /* stream :: A handle to the current stream object. */ + /* */ + /* <InOut> */ + /* table :: A pointer to a cmap object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The function assumes that the stream is already in use (i.e., */ + /* opened). In case of error, all partially allocated tables are */ + /* released. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_charmap( TT_Face face, + TT_CMapTable cmap, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory; + FT_UShort num_SH, num_Seg, i; + FT_ULong j, n; + + FT_UShort u, l; + + TT_CMap0 cmap0; + TT_CMap2 cmap2; + TT_CMap4 cmap4; + TT_CMap6 cmap6; + TT_CMap8_12 cmap8_12; + TT_CMap10 cmap10; + + TT_CMap2SubHeader cmap2sub; + TT_CMap4Segment segments; + TT_CMapGroup groups; + + + if ( cmap->loaded ) + return SFNT_Err_Ok; + + memory = stream->memory; + + if ( FT_STREAM_SEEK( cmap->offset ) ) + return error; + + switch ( cmap->format ) + { + case 0: + cmap0 = &cmap->c.cmap0; + + if ( FT_READ_USHORT( cmap0->language ) || + FT_ALLOC( cmap0->glyphIdArray, 256L ) || + FT_STREAM_READ( cmap0->glyphIdArray, 256L ) ) + goto Fail; + + cmap->get_index = code_to_index0; + cmap->get_next_char = code_to_next0; + break; + + case 2: + num_SH = 0; + cmap2 = &cmap->c.cmap2; + + /* allocate subheader keys */ + + if ( FT_NEW_ARRAY( cmap2->subHeaderKeys, 256 ) || + FT_FRAME_ENTER( 2L + 512L ) ) + goto Fail; + + cmap2->language = FT_GET_USHORT(); + + for ( i = 0; i < 256; i++ ) + { + u = (FT_UShort)( FT_GET_USHORT() / 8 ); + cmap2->subHeaderKeys[i] = u; + + if ( num_SH < u ) + num_SH = u; + } + + FT_FRAME_EXIT(); + + /* load subheaders */ + + cmap2->numGlyphId = l = (FT_UShort)( + ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFFU ) / 2 ); + + if ( FT_NEW_ARRAY( cmap2->subHeaders, num_SH + 1 ) || + FT_FRAME_ENTER( ( num_SH + 1 ) * 8L ) ) + { + FT_FREE( cmap2->subHeaderKeys ); + goto Fail; + } + + cmap2sub = cmap2->subHeaders; + + for ( i = 0; i <= num_SH; i++ ) + { + cmap2sub->firstCode = FT_GET_USHORT(); + cmap2sub->entryCount = FT_GET_USHORT(); + cmap2sub->idDelta = FT_GET_SHORT(); + /* we apply the location offset immediately */ + cmap2sub->idRangeOffset = (FT_UShort)( + FT_GET_USHORT() - ( num_SH - i ) * 8 - 2 ); + + cmap2sub++; + } + + FT_FRAME_EXIT(); + + /* load glyph IDs */ + + if ( FT_NEW_ARRAY( cmap2->glyphIdArray, l ) || + FT_FRAME_ENTER( l * 2L ) ) + { + FT_FREE( cmap2->subHeaders ); + FT_FREE( cmap2->subHeaderKeys ); + goto Fail; + } + + for ( i = 0; i < l; i++ ) + cmap2->glyphIdArray[i] = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + + cmap->get_index = code_to_index2; + cmap->get_next_char = code_to_next2; + break; + + case 4: + cmap4 = &cmap->c.cmap4; + + /* load header */ + + if ( FT_FRAME_ENTER( 10L ) ) + goto Fail; + + cmap4->language = FT_GET_USHORT(); + cmap4->segCountX2 = FT_GET_USHORT(); + cmap4->searchRange = FT_GET_USHORT(); + cmap4->entrySelector = FT_GET_USHORT(); + cmap4->rangeShift = FT_GET_USHORT(); + + num_Seg = (FT_UShort)( cmap4->segCountX2 / 2 ); + + FT_FRAME_EXIT(); + + /* load segments */ + + if ( FT_NEW_ARRAY( cmap4->segments, num_Seg ) || + FT_FRAME_ENTER( ( num_Seg * 4 + 1 ) * 2L ) ) + goto Fail; + + segments = cmap4->segments; + + for ( i = 0; i < num_Seg; i++ ) + segments[i].endCount = FT_GET_USHORT(); + + (void)FT_GET_USHORT(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].startCount = FT_GET_USHORT(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].idDelta = FT_GET_SHORT(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].idRangeOffset = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + + cmap4->numGlyphId = l = (FT_UShort)( + ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFFU ) / 2 ); + + /* load IDs */ + + if ( FT_NEW_ARRAY( cmap4->glyphIdArray, l ) || + FT_FRAME_ENTER( l * 2L ) ) + { + FT_FREE( cmap4->segments ); + goto Fail; + } + + for ( i = 0; i < l; i++ ) + cmap4->glyphIdArray[i] = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + + cmap4->last_segment = cmap4->segments; + + cmap->get_index = code_to_index4; + cmap->get_next_char = code_to_next4; + break; + + case 6: + cmap6 = &cmap->c.cmap6; + + if ( FT_FRAME_ENTER( 6L ) ) + goto Fail; + + cmap6->language = FT_GET_USHORT(); + cmap6->firstCode = FT_GET_USHORT(); + cmap6->entryCount = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + + l = cmap6->entryCount; + + if ( FT_NEW_ARRAY( cmap6->glyphIdArray, l ) || + FT_FRAME_ENTER( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap6->glyphIdArray[i] = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + cmap->get_index = code_to_index6; + cmap->get_next_char = code_to_next6; + break; + + case 8: + case 12: + cmap8_12 = &cmap->c.cmap8_12; + + if ( FT_FRAME_ENTER( 8L ) ) + goto Fail; + + cmap->length = FT_GET_ULONG(); + cmap8_12->language = FT_GET_ULONG(); + + FT_FRAME_EXIT(); + + if ( cmap->format == 8 ) + if ( FT_STREAM_SKIP( 8192L ) ) + goto Fail; + + if ( FT_READ_ULONG( cmap8_12->nGroups ) ) + goto Fail; + + n = cmap8_12->nGroups; + + if ( FT_NEW_ARRAY( cmap8_12->groups, n ) || + FT_FRAME_ENTER( n * 3 * 4L ) ) + goto Fail; + + groups = cmap8_12->groups; + + for ( j = 0; j < n; j++ ) + { + groups[j].startCharCode = FT_GET_ULONG(); + groups[j].endCharCode = FT_GET_ULONG(); + groups[j].startGlyphID = FT_GET_ULONG(); + } + + FT_FRAME_EXIT(); + + cmap8_12->last_group = cmap8_12->groups; + + cmap->get_index = code_to_index8_12; + cmap->get_next_char = code_to_next8_12; + break; + + case 10: + cmap10 = &cmap->c.cmap10; + + if ( FT_FRAME_ENTER( 16L ) ) + goto Fail; + + cmap->length = FT_GET_ULONG(); + cmap10->language = FT_GET_ULONG(); + cmap10->startCharCode = FT_GET_ULONG(); + cmap10->numChars = FT_GET_ULONG(); + + FT_FRAME_EXIT(); + + n = cmap10->numChars; + + if ( FT_NEW_ARRAY( cmap10->glyphs, n ) || + FT_FRAME_ENTER( n * 2L ) ) + goto Fail; + + for ( j = 0; j < n; j++ ) + cmap10->glyphs[j] = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + cmap->get_index = code_to_index10; + cmap->get_next_char = code_to_next10; + break; + + default: /* corrupt character mapping table */ + return SFNT_Err_Invalid_CharMap_Format; + + } + + return SFNT_Err_Ok; + + Fail: + tt_face_free_charmap( face, cmap ); + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_free_charmap */ + /* */ + /* <Description> */ + /* Destroys a character mapping table. */ + /* */ + /* <Input> */ + /* face :: A handle to the parent face object. */ + /* */ + /* cmap :: A handle to a cmap object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_free_charmap( TT_Face face, + TT_CMapTable cmap ) + { + FT_Memory memory; + + + if ( !cmap ) + return SFNT_Err_Ok; + + memory = face->root.driver->root.memory; + + switch ( cmap->format ) + { + case 0: + FT_FREE( cmap->c.cmap0.glyphIdArray ); + break; + + case 2: + FT_FREE( cmap->c.cmap2.subHeaderKeys ); + FT_FREE( cmap->c.cmap2.subHeaders ); + FT_FREE( cmap->c.cmap2.glyphIdArray ); + break; + + case 4: + FT_FREE( cmap->c.cmap4.segments ); + FT_FREE( cmap->c.cmap4.glyphIdArray ); + cmap->c.cmap4.segCountX2 = 0; + break; + + case 6: + FT_FREE( cmap->c.cmap6.glyphIdArray ); + cmap->c.cmap6.entryCount = 0; + break; + + case 8: + case 12: + FT_FREE( cmap->c.cmap8_12.groups ); + cmap->c.cmap8_12.nGroups = 0; + break; + + case 10: + FT_FREE( cmap->c.cmap10.glyphs ); + cmap->c.cmap10.numChars = 0; + break; + + default: + /* invalid table format, do nothing */ + ; + } + + cmap->loaded = FALSE; + return SFNT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_index0 */ + /* */ + /* <Description> */ + /* Converts the character code into a glyph index. Uses format 0. */ + /* `charCode' must be in the range 0x00-0xFF (otherwise 0 is */ + /* returned). */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap0 :: A pointer to a cmap table in format 0. */ + /* */ + /* <Return> */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + FT_CALLBACK_DEF( FT_UInt ) + code_to_index0( TT_CMapTable cmap, + FT_ULong charCode ) + { + TT_CMap0 cmap0 = &cmap->c.cmap0; + + + return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_next0 */ + /* */ + /* <Description> */ + /* Finds the next encoded character after the given one. Uses */ + /* format 0. `charCode' must be in the range 0x00-0xFF (otherwise 0 */ + /* is returned). */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap0 :: A pointer to a cmap table in format 0. */ + /* */ + /* <Return> */ + /* Next char code. 0 if no higher one is encoded. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next0( TT_CMapTable cmap, + FT_ULong charCode ) + { + TT_CMap0 cmap0 = &cmap->c.cmap0; + + + while ( ++charCode <= 0xFF ) + if ( cmap0->glyphIdArray[charCode] ) + return ( charCode ); + return ( 0 ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_index2 */ + /* */ + /* <Description> */ + /* Converts the character code into a glyph index. Uses format 2. */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap2 :: A pointer to a cmap table in format 2. */ + /* */ + /* <Return> */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + FT_CALLBACK_DEF( FT_UInt ) + code_to_index2( TT_CMapTable cmap, + FT_ULong charCode ) + { + FT_UInt result, index1, offset; + FT_UInt char_lo; + FT_ULong char_hi; + TT_CMap2SubHeader sh2; + TT_CMap2 cmap2; + + + cmap2 = &cmap->c.cmap2; + result = 0; + char_lo = (FT_UInt)( charCode & 0xFF ); + char_hi = charCode >> 8; + + if ( char_hi == 0 ) + { + /* an 8-bit character code -- we use the subHeader 0 in this case */ + /* to test whether the character code is in the charmap */ + index1 = cmap2->subHeaderKeys[char_lo]; + if ( index1 != 0 ) + return 0; + } + else + { + /* a 16-bit character code */ + index1 = cmap2->subHeaderKeys[char_hi & 0xFF]; + if ( index1 == 0 ) + return 0; + } + + sh2 = cmap2->subHeaders + index1; + char_lo -= sh2->firstCode; + + if ( char_lo < (FT_UInt)sh2->entryCount ) + { + offset = sh2->idRangeOffset / 2 + char_lo; + if ( offset < (FT_UInt)cmap2->numGlyphId ) + { + result = cmap2->glyphIdArray[offset]; + if ( result ) + result = ( result + sh2->idDelta ) & 0xFFFFU; + } + } + + return result; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_next2 */ + /* */ + /* <Description> */ + /* Find the next encoded character. Uses format 2. */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap2 :: A pointer to a cmap table in format 2. */ + /* */ + /* <Return> */ + /* Next encoded character. 0 if none exists. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next2( TT_CMapTable cmap, + FT_ULong charCode ) + { + FT_UInt index1, offset; + FT_UInt char_lo; + FT_ULong char_hi; + TT_CMap2SubHeader sh2; + TT_CMap2 cmap2; + + + cmap2 = &cmap->c.cmap2; + charCode++; + + /* + * This is relatively simplistic -- look for a subHeader containing + * glyphs and then walk to the first glyph in that subHeader. + */ + while ( charCode < 0x10000L ) + { + char_lo = (FT_UInt)( charCode & 0xFF ); + char_hi = charCode >> 8; + + if ( char_hi == 0 ) + { + /* an 8-bit character code -- we use the subHeader 0 in this case */ + /* to test whether the character code is in the charmap */ + index1 = cmap2->subHeaderKeys[char_lo]; + if ( index1 != 0 ) + { + charCode++; + continue; + } + } + else + { + /* a 16-bit character code */ + index1 = cmap2->subHeaderKeys[char_hi & 0xFF]; + if ( index1 == 0 ) + { + charCode = ( char_hi + 1 ) << 8; + continue; + } + } + + sh2 = cmap2->subHeaders + index1; + char_lo -= sh2->firstCode; + + if ( char_lo > (FT_UInt)sh2->entryCount ) + { + charCode = ( char_hi + 1 ) << 8; + continue; + } + + offset = sh2->idRangeOffset / 2 + char_lo; + if ( offset >= (FT_UInt)cmap2->numGlyphId || + cmap2->glyphIdArray[offset] == 0 ) + { + charCode++; + continue; + } + + return charCode; + } + return 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_index4 */ + /* */ + /* <Description> */ + /* Converts the character code into a glyph index. Uses format 4. */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap4 :: A pointer to a cmap table in format 4. */ + /* */ + /* <Return> */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + FT_CALLBACK_DEF( FT_UInt ) + code_to_index4( TT_CMapTable cmap, + FT_ULong charCode ) + { + FT_UInt result, index1, segCount; + TT_CMap4 cmap4; + TT_CMap4SegmentRec *seg4, *limit; + + + cmap4 = &cmap->c.cmap4; + result = 0; + segCount = cmap4->segCountX2 / 2; + limit = cmap4->segments + segCount; + + /* first, check against the last used segment */ + + seg4 = cmap4->last_segment; + + /* the following is equivalent to performing two tests, as in */ + /* */ + /* if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */ + /* */ + /* This is a bit strange, but it is faster, and the idea behind the */ + /* cache is to significantly speed up charcode to glyph index */ + /* conversion. */ + + if ( (FT_ULong)( charCode - seg4->startCount ) < + (FT_ULong)( seg4->endCount - seg4->startCount ) ) + goto Found1; + + for ( seg4 = cmap4->segments; seg4 < limit; seg4++ ) + { + /* the ranges are sorted in increasing order. If we are out of */ + /* the range here, the char code isn't in the charmap, so exit. */ + + if ( charCode > (FT_UInt)seg4->endCount ) + continue; + + if ( charCode >= (FT_UInt)seg4->startCount ) + goto Found; + } + return 0; + + Found: + cmap4->last_segment = seg4; + + Found1: + /* if the idRangeOffset is 0, we can compute the glyph index */ + /* directly */ + + if ( seg4->idRangeOffset == 0 ) + result = (FT_UInt)( charCode + seg4->idDelta ) & 0xFFFFU; + else + { + /* otherwise, we must use the glyphIdArray to do it */ + index1 = (FT_UInt)( seg4->idRangeOffset / 2 + + ( charCode - seg4->startCount ) + + ( seg4 - cmap4->segments ) + - segCount ); + + if ( index1 < (FT_UInt)cmap4->numGlyphId && + cmap4->glyphIdArray[index1] != 0 ) + result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFFU; + } + + return result; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_next4 */ + /* */ + /* <Description> */ + /* Find the next encoded character. Uses format 4. */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap :: A pointer to a cmap table in format 4. */ + /* */ + /* <Return> */ + /* Next encoded character. 0 if none exists. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next4( TT_CMapTable cmap, + FT_ULong charCode ) + { + FT_UInt index1, segCount; + TT_CMap4 cmap4; + TT_CMap4SegmentRec *seg4, *limit; + + + cmap4 = &cmap->c.cmap4; + segCount = cmap4->segCountX2 / 2; + limit = cmap4->segments + segCount; + + charCode++; + + for ( seg4 = cmap4->segments; seg4 < limit; seg4++ ) + { + /* The ranges are sorted in increasing order. If we are out of */ + /* the range here, the char code isn't in the charmap, so exit. */ + + if ( charCode <= (FT_UInt)seg4->endCount ) + goto Found; + } + return 0; + + Found: + if ( charCode < (FT_ULong) seg4->startCount ) + charCode = seg4->startCount; + + /* if the idRangeOffset is 0, all chars in the map exist */ + + if ( seg4->idRangeOffset == 0 ) + return ( charCode ); + + while ( charCode <= (FT_UInt) seg4->endCount ) + { + /* otherwise, we must use the glyphIdArray to do it */ + index1 = (FT_UInt)( seg4->idRangeOffset / 2 + + ( charCode - seg4->startCount ) + + ( seg4 - cmap4->segments ) + - segCount ); + + if ( index1 < (FT_UInt)cmap4->numGlyphId && + cmap4->glyphIdArray[index1] != 0 ) + return ( charCode ); + charCode++; + } + + return 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_index6 */ + /* */ + /* <Description> */ + /* Converts the character code into a glyph index. Uses format 6. */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap6 :: A pointer to a cmap table in format 6. */ + /* */ + /* <Return> */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + FT_CALLBACK_DEF( FT_UInt ) + code_to_index6( TT_CMapTable cmap, + FT_ULong charCode ) + { + TT_CMap6 cmap6; + FT_UInt result = 0; + + + cmap6 = &cmap->c.cmap6; + charCode -= cmap6->firstCode; + + if ( charCode < (FT_UInt)cmap6->entryCount ) + result = cmap6->glyphIdArray[charCode]; + + return result; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_next6 */ + /* */ + /* <Description> */ + /* Find the next encoded character. Uses format 6. */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap :: A pointer to a cmap table in format 6. */ + /* */ + /* <Return> */ + /* Next encoded character. 0 if none exists. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next6( TT_CMapTable cmap, + FT_ULong charCode ) + { + TT_CMap6 cmap6; + + + charCode++; + + cmap6 = &cmap->c.cmap6; + + if ( charCode < (FT_ULong) cmap6->firstCode ) + charCode = cmap6->firstCode; + + charCode -= cmap6->firstCode; + + while ( charCode < (FT_UInt)cmap6->entryCount ) + { + if ( cmap6->glyphIdArray[charCode] != 0 ) + return charCode + cmap6->firstCode; + charCode++; + } + + return 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_index8_12 */ + /* */ + /* <Description> */ + /* Converts the (possibly 32bit) character code into a glyph index. */ + /* Uses format 8 or 12. */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap8_12 :: A pointer to a cmap table in format 8 or 12. */ + /* */ + /* <Return> */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + FT_CALLBACK_DEF( FT_UInt ) + code_to_index8_12( TT_CMapTable cmap, + FT_ULong charCode ) + { + TT_CMap8_12 cmap8_12; + TT_CMapGroupRec *group, *limit; + + + cmap8_12 = &cmap->c.cmap8_12; + limit = cmap8_12->groups + cmap8_12->nGroups; + + /* first, check against the last used group */ + + group = cmap8_12->last_group; + + /* the following is equivalent to performing two tests, as in */ + /* */ + /* if ( charCode >= group->startCharCode && */ + /* charCode <= group->endCharCode ) */ + /* */ + /* This is a bit strange, but it is faster, and the idea behind the */ + /* cache is to significantly speed up charcode to glyph index */ + /* conversion. */ + + if ( (FT_ULong)( charCode - group->startCharCode ) < + (FT_ULong)( group->endCharCode - group->startCharCode ) ) + goto Found1; + + for ( group = cmap8_12->groups; group < limit; group++ ) + { + /* the ranges are sorted in increasing order. If we are out of */ + /* the range here, the char code isn't in the charmap, so exit. */ + + if ( charCode > group->endCharCode ) + continue; + + if ( charCode >= group->startCharCode ) + goto Found; + } + return 0; + + Found: + cmap8_12->last_group = group; + + Found1: + return (FT_UInt)( group->startGlyphID + + ( charCode - group->startCharCode ) ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_next8_12 */ + /* */ + /* <Description> */ + /* Find the next encoded character. Uses format 8 or 12. */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap :: A pointer to a cmap table in format 8 or 12. */ + /* */ + /* <Return> */ + /* Next encoded character. 0 if none exists. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next8_12( TT_CMapTable cmap, + FT_ULong charCode ) + { + TT_CMap8_12 cmap8_12; + TT_CMapGroupRec *group, *limit; + + + charCode++; + cmap8_12 = &cmap->c.cmap8_12; + limit = cmap8_12->groups + cmap8_12->nGroups; + + for ( group = cmap8_12->groups; group < limit; group++ ) + { + /* the ranges are sorted in increasing order. If we are out of */ + /* the range here, the char code isn't in the charmap, so exit. */ + + if ( charCode <= group->endCharCode ) + goto Found; + } + return 0; + + Found: + if ( charCode < group->startCharCode ) + charCode = group->startCharCode; + + return charCode; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_index10 */ + /* */ + /* <Description> */ + /* Converts the (possibly 32bit) character code into a glyph index. */ + /* Uses format 10. */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap10 :: A pointer to a cmap table in format 10. */ + /* */ + /* <Return> */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + FT_CALLBACK_DEF( FT_UInt ) + code_to_index10( TT_CMapTable cmap, + FT_ULong charCode ) + { + TT_CMap10 cmap10; + FT_UInt result = 0; + + + cmap10 = &cmap->c.cmap10; + charCode -= cmap10->startCharCode; + + /* the overflow trick for comparison works here also since the number */ + /* of glyphs (even if numChars is specified as ULong in the specs) in */ + /* an OpenType font is limited to 64k */ + + if ( charCode < cmap10->numChars ) + result = cmap10->glyphs[charCode]; + + return result; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* code_to_next10 */ + /* */ + /* <Description> */ + /* Find the next encoded character. Uses format 10. */ + /* */ + /* <Input> */ + /* charCode :: The wanted character code. */ + /* */ + /* cmap :: A pointer to a cmap table in format 10. */ + /* */ + /* <Return> */ + /* Next encoded character. 0 if none exists. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next10( TT_CMapTable cmap, + FT_ULong charCode ) + { + TT_CMap10 cmap10; + + + charCode++; + cmap10 = &cmap->c.cmap10; + + if ( charCode < cmap10->startCharCode ) + charCode = cmap10->startCharCode; + + charCode -= cmap10->startCharCode; + + /* the overflow trick for comparison works here also since the number */ + /* of glyphs (even if numChars is specified as ULong in the specs) in */ + /* an OpenType font is limited to 64k */ + + while ( charCode < cmap10->numChars ) + { + if ( cmap10->glyphs[charCode] ) + return ( charCode + cmap10->startCharCode ); + charCode++; + } + + return 0; + } + + +/* END */ |
