1 /**************************************************************************** 2 * 3 * pfrcmap.c 4 * 5 * FreeType PFR cmap handling (body). 6 * 7 * Copyright (C) 2002-2023 by 8 * David Turner, Robert Wilhelm, and Werner Lemberg. 9 * 10 * This file is part of the FreeType project, and may only be used, 11 * modified, and distributed under the terms of the FreeType project 12 * license, LICENSE.TXT. By continuing to use, modify, or distribute 13 * this file you indicate that you have read the license and 14 * understand and accept it fully. 15 * 16 */ 17 18 19 #include <freetype/internal/ftdebug.h> 20 #include "pfrcmap.h" 21 #include "pfrobjs.h" 22 23 #include "pfrerror.h" 24 25 26 FT_CALLBACK_DEF( FT_Error ) pfr_cmap_init(PFR_CMap cmap,FT_Pointer pointer)27 pfr_cmap_init( PFR_CMap cmap, 28 FT_Pointer pointer ) 29 { 30 FT_Error error = FT_Err_Ok; 31 PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); 32 33 FT_UNUSED( pointer ); 34 35 36 cmap->num_chars = face->phy_font.num_chars; 37 cmap->chars = face->phy_font.chars; 38 39 /* just for safety, check that the character entries are correctly */ 40 /* sorted in increasing character code order */ 41 { 42 FT_UInt n; 43 44 45 for ( n = 1; n < cmap->num_chars; n++ ) 46 { 47 if ( cmap->chars[n - 1].char_code >= cmap->chars[n].char_code ) 48 { 49 error = FT_THROW( Invalid_Table ); 50 goto Exit; 51 } 52 } 53 } 54 55 Exit: 56 return error; 57 } 58 59 60 FT_CALLBACK_DEF( void ) pfr_cmap_done(PFR_CMap cmap)61 pfr_cmap_done( PFR_CMap cmap ) 62 { 63 cmap->chars = NULL; 64 cmap->num_chars = 0; 65 } 66 67 68 FT_CALLBACK_DEF( FT_UInt ) pfr_cmap_char_index(PFR_CMap cmap,FT_UInt32 char_code)69 pfr_cmap_char_index( PFR_CMap cmap, 70 FT_UInt32 char_code ) 71 { 72 FT_UInt min = 0; 73 FT_UInt max = cmap->num_chars; 74 FT_UInt mid = min + ( max - min ) / 2; 75 PFR_Char gchar; 76 77 78 while ( min < max ) 79 { 80 gchar = cmap->chars + mid; 81 82 if ( gchar->char_code == char_code ) 83 return mid + 1; 84 85 if ( gchar->char_code < char_code ) 86 min = mid + 1; 87 else 88 max = mid; 89 90 /* reasonable prediction in a continuous block */ 91 mid += char_code - gchar->char_code; 92 if ( mid >= max || mid < min ) 93 mid = min + ( max - min ) / 2; 94 } 95 return 0; 96 } 97 98 99 FT_CALLBACK_DEF( FT_UInt32 ) pfr_cmap_char_next(PFR_CMap cmap,FT_UInt32 * pchar_code)100 pfr_cmap_char_next( PFR_CMap cmap, 101 FT_UInt32 *pchar_code ) 102 { 103 FT_UInt result = 0; 104 FT_UInt32 char_code = *pchar_code + 1; 105 106 107 Restart: 108 { 109 FT_UInt min = 0; 110 FT_UInt max = cmap->num_chars; 111 FT_UInt mid = min + ( max - min ) / 2; 112 PFR_Char gchar; 113 114 115 while ( min < max ) 116 { 117 gchar = cmap->chars + mid; 118 119 if ( gchar->char_code == char_code ) 120 { 121 result = mid; 122 if ( result != 0 ) 123 { 124 result++; 125 goto Exit; 126 } 127 128 char_code++; 129 goto Restart; 130 } 131 132 if ( gchar->char_code < char_code ) 133 min = mid + 1; 134 else 135 max = mid; 136 137 /* reasonable prediction in a continuous block */ 138 mid += char_code - gchar->char_code; 139 if ( mid >= max || mid < min ) 140 mid = min + ( max - min ) / 2; 141 } 142 143 /* we didn't find it, but we have a pair just above it */ 144 char_code = 0; 145 146 if ( min < cmap->num_chars ) 147 { 148 gchar = cmap->chars + min; 149 result = min; 150 if ( result != 0 ) 151 { 152 result++; 153 char_code = gchar->char_code; 154 } 155 } 156 } 157 158 Exit: 159 *pchar_code = char_code; 160 return result; 161 } 162 163 164 FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec 165 pfr_cmap_class_rec = 166 { 167 sizeof ( PFR_CMapRec ), 168 169 (FT_CMap_InitFunc) pfr_cmap_init, /* init */ 170 (FT_CMap_DoneFunc) pfr_cmap_done, /* done */ 171 (FT_CMap_CharIndexFunc)pfr_cmap_char_index, /* char_index */ 172 (FT_CMap_CharNextFunc) pfr_cmap_char_next, /* char_next */ 173 174 (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ 175 (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ 176 (FT_CMap_VariantListFunc) NULL, /* variant_list */ 177 (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ 178 (FT_CMap_VariantCharListFunc) NULL /* variantchar_list */ 179 }; 180 181 182 /* END */ 183