Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: src/sfnt/ttsbit.c

Issue 89753003: Update freetype to latest version of ASOP. (Closed) Base URL: https://chromium.googlesource.com/chromium/src/third_party/freetype.git@master
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/sfnt/ttsbit.h ('k') | src/smooth/ftgrays.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 */
OLDNEW
« no previous file with comments | « src/sfnt/ttsbit.h ('k') | src/smooth/ftgrays.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698