1 /*******************************************************************
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 ******************************************************************/
25 /* required by the tracing mode */
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
45 ******************************************************************/
48 TT_Error
CharMap_Load( PCMapTable cmap
,
51 DEFINE_LOAD_LOCALS( input
);
53 UShort num_SH
, num_Seg
, i
;
62 PCMap2SubHeader cmap2sub
;
63 PCMap4Segment segments
;
69 if ( FILE_Seek( cmap
->offset
) )
72 switch ( cmap
->format
)
75 cmap0
= &cmap
->c
.cmap0
;
77 if ( ALLOC( cmap0
->glyphIdArray
, 256L ) ||
78 FILE_Read( (void*)cmap0
->glyphIdArray
, 256L ) )
85 cmap2
= &cmap
->c
.cmap2
;
87 /* allocate subheader keys */
89 if ( ALLOC_ARRAY( cmap2
->subHeaderKeys
, 256, UShort
) ||
90 ACCESS_Frame( 512L ) )
93 for ( i
= 0; i
< 256; i
++ )
96 cmap2
->subHeaderKeys
[i
] = u
;
104 /* load subheaders */
106 cmap2
->numGlyphId
= l
=
107 ( ( cmap
->length
- 2L * (256 + 3) - num_SH
* 8L ) & 0xffff) / 2;
109 if ( ALLOC_ARRAY( cmap2
->subHeaders
,
112 ACCESS_Frame( ( num_SH
+ 1 ) * 8L ) )
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;
132 if ( ALLOC_ARRAY( cmap2
->glyphIdArray
, l
, UShort
) ||
133 ACCESS_Frame( l
* 2L ) )
136 for ( i
= 0; i
< l
; i
++ )
137 cmap2
->glyphIdArray
[i
] = GET_UShort();
143 cmap4
= &cmap
->c
.cmap4
;
147 if ( ACCESS_Frame( 8L ) )
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;
161 if ( ALLOC_ARRAY( cmap4
->segments
,
164 ACCESS_Frame( (num_Seg
* 4 + 1) * 2L ) )
167 segments
= cmap4
->segments
;
169 for ( i
= 0; i
< num_Seg
; i
++ )
170 segments
[i
].endCount
= 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();
185 cmap4
->numGlyphId
= l
=
186 ( ( cmap
->length
- ( 16L + 8L * num_Seg
) ) & 0xffff ) / 2;
190 if ( ALLOC_ARRAY( cmap4
->glyphIdArray
, l
, UShort
) ||
191 ACCESS_Frame( l
* 2L ) )
194 for ( i
= 0; i
< l
; i
++ )
195 cmap4
->glyphIdArray
[i
] = GET_UShort();
201 cmap6
= &cmap
->c
.cmap6
;
203 if ( ACCESS_Frame( 4L ) )
206 cmap6
->firstCode
= GET_UShort();
207 cmap6
->entryCount
= GET_UShort();
211 l
= cmap6
->entryCount
;
213 if ( ALLOC_ARRAY( cmap6
->glyphIdArray
,
216 ACCESS_Frame( l
* 2L ) )
219 for ( i
= 0; i
< l
; i
++ )
220 cmap6
->glyphIdArray
[i
] = GET_UShort();
225 default: /* corrupt character mapping table */
226 return TT_Err_Invalid_CharMap_Format
;
232 CharMap_Free( cmap
);
237 /*******************************************************************
239 * Function : CharMap_Free
241 * Description : Releases a given charmap table.
243 * Input : cmap pointer to cmap table
245 * Output : Error code.
247 ******************************************************************/
250 TT_Error
CharMap_Free( PCMapTable cmap
)
255 switch ( cmap
->format
)
258 FREE( cmap
->c
.cmap0
.glyphIdArray
);
262 FREE( cmap
->c
.cmap2
.subHeaderKeys
);
263 FREE( cmap
->c
.cmap2
.subHeaders
);
264 FREE( cmap
->c
.cmap2
.glyphIdArray
);
268 FREE( cmap
->c
.cmap4
.segments
);
269 FREE( cmap
->c
.cmap4
.glyphIdArray
);
270 cmap
->c
.cmap4
.segCountX2
= 0;
274 FREE( cmap
->c
.cmap6
.glyphIdArray
);
275 cmap
->c
.cmap6
.entryCount
= 0;
279 /* invalid table format, do nothing */
283 cmap
->loaded
= FALSE
;
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
);
307 UShort
CharMap_Index( PCMapTable cmap
,
310 switch ( cmap
->format
)
313 return code_to_index0( charcode
, &cmap
->c
.cmap0
);
315 return code_to_index2( charcode
, &cmap
->c
.cmap2
);
317 return code_to_index4( charcode
, &cmap
->c
.cmap4
);
319 return code_to_index6( charcode
, &cmap
->c
.cmap6
);
326 /*******************************************************************
328 * Function : code_to_index0
330 * Description : Converts the character code into a glyph index.
332 * charCode will be masked to get a value in the range
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
,
346 if ( charCode
<= 0xFF )
347 return cmap0
->glyphIdArray
[charCode
];
353 /*******************************************************************
355 * Function : code_to_index2
357 * Description : Converts the character code into a glyph index.
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
,
371 UShort index1
, idx
, offset
;
375 index1
= cmap2
->subHeaderKeys
[charCode
<= 0xFF ?
376 charCode
: (charCode
>> 8)];
380 if ( charCode
<= 0xFF )
381 return cmap2
->glyphIdArray
[charCode
]; /* 8bit character code */
385 else /* 16bit character code */
387 if ( charCode
<= 0xFF )
390 sh2
= cmap2
->subHeaders
[index1
];
392 if ( (charCode
& 0xFF) < sh2
.firstCode
)
395 if ( (charCode
& 0xFF) >= (sh2
.firstCode
+ sh2
.entryCount
) )
398 offset
= sh2
.idRangeOffset
/ 2 + (charCode
& 0xFF) - sh2
.firstCode
;
399 if ( offset
< cmap2
->numGlyphId
)
400 idx
= cmap2
->glyphIdArray
[offset
];
405 return (idx
+ sh2
.idDelta
) & 0xFFFF;
412 /*******************************************************************
414 * Function : code_to_index4
416 * Description : Converts the character code into a glyph index.
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
,
430 UShort index1
, segCount
;
435 segCount
= cmap4
->segCountX2
/ 2;
437 for ( i
= 0; i
< segCount
; i
++ )
438 if ( charCode
<= cmap4
->segments
[i
].endCount
)
441 /* Safety check - even though the last endCount should be 0xFFFF */
445 seg4
= cmap4
->segments
[i
];
447 if ( charCode
< seg4
.startCount
)
450 if ( seg4
.idRangeOffset
== 0 )
451 return ( charCode
+ seg4
.idDelta
) & 0xFFFF;
454 index1
= seg4
.idRangeOffset
/ 2 + (charCode
- seg4
.startCount
) -
457 if ( index1
< cmap4
->numGlyphId
)
459 if ( cmap4
->glyphIdArray
[index1
] == 0 )
462 return ( cmap4
->glyphIdArray
[index1
] + seg4
.idDelta
) & 0xFFFF;
470 /*******************************************************************
472 * Function : code_to_index6
474 * Description : Converts the character code into a glyph index.
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
,
491 firstCode
= cmap6
->firstCode
;
493 if ( charCode
< firstCode
)
496 if ( charCode
>= (firstCode
+ cmap6
->entryCount
) )
499 return cmap6
->glyphIdArray
[charCode
- firstCode
];