1 /***************************************************************************/ 2 /* */ 3 /* pfrsbit.c */ 4 /* */ 5 /* FreeType PFR bitmap loader (body). */ 6 /* */ 7 /* Copyright 2002 by */ 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9 /* */ 10 /* This file is part of the FreeType project, and may only be used, */ 11 /* modified, and distributed under the terms of the FreeType project */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13 /* this file you indicate that you have read the license and */ 14 /* understand and accept it fully. */ 15 /* */ 16 /***************************************************************************/ 17 18 19 #include "pfrsbit.h" 20 #include "pfrload.h" 21 #include FT_INTERNAL_DEBUG_H 22 #include FT_INTERNAL_STREAM_H 23 24 #include "pfrerror.h" 25 26 #undef FT_COMPONENT 27 #define FT_COMPONENT trace_pfr 28 29 30 /*************************************************************************/ 31 /*************************************************************************/ 32 /***** *****/ 33 /***** PFR BIT WRITER *****/ 34 /***** *****/ 35 /*************************************************************************/ 36 /*************************************************************************/ 37 38 typedef struct PFR_BitWriter_ 39 { 40 FT_Byte* line; /* current line start */ 41 FT_Int pitch; /* line size in bytes */ 42 FT_Int width; /* width in pixels/bits */ 43 FT_Int rows; /* number of remaining rows to scan */ 44 FT_Int total; /* total number of bits to draw */ 45 46 } PFR_BitWriterRec, *PFR_BitWriter; 47 48 49 static void pfr_bitwriter_init(PFR_BitWriter writer,FT_Bitmap * target,FT_Bool decreasing)50 pfr_bitwriter_init( PFR_BitWriter writer, 51 FT_Bitmap* target, 52 FT_Bool decreasing ) 53 { 54 writer->line = target->buffer; 55 writer->pitch = target->pitch; 56 writer->width = target->width; 57 writer->rows = target->rows; 58 writer->total = writer->width * writer->rows; 59 60 if ( !decreasing ) 61 { 62 writer->line += writer->pitch * ( target->rows-1 ); 63 writer->pitch = -writer->pitch; 64 } 65 } 66 67 68 static void pfr_bitwriter_decode_bytes(PFR_BitWriter writer,FT_Byte * p,FT_Byte * limit)69 pfr_bitwriter_decode_bytes( PFR_BitWriter writer, 70 FT_Byte* p, 71 FT_Byte* limit ) 72 { 73 FT_Int n, reload; 74 FT_Int left = writer->width; 75 FT_Byte* cur = writer->line; 76 FT_UInt mask = 0x80; 77 FT_UInt val = 0; 78 FT_UInt c = 0; 79 80 81 n = (FT_Int)( limit - p ) * 8; 82 if ( n > writer->total ) 83 n = writer->total; 84 85 reload = n & 7; 86 87 for ( ; n > 0; n-- ) 88 { 89 if ( ( n & 7 ) == reload ) 90 val = *p++; 91 92 if ( val & 0x80 ) 93 c |= mask; 94 95 val <<= 1; 96 mask >>= 1; 97 98 if ( --left <= 0 ) 99 { 100 cur[0] = (FT_Byte)c; 101 left = writer->width; 102 mask = 0x80; 103 104 writer->line += writer->pitch; 105 cur = writer->line; 106 c = 0; 107 } 108 else if ( mask == 0 ) 109 { 110 cur[0] = c; 111 mask = 0x80; 112 c = 0; 113 cur ++; 114 } 115 } 116 117 if ( mask != 0x80 ) 118 cur[0] = c; 119 } 120 121 122 static void pfr_bitwriter_decode_rle1(PFR_BitWriter writer,FT_Byte * p,FT_Byte * limit)123 pfr_bitwriter_decode_rle1( PFR_BitWriter writer, 124 FT_Byte* p, 125 FT_Byte* limit ) 126 { 127 FT_Int n, phase, count, counts[2], reload; 128 FT_Int left = writer->width; 129 FT_Byte* cur = writer->line; 130 FT_UInt mask = 0x80; 131 FT_UInt c = 0; 132 133 134 n = writer->total; 135 136 phase = 1; 137 counts[0] = 0; 138 counts[1] = 0; 139 count = 0; 140 reload = 1; 141 142 for ( ; n > 0; n-- ) 143 { 144 if ( reload ) 145 { 146 do 147 { 148 if ( phase ) 149 { 150 FT_Int v; 151 152 153 if ( p >= limit ) 154 break; 155 156 v = *p++; 157 counts[0] = v >> 4; 158 counts[1] = v & 15; 159 phase = 0; 160 count = counts[0]; 161 } 162 else 163 { 164 phase = 1; 165 count = counts[1]; 166 } 167 168 } while ( count == 0 ); 169 } 170 171 if ( phase ) 172 c |= mask; 173 174 mask >>= 1; 175 176 if ( --left <= 0 ) 177 { 178 cur[0] = (FT_Byte) c; 179 left = writer->width; 180 mask = 0x80; 181 182 writer->line += writer->pitch; 183 cur = writer->line; 184 c = 0; 185 } 186 else if ( mask == 0 ) 187 { 188 cur[0] = c; 189 mask = 0x80; 190 c = 0; 191 cur ++; 192 } 193 194 reload = ( --count <= 0 ); 195 } 196 197 if ( mask != 0x80 ) 198 cur[0] = (FT_Byte) c; 199 } 200 201 202 static void pfr_bitwriter_decode_rle2(PFR_BitWriter writer,FT_Byte * p,FT_Byte * limit)203 pfr_bitwriter_decode_rle2( PFR_BitWriter writer, 204 FT_Byte* p, 205 FT_Byte* limit ) 206 { 207 FT_Int n, phase, count, reload; 208 FT_Int left = writer->width; 209 FT_Byte* cur = writer->line; 210 FT_UInt mask = 0x80; 211 FT_UInt c = 0; 212 213 214 n = writer->total; 215 216 phase = 1; 217 count = 0; 218 reload = 1; 219 220 for ( ; n > 0; n-- ) 221 { 222 if ( reload ) 223 { 224 do 225 { 226 if ( p >= limit ) 227 break; 228 229 count = *p++; 230 phase = phase ^ 1; 231 232 } while ( count == 0 ); 233 } 234 235 if ( phase ) 236 c |= mask; 237 238 mask >>= 1; 239 240 if ( --left <= 0 ) 241 { 242 cur[0] = (FT_Byte) c; 243 c = 0; 244 mask = 0x80; 245 left = writer->width; 246 247 writer->line += writer->pitch; 248 cur = writer->line; 249 } 250 else if ( mask == 0 ) 251 { 252 cur[0] = c; 253 c = 0; 254 mask = 0x80; 255 cur ++; 256 } 257 258 reload = ( --count <= 0 ); 259 } 260 261 if ( mask != 0x80 ) 262 cur[0] = (FT_Byte) c; 263 } 264 265 266 /*************************************************************************/ 267 /*************************************************************************/ 268 /***** *****/ 269 /***** BITMAP DATA DECODING *****/ 270 /***** *****/ 271 /*************************************************************************/ 272 /*************************************************************************/ 273 274 static void pfr_lookup_bitmap_data(FT_Byte * base,FT_Byte * limit,FT_Int count,FT_Byte flags,FT_UInt char_code,FT_ULong * found_offset,FT_ULong * found_size)275 pfr_lookup_bitmap_data( FT_Byte* base, 276 FT_Byte* limit, 277 FT_Int count, 278 FT_Byte flags, 279 FT_UInt char_code, 280 FT_ULong* found_offset, 281 FT_ULong* found_size ) 282 { 283 FT_UInt left, right, char_len; 284 FT_Bool two = flags & 1; 285 FT_Byte* buff; 286 287 288 char_len = 4; 289 if ( two ) char_len += 1; 290 if ( flags & 2 ) char_len += 1; 291 if ( flags & 4 ) char_len += 1; 292 293 left = 0; 294 right = count; 295 296 while ( left < right ) 297 { 298 FT_UInt middle, code; 299 300 301 middle = ( left + right ) >> 1; 302 buff = base + middle * char_len; 303 304 /* check that we are not outside of the table -- */ 305 /* this is possible with broken fonts... */ 306 if ( buff + char_len > limit ) 307 goto Fail; 308 309 if ( two ) 310 code = PFR_NEXT_USHORT( buff ); 311 else 312 code = PFR_NEXT_BYTE( buff ); 313 314 if ( code == char_code ) 315 goto Found_It; 316 317 if ( code < char_code ) 318 left = middle; 319 else 320 right = middle; 321 } 322 323 Fail: 324 /* Not found */ 325 *found_size = 0; 326 *found_offset = 0; 327 return; 328 329 Found_It: 330 if ( flags & 2 ) 331 *found_size = PFR_NEXT_USHORT( buff ); 332 else 333 *found_size = PFR_NEXT_BYTE( buff ); 334 335 if ( flags & 4 ) 336 *found_offset = PFR_NEXT_ULONG( buff ); 337 else 338 *found_offset = PFR_NEXT_USHORT( buff ); 339 } 340 341 342 /* load bitmap metrics. "*padvance" must be set to the default value */ 343 /* before calling this function... */ 344 /* */ 345 static FT_Error pfr_load_bitmap_metrics(FT_Byte ** pdata,FT_Byte * limit,FT_Long scaled_advance,FT_Long * axpos,FT_Long * aypos,FT_UInt * axsize,FT_UInt * aysize,FT_Long * aadvance,FT_UInt * aformat)346 pfr_load_bitmap_metrics( FT_Byte** pdata, 347 FT_Byte* limit, 348 FT_Long scaled_advance, 349 FT_Long *axpos, 350 FT_Long *aypos, 351 FT_UInt *axsize, 352 FT_UInt *aysize, 353 FT_Long *aadvance, 354 FT_UInt *aformat ) 355 { 356 FT_Error error = 0; 357 FT_Byte flags; 358 FT_Char b; 359 FT_Byte* p = *pdata; 360 FT_Long xpos, ypos, advance; 361 FT_UInt xsize, ysize; 362 363 364 PFR_CHECK( 1 ); 365 flags = PFR_NEXT_BYTE( p ); 366 367 xpos = 0; 368 ypos = 0; 369 xsize = 0; 370 ysize = 0; 371 advance = 0; 372 373 switch ( flags & 3 ) 374 { 375 case 0: 376 PFR_CHECK( 1 ); 377 b = PFR_NEXT_INT8( p ); 378 xpos = b >> 4; 379 ypos = ( (FT_Char)( b << 4 ) ) >> 4; 380 break; 381 382 case 1: 383 PFR_CHECK( 2 ); 384 xpos = PFR_NEXT_INT8( p ); 385 ypos = PFR_NEXT_INT8( p ); 386 break; 387 388 case 2: 389 PFR_CHECK( 4 ); 390 xpos = PFR_NEXT_SHORT( p ); 391 ypos = PFR_NEXT_SHORT( p ); 392 break; 393 394 case 3: 395 PFR_CHECK( 6 ); 396 xpos = PFR_NEXT_LONG( p ); 397 ypos = PFR_NEXT_LONG( p ); 398 break; 399 400 default: 401 ; 402 } 403 404 flags >>= 2; 405 switch ( flags & 3 ) 406 { 407 case 0: 408 /* blank image */ 409 xsize = 0; 410 ysize = 0; 411 break; 412 413 case 1: 414 PFR_CHECK( 1 ); 415 b = PFR_NEXT_BYTE( p ); 416 xsize = ( b >> 4 ) & 0xF; 417 ysize = b & 0xF; 418 break; 419 420 case 2: 421 PFR_CHECK( 2 ); 422 xsize = PFR_NEXT_BYTE( p ); 423 ysize = PFR_NEXT_BYTE( p ); 424 break; 425 426 case 3: 427 PFR_CHECK( 4 ); 428 xsize = PFR_NEXT_USHORT( p ); 429 ysize = PFR_NEXT_USHORT( p ); 430 break; 431 432 default: 433 ; 434 } 435 436 flags >>= 2; 437 switch ( flags & 3 ) 438 { 439 case 0: 440 advance = scaled_advance; 441 break; 442 443 case 1: 444 PFR_CHECK( 1 ); 445 advance = PFR_NEXT_INT8( p ) << 8; 446 break; 447 448 case 2: 449 PFR_CHECK( 2 ); 450 advance = PFR_NEXT_SHORT( p ); 451 break; 452 453 case 3: 454 PFR_CHECK( 3 ); 455 advance = PFR_NEXT_LONG( p ); 456 break; 457 458 default: 459 ; 460 } 461 462 *axpos = xpos; 463 *aypos = ypos; 464 *axsize = xsize; 465 *aysize = ysize; 466 *aadvance = advance; 467 *aformat = flags >> 2; 468 *pdata = p; 469 470 Exit: 471 return error; 472 473 Too_Short: 474 error = PFR_Err_Invalid_Table; 475 FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" )); 476 goto Exit; 477 } 478 479 480 static FT_Error pfr_load_bitmap_bits(FT_Byte * p,FT_Byte * limit,FT_UInt format,FT_UInt decreasing,FT_Bitmap * target)481 pfr_load_bitmap_bits( FT_Byte* p, 482 FT_Byte* limit, 483 FT_UInt format, 484 FT_UInt decreasing, 485 FT_Bitmap* target ) 486 { 487 FT_Error error = 0; 488 PFR_BitWriterRec writer; 489 490 491 if ( target->rows > 0 && target->width > 0 ) 492 { 493 pfr_bitwriter_init( &writer, target, decreasing ); 494 495 switch ( format ) 496 { 497 case 0: /* packed bits */ 498 pfr_bitwriter_decode_bytes( &writer, p, limit ); 499 break; 500 501 case 1: /* RLE1 */ 502 pfr_bitwriter_decode_rle1( &writer, p, limit ); 503 break; 504 505 case 2: /* RLE2 */ 506 pfr_bitwriter_decode_rle2( &writer, p, limit ); 507 break; 508 509 default: 510 FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" )); 511 error = FT_Err_Invalid_File_Format; 512 } 513 } 514 515 return error; 516 } 517 518 519 /*************************************************************************/ 520 /*************************************************************************/ 521 /***** *****/ 522 /***** BITMAP LOADING *****/ 523 /***** *****/ 524 /*************************************************************************/ 525 /*************************************************************************/ 526 527 FT_LOCAL( FT_Error ) pfr_slot_load_bitmap(PFR_Slot glyph,PFR_Size size,FT_UInt glyph_index)528 pfr_slot_load_bitmap( PFR_Slot glyph, 529 PFR_Size size, 530 FT_UInt glyph_index ) 531 { 532 FT_Error error; 533 PFR_Face face = (PFR_Face) glyph->root.face; 534 FT_Stream stream = face->root.stream; 535 PFR_PhyFont phys = &face->phy_font; 536 FT_ULong gps_offset; 537 FT_ULong gps_size; 538 PFR_Char character; 539 PFR_Strike strike; 540 541 542 character = &phys->chars[glyph_index]; 543 544 /* Look-up a bitmap strike corresponding to the current */ 545 /* character dimensions */ 546 { 547 FT_UInt n; 548 549 550 strike = phys->strikes; 551 for ( n = 0; n < phys->num_strikes; n++ ) 552 { 553 if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem && 554 strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem ) 555 { 556 goto Found_Strike; 557 } 558 559 strike++; 560 } 561 562 /* couldn't find it */ 563 return FT_Err_Invalid_Argument; 564 } 565 566 Found_Strike: 567 568 /* Now lookup the glyph's position within the file */ 569 { 570 FT_UInt char_len; 571 572 573 char_len = 4; 574 if ( strike->flags & 1 ) char_len += 1; 575 if ( strike->flags & 2 ) char_len += 1; 576 if ( strike->flags & 4 ) char_len += 1; 577 578 /* Access data directly in the frame to speed lookups */ 579 if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) || 580 FT_FRAME_ENTER( char_len * strike->num_bitmaps ) ) 581 goto Exit; 582 583 pfr_lookup_bitmap_data( stream->cursor, 584 stream->limit, 585 strike->num_bitmaps, 586 strike->flags, 587 character->char_code, 588 &gps_offset, 589 &gps_size ); 590 591 FT_FRAME_EXIT(); 592 593 if ( gps_size == 0 ) 594 { 595 /* Could not find a bitmap program string for this glyph */ 596 error = FT_Err_Invalid_Argument; 597 goto Exit; 598 } 599 } 600 601 /* get the bitmap metrics */ 602 { 603 FT_Long xpos, ypos, advance; 604 FT_UInt xsize, ysize, format; 605 FT_Byte* p; 606 607 608 advance = FT_MulDiv( size->root.metrics.x_ppem << 8, 609 character->advance, 610 phys->metrics_resolution ); 611 612 /* XXX: handle linearHoriAdvance correctly! */ 613 614 if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) || 615 FT_FRAME_ENTER( gps_size ) ) 616 goto Exit; 617 618 p = stream->cursor; 619 error = pfr_load_bitmap_metrics( &p, stream->limit, 620 advance, 621 &xpos, &ypos, 622 &xsize, &ysize, 623 &advance, &format ); 624 if ( !error ) 625 { 626 glyph->root.format = FT_GLYPH_FORMAT_BITMAP; 627 628 /* Set up glyph bitmap and metrics */ 629 glyph->root.bitmap.width = (FT_Int)xsize; 630 glyph->root.bitmap.rows = (FT_Int)ysize; 631 glyph->root.bitmap.pitch = (FT_Long)( xsize + 7 ) >> 3; 632 glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO; 633 634 glyph->root.metrics.width = (FT_Long)xsize << 6; 635 glyph->root.metrics.height = (FT_Long)ysize << 6; 636 glyph->root.metrics.horiBearingX = xpos << 6; 637 glyph->root.metrics.horiBearingY = ypos << 6; 638 glyph->root.metrics.horiAdvance = ( ( advance >> 2 ) + 32 ) & -64; 639 glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1; 640 glyph->root.metrics.vertBearingY = 0; 641 glyph->root.metrics.vertAdvance = size->root.metrics.height; 642 643 glyph->root.bitmap_left = xpos; 644 glyph->root.bitmap_top = ypos + ysize; 645 646 /* Allocate and read bitmap data */ 647 { 648 FT_Memory memory = face->root.memory; 649 FT_Long len = glyph->root.bitmap.pitch * ysize; 650 651 652 if ( !FT_ALLOC( glyph->root.bitmap.buffer, len ) ) 653 { 654 error = pfr_load_bitmap_bits( p, 655 stream->limit, 656 format, 657 face->header.color_flags & 2, 658 &glyph->root.bitmap ); 659 } 660 } 661 } 662 663 FT_FRAME_EXIT(); 664 } 665 666 Exit: 667 return error; 668 } 669 670 /* END */ 671