Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /***************************************************************************/ |
2 | /* */ |
||
3 | /* ttsbit.c */ |
||
4 | /* */ |
||
5 | /* TrueType and OpenType embedded bitmap support (body). */ |
||
6 | /* */ |
||
7 | /* Copyright 2005-2009, 2013 by */ |
||
8 | /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
||
9 | /* */ |
||
10 | /* Copyright 2013 by Google, Inc. */ |
||
11 | /* Google Author(s): Behdad Esfahbod. */ |
||
12 | /* */ |
||
13 | /* This file is part of the FreeType project, and may only be used, */ |
||
14 | /* modified, and distributed under the terms of the FreeType project */ |
||
15 | /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
||
16 | /* this file you indicate that you have read the license and */ |
||
17 | /* understand and accept it fully. */ |
||
18 | /* */ |
||
19 | /***************************************************************************/ |
||
20 | |||
21 | |||
22 | #include |
||
23 | #include FT_INTERNAL_DEBUG_H |
||
24 | #include FT_INTERNAL_STREAM_H |
||
25 | #include FT_TRUETYPE_TAGS_H |
||
26 | #include FT_BITMAP_H |
||
27 | #include "ttsbit.h" |
||
28 | |||
29 | #include "sferrors.h" |
||
30 | |||
31 | #include "pngshim.h" |
||
32 | |||
33 | |||
34 | /*************************************************************************/ |
||
35 | /* */ |
||
36 | /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
||
37 | /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
||
38 | /* messages during execution. */ |
||
39 | /* */ |
||
40 | #undef FT_COMPONENT |
||
41 | #define FT_COMPONENT trace_ttsbit |
||
42 | |||
43 | |||
44 | FT_LOCAL_DEF( FT_Error ) |
||
45 | tt_face_load_eblc( TT_Face face, |
||
46 | FT_Stream stream ) |
||
47 | { |
||
48 | FT_Error error = FT_Err_Ok; |
||
49 | FT_Fixed version; |
||
50 | FT_ULong num_strikes, table_size; |
||
51 | FT_Byte* p; |
||
52 | FT_Byte* p_limit; |
||
53 | FT_UInt count; |
||
54 | |||
55 | |||
56 | face->sbit_num_strikes = 0; |
||
57 | |||
58 | /* this table is optional */ |
||
59 | error = face->goto_table( face, TTAG_CBLC, stream, &table_size ); |
||
60 | if ( error ) |
||
61 | error = face->goto_table( face, TTAG_EBLC, stream, &table_size ); |
||
62 | if ( error ) |
||
63 | error = face->goto_table( face, TTAG_bloc, stream, &table_size ); |
||
64 | if ( error ) |
||
65 | goto Exit; |
||
66 | |||
67 | if ( table_size < 8 ) |
||
68 | { |
||
69 | FT_ERROR(( "tt_face_load_sbit_strikes: table too short\n" )); |
||
70 | error = FT_THROW( Invalid_File_Format ); |
||
71 | goto Exit; |
||
72 | } |
||
73 | |||
74 | if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) ) |
||
75 | goto Exit; |
||
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 ) |
||
86 | { |
||
87 | FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" )); |
||
88 | error = FT_THROW( Invalid_File_Format ); |
||
89 | goto Fail; |
||
90 | } |
||
91 | |||
92 | /* |
||
93 | * Count the number of strikes available in the table. We are a bit |
||
94 | * paranoid there and don't trust the data. |
||
95 | */ |
||
96 | count = (FT_UInt)num_strikes; |
||
97 | if ( 8 + 48UL * count > table_size ) |
||
98 | count = (FT_UInt)( ( p_limit - p ) / 48 ); |
||
99 | |||
100 | face->sbit_num_strikes = count; |
||
101 | |||
102 | FT_TRACE3(( "sbit_num_strikes: %u\n", count )); |
||
103 | Exit: |
||
104 | return error; |
||
105 | |||
106 | Fail: |
||
107 | FT_FRAME_RELEASE( face->sbit_table ); |
||
108 | face->sbit_table_size = 0; |
||
109 | goto Exit; |
||
110 | } |
||
111 | |||
112 | |||
113 | FT_LOCAL_DEF( void ) |
||
114 | tt_face_free_eblc( TT_Face face ) |
||
115 | { |
||
116 | FT_Stream stream = face->root.stream; |
||
117 | |||
118 | |||
119 | FT_FRAME_RELEASE( face->sbit_table ); |
||
120 | face->sbit_table_size = 0; |
||
121 | face->sbit_num_strikes = 0; |
||
122 | } |
||
123 | |||
124 | |||
125 | FT_LOCAL_DEF( FT_Error ) |
||
126 | tt_face_set_sbit_strike( TT_Face face, |
||
127 | FT_Size_Request req, |
||
128 | FT_ULong* astrike_index ) |
||
129 | { |
||
130 | return FT_Match_Size( (FT_Face)face, req, 0, astrike_index ); |
||
131 | } |
||
132 | |||
133 | |||
134 | FT_LOCAL_DEF( FT_Error ) |
||
135 | tt_face_load_strike_metrics( TT_Face face, |
||
136 | FT_ULong strike_index, |
||
137 | FT_Size_Metrics* metrics ) |
||
138 | { |
||
139 | FT_Byte* strike; |
||
140 | |||
141 | |||
142 | if ( strike_index >= (FT_ULong)face->sbit_num_strikes ) |
||
143 | return FT_THROW( Invalid_Argument ); |
||
144 | |||
145 | strike = face->sbit_table + 8 + strike_index * 48; |
||
146 | |||
147 | metrics->x_ppem = (FT_UShort)strike[44]; |
||
148 | metrics->y_ppem = (FT_UShort)strike[45]; |
||
149 | |||
150 | metrics->ascender = (FT_Char)strike[16] << 6; /* hori.ascender */ |
||
151 | metrics->descender = (FT_Char)strike[17] << 6; /* hori.descender */ |
||
152 | metrics->height = metrics->ascender - metrics->descender; |
||
153 | |||
154 | /* XXX: Is this correct? */ |
||
155 | metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */ |
||
156 | strike[18] + /* max_width */ |
||
157 | (FT_Char)strike[23] /* min_advance_SB */ |
||
158 | ) << 6; |
||
159 | |||
160 | return FT_Err_Ok; |
||
161 | } |
||
162 | |||
163 | |||
164 | typedef struct TT_SBitDecoderRec_ |
||
165 | { |
||
166 | TT_Face face; |
||
167 | FT_Stream stream; |
||
168 | FT_Bitmap* bitmap; |
||
169 | TT_SBit_Metrics metrics; |
||
170 | FT_Bool metrics_loaded; |
||
171 | FT_Bool bitmap_allocated; |
||
172 | FT_Byte bit_depth; |
||
173 | |||
174 | FT_ULong ebdt_start; |
||
175 | FT_ULong ebdt_size; |
||
176 | |||
177 | FT_ULong strike_index_array; |
||
178 | FT_ULong strike_index_count; |
||
179 | FT_Byte* eblc_base; |
||
180 | FT_Byte* eblc_limit; |
||
181 | |||
182 | } TT_SBitDecoderRec, *TT_SBitDecoder; |
||
183 | |||
184 | |||
185 | static FT_Error |
||
186 | tt_sbit_decoder_init( TT_SBitDecoder decoder, |
||
187 | TT_Face face, |
||
188 | FT_ULong strike_index, |
||
189 | TT_SBit_MetricsRec* metrics ) |
||
190 | { |
||
191 | FT_Error error; |
||
192 | FT_Stream stream = face->root.stream; |
||
193 | FT_ULong ebdt_size; |
||
194 | |||
195 | |||
196 | error = face->goto_table( face, TTAG_CBDT, stream, &ebdt_size ); |
||
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 ) |
||
351 | goto Fail; |
||
352 | |||
353 | metrics->height = p[0]; |
||
354 | metrics->width = p[1]; |
||
355 | metrics->horiBearingX = (FT_Char)p[2]; |
||
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 ) |
||
685 | goto Fail; |
||
686 | |||
687 | num_components = FT_NEXT_USHORT( p ); |
||
688 | if ( p + 4 * num_components > limit ) |
||
689 | { |
||
690 | FT_TRACE1(( "tt_sbit_decoder_load_compound: broken table\n" )); |
||
691 | goto Fail; |
||
692 | } |
||
693 | |||
694 | FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d components\n", |
||
695 | num_components )); |
||
696 | |||
697 | for ( nn = 0; nn < num_components; nn++ ) |
||
698 | { |
||
699 | FT_UInt gindex = FT_NEXT_USHORT( p ); |
||
700 | FT_Byte dx = FT_NEXT_BYTE( p ); |
||
701 | FT_Byte dy = FT_NEXT_BYTE( p ); |
||
702 | |||
703 | |||
704 | /* NB: a recursive call */ |
||
705 | error = tt_sbit_decoder_load_image( decoder, load_flags, gindex, |
||
706 | x_pos + dx, y_pos + dy ); |
||
707 | if ( error ) |
||
708 | break; |
||
709 | } |
||
710 | |||
711 | FT_TRACE3(( "tt_sbit_decoder_load_compound: done\n" )); |
||
712 | |||
713 | decoder->metrics->horiBearingX = horiBearingX; |
||
714 | decoder->metrics->horiBearingY = horiBearingY; |
||
715 | decoder->metrics->horiAdvance = horiAdvance; |
||
716 | decoder->metrics->vertBearingX = vertBearingX; |
||
717 | decoder->metrics->vertBearingY = vertBearingY; |
||
718 | decoder->metrics->vertAdvance = vertAdvance; |
||
719 | decoder->metrics->width = (FT_Byte)decoder->bitmap->width; |
||
720 | decoder->metrics->height = (FT_Byte)decoder->bitmap->rows; |
||
721 | |||
722 | Exit: |
||
723 | return error; |
||
724 | |||
725 | Fail: |
||
726 | error = FT_THROW( Invalid_File_Format ); |
||
727 | goto Exit; |
||
728 | } |
||
729 | |||
730 | |||
731 | #ifdef FT_CONFIG_OPTION_USE_PNG |
||
732 | |||
733 | static FT_Error |
||
734 | tt_sbit_decoder_load_png( TT_SBitDecoder decoder, |
||
735 | FT_UInt load_flags, |
||
736 | FT_Byte* p, |
||
737 | FT_Byte* limit, |
||
738 | FT_Int x_pos, |
||
739 | FT_Int y_pos ) |
||
740 | { |
||
741 | FT_Error error = FT_Err_Ok; |
||
742 | FT_ULong png_len; |
||
743 | |||
744 | FT_UNUSED( load_flags ); |
||
745 | |||
746 | |||
747 | if ( limit - p < 4 ) |
||
748 | { |
||
749 | FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" )); |
||
750 | error = FT_THROW( Invalid_File_Format ); |
||
751 | goto Exit; |
||
752 | } |
||
753 | |||
754 | png_len = FT_NEXT_ULONG( p ); |
||
755 | if ( (FT_ULong)( limit - p ) < png_len ) |
||
756 | { |
||
757 | FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" )); |
||
758 | error = FT_THROW( Invalid_File_Format ); |
||
759 | goto Exit; |
||
760 | } |
||
761 | |||
762 | error = Load_SBit_Png( decoder->bitmap, |
||
763 | x_pos, |
||
764 | y_pos, |
||
765 | decoder->bit_depth, |
||
766 | decoder->metrics, |
||
767 | decoder->stream->memory, |
||
768 | p, |
||
769 | png_len ); |
||
770 | |||
771 | Exit: |
||
772 | if ( !error ) |
||
773 | FT_TRACE3(( "tt_sbit_decoder_load_png: loaded\n" )); |
||
774 | return error; |
||
775 | } |
||
776 | |||
777 | #endif /* FT_CONFIG_OPTION_USE_PNG */ |
||
778 | |||
779 | |||
780 | static FT_Error |
||
781 | tt_sbit_decoder_load_bitmap( TT_SBitDecoder decoder, |
||
782 | FT_UInt load_flags, |
||
783 | FT_UInt glyph_format, |
||
784 | FT_ULong glyph_start, |
||
785 | FT_ULong glyph_size, |
||
786 | FT_Int x_pos, |
||
787 | FT_Int y_pos ) |
||
788 | { |
||
789 | FT_Error error; |
||
790 | FT_Stream stream = decoder->stream; |
||
791 | FT_Byte* p; |
||
792 | FT_Byte* p_limit; |
||
793 | FT_Byte* data; |
||
794 | |||
795 | |||
796 | /* seek into the EBDT table now */ |
||
797 | if ( glyph_start + glyph_size > decoder->ebdt_size ) |
||
798 | { |
||
799 | error = FT_THROW( Invalid_Argument ); |
||
800 | goto Exit; |
||
801 | } |
||
802 | |||
803 | if ( FT_STREAM_SEEK( decoder->ebdt_start + glyph_start ) || |
||
804 | FT_FRAME_EXTRACT( glyph_size, data ) ) |
||
805 | goto Exit; |
||
806 | |||
807 | p = data; |
||
808 | p_limit = p + glyph_size; |
||
809 | |||
810 | /* read the data, depending on the glyph format */ |
||
811 | switch ( glyph_format ) |
||
812 | { |
||
813 | case 1: |
||
814 | case 2: |
||
815 | case 8: |
||
816 | case 17: |
||
817 | error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 0 ); |
||
818 | break; |
||
819 | |||
820 | case 6: |
||
821 | case 7: |
||
822 | case 9: |
||
823 | case 18: |
||
824 | error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ); |
||
825 | break; |
||
826 | |||
827 | default: |
||
828 | error = FT_Err_Ok; |
||
829 | } |
||
830 | |||
831 | if ( error ) |
||
832 | goto Fail; |
||
833 | |||
834 | { |
||
835 | TT_SBitDecoder_LoadFunc loader; |
||
836 | |||
837 | |||
838 | switch ( glyph_format ) |
||
839 | { |
||
840 | case 1: |
||
841 | case 6: |
||
842 | loader = tt_sbit_decoder_load_byte_aligned; |
||
843 | break; |
||
844 | |||
845 | case 2: |
||
846 | case 5: |
||
847 | case 7: |
||
848 | loader = tt_sbit_decoder_load_bit_aligned; |
||
849 | break; |
||
850 | |||
851 | case 8: |
||
852 | if ( p + 1 > p_limit ) |
||
853 | goto Fail; |
||
854 | |||
855 | p += 1; /* skip padding */ |
||
856 | /* fall-through */ |
||
857 | |||
858 | case 9: |
||
859 | loader = tt_sbit_decoder_load_compound; |
||
860 | break; |
||
861 | |||
862 | #ifdef FT_CONFIG_OPTION_USE_PNG |
||
863 | case 17: /* small metrics, PNG image data */ |
||
864 | case 18: /* big metrics, PNG image data */ |
||
865 | case 19: /* metrics in EBLC, PNG image data */ |
||
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 ); |
||
939 | |||
940 | Exit: |
||
941 | return error; |
||
942 | } |
||
943 | |||
944 | |||
945 | static FT_Error |
||
946 | tt_sbit_decoder_load_image( TT_SBitDecoder decoder, |
||
947 | FT_UInt load_flags, |
||
948 | FT_UInt glyph_index, |
||
949 | FT_Int x_pos, |
||
950 | FT_Int y_pos ) |
||
951 | { |
||
952 | /* |
||
953 | * First, we find the correct strike range that applies to this |
||
954 | * glyph index. |
||
955 | */ |
||
956 | |||
957 | FT_Byte* p = decoder->eblc_base + decoder->strike_index_array; |
||
958 | FT_Byte* p_limit = decoder->eblc_limit; |
||
959 | FT_ULong num_ranges = decoder->strike_index_count; |
||
960 | FT_UInt start, end, index_format, image_format; |
||
961 | FT_ULong image_start = 0, image_end = 0, image_offset; |
||
962 | |||
963 | |||
964 | for ( ; num_ranges > 0; num_ranges-- ) |
||
965 | { |
||
966 | start = FT_NEXT_USHORT( p ); |
||
967 | end = FT_NEXT_USHORT( p ); |
||
968 | |||
969 | if ( glyph_index >= start && glyph_index <= end ) |
||
970 | goto FoundRange; |
||
971 | |||
972 | p += 4; /* ignore index offset */ |
||
973 | } |
||
974 | goto NoBitmap; |
||
975 | |||
976 | FoundRange: |
||
977 | image_offset = FT_NEXT_ULONG( p ); |
||
978 | |||
979 | /* overflow check */ |
||
980 | p = decoder->eblc_base + decoder->strike_index_array; |
||
981 | if ( image_offset > (FT_ULong)( p_limit - p ) ) |
||
982 | goto Failure; |
||
983 | |||
984 | p += image_offset; |
||
985 | if ( p + 8 > p_limit ) |
||
986 | goto NoBitmap; |
||
987 | |||
988 | /* now find the glyph's location and extend within the ebdt table */ |
||
989 | index_format = FT_NEXT_USHORT( p ); |
||
990 | image_format = FT_NEXT_USHORT( p ); |
||
991 | image_offset = FT_NEXT_ULONG ( p ); |
||
992 | |||
993 | switch ( index_format ) |
||
994 | { |
||
995 | case 1: /* 4-byte offsets relative to `image_offset' */ |
||
996 | { |
||
997 | p += 4 * ( glyph_index - start ); |
||
998 | if ( p + 8 > p_limit ) |
||
999 | goto NoBitmap; |
||
1000 | |||
1001 | image_start = FT_NEXT_ULONG( p ); |
||
1002 | image_end = FT_NEXT_ULONG( p ); |
||
1003 | |||
1004 | if ( image_start == image_end ) /* missing glyph */ |
||
1005 | goto NoBitmap; |
||
1006 | } |
||
1007 | break; |
||
1008 | |||
1009 | case 2: /* big metrics, constant image size */ |
||
1010 | { |
||
1011 | FT_ULong image_size; |
||
1012 | |||
1013 | |||
1014 | if ( p + 12 > p_limit ) |
||
1015 | goto NoBitmap; |
||
1016 | |||
1017 | image_size = FT_NEXT_ULONG( p ); |
||
1018 | |||
1019 | if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) ) |
||
1020 | goto NoBitmap; |
||
1021 | |||
1022 | image_start = image_size * ( glyph_index - start ); |
||
1023 | image_end = image_start + image_size; |
||
1024 | } |
||
1025 | break; |
||
1026 | |||
1027 | case 3: /* 2-byte offsets relative to 'image_offset' */ |
||
1028 | { |
||
1029 | p += 2 * ( glyph_index - start ); |
||
1030 | if ( p + 4 > p_limit ) |
||
1031 | goto NoBitmap; |
||
1032 | |||
1033 | image_start = FT_NEXT_USHORT( p ); |
||
1034 | image_end = FT_NEXT_USHORT( p ); |
||
1035 | |||
1036 | if ( image_start == image_end ) /* missing glyph */ |
||
1037 | goto NoBitmap; |
||
1038 | } |
||
1039 | break; |
||
1040 | |||
1041 | case 4: /* sparse glyph array with (glyph,offset) pairs */ |
||
1042 | { |
||
1043 | FT_ULong mm, num_glyphs; |
||
1044 | |||
1045 | |||
1046 | if ( p + 4 > p_limit ) |
||
1047 | goto NoBitmap; |
||
1048 | |||
1049 | num_glyphs = FT_NEXT_ULONG( p ); |
||
1050 | |||
1051 | /* overflow check for p + ( num_glyphs + 1 ) * 4 */ |
||
1052 | if ( num_glyphs > (FT_ULong)( ( ( p_limit - p ) >> 2 ) - 1 ) ) |
||
1053 | goto NoBitmap; |
||
1054 | |||
1055 | for ( mm = 0; mm < num_glyphs; mm++ ) |
||
1056 | { |
||
1057 | FT_UInt gindex = FT_NEXT_USHORT( p ); |
||
1058 | |||
1059 | |||
1060 | if ( gindex == glyph_index ) |
||
1061 | { |
||
1062 | image_start = FT_NEXT_USHORT( p ); |
||
1063 | p += 2; |
||
1064 | image_end = FT_PEEK_USHORT( p ); |
||
1065 | break; |
||
1066 | } |
||
1067 | p += 2; |
||
1068 | } |
||
1069 | |||
1070 | if ( mm >= num_glyphs ) |
||
1071 | goto NoBitmap; |
||
1072 | } |
||
1073 | break; |
||
1074 | |||
1075 | case 5: /* constant metrics with sparse glyph codes */ |
||
1076 | case 19: |
||
1077 | { |
||
1078 | FT_ULong image_size, mm, num_glyphs; |
||
1079 | |||
1080 | |||
1081 | if ( p + 16 > p_limit ) |
||
1082 | goto NoBitmap; |
||
1083 | |||
1084 | image_size = FT_NEXT_ULONG( p ); |
||
1085 | |||
1086 | if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) ) |
||
1087 | goto NoBitmap; |
||
1088 | |||
1089 | num_glyphs = FT_NEXT_ULONG( p ); |
||
1090 | |||
1091 | /* overflow check for p + 2 * num_glyphs */ |
||
1092 | if ( num_glyphs > (FT_ULong)( ( p_limit - p ) >> 1 ) ) |
||
1093 | goto NoBitmap; |
||
1094 | |||
1095 | for ( mm = 0; mm < num_glyphs; mm++ ) |
||
1096 | { |
||
1097 | FT_UInt gindex = FT_NEXT_USHORT( p ); |
||
1098 | |||
1099 | |||
1100 | if ( gindex == glyph_index ) |
||
1101 | break; |
||
1102 | } |
||
1103 | |||
1104 | if ( mm >= num_glyphs ) |
||
1105 | goto NoBitmap; |
||
1106 | |||
1107 | image_start = image_size * mm; |
||
1108 | image_end = image_start + image_size; |
||
1109 | } |
||
1110 | break; |
||
1111 | |||
1112 | default: |
||
1113 | goto NoBitmap; |
||
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 ) |
||
1146 | tt_face_load_sbit_image( TT_Face face, |
||
1147 | FT_ULong strike_index, |
||
1148 | FT_UInt glyph_index, |
||
1149 | FT_UInt load_flags, |
||
1150 | FT_Stream stream, |
||
1151 | FT_Bitmap *map, |
||
1152 | TT_SBit_MetricsRec *metrics ) |
||
1153 | { |
||
1154 | TT_SBitDecoderRec decoder[1]; |
||
1155 | FT_Error error; |
||
1156 | |||
1157 | FT_UNUSED( load_flags ); |
||
1158 | FT_UNUSED( stream ); |
||
1159 | FT_UNUSED( map ); |
||
1160 | |||
1161 | |||
1162 | error = tt_sbit_decoder_init( decoder, face, strike_index, metrics ); |
||
1163 | if ( !error ) |
||
1164 | { |
||
1165 | error = tt_sbit_decoder_load_image( decoder, |
||
1166 | load_flags, |
||
1167 | glyph_index, |
||
1168 | 0, |
||
1169 | |||
1170 | tt_sbit_decoder_done( decoder ); |
||
1171 | } |
||
1172 | |||
1173 | return error; |
||
1174 | } |
||
1175 | |||
1176 | |||
1177 | /* EOF */>>=>>>>=><=>>>=><=>=><=>><>><>>>>>>=><=>=><=>>>><>><>><>> |