1 /* Copyright (C) 1997, 2000 Aladdin Enterprises. All rights reserved. 2 3 This file is part of Aladdin Ghostscript. 4 5 Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author 6 or distributor accepts any responsibility for the consequences of using it, 7 or for whether it serves any particular purpose or works at all, unless he 8 or she says so in writing. Refer to the Aladdin Ghostscript Free Public 9 License (the "License") for full details. 10 11 Every copy of Aladdin Ghostscript must include a copy of the License, 12 normally in a plain ASCII text file named PUBLIC. The License grants you 13 the right to copy, modify and redistribute Aladdin Ghostscript, but only 14 under certain conditions described in the License. Among other things, the 15 License requires that the copyright notice and this notice be preserved on 16 all copies. 17 */ 18 19 /*$Id: gsfcmap.c,v 1.2 2000/03/10 07:03:09 lpd Exp $ */ 20 /* CMap character decoding */ 21 #include "gx.h" 22 #include "gserrors.h" 23 #include "gsstruct.h" 24 #include "gxfcmap.h" 25 26 /* CMap structure descriptors */ 27 public_st_cmap(); 28 public_st_code_map(); 29 public_st_code_map_element(); 30 31 /* Because code maps can be elements of arrays, */ 32 /* their enum_ptrs procedure must never return 0 prematurely. */ 33 private 34 ENUM_PTRS_WITH(code_map_enum_ptrs, gx_code_map *pcmap) return 0; 35 ENUM_PTR(0, gx_code_map, cmap); 36 case 1: 37 switch (pcmap->type) 38 { 39 case cmap_glyph: 40 (*pcmap->cmap->mark_glyph)(pcmap->data.glyph, 41 pcmap->cmap->mark_glyph_data); 42 default: 43 ENUM_RETURN(0); 44 case cmap_subtree: 45 ENUM_RETURN_PTR(gx_code_map, data.subtree); 46 } 47 ENUM_PTRS_END 48 private RELOC_PTRS_WITH(code_map_reloc_ptrs, gx_code_map *pcmap); 49 switch (pcmap->type) { 50 case cmap_subtree: 51 RELOC_PTR(gx_code_map, data.subtree); 52 break; 53 default: 54 ; 55 } 56 RELOC_PTR(gx_code_map, cmap); 57 RELOC_PTRS_END 58 59 /* CIDSystemInfo structure descriptors */ 60 private_st_cid_system_info(); 61 public_st_cid_system_info_element(); 62 63 /* ---------------- Procedures ---------------- */ 64 65 /* 66 * Decode a character from a string using a code map, updating the index. 67 * Return 0 for a CID or name, N > 0 for a character code where N is the 68 * number of bytes in the code, or an error. Shift the decoded bytes into 69 * *pchr. For undefined characters, set *pglyph = gs_no_glyph and return 0. 70 */ 71 private int 72 code_map_decode_next(const gx_code_map * pcmap, const gs_const_string * str, 73 uint * pindex, uint * pfidx, 74 gs_char * pchr, gs_glyph * pglyph) 75 { 76 const gx_code_map *map = pcmap; 77 uint chr = 0; 78 79 for (;;) { 80 int result; 81 82 if_debug1('J', "[J]cmap char = 0x%x: ", chr); 83 switch ((gx_code_map_type) map->type) { 84 case cmap_char_code: 85 if_debug0('J', "char code"); 86 *pglyph = (gs_glyph)map->data.ccode; 87 result = map->num_bytes1 + 1; 88 leaf: if (chr > map->last) 89 goto undef; 90 if (map->add_offset) 91 *pglyph += chr - map->first; 92 *pfidx = map->byte_data.font_index; 93 if_debug3('J', " 0x%lx, fidx %u, result %d\n", 94 *pglyph, *pfidx, result); 95 return result; 96 case cmap_glyph: 97 if_debug0('J', "glyph"); 98 *pglyph = map->data.glyph; 99 result = 0; 100 goto leaf; 101 case cmap_subtree: 102 if_debug0('J', "subtree\n"); 103 if (*pindex >= str->size) 104 return_error(gs_error_rangecheck); 105 chr = str->data[(*pindex)++]; 106 if (chr >= map->data.subtree[0].first) { 107 /* Invariant: map[lo].first <= chr < map[hi].first. */ 108 uint lo = 0, hi = map->byte_data.count1 + 1; 109 110 map = map->data.subtree; 111 while (lo + 1 < hi) { 112 uint mid = (lo + hi) >> 1; 113 114 if (chr >= map[mid].first) 115 lo = mid; 116 else 117 hi = mid; 118 } 119 *pchr = (*pchr << 8) | chr; 120 map = &map[lo]; 121 continue; 122 } 123 undef: if_debug0('J', " undef\n"); 124 *pchr = 0; 125 *pglyph = gs_no_glyph; 126 return 0; 127 default: /* (can't happen) */ 128 if_debug0('J', "error!\n"); 129 return_error(gs_error_invalidfont); 130 } 131 } 132 } 133 134 /* 135 * Decode a character from a string using a CMap. 136 * Return like code_map_decode_next. 137 */ 138 int 139 gs_cmap_decode_next(const gs_cmap * pcmap, const gs_const_string * str, 140 uint * pindex, uint * pfidx, 141 gs_char * pchr, gs_glyph * pglyph) 142 { 143 uint save_index = *pindex; 144 int code; 145 146 *pchr = 0; 147 code = 148 code_map_decode_next(&pcmap->def, str, pindex, pfidx, pchr, pglyph); 149 if (code != 0 || *pglyph != gs_no_glyph) 150 return code; 151 /* This is an undefined character. Use the notdef map. */ 152 { 153 uint next_index = *pindex; 154 155 *pindex = save_index; 156 *pchr = 0; 157 code = 158 code_map_decode_next(&pcmap->notdef, str, pindex, pfidx, 159 pchr, pglyph); 160 *pindex = next_index; 161 } 162 return code; 163 } 164