diff options
Diffstat (limited to 'Build/source/libs/libttf/ttcmap.c')
-rw-r--r-- | Build/source/libs/libttf/ttcmap.c | 503 |
1 files changed, 503 insertions, 0 deletions
diff --git a/Build/source/libs/libttf/ttcmap.c b/Build/source/libs/libttf/ttcmap.c new file mode 100644 index 00000000000..2dd58ece6d9 --- /dev/null +++ b/Build/source/libs/libttf/ttcmap.c @@ -0,0 +1,503 @@ +/******************************************************************* + * + * ttcmap.c 1.0 + * + * TrueType Character Mappings + * + * Copyright 1996-1999 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 "ttobjs.h" +#include "ttdebug.h" +#include "ttfile.h" +#include "ttmemory.h" +#include "ttload.h" +#include "ttcmap.h" + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_cmap + + +/******************************************************************* + * + * Function : CharMap_Load + * + * Description : Loads a given charmap into memory. + * + * Input : cmap pointer to cmap table + * + * Output : Error code. + * + * Notes : - Assumes the the stream is already used (opened). + * + * - In case of error, releases all partially allocated + * tables. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error CharMap_Load( PCMapTable cmap, + TT_Stream input ) + { + DEFINE_LOAD_LOCALS( input ); + + UShort num_SH, num_Seg, i; + + UShort u, l; + + PCMap0 cmap0; + PCMap2 cmap2; + PCMap4 cmap4; + PCMap6 cmap6; + + PCMap2SubHeader cmap2sub; + PCMap4Segment segments; + + + if ( cmap->loaded ) + return TT_Err_Ok; + + if ( FILE_Seek( cmap->offset ) ) + return error; + + switch ( cmap->format ) + { + case 0: + cmap0 = &cmap->c.cmap0; + + if ( ALLOC( cmap0->glyphIdArray, 256L ) || + FILE_Read( (void*)cmap0->glyphIdArray, 256L ) ) + goto Fail; + + break; + + case 2: + num_SH = 0; + cmap2 = &cmap->c.cmap2; + + /* allocate subheader keys */ + + if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, UShort ) || + ACCESS_Frame( 512L ) ) + goto Fail; + + for ( i = 0; i < 256; i++ ) + { + u = GET_UShort() / 8; + cmap2->subHeaderKeys[i] = u; + + if ( num_SH < u ) + num_SH = u; + } + + FORGET_Frame(); + + /* load subheaders */ + + cmap2->numGlyphId = l = + ( ( cmap->length - 2L * (256 + 3) - num_SH * 8L ) & 0xffff) / 2; + + if ( ALLOC_ARRAY( cmap2->subHeaders, + num_SH + 1, + TCMap2SubHeader ) || + ACCESS_Frame( ( num_SH + 1 ) * 8L ) ) + goto Fail; + + cmap2sub = cmap2->subHeaders; + + for ( i = 0; i <= num_SH; i++ ) + { + cmap2sub->firstCode = GET_UShort(); + cmap2sub->entryCount = GET_UShort(); + cmap2sub->idDelta = GET_Short(); + /* we apply the location offset immediately */ + cmap2sub->idRangeOffset = GET_UShort() - ( num_SH - i ) * 8 - 2; + + cmap2sub++; + } + + FORGET_Frame(); + + /* load glyph ids */ + + if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, UShort ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap2->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + break; + + case 4: + cmap4 = &cmap->c.cmap4; + + /* load header */ + + if ( ACCESS_Frame( 8L ) ) + goto Fail; + + cmap4->segCountX2 = GET_UShort(); + cmap4->searchRange = GET_UShort(); + cmap4->entrySelector = GET_UShort(); + cmap4->rangeShift = GET_UShort(); + + num_Seg = cmap4->segCountX2 / 2; + + FORGET_Frame(); + + /* load segments */ + + if ( ALLOC_ARRAY( cmap4->segments, + num_Seg, + TCMap4Segment ) || + ACCESS_Frame( (num_Seg * 4 + 1) * 2L ) ) + goto Fail; + + segments = cmap4->segments; + + for ( i = 0; i < num_Seg; i++ ) + segments[i].endCount = GET_UShort(); + + (void)GET_UShort(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].startCount = GET_UShort(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].idDelta = GET_Short(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].idRangeOffset = GET_UShort(); + + FORGET_Frame(); + + cmap4->numGlyphId = l = + ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xffff ) / 2; + + /* load ids */ + + if ( ALLOC_ARRAY( cmap4->glyphIdArray, l , UShort ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap4->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + break; + + case 6: + cmap6 = &cmap->c.cmap6; + + if ( ACCESS_Frame( 4L ) ) + goto Fail; + + cmap6->firstCode = GET_UShort(); + cmap6->entryCount = GET_UShort(); + + FORGET_Frame(); + + l = cmap6->entryCount; + + if ( ALLOC_ARRAY( cmap6->glyphIdArray, + cmap6->entryCount, + Short ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap6->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + break; + + default: /* corrupt character mapping table */ + return TT_Err_Invalid_CharMap_Format; + + } + return TT_Err_Ok; + + Fail: + CharMap_Free( cmap ); + return error; + } + + +/******************************************************************* + * + * Function : CharMap_Free + * + * Description : Releases a given charmap table. + * + * Input : cmap pointer to cmap table + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error CharMap_Free( PCMapTable cmap ) + { + if ( !cmap ) + return TT_Err_Ok; + + switch ( cmap->format ) + { + case 0: + FREE( cmap->c.cmap0.glyphIdArray ); + break; + + case 2: + FREE( cmap->c.cmap2.subHeaderKeys ); + FREE( cmap->c.cmap2.subHeaders ); + FREE( cmap->c.cmap2.glyphIdArray ); + break; + + case 4: + FREE( cmap->c.cmap4.segments ); + FREE( cmap->c.cmap4.glyphIdArray ); + cmap->c.cmap4.segCountX2 = 0; + break; + + case 6: + FREE( cmap->c.cmap6.glyphIdArray ); + cmap->c.cmap6.entryCount = 0; + break; + + default: + /* invalid table format, do nothing */ + ; + } + + cmap->loaded = FALSE; + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : CharMap_Index + * + * Description : Performs charcode->glyph index translation. + * + * Input : cmap pointer to cmap table + * + * Output : Glyph index, 0 in case of failure. + * + ******************************************************************/ + + static UShort code_to_index0( ULong charCode, PCMap0 cmap0 ); + static UShort code_to_index2( ULong charCode, PCMap2 cmap2 ); + static UShort code_to_index4( ULong charCode, PCMap4 cmap4 ); + static UShort code_to_index6( ULong charCode, PCMap6 cmap6 ); + + + LOCAL_FUNC + UShort CharMap_Index( PCMapTable cmap, + ULong charcode ) + { + switch ( cmap->format ) + { + case 0: + return code_to_index0( charcode, &cmap->c.cmap0 ); + case 2: + return code_to_index2( charcode, &cmap->c.cmap2 ); + case 4: + return code_to_index4( charcode, &cmap->c.cmap4 ); + case 6: + return code_to_index6( charcode, &cmap->c.cmap6 ); + default: + return 0; + } + } + + +/******************************************************************* + * + * Function : code_to_index0 + * + * Description : Converts the character code into a glyph index. + * Uses format 0. + * charCode will be masked to get a value in the range + * 0x00-0xFF. + * + * Input : charCode the wanted character code + * cmap0 a pointer to a cmap table in format 0 + * + * Output : Glyph index into the glyphs array. + * 0 if the glyph does not exist. + * + ******************************************************************/ + + static UShort code_to_index0( ULong charCode, + PCMap0 cmap0 ) + { + if ( charCode <= 0xFF ) + return cmap0->glyphIdArray[charCode]; + else + 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 + * + * Output : Glyph index into the glyphs array. + * 0 if the glyph does not exist. + * + ******************************************************************/ + + static UShort code_to_index2( ULong charCode, + PCMap2 cmap2 ) + { + UShort index1, idx, offset; + TCMap2SubHeader sh2; + + + index1 = cmap2->subHeaderKeys[charCode <= 0xFF ? + charCode : (charCode >> 8)]; + + if ( index1 == 0 ) + { + if ( charCode <= 0xFF ) + return cmap2->glyphIdArray[charCode]; /* 8bit character code */ + else + return 0; + } + else /* 16bit character code */ + { + if ( charCode <= 0xFF ) + return 0; + + sh2 = cmap2->subHeaders[index1]; + + if ( (charCode & 0xFF) < sh2.firstCode ) + return 0; + + if ( (charCode & 0xFF) >= (sh2.firstCode + sh2.entryCount) ) + return 0; + + offset = sh2.idRangeOffset / 2 + (charCode & 0xFF) - sh2.firstCode; + if ( offset < cmap2->numGlyphId ) + idx = cmap2->glyphIdArray[offset]; + else + return 0; + + if ( idx ) + return (idx + sh2.idDelta) & 0xFFFF; + else + 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 + * + * Output : Glyph index into the glyphs array. + * 0 if the glyph does not exist. + * + ******************************************************************/ + + static UShort code_to_index4( ULong charCode, + PCMap4 cmap4 ) + { + UShort index1, segCount; + UShort i; + TCMap4Segment seg4; + + + segCount = cmap4->segCountX2 / 2; + + for ( i = 0; i < segCount; i++ ) + if ( charCode <= cmap4->segments[i].endCount ) + break; + + /* Safety check - even though the last endCount should be 0xFFFF */ + if ( i >= segCount ) + return 0; + + seg4 = cmap4->segments[i]; + + if ( charCode < seg4.startCount ) + return 0; + + if ( seg4.idRangeOffset == 0 ) + return ( charCode + seg4.idDelta ) & 0xFFFF; + else + { + index1 = seg4.idRangeOffset / 2 + (charCode - seg4.startCount) - + (segCount - i); + + if ( index1 < cmap4->numGlyphId ) + { + if ( cmap4->glyphIdArray[index1] == 0 ) + return 0; + else + return ( cmap4->glyphIdArray[index1] + seg4.idDelta ) & 0xFFFF; + } + else + 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 + * + * Output : Glyph index into the glyphs array. + * 0 if the glyph does not exist (`missing character glyph'). + * + ******************************************************************/ + + static UShort code_to_index6( ULong charCode, + PCMap6 cmap6 ) + { + UShort firstCode; + + + firstCode = cmap6->firstCode; + + if ( charCode < firstCode ) + return 0; + + if ( charCode >= (firstCode + cmap6->entryCount) ) + return 0; + + return cmap6->glyphIdArray[charCode - firstCode]; + } + + +/* END */ |