Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenttsbit0.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* ttsbit0.c */ 00004 /* */ 00005 /* TrueType and OpenType embedded bitmap support (body). */ 00006 /* This is a heap-optimized version. */ 00007 /* */ 00008 /* Copyright 2005, 2006, 2007, 2008, 2009 by */ 00009 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00010 /* */ 00011 /* This file is part of the FreeType project, and may only be used, */ 00012 /* modified, and distributed under the terms of the FreeType project */ 00013 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00014 /* this file you indicate that you have read the license and */ 00015 /* understand and accept it fully. */ 00016 /* */ 00017 /***************************************************************************/ 00018 00019 00020 /* This file is included by ttsbit.c */ 00021 00022 00023 #include <ft2build.h> 00024 #include FT_INTERNAL_DEBUG_H 00025 #include FT_INTERNAL_STREAM_H 00026 #include FT_TRUETYPE_TAGS_H 00027 #include "ttsbit.h" 00028 00029 #include "sferrors.h" 00030 00031 00032 /*************************************************************************/ 00033 /* */ 00034 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00035 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00036 /* messages during execution. */ 00037 /* */ 00038 #undef FT_COMPONENT 00039 #define FT_COMPONENT trace_ttsbit 00040 00041 00042 FT_LOCAL_DEF( FT_Error ) 00043 tt_face_load_eblc( TT_Face face, 00044 FT_Stream stream ) 00045 { 00046 FT_Error error = SFNT_Err_Ok; 00047 FT_Fixed version; 00048 FT_ULong num_strikes, table_size; 00049 FT_Byte* p; 00050 FT_Byte* p_limit; 00051 FT_UInt count; 00052 00053 00054 face->sbit_num_strikes = 0; 00055 00056 /* this table is optional */ 00057 error = face->goto_table( face, TTAG_EBLC, stream, &table_size ); 00058 if ( error ) 00059 error = face->goto_table( face, TTAG_bloc, stream, &table_size ); 00060 if ( error ) 00061 goto Exit; 00062 00063 if ( table_size < 8 ) 00064 { 00065 FT_ERROR(( "tt_face_load_sbit_strikes: table too short\n" )); 00066 error = SFNT_Err_Invalid_File_Format; 00067 goto Exit; 00068 } 00069 00070 if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) ) 00071 goto Exit; 00072 00073 face->sbit_table_size = table_size; 00074 00075 p = face->sbit_table; 00076 p_limit = p + table_size; 00077 00078 version = FT_NEXT_ULONG( p ); 00079 num_strikes = FT_NEXT_ULONG( p ); 00080 00081 if ( version != 0x00020000UL || num_strikes >= 0x10000UL ) 00082 { 00083 FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" )); 00084 error = SFNT_Err_Invalid_File_Format; 00085 goto Fail; 00086 } 00087 00088 /* 00089 * Count the number of strikes available in the table. We are a bit 00090 * paranoid there and don't trust the data. 00091 */ 00092 count = (FT_UInt)num_strikes; 00093 if ( 8 + 48UL * count > table_size ) 00094 count = (FT_UInt)( ( p_limit - p ) / 48 ); 00095 00096 face->sbit_num_strikes = count; 00097 00098 FT_TRACE3(( "sbit_num_strikes: %u\n", count )); 00099 Exit: 00100 return error; 00101 00102 Fail: 00103 FT_FRAME_RELEASE( face->sbit_table ); 00104 face->sbit_table_size = 0; 00105 goto Exit; 00106 } 00107 00108 00109 FT_LOCAL_DEF( void ) 00110 tt_face_free_eblc( TT_Face face ) 00111 { 00112 FT_Stream stream = face->root.stream; 00113 00114 00115 FT_FRAME_RELEASE( face->sbit_table ); 00116 face->sbit_table_size = 0; 00117 face->sbit_num_strikes = 0; 00118 } 00119 00120 00121 FT_LOCAL_DEF( FT_Error ) 00122 tt_face_set_sbit_strike( TT_Face face, 00123 FT_Size_Request req, 00124 FT_ULong* astrike_index ) 00125 { 00126 return FT_Match_Size( (FT_Face)face, req, 0, astrike_index ); 00127 } 00128 00129 00130 FT_LOCAL_DEF( FT_Error ) 00131 tt_face_load_strike_metrics( TT_Face face, 00132 FT_ULong strike_index, 00133 FT_Size_Metrics* metrics ) 00134 { 00135 FT_Byte* strike; 00136 00137 00138 if ( strike_index >= (FT_ULong)face->sbit_num_strikes ) 00139 return SFNT_Err_Invalid_Argument; 00140 00141 strike = face->sbit_table + 8 + strike_index * 48; 00142 00143 metrics->x_ppem = (FT_UShort)strike[44]; 00144 metrics->y_ppem = (FT_UShort)strike[45]; 00145 00146 metrics->ascender = (FT_Char)strike[16] << 6; /* hori.ascender */ 00147 metrics->descender = (FT_Char)strike[17] << 6; /* hori.descender */ 00148 metrics->height = metrics->ascender - metrics->descender; 00149 00150 /* XXX: Is this correct? */ 00151 metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */ 00152 strike[18] + /* max_width */ 00153 (FT_Char)strike[23] /* min_advance_SB */ 00154 ) << 6; 00155 00156 return SFNT_Err_Ok; 00157 } 00158 00159 00160 typedef struct TT_SBitDecoderRec_ 00161 { 00162 TT_Face face; 00163 FT_Stream stream; 00164 FT_Bitmap* bitmap; 00165 TT_SBit_Metrics metrics; 00166 FT_Bool metrics_loaded; 00167 FT_Bool bitmap_allocated; 00168 FT_Byte bit_depth; 00169 00170 FT_ULong ebdt_start; 00171 FT_ULong ebdt_size; 00172 00173 FT_ULong strike_index_array; 00174 FT_ULong strike_index_count; 00175 FT_Byte* eblc_base; 00176 FT_Byte* eblc_limit; 00177 00178 } TT_SBitDecoderRec, *TT_SBitDecoder; 00179 00180 00181 static FT_Error 00182 tt_sbit_decoder_init( TT_SBitDecoder decoder, 00183 TT_Face face, 00184 FT_ULong strike_index, 00185 TT_SBit_MetricsRec* metrics ) 00186 { 00187 FT_Error error; 00188 FT_Stream stream = face->root.stream; 00189 FT_ULong ebdt_size; 00190 00191 00192 error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size ); 00193 if ( error ) 00194 error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size ); 00195 if ( error ) 00196 goto Exit; 00197 00198 decoder->face = face; 00199 decoder->stream = stream; 00200 decoder->bitmap = &face->root.glyph->bitmap; 00201 decoder->metrics = metrics; 00202 00203 decoder->metrics_loaded = 0; 00204 decoder->bitmap_allocated = 0; 00205 00206 decoder->ebdt_start = FT_STREAM_POS(); 00207 decoder->ebdt_size = ebdt_size; 00208 00209 decoder->eblc_base = face->sbit_table; 00210 decoder->eblc_limit = face->sbit_table + face->sbit_table_size; 00211 00212 /* now find the strike corresponding to the index */ 00213 { 00214 FT_Byte* p; 00215 00216 00217 if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size ) 00218 { 00219 error = SFNT_Err_Invalid_File_Format; 00220 goto Exit; 00221 } 00222 00223 p = decoder->eblc_base + 8 + 48 * strike_index; 00224 00225 decoder->strike_index_array = FT_NEXT_ULONG( p ); 00226 p += 4; 00227 decoder->strike_index_count = FT_NEXT_ULONG( p ); 00228 p += 34; 00229 decoder->bit_depth = *p; 00230 00231 if ( decoder->strike_index_array > face->sbit_table_size || 00232 decoder->strike_index_array + 8 * decoder->strike_index_count > 00233 face->sbit_table_size ) 00234 error = SFNT_Err_Invalid_File_Format; 00235 } 00236 00237 Exit: 00238 return error; 00239 } 00240 00241 00242 static void 00243 tt_sbit_decoder_done( TT_SBitDecoder decoder ) 00244 { 00245 FT_UNUSED( decoder ); 00246 } 00247 00248 00249 static FT_Error 00250 tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder ) 00251 { 00252 FT_Error error = SFNT_Err_Ok; 00253 FT_UInt width, height; 00254 FT_Bitmap* map = decoder->bitmap; 00255 FT_Long size; 00256 00257 00258 if ( !decoder->metrics_loaded ) 00259 { 00260 error = SFNT_Err_Invalid_Argument; 00261 goto Exit; 00262 } 00263 00264 width = decoder->metrics->width; 00265 height = decoder->metrics->height; 00266 00267 map->width = (int)width; 00268 map->rows = (int)height; 00269 00270 switch ( decoder->bit_depth ) 00271 { 00272 case 1: 00273 map->pixel_mode = FT_PIXEL_MODE_MONO; 00274 map->pitch = ( map->width + 7 ) >> 3; 00275 break; 00276 00277 case 2: 00278 map->pixel_mode = FT_PIXEL_MODE_GRAY2; 00279 map->pitch = ( map->width + 3 ) >> 2; 00280 break; 00281 00282 case 4: 00283 map->pixel_mode = FT_PIXEL_MODE_GRAY4; 00284 map->pitch = ( map->width + 1 ) >> 1; 00285 break; 00286 00287 case 8: 00288 map->pixel_mode = FT_PIXEL_MODE_GRAY; 00289 map->pitch = map->width; 00290 break; 00291 00292 default: 00293 error = SFNT_Err_Invalid_File_Format; 00294 goto Exit; 00295 } 00296 00297 size = map->rows * map->pitch; 00298 00299 /* check that there is no empty image */ 00300 if ( size == 0 ) 00301 goto Exit; /* exit successfully! */ 00302 00303 error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size ); 00304 if ( error ) 00305 goto Exit; 00306 00307 decoder->bitmap_allocated = 1; 00308 00309 Exit: 00310 return error; 00311 } 00312 00313 00314 static FT_Error 00315 tt_sbit_decoder_load_metrics( TT_SBitDecoder decoder, 00316 FT_Byte* *pp, 00317 FT_Byte* limit, 00318 FT_Bool big ) 00319 { 00320 FT_Byte* p = *pp; 00321 TT_SBit_Metrics metrics = decoder->metrics; 00322 00323 00324 if ( p + 5 > limit ) 00325 goto Fail; 00326 00327 metrics->height = p[0]; 00328 metrics->width = p[1]; 00329 metrics->horiBearingX = (FT_Char)p[2]; 00330 metrics->horiBearingY = (FT_Char)p[3]; 00331 metrics->horiAdvance = p[4]; 00332 00333 p += 5; 00334 if ( big ) 00335 { 00336 if ( p + 3 > limit ) 00337 goto Fail; 00338 00339 metrics->vertBearingX = (FT_Char)p[0]; 00340 metrics->vertBearingY = (FT_Char)p[1]; 00341 metrics->vertAdvance = p[2]; 00342 00343 p += 3; 00344 } 00345 00346 decoder->metrics_loaded = 1; 00347 *pp = p; 00348 return SFNT_Err_Ok; 00349 00350 Fail: 00351 return SFNT_Err_Invalid_Argument; 00352 } 00353 00354 00355 /* forward declaration */ 00356 static FT_Error 00357 tt_sbit_decoder_load_image( TT_SBitDecoder decoder, 00358 FT_UInt glyph_index, 00359 FT_Int x_pos, 00360 FT_Int y_pos ); 00361 00362 typedef FT_Error (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder decoder, 00363 FT_Byte* p, 00364 FT_Byte* plimit, 00365 FT_Int x_pos, 00366 FT_Int y_pos ); 00367 00368 00369 static FT_Error 00370 tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder decoder, 00371 FT_Byte* p, 00372 FT_Byte* limit, 00373 FT_Int x_pos, 00374 FT_Int y_pos ) 00375 { 00376 FT_Error error = SFNT_Err_Ok; 00377 FT_Byte* line; 00378 FT_Int bit_height, bit_width, pitch, width, height, h; 00379 FT_Bitmap* bitmap; 00380 00381 00382 if ( !decoder->bitmap_allocated ) 00383 { 00384 error = tt_sbit_decoder_alloc_bitmap( decoder ); 00385 if ( error ) 00386 goto Exit; 00387 } 00388 00389 /* check that we can write the glyph into the bitmap */ 00390 bitmap = decoder->bitmap; 00391 bit_width = bitmap->width; 00392 bit_height = bitmap->rows; 00393 pitch = bitmap->pitch; 00394 line = bitmap->buffer; 00395 00396 width = decoder->metrics->width; 00397 height = decoder->metrics->height; 00398 00399 if ( x_pos < 0 || x_pos + width > bit_width || 00400 y_pos < 0 || y_pos + height > bit_height ) 00401 { 00402 error = SFNT_Err_Invalid_File_Format; 00403 goto Exit; 00404 } 00405 00406 if ( p + ( ( width + 7 ) >> 3 ) * height > limit ) 00407 { 00408 error = SFNT_Err_Invalid_File_Format; 00409 goto Exit; 00410 } 00411 00412 /* now do the blit */ 00413 line += y_pos * pitch + ( x_pos >> 3 ); 00414 x_pos &= 7; 00415 00416 if ( x_pos == 0 ) /* the easy one */ 00417 { 00418 for ( h = height; h > 0; h--, line += pitch ) 00419 { 00420 FT_Byte* write = line; 00421 FT_Int w; 00422 00423 00424 for ( w = width; w >= 8; w -= 8 ) 00425 { 00426 write[0] = (FT_Byte)( write[0] | *p++ ); 00427 write += 1; 00428 } 00429 00430 if ( w > 0 ) 00431 write[0] = (FT_Byte)( write[0] | ( *p++ & ( 0xFF00U >> w ) ) ); 00432 } 00433 } 00434 else /* x_pos > 0 */ 00435 { 00436 for ( h = height; h > 0; h--, line += pitch ) 00437 { 00438 FT_Byte* write = line; 00439 FT_Int w; 00440 FT_UInt wval = 0; 00441 00442 00443 for ( w = width; w >= 8; w -= 8 ) 00444 { 00445 wval = (FT_UInt)( wval | *p++ ); 00446 write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) ); 00447 write += 1; 00448 wval <<= 8; 00449 } 00450 00451 if ( w > 0 ) 00452 wval = (FT_UInt)( wval | ( *p++ & ( 0xFF00U >> w ) ) ); 00453 00454 /* all bits read and there are `x_pos + w' bits to be written */ 00455 00456 write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) ); 00457 00458 if ( x_pos + w > 8 ) 00459 { 00460 write++; 00461 wval <<= 8; 00462 write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) ); 00463 } 00464 } 00465 } 00466 00467 Exit: 00468 return error; 00469 } 00470 00471 00472 /* 00473 * Load a bit-aligned bitmap (with pointer `p') into a line-aligned bitmap 00474 * (with pointer `write'). In the example below, the width is 3 pixel, 00475 * and `x_pos' is 1 pixel. 00476 * 00477 * p p+1 00478 * | | | 00479 * | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |... 00480 * | | | 00481 * +-------+ +-------+ +-------+ ... 00482 * . . . 00483 * . . . 00484 * v . . 00485 * +-------+ . . 00486 * | | . 00487 * | 7 6 5 4 3 2 1 0 | . 00488 * | | . 00489 * write . . 00490 * . . 00491 * v . 00492 * +-------+ . 00493 * | | 00494 * | 7 6 5 4 3 2 1 0 | 00495 * | | 00496 * write+1 . 00497 * . 00498 * v 00499 * +-------+ 00500 * | | 00501 * | 7 6 5 4 3 2 1 0 | 00502 * | | 00503 * write+2 00504 * 00505 */ 00506 00507 static FT_Error 00508 tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder decoder, 00509 FT_Byte* p, 00510 FT_Byte* limit, 00511 FT_Int x_pos, 00512 FT_Int y_pos ) 00513 { 00514 FT_Error error = SFNT_Err_Ok; 00515 FT_Byte* line; 00516 FT_Int bit_height, bit_width, pitch, width, height, h, nbits; 00517 FT_Bitmap* bitmap; 00518 FT_UShort rval; 00519 00520 00521 if ( !decoder->bitmap_allocated ) 00522 { 00523 error = tt_sbit_decoder_alloc_bitmap( decoder ); 00524 if ( error ) 00525 goto Exit; 00526 } 00527 00528 /* check that we can write the glyph into the bitmap */ 00529 bitmap = decoder->bitmap; 00530 bit_width = bitmap->width; 00531 bit_height = bitmap->rows; 00532 pitch = bitmap->pitch; 00533 line = bitmap->buffer; 00534 00535 width = decoder->metrics->width; 00536 height = decoder->metrics->height; 00537 00538 if ( x_pos < 0 || x_pos + width > bit_width || 00539 y_pos < 0 || y_pos + height > bit_height ) 00540 { 00541 error = SFNT_Err_Invalid_File_Format; 00542 goto Exit; 00543 } 00544 00545 if ( p + ( ( width * height + 7 ) >> 3 ) > limit ) 00546 { 00547 error = SFNT_Err_Invalid_File_Format; 00548 goto Exit; 00549 } 00550 00551 /* now do the blit */ 00552 00553 /* adjust `line' to point to the first byte of the bitmap */ 00554 line += y_pos * pitch + ( x_pos >> 3 ); 00555 x_pos &= 7; 00556 00557 /* the higher byte of `rval' is used as a buffer */ 00558 rval = 0; 00559 nbits = 0; 00560 00561 for ( h = height; h > 0; h--, line += pitch ) 00562 { 00563 FT_Byte* write = line; 00564 FT_Int w = width; 00565 00566 00567 /* handle initial byte (in target bitmap) specially if necessary */ 00568 if ( x_pos ) 00569 { 00570 w = ( width < 8 - x_pos ) ? width : 8 - x_pos; 00571 00572 if ( h == height ) 00573 { 00574 rval = *p++; 00575 nbits = x_pos; 00576 } 00577 else if ( nbits < w ) 00578 { 00579 if ( p < limit ) 00580 rval |= *p++; 00581 nbits += 8 - w; 00582 } 00583 else 00584 { 00585 rval >>= 8; 00586 nbits -= w; 00587 } 00588 00589 *write++ |= ( ( rval >> nbits ) & 0xFF ) & 00590 ( ~( 0xFF << w ) << ( 8 - w - x_pos ) ); 00591 rval <<= 8; 00592 00593 w = width - w; 00594 } 00595 00596 /* handle medial bytes */ 00597 for ( ; w >= 8; w -= 8 ) 00598 { 00599 rval |= *p++; 00600 *write++ |= ( rval >> nbits ) & 0xFF; 00601 00602 rval <<= 8; 00603 } 00604 00605 /* handle final byte if necessary */ 00606 if ( w > 0 ) 00607 { 00608 if ( nbits < w ) 00609 { 00610 if ( p < limit ) 00611 rval |= *p++; 00612 *write |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w ); 00613 nbits += 8 - w; 00614 00615 rval <<= 8; 00616 } 00617 else 00618 { 00619 *write |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w ); 00620 nbits -= w; 00621 } 00622 } 00623 } 00624 00625 Exit: 00626 return error; 00627 } 00628 00629 00630 static FT_Error 00631 tt_sbit_decoder_load_compound( TT_SBitDecoder decoder, 00632 FT_Byte* p, 00633 FT_Byte* limit, 00634 FT_Int x_pos, 00635 FT_Int y_pos ) 00636 { 00637 FT_Error error = SFNT_Err_Ok; 00638 FT_UInt num_components, nn; 00639 00640 FT_Char horiBearingX = decoder->metrics->horiBearingX; 00641 FT_Char horiBearingY = decoder->metrics->horiBearingY; 00642 FT_Byte horiAdvance = decoder->metrics->horiAdvance; 00643 FT_Char vertBearingX = decoder->metrics->vertBearingX; 00644 FT_Char vertBearingY = decoder->metrics->vertBearingY; 00645 FT_Byte vertAdvance = decoder->metrics->vertAdvance; 00646 00647 00648 if ( p + 2 > limit ) 00649 goto Fail; 00650 00651 num_components = FT_NEXT_USHORT( p ); 00652 if ( p + 4 * num_components > limit ) 00653 goto Fail; 00654 00655 if ( !decoder->bitmap_allocated ) 00656 { 00657 error = tt_sbit_decoder_alloc_bitmap( decoder ); 00658 if ( error ) 00659 goto Exit; 00660 } 00661 00662 for ( nn = 0; nn < num_components; nn++ ) 00663 { 00664 FT_UInt gindex = FT_NEXT_USHORT( p ); 00665 FT_Byte dx = FT_NEXT_BYTE( p ); 00666 FT_Byte dy = FT_NEXT_BYTE( p ); 00667 00668 00669 /* NB: a recursive call */ 00670 error = tt_sbit_decoder_load_image( decoder, gindex, 00671 x_pos + dx, y_pos + dy ); 00672 if ( error ) 00673 break; 00674 } 00675 00676 decoder->metrics->horiBearingX = horiBearingX; 00677 decoder->metrics->horiBearingY = horiBearingY; 00678 decoder->metrics->horiAdvance = horiAdvance; 00679 decoder->metrics->vertBearingX = vertBearingX; 00680 decoder->metrics->vertBearingY = vertBearingY; 00681 decoder->metrics->vertAdvance = vertAdvance; 00682 decoder->metrics->width = (FT_UInt)decoder->bitmap->width; 00683 decoder->metrics->height = (FT_UInt)decoder->bitmap->rows; 00684 00685 Exit: 00686 return error; 00687 00688 Fail: 00689 error = SFNT_Err_Invalid_File_Format; 00690 goto Exit; 00691 } 00692 00693 00694 static FT_Error 00695 tt_sbit_decoder_load_bitmap( TT_SBitDecoder decoder, 00696 FT_UInt glyph_format, 00697 FT_ULong glyph_start, 00698 FT_ULong glyph_size, 00699 FT_Int x_pos, 00700 FT_Int y_pos ) 00701 { 00702 FT_Error error; 00703 FT_Stream stream = decoder->stream; 00704 FT_Byte* p; 00705 FT_Byte* p_limit; 00706 FT_Byte* data; 00707 00708 00709 /* seek into the EBDT table now */ 00710 if ( glyph_start + glyph_size > decoder->ebdt_size ) 00711 { 00712 error = SFNT_Err_Invalid_Argument; 00713 goto Exit; 00714 } 00715 00716 if ( FT_STREAM_SEEK( decoder->ebdt_start + glyph_start ) || 00717 FT_FRAME_EXTRACT( glyph_size, data ) ) 00718 goto Exit; 00719 00720 p = data; 00721 p_limit = p + glyph_size; 00722 00723 /* read the data, depending on the glyph format */ 00724 switch ( glyph_format ) 00725 { 00726 case 1: 00727 case 2: 00728 case 8: 00729 error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 0 ); 00730 break; 00731 00732 case 6: 00733 case 7: 00734 case 9: 00735 error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ); 00736 break; 00737 00738 default: 00739 error = SFNT_Err_Ok; 00740 } 00741 00742 if ( error ) 00743 goto Fail; 00744 00745 { 00746 TT_SBitDecoder_LoadFunc loader; 00747 00748 00749 switch ( glyph_format ) 00750 { 00751 case 1: 00752 case 6: 00753 loader = tt_sbit_decoder_load_byte_aligned; 00754 break; 00755 00756 case 2: 00757 case 5: 00758 case 7: 00759 loader = tt_sbit_decoder_load_bit_aligned; 00760 break; 00761 00762 case 8: 00763 if ( p + 1 > p_limit ) 00764 goto Fail; 00765 00766 p += 1; /* skip padding */ 00767 /* fall-through */ 00768 00769 case 9: 00770 loader = tt_sbit_decoder_load_compound; 00771 break; 00772 00773 default: 00774 goto Fail; 00775 } 00776 00777 error = loader( decoder, p, p_limit, x_pos, y_pos ); 00778 } 00779 00780 Fail: 00781 FT_FRAME_RELEASE( data ); 00782 00783 Exit: 00784 return error; 00785 } 00786 00787 00788 static FT_Error 00789 tt_sbit_decoder_load_image( TT_SBitDecoder decoder, 00790 FT_UInt glyph_index, 00791 FT_Int x_pos, 00792 FT_Int y_pos ) 00793 { 00794 /* 00795 * First, we find the correct strike range that applies to this 00796 * glyph index. 00797 */ 00798 00799 FT_Byte* p = decoder->eblc_base + decoder->strike_index_array; 00800 FT_Byte* p_limit = decoder->eblc_limit; 00801 FT_ULong num_ranges = decoder->strike_index_count; 00802 FT_UInt start, end, index_format, image_format; 00803 FT_ULong image_start = 0, image_end = 0, image_offset; 00804 00805 00806 for ( ; num_ranges > 0; num_ranges-- ) 00807 { 00808 start = FT_NEXT_USHORT( p ); 00809 end = FT_NEXT_USHORT( p ); 00810 00811 if ( glyph_index >= start && glyph_index <= end ) 00812 goto FoundRange; 00813 00814 p += 4; /* ignore index offset */ 00815 } 00816 goto NoBitmap; 00817 00818 FoundRange: 00819 image_offset = FT_NEXT_ULONG( p ); 00820 00821 /* overflow check */ 00822 if ( decoder->eblc_base + decoder->strike_index_array + image_offset < 00823 decoder->eblc_base ) 00824 goto Failure; 00825 00826 p = decoder->eblc_base + decoder->strike_index_array + image_offset; 00827 if ( p + 8 > p_limit ) 00828 goto NoBitmap; 00829 00830 /* now find the glyph's location and extend within the ebdt table */ 00831 index_format = FT_NEXT_USHORT( p ); 00832 image_format = FT_NEXT_USHORT( p ); 00833 image_offset = FT_NEXT_ULONG ( p ); 00834 00835 switch ( index_format ) 00836 { 00837 case 1: /* 4-byte offsets relative to `image_offset' */ 00838 { 00839 p += 4 * ( glyph_index - start ); 00840 if ( p + 8 > p_limit ) 00841 goto NoBitmap; 00842 00843 image_start = FT_NEXT_ULONG( p ); 00844 image_end = FT_NEXT_ULONG( p ); 00845 00846 if ( image_start == image_end ) /* missing glyph */ 00847 goto NoBitmap; 00848 } 00849 break; 00850 00851 case 2: /* big metrics, constant image size */ 00852 { 00853 FT_ULong image_size; 00854 00855 00856 if ( p + 12 > p_limit ) 00857 goto NoBitmap; 00858 00859 image_size = FT_NEXT_ULONG( p ); 00860 00861 if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) ) 00862 goto NoBitmap; 00863 00864 image_start = image_size * ( glyph_index - start ); 00865 image_end = image_start + image_size; 00866 } 00867 break; 00868 00869 case 3: /* 2-byte offsets relative to 'image_offset' */ 00870 { 00871 p += 2 * ( glyph_index - start ); 00872 if ( p + 4 > p_limit ) 00873 goto NoBitmap; 00874 00875 image_start = FT_NEXT_USHORT( p ); 00876 image_end = FT_NEXT_USHORT( p ); 00877 00878 if ( image_start == image_end ) /* missing glyph */ 00879 goto NoBitmap; 00880 } 00881 break; 00882 00883 case 4: /* sparse glyph array with (glyph,offset) pairs */ 00884 { 00885 FT_ULong mm, num_glyphs; 00886 00887 00888 if ( p + 4 > p_limit ) 00889 goto NoBitmap; 00890 00891 num_glyphs = FT_NEXT_ULONG( p ); 00892 00893 /* overflow check */ 00894 if ( p + ( num_glyphs + 1 ) * 4 < p ) 00895 goto Failure; 00896 00897 if ( p + ( num_glyphs + 1 ) * 4 > p_limit ) 00898 goto NoBitmap; 00899 00900 for ( mm = 0; mm < num_glyphs; mm++ ) 00901 { 00902 FT_UInt gindex = FT_NEXT_USHORT( p ); 00903 00904 00905 if ( gindex == glyph_index ) 00906 { 00907 image_start = FT_NEXT_USHORT( p ); 00908 p += 2; 00909 image_end = FT_PEEK_USHORT( p ); 00910 break; 00911 } 00912 p += 2; 00913 } 00914 00915 if ( mm >= num_glyphs ) 00916 goto NoBitmap; 00917 } 00918 break; 00919 00920 case 5: /* constant metrics with sparse glyph codes */ 00921 { 00922 FT_ULong image_size, mm, num_glyphs; 00923 00924 00925 if ( p + 16 > p_limit ) 00926 goto NoBitmap; 00927 00928 image_size = FT_NEXT_ULONG( p ); 00929 00930 if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) ) 00931 goto NoBitmap; 00932 00933 num_glyphs = FT_NEXT_ULONG( p ); 00934 00935 /* overflow check */ 00936 if ( p + 2 * num_glyphs < p ) 00937 goto Failure; 00938 00939 if ( p + 2 * num_glyphs > p_limit ) 00940 goto NoBitmap; 00941 00942 for ( mm = 0; mm < num_glyphs; mm++ ) 00943 { 00944 FT_UInt gindex = FT_NEXT_USHORT( p ); 00945 00946 00947 if ( gindex == glyph_index ) 00948 break; 00949 } 00950 00951 if ( mm >= num_glyphs ) 00952 goto NoBitmap; 00953 00954 image_start = image_size * mm; 00955 image_end = image_start + image_size; 00956 } 00957 break; 00958 00959 default: 00960 goto NoBitmap; 00961 } 00962 00963 if ( image_start > image_end ) 00964 goto NoBitmap; 00965 00966 image_end -= image_start; 00967 image_start = image_offset + image_start; 00968 00969 return tt_sbit_decoder_load_bitmap( decoder, 00970 image_format, 00971 image_start, 00972 image_end, 00973 x_pos, 00974 y_pos ); 00975 00976 Failure: 00977 return SFNT_Err_Invalid_Table; 00978 00979 NoBitmap: 00980 return SFNT_Err_Invalid_Argument; 00981 } 00982 00983 00984 FT_LOCAL( FT_Error ) 00985 tt_face_load_sbit_image( TT_Face face, 00986 FT_ULong strike_index, 00987 FT_UInt glyph_index, 00988 FT_UInt load_flags, 00989 FT_Stream stream, 00990 FT_Bitmap *map, 00991 TT_SBit_MetricsRec *metrics ) 00992 { 00993 TT_SBitDecoderRec decoder[1]; 00994 FT_Error error; 00995 00996 FT_UNUSED( load_flags ); 00997 FT_UNUSED( stream ); 00998 FT_UNUSED( map ); 00999 01000 01001 error = tt_sbit_decoder_init( decoder, face, strike_index, metrics ); 01002 if ( !error ) 01003 { 01004 error = tt_sbit_decoder_load_image( decoder, glyph_index, 0, 0 ); 01005 tt_sbit_decoder_done( decoder ); 01006 } 01007 01008 return error; 01009 } 01010 01011 /* EOF */ Generated on Tue May 22 2012 04:38:07 for ReactOS by
1.7.6.1
|