[FREETYPE]
[reactos.git] / reactos / lib / 3rdparty / freetype / src / sfnt / ttsbit.c
1 /***************************************************************************/
2 /* */
3 /* ttsbit.c */
4 /* */
5 /* TrueType and OpenType embedded bitmap support (body). */
6 /* */
7 /* Copyright 2005-2009, 2013, 2014 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 <ft2build.h>
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 "ttmtx.h"
32 #include "pngshim.h"
33
34
35 /*************************************************************************/
36 /* */
37 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
38 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
39 /* messages during execution. */
40 /* */
41 #undef FT_COMPONENT
42 #define FT_COMPONENT trace_ttsbit
43
44
45 FT_LOCAL_DEF( FT_Error )
46 tt_face_load_sbit( TT_Face face,
47 FT_Stream stream )
48 {
49 FT_Error error;
50 FT_ULong table_size;
51
52
53 face->sbit_table = NULL;
54 face->sbit_table_size = 0;
55 face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE;
56 face->sbit_num_strikes = 0;
57
58 error = face->goto_table( face, TTAG_CBLC, stream, &table_size );
59 if ( !error )
60 face->sbit_table_type = TT_SBIT_TABLE_TYPE_CBLC;
61 else
62 {
63 error = face->goto_table( face, TTAG_EBLC, stream, &table_size );
64 if ( error )
65 error = face->goto_table( face, TTAG_bloc, stream, &table_size );
66 if ( !error )
67 face->sbit_table_type = TT_SBIT_TABLE_TYPE_EBLC;
68 }
69
70 if ( error )
71 {
72 error = face->goto_table( face, TTAG_sbix, stream, &table_size );
73 if ( !error )
74 face->sbit_table_type = TT_SBIT_TABLE_TYPE_SBIX;
75 }
76 if ( error )
77 goto Exit;
78
79 if ( table_size < 8 )
80 {
81 FT_ERROR(( "tt_face_load_sbit_strikes: table too short\n" ));
82 error = FT_THROW( Invalid_File_Format );
83 goto Exit;
84 }
85
86 switch ( (FT_UInt)face->sbit_table_type )
87 {
88 case TT_SBIT_TABLE_TYPE_EBLC:
89 case TT_SBIT_TABLE_TYPE_CBLC:
90 {
91 FT_Byte* p;
92 FT_Fixed version;
93 FT_ULong num_strikes;
94 FT_UInt count;
95
96
97 if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
98 goto Exit;
99
100 face->sbit_table_size = table_size;
101
102 p = face->sbit_table;
103
104 version = FT_NEXT_ULONG( p );
105 num_strikes = FT_NEXT_ULONG( p );
106
107 if ( ( version & 0xFFFF0000UL ) != 0x00020000UL )
108 {
109 error = FT_THROW( Unknown_File_Format );
110 goto Exit;
111 }
112
113 if ( num_strikes >= 0x10000UL )
114 {
115 error = FT_THROW( Invalid_File_Format );
116 goto Exit;
117 }
118
119 /*
120 * Count the number of strikes available in the table. We are a bit
121 * paranoid there and don't trust the data.
122 */
123 count = (FT_UInt)num_strikes;
124 if ( 8 + 48UL * count > table_size )
125 count = (FT_UInt)( ( table_size - 8 ) / 48 );
126
127 face->sbit_num_strikes = count;
128 }
129 break;
130
131 case TT_SBIT_TABLE_TYPE_SBIX:
132 {
133 FT_UShort version;
134 FT_UShort flags;
135 FT_ULong num_strikes;
136 FT_UInt count;
137
138
139 if ( FT_FRAME_ENTER( 8 ) )
140 goto Exit;
141
142 version = FT_GET_USHORT();
143 flags = FT_GET_USHORT();
144 num_strikes = FT_GET_ULONG();
145
146 FT_FRAME_EXIT();
147
148 if ( version < 1 )
149 {
150 error = FT_THROW( Unknown_File_Format );
151 goto Exit;
152 }
153 if ( flags != 0x0001 || num_strikes >= 0x10000UL )
154 {
155 error = FT_THROW( Invalid_File_Format );
156 goto Exit;
157 }
158
159 /*
160 * Count the number of strikes available in the table. We are a bit
161 * paranoid there and don't trust the data.
162 */
163 count = (FT_UInt)num_strikes;
164 if ( 8 + 4UL * count > table_size )
165 count = (FT_UInt)( ( table_size - 8 ) / 4 );
166
167 if ( FT_STREAM_SEEK( FT_STREAM_POS() - 8 ) )
168 goto Exit;
169
170 face->sbit_table_size = 8 + count * 4;
171 if ( FT_FRAME_EXTRACT( face->sbit_table_size, face->sbit_table ) )
172 goto Exit;
173
174 face->sbit_num_strikes = count;
175 }
176 break;
177
178 default:
179 error = FT_THROW( Unknown_File_Format );
180 break;
181 }
182
183 if ( !error )
184 FT_TRACE3(( "sbit_num_strikes: %u\n", face->sbit_num_strikes ));
185
186 return FT_Err_Ok;
187
188 Exit:
189 if ( error )
190 {
191 if ( face->sbit_table )
192 FT_FRAME_RELEASE( face->sbit_table );
193 face->sbit_table_size = 0;
194 face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE;
195 }
196
197 return error;
198 }
199
200
201 FT_LOCAL_DEF( void )
202 tt_face_free_sbit( TT_Face face )
203 {
204 FT_Stream stream = face->root.stream;
205
206
207 FT_FRAME_RELEASE( face->sbit_table );
208 face->sbit_table_size = 0;
209 face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE;
210 face->sbit_num_strikes = 0;
211 }
212
213
214 FT_LOCAL_DEF( FT_Error )
215 tt_face_set_sbit_strike( TT_Face face,
216 FT_Size_Request req,
217 FT_ULong* astrike_index )
218 {
219 return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );
220 }
221
222
223 FT_LOCAL_DEF( FT_Error )
224 tt_face_load_strike_metrics( TT_Face face,
225 FT_ULong strike_index,
226 FT_Size_Metrics* metrics )
227 {
228 if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
229 return FT_THROW( Invalid_Argument );
230
231 switch ( (FT_UInt)face->sbit_table_type )
232 {
233 case TT_SBIT_TABLE_TYPE_EBLC:
234 case TT_SBIT_TABLE_TYPE_CBLC:
235 {
236 FT_Byte* strike;
237
238
239 strike = face->sbit_table + 8 + strike_index * 48;
240
241 metrics->x_ppem = (FT_UShort)strike[44];
242 metrics->y_ppem = (FT_UShort)strike[45];
243
244 metrics->ascender = (FT_Char)strike[16] << 6; /* hori.ascender */
245 metrics->descender = (FT_Char)strike[17] << 6; /* hori.descender */
246 metrics->height = metrics->ascender - metrics->descender;
247
248 /* Is this correct? */
249 metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */
250 strike[18] + /* max_width */
251 (FT_Char)strike[23] /* min_advance_SB */
252 ) << 6;
253 return FT_Err_Ok;
254 }
255
256 case TT_SBIT_TABLE_TYPE_SBIX:
257 {
258 FT_Stream stream = face->root.stream;
259 FT_UInt offset, ppem, resolution, upem;
260 TT_HoriHeader *hori;
261 FT_ULong table_size;
262
263 FT_Error error;
264 FT_Byte* p;
265
266
267 p = face->sbit_table + 8 + 4 * strike_index;
268 offset = FT_NEXT_ULONG( p );
269
270 error = face->goto_table( face, TTAG_sbix, stream, &table_size );
271 if ( error )
272 return error;
273
274 if ( offset + 4 > table_size )
275 return FT_THROW( Invalid_File_Format );
276
277 if ( FT_STREAM_SEEK( FT_STREAM_POS() + offset ) ||
278 FT_FRAME_ENTER( 4 ) )
279 return error;
280
281 ppem = FT_GET_USHORT();
282 resolution = FT_GET_USHORT();
283
284 FT_UNUSED( resolution ); /* What to do with this? */
285
286 FT_FRAME_EXIT();
287
288 upem = face->header.Units_Per_EM;
289 hori = &face->horizontal;
290
291 metrics->x_ppem = ppem;
292 metrics->y_ppem = ppem;
293
294 metrics->ascender = ppem * hori->Ascender * 64 / upem;
295 metrics->descender = ppem * hori->Descender * 64 / upem;
296 metrics->height = ppem * ( hori->Ascender -
297 hori->Descender +
298 hori->Line_Gap ) * 64 / upem;
299 metrics->max_advance = ppem * hori->advance_Width_Max * 64 / upem;
300
301 return error;
302 }
303
304 default:
305 return FT_THROW( Unknown_File_Format );
306 }
307 }
308
309
310 typedef struct TT_SBitDecoderRec_
311 {
312 TT_Face face;
313 FT_Stream stream;
314 FT_Bitmap* bitmap;
315 TT_SBit_Metrics metrics;
316 FT_Bool metrics_loaded;
317 FT_Bool bitmap_allocated;
318 FT_Byte bit_depth;
319
320 FT_ULong ebdt_start;
321 FT_ULong ebdt_size;
322
323 FT_ULong strike_index_array;
324 FT_ULong strike_index_count;
325 FT_Byte* eblc_base;
326 FT_Byte* eblc_limit;
327
328 } TT_SBitDecoderRec, *TT_SBitDecoder;
329
330
331 static FT_Error
332 tt_sbit_decoder_init( TT_SBitDecoder decoder,
333 TT_Face face,
334 FT_ULong strike_index,
335 TT_SBit_MetricsRec* metrics )
336 {
337 FT_Error error;
338 FT_Stream stream = face->root.stream;
339 FT_ULong ebdt_size;
340
341
342 error = face->goto_table( face, TTAG_CBDT, stream, &ebdt_size );
343 if ( error )
344 error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size );
345 if ( error )
346 error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size );
347 if ( error )
348 goto Exit;
349
350 decoder->face = face;
351 decoder->stream = stream;
352 decoder->bitmap = &face->root.glyph->bitmap;
353 decoder->metrics = metrics;
354
355 decoder->metrics_loaded = 0;
356 decoder->bitmap_allocated = 0;
357
358 decoder->ebdt_start = FT_STREAM_POS();
359 decoder->ebdt_size = ebdt_size;
360
361 decoder->eblc_base = face->sbit_table;
362 decoder->eblc_limit = face->sbit_table + face->sbit_table_size;
363
364 /* now find the strike corresponding to the index */
365 {
366 FT_Byte* p;
367
368
369 if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size )
370 {
371 error = FT_THROW( Invalid_File_Format );
372 goto Exit;
373 }
374
375 p = decoder->eblc_base + 8 + 48 * strike_index;
376
377 decoder->strike_index_array = FT_NEXT_ULONG( p );
378 p += 4;
379 decoder->strike_index_count = FT_NEXT_ULONG( p );
380 p += 34;
381 decoder->bit_depth = *p;
382
383 if ( decoder->strike_index_array > face->sbit_table_size ||
384 decoder->strike_index_array + 8 * decoder->strike_index_count >
385 face->sbit_table_size )
386 error = FT_THROW( Invalid_File_Format );
387 }
388
389 Exit:
390 return error;
391 }
392
393
394 static void
395 tt_sbit_decoder_done( TT_SBitDecoder decoder )
396 {
397 FT_UNUSED( decoder );
398 }
399
400
401 static FT_Error
402 tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder )
403 {
404 FT_Error error = FT_Err_Ok;
405 FT_UInt width, height;
406 FT_Bitmap* map = decoder->bitmap;
407 FT_Long size;
408
409
410 if ( !decoder->metrics_loaded )
411 {
412 error = FT_THROW( Invalid_Argument );
413 goto Exit;
414 }
415
416 width = decoder->metrics->width;
417 height = decoder->metrics->height;
418
419 map->width = (int)width;
420 map->rows = (int)height;
421
422 switch ( decoder->bit_depth )
423 {
424 case 1:
425 map->pixel_mode = FT_PIXEL_MODE_MONO;
426 map->pitch = ( map->width + 7 ) >> 3;
427 map->num_grays = 2;
428 break;
429
430 case 2:
431 map->pixel_mode = FT_PIXEL_MODE_GRAY2;
432 map->pitch = ( map->width + 3 ) >> 2;
433 map->num_grays = 4;
434 break;
435
436 case 4:
437 map->pixel_mode = FT_PIXEL_MODE_GRAY4;
438 map->pitch = ( map->width + 1 ) >> 1;
439 map->num_grays = 16;
440 break;
441
442 case 8:
443 map->pixel_mode = FT_PIXEL_MODE_GRAY;
444 map->pitch = map->width;
445 map->num_grays = 256;
446 break;
447
448 case 32:
449 map->pixel_mode = FT_PIXEL_MODE_BGRA;
450 map->pitch = map->width * 4;
451 map->num_grays = 256;
452 break;
453
454 default:
455 error = FT_THROW( Invalid_File_Format );
456 goto Exit;
457 }
458
459 size = map->rows * map->pitch;
460
461 /* check that there is no empty image */
462 if ( size == 0 )
463 goto Exit; /* exit successfully! */
464
465 error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size );
466 if ( error )
467 goto Exit;
468
469 decoder->bitmap_allocated = 1;
470
471 Exit:
472 return error;
473 }
474
475
476 static FT_Error
477 tt_sbit_decoder_load_metrics( TT_SBitDecoder decoder,
478 FT_Byte* *pp,
479 FT_Byte* limit,
480 FT_Bool big )
481 {
482 FT_Byte* p = *pp;
483 TT_SBit_Metrics metrics = decoder->metrics;
484
485
486 if ( p + 5 > limit )
487 goto Fail;
488
489 metrics->height = p[0];
490 metrics->width = p[1];
491 metrics->horiBearingX = (FT_Char)p[2];
492 metrics->horiBearingY = (FT_Char)p[3];
493 metrics->horiAdvance = p[4];
494
495 p += 5;
496 if ( big )
497 {
498 if ( p + 3 > limit )
499 goto Fail;
500
501 metrics->vertBearingX = (FT_Char)p[0];
502 metrics->vertBearingY = (FT_Char)p[1];
503 metrics->vertAdvance = p[2];
504
505 p += 3;
506 }
507
508 decoder->metrics_loaded = 1;
509 *pp = p;
510 return FT_Err_Ok;
511
512 Fail:
513 FT_TRACE1(( "tt_sbit_decoder_load_metrics: broken table" ));
514 return FT_THROW( Invalid_Argument );
515 }
516
517
518 /* forward declaration */
519 static FT_Error
520 tt_sbit_decoder_load_image( TT_SBitDecoder decoder,
521 FT_UInt glyph_index,
522 FT_Int x_pos,
523 FT_Int y_pos );
524
525 typedef FT_Error (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder decoder,
526 FT_Byte* p,
527 FT_Byte* plimit,
528 FT_Int x_pos,
529 FT_Int y_pos );
530
531
532 static FT_Error
533 tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder decoder,
534 FT_Byte* p,
535 FT_Byte* limit,
536 FT_Int x_pos,
537 FT_Int y_pos )
538 {
539 FT_Error error = FT_Err_Ok;
540 FT_Byte* line;
541 FT_Int bit_height, bit_width, pitch, width, height, line_bits, h;
542 FT_Bitmap* bitmap;
543
544
545 /* check that we can write the glyph into the bitmap */
546 bitmap = decoder->bitmap;
547 bit_width = bitmap->width;
548 bit_height = bitmap->rows;
549 pitch = bitmap->pitch;
550 line = bitmap->buffer;
551
552 width = decoder->metrics->width;
553 height = decoder->metrics->height;
554
555 line_bits = width * decoder->bit_depth;
556
557 if ( x_pos < 0 || x_pos + width > bit_width ||
558 y_pos < 0 || y_pos + height > bit_height )
559 {
560 FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned:"
561 " invalid bitmap dimensions\n" ));
562 error = FT_THROW( Invalid_File_Format );
563 goto Exit;
564 }
565
566 if ( p + ( ( line_bits + 7 ) >> 3 ) * height > limit )
567 {
568 FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned: broken bitmap\n" ));
569 error = FT_THROW( Invalid_File_Format );
570 goto Exit;
571 }
572
573 /* now do the blit */
574 line += y_pos * pitch + ( x_pos >> 3 );
575 x_pos &= 7;
576
577 if ( x_pos == 0 ) /* the easy one */
578 {
579 for ( h = height; h > 0; h--, line += pitch )
580 {
581 FT_Byte* pwrite = line;
582 FT_Int w;
583
584
585 for ( w = line_bits; w >= 8; w -= 8 )
586 {
587 pwrite[0] = (FT_Byte)( pwrite[0] | *p++ );
588 pwrite += 1;
589 }
590
591 if ( w > 0 )
592 pwrite[0] = (FT_Byte)( pwrite[0] | ( *p++ & ( 0xFF00U >> w ) ) );
593 }
594 }
595 else /* x_pos > 0 */
596 {
597 for ( h = height; h > 0; h--, line += pitch )
598 {
599 FT_Byte* pwrite = line;
600 FT_Int w;
601 FT_UInt wval = 0;
602
603
604 for ( w = line_bits; w >= 8; w -= 8 )
605 {
606 wval = (FT_UInt)( wval | *p++ );
607 pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) );
608 pwrite += 1;
609 wval <<= 8;
610 }
611
612 if ( w > 0 )
613 wval = (FT_UInt)( wval | ( *p++ & ( 0xFF00U >> w ) ) );
614
615 /* all bits read and there are `x_pos + w' bits to be written */
616
617 pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) );
618
619 if ( x_pos + w > 8 )
620 {
621 pwrite++;
622 wval <<= 8;
623 pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) );
624 }
625 }
626 }
627
628 Exit:
629 if ( !error )
630 FT_TRACE3(( "tt_sbit_decoder_load_byte_aligned: loaded\n" ));
631 return error;
632 }
633
634
635 /*
636 * Load a bit-aligned bitmap (with pointer `p') into a line-aligned bitmap
637 * (with pointer `pwrite'). In the example below, the width is 3 pixel,
638 * and `x_pos' is 1 pixel.
639 *
640 * p p+1
641 * | | |
642 * | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |...
643 * | | |
644 * +-------+ +-------+ +-------+ ...
645 * . . .
646 * . . .
647 * v . .
648 * +-------+ . .
649 * | | .
650 * | 7 6 5 4 3 2 1 0 | .
651 * | | .
652 * pwrite . .
653 * . .
654 * v .
655 * +-------+ .
656 * | |
657 * | 7 6 5 4 3 2 1 0 |
658 * | |
659 * pwrite+1 .
660 * .
661 * v
662 * +-------+
663 * | |
664 * | 7 6 5 4 3 2 1 0 |
665 * | |
666 * pwrite+2
667 *
668 */
669
670 static FT_Error
671 tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder decoder,
672 FT_Byte* p,
673 FT_Byte* limit,
674 FT_Int x_pos,
675 FT_Int y_pos )
676 {
677 FT_Error error = FT_Err_Ok;
678 FT_Byte* line;
679 FT_Int bit_height, bit_width, pitch, width, height, line_bits, h, nbits;
680 FT_Bitmap* bitmap;
681 FT_UShort rval;
682
683
684 /* check that we can write the glyph into the bitmap */
685 bitmap = decoder->bitmap;
686 bit_width = bitmap->width;
687 bit_height = bitmap->rows;
688 pitch = bitmap->pitch;
689 line = bitmap->buffer;
690
691 width = decoder->metrics->width;
692 height = decoder->metrics->height;
693
694 line_bits = width * decoder->bit_depth;
695
696 if ( x_pos < 0 || x_pos + width > bit_width ||
697 y_pos < 0 || y_pos + height > bit_height )
698 {
699 FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned:"
700 " invalid bitmap dimensions\n" ));
701 error = FT_THROW( Invalid_File_Format );
702 goto Exit;
703 }
704
705 if ( p + ( ( line_bits * height + 7 ) >> 3 ) > limit )
706 {
707 FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned: broken bitmap\n" ));
708 error = FT_THROW( Invalid_File_Format );
709 goto Exit;
710 }
711
712 /* now do the blit */
713
714 /* adjust `line' to point to the first byte of the bitmap */
715 line += y_pos * pitch + ( x_pos >> 3 );
716 x_pos &= 7;
717
718 /* the higher byte of `rval' is used as a buffer */
719 rval = 0;
720 nbits = 0;
721
722 for ( h = height; h > 0; h--, line += pitch )
723 {
724 FT_Byte* pwrite = line;
725 FT_Int w = line_bits;
726
727
728 /* handle initial byte (in target bitmap) specially if necessary */
729 if ( x_pos )
730 {
731 w = ( line_bits < 8 - x_pos ) ? line_bits : 8 - x_pos;
732
733 if ( h == height )
734 {
735 rval = *p++;
736 nbits = x_pos;
737 }
738 else if ( nbits < w )
739 {
740 if ( p < limit )
741 rval |= *p++;
742 nbits += 8 - w;
743 }
744 else
745 {
746 rval >>= 8;
747 nbits -= w;
748 }
749
750 *pwrite++ |= ( ( rval >> nbits ) & 0xFF ) &
751 ( ~( 0xFF << w ) << ( 8 - w - x_pos ) );
752 rval <<= 8;
753
754 w = line_bits - w;
755 }
756
757 /* handle medial bytes */
758 for ( ; w >= 8; w -= 8 )
759 {
760 rval |= *p++;
761 *pwrite++ |= ( rval >> nbits ) & 0xFF;
762
763 rval <<= 8;
764 }
765
766 /* handle final byte if necessary */
767 if ( w > 0 )
768 {
769 if ( nbits < w )
770 {
771 if ( p < limit )
772 rval |= *p++;
773 *pwrite |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );
774 nbits += 8 - w;
775
776 rval <<= 8;
777 }
778 else
779 {
780 *pwrite |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );
781 nbits -= w;
782 }
783 }
784 }
785
786 Exit:
787 if ( !error )
788 FT_TRACE3(( "tt_sbit_decoder_load_bit_aligned: loaded\n" ));
789 return error;
790 }
791
792
793 static FT_Error
794 tt_sbit_decoder_load_compound( TT_SBitDecoder decoder,
795 FT_Byte* p,
796 FT_Byte* limit,
797 FT_Int x_pos,
798 FT_Int y_pos )
799 {
800 FT_Error error = FT_Err_Ok;
801 FT_UInt num_components, nn;
802
803 FT_Char horiBearingX = decoder->metrics->horiBearingX;
804 FT_Char horiBearingY = decoder->metrics->horiBearingY;
805 FT_Byte horiAdvance = decoder->metrics->horiAdvance;
806 FT_Char vertBearingX = decoder->metrics->vertBearingX;
807 FT_Char vertBearingY = decoder->metrics->vertBearingY;
808 FT_Byte vertAdvance = decoder->metrics->vertAdvance;
809
810
811 if ( p + 2 > limit )
812 goto Fail;
813
814 num_components = FT_NEXT_USHORT( p );
815 if ( p + 4 * num_components > limit )
816 {
817 FT_TRACE1(( "tt_sbit_decoder_load_compound: broken table\n" ));
818 goto Fail;
819 }
820
821 FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d components\n",
822 num_components ));
823
824 for ( nn = 0; nn < num_components; nn++ )
825 {
826 FT_UInt gindex = FT_NEXT_USHORT( p );
827 FT_Byte dx = FT_NEXT_BYTE( p );
828 FT_Byte dy = FT_NEXT_BYTE( p );
829
830
831 /* NB: a recursive call */
832 error = tt_sbit_decoder_load_image( decoder, gindex,
833 x_pos + dx, y_pos + dy );
834 if ( error )
835 break;
836 }
837
838 FT_TRACE3(( "tt_sbit_decoder_load_compound: done\n" ));
839
840 decoder->metrics->horiBearingX = horiBearingX;
841 decoder->metrics->horiBearingY = horiBearingY;
842 decoder->metrics->horiAdvance = horiAdvance;
843 decoder->metrics->vertBearingX = vertBearingX;
844 decoder->metrics->vertBearingY = vertBearingY;
845 decoder->metrics->vertAdvance = vertAdvance;
846 decoder->metrics->width = (FT_Byte)decoder->bitmap->width;
847 decoder->metrics->height = (FT_Byte)decoder->bitmap->rows;
848
849 Exit:
850 return error;
851
852 Fail:
853 error = FT_THROW( Invalid_File_Format );
854 goto Exit;
855 }
856
857
858 #ifdef FT_CONFIG_OPTION_USE_PNG
859
860 static FT_Error
861 tt_sbit_decoder_load_png( TT_SBitDecoder decoder,
862 FT_Byte* p,
863 FT_Byte* limit,
864 FT_Int x_pos,
865 FT_Int y_pos )
866 {
867 FT_Error error = FT_Err_Ok;
868 FT_ULong png_len;
869
870
871 if ( limit - p < 4 )
872 {
873 FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" ));
874 error = FT_THROW( Invalid_File_Format );
875 goto Exit;
876 }
877
878 png_len = FT_NEXT_ULONG( p );
879 if ( (FT_ULong)( limit - p ) < png_len )
880 {
881 FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" ));
882 error = FT_THROW( Invalid_File_Format );
883 goto Exit;
884 }
885
886 error = Load_SBit_Png( decoder->face->root.glyph,
887 x_pos,
888 y_pos,
889 decoder->bit_depth,
890 decoder->metrics,
891 decoder->stream->memory,
892 p,
893 png_len,
894 FALSE );
895
896 Exit:
897 if ( !error )
898 FT_TRACE3(( "tt_sbit_decoder_load_png: loaded\n" ));
899 return error;
900 }
901
902 #endif /* FT_CONFIG_OPTION_USE_PNG */
903
904
905 static FT_Error
906 tt_sbit_decoder_load_bitmap( TT_SBitDecoder decoder,
907 FT_UInt glyph_format,
908 FT_ULong glyph_start,
909 FT_ULong glyph_size,
910 FT_Int x_pos,
911 FT_Int y_pos )
912 {
913 FT_Error error;
914 FT_Stream stream = decoder->stream;
915 FT_Byte* p;
916 FT_Byte* p_limit;
917 FT_Byte* data;
918
919
920 /* seek into the EBDT table now */
921 if ( glyph_start + glyph_size > decoder->ebdt_size )
922 {
923 error = FT_THROW( Invalid_Argument );
924 goto Exit;
925 }
926
927 if ( FT_STREAM_SEEK( decoder->ebdt_start + glyph_start ) ||
928 FT_FRAME_EXTRACT( glyph_size, data ) )
929 goto Exit;
930
931 p = data;
932 p_limit = p + glyph_size;
933
934 /* read the data, depending on the glyph format */
935 switch ( glyph_format )
936 {
937 case 1:
938 case 2:
939 case 8:
940 case 17:
941 error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 0 );
942 break;
943
944 case 6:
945 case 7:
946 case 9:
947 case 18:
948 error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 );
949 break;
950
951 default:
952 error = FT_Err_Ok;
953 }
954
955 if ( error )
956 goto Fail;
957
958 {
959 TT_SBitDecoder_LoadFunc loader;
960
961
962 switch ( glyph_format )
963 {
964 case 1:
965 case 6:
966 loader = tt_sbit_decoder_load_byte_aligned;
967 break;
968
969 case 2:
970 case 7:
971 {
972 /* Don't trust `glyph_format'. For example, Apple's main Korean */
973 /* system font, `AppleMyungJo.ttf' (version 7.0d2e6), uses glyph */
974 /* format 7, but the data is format 6. We check whether we have */
975 /* an excessive number of bytes in the image: If it is equal to */
976 /* the value for a byte-aligned glyph, use the other loading */
977 /* routine. */
978 /* */
979 /* Note that for some (width,height) combinations, where the */
980 /* width is not a multiple of 8, the sizes for bit- and */
981 /* byte-aligned data are equal, for example (7,7) or (15,6). We */
982 /* then prefer what `glyph_format' specifies. */
983
984 FT_UInt width = decoder->metrics->width;
985 FT_UInt height = decoder->metrics->height;
986
987 FT_UInt bit_size = ( width * height + 7 ) >> 3;
988 FT_UInt byte_size = height * ( ( width + 7 ) >> 3 );
989
990
991 if ( bit_size < byte_size &&
992 byte_size == (FT_UInt)( p_limit - p ) )
993 loader = tt_sbit_decoder_load_byte_aligned;
994 else
995 loader = tt_sbit_decoder_load_bit_aligned;
996 }
997 break;
998
999 case 5:
1000 loader = tt_sbit_decoder_load_bit_aligned;
1001 break;
1002
1003 case 8:
1004 if ( p + 1 > p_limit )
1005 goto Fail;
1006
1007 p += 1; /* skip padding */
1008 /* fall-through */
1009
1010 case 9:
1011 loader = tt_sbit_decoder_load_compound;
1012 break;
1013
1014 case 17: /* small metrics, PNG image data */
1015 case 18: /* big metrics, PNG image data */
1016 case 19: /* metrics in EBLC, PNG image data */
1017 #ifdef FT_CONFIG_OPTION_USE_PNG
1018 loader = tt_sbit_decoder_load_png;
1019 break;
1020 #else
1021 error = FT_THROW( Unimplemented_Feature );
1022 goto Fail;
1023 #endif /* FT_CONFIG_OPTION_USE_PNG */
1024
1025 default:
1026 error = FT_THROW( Invalid_Table );
1027 goto Fail;
1028 }
1029
1030 if ( !decoder->bitmap_allocated )
1031 {
1032 error = tt_sbit_decoder_alloc_bitmap( decoder );
1033 if ( error )
1034 goto Fail;
1035 }
1036
1037 error = loader( decoder, p, p_limit, x_pos, y_pos );
1038 }
1039
1040 Fail:
1041 FT_FRAME_RELEASE( data );
1042
1043 Exit:
1044 return error;
1045 }
1046
1047
1048 static FT_Error
1049 tt_sbit_decoder_load_image( TT_SBitDecoder decoder,
1050 FT_UInt glyph_index,
1051 FT_Int x_pos,
1052 FT_Int y_pos )
1053 {
1054 /*
1055 * First, we find the correct strike range that applies to this
1056 * glyph index.
1057 */
1058
1059 FT_Byte* p = decoder->eblc_base + decoder->strike_index_array;
1060 FT_Byte* p_limit = decoder->eblc_limit;
1061 FT_ULong num_ranges = decoder->strike_index_count;
1062 FT_UInt start, end, index_format, image_format;
1063 FT_ULong image_start = 0, image_end = 0, image_offset;
1064
1065
1066 for ( ; num_ranges > 0; num_ranges-- )
1067 {
1068 start = FT_NEXT_USHORT( p );
1069 end = FT_NEXT_USHORT( p );
1070
1071 if ( glyph_index >= start && glyph_index <= end )
1072 goto FoundRange;
1073
1074 p += 4; /* ignore index offset */
1075 }
1076 goto NoBitmap;
1077
1078 FoundRange:
1079 image_offset = FT_NEXT_ULONG( p );
1080
1081 /* overflow check */
1082 p = decoder->eblc_base + decoder->strike_index_array;
1083 if ( image_offset > (FT_ULong)( p_limit - p ) )
1084 goto Failure;
1085
1086 p += image_offset;
1087 if ( p + 8 > p_limit )
1088 goto NoBitmap;
1089
1090 /* now find the glyph's location and extend within the ebdt table */
1091 index_format = FT_NEXT_USHORT( p );
1092 image_format = FT_NEXT_USHORT( p );
1093 image_offset = FT_NEXT_ULONG ( p );
1094
1095 switch ( index_format )
1096 {
1097 case 1: /* 4-byte offsets relative to `image_offset' */
1098 p += 4 * ( glyph_index - start );
1099 if ( p + 8 > p_limit )
1100 goto NoBitmap;
1101
1102 image_start = FT_NEXT_ULONG( p );
1103 image_end = FT_NEXT_ULONG( p );
1104
1105 if ( image_start == image_end ) /* missing glyph */
1106 goto NoBitmap;
1107 break;
1108
1109 case 2: /* big metrics, constant image size */
1110 {
1111 FT_ULong image_size;
1112
1113
1114 if ( p + 12 > p_limit )
1115 goto NoBitmap;
1116
1117 image_size = FT_NEXT_ULONG( p );
1118
1119 if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )
1120 goto NoBitmap;
1121
1122 image_start = image_size * ( glyph_index - start );
1123 image_end = image_start + image_size;
1124 }
1125 break;
1126
1127 case 3: /* 2-byte offsets relative to 'image_offset' */
1128 p += 2 * ( glyph_index - start );
1129 if ( p + 4 > p_limit )
1130 goto NoBitmap;
1131
1132 image_start = FT_NEXT_USHORT( p );
1133 image_end = FT_NEXT_USHORT( p );
1134
1135 if ( image_start == image_end ) /* missing glyph */
1136 goto NoBitmap;
1137 break;
1138
1139 case 4: /* sparse glyph array with (glyph,offset) pairs */
1140 {
1141 FT_ULong mm, num_glyphs;
1142
1143
1144 if ( p + 4 > p_limit )
1145 goto NoBitmap;
1146
1147 num_glyphs = FT_NEXT_ULONG( p );
1148
1149 /* overflow check for p + ( num_glyphs + 1 ) * 4 */
1150 if ( num_glyphs > (FT_ULong)( ( ( p_limit - p ) >> 2 ) - 1 ) )
1151 goto NoBitmap;
1152
1153 for ( mm = 0; mm < num_glyphs; mm++ )
1154 {
1155 FT_UInt gindex = FT_NEXT_USHORT( p );
1156
1157
1158 if ( gindex == glyph_index )
1159 {
1160 image_start = FT_NEXT_USHORT( p );
1161 p += 2;
1162 image_end = FT_PEEK_USHORT( p );
1163 break;
1164 }
1165 p += 2;
1166 }
1167
1168 if ( mm >= num_glyphs )
1169 goto NoBitmap;
1170 }
1171 break;
1172
1173 case 5: /* constant metrics with sparse glyph codes */
1174 case 19:
1175 {
1176 FT_ULong image_size, mm, num_glyphs;
1177
1178
1179 if ( p + 16 > p_limit )
1180 goto NoBitmap;
1181
1182 image_size = FT_NEXT_ULONG( p );
1183
1184 if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )
1185 goto NoBitmap;
1186
1187 num_glyphs = FT_NEXT_ULONG( p );
1188
1189 /* overflow check for p + 2 * num_glyphs */
1190 if ( num_glyphs > (FT_ULong)( ( p_limit - p ) >> 1 ) )
1191 goto NoBitmap;
1192
1193 for ( mm = 0; mm < num_glyphs; mm++ )
1194 {
1195 FT_UInt gindex = FT_NEXT_USHORT( p );
1196
1197
1198 if ( gindex == glyph_index )
1199 break;
1200 }
1201
1202 if ( mm >= num_glyphs )
1203 goto NoBitmap;
1204
1205 image_start = image_size * mm;
1206 image_end = image_start + image_size;
1207 }
1208 break;
1209
1210 default:
1211 goto NoBitmap;
1212 }
1213
1214 if ( image_start > image_end )
1215 goto NoBitmap;
1216
1217 image_end -= image_start;
1218 image_start = image_offset + image_start;
1219
1220 FT_TRACE3(( "tt_sbit_decoder_load_image:"
1221 " found sbit (format %d) for glyph index %d\n",
1222 image_format, glyph_index ));
1223
1224 return tt_sbit_decoder_load_bitmap( decoder,
1225 image_format,
1226 image_start,
1227 image_end,
1228 x_pos,
1229 y_pos );
1230
1231 Failure:
1232 return FT_THROW( Invalid_Table );
1233
1234 NoBitmap:
1235 FT_TRACE4(( "tt_sbit_decoder_load_image:"
1236 " no sbit found for glyph index %d\n", glyph_index ));
1237
1238 return FT_THROW( Invalid_Argument );
1239 }
1240
1241
1242 static FT_Error
1243 tt_face_load_sbix_image( TT_Face face,
1244 FT_ULong strike_index,
1245 FT_UInt glyph_index,
1246 FT_Stream stream,
1247 FT_Bitmap *map,
1248 TT_SBit_MetricsRec *metrics )
1249 {
1250 FT_UInt sbix_pos, strike_offset, glyph_start, glyph_end;
1251 FT_ULong table_size;
1252 FT_Int originOffsetX, originOffsetY;
1253 FT_Tag graphicType;
1254 FT_Int recurse_depth = 0;
1255
1256 FT_Error error;
1257 FT_Byte* p;
1258
1259 FT_UNUSED( map );
1260
1261
1262 metrics->width = 0;
1263 metrics->height = 0;
1264
1265 p = face->sbit_table + 8 + 4 * strike_index;
1266 strike_offset = FT_NEXT_ULONG( p );
1267
1268 error = face->goto_table( face, TTAG_sbix, stream, &table_size );
1269 if ( error )
1270 return error;
1271 sbix_pos = FT_STREAM_POS();
1272
1273 retry:
1274 if ( glyph_index > (FT_UInt)face->root.num_glyphs )
1275 return FT_THROW( Invalid_Argument );
1276
1277 if ( strike_offset >= table_size ||
1278 table_size - strike_offset < 4 + glyph_index * 4 + 8 )
1279 return FT_THROW( Invalid_File_Format );
1280
1281 if ( FT_STREAM_SEEK( sbix_pos + strike_offset + 4 + glyph_index * 4 ) ||
1282 FT_FRAME_ENTER( 8 ) )
1283 return error;
1284
1285 glyph_start = FT_GET_ULONG();
1286 glyph_end = FT_GET_ULONG();
1287
1288 FT_FRAME_EXIT();
1289
1290 if ( glyph_start == glyph_end )
1291 return FT_THROW( Invalid_Argument );
1292 if ( glyph_start > glyph_end ||
1293 glyph_end - glyph_start < 8 ||
1294 table_size - strike_offset < glyph_end )
1295 return FT_THROW( Invalid_File_Format );
1296
1297 if ( FT_STREAM_SEEK( sbix_pos + strike_offset + glyph_start ) ||
1298 FT_FRAME_ENTER( glyph_end - glyph_start ) )
1299 return error;
1300
1301 originOffsetX = FT_GET_SHORT();
1302 originOffsetY = FT_GET_SHORT();
1303
1304 graphicType = FT_GET_TAG4();
1305
1306 switch ( graphicType )
1307 {
1308 case FT_MAKE_TAG( 'd', 'u', 'p', 'e' ):
1309 if ( recurse_depth < 4 )
1310 {
1311 glyph_index = FT_GET_USHORT();
1312 FT_FRAME_EXIT();
1313 recurse_depth++;
1314 goto retry;
1315 }
1316 error = FT_THROW( Invalid_File_Format );
1317 break;
1318
1319 case FT_MAKE_TAG( 'p', 'n', 'g', ' ' ):
1320 #ifdef FT_CONFIG_OPTION_USE_PNG
1321 error = Load_SBit_Png( face->root.glyph,
1322 0,
1323 0,
1324 32,
1325 metrics,
1326 stream->memory,
1327 stream->cursor,
1328 glyph_end - glyph_start - 8,
1329 TRUE );
1330 #else
1331 error = FT_THROW( Unimplemented_Feature );
1332 #endif
1333 break;
1334
1335 case FT_MAKE_TAG( 'j', 'p', 'g', ' ' ):
1336 case FT_MAKE_TAG( 't', 'i', 'f', 'f' ):
1337 error = FT_THROW( Unknown_File_Format );
1338 break;
1339
1340 default:
1341 error = FT_THROW( Unimplemented_Feature );
1342 break;
1343 }
1344
1345 FT_FRAME_EXIT();
1346
1347 if ( !error )
1348 {
1349 FT_Short abearing;
1350 FT_UShort aadvance;
1351
1352
1353 tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance );
1354
1355 metrics->horiBearingX = originOffsetX;
1356 metrics->horiBearingY = -originOffsetY + metrics->height;
1357 metrics->horiAdvance = aadvance * face->root.size->metrics.x_ppem /
1358 face->header.Units_Per_EM;
1359 }
1360
1361 return error;
1362 }
1363
1364 FT_LOCAL( FT_Error )
1365 tt_face_load_sbit_image( TT_Face face,
1366 FT_ULong strike_index,
1367 FT_UInt glyph_index,
1368 FT_UInt load_flags,
1369 FT_Stream stream,
1370 FT_Bitmap *map,
1371 TT_SBit_MetricsRec *metrics )
1372 {
1373 FT_Error error = FT_Err_Ok;
1374
1375
1376 switch ( (FT_UInt)face->sbit_table_type )
1377 {
1378 case TT_SBIT_TABLE_TYPE_EBLC:
1379 case TT_SBIT_TABLE_TYPE_CBLC:
1380 {
1381 TT_SBitDecoderRec decoder[1];
1382
1383
1384 error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
1385 if ( !error )
1386 {
1387 error = tt_sbit_decoder_load_image( decoder,
1388 glyph_index,
1389 0,
1390 0 );
1391 tt_sbit_decoder_done( decoder );
1392 }
1393 }
1394 break;
1395
1396 case TT_SBIT_TABLE_TYPE_SBIX:
1397 error = tt_face_load_sbix_image( face,
1398 strike_index,
1399 glyph_index,
1400 stream,
1401 map,
1402 metrics );
1403 break;
1404
1405 default:
1406 error = FT_THROW( Unknown_File_Format );
1407 break;
1408 }
1409
1410 /* Flatten color bitmaps if color was not requested. */
1411 if ( !error &&
1412 !( load_flags & FT_LOAD_COLOR ) &&
1413 map->pixel_mode == FT_PIXEL_MODE_BGRA )
1414 {
1415 FT_Bitmap new_map;
1416 FT_Library library = face->root.glyph->library;
1417
1418
1419 FT_Bitmap_New( &new_map );
1420
1421 /* Convert to 8bit grayscale. */
1422 error = FT_Bitmap_Convert( library, map, &new_map, 1 );
1423 if ( error )
1424 FT_Bitmap_Done( library, &new_map );
1425 else
1426 {
1427 map->pixel_mode = new_map.pixel_mode;
1428 map->pitch = new_map.pitch;
1429 map->num_grays = new_map.num_grays;
1430
1431 ft_glyphslot_set_bitmap( face->root.glyph, new_map.buffer );
1432 face->root.glyph->internal->flags |= FT_GLYPH_OWN_BITMAP;
1433 }
1434 }
1435
1436 return error;
1437 }
1438
1439
1440 /* EOF */