1 /***************************************************************************/
5 /* TrueType and OpenType embedded bitmap support (body). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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 /***************************************************************************/
19 #include FT_INTERNAL_DEBUG_H
20 #include FT_INTERNAL_STREAM_H
21 #include FT_TRUETYPE_TAGS_H
24 * Alas, the memory-optimized sbit loader can't be used when implementing
25 * the `old internals' hack
27 #if !defined FT_CONFIG_OPTION_OLD_INTERNALS
31 #else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
34 #include FT_INTERNAL_DEBUG_H
35 #include FT_INTERNAL_STREAM_H
36 #include FT_TRUETYPE_TAGS_H
42 /*************************************************************************/
44 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
45 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
46 /* messages during execution. */
49 #define FT_COMPONENT trace_ttsbit
52 /*************************************************************************/
58 /* Blits a bitmap from an input stream into a given target. Supports */
59 /* x and y offsets as well as byte padded lines. */
62 /* target :: The target bitmap/pixmap. */
64 /* source :: The input packed bitmap data. */
66 /* line_bits :: The number of bits per line. */
68 /* byte_padded :: A flag which is true if lines are byte-padded. */
70 /* x_offset :: The horizontal offset. */
72 /* y_offset :: The vertical offset. */
75 /* IMPORTANT: The x and y offsets are relative to the top corner of */
76 /* the target bitmap (unlike the normal TrueType */
77 /* convention). A positive y offset indicates a downwards */
81 blit_sbit( FT_Bitmap
* target
,
96 /* first of all, compute starting write position */
97 line_incr
= target
->pitch
;
98 line_buff
= target
->buffer
;
101 line_buff
-= line_incr
* ( target
->rows
- 1 );
103 line_buff
+= ( x_offset
>> 3 ) + y_offset
* line_incr
;
105 /***********************************************************************/
107 /* We use the extra-classic `accumulator' trick to extract the bits */
108 /* from the source byte stream. */
110 /* Namely, the variable `acc' is a 16-bit accumulator containing the */
111 /* last `loaded' bits from the input stream. The bits are shifted to */
112 /* the upmost position in `acc'. */
114 /***********************************************************************/
116 acc
= 0; /* clear accumulator */
117 loaded
= 0; /* no bits were loaded */
119 for ( height
= target
->rows
; height
> 0; height
-- )
121 FT_Byte
* cur
= line_buff
; /* current write cursor */
122 FT_Int count
= line_bits
; /* # of bits to extract per line */
123 FT_Byte shift
= (FT_Byte
)( x_offset
& 7 ); /* current write shift */
124 FT_Byte space
= (FT_Byte
)( 8 - shift
);
127 /* first of all, read individual source bytes */
137 /* ensure that there are at least 8 bits in the accumulator */
140 acc
|= (FT_UShort
)((FT_UShort
)*source
++ << ( 8 - loaded
));
144 /* now write one byte */
145 val
= (FT_Byte
)( acc
>> 8 );
148 cur
[0] |= (FT_Byte
)( val
>> shift
);
149 cur
[1] |= (FT_Byte
)( val
<< space
);
155 acc
<<= 8; /* remove bits from accumulator */
159 } while ( count
>= 0 );
162 /* restore `count' to correct value */
166 /* now write remaining bits (count < 8) */
172 /* ensure that there are at least `count' bits in the accumulator */
173 if ( (FT_Int
)loaded
< count
)
175 acc
|= (FT_UShort
)((FT_UShort
)*source
++ << ( 8 - loaded
));
179 /* now write remaining bits */
180 val
= (FT_Byte
)( ( (FT_Byte
)( acc
>> 8 ) ) & ~( 0xFF >> count
) );
181 cur
[0] |= (FT_Byte
)( val
>> shift
);
184 cur
[1] |= (FT_Byte
)( val
<< space
);
190 /* now, skip to next line */
194 loaded
= 0; /* clear accumulator on byte-padded lines */
197 line_buff
+= line_incr
;
202 static const FT_Frame_Field sbit_metrics_fields
[] =
205 #define FT_STRUCTURE TT_SBit_MetricsRec
208 FT_FRAME_BYTE( height
),
209 FT_FRAME_BYTE( width
),
211 FT_FRAME_CHAR( horiBearingX
),
212 FT_FRAME_CHAR( horiBearingY
),
213 FT_FRAME_BYTE( horiAdvance
),
215 FT_FRAME_CHAR( vertBearingX
),
216 FT_FRAME_CHAR( vertBearingY
),
217 FT_FRAME_BYTE( vertAdvance
),
222 /*************************************************************************/
225 /* Load_SBit_Const_Metrics */
228 /* Loads the metrics for `EBLC' index tables format 2 and 5. */
231 /* range :: The target range. */
233 /* stream :: The input stream. */
236 /* FreeType error code. 0 means success. */
239 Load_SBit_Const_Metrics( TT_SBit_Range range
,
245 if ( FT_READ_ULONG( range
->image_size
) )
248 return FT_STREAM_READ_FIELDS( sbit_metrics_fields
, &range
->metrics
);
252 /*************************************************************************/
255 /* Load_SBit_Range_Codes */
258 /* Loads the range codes for `EBLC' index tables format 4 and 5. */
261 /* range :: The target range. */
263 /* stream :: The input stream. */
265 /* load_offsets :: A flag whether to load the glyph offset table. */
268 /* FreeType error code. 0 means success. */
271 Load_SBit_Range_Codes( TT_SBit_Range range
,
273 FT_Bool load_offsets
)
276 FT_ULong count
, n
, size
;
277 FT_Memory memory
= stream
->memory
;
280 if ( FT_READ_ULONG( count
) )
283 range
->num_glyphs
= count
;
285 /* Allocate glyph offsets table if needed */
288 if ( FT_NEW_ARRAY( range
->glyph_offsets
, count
) )
296 /* Allocate glyph codes table and access frame */
297 if ( FT_NEW_ARRAY ( range
->glyph_codes
, count
) ||
298 FT_FRAME_ENTER( size
) )
301 for ( n
= 0; n
< count
; n
++ )
303 range
->glyph_codes
[n
] = FT_GET_USHORT();
306 range
->glyph_offsets
[n
] = (FT_ULong
)range
->image_offset
+
317 /*************************************************************************/
320 /* Load_SBit_Range */
323 /* Loads a given `EBLC' index/range table. */
326 /* range :: The target range. */
328 /* stream :: The input stream. */
331 /* FreeType error code. 0 means success. */
334 Load_SBit_Range( TT_SBit_Range range
,
338 FT_Memory memory
= stream
->memory
;
341 switch( range
->index_format
)
343 case 1: /* variable metrics with 4-byte offsets */
344 case 3: /* variable metrics with 2-byte offsets */
346 FT_ULong num_glyphs
, n
;
348 FT_Bool large
= FT_BOOL( range
->index_format
== 1 );
352 if ( range
->last_glyph
< range
->first_glyph
)
354 error
= SFNT_Err_Invalid_File_Format
;
358 num_glyphs
= range
->last_glyph
- range
->first_glyph
+ 1L;
359 range
->num_glyphs
= num_glyphs
;
360 num_glyphs
++; /* XXX: BEWARE - see spec */
362 size_elem
= large
? 4 : 2;
364 if ( FT_NEW_ARRAY( range
->glyph_offsets
, num_glyphs
) ||
365 FT_FRAME_ENTER( num_glyphs
* size_elem
) )
368 for ( n
= 0; n
< num_glyphs
; n
++ )
369 range
->glyph_offsets
[n
] = (FT_ULong
)( range
->image_offset
+
370 ( large
? FT_GET_ULONG()
371 : FT_GET_USHORT() ) );
376 case 2: /* all glyphs have identical metrics */
377 error
= Load_SBit_Const_Metrics( range
, stream
);
381 error
= Load_SBit_Range_Codes( range
, stream
, 1 );
385 error
= Load_SBit_Const_Metrics( range
, stream
) ||
386 Load_SBit_Range_Codes( range
, stream
, 0 );
390 error
= SFNT_Err_Invalid_File_Format
;
398 /*************************************************************************/
401 /* tt_face_load_eblc */
404 /* Loads the table of embedded bitmap sizes for this face. */
407 /* face :: The target face object. */
409 /* stream :: The input stream. */
412 /* FreeType error code. 0 means success. */
414 FT_LOCAL_DEF( FT_Error
)
415 tt_face_load_eblc( TT_Face face
,
419 FT_Memory memory
= stream
->memory
;
421 FT_ULong num_strikes
;
424 static const FT_Frame_Field sbit_line_metrics_fields
[] =
427 #define FT_STRUCTURE TT_SBit_LineMetricsRec
429 /* no FT_FRAME_START */
430 FT_FRAME_CHAR( ascender
),
431 FT_FRAME_CHAR( descender
),
432 FT_FRAME_BYTE( max_width
),
434 FT_FRAME_CHAR( caret_slope_numerator
),
435 FT_FRAME_CHAR( caret_slope_denominator
),
436 FT_FRAME_CHAR( caret_offset
),
438 FT_FRAME_CHAR( min_origin_SB
),
439 FT_FRAME_CHAR( min_advance_SB
),
440 FT_FRAME_CHAR( max_before_BL
),
441 FT_FRAME_CHAR( min_after_BL
),
442 FT_FRAME_CHAR( pads
[0] ),
443 FT_FRAME_CHAR( pads
[1] ),
447 static const FT_Frame_Field strike_start_fields
[] =
450 #define FT_STRUCTURE TT_SBit_StrikeRec
452 /* no FT_FRAME_START */
453 FT_FRAME_ULONG( ranges_offset
),
455 FT_FRAME_ULONG( num_ranges
),
456 FT_FRAME_ULONG( color_ref
),
460 static const FT_Frame_Field strike_end_fields
[] =
462 /* no FT_FRAME_START */
463 FT_FRAME_USHORT( start_glyph
),
464 FT_FRAME_USHORT( end_glyph
),
465 FT_FRAME_BYTE ( x_ppem
),
466 FT_FRAME_BYTE ( y_ppem
),
467 FT_FRAME_BYTE ( bit_depth
),
468 FT_FRAME_CHAR ( flags
),
473 face
->num_sbit_strikes
= 0;
475 /* this table is optional */
476 error
= face
->goto_table( face
, TTAG_EBLC
, stream
, 0 );
478 error
= face
->goto_table( face
, TTAG_bloc
, stream
, 0 );
482 table_base
= FT_STREAM_POS();
483 if ( FT_FRAME_ENTER( 8L ) )
486 version
= FT_GET_LONG();
487 num_strikes
= FT_GET_ULONG();
491 /* check version number and strike count */
492 if ( version
!= 0x00020000L
||
493 num_strikes
>= 0x10000L
)
495 FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version!\n" ));
496 error
= SFNT_Err_Invalid_File_Format
;
501 /* allocate the strikes table */
502 if ( FT_NEW_ARRAY( face
->sbit_strikes
, num_strikes
) )
505 face
->num_sbit_strikes
= num_strikes
;
507 /* now read each strike table separately */
509 TT_SBit_Strike strike
= face
->sbit_strikes
;
510 FT_ULong count
= num_strikes
;
513 if ( FT_FRAME_ENTER( 48L * num_strikes
) )
518 if ( FT_STREAM_READ_FIELDS( strike_start_fields
, strike
) ||
519 FT_STREAM_READ_FIELDS( sbit_line_metrics_fields
, &strike
->hori
) ||
520 FT_STREAM_READ_FIELDS( sbit_line_metrics_fields
, &strike
->vert
) ||
521 FT_STREAM_READ_FIELDS( strike_end_fields
, strike
) )
531 /* allocate the index ranges for each strike table */
533 TT_SBit_Strike strike
= face
->sbit_strikes
;
534 FT_ULong count
= num_strikes
;
540 FT_ULong count2
= strike
->num_ranges
;
543 /* read each range */
544 if ( FT_STREAM_SEEK( table_base
+ strike
->ranges_offset
) ||
545 FT_FRAME_ENTER( strike
->num_ranges
* 8L ) )
548 if ( FT_NEW_ARRAY( strike
->sbit_ranges
, strike
->num_ranges
) )
551 range
= strike
->sbit_ranges
;
554 range
->first_glyph
= FT_GET_USHORT();
555 range
->last_glyph
= FT_GET_USHORT();
556 range
->table_offset
= table_base
+ strike
->ranges_offset
+
564 /* Now, read each index table */
565 count2
= strike
->num_ranges
;
566 range
= strike
->sbit_ranges
;
569 /* Read the header */
570 if ( FT_STREAM_SEEK( range
->table_offset
) ||
571 FT_FRAME_ENTER( 8L ) )
574 range
->index_format
= FT_GET_USHORT();
575 range
->image_format
= FT_GET_USHORT();
576 range
->image_offset
= FT_GET_ULONG();
580 error
= Load_SBit_Range( range
, stream
);
598 /*************************************************************************/
601 /* tt_face_free_eblc */
604 /* Releases the embedded bitmap tables. */
607 /* face :: The target face object. */
610 tt_face_free_eblc( TT_Face face
)
612 FT_Memory memory
= face
->root
.memory
;
613 TT_SBit_Strike strike
= face
->sbit_strikes
;
614 TT_SBit_Strike strike_limit
= strike
+ face
->num_sbit_strikes
;
619 for ( ; strike
< strike_limit
; strike
++ )
621 TT_SBit_Range range
= strike
->sbit_ranges
;
622 TT_SBit_Range range_limit
= range
+ strike
->num_ranges
;
627 for ( ; range
< range_limit
; range
++ )
629 /* release the glyph offsets and codes tables */
630 /* where appropriate */
631 FT_FREE( range
->glyph_offsets
);
632 FT_FREE( range
->glyph_codes
);
635 FT_FREE( strike
->sbit_ranges
);
636 strike
->num_ranges
= 0;
638 FT_FREE( face
->sbit_strikes
);
640 face
->num_sbit_strikes
= 0;
644 FT_LOCAL_DEF( FT_Error
)
645 tt_face_set_sbit_strike( TT_Face face
,
647 FT_ULong
* astrike_index
)
649 return FT_Match_Size( (FT_Face
)face
, req
, 0, astrike_index
);
653 FT_LOCAL_DEF( FT_Error
)
654 tt_face_load_strike_metrics( TT_Face face
,
655 FT_ULong strike_index
,
656 FT_Size_Metrics
* metrics
)
658 TT_SBit_Strike strike
;
661 if ( strike_index
>= face
->num_sbit_strikes
)
662 return SFNT_Err_Invalid_Argument
;
664 strike
= face
->sbit_strikes
+ strike_index
;
666 metrics
->x_ppem
= strike
->x_ppem
;
667 metrics
->y_ppem
= strike
->y_ppem
;
669 metrics
->ascender
= strike
->hori
.ascender
<< 6;
670 metrics
->descender
= strike
->hori
.descender
<< 6;
672 /* XXX: Is this correct? */
673 metrics
->max_advance
= ( strike
->hori
.min_origin_SB
+
674 strike
->hori
.max_width
+
675 strike
->hori
.min_advance_SB
) << 6;
677 metrics
->height
= metrics
->ascender
- metrics
->descender
;
683 /*************************************************************************/
686 /* find_sbit_range */
689 /* Scans a given strike's ranges and return, for a given glyph */
690 /* index, the corresponding sbit range, and `EBDT' offset. */
693 /* glyph_index :: The glyph index. */
695 /* strike :: The source/current sbit strike. */
698 /* arange :: The sbit range containing the glyph index. */
700 /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
703 /* FreeType error code. 0 means the glyph index was found. */
706 find_sbit_range( FT_UInt glyph_index
,
707 TT_SBit_Strike strike
,
708 TT_SBit_Range
*arange
,
709 FT_ULong
*aglyph_offset
)
711 TT_SBit_RangeRec
*range
, *range_limit
;
714 /* check whether the glyph index is within this strike's */
716 if ( glyph_index
< (FT_UInt
)strike
->start_glyph
||
717 glyph_index
> (FT_UInt
)strike
->end_glyph
)
720 /* scan all ranges in strike */
721 range
= strike
->sbit_ranges
;
722 range_limit
= range
+ strike
->num_ranges
;
726 for ( ; range
< range_limit
; range
++ )
728 if ( glyph_index
>= (FT_UInt
)range
->first_glyph
&&
729 glyph_index
<= (FT_UInt
)range
->last_glyph
)
731 FT_UShort delta
= (FT_UShort
)( glyph_index
- range
->first_glyph
);
734 switch ( range
->index_format
)
738 *aglyph_offset
= range
->glyph_offsets
[delta
];
742 *aglyph_offset
= range
->image_offset
+
743 range
->image_size
* delta
;
752 for ( n
= 0; n
< range
->num_glyphs
; n
++ )
754 if ( (FT_UInt
)range
->glyph_codes
[n
] == glyph_index
)
756 if ( range
->index_format
== 4 )
757 *aglyph_offset
= range
->glyph_offsets
[n
];
759 *aglyph_offset
= range
->image_offset
+
760 n
* range
->image_size
;
772 /* return successfully! */
782 return SFNT_Err_Invalid_Argument
;
786 /*************************************************************************/
789 /* tt_find_sbit_image */
792 /* Checks whether an embedded bitmap (an `sbit') exists for a given */
793 /* glyph, at a given strike. */
796 /* face :: The target face object. */
798 /* glyph_index :: The glyph index. */
800 /* strike_index :: The current strike index. */
803 /* arange :: The SBit range containing the glyph index. */
805 /* astrike :: The SBit strike containing the glyph index. */
807 /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
810 /* FreeType error code. 0 means success. Returns */
811 /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */
815 tt_find_sbit_image( TT_Face face
,
817 FT_ULong strike_index
,
818 TT_SBit_Range
*arange
,
819 TT_SBit_Strike
*astrike
,
820 FT_ULong
*aglyph_offset
)
823 TT_SBit_Strike strike
;
826 if ( !face
->sbit_strikes
||
827 ( face
->num_sbit_strikes
<= strike_index
) )
830 strike
= &face
->sbit_strikes
[strike_index
];
832 error
= find_sbit_range( glyph_index
, strike
,
833 arange
, aglyph_offset
);
842 /* no embedded bitmap for this glyph in face */
847 return SFNT_Err_Invalid_Argument
;
851 /*************************************************************************/
854 /* tt_load_sbit_metrics */
857 /* Gets the big metrics for a given SBit. */
860 /* stream :: The input stream. */
862 /* range :: The SBit range containing the glyph. */
865 /* big_metrics :: A big SBit metrics structure for the glyph. */
868 /* FreeType error code. 0 means success. */
871 /* The stream cursor must be positioned at the glyph's offset within */
872 /* the `EBDT' table before the call. */
874 /* If the image format uses variable metrics, the stream cursor is */
875 /* positioned just after the metrics header in the `EBDT' table on */
879 tt_load_sbit_metrics( FT_Stream stream
,
881 TT_SBit_Metrics metrics
)
883 FT_Error error
= SFNT_Err_Ok
;
886 switch ( range
->image_format
)
891 /* variable small metrics */
893 TT_SBit_SmallMetricsRec smetrics
;
895 static const FT_Frame_Field sbit_small_metrics_fields
[] =
898 #define FT_STRUCTURE TT_SBit_SmallMetricsRec
901 FT_FRAME_BYTE( height
),
902 FT_FRAME_BYTE( width
),
903 FT_FRAME_CHAR( bearingX
),
904 FT_FRAME_CHAR( bearingY
),
905 FT_FRAME_BYTE( advance
),
910 /* read small metrics */
911 if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields
, &smetrics
) )
914 /* convert it to a big metrics */
915 metrics
->height
= smetrics
.height
;
916 metrics
->width
= smetrics
.width
;
917 metrics
->horiBearingX
= smetrics
.bearingX
;
918 metrics
->horiBearingY
= smetrics
.bearingY
;
919 metrics
->horiAdvance
= smetrics
.advance
;
921 /* these metrics are made up at a higher level when */
923 metrics
->vertBearingX
= 0;
924 metrics
->vertBearingY
= 0;
925 metrics
->vertAdvance
= 0;
932 /* variable big metrics */
933 if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields
, metrics
) )
938 default: /* constant metrics */
939 if ( range
->index_format
== 2 || range
->index_format
== 5 )
940 *metrics
= range
->metrics
;
942 return SFNT_Err_Invalid_File_Format
;
950 /*************************************************************************/
956 /* Crops a bitmap to its tightest bounding box, and adjusts its */
960 /* map :: The bitmap. */
962 /* metrics :: The corresponding metrics structure. */
965 crop_bitmap( FT_Bitmap
* map
,
966 TT_SBit_Metrics metrics
)
968 /***********************************************************************/
970 /* In this situation, some bounding boxes of embedded bitmaps are too */
971 /* large. We need to crop it to a reasonable size. */
977 /* | * | ------> | * | */
981 /* --------- ----- */
983 /***********************************************************************/
990 /***********************************************************************/
992 /* first of all, check the top-most lines of the bitmap, and remove */
993 /* them if they're empty. */
996 line
= (FT_Byte
*)map
->buffer
;
998 line_len
= map
->pitch
;
1001 for ( count
= 0; count
< rows
; count
++ )
1003 FT_Byte
* cur
= line
;
1004 FT_Byte
* limit
= line
+ line_len
;
1007 for ( ; cur
< limit
; cur
++ )
1011 /* the current line was empty - skip to next one */
1016 /* check that we have at least one filled line */
1017 if ( count
>= rows
)
1020 /* now, crop the empty upper lines */
1023 line
= (FT_Byte
*)map
->buffer
;
1025 FT_MEM_MOVE( line
, line
+ count
* line_len
,
1026 ( rows
- count
) * line_len
);
1028 metrics
->height
= (FT_Byte
)( metrics
->height
- count
);
1029 metrics
->horiBearingY
= (FT_Char
)( metrics
->horiBearingY
- count
);
1030 metrics
->vertBearingY
= (FT_Char
)( metrics
->vertBearingY
- count
);
1037 /***********************************************************************/
1039 /* second, crop the lower lines */
1042 line
= (FT_Byte
*)map
->buffer
+ ( rows
- 1 ) * line_len
;
1044 for ( count
= 0; count
< rows
; count
++ )
1046 FT_Byte
* cur
= line
;
1047 FT_Byte
* limit
= line
+ line_len
;
1050 for ( ; cur
< limit
; cur
++ )
1054 /* the current line was empty - skip to previous one */
1061 metrics
->height
= (FT_Byte
)( metrics
->height
- count
);
1067 /***********************************************************************/
1069 /* third, get rid of the space on the left side of the glyph */
1076 line
= (FT_Byte
*)map
->buffer
;
1077 limit
= line
+ rows
* line_len
;
1079 for ( ; line
< limit
; line
+= line_len
)
1080 if ( line
[0] & 0x80 )
1083 /* shift the whole glyph one pixel to the left */
1084 line
= (FT_Byte
*)map
->buffer
;
1085 limit
= line
+ rows
* line_len
;
1087 for ( ; line
< limit
; line
+= line_len
)
1089 FT_Int n
, width
= map
->width
;
1091 FT_Byte
* cur
= line
;
1094 old
= (FT_Byte
)(cur
[0] << 1);
1095 for ( n
= 8; n
< width
; n
+= 8 )
1101 cur
[0] = (FT_Byte
)( old
| ( val
>> 7 ) );
1102 old
= (FT_Byte
)( val
<< 1 );
1109 metrics
->horiBearingX
++;
1110 metrics
->vertBearingX
++;
1113 } while ( map
->width
> 0 );
1117 /***********************************************************************/
1119 /* finally, crop the bitmap width to get rid of the space on the right */
1120 /* side of the glyph. */
1124 FT_Int right
= map
->width
- 1;
1129 line
= (FT_Byte
*)map
->buffer
+ ( right
>> 3 );
1130 limit
= line
+ rows
* line_len
;
1131 mask
= (FT_Byte
)( 0x80 >> ( right
& 7 ) );
1133 for ( ; line
< limit
; line
+= line_len
)
1134 if ( line
[0] & mask
)
1137 /* crop the whole glyph to the right */
1141 } while ( map
->width
> 0 );
1144 /* all right, the bitmap was cropped */
1151 map
->pixel_mode
= FT_PIXEL_MODE_MONO
;
1156 Load_SBit_Single( FT_Bitmap
* map
,
1160 FT_UShort image_format
,
1161 TT_SBit_Metrics metrics
,
1167 /* check that the source bitmap fits into the target pixmap */
1168 if ( x_offset
< 0 || x_offset
+ metrics
->width
> map
->width
||
1169 y_offset
< 0 || y_offset
+ metrics
->height
> map
->rows
)
1171 error
= SFNT_Err_Invalid_Argument
;
1177 FT_Int glyph_width
= metrics
->width
;
1178 FT_Int glyph_height
= metrics
->height
;
1180 FT_Int line_bits
= pix_bits
* glyph_width
;
1181 FT_Bool pad_bytes
= 0;
1184 /* compute size of glyph image */
1185 switch ( image_format
)
1187 case 1: /* byte-padded formats */
1196 line_length
= ( glyph_width
+ 7 ) >> 3;
1199 line_length
= ( glyph_width
+ 3 ) >> 2;
1202 line_length
= ( glyph_width
+ 1 ) >> 1;
1205 line_length
= glyph_width
;
1208 glyph_size
= glyph_height
* line_length
;
1216 line_bits
= glyph_width
* pix_bits
;
1217 glyph_size
= ( glyph_height
* line_bits
+ 7 ) >> 3;
1220 default: /* invalid format */
1221 return SFNT_Err_Invalid_File_Format
;
1224 /* Now read data and draw glyph into target pixmap */
1225 if ( FT_FRAME_ENTER( glyph_size
) )
1228 /* don't forget to multiply `x_offset' by `map->pix_bits' as */
1229 /* the sbit blitter doesn't make a difference between pixmap */
1231 blit_sbit( map
, (FT_Byte
*)stream
->cursor
, line_bits
, pad_bytes
,
1232 x_offset
* pix_bits
, y_offset
);
1243 Load_SBit_Image( TT_SBit_Strike strike
,
1244 TT_SBit_Range range
,
1246 FT_ULong glyph_offset
,
1251 TT_SBit_Metrics metrics
,
1254 FT_Memory memory
= stream
->memory
;
1255 FT_Bitmap
* map
= &slot
->bitmap
;
1259 /* place stream at beginning of glyph data and read metrics */
1260 if ( FT_STREAM_SEEK( ebdt_pos
+ glyph_offset
) )
1263 error
= tt_load_sbit_metrics( stream
, range
, metrics
);
1267 /* This function is recursive. At the top-level call, we */
1268 /* compute the dimensions of the higher-level glyph to */
1269 /* allocate the final pixmap buffer. */
1275 map
->width
= metrics
->width
;
1276 map
->rows
= metrics
->height
;
1278 switch ( strike
->bit_depth
)
1281 map
->pixel_mode
= FT_PIXEL_MODE_MONO
;
1282 map
->pitch
= ( map
->width
+ 7 ) >> 3;
1286 map
->pixel_mode
= FT_PIXEL_MODE_GRAY2
;
1287 map
->pitch
= ( map
->width
+ 3 ) >> 2;
1291 map
->pixel_mode
= FT_PIXEL_MODE_GRAY4
;
1292 map
->pitch
= ( map
->width
+ 1 ) >> 1;
1296 map
->pixel_mode
= FT_PIXEL_MODE_GRAY
;
1297 map
->pitch
= map
->width
;
1301 return SFNT_Err_Invalid_File_Format
;
1304 size
= map
->rows
* map
->pitch
;
1306 /* check that there is no empty image */
1308 goto Exit
; /* exit successfully! */
1310 error
= ft_glyphslot_alloc_bitmap( slot
, size
);
1315 switch ( range
->image_format
)
1317 case 1: /* single sbit image - load it */
1322 return Load_SBit_Single( map
, x_offset
, y_offset
, strike
->bit_depth
,
1323 range
->image_format
, metrics
, stream
);
1325 case 8: /* compound format */
1326 FT_Stream_Skip( stream
, 1L );
1332 default: /* invalid image format */
1333 return SFNT_Err_Invalid_File_Format
;
1336 /* All right, we have a compound format. First of all, read */
1337 /* the array of elements. */
1339 TT_SBit_Component components
;
1340 TT_SBit_Component comp
;
1341 FT_UShort num_components
, count
;
1344 if ( FT_READ_USHORT( num_components
) ||
1345 FT_NEW_ARRAY( components
, num_components
) )
1348 count
= num_components
;
1350 if ( FT_FRAME_ENTER( 4L * num_components
) )
1353 for ( comp
= components
; count
> 0; count
--, comp
++ )
1355 comp
->glyph_code
= FT_GET_USHORT();
1356 comp
->x_offset
= FT_GET_CHAR();
1357 comp
->y_offset
= FT_GET_CHAR();
1362 /* Now recursively load each element glyph */
1363 count
= num_components
;
1365 for ( ; count
> 0; count
--, comp
++ )
1367 TT_SBit_Range elem_range
;
1368 TT_SBit_MetricsRec elem_metrics
;
1369 FT_ULong elem_offset
;
1372 /* find the range for this element */
1373 error
= find_sbit_range( comp
->glyph_code
,
1380 /* now load the element, recursively */
1381 error
= Load_SBit_Image( strike
,
1386 x_offset
+ comp
->x_offset
,
1387 y_offset
+ comp
->y_offset
,
1396 FT_FREE( components
);
1404 /*************************************************************************/
1407 /* tt_face_load_sbit_image */
1410 /* Loads a given glyph sbit image from the font resource. This also */
1411 /* returns its metrics. */
1414 /* face :: The target face object. */
1416 /* strike_index :: The current strike index. */
1418 /* glyph_index :: The current glyph index. */
1420 /* load_flags :: The glyph load flags (the code checks for the flag */
1421 /* FT_LOAD_CROP_BITMAP). */
1423 /* stream :: The input stream. */
1426 /* map :: The target pixmap. */
1428 /* metrics :: A big sbit metrics structure for the glyph image. */
1431 /* FreeType error code. 0 means success. Returns an error if no */
1432 /* glyph sbit exists for the index. */
1435 /* The `map.buffer' field is always freed before the glyph is loaded. */
1437 FT_LOCAL_DEF( FT_Error
)
1438 tt_face_load_sbit_image( TT_Face face
,
1439 FT_ULong strike_index
,
1440 FT_UInt glyph_index
,
1444 TT_SBit_MetricsRec
*metrics
)
1447 FT_ULong ebdt_pos
, glyph_offset
;
1449 TT_SBit_Strike strike
;
1450 TT_SBit_Range range
;
1453 /* Check whether there is a glyph sbit for the current index */
1454 error
= tt_find_sbit_image( face
, glyph_index
, strike_index
,
1455 &range
, &strike
, &glyph_offset
);
1459 /* now, find the location of the `EBDT' table in */
1461 error
= face
->goto_table( face
, TTAG_EBDT
, stream
, 0 );
1463 error
= face
->goto_table( face
, TTAG_bdat
, stream
, 0 );
1467 ebdt_pos
= FT_STREAM_POS();
1469 error
= Load_SBit_Image( strike
, range
, ebdt_pos
, glyph_offset
,
1470 face
->root
.glyph
, 0, 0, stream
, metrics
, 0 );
1474 /* setup vertical metrics if needed */
1475 if ( strike
->flags
& 1 )
1477 /* in case of a horizontal strike only */
1481 advance
= strike
->hori
.ascender
- strike
->hori
.descender
;
1483 /* some heuristic values */
1485 metrics
->vertBearingX
= (FT_Char
)(-metrics
->width
/ 2 );
1486 metrics
->vertBearingY
= (FT_Char
)( ( advance
- metrics
->height
) / 2 );
1487 metrics
->vertAdvance
= (FT_Char
)( advance
* 12 / 10 );
1490 /* Crop the bitmap now, unless specified otherwise */
1491 if ( load_flags
& FT_LOAD_CROP_BITMAP
)
1492 crop_bitmap( map
, metrics
);
1498 #endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */