OLD | NEW |
1 /***************************************************************************/ | 1 /***************************************************************************/ |
2 /* */ | 2 /* */ |
3 /* ttsbit.c */ | 3 /* ttsbit.c */ |
4 /* */ | 4 /* */ |
5 /* TrueType and OpenType embedded bitmap support (body). */ | 5 /* TrueType and OpenType embedded bitmap support (body). */ |
6 /* */ | 6 /* */ |
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ | 7 /* Copyright 2005-2009, 2013 by */ |
8 /* 2010 by */ | |
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
10 /* */ | 9 /* */ |
| 10 /* Copyright 2013 by Google, Inc. */ |
| 11 /* Google Author(s): Behdad Esfahbod. */ |
| 12 /* */ |
11 /* This file is part of the FreeType project, and may only be used, */ | 13 /* This file is part of the FreeType project, and may only be used, */ |
12 /* modified, and distributed under the terms of the FreeType project */ | 14 /* modified, and distributed under the terms of the FreeType project */ |
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | 15 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
14 /* this file you indicate that you have read the license and */ | 16 /* this file you indicate that you have read the license and */ |
15 /* understand and accept it fully. */ | 17 /* understand and accept it fully. */ |
16 /* */ | 18 /* */ |
17 /***************************************************************************/ | 19 /***************************************************************************/ |
18 | 20 |
| 21 |
19 #include <ft2build.h> | 22 #include <ft2build.h> |
20 #include FT_INTERNAL_DEBUG_H | 23 #include FT_INTERNAL_DEBUG_H |
21 #include FT_INTERNAL_STREAM_H | 24 #include FT_INTERNAL_STREAM_H |
22 #include FT_TRUETYPE_TAGS_H | 25 #include FT_TRUETYPE_TAGS_H |
23 | 26 #include FT_BITMAP_H |
24 /* | |
25 * Alas, the memory-optimized sbit loader can't be used when implementing | |
26 * the `old internals' hack | |
27 */ | |
28 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS | |
29 | |
30 #include "ttsbit0.c" | |
31 | |
32 #else /* FT_CONFIG_OPTION_OLD_INTERNALS */ | |
33 | |
34 #include <ft2build.h> | |
35 #include FT_INTERNAL_DEBUG_H | |
36 #include FT_INTERNAL_STREAM_H | |
37 #include FT_TRUETYPE_TAGS_H | |
38 #include "ttsbit.h" | 27 #include "ttsbit.h" |
39 | 28 |
40 #include "sferrors.h" | 29 #include "sferrors.h" |
41 | 30 |
| 31 #include "pngshim.h" |
| 32 |
42 | 33 |
43 /*************************************************************************/ | 34 /*************************************************************************/ |
44 /* */ | 35 /* */ |
45 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | 36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
46 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | 37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
47 /* messages during execution. */ | 38 /* messages during execution. */ |
48 /* */ | 39 /* */ |
49 #undef FT_COMPONENT | 40 #undef FT_COMPONENT |
50 #define FT_COMPONENT trace_ttsbit | 41 #define FT_COMPONENT trace_ttsbit |
51 | 42 |
52 | 43 |
53 /*************************************************************************/ | |
54 /* */ | |
55 /* <Function> */ | |
56 /* blit_sbit */ | |
57 /* */ | |
58 /* <Description> */ | |
59 /* Blits a bitmap from an input stream into a given target. Supports */ | |
60 /* x and y offsets as well as byte padded lines. */ | |
61 /* */ | |
62 /* <Input> */ | |
63 /* target :: The target bitmap/pixmap. */ | |
64 /* */ | |
65 /* source :: The input packed bitmap data. */ | |
66 /* */ | |
67 /* line_bits :: The number of bits per line. */ | |
68 /* */ | |
69 /* byte_padded :: A flag which is true if lines are byte-padded. */ | |
70 /* */ | |
71 /* x_offset :: The horizontal offset. */ | |
72 /* */ | |
73 /* y_offset :: The vertical offset. */ | |
74 /* */ | |
75 /* <Note> */ | |
76 /* IMPORTANT: The x and y offsets are relative to the top corner of */ | |
77 /* the target bitmap (unlike the normal TrueType */ | |
78 /* convention). A positive y offset indicates a downwards */ | |
79 /* direction! */ | |
80 /* */ | |
81 static void | |
82 blit_sbit( FT_Bitmap* target, | |
83 FT_Byte* source, | |
84 FT_Int line_bits, | |
85 FT_Bool byte_padded, | |
86 FT_Int x_offset, | |
87 FT_Int y_offset, | |
88 FT_Int source_height ) | |
89 { | |
90 FT_Byte* line_buff; | |
91 FT_Int line_incr; | |
92 FT_Int height; | |
93 | |
94 FT_UShort acc; | |
95 FT_UInt loaded; | |
96 | |
97 | |
98 /* first of all, compute starting write position */ | |
99 line_incr = target->pitch; | |
100 line_buff = target->buffer; | |
101 | |
102 if ( line_incr < 0 ) | |
103 line_buff -= line_incr * ( target->rows - 1 ); | |
104 | |
105 line_buff += ( x_offset >> 3 ) + y_offset * line_incr; | |
106 | |
107 /***********************************************************************/ | |
108 /* */ | |
109 /* We use the extra-classic `accumulator' trick to extract the bits */ | |
110 /* from the source byte stream. */ | |
111 /* */ | |
112 /* Namely, the variable `acc' is a 16-bit accumulator containing the */ | |
113 /* last `loaded' bits from the input stream. The bits are shifted to */ | |
114 /* the upmost position in `acc'. */ | |
115 /* */ | |
116 /***********************************************************************/ | |
117 | |
118 acc = 0; /* clear accumulator */ | |
119 loaded = 0; /* no bits were loaded */ | |
120 | |
121 for ( height = source_height; height > 0; height-- ) | |
122 { | |
123 FT_Byte* cur = line_buff; /* current write cursor */ | |
124 FT_Int count = line_bits; /* # of bits to extract per line */ | |
125 FT_Byte shift = (FT_Byte)( x_offset & 7 ); /* current write shift */ | |
126 FT_Byte space = (FT_Byte)( 8 - shift ); | |
127 | |
128 | |
129 /* first of all, read individual source bytes */ | |
130 if ( count >= 8 ) | |
131 { | |
132 count -= 8; | |
133 { | |
134 do | |
135 { | |
136 FT_Byte val; | |
137 | |
138 | |
139 /* ensure that there are at least 8 bits in the accumulator */ | |
140 if ( loaded < 8 ) | |
141 { | |
142 acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded )); | |
143 loaded += 8; | |
144 } | |
145 | |
146 /* now write one byte */ | |
147 val = (FT_Byte)( acc >> 8 ); | |
148 if ( shift ) | |
149 { | |
150 cur[0] |= (FT_Byte)( val >> shift ); | |
151 cur[1] |= (FT_Byte)( val << space ); | |
152 } | |
153 else | |
154 cur[0] |= val; | |
155 | |
156 cur++; | |
157 acc <<= 8; /* remove bits from accumulator */ | |
158 loaded -= 8; | |
159 count -= 8; | |
160 | |
161 } while ( count >= 0 ); | |
162 } | |
163 | |
164 /* restore `count' to correct value */ | |
165 count += 8; | |
166 } | |
167 | |
168 /* now write remaining bits (count < 8) */ | |
169 if ( count > 0 ) | |
170 { | |
171 FT_Byte val; | |
172 | |
173 | |
174 /* ensure that there are at least `count' bits in the accumulator */ | |
175 if ( (FT_Int)loaded < count ) | |
176 { | |
177 acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded )); | |
178 loaded += 8; | |
179 } | |
180 | |
181 /* now write remaining bits */ | |
182 val = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) ); | |
183 cur[0] |= (FT_Byte)( val >> shift ); | |
184 | |
185 if ( count > space ) | |
186 cur[1] |= (FT_Byte)( val << space ); | |
187 | |
188 acc <<= count; | |
189 loaded -= count; | |
190 } | |
191 | |
192 /* now, skip to next line */ | |
193 if ( byte_padded ) | |
194 { | |
195 acc = 0; | |
196 loaded = 0; /* clear accumulator on byte-padded lines */ | |
197 } | |
198 | |
199 line_buff += line_incr; | |
200 } | |
201 } | |
202 | |
203 | |
204 static const FT_Frame_Field sbit_metrics_fields[] = | |
205 { | |
206 #undef FT_STRUCTURE | |
207 #define FT_STRUCTURE TT_SBit_MetricsRec | |
208 | |
209 FT_FRAME_START( 8 ), | |
210 FT_FRAME_BYTE( height ), | |
211 FT_FRAME_BYTE( width ), | |
212 | |
213 FT_FRAME_CHAR( horiBearingX ), | |
214 FT_FRAME_CHAR( horiBearingY ), | |
215 FT_FRAME_BYTE( horiAdvance ), | |
216 | |
217 FT_FRAME_CHAR( vertBearingX ), | |
218 FT_FRAME_CHAR( vertBearingY ), | |
219 FT_FRAME_BYTE( vertAdvance ), | |
220 FT_FRAME_END | |
221 }; | |
222 | |
223 | |
224 /*************************************************************************/ | |
225 /* */ | |
226 /* <Function> */ | |
227 /* Load_SBit_Const_Metrics */ | |
228 /* */ | |
229 /* <Description> */ | |
230 /* Loads the metrics for `EBLC' index tables format 2 and 5. */ | |
231 /* */ | |
232 /* <Input> */ | |
233 /* range :: The target range. */ | |
234 /* */ | |
235 /* stream :: The input stream. */ | |
236 /* */ | |
237 /* <Return> */ | |
238 /* FreeType error code. 0 means success. */ | |
239 /* */ | |
240 static FT_Error | |
241 Load_SBit_Const_Metrics( TT_SBit_Range range, | |
242 FT_Stream stream ) | |
243 { | |
244 FT_Error error; | |
245 | |
246 | |
247 if ( FT_READ_ULONG( range->image_size ) ) | |
248 return error; | |
249 | |
250 return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics ); | |
251 } | |
252 | |
253 | |
254 /*************************************************************************/ | |
255 /* */ | |
256 /* <Function> */ | |
257 /* Load_SBit_Range_Codes */ | |
258 /* */ | |
259 /* <Description> */ | |
260 /* Loads the range codes for `EBLC' index tables format 4 and 5. */ | |
261 /* */ | |
262 /* <Input> */ | |
263 /* range :: The target range. */ | |
264 /* */ | |
265 /* stream :: The input stream. */ | |
266 /* */ | |
267 /* load_offsets :: A flag whether to load the glyph offset table. */ | |
268 /* */ | |
269 /* <Return> */ | |
270 /* FreeType error code. 0 means success. */ | |
271 /* */ | |
272 static FT_Error | |
273 Load_SBit_Range_Codes( TT_SBit_Range range, | |
274 FT_Stream stream, | |
275 FT_Bool load_offsets ) | |
276 { | |
277 FT_Error error; | |
278 FT_ULong count, n, size; | |
279 FT_Memory memory = stream->memory; | |
280 | |
281 | |
282 if ( FT_READ_ULONG( count ) ) | |
283 goto Exit; | |
284 | |
285 range->num_glyphs = count; | |
286 | |
287 /* Allocate glyph offsets table if needed */ | |
288 if ( load_offsets ) | |
289 { | |
290 if ( FT_NEW_ARRAY( range->glyph_offsets, count ) ) | |
291 goto Exit; | |
292 | |
293 size = count * 4L; | |
294 } | |
295 else | |
296 size = count * 2L; | |
297 | |
298 /* Allocate glyph codes table and access frame */ | |
299 if ( FT_NEW_ARRAY ( range->glyph_codes, count ) || | |
300 FT_FRAME_ENTER( size ) ) | |
301 goto Exit; | |
302 | |
303 for ( n = 0; n < count; n++ ) | |
304 { | |
305 range->glyph_codes[n] = FT_GET_USHORT(); | |
306 | |
307 if ( load_offsets ) | |
308 range->glyph_offsets[n] = (FT_ULong)range->image_offset + | |
309 FT_GET_USHORT(); | |
310 } | |
311 | |
312 FT_FRAME_EXIT(); | |
313 | |
314 Exit: | |
315 return error; | |
316 } | |
317 | |
318 | |
319 /*************************************************************************/ | |
320 /* */ | |
321 /* <Function> */ | |
322 /* Load_SBit_Range */ | |
323 /* */ | |
324 /* <Description> */ | |
325 /* Loads a given `EBLC' index/range table. */ | |
326 /* */ | |
327 /* <Input> */ | |
328 /* range :: The target range. */ | |
329 /* */ | |
330 /* stream :: The input stream. */ | |
331 /* */ | |
332 /* <Return> */ | |
333 /* FreeType error code. 0 means success. */ | |
334 /* */ | |
335 static FT_Error | |
336 Load_SBit_Range( TT_SBit_Range range, | |
337 FT_Stream stream ) | |
338 { | |
339 FT_Error error; | |
340 FT_Memory memory = stream->memory; | |
341 | |
342 | |
343 switch( range->index_format ) | |
344 { | |
345 case 1: /* variable metrics with 4-byte offsets */ | |
346 case 3: /* variable metrics with 2-byte offsets */ | |
347 { | |
348 FT_ULong num_glyphs, n; | |
349 FT_Int size_elem; | |
350 FT_Bool large = FT_BOOL( range->index_format == 1 ); | |
351 | |
352 | |
353 | |
354 if ( range->last_glyph < range->first_glyph ) | |
355 { | |
356 error = SFNT_Err_Invalid_File_Format; | |
357 goto Exit; | |
358 } | |
359 | |
360 num_glyphs = range->last_glyph - range->first_glyph + 1L; | |
361 range->num_glyphs = num_glyphs; | |
362 num_glyphs++; /* XXX: BEWARE - see spec */ | |
363 | |
364 size_elem = large ? 4 : 2; | |
365 | |
366 if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) || | |
367 FT_FRAME_ENTER( num_glyphs * size_elem ) ) | |
368 goto Exit; | |
369 | |
370 for ( n = 0; n < num_glyphs; n++ ) | |
371 range->glyph_offsets[n] = (FT_ULong)( range->image_offset + | |
372 ( large ? FT_GET_ULONG() | |
373 : FT_GET_USHORT() ) ); | |
374 FT_FRAME_EXIT(); | |
375 } | |
376 break; | |
377 | |
378 case 2: /* all glyphs have identical metrics */ | |
379 error = Load_SBit_Const_Metrics( range, stream ); | |
380 break; | |
381 | |
382 case 4: | |
383 error = Load_SBit_Range_Codes( range, stream, 1 ); | |
384 break; | |
385 | |
386 case 5: | |
387 error = Load_SBit_Const_Metrics( range, stream ); | |
388 if ( !error ) | |
389 error = Load_SBit_Range_Codes( range, stream, 0 ); | |
390 break; | |
391 | |
392 default: | |
393 error = SFNT_Err_Invalid_File_Format; | |
394 } | |
395 | |
396 Exit: | |
397 return error; | |
398 } | |
399 | |
400 | |
401 /*************************************************************************/ | |
402 /* */ | |
403 /* <Function> */ | |
404 /* tt_face_load_eblc */ | |
405 /* */ | |
406 /* <Description> */ | |
407 /* Loads the table of embedded bitmap sizes for this face. */ | |
408 /* */ | |
409 /* <Input> */ | |
410 /* face :: The target face object. */ | |
411 /* */ | |
412 /* stream :: The input stream. */ | |
413 /* */ | |
414 /* <Return> */ | |
415 /* FreeType error code. 0 means success. */ | |
416 /* */ | |
417 FT_LOCAL_DEF( FT_Error ) | 44 FT_LOCAL_DEF( FT_Error ) |
418 tt_face_load_eblc( TT_Face face, | 45 tt_face_load_eblc( TT_Face face, |
419 FT_Stream stream ) | 46 FT_Stream stream ) |
420 { | 47 { |
421 FT_Error error = SFNT_Err_Ok; | 48 FT_Error error = FT_Err_Ok; |
422 FT_Memory memory = stream->memory; | 49 FT_Fixed version; |
423 FT_Fixed version; | 50 FT_ULong num_strikes, table_size; |
424 FT_ULong num_strikes; | 51 FT_Byte* p; |
425 FT_ULong table_base; | 52 FT_Byte* p_limit; |
426 | 53 FT_UInt count; |
427 static const FT_Frame_Field sbit_line_metrics_fields[] = | 54 |
428 { | 55 |
429 #undef FT_STRUCTURE | 56 face->sbit_num_strikes = 0; |
430 #define FT_STRUCTURE TT_SBit_LineMetricsRec | |
431 | |
432 /* no FT_FRAME_START */ | |
433 FT_FRAME_CHAR( ascender ), | |
434 FT_FRAME_CHAR( descender ), | |
435 FT_FRAME_BYTE( max_width ), | |
436 | |
437 FT_FRAME_CHAR( caret_slope_numerator ), | |
438 FT_FRAME_CHAR( caret_slope_denominator ), | |
439 FT_FRAME_CHAR( caret_offset ), | |
440 | |
441 FT_FRAME_CHAR( min_origin_SB ), | |
442 FT_FRAME_CHAR( min_advance_SB ), | |
443 FT_FRAME_CHAR( max_before_BL ), | |
444 FT_FRAME_CHAR( min_after_BL ), | |
445 FT_FRAME_CHAR( pads[0] ), | |
446 FT_FRAME_CHAR( pads[1] ), | |
447 FT_FRAME_END | |
448 }; | |
449 | |
450 static const FT_Frame_Field strike_start_fields[] = | |
451 { | |
452 #undef FT_STRUCTURE | |
453 #define FT_STRUCTURE TT_SBit_StrikeRec | |
454 | |
455 /* no FT_FRAME_START */ | |
456 FT_FRAME_ULONG( ranges_offset ), | |
457 FT_FRAME_SKIP_LONG, | |
458 FT_FRAME_ULONG( num_ranges ), | |
459 FT_FRAME_ULONG( color_ref ), | |
460 FT_FRAME_END | |
461 }; | |
462 | |
463 static const FT_Frame_Field strike_end_fields[] = | |
464 { | |
465 /* no FT_FRAME_START */ | |
466 FT_FRAME_USHORT( start_glyph ), | |
467 FT_FRAME_USHORT( end_glyph ), | |
468 FT_FRAME_BYTE ( x_ppem ), | |
469 FT_FRAME_BYTE ( y_ppem ), | |
470 FT_FRAME_BYTE ( bit_depth ), | |
471 FT_FRAME_CHAR ( flags ), | |
472 FT_FRAME_END | |
473 }; | |
474 | |
475 | |
476 face->num_sbit_strikes = 0; | |
477 | 57 |
478 /* this table is optional */ | 58 /* this table is optional */ |
479 error = face->goto_table( face, TTAG_EBLC, stream, 0 ); | 59 error = face->goto_table( face, TTAG_CBLC, stream, &table_size ); |
480 if ( error ) | 60 if ( error ) |
481 error = face->goto_table( face, TTAG_bloc, stream, 0 ); | 61 error = face->goto_table( face, TTAG_EBLC, stream, &table_size ); |
482 if ( error ) | 62 if ( error ) |
483 goto Exit; | 63 error = face->goto_table( face, TTAG_bloc, stream, &table_size ); |
484 | 64 if ( error ) |
485 table_base = FT_STREAM_POS(); | 65 goto Exit; |
486 if ( FT_FRAME_ENTER( 8L ) ) | 66 |
487 goto Exit; | 67 if ( table_size < 8 ) |
488 | 68 { |
489 version = FT_GET_LONG(); | 69 FT_ERROR(( "tt_face_load_sbit_strikes: table too short\n" )); |
490 num_strikes = FT_GET_ULONG(); | 70 error = FT_THROW( Invalid_File_Format ); |
491 | 71 goto Exit; |
492 FT_FRAME_EXIT(); | 72 } |
493 | 73 |
494 /* check version number and strike count */ | 74 if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) ) |
495 if ( version != 0x00020000L || | 75 goto Exit; |
496 num_strikes >= 0x10000L ) | 76 |
| 77 face->sbit_table_size = table_size; |
| 78 |
| 79 p = face->sbit_table; |
| 80 p_limit = p + table_size; |
| 81 |
| 82 version = FT_NEXT_ULONG( p ); |
| 83 num_strikes = FT_NEXT_ULONG( p ); |
| 84 |
| 85 if ( version != 0x00020000UL || num_strikes >= 0x10000UL ) |
497 { | 86 { |
498 FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" )); | 87 FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" )); |
499 error = SFNT_Err_Invalid_File_Format; | 88 error = FT_THROW( Invalid_File_Format ); |
500 | 89 goto Fail; |
501 goto Exit; | 90 } |
502 } | 91 |
503 | 92 /* |
504 /* allocate the strikes table */ | 93 * Count the number of strikes available in the table. We are a bit |
505 if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) ) | 94 * paranoid there and don't trust the data. |
506 goto Exit; | 95 */ |
507 | 96 count = (FT_UInt)num_strikes; |
508 face->num_sbit_strikes = num_strikes; | 97 if ( 8 + 48UL * count > table_size ) |
509 | 98 count = (FT_UInt)( ( p_limit - p ) / 48 ); |
510 /* now read each strike table separately */ | 99 |
511 { | 100 face->sbit_num_strikes = count; |
512 TT_SBit_Strike strike = face->sbit_strikes; | 101 |
513 FT_ULong count = num_strikes; | 102 FT_TRACE3(( "sbit_num_strikes: %u\n", count )); |
514 | |
515 | |
516 if ( FT_FRAME_ENTER( 48L * num_strikes ) ) | |
517 goto Exit; | |
518 | |
519 while ( count > 0 ) | |
520 { | |
521 if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike ) || | |
522 FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) || | |
523 FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) || | |
524 FT_STREAM_READ_FIELDS( strike_end_fields, strike ) ) | |
525 break; | |
526 | |
527 count--; | |
528 strike++; | |
529 } | |
530 | |
531 FT_FRAME_EXIT(); | |
532 } | |
533 | |
534 /* allocate the index ranges for each strike table */ | |
535 { | |
536 TT_SBit_Strike strike = face->sbit_strikes; | |
537 FT_ULong count = num_strikes; | |
538 | |
539 | |
540 while ( count > 0 ) | |
541 { | |
542 TT_SBit_Range range; | |
543 FT_ULong count2 = strike->num_ranges; | |
544 | |
545 | |
546 /* read each range */ | |
547 if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) || | |
548 FT_FRAME_ENTER( strike->num_ranges * 8L ) ) | |
549 goto Exit; | |
550 | |
551 if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) ) | |
552 goto Exit; | |
553 | |
554 range = strike->sbit_ranges; | |
555 while ( count2 > 0 ) | |
556 { | |
557 range->first_glyph = FT_GET_USHORT(); | |
558 range->last_glyph = FT_GET_USHORT(); | |
559 range->table_offset = table_base + strike->ranges_offset + | |
560 FT_GET_ULONG(); | |
561 count2--; | |
562 range++; | |
563 } | |
564 | |
565 FT_FRAME_EXIT(); | |
566 | |
567 /* Now, read each index table */ | |
568 count2 = strike->num_ranges; | |
569 range = strike->sbit_ranges; | |
570 while ( count2 > 0 ) | |
571 { | |
572 /* Read the header */ | |
573 if ( FT_STREAM_SEEK( range->table_offset ) || | |
574 FT_FRAME_ENTER( 8L ) ) | |
575 goto Exit; | |
576 | |
577 range->index_format = FT_GET_USHORT(); | |
578 range->image_format = FT_GET_USHORT(); | |
579 range->image_offset = FT_GET_ULONG(); | |
580 | |
581 FT_FRAME_EXIT(); | |
582 | |
583 error = Load_SBit_Range( range, stream ); | |
584 if ( error ) | |
585 goto Exit; | |
586 | |
587 count2--; | |
588 range++; | |
589 } | |
590 | |
591 count--; | |
592 strike++; | |
593 } | |
594 } | |
595 | |
596 Exit: | 103 Exit: |
597 return error; | 104 return error; |
598 } | 105 |
599 | 106 Fail: |
600 | 107 FT_FRAME_RELEASE( face->sbit_table ); |
601 /*************************************************************************/ | 108 face->sbit_table_size = 0; |
602 /* */ | 109 goto Exit; |
603 /* <Function> */ | 110 } |
604 /* tt_face_free_eblc */ | 111 |
605 /* */ | 112 |
606 /* <Description> */ | |
607 /* Releases the embedded bitmap tables. */ | |
608 /* */ | |
609 /* <Input> */ | |
610 /* face :: The target face object. */ | |
611 /* */ | |
612 FT_LOCAL_DEF( void ) | 113 FT_LOCAL_DEF( void ) |
613 tt_face_free_eblc( TT_Face face ) | 114 tt_face_free_eblc( TT_Face face ) |
614 { | 115 { |
615 FT_Memory memory = face->root.memory; | 116 FT_Stream stream = face->root.stream; |
616 TT_SBit_Strike strike = face->sbit_strikes; | 117 |
617 TT_SBit_Strike strike_limit = strike + face->num_sbit_strikes; | 118 |
618 | 119 FT_FRAME_RELEASE( face->sbit_table ); |
619 | 120 face->sbit_table_size = 0; |
620 if ( strike ) | 121 face->sbit_num_strikes = 0; |
621 { | |
622 for ( ; strike < strike_limit; strike++ ) | |
623 { | |
624 TT_SBit_Range range = strike->sbit_ranges; | |
625 TT_SBit_Range range_limit = range + strike->num_ranges; | |
626 | |
627 | |
628 if ( range ) | |
629 { | |
630 for ( ; range < range_limit; range++ ) | |
631 { | |
632 /* release the glyph offsets and codes tables */ | |
633 /* where appropriate */ | |
634 FT_FREE( range->glyph_offsets ); | |
635 FT_FREE( range->glyph_codes ); | |
636 } | |
637 } | |
638 FT_FREE( strike->sbit_ranges ); | |
639 strike->num_ranges = 0; | |
640 } | |
641 FT_FREE( face->sbit_strikes ); | |
642 } | |
643 face->num_sbit_strikes = 0; | |
644 } | 122 } |
645 | 123 |
646 | 124 |
647 FT_LOCAL_DEF( FT_Error ) | 125 FT_LOCAL_DEF( FT_Error ) |
648 tt_face_set_sbit_strike( TT_Face face, | 126 tt_face_set_sbit_strike( TT_Face face, |
649 FT_Size_Request req, | 127 FT_Size_Request req, |
650 FT_ULong* astrike_index ) | 128 FT_ULong* astrike_index ) |
651 { | 129 { |
652 return FT_Match_Size( (FT_Face)face, req, 0, astrike_index ); | 130 return FT_Match_Size( (FT_Face)face, req, 0, astrike_index ); |
653 } | 131 } |
654 | 132 |
655 | 133 |
656 FT_LOCAL_DEF( FT_Error ) | 134 FT_LOCAL_DEF( FT_Error ) |
657 tt_face_load_strike_metrics( TT_Face face, | 135 tt_face_load_strike_metrics( TT_Face face, |
658 FT_ULong strike_index, | 136 FT_ULong strike_index, |
659 FT_Size_Metrics* metrics ) | 137 FT_Size_Metrics* metrics ) |
660 { | 138 { |
661 TT_SBit_Strike strike; | 139 FT_Byte* strike; |
662 | 140 |
663 | 141 |
664 if ( strike_index >= face->num_sbit_strikes ) | 142 if ( strike_index >= (FT_ULong)face->sbit_num_strikes ) |
665 return SFNT_Err_Invalid_Argument; | 143 return FT_THROW( Invalid_Argument ); |
666 | 144 |
667 strike = face->sbit_strikes + strike_index; | 145 strike = face->sbit_table + 8 + strike_index * 48; |
668 | 146 |
669 metrics->x_ppem = strike->x_ppem; | 147 metrics->x_ppem = (FT_UShort)strike[44]; |
670 metrics->y_ppem = strike->y_ppem; | 148 metrics->y_ppem = (FT_UShort)strike[45]; |
671 | 149 |
672 metrics->ascender = strike->hori.ascender << 6; | 150 metrics->ascender = (FT_Char)strike[16] << 6; /* hori.ascender */ |
673 metrics->descender = strike->hori.descender << 6; | 151 metrics->descender = (FT_Char)strike[17] << 6; /* hori.descender */ |
| 152 metrics->height = metrics->ascender - metrics->descender; |
674 | 153 |
675 /* XXX: Is this correct? */ | 154 /* XXX: Is this correct? */ |
676 metrics->max_advance = ( strike->hori.min_origin_SB + | 155 metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */ |
677 strike->hori.max_width + | 156 strike[18] + /* max_width */ |
678 strike->hori.min_advance_SB ) << 6; | 157 (FT_Char)strike[23] /* min_advance_SB */ |
679 | 158 ) << 6; |
680 metrics->height = metrics->ascender - metrics->descender; | 159 |
681 | 160 return FT_Err_Ok; |
682 return SFNT_Err_Ok; | 161 } |
683 } | 162 |
684 | 163 |
685 | 164 typedef struct TT_SBitDecoderRec_ |
686 /*************************************************************************/ | 165 { |
687 /* */ | 166 TT_Face face; |
688 /* <Function> */ | 167 FT_Stream stream; |
689 /* find_sbit_range */ | 168 FT_Bitmap* bitmap; |
690 /* */ | 169 TT_SBit_Metrics metrics; |
691 /* <Description> */ | 170 FT_Bool metrics_loaded; |
692 /* Scans a given strike's ranges and return, for a given glyph */ | 171 FT_Bool bitmap_allocated; |
693 /* index, the corresponding sbit range, and `EBDT' offset. */ | 172 FT_Byte bit_depth; |
694 /* */ | 173 |
695 /* <Input> */ | 174 FT_ULong ebdt_start; |
696 /* glyph_index :: The glyph index. */ | 175 FT_ULong ebdt_size; |
697 /* */ | 176 |
698 /* strike :: The source/current sbit strike. */ | 177 FT_ULong strike_index_array; |
699 /* */ | 178 FT_ULong strike_index_count; |
700 /* <Output> */ | 179 FT_Byte* eblc_base; |
701 /* arange :: The sbit range containing the glyph index. */ | 180 FT_Byte* eblc_limit; |
702 /* */ | 181 |
703 /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ | 182 } TT_SBitDecoderRec, *TT_SBitDecoder; |
704 /* */ | 183 |
705 /* <Return> */ | 184 |
706 /* FreeType error code. 0 means the glyph index was found. */ | |
707 /* */ | |
708 static FT_Error | 185 static FT_Error |
709 find_sbit_range( FT_UInt glyph_index, | 186 tt_sbit_decoder_init( TT_SBitDecoder decoder, |
710 TT_SBit_Strike strike, | 187 TT_Face face, |
711 TT_SBit_Range *arange, | 188 FT_ULong strike_index, |
712 FT_ULong *aglyph_offset ) | 189 TT_SBit_MetricsRec* metrics ) |
713 { | 190 { |
714 TT_SBit_RangeRec *range, *range_limit; | 191 FT_Error error; |
715 | 192 FT_Stream stream = face->root.stream; |
716 | 193 FT_ULong ebdt_size; |
717 /* check whether the glyph index is within this strike's */ | 194 |
718 /* glyph range */ | 195 |
719 if ( glyph_index < (FT_UInt)strike->start_glyph || | 196 error = face->goto_table( face, TTAG_CBDT, stream, &ebdt_size ); |
720 glyph_index > (FT_UInt)strike->end_glyph ) | 197 if ( error ) |
| 198 error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size ); |
| 199 if ( error ) |
| 200 error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size ); |
| 201 if ( error ) |
| 202 goto Exit; |
| 203 |
| 204 decoder->face = face; |
| 205 decoder->stream = stream; |
| 206 decoder->bitmap = &face->root.glyph->bitmap; |
| 207 decoder->metrics = metrics; |
| 208 |
| 209 decoder->metrics_loaded = 0; |
| 210 decoder->bitmap_allocated = 0; |
| 211 |
| 212 decoder->ebdt_start = FT_STREAM_POS(); |
| 213 decoder->ebdt_size = ebdt_size; |
| 214 |
| 215 decoder->eblc_base = face->sbit_table; |
| 216 decoder->eblc_limit = face->sbit_table + face->sbit_table_size; |
| 217 |
| 218 /* now find the strike corresponding to the index */ |
| 219 { |
| 220 FT_Byte* p; |
| 221 |
| 222 |
| 223 if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size ) |
| 224 { |
| 225 error = FT_THROW( Invalid_File_Format ); |
| 226 goto Exit; |
| 227 } |
| 228 |
| 229 p = decoder->eblc_base + 8 + 48 * strike_index; |
| 230 |
| 231 decoder->strike_index_array = FT_NEXT_ULONG( p ); |
| 232 p += 4; |
| 233 decoder->strike_index_count = FT_NEXT_ULONG( p ); |
| 234 p += 34; |
| 235 decoder->bit_depth = *p; |
| 236 |
| 237 if ( decoder->strike_index_array > face->sbit_table_size || |
| 238 decoder->strike_index_array + 8 * decoder->strike_index_count > |
| 239 face->sbit_table_size ) |
| 240 error = FT_THROW( Invalid_File_Format ); |
| 241 } |
| 242 |
| 243 Exit: |
| 244 return error; |
| 245 } |
| 246 |
| 247 |
| 248 static void |
| 249 tt_sbit_decoder_done( TT_SBitDecoder decoder ) |
| 250 { |
| 251 FT_UNUSED( decoder ); |
| 252 } |
| 253 |
| 254 |
| 255 static FT_Error |
| 256 tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder, |
| 257 FT_UInt load_flags ) |
| 258 { |
| 259 FT_Error error = FT_Err_Ok; |
| 260 FT_UInt width, height; |
| 261 FT_Bitmap* map = decoder->bitmap; |
| 262 FT_Long size; |
| 263 |
| 264 |
| 265 if ( !decoder->metrics_loaded ) |
| 266 { |
| 267 error = FT_THROW( Invalid_Argument ); |
| 268 goto Exit; |
| 269 } |
| 270 |
| 271 width = decoder->metrics->width; |
| 272 height = decoder->metrics->height; |
| 273 |
| 274 map->width = (int)width; |
| 275 map->rows = (int)height; |
| 276 |
| 277 switch ( decoder->bit_depth ) |
| 278 { |
| 279 case 1: |
| 280 map->pixel_mode = FT_PIXEL_MODE_MONO; |
| 281 map->pitch = ( map->width + 7 ) >> 3; |
| 282 map->num_grays = 2; |
| 283 break; |
| 284 |
| 285 case 2: |
| 286 map->pixel_mode = FT_PIXEL_MODE_GRAY2; |
| 287 map->pitch = ( map->width + 3 ) >> 2; |
| 288 map->num_grays = 4; |
| 289 break; |
| 290 |
| 291 case 4: |
| 292 map->pixel_mode = FT_PIXEL_MODE_GRAY4; |
| 293 map->pitch = ( map->width + 1 ) >> 1; |
| 294 map->num_grays = 16; |
| 295 break; |
| 296 |
| 297 case 8: |
| 298 map->pixel_mode = FT_PIXEL_MODE_GRAY; |
| 299 map->pitch = map->width; |
| 300 map->num_grays = 256; |
| 301 break; |
| 302 |
| 303 case 32: |
| 304 if ( load_flags & FT_LOAD_COLOR ) |
| 305 { |
| 306 map->pixel_mode = FT_PIXEL_MODE_BGRA; |
| 307 map->pitch = map->width * 4; |
| 308 map->num_grays = 256; |
| 309 } |
| 310 else |
| 311 { |
| 312 map->pixel_mode = FT_PIXEL_MODE_GRAY; |
| 313 map->pitch = map->width; |
| 314 map->num_grays = 256; |
| 315 } |
| 316 break; |
| 317 |
| 318 default: |
| 319 error = FT_THROW( Invalid_File_Format ); |
| 320 goto Exit; |
| 321 } |
| 322 |
| 323 size = map->rows * map->pitch; |
| 324 |
| 325 /* check that there is no empty image */ |
| 326 if ( size == 0 ) |
| 327 goto Exit; /* exit successfully! */ |
| 328 |
| 329 error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size ); |
| 330 if ( error ) |
| 331 goto Exit; |
| 332 |
| 333 decoder->bitmap_allocated = 1; |
| 334 |
| 335 Exit: |
| 336 return error; |
| 337 } |
| 338 |
| 339 |
| 340 static FT_Error |
| 341 tt_sbit_decoder_load_metrics( TT_SBitDecoder decoder, |
| 342 FT_Byte* *pp, |
| 343 FT_Byte* limit, |
| 344 FT_Bool big ) |
| 345 { |
| 346 FT_Byte* p = *pp; |
| 347 TT_SBit_Metrics metrics = decoder->metrics; |
| 348 |
| 349 |
| 350 if ( p + 5 > limit ) |
721 goto Fail; | 351 goto Fail; |
722 | 352 |
723 /* scan all ranges in strike */ | 353 metrics->height = p[0]; |
724 range = strike->sbit_ranges; | 354 metrics->width = p[1]; |
725 range_limit = range + strike->num_ranges; | 355 metrics->horiBearingX = (FT_Char)p[2]; |
726 if ( !range ) | 356 metrics->horiBearingY = (FT_Char)p[3]; |
| 357 metrics->horiAdvance = p[4]; |
| 358 |
| 359 p += 5; |
| 360 if ( big ) |
| 361 { |
| 362 if ( p + 3 > limit ) |
| 363 goto Fail; |
| 364 |
| 365 metrics->vertBearingX = (FT_Char)p[0]; |
| 366 metrics->vertBearingY = (FT_Char)p[1]; |
| 367 metrics->vertAdvance = p[2]; |
| 368 |
| 369 p += 3; |
| 370 } |
| 371 |
| 372 decoder->metrics_loaded = 1; |
| 373 *pp = p; |
| 374 return FT_Err_Ok; |
| 375 |
| 376 Fail: |
| 377 FT_TRACE1(( "tt_sbit_decoder_load_metrics: broken table" )); |
| 378 return FT_THROW( Invalid_Argument ); |
| 379 } |
| 380 |
| 381 |
| 382 /* forward declaration */ |
| 383 static FT_Error |
| 384 tt_sbit_decoder_load_image( TT_SBitDecoder decoder, |
| 385 FT_UInt load_flags, |
| 386 FT_UInt glyph_index, |
| 387 FT_Int x_pos, |
| 388 FT_Int y_pos ); |
| 389 |
| 390 typedef FT_Error (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder decoder, |
| 391 FT_UInt load_flags, |
| 392 FT_Byte* p, |
| 393 FT_Byte* plimit, |
| 394 FT_Int x_pos, |
| 395 FT_Int y_pos ); |
| 396 |
| 397 |
| 398 static FT_Error |
| 399 tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder decoder, |
| 400 FT_UInt load_flags, |
| 401 FT_Byte* p, |
| 402 FT_Byte* limit, |
| 403 FT_Int x_pos, |
| 404 FT_Int y_pos ) |
| 405 { |
| 406 FT_Error error = FT_Err_Ok; |
| 407 FT_Byte* line; |
| 408 FT_Int bit_height, bit_width, pitch, width, height, line_bits, h; |
| 409 FT_Bitmap* bitmap; |
| 410 |
| 411 FT_UNUSED( load_flags ); |
| 412 |
| 413 |
| 414 /* check that we can write the glyph into the bitmap */ |
| 415 bitmap = decoder->bitmap; |
| 416 bit_width = bitmap->width; |
| 417 bit_height = bitmap->rows; |
| 418 pitch = bitmap->pitch; |
| 419 line = bitmap->buffer; |
| 420 |
| 421 width = decoder->metrics->width; |
| 422 height = decoder->metrics->height; |
| 423 |
| 424 line_bits = width * decoder->bit_depth; |
| 425 |
| 426 if ( x_pos < 0 || x_pos + width > bit_width || |
| 427 y_pos < 0 || y_pos + height > bit_height ) |
| 428 { |
| 429 FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned:" |
| 430 " invalid bitmap dimensions\n" )); |
| 431 error = FT_THROW( Invalid_File_Format ); |
| 432 goto Exit; |
| 433 } |
| 434 |
| 435 if ( p + ( ( line_bits + 7 ) >> 3 ) * height > limit ) |
| 436 { |
| 437 FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned: broken bitmap\n" )); |
| 438 error = FT_THROW( Invalid_File_Format ); |
| 439 goto Exit; |
| 440 } |
| 441 |
| 442 /* now do the blit */ |
| 443 line += y_pos * pitch + ( x_pos >> 3 ); |
| 444 x_pos &= 7; |
| 445 |
| 446 if ( x_pos == 0 ) /* the easy one */ |
| 447 { |
| 448 for ( h = height; h > 0; h--, line += pitch ) |
| 449 { |
| 450 FT_Byte* pwrite = line; |
| 451 FT_Int w; |
| 452 |
| 453 |
| 454 for ( w = line_bits; w >= 8; w -= 8 ) |
| 455 { |
| 456 pwrite[0] = (FT_Byte)( pwrite[0] | *p++ ); |
| 457 pwrite += 1; |
| 458 } |
| 459 |
| 460 if ( w > 0 ) |
| 461 pwrite[0] = (FT_Byte)( pwrite[0] | ( *p++ & ( 0xFF00U >> w ) ) ); |
| 462 } |
| 463 } |
| 464 else /* x_pos > 0 */ |
| 465 { |
| 466 for ( h = height; h > 0; h--, line += pitch ) |
| 467 { |
| 468 FT_Byte* pwrite = line; |
| 469 FT_Int w; |
| 470 FT_UInt wval = 0; |
| 471 |
| 472 |
| 473 for ( w = line_bits; w >= 8; w -= 8 ) |
| 474 { |
| 475 wval = (FT_UInt)( wval | *p++ ); |
| 476 pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) ); |
| 477 pwrite += 1; |
| 478 wval <<= 8; |
| 479 } |
| 480 |
| 481 if ( w > 0 ) |
| 482 wval = (FT_UInt)( wval | ( *p++ & ( 0xFF00U >> w ) ) ); |
| 483 |
| 484 /* all bits read and there are `x_pos + w' bits to be written */ |
| 485 |
| 486 pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) ); |
| 487 |
| 488 if ( x_pos + w > 8 ) |
| 489 { |
| 490 pwrite++; |
| 491 wval <<= 8; |
| 492 pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) ); |
| 493 } |
| 494 } |
| 495 } |
| 496 |
| 497 Exit: |
| 498 if ( !error ) |
| 499 FT_TRACE3(( "tt_sbit_decoder_load_byte_aligned: loaded\n" )); |
| 500 return error; |
| 501 } |
| 502 |
| 503 |
| 504 /* |
| 505 * Load a bit-aligned bitmap (with pointer `p') into a line-aligned bitmap |
| 506 * (with pointer `pwrite'). In the example below, the width is 3 pixel, |
| 507 * and `x_pos' is 1 pixel. |
| 508 * |
| 509 * p p+1 |
| 510 * | | | |
| 511 * | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |... |
| 512 * | | | |
| 513 * +-------+ +-------+ +-------+ ... |
| 514 * . . . |
| 515 * . . . |
| 516 * v . . |
| 517 * +-------+ . . |
| 518 * | | . |
| 519 * | 7 6 5 4 3 2 1 0 | . |
| 520 * | | . |
| 521 * pwrite . . |
| 522 * . . |
| 523 * v . |
| 524 * +-------+ . |
| 525 * | | |
| 526 * | 7 6 5 4 3 2 1 0 | |
| 527 * | | |
| 528 * pwrite+1 . |
| 529 * . |
| 530 * v |
| 531 * +-------+ |
| 532 * | | |
| 533 * | 7 6 5 4 3 2 1 0 | |
| 534 * | | |
| 535 * pwrite+2 |
| 536 * |
| 537 */ |
| 538 |
| 539 static FT_Error |
| 540 tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder decoder, |
| 541 FT_UInt load_flags, |
| 542 FT_Byte* p, |
| 543 FT_Byte* limit, |
| 544 FT_Int x_pos, |
| 545 FT_Int y_pos ) |
| 546 { |
| 547 FT_Error error = FT_Err_Ok; |
| 548 FT_Byte* line; |
| 549 FT_Int bit_height, bit_width, pitch, width, height, line_bits, h, nbits
; |
| 550 FT_Bitmap* bitmap; |
| 551 FT_UShort rval; |
| 552 |
| 553 FT_UNUSED( load_flags ); |
| 554 |
| 555 |
| 556 /* check that we can write the glyph into the bitmap */ |
| 557 bitmap = decoder->bitmap; |
| 558 bit_width = bitmap->width; |
| 559 bit_height = bitmap->rows; |
| 560 pitch = bitmap->pitch; |
| 561 line = bitmap->buffer; |
| 562 |
| 563 width = decoder->metrics->width; |
| 564 height = decoder->metrics->height; |
| 565 |
| 566 line_bits = width * decoder->bit_depth; |
| 567 |
| 568 if ( x_pos < 0 || x_pos + width > bit_width || |
| 569 y_pos < 0 || y_pos + height > bit_height ) |
| 570 { |
| 571 FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned:" |
| 572 " invalid bitmap dimensions\n" )); |
| 573 error = FT_THROW( Invalid_File_Format ); |
| 574 goto Exit; |
| 575 } |
| 576 |
| 577 if ( p + ( ( line_bits * height + 7 ) >> 3 ) > limit ) |
| 578 { |
| 579 FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned: broken bitmap\n" )); |
| 580 error = FT_THROW( Invalid_File_Format ); |
| 581 goto Exit; |
| 582 } |
| 583 |
| 584 /* now do the blit */ |
| 585 |
| 586 /* adjust `line' to point to the first byte of the bitmap */ |
| 587 line += y_pos * pitch + ( x_pos >> 3 ); |
| 588 x_pos &= 7; |
| 589 |
| 590 /* the higher byte of `rval' is used as a buffer */ |
| 591 rval = 0; |
| 592 nbits = 0; |
| 593 |
| 594 for ( h = height; h > 0; h--, line += pitch ) |
| 595 { |
| 596 FT_Byte* pwrite = line; |
| 597 FT_Int w = line_bits; |
| 598 |
| 599 |
| 600 /* handle initial byte (in target bitmap) specially if necessary */ |
| 601 if ( x_pos ) |
| 602 { |
| 603 w = ( line_bits < 8 - x_pos ) ? line_bits : 8 - x_pos; |
| 604 |
| 605 if ( h == height ) |
| 606 { |
| 607 rval = *p++; |
| 608 nbits = x_pos; |
| 609 } |
| 610 else if ( nbits < w ) |
| 611 { |
| 612 if ( p < limit ) |
| 613 rval |= *p++; |
| 614 nbits += 8 - w; |
| 615 } |
| 616 else |
| 617 { |
| 618 rval >>= 8; |
| 619 nbits -= w; |
| 620 } |
| 621 |
| 622 *pwrite++ |= ( ( rval >> nbits ) & 0xFF ) & |
| 623 ( ~( 0xFF << w ) << ( 8 - w - x_pos ) ); |
| 624 rval <<= 8; |
| 625 |
| 626 w = line_bits - w; |
| 627 } |
| 628 |
| 629 /* handle medial bytes */ |
| 630 for ( ; w >= 8; w -= 8 ) |
| 631 { |
| 632 rval |= *p++; |
| 633 *pwrite++ |= ( rval >> nbits ) & 0xFF; |
| 634 |
| 635 rval <<= 8; |
| 636 } |
| 637 |
| 638 /* handle final byte if necessary */ |
| 639 if ( w > 0 ) |
| 640 { |
| 641 if ( nbits < w ) |
| 642 { |
| 643 if ( p < limit ) |
| 644 rval |= *p++; |
| 645 *pwrite |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w ); |
| 646 nbits += 8 - w; |
| 647 |
| 648 rval <<= 8; |
| 649 } |
| 650 else |
| 651 { |
| 652 *pwrite |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w ); |
| 653 nbits -= w; |
| 654 } |
| 655 } |
| 656 } |
| 657 |
| 658 Exit: |
| 659 if ( !error ) |
| 660 FT_TRACE3(( "tt_sbit_decoder_load_bit_aligned: loaded\n" )); |
| 661 return error; |
| 662 } |
| 663 |
| 664 |
| 665 static FT_Error |
| 666 tt_sbit_decoder_load_compound( TT_SBitDecoder decoder, |
| 667 FT_UInt load_flags, |
| 668 FT_Byte* p, |
| 669 FT_Byte* limit, |
| 670 FT_Int x_pos, |
| 671 FT_Int y_pos ) |
| 672 { |
| 673 FT_Error error = FT_Err_Ok; |
| 674 FT_UInt num_components, nn; |
| 675 |
| 676 FT_Char horiBearingX = decoder->metrics->horiBearingX; |
| 677 FT_Char horiBearingY = decoder->metrics->horiBearingY; |
| 678 FT_Byte horiAdvance = decoder->metrics->horiAdvance; |
| 679 FT_Char vertBearingX = decoder->metrics->vertBearingX; |
| 680 FT_Char vertBearingY = decoder->metrics->vertBearingY; |
| 681 FT_Byte vertAdvance = decoder->metrics->vertAdvance; |
| 682 |
| 683 |
| 684 if ( p + 2 > limit ) |
727 goto Fail; | 685 goto Fail; |
728 | 686 |
729 for ( ; range < range_limit; range++ ) | 687 num_components = FT_NEXT_USHORT( p ); |
730 { | 688 if ( p + 4 * num_components > limit ) |
731 if ( glyph_index >= (FT_UInt)range->first_glyph && | 689 { |
732 glyph_index <= (FT_UInt)range->last_glyph ) | 690 FT_TRACE1(( "tt_sbit_decoder_load_compound: broken table\n" )); |
733 { | 691 goto Fail; |
734 FT_UShort delta = (FT_UShort)( glyph_index - range->first_glyph ); | 692 } |
735 | 693 |
736 | 694 FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d components\n", |
737 switch ( range->index_format ) | 695 num_components )); |
738 { | 696 |
739 case 1: | 697 for ( nn = 0; nn < num_components; nn++ ) |
740 case 3: | 698 { |
741 *aglyph_offset = range->glyph_offsets[delta]; | 699 FT_UInt gindex = FT_NEXT_USHORT( p ); |
742 break; | 700 FT_Byte dx = FT_NEXT_BYTE( p ); |
743 | 701 FT_Byte dy = FT_NEXT_BYTE( p ); |
744 case 2: | 702 |
745 *aglyph_offset = range->image_offset + | 703 |
746 range->image_size * delta; | 704 /* NB: a recursive call */ |
747 break; | 705 error = tt_sbit_decoder_load_image( decoder, load_flags, gindex, |
748 | 706 x_pos + dx, y_pos + dy ); |
749 case 4: | 707 if ( error ) |
750 case 5: | 708 break; |
751 { | 709 } |
752 FT_ULong n; | 710 |
753 | 711 FT_TRACE3(( "tt_sbit_decoder_load_compound: done\n" )); |
754 | 712 |
755 for ( n = 0; n < range->num_glyphs; n++ ) | 713 decoder->metrics->horiBearingX = horiBearingX; |
756 { | 714 decoder->metrics->horiBearingY = horiBearingY; |
757 if ( (FT_UInt)range->glyph_codes[n] == glyph_index ) | 715 decoder->metrics->horiAdvance = horiAdvance; |
758 { | 716 decoder->metrics->vertBearingX = vertBearingX; |
759 if ( range->index_format == 4 ) | 717 decoder->metrics->vertBearingY = vertBearingY; |
760 *aglyph_offset = range->glyph_offsets[n]; | 718 decoder->metrics->vertAdvance = vertAdvance; |
761 else | 719 decoder->metrics->width = (FT_Byte)decoder->bitmap->width; |
762 *aglyph_offset = range->image_offset + | 720 decoder->metrics->height = (FT_Byte)decoder->bitmap->rows; |
763 n * range->image_size; | 721 |
764 goto Found; | 722 Exit: |
765 } | 723 return error; |
766 } | |
767 } | |
768 | |
769 /* fall-through */ | |
770 default: | |
771 goto Fail; | |
772 } | |
773 | |
774 Found: | |
775 /* return successfully! */ | |
776 *arange = range; | |
777 return SFNT_Err_Ok; | |
778 } | |
779 } | |
780 | 724 |
781 Fail: | 725 Fail: |
782 *arange = 0; | 726 error = FT_THROW( Invalid_File_Format ); |
783 *aglyph_offset = 0; | 727 goto Exit; |
784 | 728 } |
785 return SFNT_Err_Invalid_Argument; | 729 |
786 } | 730 |
787 | 731 #ifdef FT_CONFIG_OPTION_USE_PNG |
788 | 732 |
789 /*************************************************************************/ | 733 static FT_Error |
790 /* */ | 734 tt_sbit_decoder_load_png( TT_SBitDecoder decoder, |
791 /* <Function> */ | 735 FT_UInt load_flags, |
792 /* tt_find_sbit_image */ | 736 FT_Byte* p, |
793 /* */ | 737 FT_Byte* limit, |
794 /* <Description> */ | 738 FT_Int x_pos, |
795 /* Checks whether an embedded bitmap (an `sbit') exists for a given */ | 739 FT_Int y_pos ) |
796 /* glyph, at a given strike. */ | 740 { |
797 /* */ | 741 FT_Error error = FT_Err_Ok; |
798 /* <Input> */ | 742 FT_ULong png_len; |
799 /* face :: The target face object. */ | 743 |
800 /* */ | 744 FT_UNUSED( load_flags ); |
801 /* glyph_index :: The glyph index. */ | 745 |
802 /* */ | 746 |
803 /* strike_index :: The current strike index. */ | 747 if ( limit - p < 4 ) |
804 /* */ | 748 { |
805 /* <Output> */ | 749 FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" )); |
806 /* arange :: The SBit range containing the glyph index. */ | 750 error = FT_THROW( Invalid_File_Format ); |
807 /* */ | 751 goto Exit; |
808 /* astrike :: The SBit strike containing the glyph index. */ | 752 } |
809 /* */ | 753 |
810 /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ | 754 png_len = FT_NEXT_ULONG( p ); |
811 /* */ | 755 if ( (FT_ULong)( limit - p ) < png_len ) |
812 /* <Return> */ | 756 { |
813 /* FreeType error code. 0 means success. Returns */ | 757 FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" )); |
814 /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */ | 758 error = FT_THROW( Invalid_File_Format ); |
815 /* glyph. */ | 759 goto Exit; |
816 /* */ | 760 } |
817 FT_LOCAL( FT_Error ) | 761 |
818 tt_find_sbit_image( TT_Face face, | 762 error = Load_SBit_Png( decoder->bitmap, |
819 FT_UInt glyph_index, | 763 x_pos, |
820 FT_ULong strike_index, | 764 y_pos, |
821 TT_SBit_Range *arange, | 765 decoder->bit_depth, |
822 TT_SBit_Strike *astrike, | 766 decoder->metrics, |
823 FT_ULong *aglyph_offset ) | 767 decoder->stream->memory, |
824 { | 768 p, |
825 FT_Error error; | 769 png_len ); |
826 TT_SBit_Strike strike; | 770 |
827 | 771 Exit: |
828 | 772 if ( !error ) |
829 if ( !face->sbit_strikes || | 773 FT_TRACE3(( "tt_sbit_decoder_load_png: loaded\n" )); |
830 ( face->num_sbit_strikes <= strike_index ) ) | 774 return error; |
831 goto Fail; | 775 } |
832 | 776 |
833 strike = &face->sbit_strikes[strike_index]; | 777 #endif /* FT_CONFIG_OPTION_USE_PNG */ |
834 | 778 |
835 error = find_sbit_range( glyph_index, strike, | 779 |
836 arange, aglyph_offset ); | 780 static FT_Error |
837 if ( error ) | 781 tt_sbit_decoder_load_bitmap( TT_SBitDecoder decoder, |
838 goto Fail; | 782 FT_UInt load_flags, |
839 | 783 FT_UInt glyph_format, |
840 *astrike = strike; | 784 FT_ULong glyph_start, |
841 | 785 FT_ULong glyph_size, |
842 return SFNT_Err_Ok; | 786 FT_Int x_pos, |
843 | 787 FT_Int y_pos ) |
844 Fail: | 788 { |
845 /* no embedded bitmap for this glyph in face */ | 789 FT_Error error; |
846 *arange = 0; | 790 FT_Stream stream = decoder->stream; |
847 *astrike = 0; | 791 FT_Byte* p; |
848 *aglyph_offset = 0; | 792 FT_Byte* p_limit; |
849 | 793 FT_Byte* data; |
850 return SFNT_Err_Invalid_Argument; | 794 |
851 } | 795 |
852 | 796 /* seek into the EBDT table now */ |
853 | 797 if ( glyph_start + glyph_size > decoder->ebdt_size ) |
854 /*************************************************************************/ | 798 { |
855 /* */ | 799 error = FT_THROW( Invalid_Argument ); |
856 /* <Function> */ | 800 goto Exit; |
857 /* tt_load_sbit_metrics */ | 801 } |
858 /* */ | 802 |
859 /* <Description> */ | 803 if ( FT_STREAM_SEEK( decoder->ebdt_start + glyph_start ) || |
860 /* Gets the big metrics for a given SBit. */ | 804 FT_FRAME_EXTRACT( glyph_size, data ) ) |
861 /* */ | 805 goto Exit; |
862 /* <Input> */ | 806 |
863 /* stream :: The input stream. */ | 807 p = data; |
864 /* */ | 808 p_limit = p + glyph_size; |
865 /* range :: The SBit range containing the glyph. */ | 809 |
866 /* */ | 810 /* read the data, depending on the glyph format */ |
867 /* <Output> */ | 811 switch ( glyph_format ) |
868 /* big_metrics :: A big SBit metrics structure for the glyph. */ | |
869 /* */ | |
870 /* <Return> */ | |
871 /* FreeType error code. 0 means success. */ | |
872 /* */ | |
873 /* <Note> */ | |
874 /* The stream cursor must be positioned at the glyph's offset within */ | |
875 /* the `EBDT' table before the call. */ | |
876 /* */ | |
877 /* If the image format uses variable metrics, the stream cursor is */ | |
878 /* positioned just after the metrics header in the `EBDT' table on */ | |
879 /* function exit. */ | |
880 /* */ | |
881 FT_LOCAL( FT_Error ) | |
882 tt_load_sbit_metrics( FT_Stream stream, | |
883 TT_SBit_Range range, | |
884 TT_SBit_Metrics metrics ) | |
885 { | |
886 FT_Error error = SFNT_Err_Ok; | |
887 | |
888 | |
889 switch ( range->image_format ) | |
890 { | 812 { |
891 case 1: | 813 case 1: |
892 case 2: | 814 case 2: |
893 case 8: | 815 case 8: |
894 /* variable small metrics */ | 816 case 17: |
895 { | 817 error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 0 ); |
896 TT_SBit_SmallMetricsRec smetrics; | |
897 | |
898 static const FT_Frame_Field sbit_small_metrics_fields[] = | |
899 { | |
900 #undef FT_STRUCTURE | |
901 #define FT_STRUCTURE TT_SBit_SmallMetricsRec | |
902 | |
903 FT_FRAME_START( 5 ), | |
904 FT_FRAME_BYTE( height ), | |
905 FT_FRAME_BYTE( width ), | |
906 FT_FRAME_CHAR( bearingX ), | |
907 FT_FRAME_CHAR( bearingY ), | |
908 FT_FRAME_BYTE( advance ), | |
909 FT_FRAME_END | |
910 }; | |
911 | |
912 | |
913 /* read small metrics */ | |
914 if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) ) | |
915 goto Exit; | |
916 | |
917 /* convert it to a big metrics */ | |
918 metrics->height = smetrics.height; | |
919 metrics->width = smetrics.width; | |
920 metrics->horiBearingX = smetrics.bearingX; | |
921 metrics->horiBearingY = smetrics.bearingY; | |
922 metrics->horiAdvance = smetrics.advance; | |
923 | |
924 /* these metrics are made up at a higher level when */ | |
925 /* needed. */ | |
926 metrics->vertBearingX = 0; | |
927 metrics->vertBearingY = 0; | |
928 metrics->vertAdvance = 0; | |
929 } | |
930 break; | 818 break; |
931 | 819 |
932 case 6: | 820 case 6: |
933 case 7: | 821 case 7: |
934 case 9: | 822 case 9: |
935 /* variable big metrics */ | 823 case 18: |
936 if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) ) | 824 error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ); |
937 goto Exit; | |
938 break; | 825 break; |
939 | 826 |
940 case 5: | 827 default: |
941 default: /* constant metrics */ | 828 error = FT_Err_Ok; |
942 if ( range->index_format == 2 || range->index_format == 5 ) | 829 } |
943 *metrics = range->metrics; | 830 |
944 else | 831 if ( error ) |
945 return SFNT_Err_Invalid_File_Format; | 832 goto Fail; |
946 } | 833 |
947 | 834 { |
948 Exit: | 835 TT_SBitDecoder_LoadFunc loader; |
949 return error; | 836 |
950 } | 837 |
951 | 838 switch ( glyph_format ) |
952 | 839 { |
953 /*************************************************************************/ | 840 case 1: |
954 /* */ | |
955 /* <Function> */ | |
956 /* crop_bitmap */ | |
957 /* */ | |
958 /* <Description> */ | |
959 /* Crops a bitmap to its tightest bounding box, and adjusts its */ | |
960 /* metrics. */ | |
961 /* */ | |
962 /* <InOut> */ | |
963 /* map :: The bitmap. */ | |
964 /* */ | |
965 /* metrics :: The corresponding metrics structure. */ | |
966 /* */ | |
967 static void | |
968 crop_bitmap( FT_Bitmap* map, | |
969 TT_SBit_Metrics metrics ) | |
970 { | |
971 /***********************************************************************/ | |
972 /* */ | |
973 /* In this situation, some bounding boxes of embedded bitmaps are too */ | |
974 /* large. We need to crop it to a reasonable size. */ | |
975 /* */ | |
976 /* --------- */ | |
977 /* | | ----- */ | |
978 /* | *** | |***| */ | |
979 /* | * | | * | */ | |
980 /* | * | ------> | * | */ | |
981 /* | * | | * | */ | |
982 /* | * | | * | */ | |
983 /* | *** | |***| */ | |
984 /* --------- ----- */ | |
985 /* */ | |
986 /***********************************************************************/ | |
987 | |
988 FT_Int rows, count; | |
989 FT_Long line_len; | |
990 FT_Byte* line; | |
991 | |
992 | |
993 /***********************************************************************/ | |
994 /* */ | |
995 /* first of all, check the top-most lines of the bitmap, and remove */ | |
996 /* them if they're empty. */ | |
997 /* */ | |
998 { | |
999 line = (FT_Byte*)map->buffer; | |
1000 rows = map->rows; | |
1001 line_len = map->pitch; | |
1002 | |
1003 | |
1004 for ( count = 0; count < rows; count++ ) | |
1005 { | |
1006 FT_Byte* cur = line; | |
1007 FT_Byte* limit = line + line_len; | |
1008 | |
1009 | |
1010 for ( ; cur < limit; cur++ ) | |
1011 if ( cur[0] ) | |
1012 goto Found_Top; | |
1013 | |
1014 /* the current line was empty - skip to next one */ | |
1015 line = limit; | |
1016 } | |
1017 | |
1018 Found_Top: | |
1019 /* check that we have at least one filled line */ | |
1020 if ( count >= rows ) | |
1021 goto Empty_Bitmap; | |
1022 | |
1023 /* now, crop the empty upper lines */ | |
1024 if ( count > 0 ) | |
1025 { | |
1026 line = (FT_Byte*)map->buffer; | |
1027 | |
1028 FT_MEM_MOVE( line, line + count * line_len, | |
1029 ( rows - count ) * line_len ); | |
1030 | |
1031 metrics->height = (FT_Byte)( metrics->height - count ); | |
1032 metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count ); | |
1033 metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count ); | |
1034 | |
1035 map->rows -= count; | |
1036 rows -= count; | |
1037 } | |
1038 } | |
1039 | |
1040 /***********************************************************************/ | |
1041 /* */ | |
1042 /* second, crop the lower lines */ | |
1043 /* */ | |
1044 { | |
1045 line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len; | |
1046 | |
1047 for ( count = 0; count < rows; count++ ) | |
1048 { | |
1049 FT_Byte* cur = line; | |
1050 FT_Byte* limit = line + line_len; | |
1051 | |
1052 | |
1053 for ( ; cur < limit; cur++ ) | |
1054 if ( cur[0] ) | |
1055 goto Found_Bottom; | |
1056 | |
1057 /* the current line was empty - skip to previous one */ | |
1058 line -= line_len; | |
1059 } | |
1060 | |
1061 Found_Bottom: | |
1062 if ( count > 0 ) | |
1063 { | |
1064 metrics->height = (FT_Byte)( metrics->height - count ); | |
1065 rows -= count; | |
1066 map->rows -= count; | |
1067 } | |
1068 } | |
1069 | |
1070 /***********************************************************************/ | |
1071 /* */ | |
1072 /* third, get rid of the space on the left side of the glyph */ | |
1073 /* */ | |
1074 do | |
1075 { | |
1076 FT_Byte* limit; | |
1077 | |
1078 | |
1079 line = (FT_Byte*)map->buffer; | |
1080 limit = line + rows * line_len; | |
1081 | |
1082 for ( ; line < limit; line += line_len ) | |
1083 if ( line[0] & 0x80 ) | |
1084 goto Found_Left; | |
1085 | |
1086 /* shift the whole glyph one pixel to the left */ | |
1087 line = (FT_Byte*)map->buffer; | |
1088 limit = line + rows * line_len; | |
1089 | |
1090 for ( ; line < limit; line += line_len ) | |
1091 { | |
1092 FT_Int n, width = map->width; | |
1093 FT_Byte old; | |
1094 FT_Byte* cur = line; | |
1095 | |
1096 | |
1097 old = (FT_Byte)(cur[0] << 1); | |
1098 for ( n = 8; n < width; n += 8 ) | |
1099 { | |
1100 FT_Byte val; | |
1101 | |
1102 | |
1103 val = cur[1]; | |
1104 cur[0] = (FT_Byte)( old | ( val >> 7 ) ); | |
1105 old = (FT_Byte)( val << 1 ); | |
1106 cur++; | |
1107 } | |
1108 cur[0] = old; | |
1109 } | |
1110 | |
1111 map->width--; | |
1112 metrics->horiBearingX++; | |
1113 metrics->vertBearingX++; | |
1114 metrics->width--; | |
1115 | |
1116 } while ( map->width > 0 ); | |
1117 | |
1118 Found_Left: | |
1119 | |
1120 /***********************************************************************/ | |
1121 /* */ | |
1122 /* finally, crop the bitmap width to get rid of the space on the right */ | |
1123 /* side of the glyph. */ | |
1124 /* */ | |
1125 do | |
1126 { | |
1127 FT_Int right = map->width - 1; | |
1128 FT_Byte* limit; | |
1129 FT_Byte mask; | |
1130 | |
1131 | |
1132 line = (FT_Byte*)map->buffer + ( right >> 3 ); | |
1133 limit = line + rows * line_len; | |
1134 mask = (FT_Byte)( 0x80 >> ( right & 7 ) ); | |
1135 | |
1136 for ( ; line < limit; line += line_len ) | |
1137 if ( line[0] & mask ) | |
1138 goto Found_Right; | |
1139 | |
1140 /* crop the whole glyph to the right */ | |
1141 map->width--; | |
1142 metrics->width--; | |
1143 | |
1144 } while ( map->width > 0 ); | |
1145 | |
1146 Found_Right: | |
1147 /* all right, the bitmap was cropped */ | |
1148 return; | |
1149 | |
1150 Empty_Bitmap: | |
1151 map->width = 0; | |
1152 map->rows = 0; | |
1153 map->pitch = 0; | |
1154 map->pixel_mode = FT_PIXEL_MODE_MONO; | |
1155 } | |
1156 | |
1157 | |
1158 static FT_Error | |
1159 Load_SBit_Single( FT_Bitmap* map, | |
1160 FT_Int x_offset, | |
1161 FT_Int y_offset, | |
1162 FT_Int pix_bits, | |
1163 FT_UShort image_format, | |
1164 TT_SBit_Metrics metrics, | |
1165 FT_Stream stream ) | |
1166 { | |
1167 FT_Error error; | |
1168 | |
1169 | |
1170 /* check that the source bitmap fits into the target pixmap */ | |
1171 if ( x_offset < 0 || x_offset + metrics->width > map->width || | |
1172 y_offset < 0 || y_offset + metrics->height > map->rows ) | |
1173 { | |
1174 error = SFNT_Err_Invalid_Argument; | |
1175 | |
1176 goto Exit; | |
1177 } | |
1178 | |
1179 { | |
1180 FT_Int glyph_width = metrics->width; | |
1181 FT_Int glyph_height = metrics->height; | |
1182 FT_Int glyph_size; | |
1183 FT_Int line_bits = pix_bits * glyph_width; | |
1184 FT_Bool pad_bytes = 0; | |
1185 | |
1186 | |
1187 /* compute size of glyph image */ | |
1188 switch ( image_format ) | |
1189 { | |
1190 case 1: /* byte-padded formats */ | |
1191 case 6: | 841 case 6: |
1192 { | 842 loader = tt_sbit_decoder_load_byte_aligned; |
1193 FT_Int line_length; | |
1194 | |
1195 | |
1196 switch ( pix_bits ) | |
1197 { | |
1198 case 1: | |
1199 line_length = ( glyph_width + 7 ) >> 3; | |
1200 break; | |
1201 case 2: | |
1202 line_length = ( glyph_width + 3 ) >> 2; | |
1203 break; | |
1204 case 4: | |
1205 line_length = ( glyph_width + 1 ) >> 1; | |
1206 break; | |
1207 default: | |
1208 line_length = glyph_width; | |
1209 } | |
1210 | |
1211 glyph_size = glyph_height * line_length; | |
1212 pad_bytes = 1; | |
1213 } | |
1214 break; | 843 break; |
1215 | 844 |
1216 case 2: | 845 case 2: |
1217 case 5: | 846 case 5: |
1218 case 7: | 847 case 7: |
1219 line_bits = glyph_width * pix_bits; | 848 loader = tt_sbit_decoder_load_bit_aligned; |
1220 glyph_size = ( glyph_height * line_bits + 7 ) >> 3; | |
1221 break; | 849 break; |
1222 | 850 |
1223 default: /* invalid format */ | 851 case 8: |
1224 return SFNT_Err_Invalid_File_Format; | 852 if ( p + 1 > p_limit ) |
1225 } | 853 goto Fail; |
1226 | 854 |
1227 /* Now read data and draw glyph into target pixmap */ | 855 p += 1; /* skip padding */ |
1228 if ( FT_FRAME_ENTER( glyph_size ) ) | 856 /* fall-through */ |
1229 goto Exit; | 857 |
1230 | 858 case 9: |
1231 /* don't forget to multiply `x_offset' by `map->pix_bits' as */ | 859 loader = tt_sbit_decoder_load_compound; |
1232 /* the sbit blitter doesn't make a difference between pixmap */ | 860 break; |
1233 /* depths. */ | 861 |
1234 blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes, | 862 #ifdef FT_CONFIG_OPTION_USE_PNG |
1235 x_offset * pix_bits, y_offset, metrics->height ); | 863 case 17: /* small metrics, PNG image data */ |
1236 | 864 case 18: /* big metrics, PNG image data */ |
1237 FT_FRAME_EXIT(); | 865 case 19: /* metrics in EBLC, PNG image data */ |
1238 } | 866 loader = tt_sbit_decoder_load_png; |
| 867 break; |
| 868 #endif /* FT_CONFIG_OPTION_USE_PNG */ |
| 869 |
| 870 default: |
| 871 error = FT_THROW( Invalid_Table ); |
| 872 goto Fail; |
| 873 } |
| 874 |
| 875 if ( !decoder->bitmap_allocated ) |
| 876 { |
| 877 error = tt_sbit_decoder_alloc_bitmap( decoder, load_flags ); |
| 878 if ( error ) |
| 879 goto Fail; |
| 880 } |
| 881 |
| 882 if ( decoder->bit_depth == 32 && |
| 883 decoder->bitmap->pixel_mode != FT_PIXEL_MODE_BGRA ) |
| 884 { |
| 885 /* Flatten color bitmaps if color was not requested. */ |
| 886 |
| 887 FT_Library library = decoder->face->root.glyph->library; |
| 888 FT_Memory memory = decoder->stream->memory; |
| 889 |
| 890 FT_Bitmap color, *orig; |
| 891 |
| 892 |
| 893 if ( decoder->bitmap->pixel_mode != FT_PIXEL_MODE_GRAY || |
| 894 x_pos != 0 || y_pos != 0 ) |
| 895 { |
| 896 /* Shouldn't happen. */ |
| 897 error = FT_THROW( Invalid_Table ); |
| 898 goto Fail; |
| 899 } |
| 900 |
| 901 FT_Bitmap_New( &color ); |
| 902 |
| 903 color.rows = decoder->bitmap->rows; |
| 904 color.width = decoder->bitmap->width; |
| 905 color.pitch = color.width * 4; |
| 906 color.pixel_mode = FT_PIXEL_MODE_BGRA; |
| 907 |
| 908 if ( FT_ALLOC( color.buffer, color.rows * color.pitch ) ) |
| 909 goto Fail; |
| 910 |
| 911 orig = decoder->bitmap; |
| 912 decoder->bitmap = &color; |
| 913 |
| 914 error = loader( decoder, load_flags, p, p_limit, x_pos, y_pos ); |
| 915 |
| 916 decoder->bitmap = orig; |
| 917 |
| 918 /* explicitly test against FT_Err_Ok to avoid compiler warnings */ |
| 919 /* (we do an assignment within a conditional) */ |
| 920 if ( error || |
| 921 ( error = FT_Bitmap_Convert( library, |
| 922 &color, |
| 923 decoder->bitmap, |
| 924 1 ) ) != FT_Err_Ok ) |
| 925 { |
| 926 FT_Bitmap_Done( library, &color ); |
| 927 goto Fail; |
| 928 } |
| 929 |
| 930 FT_Bitmap_Done( library, &color ); |
| 931 } |
| 932 |
| 933 else |
| 934 error = loader( decoder, load_flags, p, p_limit, x_pos, y_pos ); |
| 935 } |
| 936 |
| 937 Fail: |
| 938 FT_FRAME_RELEASE( data ); |
1239 | 939 |
1240 Exit: | 940 Exit: |
1241 return error; | 941 return error; |
1242 } | 942 } |
1243 | 943 |
1244 | 944 |
1245 static FT_Error | 945 static FT_Error |
1246 Load_SBit_Image( TT_SBit_Strike strike, | 946 tt_sbit_decoder_load_image( TT_SBitDecoder decoder, |
1247 TT_SBit_Range range, | 947 FT_UInt load_flags, |
1248 FT_ULong ebdt_pos, | 948 FT_UInt glyph_index, |
1249 FT_ULong glyph_offset, | 949 FT_Int x_pos, |
1250 FT_GlyphSlot slot, | 950 FT_Int y_pos ) |
1251 FT_Int x_offset, | 951 { |
1252 FT_Int y_offset, | 952 /* |
1253 FT_Stream stream, | 953 * First, we find the correct strike range that applies to this |
1254 TT_SBit_Metrics metrics, | 954 * glyph index. |
1255 FT_Int depth ) | 955 */ |
1256 { | 956 |
1257 FT_Memory memory = stream->memory; | 957 FT_Byte* p = decoder->eblc_base + decoder->strike_index_array; |
1258 FT_Bitmap* map = &slot->bitmap; | 958 FT_Byte* p_limit = decoder->eblc_limit; |
1259 FT_Error error; | 959 FT_ULong num_ranges = decoder->strike_index_count; |
1260 | 960 FT_UInt start, end, index_format, image_format; |
1261 | 961 FT_ULong image_start = 0, image_end = 0, image_offset; |
1262 /* place stream at beginning of glyph data and read metrics */ | 962 |
1263 if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) ) | 963 |
1264 goto Exit; | 964 for ( ; num_ranges > 0; num_ranges-- ) |
1265 | 965 { |
1266 error = tt_load_sbit_metrics( stream, range, metrics ); | 966 start = FT_NEXT_USHORT( p ); |
1267 if ( error ) | 967 end = FT_NEXT_USHORT( p ); |
1268 goto Exit; | 968 |
1269 | 969 if ( glyph_index >= start && glyph_index <= end ) |
1270 /* This function is recursive. At the top-level call, we */ | 970 goto FoundRange; |
1271 /* compute the dimensions of the higher-level glyph to */ | 971 |
1272 /* allocate the final pixmap buffer. */ | 972 p += 4; /* ignore index offset */ |
1273 if ( depth == 0 ) | 973 } |
1274 { | 974 goto NoBitmap; |
1275 FT_Long size; | 975 |
1276 | 976 FoundRange: |
1277 | 977 image_offset = FT_NEXT_ULONG( p ); |
1278 map->width = metrics->width; | 978 |
1279 map->rows = metrics->height; | 979 /* overflow check */ |
1280 | 980 p = decoder->eblc_base + decoder->strike_index_array; |
1281 switch ( strike->bit_depth ) | 981 if ( image_offset > (FT_ULong)( p_limit - p ) ) |
1282 { | 982 goto Failure; |
1283 case 1: | 983 |
1284 map->pixel_mode = FT_PIXEL_MODE_MONO; | 984 p += image_offset; |
1285 map->pitch = ( map->width + 7 ) >> 3; | 985 if ( p + 8 > p_limit ) |
1286 break; | 986 goto NoBitmap; |
1287 | 987 |
1288 case 2: | 988 /* now find the glyph's location and extend within the ebdt table */ |
1289 map->pixel_mode = FT_PIXEL_MODE_GRAY2; | 989 index_format = FT_NEXT_USHORT( p ); |
1290 map->pitch = ( map->width + 3 ) >> 2; | 990 image_format = FT_NEXT_USHORT( p ); |
1291 break; | 991 image_offset = FT_NEXT_ULONG ( p ); |
1292 | 992 |
1293 case 4: | 993 switch ( index_format ) |
1294 map->pixel_mode = FT_PIXEL_MODE_GRAY4; | 994 { |
1295 map->pitch = ( map->width + 1 ) >> 1; | 995 case 1: /* 4-byte offsets relative to `image_offset' */ |
1296 break; | 996 { |
1297 | 997 p += 4 * ( glyph_index - start ); |
1298 case 8: | 998 if ( p + 8 > p_limit ) |
1299 map->pixel_mode = FT_PIXEL_MODE_GRAY; | 999 goto NoBitmap; |
1300 map->pitch = map->width; | 1000 |
1301 break; | 1001 image_start = FT_NEXT_ULONG( p ); |
1302 | 1002 image_end = FT_NEXT_ULONG( p ); |
1303 default: | 1003 |
1304 return SFNT_Err_Invalid_File_Format; | 1004 if ( image_start == image_end ) /* missing glyph */ |
1305 } | 1005 goto NoBitmap; |
1306 | 1006 } |
1307 size = map->rows * map->pitch; | |
1308 | |
1309 /* check that there is no empty image */ | |
1310 if ( size == 0 ) | |
1311 goto Exit; /* exit successfully! */ | |
1312 | |
1313 error = ft_glyphslot_alloc_bitmap( slot, size ); | |
1314 if (error) | |
1315 goto Exit; | |
1316 } | |
1317 | |
1318 switch ( range->image_format ) | |
1319 { | |
1320 case 1: /* single sbit image - load it */ | |
1321 case 2: | |
1322 case 5: | |
1323 case 6: | |
1324 case 7: | |
1325 return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth, | |
1326 range->image_format, metrics, stream ); | |
1327 | |
1328 case 8: /* compound format */ | |
1329 if ( FT_STREAM_SKIP( 1L ) ) | |
1330 { | |
1331 error = SFNT_Err_Invalid_Stream_Skip; | |
1332 goto Exit; | |
1333 } | |
1334 /* fallthrough */ | |
1335 | |
1336 case 9: | |
1337 break; | 1007 break; |
1338 | 1008 |
1339 default: /* invalid image format */ | 1009 case 2: /* big metrics, constant image size */ |
1340 return SFNT_Err_Invalid_File_Format; | 1010 { |
1341 } | 1011 FT_ULong image_size; |
1342 | 1012 |
1343 /* All right, we have a compound format. First of all, read */ | 1013 |
1344 /* the array of elements. */ | 1014 if ( p + 12 > p_limit ) |
1345 { | 1015 goto NoBitmap; |
1346 TT_SBit_Component components = NULL; | 1016 |
1347 TT_SBit_Component comp; | 1017 image_size = FT_NEXT_ULONG( p ); |
1348 FT_UShort num_components, count; | 1018 |
1349 | 1019 if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) ) |
1350 | 1020 goto NoBitmap; |
1351 if ( FT_READ_USHORT( num_components ) || | 1021 |
1352 FT_NEW_ARRAY( components, num_components ) ) | 1022 image_start = image_size * ( glyph_index - start ); |
1353 goto Exit; | 1023 image_end = image_start + image_size; |
1354 | 1024 } |
1355 count = num_components; | 1025 break; |
1356 | 1026 |
1357 if ( FT_FRAME_ENTER( 4L * num_components ) ) | 1027 case 3: /* 2-byte offsets relative to 'image_offset' */ |
1358 goto Fail_Memory; | 1028 { |
1359 | 1029 p += 2 * ( glyph_index - start ); |
1360 for ( comp = components; count > 0; count--, comp++ ) | 1030 if ( p + 4 > p_limit ) |
1361 { | 1031 goto NoBitmap; |
1362 comp->glyph_code = FT_GET_USHORT(); | 1032 |
1363 comp->x_offset = FT_GET_CHAR(); | 1033 image_start = FT_NEXT_USHORT( p ); |
1364 comp->y_offset = FT_GET_CHAR(); | 1034 image_end = FT_NEXT_USHORT( p ); |
1365 } | 1035 |
1366 | 1036 if ( image_start == image_end ) /* missing glyph */ |
1367 FT_FRAME_EXIT(); | 1037 goto NoBitmap; |
1368 | 1038 } |
1369 /* Now recursively load each element glyph */ | 1039 break; |
1370 count = num_components; | 1040 |
1371 comp = components; | 1041 case 4: /* sparse glyph array with (glyph,offset) pairs */ |
1372 for ( ; count > 0; count--, comp++ ) | 1042 { |
1373 { | 1043 FT_ULong mm, num_glyphs; |
1374 TT_SBit_Range elem_range; | 1044 |
1375 TT_SBit_MetricsRec elem_metrics; | 1045 |
1376 FT_ULong elem_offset; | 1046 if ( p + 4 > p_limit ) |
1377 | 1047 goto NoBitmap; |
1378 | 1048 |
1379 /* find the range for this element */ | 1049 num_glyphs = FT_NEXT_ULONG( p ); |
1380 error = find_sbit_range( comp->glyph_code, | 1050 |
1381 strike, | 1051 /* overflow check for p + ( num_glyphs + 1 ) * 4 */ |
1382 &elem_range, | 1052 if ( num_glyphs > (FT_ULong)( ( ( p_limit - p ) >> 2 ) - 1 ) ) |
1383 &elem_offset ); | 1053 goto NoBitmap; |
1384 if ( error ) | 1054 |
1385 goto Fail_Memory; | 1055 for ( mm = 0; mm < num_glyphs; mm++ ) |
1386 | 1056 { |
1387 /* now load the element, recursively */ | 1057 FT_UInt gindex = FT_NEXT_USHORT( p ); |
1388 error = Load_SBit_Image( strike, | 1058 |
1389 elem_range, | 1059 |
1390 ebdt_pos, | 1060 if ( gindex == glyph_index ) |
1391 elem_offset, | 1061 { |
1392 slot, | 1062 image_start = FT_NEXT_USHORT( p ); |
1393 x_offset + comp->x_offset, | 1063 p += 2; |
1394 y_offset + comp->y_offset, | 1064 image_end = FT_PEEK_USHORT( p ); |
1395 stream, | 1065 break; |
1396 &elem_metrics, | 1066 } |
1397 depth + 1 ); | 1067 p += 2; |
1398 if ( error ) | 1068 } |
1399 goto Fail_Memory; | 1069 |
1400 } | 1070 if ( mm >= num_glyphs ) |
1401 | 1071 goto NoBitmap; |
1402 Fail_Memory: | 1072 } |
1403 FT_FREE( components ); | 1073 break; |
1404 } | 1074 |
1405 | 1075 case 5: /* constant metrics with sparse glyph codes */ |
1406 Exit: | 1076 case 19: |
1407 return error; | 1077 { |
1408 } | 1078 FT_ULong image_size, mm, num_glyphs; |
1409 | 1079 |
1410 | 1080 |
1411 /*************************************************************************/ | 1081 if ( p + 16 > p_limit ) |
1412 /* */ | 1082 goto NoBitmap; |
1413 /* <Function> */ | 1083 |
1414 /* tt_face_load_sbit_image */ | 1084 image_size = FT_NEXT_ULONG( p ); |
1415 /* */ | 1085 |
1416 /* <Description> */ | 1086 if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) ) |
1417 /* Loads a given glyph sbit image from the font resource. This also */ | 1087 goto NoBitmap; |
1418 /* returns its metrics. */ | 1088 |
1419 /* */ | 1089 num_glyphs = FT_NEXT_ULONG( p ); |
1420 /* <Input> */ | 1090 |
1421 /* face :: The target face object. */ | 1091 /* overflow check for p + 2 * num_glyphs */ |
1422 /* */ | 1092 if ( num_glyphs > (FT_ULong)( ( p_limit - p ) >> 1 ) ) |
1423 /* strike_index :: The current strike index. */ | 1093 goto NoBitmap; |
1424 /* */ | 1094 |
1425 /* glyph_index :: The current glyph index. */ | 1095 for ( mm = 0; mm < num_glyphs; mm++ ) |
1426 /* */ | 1096 { |
1427 /* load_flags :: The glyph load flags (the code checks for the flag */ | 1097 FT_UInt gindex = FT_NEXT_USHORT( p ); |
1428 /* FT_LOAD_CROP_BITMAP). */ | 1098 |
1429 /* */ | 1099 |
1430 /* stream :: The input stream. */ | 1100 if ( gindex == glyph_index ) |
1431 /* */ | 1101 break; |
1432 /* <Output> */ | 1102 } |
1433 /* map :: The target pixmap. */ | 1103 |
1434 /* */ | 1104 if ( mm >= num_glyphs ) |
1435 /* metrics :: A big sbit metrics structure for the glyph image. */ | 1105 goto NoBitmap; |
1436 /* */ | 1106 |
1437 /* <Return> */ | 1107 image_start = image_size * mm; |
1438 /* FreeType error code. 0 means success. Returns an error if no */ | 1108 image_end = image_start + image_size; |
1439 /* glyph sbit exists for the index. */ | 1109 } |
1440 /* */ | 1110 break; |
1441 /* <Note> */ | 1111 |
1442 /* The `map.buffer' field is always freed before the glyph is loaded. */ | 1112 default: |
1443 /* */ | 1113 goto NoBitmap; |
1444 FT_LOCAL_DEF( FT_Error ) | 1114 } |
| 1115 |
| 1116 if ( image_start > image_end ) |
| 1117 goto NoBitmap; |
| 1118 |
| 1119 image_end -= image_start; |
| 1120 image_start = image_offset + image_start; |
| 1121 |
| 1122 FT_TRACE3(( "tt_sbit_decoder_load_image:" |
| 1123 " found sbit (format %d) for glyph index %d\n", |
| 1124 image_format, glyph_index )); |
| 1125 |
| 1126 return tt_sbit_decoder_load_bitmap( decoder, |
| 1127 load_flags, |
| 1128 image_format, |
| 1129 image_start, |
| 1130 image_end, |
| 1131 x_pos, |
| 1132 y_pos ); |
| 1133 |
| 1134 Failure: |
| 1135 return FT_THROW( Invalid_Table ); |
| 1136 |
| 1137 NoBitmap: |
| 1138 FT_TRACE4(( "tt_sbit_decoder_load_image:" |
| 1139 " no sbit found for glyph index %d\n", glyph_index )); |
| 1140 |
| 1141 return FT_THROW( Invalid_Argument ); |
| 1142 } |
| 1143 |
| 1144 |
| 1145 FT_LOCAL( FT_Error ) |
1445 tt_face_load_sbit_image( TT_Face face, | 1146 tt_face_load_sbit_image( TT_Face face, |
1446 FT_ULong strike_index, | 1147 FT_ULong strike_index, |
1447 FT_UInt glyph_index, | 1148 FT_UInt glyph_index, |
1448 FT_UInt load_flags, | 1149 FT_UInt load_flags, |
1449 FT_Stream stream, | 1150 FT_Stream stream, |
1450 FT_Bitmap *map, | 1151 FT_Bitmap *map, |
1451 TT_SBit_MetricsRec *metrics ) | 1152 TT_SBit_MetricsRec *metrics ) |
1452 { | 1153 { |
1453 FT_Error error; | 1154 TT_SBitDecoderRec decoder[1]; |
1454 FT_ULong ebdt_pos, glyph_offset; | 1155 FT_Error error; |
1455 | 1156 |
1456 TT_SBit_Strike strike; | 1157 FT_UNUSED( load_flags ); |
1457 TT_SBit_Range range; | 1158 FT_UNUSED( stream ); |
| 1159 FT_UNUSED( map ); |
1458 | 1160 |
1459 | 1161 |
1460 /* Check whether there is a glyph sbit for the current index */ | 1162 error = tt_sbit_decoder_init( decoder, face, strike_index, metrics ); |
1461 error = tt_find_sbit_image( face, glyph_index, strike_index, | 1163 if ( !error ) |
1462 &range, &strike, &glyph_offset ); | |
1463 if ( error ) | |
1464 goto Exit; | |
1465 | |
1466 /* now, find the location of the `EBDT' table in */ | |
1467 /* the font file */ | |
1468 error = face->goto_table( face, TTAG_EBDT, stream, 0 ); | |
1469 if ( error ) | |
1470 error = face->goto_table( face, TTAG_bdat, stream, 0 ); | |
1471 if ( error ) | |
1472 goto Exit; | |
1473 | |
1474 ebdt_pos = FT_STREAM_POS(); | |
1475 | |
1476 error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset, | |
1477 face->root.glyph, 0, 0, stream, metrics, 0 ); | |
1478 if ( error ) | |
1479 goto Exit; | |
1480 | |
1481 /* setup vertical metrics if needed */ | |
1482 if ( strike->flags & 1 ) | |
1483 { | 1164 { |
1484 /* in case of a horizontal strike only */ | 1165 error = tt_sbit_decoder_load_image( decoder, |
1485 FT_Int advance; | 1166 load_flags, |
1486 | 1167 glyph_index, |
1487 | 1168 0, |
1488 advance = strike->hori.ascender - strike->hori.descender; | 1169 0 ); |
1489 | 1170 tt_sbit_decoder_done( decoder ); |
1490 /* some heuristic values */ | |
1491 | |
1492 metrics->vertBearingX = (FT_Char)(-metrics->width / 2 ); | |
1493 metrics->vertBearingY = (FT_Char)( ( advance - metrics->height ) / 2 ); | |
1494 metrics->vertAdvance = (FT_Char)( advance * 12 / 10 ); | |
1495 } | 1171 } |
1496 | 1172 |
1497 /* Crop the bitmap now, unless specified otherwise */ | |
1498 if ( load_flags & FT_LOAD_CROP_BITMAP ) | |
1499 crop_bitmap( map, metrics ); | |
1500 | |
1501 Exit: | |
1502 return error; | 1173 return error; |
1503 } | 1174 } |
1504 | 1175 |
1505 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ | |
1506 | 1176 |
1507 | 1177 /* EOF */ |
1508 /* END */ | |
OLD | NEW |