contrib/OWB: add correct SDL dependency, fix compilers used
[AROS-Contrib.git] / freetype1 / lib / ttcmap.c
blob6b8596f3d9070662e8f0c214522f8e7b13d5376b
1 /*******************************************************************
3 * ttcmap.c 1.0
5 * TrueType Character Mappings
7 * Copyright 1996-1999 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
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.
16 ******************************************************************/
18 #include "ttobjs.h"
19 #include "ttdebug.h"
20 #include "ttfile.h"
21 #include "ttmemory.h"
22 #include "ttload.h"
23 #include "ttcmap.h"
25 /* required by the tracing mode */
26 #undef TT_COMPONENT
27 #define TT_COMPONENT trace_cmap
30 /*******************************************************************
32 * Function : CharMap_Load
34 * Description : Loads a given charmap into memory.
36 * Input : cmap pointer to cmap table
38 * Output : Error code.
40 * Notes : - Assumes the the stream is already used (opened).
42 * - In case of error, releases all partially allocated
43 * tables.
45 ******************************************************************/
47 LOCAL_FUNC
48 TT_Error CharMap_Load( PCMapTable cmap,
49 TT_Stream input )
51 DEFINE_LOAD_LOCALS( input );
53 UShort num_SH, num_Seg, i;
55 UShort u, l;
57 PCMap0 cmap0;
58 PCMap2 cmap2;
59 PCMap4 cmap4;
60 PCMap6 cmap6;
62 PCMap2SubHeader cmap2sub;
63 PCMap4Segment segments;
66 if ( cmap->loaded )
67 return TT_Err_Ok;
69 if ( FILE_Seek( cmap->offset ) )
70 return error;
72 switch ( cmap->format )
74 case 0:
75 cmap0 = &cmap->c.cmap0;
77 if ( ALLOC( cmap0->glyphIdArray, 256L ) ||
78 FILE_Read( (void*)cmap0->glyphIdArray, 256L ) )
79 goto Fail;
81 break;
83 case 2:
84 num_SH = 0;
85 cmap2 = &cmap->c.cmap2;
87 /* allocate subheader keys */
89 if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, UShort ) ||
90 ACCESS_Frame( 512L ) )
91 goto Fail;
93 for ( i = 0; i < 256; i++ )
95 u = GET_UShort() / 8;
96 cmap2->subHeaderKeys[i] = u;
98 if ( num_SH < u )
99 num_SH = u;
102 FORGET_Frame();
104 /* load subheaders */
106 cmap2->numGlyphId = l =
107 ( ( cmap->length - 2L * (256 + 3) - num_SH * 8L ) & 0xffff) / 2;
109 if ( ALLOC_ARRAY( cmap2->subHeaders,
110 num_SH + 1,
111 TCMap2SubHeader ) ||
112 ACCESS_Frame( ( num_SH + 1 ) * 8L ) )
113 goto Fail;
115 cmap2sub = cmap2->subHeaders;
117 for ( i = 0; i <= num_SH; i++ )
119 cmap2sub->firstCode = GET_UShort();
120 cmap2sub->entryCount = GET_UShort();
121 cmap2sub->idDelta = GET_Short();
122 /* we apply the location offset immediately */
123 cmap2sub->idRangeOffset = GET_UShort() - ( num_SH - i ) * 8 - 2;
125 cmap2sub++;
128 FORGET_Frame();
130 /* load glyph ids */
132 if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, UShort ) ||
133 ACCESS_Frame( l * 2L ) )
134 goto Fail;
136 for ( i = 0; i < l; i++ )
137 cmap2->glyphIdArray[i] = GET_UShort();
139 FORGET_Frame();
140 break;
142 case 4:
143 cmap4 = &cmap->c.cmap4;
145 /* load header */
147 if ( ACCESS_Frame( 8L ) )
148 goto Fail;
150 cmap4->segCountX2 = GET_UShort();
151 cmap4->searchRange = GET_UShort();
152 cmap4->entrySelector = GET_UShort();
153 cmap4->rangeShift = GET_UShort();
155 num_Seg = cmap4->segCountX2 / 2;
157 FORGET_Frame();
159 /* load segments */
161 if ( ALLOC_ARRAY( cmap4->segments,
162 num_Seg,
163 TCMap4Segment ) ||
164 ACCESS_Frame( (num_Seg * 4 + 1) * 2L ) )
165 goto Fail;
167 segments = cmap4->segments;
169 for ( i = 0; i < num_Seg; i++ )
170 segments[i].endCount = GET_UShort();
172 (void)GET_UShort();
174 for ( i = 0; i < num_Seg; i++ )
175 segments[i].startCount = GET_UShort();
177 for ( i = 0; i < num_Seg; i++ )
178 segments[i].idDelta = GET_Short();
180 for ( i = 0; i < num_Seg; i++ )
181 segments[i].idRangeOffset = GET_UShort();
183 FORGET_Frame();
185 cmap4->numGlyphId = l =
186 ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xffff ) / 2;
188 /* load ids */
190 if ( ALLOC_ARRAY( cmap4->glyphIdArray, l , UShort ) ||
191 ACCESS_Frame( l * 2L ) )
192 goto Fail;
194 for ( i = 0; i < l; i++ )
195 cmap4->glyphIdArray[i] = GET_UShort();
197 FORGET_Frame();
198 break;
200 case 6:
201 cmap6 = &cmap->c.cmap6;
203 if ( ACCESS_Frame( 4L ) )
204 goto Fail;
206 cmap6->firstCode = GET_UShort();
207 cmap6->entryCount = GET_UShort();
209 FORGET_Frame();
211 l = cmap6->entryCount;
213 if ( ALLOC_ARRAY( cmap6->glyphIdArray,
214 cmap6->entryCount,
215 Short ) ||
216 ACCESS_Frame( l * 2L ) )
217 goto Fail;
219 for ( i = 0; i < l; i++ )
220 cmap6->glyphIdArray[i] = GET_UShort();
222 FORGET_Frame();
223 break;
225 default: /* corrupt character mapping table */
226 return TT_Err_Invalid_CharMap_Format;
229 return TT_Err_Ok;
231 Fail:
232 CharMap_Free( cmap );
233 return error;
237 /*******************************************************************
239 * Function : CharMap_Free
241 * Description : Releases a given charmap table.
243 * Input : cmap pointer to cmap table
245 * Output : Error code.
247 ******************************************************************/
249 LOCAL_FUNC
250 TT_Error CharMap_Free( PCMapTable cmap )
252 if ( !cmap )
253 return TT_Err_Ok;
255 switch ( cmap->format )
257 case 0:
258 FREE( cmap->c.cmap0.glyphIdArray );
259 break;
261 case 2:
262 FREE( cmap->c.cmap2.subHeaderKeys );
263 FREE( cmap->c.cmap2.subHeaders );
264 FREE( cmap->c.cmap2.glyphIdArray );
265 break;
267 case 4:
268 FREE( cmap->c.cmap4.segments );
269 FREE( cmap->c.cmap4.glyphIdArray );
270 cmap->c.cmap4.segCountX2 = 0;
271 break;
273 case 6:
274 FREE( cmap->c.cmap6.glyphIdArray );
275 cmap->c.cmap6.entryCount = 0;
276 break;
278 default:
279 /* invalid table format, do nothing */
283 cmap->loaded = FALSE;
284 return TT_Err_Ok;
288 /*******************************************************************
290 * Function : CharMap_Index
292 * Description : Performs charcode->glyph index translation.
294 * Input : cmap pointer to cmap table
296 * Output : Glyph index, 0 in case of failure.
298 ******************************************************************/
300 static UShort code_to_index0( UShort charCode, PCMap0 cmap0 );
301 static UShort code_to_index2( UShort charCode, PCMap2 cmap2 );
302 static UShort code_to_index4( UShort charCode, PCMap4 cmap4 );
303 static UShort code_to_index6( UShort charCode, PCMap6 cmap6 );
306 LOCAL_FUNC
307 UShort CharMap_Index( PCMapTable cmap,
308 UShort charcode )
310 switch ( cmap->format )
312 case 0:
313 return code_to_index0( charcode, &cmap->c.cmap0 );
314 case 2:
315 return code_to_index2( charcode, &cmap->c.cmap2 );
316 case 4:
317 return code_to_index4( charcode, &cmap->c.cmap4 );
318 case 6:
319 return code_to_index6( charcode, &cmap->c.cmap6 );
320 default:
321 return 0;
326 /*******************************************************************
328 * Function : code_to_index0
330 * Description : Converts the character code into a glyph index.
331 * Uses format 0.
332 * charCode will be masked to get a value in the range
333 * 0x00-0xFF.
335 * Input : charCode the wanted character code
336 * cmap0 a pointer to a cmap table in format 0
338 * Output : Glyph index into the glyphs array.
339 * 0 if the glyph does not exist.
341 ******************************************************************/
343 static UShort code_to_index0( UShort charCode,
344 PCMap0 cmap0 )
346 if ( charCode <= 0xFF )
347 return cmap0->glyphIdArray[charCode];
348 else
349 return 0;
353 /*******************************************************************
355 * Function : code_to_index2
357 * Description : Converts the character code into a glyph index.
358 * Uses format 2.
360 * Input : charCode the wanted character code
361 * cmap2 a pointer to a cmap table in format 2
363 * Output : Glyph index into the glyphs array.
364 * 0 if the glyph does not exist.
366 ******************************************************************/
368 static UShort code_to_index2( UShort charCode,
369 PCMap2 cmap2 )
371 UShort index1, idx, offset;
372 TCMap2SubHeader sh2;
375 index1 = cmap2->subHeaderKeys[charCode <= 0xFF ?
376 charCode : (charCode >> 8)];
378 if ( index1 == 0 )
380 if ( charCode <= 0xFF )
381 return cmap2->glyphIdArray[charCode]; /* 8bit character code */
382 else
383 return 0;
385 else /* 16bit character code */
387 if ( charCode <= 0xFF )
388 return 0;
390 sh2 = cmap2->subHeaders[index1];
392 if ( (charCode & 0xFF) < sh2.firstCode )
393 return 0;
395 if ( (charCode & 0xFF) >= (sh2.firstCode + sh2.entryCount) )
396 return 0;
398 offset = sh2.idRangeOffset / 2 + (charCode & 0xFF) - sh2.firstCode;
399 if ( offset < cmap2->numGlyphId )
400 idx = cmap2->glyphIdArray[offset];
401 else
402 return 0;
404 if ( idx )
405 return (idx + sh2.idDelta) & 0xFFFF;
406 else
407 return 0;
412 /*******************************************************************
414 * Function : code_to_index4
416 * Description : Converts the character code into a glyph index.
417 * Uses format 4.
419 * Input : charCode the wanted character code
420 * cmap4 a pointer to a cmap table in format 4
422 * Output : Glyph index into the glyphs array.
423 * 0 if the glyph does not exist.
425 ******************************************************************/
427 static UShort code_to_index4( UShort charCode,
428 PCMap4 cmap4 )
430 UShort index1, segCount;
431 UShort i;
432 TCMap4Segment seg4;
435 segCount = cmap4->segCountX2 / 2;
437 for ( i = 0; i < segCount; i++ )
438 if ( charCode <= cmap4->segments[i].endCount )
439 break;
441 /* Safety check - even though the last endCount should be 0xFFFF */
442 if ( i >= segCount )
443 return 0;
445 seg4 = cmap4->segments[i];
447 if ( charCode < seg4.startCount )
448 return 0;
450 if ( seg4.idRangeOffset == 0 )
451 return ( charCode + seg4.idDelta ) & 0xFFFF;
452 else
454 index1 = seg4.idRangeOffset / 2 + (charCode - seg4.startCount) -
455 (segCount - i);
457 if ( index1 < cmap4->numGlyphId )
459 if ( cmap4->glyphIdArray[index1] == 0 )
460 return 0;
461 else
462 return ( cmap4->glyphIdArray[index1] + seg4.idDelta ) & 0xFFFF;
464 else
465 return 0;
470 /*******************************************************************
472 * Function : code_to_index6
474 * Description : Converts the character code into a glyph index.
475 * Uses format 6.
477 * Input : charCode the wanted character code
478 * cmap6 a pointer to a cmap table in format 6
480 * Output : Glyph index into the glyphs array.
481 * 0 if the glyph does not exist (`missing character glyph').
483 ******************************************************************/
485 static UShort code_to_index6( UShort charCode,
486 PCMap6 cmap6 )
488 UShort firstCode;
491 firstCode = cmap6->firstCode;
493 if ( charCode < firstCode )
494 return 0;
496 if ( charCode >= (firstCode + cmap6->entryCount) )
497 return 0;
499 return cmap6->glyphIdArray[charCode - firstCode];
503 /* END */