FT_LOCAL_DEF FT_Error TT_CharMap_Load( TT_Face face, TT_CMapTable* cmap, FT_Stream stream ) { FT_Error error; FT_Memory memory; FT_UShort num_SH, num_Seg, i; FT_UShort u, l; TT_CMap0* cmap0; TT_CMap2* cmap2; TT_CMap4* cmap4; TT_CMap6* cmap6; TT_CMap2SubHeader* cmap2sub; TT_CMap4Segment* segments; if ( cmap->loaded ) return TT_Err_Ok; memory = stream->memory; if ( FILE_Seek( cmap->offset ) ) return error; switch ( cmap->format ) { case 0: cmap0 = &cmap->c.cmap0; if ( ALLOC( cmap0->glyphIdArray, 256L ) || FILE_Read( cmap0->glyphIdArray, 256L ) ) goto Fail; cmap->get_index = code_to_index0; break; case 2: num_SH = 0; cmap2 = &cmap->c.cmap2; /* allocate subheader keys */ if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, FT_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, TT_CMap2SubHeader ) || 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, FT_UShort ) || ACCESS_Frame( l * 2L ) ) goto Fail; for ( i = 0; i < l; i++ ) cmap2->glyphIdArray[i] = GET_UShort(); FORGET_Frame(); cmap->get_index = code_to_index2; 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, TT_CMap4Segment ) || 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, FT_UShort ) || ACCESS_Frame( l * 2L ) ) goto Fail; for ( i = 0; i < l; i++ ) cmap4->glyphIdArray[i] = GET_UShort(); FORGET_Frame(); cmap->get_index = code_to_index4; cmap4->last_segment = cmap4->segments; 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, FT_Short ) || ACCESS_Frame( l * 2L ) ) goto Fail; for ( i = 0; i < l; i++ ) cmap6->glyphIdArray[i] = GET_UShort(); FORGET_Frame(); cmap->get_index = code_to_index6; break; default: /* corrupt character mapping table */ return TT_Err_Invalid_CharMap_Format; } return TT_Err_Ok; Fail: TT_CharMap_Free( face, cmap ); return error; }
TT_CharMap_Load( 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_CharMap_Free( face, cmap ); return error; }