| /***************************************************************************/ |
| /* */ |
| /* pfrcmap.c */ |
| /* */ |
| /* FreeType PFR cmap handling (body). */ |
| /* */ |
| /* Copyright 2002, 2007, 2009 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 "pfrcmap.h" |
| #include "pfrobjs.h" |
| |
| #include "pfrerror.h" |
| |
| |
| FT_CALLBACK_DEF( FT_Error ) |
| pfr_cmap_init( PFR_CMap cmap ) |
| { |
| FT_Error error = PFR_Err_Ok; |
| PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); |
| |
| |
| cmap->num_chars = face->phy_font.num_chars; |
| cmap->chars = face->phy_font.chars; |
| |
| /* just for safety, check that the character entries are correctly */ |
| /* sorted in increasing character code order */ |
| { |
| FT_UInt n; |
| |
| |
| for ( n = 1; n < cmap->num_chars; n++ ) |
| { |
| if ( cmap->chars[n - 1].char_code >= cmap->chars[n].char_code ) |
| { |
| error = PFR_Err_Invalid_Table; |
| goto Exit; |
| } |
| } |
| } |
| |
| Exit: |
| return error; |
| } |
| |
| |
| FT_CALLBACK_DEF( void ) |
| pfr_cmap_done( PFR_CMap cmap ) |
| { |
| cmap->chars = NULL; |
| cmap->num_chars = 0; |
| } |
| |
| |
| FT_CALLBACK_DEF( FT_UInt ) |
| pfr_cmap_char_index( PFR_CMap cmap, |
| FT_UInt32 char_code ) |
| { |
| FT_UInt min = 0; |
| FT_UInt max = cmap->num_chars; |
| FT_UInt mid; |
| PFR_Char gchar; |
| |
| |
| while ( min < max ) |
| { |
| mid = min + ( max - min ) / 2; |
| gchar = cmap->chars + mid; |
| |
| if ( gchar->char_code == char_code ) |
| return mid + 1; |
| |
| if ( gchar->char_code < char_code ) |
| min = mid + 1; |
| else |
| max = mid; |
| } |
| return 0; |
| } |
| |
| |
| FT_CALLBACK_DEF( FT_UInt ) |
| pfr_cmap_char_next( PFR_CMap cmap, |
| FT_UInt32 *pchar_code ) |
| { |
| FT_UInt result = 0; |
| FT_UInt32 char_code = *pchar_code + 1; |
| |
| |
| Restart: |
| { |
| FT_UInt min = 0; |
| FT_UInt max = cmap->num_chars; |
| FT_UInt mid; |
| PFR_Char gchar; |
| |
| |
| while ( min < max ) |
| { |
| mid = min + ( ( max - min ) >> 1 ); |
| gchar = cmap->chars + mid; |
| |
| if ( gchar->char_code == char_code ) |
| { |
| result = mid; |
| if ( result != 0 ) |
| { |
| result++; |
| goto Exit; |
| } |
| |
| char_code++; |
| goto Restart; |
| } |
| |
| if ( gchar->char_code < char_code ) |
| min = mid+1; |
| else |
| max = mid; |
| } |
| |
| /* we didn't find it, but we have a pair just above it */ |
| char_code = 0; |
| |
| if ( min < cmap->num_chars ) |
| { |
| gchar = cmap->chars + min; |
| result = min; |
| if ( result != 0 ) |
| { |
| result++; |
| char_code = gchar->char_code; |
| } |
| } |
| } |
| |
| Exit: |
| *pchar_code = char_code; |
| return result; |
| } |
| |
| |
| FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec |
| pfr_cmap_class_rec = |
| { |
| sizeof ( PFR_CMapRec ), |
| |
| (FT_CMap_InitFunc) pfr_cmap_init, |
| (FT_CMap_DoneFunc) pfr_cmap_done, |
| (FT_CMap_CharIndexFunc)pfr_cmap_char_index, |
| (FT_CMap_CharNextFunc) pfr_cmap_char_next, |
| |
| NULL, NULL, NULL, NULL, NULL |
| }; |
| |
| |
| /* END */ |