1 /****************************************************************************
5 * FreeType PFR bitmap loader (body).
7 * Copyright (C) 2002-2020 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
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.
21 #include <freetype/internal/ftdebug.h>
22 #include <freetype/internal/ftstream.h>
27 #define FT_COMPONENT pfr
30 /*************************************************************************/
31 /*************************************************************************/
33 /***** PFR BIT WRITER *****/
35 /*************************************************************************/
36 /*************************************************************************/
38 typedef struct PFR_BitWriter_
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 */
46 } PFR_BitWriterRec, *PFR_BitWriter;
50 pfr_bitwriter_init( PFR_BitWriter writer,
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;
62 writer->line += writer->pitch * (FT_Int)( target->rows - 1 );
63 writer->pitch = -writer->pitch;
69 pfr_bitwriter_decode_bytes( PFR_BitWriter writer,
74 FT_UInt left = writer->width;
75 FT_Byte* cur = writer->line;
81 n = (FT_UInt)( limit - p ) * 8;
82 if ( n > writer->total )
89 if ( ( n & 7 ) == reload )
101 left = writer->width;
104 writer->line += writer->pitch;
108 else if ( mask == 0 )
123 pfr_bitwriter_decode_rle1( PFR_BitWriter writer,
127 FT_Int phase, count, counts[2];
129 FT_UInt left = writer->width;
130 FT_Byte* cur = writer->line;
169 } while ( count == 0 );
180 left = writer->width;
183 writer->line += writer->pitch;
187 else if ( mask == 0 )
195 reload = ( --count <= 0 );
199 cur[0] = (FT_Byte) c;
204 pfr_bitwriter_decode_rle2( PFR_BitWriter writer,
210 FT_UInt left = writer->width;
211 FT_Byte* cur = writer->line;
234 } while ( count == 0 );
247 left = writer->width;
249 writer->line += writer->pitch;
252 else if ( mask == 0 )
260 reload = ( --count <= 0 );
264 cur[0] = (FT_Byte) c;
268 /*************************************************************************/
269 /*************************************************************************/
271 /***** BITMAP DATA DECODING *****/
273 /*************************************************************************/
274 /*************************************************************************/
277 pfr_lookup_bitmap_data( FT_Byte* base,
282 FT_ULong* found_offset,
283 FT_ULong* found_size )
285 FT_UInt min, max, char_len;
286 FT_Bool two = FT_BOOL( *flags & PFR_BITMAP_2BYTE_CHARCODE );
293 if ( *flags & PFR_BITMAP_2BYTE_SIZE )
295 if ( *flags & PFR_BITMAP_3BYTE_OFFSET )
298 if ( !( *flags & PFR_BITMAP_CHARCODES_VALIDATED ) )
306 *flags |= PFR_BITMAP_VALID_CHARCODES;
308 lim = base + count * char_len;
312 FT_TRACE0(( "pfr_lookup_bitmap_data:"
313 " number of bitmap records too large,\n"
315 " thus ignoring all bitmaps in this strike\n" ));
316 *flags &= ~PFR_BITMAP_VALID_CHARCODES;
320 /* check whether records are sorted by code */
321 for ( p = base; p < lim; p += char_len )
324 code = FT_PEEK_USHORT( p );
328 if ( (FT_Long)code <= prev_code )
330 FT_TRACE0(( "pfr_lookup_bitmap_data:"
331 " bitmap records are not sorted,\n"
333 " thus ignoring all bitmaps in this strike\n" ));
334 *flags &= ~PFR_BITMAP_VALID_CHARCODES;
342 *flags |= PFR_BITMAP_CHARCODES_VALIDATED;
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 ) )
359 mid = ( min + max ) >> 1;
360 buff = base + mid * char_len;
363 code = PFR_NEXT_USHORT( buff );
365 code = PFR_NEXT_BYTE( buff );
367 if ( char_code < code )
369 else if ( char_code > code )
382 if ( *flags & PFR_BITMAP_2BYTE_SIZE )
383 *found_size = PFR_NEXT_USHORT( buff );
385 *found_size = PFR_NEXT_BYTE( buff );
387 if ( *flags & PFR_BITMAP_3BYTE_OFFSET )
388 *found_offset = PFR_NEXT_ULONG( buff );
390 *found_offset = PFR_NEXT_USHORT( buff );
394 /* load bitmap metrics. `*padvance' must be set to the default value */
395 /* before calling this function */
398 pfr_load_bitmap_metrics( FT_Byte** pdata,
400 FT_Long scaled_advance,
408 FT_Error error = FT_Err_Ok;
412 FT_Long xpos, ypos, advance;
413 FT_UInt xsize, ysize;
417 flags = PFR_NEXT_BYTE( p );
429 b = PFR_NEXT_BYTE( p );
430 xpos = (FT_Char)b >> 4;
431 ypos = ( (FT_Char)( b << 4 ) ) >> 4;
436 xpos = PFR_NEXT_INT8( p );
437 ypos = PFR_NEXT_INT8( p );
442 xpos = PFR_NEXT_SHORT( p );
443 ypos = PFR_NEXT_SHORT( p );
448 xpos = PFR_NEXT_LONG( p );
449 ypos = PFR_NEXT_LONG( p );
467 b = PFR_NEXT_BYTE( p );
468 xsize = ( b >> 4 ) & 0xF;
474 xsize = PFR_NEXT_BYTE( p );
475 ysize = PFR_NEXT_BYTE( p );
480 xsize = PFR_NEXT_USHORT( p );
481 ysize = PFR_NEXT_USHORT( p );
492 advance = scaled_advance;
497 advance = PFR_NEXT_INT8( p ) * 256;
502 advance = PFR_NEXT_SHORT( p );
507 advance = PFR_NEXT_LONG( p );
519 *aformat = flags >> 2;
526 error = FT_THROW( Invalid_Table );
527 FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
533 pfr_load_bitmap_bits( FT_Byte* p,
539 FT_Error error = FT_Err_Ok;
540 PFR_BitWriterRec writer;
543 if ( target->rows > 0 && target->width > 0 )
545 pfr_bitwriter_init( &writer, target, decreasing );
549 case 0: /* packed bits */
550 pfr_bitwriter_decode_bytes( &writer, p, limit );
554 pfr_bitwriter_decode_rle1( &writer, p, limit );
558 pfr_bitwriter_decode_rle2( &writer, p, limit );
570 /*************************************************************************/
571 /*************************************************************************/
573 /***** BITMAP LOADING *****/
575 /*************************************************************************/
576 /*************************************************************************/
579 pfr_slot_load_bitmap( PFR_Slot glyph,
582 FT_Bool metrics_only )
585 PFR_Face face = (PFR_Face) glyph->root.face;
586 FT_Stream stream = face->root.stream;
587 PFR_PhyFont phys = &face->phy_font;
594 character = &phys->chars[glyph_index];
596 /* look up a bitmap strike corresponding to the current */
597 /* character dimensions */
602 strike = phys->strikes;
603 for ( n = 0; n < phys->num_strikes; n++ )
605 if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&
606 strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )
612 /* couldn't find it */
613 return FT_THROW( Invalid_Argument );
618 /* now look up the glyph's position within the file */
624 if ( strike->flags & PFR_BITMAP_2BYTE_CHARCODE )
626 if ( strike->flags & PFR_BITMAP_2BYTE_SIZE )
628 if ( strike->flags & PFR_BITMAP_3BYTE_OFFSET )
631 /* access data directly in the frame to speed lookups */
632 if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
633 FT_FRAME_ENTER( char_len * strike->num_bitmaps ) )
636 pfr_lookup_bitmap_data( stream->cursor,
640 character->char_code,
648 /* could not find a bitmap program string for this glyph */
649 error = FT_THROW( Invalid_Argument );
654 /* get the bitmap metrics */
656 FT_Long xpos = 0, ypos = 0, advance = 0;
657 FT_UInt xsize = 0, ysize = 0, format = 0;
661 /* compute linear advance */
662 advance = character->advance;
663 if ( phys->metrics_resolution != phys->outline_resolution )
664 advance = FT_MulDiv( advance,
665 (FT_Long)phys->outline_resolution,
666 (FT_Long)phys->metrics_resolution );
668 glyph->root.linearHoriAdvance = advance;
670 /* compute default advance, i.e., scaled advance; this can be */
671 /* overridden in the bitmap header of certain glyphs */
672 advance = FT_MulDiv( (FT_Fixed)size->root.metrics.x_ppem << 8,
674 (FT_Long)phys->metrics_resolution );
676 if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
677 FT_FRAME_ENTER( gps_size ) )
681 error = pfr_load_bitmap_metrics( &p, stream->limit,
690 * Before allocating the target bitmap, we check whether the given
691 * bitmap dimensions are valid, depending on the image format.
693 * Format 0: We have a stream of pixels (with 8 pixels per byte).
695 * (xsize * ysize + 7) / 8 <= gps_size
697 * Format 1: Run-length encoding; the high nibble holds the number of
698 * white bits, the low nibble the number of black bits. In
699 * other words, a single byte can represent at most 15
702 * xsize * ysize <= 15 * gps_size
704 * Format 2: Run-length encoding; the high byte holds the number of
705 * white bits, the low byte the number of black bits. In
706 * other words, two bytes can represent at most 255 pixels.
708 * xsize * ysize <= 255 * (gps_size + 1) / 2
713 if ( ( (FT_ULong)xsize * ysize + 7 ) / 8 > gps_size )
714 error = FT_THROW( Invalid_Table );
717 if ( (FT_ULong)xsize * ysize > 15 * gps_size )
718 error = FT_THROW( Invalid_Table );
721 if ( (FT_ULong)xsize * ysize > 255 * ( ( gps_size + 1 ) / 2 ) )
722 error = FT_THROW( Invalid_Table );
725 FT_ERROR(( "pfr_slot_load_bitmap: invalid image type\n" ));
726 error = FT_THROW( Invalid_Table );
731 if ( FT_ERR_EQ( error, Invalid_Table ) )
732 FT_ERROR(( "pfr_slot_load_bitmap: invalid bitmap dimensions\n" ));
737 * XXX: on 16bit systems we return an error for huge bitmaps
738 * that cause size truncation, because truncated
739 * size properties make bitmap glyphs broken.
741 if ( xpos > FT_INT_MAX ||
743 ysize > FT_INT_MAX ||
744 ypos > FT_INT_MAX - (FT_Long)ysize ||
745 ypos + (FT_Long)ysize < FT_INT_MIN )
747 FT_TRACE1(( "pfr_slot_load_bitmap:" ));
748 FT_TRACE1(( "huge bitmap glyph %ldx%ld over FT_GlyphSlot\n",
750 error = FT_THROW( Invalid_Pixel_Size );
755 glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
757 /* Set up glyph bitmap and metrics */
759 /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */
760 glyph->root.bitmap.width = xsize;
761 glyph->root.bitmap.rows = ysize;
762 glyph->root.bitmap.pitch = (FT_Int)( xsize + 7 ) >> 3;
763 glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
765 /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */
766 glyph->root.metrics.width = (FT_Pos)xsize << 6;
767 glyph->root.metrics.height = (FT_Pos)ysize << 6;
768 glyph->root.metrics.horiBearingX = xpos * 64;
769 glyph->root.metrics.horiBearingY = ypos * 64;
770 glyph->root.metrics.horiAdvance = FT_PIX_ROUND( ( advance >> 2 ) );
771 glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
772 glyph->root.metrics.vertBearingY = 0;
773 glyph->root.metrics.vertAdvance = size->root.metrics.height;
775 /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */
776 glyph->root.bitmap_left = (FT_Int)xpos;
777 glyph->root.bitmap_top = (FT_Int)( ypos + (FT_Long)ysize );
782 /* Allocate and read bitmap data */
784 FT_ULong len = (FT_ULong)glyph->root.bitmap.pitch * ysize;
787 error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
789 error = pfr_load_bitmap_bits(
793 FT_BOOL( face->header.color_flags &
794 PFR_FLAG_INVERT_BITMAP ),
795 &glyph->root.bitmap );