1 /***************************************************************************/
5 /* FreeType PFR bitmap loader (body). */
7 /* Copyright 2002-2015 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. */
16 /***************************************************************************/
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_INTERNAL_STREAM_H
27 #define FT_COMPONENT trace_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 left
, right
, char_len
;
286 FT_Bool two
= FT_BOOL( flags
& 1 );
291 if ( two
) char_len
+= 1;
292 if ( flags
& 2 ) char_len
+= 1;
293 if ( flags
& 4 ) char_len
+= 1;
298 while ( left
< right
)
300 FT_UInt middle
, code
;
303 middle
= ( left
+ right
) >> 1;
304 buff
= base
+ middle
* char_len
;
306 /* check that we are not outside of the table -- */
307 /* this is possible with broken fonts... */
308 if ( buff
+ char_len
> limit
)
312 code
= PFR_NEXT_USHORT( buff
);
314 code
= PFR_NEXT_BYTE( buff
);
316 if ( code
== char_code
)
319 if ( code
< char_code
)
333 *found_size
= PFR_NEXT_USHORT( buff
);
335 *found_size
= PFR_NEXT_BYTE( buff
);
338 *found_offset
= PFR_NEXT_ULONG( buff
);
340 *found_offset
= PFR_NEXT_USHORT( buff
);
344 /* load bitmap metrics. `*padvance' must be set to the default value */
345 /* before calling this function */
348 pfr_load_bitmap_metrics( FT_Byte
** pdata
,
350 FT_Long scaled_advance
,
358 FT_Error error
= FT_Err_Ok
;
363 FT_Long xpos
, ypos
, advance
;
364 FT_UInt xsize
, ysize
;
368 flags
= PFR_NEXT_BYTE( p
);
380 c
= PFR_NEXT_INT8( p
);
382 ypos
= ( (FT_Char
)( c
<< 4 ) ) >> 4;
387 xpos
= PFR_NEXT_INT8( p
);
388 ypos
= PFR_NEXT_INT8( p
);
393 xpos
= PFR_NEXT_SHORT( p
);
394 ypos
= PFR_NEXT_SHORT( p
);
399 xpos
= PFR_NEXT_LONG( p
);
400 ypos
= PFR_NEXT_LONG( p
);
418 b
= PFR_NEXT_BYTE( p
);
419 xsize
= ( b
>> 4 ) & 0xF;
425 xsize
= PFR_NEXT_BYTE( p
);
426 ysize
= PFR_NEXT_BYTE( p
);
431 xsize
= PFR_NEXT_USHORT( p
);
432 ysize
= PFR_NEXT_USHORT( p
);
443 advance
= scaled_advance
;
448 advance
= PFR_NEXT_INT8( p
) << 8;
453 advance
= PFR_NEXT_SHORT( p
);
458 advance
= PFR_NEXT_LONG( p
);
470 *aformat
= flags
>> 2;
477 error
= FT_THROW( Invalid_Table
);
478 FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
484 pfr_load_bitmap_bits( FT_Byte
* p
,
490 FT_Error error
= FT_Err_Ok
;
491 PFR_BitWriterRec writer
;
494 if ( target
->rows
> 0 && target
->width
> 0 )
496 pfr_bitwriter_init( &writer
, target
, decreasing
);
500 case 0: /* packed bits */
501 pfr_bitwriter_decode_bytes( &writer
, p
, limit
);
505 pfr_bitwriter_decode_rle1( &writer
, p
, limit
);
509 pfr_bitwriter_decode_rle2( &writer
, p
, limit
);
521 /*************************************************************************/
522 /*************************************************************************/
524 /***** BITMAP LOADING *****/
526 /*************************************************************************/
527 /*************************************************************************/
530 pfr_slot_load_bitmap( PFR_Slot glyph
,
532 FT_UInt glyph_index
)
535 PFR_Face face
= (PFR_Face
) glyph
->root
.face
;
536 FT_Stream stream
= face
->root
.stream
;
537 PFR_PhyFont phys
= &face
->phy_font
;
544 character
= &phys
->chars
[glyph_index
];
546 /* look up a bitmap strike corresponding to the current */
547 /* character dimensions */
552 strike
= phys
->strikes
;
553 for ( n
= 0; n
< phys
->num_strikes
; n
++ )
555 if ( strike
->x_ppm
== (FT_UInt
)size
->root
.metrics
.x_ppem
&&
556 strike
->y_ppm
== (FT_UInt
)size
->root
.metrics
.y_ppem
)
562 /* couldn't find it */
563 return FT_THROW( Invalid_Argument
);
568 /* now look up the glyph's position within the file */
574 if ( strike
->flags
& 1 ) char_len
+= 1;
575 if ( strike
->flags
& 2 ) char_len
+= 1;
576 if ( strike
->flags
& 4 ) char_len
+= 1;
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
) )
583 pfr_lookup_bitmap_data( stream
->cursor
,
587 character
->char_code
,
595 /* could not find a bitmap program string for this glyph */
596 error
= FT_THROW( Invalid_Argument
);
601 /* get the bitmap metrics */
603 FT_Long xpos
= 0, ypos
= 0, advance
= 0;
604 FT_UInt xsize
= 0, ysize
= 0, format
= 0;
608 /* compute linear advance */
609 advance
= character
->advance
;
610 if ( phys
->metrics_resolution
!= phys
->outline_resolution
)
611 advance
= FT_MulDiv( advance
,
612 (FT_Long
)phys
->outline_resolution
,
613 (FT_Long
)phys
->metrics_resolution
);
615 glyph
->root
.linearHoriAdvance
= advance
;
617 /* compute default advance, i.e., scaled advance; this can be */
618 /* overridden in the bitmap header of certain glyphs */
619 advance
= FT_MulDiv( (FT_Fixed
)size
->root
.metrics
.x_ppem
<< 8,
621 (FT_Long
)phys
->metrics_resolution
);
623 if ( FT_STREAM_SEEK( face
->header
.gps_section_offset
+ gps_offset
) ||
624 FT_FRAME_ENTER( gps_size
) )
628 error
= pfr_load_bitmap_metrics( &p
, stream
->limit
,
635 * Before allocating the target bitmap, we check whether the given
636 * bitmap dimensions are valid, depending on the image format.
638 * Format 0: We have a stream of pixels (with 8 pixels per byte).
640 * (xsize * ysize + 7) / 8 <= gps_size
642 * Format 1: Run-length encoding; the high nibble holds the number of
643 * white bits, the low nibble the number of black bits. In
644 * other words, a single byte can represent at most 15
647 * xsize * ysize <= 15 * gps_size
649 * Format 2: Run-length encoding; the high byte holds the number of
650 * white bits, the low byte the number of black bits. In
651 * other words, two bytes can represent at most 255 pixels.
653 * xsize * ysize <= 255 * (gps_size + 1) / 2
658 if ( ( (FT_ULong
)xsize
* ysize
+ 7 ) / 8 > gps_size
)
659 error
= FT_THROW( Invalid_Table
);
662 if ( (FT_ULong
)xsize
* ysize
> 15 * gps_size
)
663 error
= FT_THROW( Invalid_Table
);
666 if ( (FT_ULong
)xsize
* ysize
> 255 * ( ( gps_size
+ 1 ) / 2 ) )
667 error
= FT_THROW( Invalid_Table
);
670 FT_ERROR(( "pfr_slot_load_bitmap: invalid image type\n" ));
671 error
= FT_THROW( Invalid_Table
);
676 if ( FT_ERR_EQ( error
, Invalid_Table
) )
677 FT_ERROR(( "pfr_slot_load_bitmap: invalid bitmap dimensions\n" ));
682 * XXX: on 16bit systems we return an error for huge bitmaps
683 * that cause size truncation, because truncated
684 * size properties make bitmap glyphs broken.
686 if ( xpos
> FT_INT_MAX
||
688 ysize
> FT_INT_MAX
||
689 ypos
> FT_INT_MAX
- (FT_Long
)ysize
||
690 ypos
+ (FT_Long
)ysize
< FT_INT_MIN
)
692 FT_TRACE1(( "pfr_slot_load_bitmap:" ));
693 FT_TRACE1(( "huge bitmap glyph %dx%d over FT_GlyphSlot\n",
695 error
= FT_THROW( Invalid_Pixel_Size
);
700 glyph
->root
.format
= FT_GLYPH_FORMAT_BITMAP
;
702 /* Set up glyph bitmap and metrics */
704 /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */
705 glyph
->root
.bitmap
.width
= xsize
;
706 glyph
->root
.bitmap
.rows
= ysize
;
707 glyph
->root
.bitmap
.pitch
= (FT_Int
)( xsize
+ 7 ) >> 3;
708 glyph
->root
.bitmap
.pixel_mode
= FT_PIXEL_MODE_MONO
;
710 /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */
711 glyph
->root
.metrics
.width
= (FT_Pos
)xsize
<< 6;
712 glyph
->root
.metrics
.height
= (FT_Pos
)ysize
<< 6;
713 glyph
->root
.metrics
.horiBearingX
= xpos
<< 6;
714 glyph
->root
.metrics
.horiBearingY
= ypos
<< 6;
715 glyph
->root
.metrics
.horiAdvance
= FT_PIX_ROUND( ( advance
>> 2 ) );
716 glyph
->root
.metrics
.vertBearingX
= - glyph
->root
.metrics
.width
>> 1;
717 glyph
->root
.metrics
.vertBearingY
= 0;
718 glyph
->root
.metrics
.vertAdvance
= size
->root
.metrics
.height
;
720 /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */
721 glyph
->root
.bitmap_left
= (FT_Int
)xpos
;
722 glyph
->root
.bitmap_top
= (FT_Int
)( ypos
+ (FT_Long
)ysize
);
724 /* Allocate and read bitmap data */
726 FT_ULong len
= (FT_ULong
)glyph
->root
.bitmap
.pitch
* ysize
;
729 error
= ft_glyphslot_alloc_bitmap( &glyph
->root
, len
);
731 error
= pfr_load_bitmap_bits(
735 FT_BOOL(face
->header
.color_flags
& 2),
736 &glyph
->root
.bitmap
);