1/****************************************************************************
2 *
3 * pfrsbit.c
4 *
5 * FreeType PFR bitmap loader (body).
6 *
7 * Copyright (C) 2002-2023 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 <freetype/internal/ftdebug.h>
22#include <freetype/internal/ftstream.h>
23
24#include "pfrerror.h"
25
26#undef FT_COMPONENT
27#define FT_COMPONENT 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_UInt width; /* width in pixels/bits */
43 FT_UInt rows; /* number of remaining rows to scan */
44 FT_UInt total; /* total number of bits to draw */
45
46 } PFR_BitWriterRec, *PFR_BitWriter;
47
48
49 static void
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 * (FT_Int)( target->rows - 1 );
63 writer->pitch = -writer->pitch;
64 }
65 }
66
67
68 static void
69 pfr_bitwriter_decode_bytes( PFR_BitWriter writer,
70 FT_Byte* p,
71 FT_Byte* limit )
72 {
73 FT_UInt n, reload;
74 FT_UInt 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_UInt)( 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] = (FT_Byte)c;
111 mask = 0x80;
112 c = 0;
113 cur++;
114 }
115 }
116
117 if ( mask != 0x80 )
118 cur[0] = (FT_Byte)c;
119 }
120
121
122 static void
123 pfr_bitwriter_decode_rle1( PFR_BitWriter writer,
124 FT_Byte* p,
125 FT_Byte* limit )
126 {
127 FT_Int phase, count, counts[2];
128 FT_UInt n, reload;
129 FT_UInt left = writer->width;
130 FT_Byte* cur = writer->line;
131 FT_UInt mask = 0x80;
132 FT_UInt c = 0;
133
134
135 n = writer->total;
136
137 phase = 1;
138 counts[0] = 0;
139 counts[1] = 0;
140 count = 0;
141 reload = 1;
142
143 for ( ; n > 0; n-- )
144 {
145 if ( reload )
146 {
147 do
148 {
149 if ( phase )
150 {
151 FT_Int v;
152
153
154 if ( p >= limit )
155 break;
156
157 v = *p++;
158 counts[0] = v >> 4;
159 counts[1] = v & 15;
160 phase = 0;
161 count = counts[0];
162 }
163 else
164 {
165 phase = 1;
166 count = counts[1];
167 }
168
169 } while ( count == 0 );
170 }
171
172 if ( phase )
173 c |= mask;
174
175 mask >>= 1;
176
177 if ( --left <= 0 )
178 {
179 cur[0] = (FT_Byte)c;
180 left = writer->width;
181 mask = 0x80;
182
183 writer->line += writer->pitch;
184 cur = writer->line;
185 c = 0;
186 }
187 else if ( mask == 0 )
188 {
189 cur[0] = (FT_Byte)c;
190 mask = 0x80;
191 c = 0;
192 cur++;
193 }
194
195 reload = ( --count <= 0 );
196 }
197
198 if ( mask != 0x80 )
199 cur[0] = (FT_Byte) c;
200 }
201
202
203 static void
204 pfr_bitwriter_decode_rle2( PFR_BitWriter writer,
205 FT_Byte* p,
206 FT_Byte* limit )
207 {
208 FT_Int phase, count;
209 FT_UInt n, reload;
210 FT_UInt left = writer->width;
211 FT_Byte* cur = writer->line;
212 FT_UInt mask = 0x80;
213 FT_UInt c = 0;
214
215
216 n = writer->total;
217
218 phase = 1;
219 count = 0;
220 reload = 1;
221
222 for ( ; n > 0; n-- )
223 {
224 if ( reload )
225 {
226 do
227 {
228 if ( p >= limit )
229 break;
230
231 count = *p++;
232 phase = phase ^ 1;
233
234 } while ( count == 0 );
235 }
236
237 if ( phase )
238 c |= mask;
239
240 mask >>= 1;
241
242 if ( --left <= 0 )
243 {
244 cur[0] = (FT_Byte)c;
245 c = 0;
246 mask = 0x80;
247 left = writer->width;
248
249 writer->line += writer->pitch;
250 cur = writer->line;
251 }
252 else if ( mask == 0 )
253 {
254 cur[0] = (FT_Byte)c;
255 c = 0;
256 mask = 0x80;
257 cur++;
258 }
259
260 reload = ( --count <= 0 );
261 }
262
263 if ( mask != 0x80 )
264 cur[0] = (FT_Byte) c;
265 }
266
267
268 /*************************************************************************/
269 /*************************************************************************/
270 /***** *****/
271 /***** BITMAP DATA DECODING *****/
272 /***** *****/
273 /*************************************************************************/
274 /*************************************************************************/
275
276 static void
277 pfr_lookup_bitmap_data( FT_Byte* base,
278 FT_Byte* limit,
279 FT_UInt count,
280 FT_UInt* flags,
281 FT_UInt char_code,
282 FT_ULong* found_offset,
283 FT_ULong* found_size )
284 {
285 FT_UInt min, max, mid, char_len;
286 FT_Bool two = FT_BOOL( *flags & PFR_BITMAP_2BYTE_CHARCODE );
287 FT_Byte* buff;
288
289
290 char_len = 4;
291 if ( two )
292 char_len += 1;
293 if ( *flags & PFR_BITMAP_2BYTE_SIZE )
294 char_len += 1;
295 if ( *flags & PFR_BITMAP_3BYTE_OFFSET )
296 char_len += 1;
297
298 if ( !( *flags & PFR_BITMAP_CHARCODES_VALIDATED ) )
299 {
300 FT_Byte* p;
301 FT_Byte* lim;
302 FT_UInt code;
303 FT_Long prev_code;
304
305
306 *flags |= PFR_BITMAP_VALID_CHARCODES;
307 prev_code = -1;
308 lim = base + count * char_len;
309
310 if ( lim > limit )
311 {
312 FT_TRACE0(( "pfr_lookup_bitmap_data:"
313 " number of bitmap records too large,\n" ));
314 FT_TRACE0(( " "
315 " thus ignoring all bitmaps in this strike\n" ));
316 *flags &= ~PFR_BITMAP_VALID_CHARCODES;
317 }
318 else
319 {
320 /* check whether records are sorted by code */
321 for ( p = base; p < lim; p += char_len )
322 {
323 if ( two )
324 code = FT_PEEK_USHORT( p );
325 else
326 code = *p;
327
328 if ( (FT_Long)code <= prev_code )
329 {
330 FT_TRACE0(( "pfr_lookup_bitmap_data:"
331 " bitmap records are not sorted,\n" ));
332 FT_TRACE0(( " "
333 " thus ignoring all bitmaps in this strike\n" ));
334 *flags &= ~PFR_BITMAP_VALID_CHARCODES;
335 break;
336 }
337
338 prev_code = code;
339 }
340 }
341
342 *flags |= PFR_BITMAP_CHARCODES_VALIDATED;
343 }
344
345 /* ignore bitmaps in case table is not valid */
346 /* (this might be sanitized, but PFR is dead...) */
347 if ( !( *flags & PFR_BITMAP_VALID_CHARCODES ) )
348 goto Fail;
349
350 min = 0;
351 max = count;
352 mid = min + ( max - min ) / 2;
353
354 /* binary search */
355 while ( min < max )
356 {
357 FT_UInt code;
358
359
360 buff = base + mid * char_len;
361
362 if ( two )
363 code = PFR_NEXT_USHORT( buff );
364 else
365 code = PFR_NEXT_BYTE( buff );
366
367 if ( char_code < code )
368 max = mid;
369 else if ( char_code > code )
370 min = mid + 1;
371 else
372 goto Found_It;
373
374 /* reasonable prediction in a continuous block */
375 mid += char_code - code;
376 if ( mid >= max || mid < min )
377 mid = min + ( max - min ) / 2;
378 }
379
380 Fail:
381 /* Not found */
382 *found_size = 0;
383 *found_offset = 0;
384 return;
385
386 Found_It:
387 if ( *flags & PFR_BITMAP_2BYTE_SIZE )
388 *found_size = PFR_NEXT_USHORT( buff );
389 else
390 *found_size = PFR_NEXT_BYTE( buff );
391
392 if ( *flags & PFR_BITMAP_3BYTE_OFFSET )
393 *found_offset = PFR_NEXT_ULONG( buff );
394 else
395 *found_offset = PFR_NEXT_USHORT( buff );
396 }
397
398
399 /* load bitmap metrics. `*aadvance' must be set to the default value */
400 /* before calling this function */
401 /* */
402 static FT_Error
403 pfr_load_bitmap_metrics( FT_Byte** pdata,
404 FT_Byte* limit,
405 FT_Long scaled_advance,
406 FT_Long *axpos,
407 FT_Long *aypos,
408 FT_UInt *axsize,
409 FT_UInt *aysize,
410 FT_Long *aadvance,
411 FT_UInt *aformat )
412 {
413 FT_Error error = FT_Err_Ok;
414 FT_Byte flags;
415 FT_Byte b;
416 FT_Byte* p = *pdata;
417 FT_Long xpos, ypos, advance;
418 FT_UInt xsize, ysize;
419
420
421 PFR_CHECK( 1 );
422 flags = PFR_NEXT_BYTE( p );
423
424 xpos = 0;
425 ypos = 0;
426 xsize = 0;
427 ysize = 0;
428 advance = 0;
429
430 switch ( flags & 3 )
431 {
432 case 0:
433 PFR_CHECK( 1 );
434 b = PFR_NEXT_BYTE( p );
435 xpos = (FT_Char)b >> 4;
436 ypos = ( (FT_Char)( b << 4 ) ) >> 4;
437 break;
438
439 case 1:
440 PFR_CHECK( 2 );
441 xpos = PFR_NEXT_INT8( p );
442 ypos = PFR_NEXT_INT8( p );
443 break;
444
445 case 2:
446 PFR_CHECK( 4 );
447 xpos = PFR_NEXT_SHORT( p );
448 ypos = PFR_NEXT_SHORT( p );
449 break;
450
451 case 3:
452 PFR_CHECK( 6 );
453 xpos = PFR_NEXT_LONG( p );
454 ypos = PFR_NEXT_LONG( p );
455 break;
456
457 default:
458 ;
459 }
460
461 flags >>= 2;
462 switch ( flags & 3 )
463 {
464 case 0:
465 /* blank image */
466 xsize = 0;
467 ysize = 0;
468 break;
469
470 case 1:
471 PFR_CHECK( 1 );
472 b = PFR_NEXT_BYTE( p );
473 xsize = ( b >> 4 ) & 0xF;
474 ysize = b & 0xF;
475 break;
476
477 case 2:
478 PFR_CHECK( 2 );
479 xsize = PFR_NEXT_BYTE( p );
480 ysize = PFR_NEXT_BYTE( p );
481 break;
482
483 case 3:
484 PFR_CHECK( 4 );
485 xsize = PFR_NEXT_USHORT( p );
486 ysize = PFR_NEXT_USHORT( p );
487 break;
488
489 default:
490 ;
491 }
492
493 flags >>= 2;
494 switch ( flags & 3 )
495 {
496 case 0:
497 advance = scaled_advance;
498 break;
499
500 case 1:
501 PFR_CHECK( 1 );
502 advance = PFR_NEXT_INT8( p ) * 256;
503 break;
504
505 case 2:
506 PFR_CHECK( 2 );
507 advance = PFR_NEXT_SHORT( p );
508 break;
509
510 case 3:
511 PFR_CHECK( 3 );
512 advance = PFR_NEXT_LONG( p );
513 break;
514
515 default:
516 ;
517 }
518
519 *axpos = xpos;
520 *aypos = ypos;
521 *axsize = xsize;
522 *aysize = ysize;
523 *aadvance = advance;
524 *aformat = flags >> 2;
525 *pdata = p;
526
527 Exit:
528 return error;
529
530 Too_Short:
531 error = FT_THROW( Invalid_Table );
532 FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
533 goto Exit;
534 }
535
536
537 static FT_Error
538 pfr_load_bitmap_bits( FT_Byte* p,
539 FT_Byte* limit,
540 FT_UInt format,
541 FT_Bool decreasing,
542 FT_Bitmap* target )
543 {
544 FT_Error error = FT_Err_Ok;
545 PFR_BitWriterRec writer;
546
547
548 if ( target->rows > 0 && target->width > 0 )
549 {
550 pfr_bitwriter_init( &writer, target, decreasing );
551
552 switch ( format )
553 {
554 case 0: /* packed bits */
555 pfr_bitwriter_decode_bytes( &writer, p, limit );
556 break;
557
558 case 1: /* RLE1 */
559 pfr_bitwriter_decode_rle1( &writer, p, limit );
560 break;
561
562 case 2: /* RLE2 */
563 pfr_bitwriter_decode_rle2( &writer, p, limit );
564 break;
565
566 default:
567 ;
568 }
569 }
570
571 return error;
572 }
573
574
575 /*************************************************************************/
576 /*************************************************************************/
577 /***** *****/
578 /***** BITMAP LOADING *****/
579 /***** *****/
580 /*************************************************************************/
581 /*************************************************************************/
582
583 FT_LOCAL_DEF( FT_Error )
584 pfr_slot_load_bitmap( PFR_Slot glyph,
585 PFR_Size size,
586 FT_UInt glyph_index,
587 FT_Bool metrics_only )
588 {
589 FT_Error error;
590 PFR_Face face = (PFR_Face) glyph->root.face;
591 FT_Stream stream = face->root.stream;
592 PFR_PhyFont phys = &face->phy_font;
593 FT_ULong gps_offset;
594 FT_ULong gps_size;
595 PFR_Char character;
596 PFR_Strike strike;
597
598
599 character = &phys->chars[glyph_index];
600
601 /* look up a bitmap strike corresponding to the current */
602 /* character dimensions */
603 {
604 FT_UInt n;
605
606
607 strike = phys->strikes;
608 for ( n = 0; n < phys->num_strikes; n++ )
609 {
610 if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&
611 strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )
612 goto Found_Strike;
613
614 strike++;
615 }
616
617 /* couldn't find it */
618 return FT_THROW( Invalid_Argument );
619 }
620
621 Found_Strike:
622
623 /* now look up the glyph's position within the file */
624 {
625 FT_UInt char_len;
626
627
628 char_len = 4;
629 if ( strike->flags & PFR_BITMAP_2BYTE_CHARCODE )
630 char_len += 1;
631 if ( strike->flags & PFR_BITMAP_2BYTE_SIZE )
632 char_len += 1;
633 if ( strike->flags & PFR_BITMAP_3BYTE_OFFSET )
634 char_len += 1;
635
636 /* access data directly in the frame to speed up lookups */
637 if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
638 FT_FRAME_ENTER( char_len * strike->num_bitmaps ) )
639 goto Exit;
640
641 pfr_lookup_bitmap_data( stream->cursor,
642 stream->limit,
643 strike->num_bitmaps,
644 &strike->flags,
645 character->char_code,
646 &gps_offset,
647 &gps_size );
648
649 FT_FRAME_EXIT();
650
651 if ( gps_size == 0 )
652 {
653 /* could not find a bitmap program string for this glyph */
654 error = FT_THROW( Invalid_Argument );
655 goto Exit;
656 }
657 }
658
659 /* get the bitmap metrics */
660 {
661 FT_Long xpos = 0, ypos = 0, advance = 0;
662 FT_UInt xsize = 0, ysize = 0, format = 0;
663 FT_Byte* p;
664
665
666 /* compute linear advance */
667 advance = character->advance;
668 if ( phys->metrics_resolution != phys->outline_resolution )
669 advance = FT_MulDiv( advance,
670 (FT_Long)phys->outline_resolution,
671 (FT_Long)phys->metrics_resolution );
672
673 glyph->root.linearHoriAdvance = advance;
674
675 /* compute default advance, i.e., scaled advance; this can be */
676 /* overridden in the bitmap header of certain glyphs */
677 advance = FT_MulDiv( (FT_Fixed)size->root.metrics.x_ppem << 8,
678 character->advance,
679 (FT_Long)phys->metrics_resolution );
680
681 if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
682 FT_FRAME_ENTER( gps_size ) )
683 goto Exit;
684
685 p = stream->cursor;
686 error = pfr_load_bitmap_metrics( &p, stream->limit,
687 advance,
688 &xpos, &ypos,
689 &xsize, &ysize,
690 &advance, &format );
691 if ( error )
692 goto Exit1;
693
694 /*
695 * Before allocating the target bitmap, we check whether the given
696 * bitmap dimensions are valid, depending on the image format.
697 *
698 * Format 0: We have a stream of pixels (with 8 pixels per byte).
699 *
700 * (xsize * ysize + 7) / 8 <= gps_size
701 *
702 * Format 1: Run-length encoding; the high nibble holds the number of
703 * white bits, the low nibble the number of black bits. In
704 * other words, a single byte can represent at most 15
705 * pixels.
706 *
707 * xsize * ysize <= 15 * gps_size
708 *
709 * Format 2: Run-length encoding; the high byte holds the number of
710 * white bits, the low byte the number of black bits. In
711 * other words, two bytes can represent at most 255 pixels.
712 *
713 * xsize * ysize <= 255 * (gps_size + 1) / 2
714 */
715 switch ( format )
716 {
717 case 0:
718 if ( ( (FT_ULong)xsize * ysize + 7 ) / 8 > gps_size )
719 error = FT_THROW( Invalid_Table );
720 break;
721 case 1:
722 if ( (FT_ULong)xsize * ysize > 15 * gps_size )
723 error = FT_THROW( Invalid_Table );
724 break;
725 case 2:
726 if ( (FT_ULong)xsize * ysize > 255 * ( ( gps_size + 1 ) / 2 ) )
727 error = FT_THROW( Invalid_Table );
728 break;
729 default:
730 FT_ERROR(( "pfr_slot_load_bitmap: invalid image type\n" ));
731 error = FT_THROW( Invalid_Table );
732 }
733
734 if ( error )
735 {
736 if ( FT_ERR_EQ( error, Invalid_Table ) )
737 FT_ERROR(( "pfr_slot_load_bitmap: invalid bitmap dimensions\n" ));
738 goto Exit1;
739 }
740
741 /*
742 * XXX: on 16bit systems we return an error for huge bitmaps
743 * that cause size truncation, because truncated
744 * size properties make bitmap glyphs broken.
745 */
746 if ( xpos > FT_INT_MAX ||
747 xpos < FT_INT_MIN ||
748 ysize > FT_INT_MAX ||
749 ypos > FT_INT_MAX - (FT_Long)ysize ||
750 ypos + (FT_Long)ysize < FT_INT_MIN )
751 {
752 FT_TRACE1(( "pfr_slot_load_bitmap:"
753 " huge bitmap glyph %ldx%ld over FT_GlyphSlot\n",
754 xpos, ypos ));
755 error = FT_THROW( Invalid_Pixel_Size );
756 }
757
758 if ( !error )
759 {
760 glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
761
762 /* Set up glyph bitmap and metrics */
763
764 /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */
765 glyph->root.bitmap.width = xsize;
766 glyph->root.bitmap.rows = ysize;
767 glyph->root.bitmap.pitch = (FT_Int)( xsize + 7 ) >> 3;
768 glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
769
770 /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */
771 glyph->root.metrics.width = (FT_Pos)xsize << 6;
772 glyph->root.metrics.height = (FT_Pos)ysize << 6;
773 glyph->root.metrics.horiBearingX = xpos * 64;
774 glyph->root.metrics.horiBearingY = ypos * 64;
775 glyph->root.metrics.horiAdvance = FT_PIX_ROUND( ( advance >> 2 ) );
776 glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
777 glyph->root.metrics.vertBearingY = 0;
778 glyph->root.metrics.vertAdvance = size->root.metrics.height;
779
780 /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */
781 glyph->root.bitmap_left = (FT_Int)xpos;
782 glyph->root.bitmap_top = (FT_Int)( ypos + (FT_Long)ysize );
783
784 if ( metrics_only )
785 goto Exit1;
786
787 /* Allocate and read bitmap data */
788 {
789 FT_ULong len = (FT_ULong)glyph->root.bitmap.pitch * ysize;
790
791
792 error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
793 if ( !error )
794 error = pfr_load_bitmap_bits(
795 p,
796 stream->limit,
797 format,
798 FT_BOOL( face->header.color_flags &
799 PFR_FLAG_INVERT_BITMAP ),
800 &glyph->root.bitmap );
801 }
802 }
803
804 Exit1:
805 FT_FRAME_EXIT();
806 }
807
808 Exit:
809 return error;
810 }
811
812
813/* END */
814