Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpfrsbit.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* pfrsbit.c */ 00004 /* */ 00005 /* FreeType PFR bitmap loader (body). */ 00006 /* */ 00007 /* Copyright 2002, 2003, 2006, 2009, 2010 by */ 00008 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00009 /* */ 00010 /* This file is part of the FreeType project, and may only be used, */ 00011 /* modified, and distributed under the terms of the FreeType project */ 00012 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00013 /* this file you indicate that you have read the license and */ 00014 /* understand and accept it fully. */ 00015 /* */ 00016 /***************************************************************************/ 00017 00018 00019 #include "pfrsbit.h" 00020 #include "pfrload.h" 00021 #include FT_INTERNAL_DEBUG_H 00022 #include FT_INTERNAL_STREAM_H 00023 00024 #include "pfrerror.h" 00025 00026 #undef FT_COMPONENT 00027 #define FT_COMPONENT trace_pfr 00028 00029 00030 /*************************************************************************/ 00031 /*************************************************************************/ 00032 /***** *****/ 00033 /***** PFR BIT WRITER *****/ 00034 /***** *****/ 00035 /*************************************************************************/ 00036 /*************************************************************************/ 00037 00038 typedef struct PFR_BitWriter_ 00039 { 00040 FT_Byte* line; /* current line start */ 00041 FT_Int pitch; /* line size in bytes */ 00042 FT_Int width; /* width in pixels/bits */ 00043 FT_Int rows; /* number of remaining rows to scan */ 00044 FT_Int total; /* total number of bits to draw */ 00045 00046 } PFR_BitWriterRec, *PFR_BitWriter; 00047 00048 00049 static void 00050 pfr_bitwriter_init( PFR_BitWriter writer, 00051 FT_Bitmap* target, 00052 FT_Bool decreasing ) 00053 { 00054 writer->line = target->buffer; 00055 writer->pitch = target->pitch; 00056 writer->width = target->width; 00057 writer->rows = target->rows; 00058 writer->total = writer->width * writer->rows; 00059 00060 if ( !decreasing ) 00061 { 00062 writer->line += writer->pitch * ( target->rows-1 ); 00063 writer->pitch = -writer->pitch; 00064 } 00065 } 00066 00067 00068 static void 00069 pfr_bitwriter_decode_bytes( PFR_BitWriter writer, 00070 FT_Byte* p, 00071 FT_Byte* limit ) 00072 { 00073 FT_Int n, reload; 00074 FT_Int left = writer->width; 00075 FT_Byte* cur = writer->line; 00076 FT_UInt mask = 0x80; 00077 FT_UInt val = 0; 00078 FT_UInt c = 0; 00079 00080 00081 n = (FT_Int)( limit - p ) * 8; 00082 if ( n > writer->total ) 00083 n = writer->total; 00084 00085 reload = n & 7; 00086 00087 for ( ; n > 0; n-- ) 00088 { 00089 if ( ( n & 7 ) == reload ) 00090 val = *p++; 00091 00092 if ( val & 0x80 ) 00093 c |= mask; 00094 00095 val <<= 1; 00096 mask >>= 1; 00097 00098 if ( --left <= 0 ) 00099 { 00100 cur[0] = (FT_Byte)c; 00101 left = writer->width; 00102 mask = 0x80; 00103 00104 writer->line += writer->pitch; 00105 cur = writer->line; 00106 c = 0; 00107 } 00108 else if ( mask == 0 ) 00109 { 00110 cur[0] = (FT_Byte)c; 00111 mask = 0x80; 00112 c = 0; 00113 cur ++; 00114 } 00115 } 00116 00117 if ( mask != 0x80 ) 00118 cur[0] = (FT_Byte)c; 00119 } 00120 00121 00122 static void 00123 pfr_bitwriter_decode_rle1( PFR_BitWriter writer, 00124 FT_Byte* p, 00125 FT_Byte* limit ) 00126 { 00127 FT_Int n, phase, count, counts[2], reload; 00128 FT_Int left = writer->width; 00129 FT_Byte* cur = writer->line; 00130 FT_UInt mask = 0x80; 00131 FT_UInt c = 0; 00132 00133 00134 n = writer->total; 00135 00136 phase = 1; 00137 counts[0] = 0; 00138 counts[1] = 0; 00139 count = 0; 00140 reload = 1; 00141 00142 for ( ; n > 0; n-- ) 00143 { 00144 if ( reload ) 00145 { 00146 do 00147 { 00148 if ( phase ) 00149 { 00150 FT_Int v; 00151 00152 00153 if ( p >= limit ) 00154 break; 00155 00156 v = *p++; 00157 counts[0] = v >> 4; 00158 counts[1] = v & 15; 00159 phase = 0; 00160 count = counts[0]; 00161 } 00162 else 00163 { 00164 phase = 1; 00165 count = counts[1]; 00166 } 00167 00168 } while ( count == 0 ); 00169 } 00170 00171 if ( phase ) 00172 c |= mask; 00173 00174 mask >>= 1; 00175 00176 if ( --left <= 0 ) 00177 { 00178 cur[0] = (FT_Byte) c; 00179 left = writer->width; 00180 mask = 0x80; 00181 00182 writer->line += writer->pitch; 00183 cur = writer->line; 00184 c = 0; 00185 } 00186 else if ( mask == 0 ) 00187 { 00188 cur[0] = (FT_Byte)c; 00189 mask = 0x80; 00190 c = 0; 00191 cur ++; 00192 } 00193 00194 reload = ( --count <= 0 ); 00195 } 00196 00197 if ( mask != 0x80 ) 00198 cur[0] = (FT_Byte) c; 00199 } 00200 00201 00202 static void 00203 pfr_bitwriter_decode_rle2( PFR_BitWriter writer, 00204 FT_Byte* p, 00205 FT_Byte* limit ) 00206 { 00207 FT_Int n, phase, count, reload; 00208 FT_Int left = writer->width; 00209 FT_Byte* cur = writer->line; 00210 FT_UInt mask = 0x80; 00211 FT_UInt c = 0; 00212 00213 00214 n = writer->total; 00215 00216 phase = 1; 00217 count = 0; 00218 reload = 1; 00219 00220 for ( ; n > 0; n-- ) 00221 { 00222 if ( reload ) 00223 { 00224 do 00225 { 00226 if ( p >= limit ) 00227 break; 00228 00229 count = *p++; 00230 phase = phase ^ 1; 00231 00232 } while ( count == 0 ); 00233 } 00234 00235 if ( phase ) 00236 c |= mask; 00237 00238 mask >>= 1; 00239 00240 if ( --left <= 0 ) 00241 { 00242 cur[0] = (FT_Byte) c; 00243 c = 0; 00244 mask = 0x80; 00245 left = writer->width; 00246 00247 writer->line += writer->pitch; 00248 cur = writer->line; 00249 } 00250 else if ( mask == 0 ) 00251 { 00252 cur[0] = (FT_Byte)c; 00253 c = 0; 00254 mask = 0x80; 00255 cur ++; 00256 } 00257 00258 reload = ( --count <= 0 ); 00259 } 00260 00261 if ( mask != 0x80 ) 00262 cur[0] = (FT_Byte) c; 00263 } 00264 00265 00266 /*************************************************************************/ 00267 /*************************************************************************/ 00268 /***** *****/ 00269 /***** BITMAP DATA DECODING *****/ 00270 /***** *****/ 00271 /*************************************************************************/ 00272 /*************************************************************************/ 00273 00274 static void 00275 pfr_lookup_bitmap_data( FT_Byte* base, 00276 FT_Byte* limit, 00277 FT_UInt count, 00278 FT_UInt flags, 00279 FT_UInt char_code, 00280 FT_ULong* found_offset, 00281 FT_ULong* found_size ) 00282 { 00283 FT_UInt left, right, char_len; 00284 FT_Bool two = FT_BOOL( flags & 1 ); 00285 FT_Byte* buff; 00286 00287 00288 char_len = 4; 00289 if ( two ) char_len += 1; 00290 if ( flags & 2 ) char_len += 1; 00291 if ( flags & 4 ) char_len += 1; 00292 00293 left = 0; 00294 right = count; 00295 00296 while ( left < right ) 00297 { 00298 FT_UInt middle, code; 00299 00300 00301 middle = ( left + right ) >> 1; 00302 buff = base + middle * char_len; 00303 00304 /* check that we are not outside of the table -- */ 00305 /* this is possible with broken fonts... */ 00306 if ( buff + char_len > limit ) 00307 goto Fail; 00308 00309 if ( two ) 00310 code = PFR_NEXT_USHORT( buff ); 00311 else 00312 code = PFR_NEXT_BYTE( buff ); 00313 00314 if ( code == char_code ) 00315 goto Found_It; 00316 00317 if ( code < char_code ) 00318 left = middle; 00319 else 00320 right = middle; 00321 } 00322 00323 Fail: 00324 /* Not found */ 00325 *found_size = 0; 00326 *found_offset = 0; 00327 return; 00328 00329 Found_It: 00330 if ( flags & 2 ) 00331 *found_size = PFR_NEXT_USHORT( buff ); 00332 else 00333 *found_size = PFR_NEXT_BYTE( buff ); 00334 00335 if ( flags & 4 ) 00336 *found_offset = PFR_NEXT_ULONG( buff ); 00337 else 00338 *found_offset = PFR_NEXT_USHORT( buff ); 00339 } 00340 00341 00342 /* load bitmap metrics. "*padvance" must be set to the default value */ 00343 /* before calling this function... */ 00344 /* */ 00345 static FT_Error 00346 pfr_load_bitmap_metrics( FT_Byte** pdata, 00347 FT_Byte* limit, 00348 FT_Long scaled_advance, 00349 FT_Long *axpos, 00350 FT_Long *aypos, 00351 FT_UInt *axsize, 00352 FT_UInt *aysize, 00353 FT_Long *aadvance, 00354 FT_UInt *aformat ) 00355 { 00356 FT_Error error = PFR_Err_Ok; 00357 FT_Byte flags; 00358 FT_Char b; 00359 FT_Byte* p = *pdata; 00360 FT_Long xpos, ypos, advance; 00361 FT_UInt xsize, ysize; 00362 00363 00364 PFR_CHECK( 1 ); 00365 flags = PFR_NEXT_BYTE( p ); 00366 00367 xpos = 0; 00368 ypos = 0; 00369 xsize = 0; 00370 ysize = 0; 00371 advance = 0; 00372 00373 switch ( flags & 3 ) 00374 { 00375 case 0: 00376 PFR_CHECK( 1 ); 00377 b = PFR_NEXT_INT8( p ); 00378 xpos = b >> 4; 00379 ypos = ( (FT_Char)( b << 4 ) ) >> 4; 00380 break; 00381 00382 case 1: 00383 PFR_CHECK( 2 ); 00384 xpos = PFR_NEXT_INT8( p ); 00385 ypos = PFR_NEXT_INT8( p ); 00386 break; 00387 00388 case 2: 00389 PFR_CHECK( 4 ); 00390 xpos = PFR_NEXT_SHORT( p ); 00391 ypos = PFR_NEXT_SHORT( p ); 00392 break; 00393 00394 case 3: 00395 PFR_CHECK( 6 ); 00396 xpos = PFR_NEXT_LONG( p ); 00397 ypos = PFR_NEXT_LONG( p ); 00398 break; 00399 00400 default: 00401 ; 00402 } 00403 00404 flags >>= 2; 00405 switch ( flags & 3 ) 00406 { 00407 case 0: 00408 /* blank image */ 00409 xsize = 0; 00410 ysize = 0; 00411 break; 00412 00413 case 1: 00414 PFR_CHECK( 1 ); 00415 b = PFR_NEXT_BYTE( p ); 00416 xsize = ( b >> 4 ) & 0xF; 00417 ysize = b & 0xF; 00418 break; 00419 00420 case 2: 00421 PFR_CHECK( 2 ); 00422 xsize = PFR_NEXT_BYTE( p ); 00423 ysize = PFR_NEXT_BYTE( p ); 00424 break; 00425 00426 case 3: 00427 PFR_CHECK( 4 ); 00428 xsize = PFR_NEXT_USHORT( p ); 00429 ysize = PFR_NEXT_USHORT( p ); 00430 break; 00431 00432 default: 00433 ; 00434 } 00435 00436 flags >>= 2; 00437 switch ( flags & 3 ) 00438 { 00439 case 0: 00440 advance = scaled_advance; 00441 break; 00442 00443 case 1: 00444 PFR_CHECK( 1 ); 00445 advance = PFR_NEXT_INT8( p ) << 8; 00446 break; 00447 00448 case 2: 00449 PFR_CHECK( 2 ); 00450 advance = PFR_NEXT_SHORT( p ); 00451 break; 00452 00453 case 3: 00454 PFR_CHECK( 3 ); 00455 advance = PFR_NEXT_LONG( p ); 00456 break; 00457 00458 default: 00459 ; 00460 } 00461 00462 *axpos = xpos; 00463 *aypos = ypos; 00464 *axsize = xsize; 00465 *aysize = ysize; 00466 *aadvance = advance; 00467 *aformat = flags >> 2; 00468 *pdata = p; 00469 00470 Exit: 00471 return error; 00472 00473 Too_Short: 00474 error = PFR_Err_Invalid_Table; 00475 FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" )); 00476 goto Exit; 00477 } 00478 00479 00480 static FT_Error 00481 pfr_load_bitmap_bits( FT_Byte* p, 00482 FT_Byte* limit, 00483 FT_UInt format, 00484 FT_Bool decreasing, 00485 FT_Bitmap* target ) 00486 { 00487 FT_Error error = PFR_Err_Ok; 00488 PFR_BitWriterRec writer; 00489 00490 00491 if ( target->rows > 0 && target->width > 0 ) 00492 { 00493 pfr_bitwriter_init( &writer, target, decreasing ); 00494 00495 switch ( format ) 00496 { 00497 case 0: /* packed bits */ 00498 pfr_bitwriter_decode_bytes( &writer, p, limit ); 00499 break; 00500 00501 case 1: /* RLE1 */ 00502 pfr_bitwriter_decode_rle1( &writer, p, limit ); 00503 break; 00504 00505 case 2: /* RLE2 */ 00506 pfr_bitwriter_decode_rle2( &writer, p, limit ); 00507 break; 00508 00509 default: 00510 FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" )); 00511 error = PFR_Err_Invalid_File_Format; 00512 } 00513 } 00514 00515 return error; 00516 } 00517 00518 00519 /*************************************************************************/ 00520 /*************************************************************************/ 00521 /***** *****/ 00522 /***** BITMAP LOADING *****/ 00523 /***** *****/ 00524 /*************************************************************************/ 00525 /*************************************************************************/ 00526 00527 FT_LOCAL( FT_Error ) 00528 pfr_slot_load_bitmap( PFR_Slot glyph, 00529 PFR_Size size, 00530 FT_UInt glyph_index ) 00531 { 00532 FT_Error error; 00533 PFR_Face face = (PFR_Face) glyph->root.face; 00534 FT_Stream stream = face->root.stream; 00535 PFR_PhyFont phys = &face->phy_font; 00536 FT_ULong gps_offset; 00537 FT_ULong gps_size; 00538 PFR_Char character; 00539 PFR_Strike strike; 00540 00541 00542 character = &phys->chars[glyph_index]; 00543 00544 /* Look-up a bitmap strike corresponding to the current */ 00545 /* character dimensions */ 00546 { 00547 FT_UInt n; 00548 00549 00550 strike = phys->strikes; 00551 for ( n = 0; n < phys->num_strikes; n++ ) 00552 { 00553 if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem && 00554 strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem ) 00555 { 00556 goto Found_Strike; 00557 } 00558 00559 strike++; 00560 } 00561 00562 /* couldn't find it */ 00563 return PFR_Err_Invalid_Argument; 00564 } 00565 00566 Found_Strike: 00567 00568 /* Now lookup the glyph's position within the file */ 00569 { 00570 FT_UInt char_len; 00571 00572 00573 char_len = 4; 00574 if ( strike->flags & 1 ) char_len += 1; 00575 if ( strike->flags & 2 ) char_len += 1; 00576 if ( strike->flags & 4 ) char_len += 1; 00577 00578 /* Access data directly in the frame to speed lookups */ 00579 if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) || 00580 FT_FRAME_ENTER( char_len * strike->num_bitmaps ) ) 00581 goto Exit; 00582 00583 pfr_lookup_bitmap_data( stream->cursor, 00584 stream->limit, 00585 strike->num_bitmaps, 00586 strike->flags, 00587 character->char_code, 00588 &gps_offset, 00589 &gps_size ); 00590 00591 FT_FRAME_EXIT(); 00592 00593 if ( gps_size == 0 ) 00594 { 00595 /* Could not find a bitmap program string for this glyph */ 00596 error = PFR_Err_Invalid_Argument; 00597 goto Exit; 00598 } 00599 } 00600 00601 /* get the bitmap metrics */ 00602 { 00603 FT_Long xpos = 0, ypos = 0, advance = 0; 00604 FT_UInt xsize = 0, ysize = 0, format = 0; 00605 FT_Byte* p; 00606 00607 00608 /* compute linear advance */ 00609 advance = character->advance; 00610 if ( phys->metrics_resolution != phys->outline_resolution ) 00611 advance = FT_MulDiv( advance, 00612 phys->outline_resolution, 00613 phys->metrics_resolution ); 00614 00615 glyph->root.linearHoriAdvance = advance; 00616 00617 /* compute default advance, i.e., scaled advance. This can be */ 00618 /* overridden in the bitmap header of certain glyphs. */ 00619 advance = FT_MulDiv( (FT_Fixed)size->root.metrics.x_ppem << 8, 00620 character->advance, 00621 phys->metrics_resolution ); 00622 00623 if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) || 00624 FT_FRAME_ENTER( gps_size ) ) 00625 goto Exit; 00626 00627 p = stream->cursor; 00628 error = pfr_load_bitmap_metrics( &p, stream->limit, 00629 advance, 00630 &xpos, &ypos, 00631 &xsize, &ysize, 00632 &advance, &format ); 00633 00634 /* 00635 * XXX: on 16bit system, we return an error for huge bitmap 00636 * which causes a size truncation, because truncated 00637 * size properties makes bitmap glyph broken. 00638 */ 00639 if ( xpos > FT_INT_MAX || ( ypos + ysize ) > FT_INT_MAX ) 00640 { 00641 FT_TRACE1(( "pfr_slot_load_bitmap:" )); 00642 FT_TRACE1(( "huge bitmap glyph %dx%d over FT_GlyphSlot\n", 00643 xpos, ypos )); 00644 error = PFR_Err_Invalid_Pixel_Size; 00645 } 00646 00647 if ( !error ) 00648 { 00649 glyph->root.format = FT_GLYPH_FORMAT_BITMAP; 00650 00651 /* Set up glyph bitmap and metrics */ 00652 00653 /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */ 00654 glyph->root.bitmap.width = (FT_Int)xsize; 00655 glyph->root.bitmap.rows = (FT_Int)ysize; 00656 glyph->root.bitmap.pitch = (FT_Int)( xsize + 7 ) >> 3; 00657 glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO; 00658 00659 /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */ 00660 glyph->root.metrics.width = (FT_Pos)xsize << 6; 00661 glyph->root.metrics.height = (FT_Pos)ysize << 6; 00662 glyph->root.metrics.horiBearingX = xpos << 6; 00663 glyph->root.metrics.horiBearingY = ypos << 6; 00664 glyph->root.metrics.horiAdvance = FT_PIX_ROUND( ( advance >> 2 ) ); 00665 glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1; 00666 glyph->root.metrics.vertBearingY = 0; 00667 glyph->root.metrics.vertAdvance = size->root.metrics.height; 00668 00669 /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */ 00670 glyph->root.bitmap_left = (FT_Int)xpos; 00671 glyph->root.bitmap_top = (FT_Int)(ypos + ysize); 00672 00673 /* Allocate and read bitmap data */ 00674 { 00675 FT_ULong len = glyph->root.bitmap.pitch * ysize; 00676 00677 00678 error = ft_glyphslot_alloc_bitmap( &glyph->root, len ); 00679 if ( !error ) 00680 { 00681 error = pfr_load_bitmap_bits( 00682 p, 00683 stream->limit, 00684 format, 00685 FT_BOOL(face->header.color_flags & 2), 00686 &glyph->root.bitmap ); 00687 } 00688 } 00689 } 00690 00691 FT_FRAME_EXIT(); 00692 } 00693 00694 Exit: 00695 return error; 00696 } 00697 00698 /* END */ Generated on Sun May 27 2012 04:33:58 for ReactOS by
1.7.6.1
|