1 /***************************************************************************/
5 /* TrueType and OpenType embedded bitmap support (body). */
7 /* Copyright 1996-2000 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 <freetype/internal/ftdebug.h>
20 #include <freetype/internal/tterrors.h>
21 #include <freetype/tttags.h>
24 #ifdef FT_FLAT_COMPILE
30 #include <sfnt/ttsbit.h>
35 /*************************************************************************/
37 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
38 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
39 /* messages during execution. */
42 #define FT_COMPONENT trace_ttsbit
45 /*************************************************************************/
51 /* Blits a bitmap from an input stream into a given target. Supports */
52 /* x and y offsets as well as byte padded lines. */
55 /* target :: The target bitmap/pixmap. */
57 /* source :: The input packed bitmap data. */
59 /* line_bits :: The number of bits per line. */
61 /* byte_padded :: A flag which is true if lines are byte-padded. */
63 /* x_offset :: The horizontal offset. */
65 /* y_offset :: The vertical offset. */
68 /* IMPORTANT: The x and y offsets are relative to the top corner of */
69 /* the target bitmap (unlike the normal TrueType */
70 /* convention). A positive y offset indicates a downwards */
74 void blit_sbit( FT_Bitmap
* target
,
89 /* first of all, compute starting write position */
90 line_incr
= target
->pitch
;
91 line_buff
= target
->buffer
;
94 line_buff
-= line_incr
* ( target
->rows
- 1 );
96 line_buff
+= ( x_offset
>> 3 ) + y_offset
* line_incr
;
98 /***********************************************************************/
100 /* We use the extra-classic `accumulator' trick to extract the bits */
101 /* from the source byte stream. */
103 /* Namely, the variable `acc' is a 16-bit accumulator containing the */
104 /* last `loaded' bits from the input stream. The bits are shifted to */
105 /* the upmost position in `acc'. */
107 /***********************************************************************/
109 acc
= 0; /* clear accumulator */
110 loaded
= 0; /* no bits were loaded */
112 for ( height
= target
->rows
; height
> 0; height
-- )
114 FT_Byte
* cur
= line_buff
; /* current write cursor */
115 FT_Int count
= line_bits
; /* # of bits to extract per line */
116 FT_Byte shift
= x_offset
& 7; /* current write shift */
117 FT_Byte space
= 8 - shift
;
120 /* first of all, read individual source bytes */
130 /* ensure that there are at least 8 bits in the accumulator */
133 acc
|= (FT_UShort
)*source
++ << ( 8 - loaded
);
137 /* now write one byte */
138 val
= (FT_Byte
)( acc
>> 8 );
141 cur
[0] |= val
>> shift
;
142 cur
[1] |= val
<< space
;
148 acc
<<= 8; /* remove bits from accumulator */
152 } while ( count
>= 0 );
155 /* restore `count' to correct value */
159 /* now write remaining bits (count < 8) */
165 /* ensure that there are at least `count' bits in the accumulator */
166 if ( loaded
< count
)
168 acc
|= (FT_UShort
)*source
++ << ( 8 - loaded
);
172 /* now write remaining bits */
173 val
= ( (FT_Byte
)( acc
>> 8 ) ) & ~( 0xFF >> count
);
174 cur
[0] |= val
>> shift
;
177 cur
[1] |= val
<< space
;
183 /* now, skip to next line */
185 acc
= loaded
= 0; /* clear accumulator on byte-padded lines */
187 line_buff
+= line_incr
;
192 const FT_Frame_Field sbit_metrics_fields
[] =
195 FT_FRAME_BYTE( TT_SBit_Metrics
, height
),
196 FT_FRAME_BYTE( TT_SBit_Metrics
, width
),
198 FT_FRAME_CHAR( TT_SBit_Metrics
, horiBearingX
),
199 FT_FRAME_CHAR( TT_SBit_Metrics
, horiBearingY
),
200 FT_FRAME_BYTE( TT_SBit_Metrics
, horiAdvance
),
202 FT_FRAME_CHAR( TT_SBit_Metrics
, vertBearingX
),
203 FT_FRAME_CHAR( TT_SBit_Metrics
, vertBearingY
),
204 FT_FRAME_BYTE( TT_SBit_Metrics
, vertAdvance
),
209 /*************************************************************************/
212 /* TT_Load_SBit_Const_Metrics */
215 /* Loads the metrics for `EBLC' index tables format 2 and 5. */
218 /* range :: The target range. */
220 /* stream :: The input stream. */
223 /* FreeType error code. 0 means success. */
226 FT_Error
Load_SBit_Const_Metrics( TT_SBit_Range
* range
,
232 if ( READ_ULong( range
->image_size
) )
235 return READ_Fields( sbit_metrics_fields
, &range
->metrics
);
239 /*************************************************************************/
242 /* TT_Load_SBit_Range_Codes */
245 /* Loads the range codes for `EBLC' index tables format 4 and 5. */
248 /* range :: The target range. */
250 /* stream :: The input stream. */
252 /* load_offsets :: A flag whether to load the glyph offset table. */
255 /* FreeType error code. 0 means success. */
258 FT_Error
Load_SBit_Range_Codes( TT_SBit_Range
* range
,
260 FT_Bool load_offsets
)
263 FT_ULong count
, n
, size
;
264 FT_Memory memory
= stream
->memory
;
267 if ( READ_ULong( count
) )
270 range
->num_glyphs
= count
;
272 /* Allocate glyph offsets table if needed */
275 if ( ALLOC_ARRAY( range
->glyph_offsets
, count
, FT_ULong
) )
283 /* Allocate glyph codes table and access frame */
284 if ( ALLOC_ARRAY ( range
->glyph_codes
, count
, FT_UShort
) ||
285 ACCESS_Frame( size
) )
288 for ( n
= 0; n
< count
; n
++ )
290 range
->glyph_codes
[n
] = GET_UShort();
293 range
->glyph_offsets
[n
] = (FT_ULong
)range
->image_offset
+
304 /*************************************************************************/
307 /* TT_Load_SBit_Range */
310 /* Loads a given `EBLC' index/range table. */
313 /* range :: The target range. */
315 /* stream :: The input stream. */
318 /* FreeType error code. 0 means success. */
321 FT_Error
Load_SBit_Range( TT_SBit_Range
* range
,
325 FT_Memory memory
= stream
->memory
;
328 switch( range
->index_format
)
330 case 1: /* variable metrics with 4-byte offsets */
331 case 3: /* variable metrics with 2-byte offsets */
333 FT_ULong num_glyphs
, n
;
335 FT_Bool large
= ( range
->index_format
== 1 );
338 num_glyphs
= range
->last_glyph
- range
->first_glyph
+ 1L;
339 range
->num_glyphs
= num_glyphs
;
340 num_glyphs
++; /* XXX: BEWARE - see spec */
342 size_elem
= large
? 4 : 2;
344 if ( ALLOC_ARRAY( range
->glyph_offsets
,
345 num_glyphs
, FT_ULong
) ||
346 ACCESS_Frame( num_glyphs
* size_elem
) )
349 for ( n
= 0; n
< num_glyphs
; n
++ )
350 range
->glyph_offsets
[n
] = (FT_ULong
)( range
->image_offset
+
351 ( large
? GET_ULong()
357 case 2: /* all glyphs have identical metrics */
358 error
= Load_SBit_Const_Metrics( range
, stream
);
362 error
= Load_SBit_Range_Codes( range
, stream
, 1 );
366 error
= Load_SBit_Const_Metrics( range
, stream
) ||
367 Load_SBit_Range_Codes( range
, stream
, 0 );
371 error
= TT_Err_Invalid_File_Format
;
379 /*************************************************************************/
382 /* TT_Load_SBit_Strikes */
385 /* Loads the table of embedded bitmap sizes for this face. */
388 /* face :: The target face object. */
390 /* stream :: The input stream. */
393 /* FreeType error code. 0 means success. */
396 FT_Error
TT_Load_SBit_Strikes( TT_Face face
,
400 FT_Memory memory
= stream
->memory
;
402 FT_ULong num_strikes
;
405 const FT_Frame_Field sbit_line_metrics_fields
[] =
407 /* no FT_FRAME_START */
408 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, ascender
),
409 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, descender
),
410 FT_FRAME_BYTE( TT_SBit_Line_Metrics
, max_width
),
412 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, caret_slope_numerator
),
413 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, caret_slope_denominator
),
414 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, caret_offset
),
416 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, min_origin_SB
),
417 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, min_advance_SB
),
418 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, max_before_BL
),
419 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, min_after_BL
),
420 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, pads
[0] ),
421 FT_FRAME_CHAR( TT_SBit_Line_Metrics
, pads
[1] ),
425 const FT_Frame_Field strike_start_fields
[] =
427 /* no FT_FRAME_START */
428 FT_FRAME_ULONG( TT_SBit_Strike
, ranges_offset
),
430 FT_FRAME_ULONG( TT_SBit_Strike
, num_ranges
),
431 FT_FRAME_ULONG( TT_SBit_Strike
, color_ref
),
435 const FT_Frame_Field strike_end_fields
[] =
437 /* no FT_FRAME_START */
438 FT_FRAME_USHORT( TT_SBit_Strike
, start_glyph
),
439 FT_FRAME_USHORT( TT_SBit_Strike
, end_glyph
),
440 FT_FRAME_BYTE ( TT_SBit_Strike
, x_ppem
),
441 FT_FRAME_BYTE ( TT_SBit_Strike
, y_ppem
),
442 FT_FRAME_BYTE ( TT_SBit_Strike
, bit_depth
),
443 FT_FRAME_CHAR ( TT_SBit_Strike
, flags
),
448 face
->num_sbit_strikes
= 0;
450 /* this table is optional */
451 error
= face
->goto_table( face
, TTAG_EBLC
, stream
, 0 );
453 error
= face
->goto_table( face
, TTAG_bloc
, stream
, 0 );
460 table_base
= FILE_Pos();
461 if ( ACCESS_Frame( 8L ) )
464 version
= GET_Long();
465 num_strikes
= GET_ULong();
469 /* check version number and strike count */
470 if ( version
!= 0x00020000L
||
471 num_strikes
>= 0x10000L
)
473 FT_ERROR(( "TT_Load_SBit_Strikes: invalid table version!\n" ));
474 error
= TT_Err_Invalid_File_Format
;
479 /* allocate the strikes table */
480 if ( ALLOC_ARRAY( face
->sbit_strikes
, num_strikes
, TT_SBit_Strike
) )
483 face
->num_sbit_strikes
= num_strikes
;
485 /* now read each strike table separately */
487 TT_SBit_Strike
* strike
= face
->sbit_strikes
;
488 FT_ULong count
= num_strikes
;
491 if ( ACCESS_Frame( 48L * num_strikes
) )
496 (void)READ_Fields( strike_start_fields
, strike
);
498 (void)READ_Fields( sbit_line_metrics_fields
, &strike
->hori
);
499 (void)READ_Fields( sbit_line_metrics_fields
, &strike
->vert
);
501 (void)READ_Fields( strike_end_fields
, strike
);
510 /* allocate the index ranges for each strike table */
512 TT_SBit_Strike
* strike
= face
->sbit_strikes
;
513 FT_ULong count
= num_strikes
;
518 TT_SBit_Range
* range
;
519 FT_ULong count2
= strike
->num_ranges
;
522 if ( ALLOC_ARRAY( strike
->sbit_ranges
,
527 /* read each range */
528 if ( FILE_Seek( table_base
+ strike
->ranges_offset
) ||
529 ACCESS_Frame( strike
->num_ranges
* 8L ) )
532 range
= strike
->sbit_ranges
;
535 range
->first_glyph
= GET_UShort();
536 range
->last_glyph
= GET_UShort();
537 range
->table_offset
= table_base
+ strike
->ranges_offset
545 /* Now, read each index table */
546 count2
= strike
->num_ranges
;
547 range
= strike
->sbit_ranges
;
550 /* Read the header */
551 if ( FILE_Seek( range
->table_offset
) ||
555 range
->index_format
= GET_UShort();
556 range
->image_format
= GET_UShort();
557 range
->image_offset
= GET_ULong();
561 error
= Load_SBit_Range( range
, stream
);
579 /*************************************************************************/
582 /* TT_Free_SBit_Strikes */
585 /* Releases the embedded bitmap tables. */
588 /* face :: The target face object. */
591 void TT_Free_SBit_Strikes( TT_Face face
)
593 FT_Memory memory
= face
->root
.memory
;
594 TT_SBit_Strike
* strike
= face
->sbit_strikes
;
595 TT_SBit_Strike
* strike_limit
= strike
+ face
->num_sbit_strikes
;
600 for ( ; strike
< strike_limit
; strike
++ )
602 TT_SBit_Range
* range
= strike
->sbit_ranges
;
603 TT_SBit_Range
* range_limit
= range
+ strike
->num_ranges
;
608 for ( ; range
< range_limit
; range
++ )
610 /* release the glyph offsets and codes tables */
611 /* where appropriate */
612 FREE( range
->glyph_offsets
);
613 FREE( range
->glyph_codes
);
616 FREE( strike
->sbit_ranges
);
617 strike
->num_ranges
= 0;
619 FREE( face
->sbit_strikes
);
621 face
->num_sbit_strikes
= 0;
625 /*************************************************************************/
628 /* Find_SBit_Range */
631 /* Scans a given strike's ranges and return, for a given glyph */
632 /* index, the corresponding sbit range, and `EBDT' offset. */
635 /* glyph_index :: The glyph index. */
636 /* strike :: The source/current sbit strike. */
639 /* arange :: The sbit range containing the glyph index. */
640 /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
643 /* FreeType error code. 0 means the glyph index was found. */
646 FT_Error
Find_SBit_Range( FT_UInt glyph_index
,
647 TT_SBit_Strike
* strike
,
648 TT_SBit_Range
** arange
,
649 FT_ULong
* aglyph_offset
)
651 TT_SBit_Range
*range
, *range_limit
;
654 /* check whether the glyph index is within this strike's */
656 if ( glyph_index
< strike
->start_glyph
||
657 glyph_index
> strike
->end_glyph
)
660 /* scan all ranges in strike */
661 range
= strike
->sbit_ranges
;
662 range_limit
= range
+ strike
->num_ranges
;
666 for ( ; range
< range_limit
; range
++ )
668 if ( glyph_index
>= range
->first_glyph
&&
669 glyph_index
<= range
->last_glyph
)
671 FT_UShort delta
= glyph_index
- range
->first_glyph
;
674 switch ( range
->index_format
)
678 *aglyph_offset
= range
->glyph_offsets
[delta
];
682 *aglyph_offset
= range
->image_offset
+
683 range
->image_size
* delta
;
692 for ( n
= 0; n
< range
->num_glyphs
; n
++ )
694 if ( range
->glyph_codes
[n
] == glyph_index
)
696 if ( range
->index_format
== 4 )
697 *aglyph_offset
= range
->glyph_offsets
[n
];
699 *aglyph_offset
= range
->image_offset
+
700 n
* range
->image_size
;
712 /* return successfully! */
722 return TT_Err_Invalid_Argument
;
726 /*************************************************************************/
729 /* Find_SBit_Image */
732 /* Checks whether an embedded bitmap (an `sbit') exists for a given */
733 /* glyph, at given x and y ppems. */
736 /* face :: The target face object. */
737 /* glyph_index :: The glyph index. */
738 /* x_ppem :: The horizontal resolution in points per EM. */
739 /* y_ppem :: The vertical resolution in points per EM. */
742 /* arange :: The SBit range containing the glyph index. */
743 /* astrike :: The SBit strike containing the glyph index. */
744 /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
747 /* FreeType error code. 0 means success. Returns */
748 /* TT_Err_Invalid_Argument if no sbit exists for the requested glyph. */
751 FT_Error
Find_SBit_Image( TT_Face face
,
756 TT_SBit_Range
** arange
,
757 TT_SBit_Strike
** astrike
,
758 FT_ULong
* aglyph_offset
)
760 TT_SBit_Strike
* strike
= face
->sbit_strikes
;
761 TT_SBit_Strike
* strike_limit
= strike
+ face
->num_sbit_strikes
;
767 for ( ; strike
< strike_limit
; strike
++ )
769 if ( strike
->x_ppem
== x_ppem
&& strike
->y_ppem
== y_ppem
)
774 error
= Find_SBit_Range( glyph_index
, strike
,
775 arange
, aglyph_offset
);
786 /* no embedded bitmap for this glyph in face */
791 return TT_Err_Invalid_Argument
;
795 /*************************************************************************/
798 /* Load_SBit_Metrics */
801 /* Gets the big metrics for a given SBit. */
804 /* stream :: The input stream. */
806 /* range :: The SBit range containing the glyph. */
809 /* big_metrics :: A big SBit metrics structure for the glyph. */
812 /* FreeType error code. 0 means success. */
815 /* The stream cursor must be positioned at the glyph's offset within */
816 /* the `EBDT' table before the call. */
818 /* If the image format uses variable metrics, the stream cursor is */
819 /* positioned just after the metrics header in the `EBDT' table on */
823 FT_Error
Load_SBit_Metrics( FT_Stream stream
,
824 TT_SBit_Range
* range
,
825 TT_SBit_Metrics
* metrics
)
827 FT_Error error
= TT_Err_Ok
;
830 switch ( range
->image_format
)
835 /* variable small metrics */
837 TT_SBit_Small_Metrics smetrics
;
839 const FT_Frame_Field sbit_small_metrics_fields
[] =
842 FT_FRAME_BYTE( TT_SBit_Small_Metrics
, height
),
843 FT_FRAME_BYTE( TT_SBit_Small_Metrics
, width
),
844 FT_FRAME_CHAR( TT_SBit_Small_Metrics
, bearingX
),
845 FT_FRAME_CHAR( TT_SBit_Small_Metrics
, bearingY
),
846 FT_FRAME_BYTE( TT_SBit_Small_Metrics
, advance
),
851 /* read small metrics */
852 if ( READ_Fields( sbit_small_metrics_fields
, &smetrics
) )
855 /* convert it to a big metrics */
856 metrics
->height
= smetrics
.height
;
857 metrics
->width
= smetrics
.width
;
858 metrics
->horiBearingX
= smetrics
.bearingX
;
859 metrics
->horiBearingY
= smetrics
.bearingY
;
860 metrics
->horiAdvance
= smetrics
.advance
;
862 /* these metrics are made up at a higher level when */
864 metrics
->vertBearingX
= 0;
865 metrics
->vertBearingY
= 0;
866 metrics
->vertAdvance
= 0;
873 /* variable big metrics */
874 (void)READ_Fields( sbit_metrics_fields
, metrics
);
878 default: /* constant metrics */
879 if ( range
->index_format
== 2 || range
->index_format
== 5 )
880 *metrics
= range
->metrics
;
882 return TT_Err_Invalid_File_Format
;
890 /*************************************************************************/
896 /* Crops a bitmap to its tightest bounding box, and adjusts its */
900 /* image :: The input glyph slot. */
902 /* metrics :: The corresponding metrics structure. */
905 void Crop_Bitmap( FT_Bitmap
* map
,
906 TT_SBit_Metrics
* metrics
)
908 /***********************************************************************/
910 /* In this situation, some bounding boxes of embedded bitmaps are too */
911 /* large. We need to crop it to a reasonable size. */
917 /* | * | ------> | * | */
921 /* --------- ----- */
923 /***********************************************************************/
930 /***********************************************************************/
932 /* first of all, check the top-most lines of the bitmap, and remove */
933 /* them if they're empty. */
936 line
= (FT_Byte
*)map
->buffer
;
938 line_len
= map
->pitch
;
941 for ( count
= 0; count
< rows
; count
++ )
944 FT_Byte
* limit
= line
+ line_len
;
947 for ( ; cur
< limit
; cur
++ )
951 /* the current line was empty - skip to next one */
956 /* check that we have at least one filled line */
960 /* now, crop the empty upper lines */
963 line
= (FT_Byte
*)map
->buffer
;
965 MEM_Move( line
, line
+ count
* line_len
,
966 ( rows
- count
) * line_len
);
968 metrics
->height
-= count
;
969 metrics
->horiBearingY
-= count
;
970 metrics
->vertBearingY
-= count
;
977 /***********************************************************************/
979 /* second, crop the lower lines */
982 line
= (FT_Byte
*)map
->buffer
+ ( rows
- 1 ) * line_len
;
984 for ( count
= 0; count
< rows
; count
++ )
987 FT_Byte
* limit
= line
+ line_len
;
990 for ( ; cur
< limit
; cur
++ )
994 /* the current line was empty - skip to previous one */
1001 metrics
->height
-= count
;
1007 /***********************************************************************/
1009 /* third, get rid of the space on the left side of the glyph */
1016 line
= (FT_Byte
*)map
->buffer
;
1017 limit
= line
+ rows
* line_len
;
1019 for ( ; line
< limit
; line
+= line_len
)
1020 if ( line
[0] & 0x80 )
1023 /* shift the whole glyph one pixel to the left */
1024 line
= (FT_Byte
*)map
->buffer
;
1025 limit
= line
+ rows
* line_len
;
1027 for ( ; line
< limit
; line
+= line_len
)
1029 FT_Int n
, width
= map
->width
;
1031 FT_Byte
* cur
= line
;
1035 for ( n
= 8; n
< width
; n
+= 8 )
1041 cur
[0] = old
| ( val
>> 7 );
1049 metrics
->horiBearingX
++;
1050 metrics
->vertBearingX
++;
1053 } while ( map
->width
> 0 );
1057 /***********************************************************************/
1059 /* finally, crop the bitmap width to get rid of the space on the right */
1060 /* side of the glyph. */
1064 FT_Int right
= map
->width
- 1;
1069 line
= (FT_Byte
*)map
->buffer
+ ( right
>> 3 );
1070 limit
= line
+ rows
* line_len
;
1071 mask
= 0x80 >> ( right
& 7 );
1073 for ( ; line
< limit
; line
+= line_len
)
1074 if ( line
[0] & mask
)
1077 /* crop the whole glyph to the right */
1081 } while ( map
->width
> 0 );
1084 /* all right, the bitmap was cropped */
1091 map
->pixel_mode
= ft_pixel_mode_mono
;
1096 FT_Error
Load_SBit_Single( FT_Bitmap
* map
,
1100 FT_UShort image_format
,
1101 TT_SBit_Metrics
* metrics
,
1107 /* check that the source bitmap fits into the target pixmap */
1108 if ( x_offset
< 0 || x_offset
+ metrics
->width
> map
->width
||
1109 y_offset
< 0 || y_offset
+ metrics
->height
> map
->rows
)
1111 error
= TT_Err_Invalid_Argument
;
1117 FT_Int glyph_width
= metrics
->width
;
1118 FT_Int glyph_height
= metrics
->height
;
1120 FT_Int line_bits
= pix_bits
* glyph_width
;
1121 FT_Bool pad_bytes
= 0;
1124 /* compute size of glyph image */
1125 switch ( image_format
)
1127 case 1: /* byte-padded formats */
1135 case 1: line_length
= ( glyph_width
+ 7 ) >> 3; break;
1136 case 2: line_length
= ( glyph_width
+ 3 ) >> 2; break;
1137 case 4: line_length
= ( glyph_width
+ 1 ) >> 1; break;
1138 default: line_length
= glyph_width
;
1141 glyph_size
= glyph_height
* line_length
;
1149 line_bits
= glyph_width
* pix_bits
;
1150 glyph_size
= ( glyph_height
* line_bits
+ 7 ) >> 3;
1153 default: /* invalid format */
1154 return TT_Err_Invalid_File_Format
;
1157 /* Now read data and draw glyph into target pixmap */
1158 if ( ACCESS_Frame( glyph_size
) )
1161 /* don't forget to multiply `x_offset' by `map->pix_bits' as */
1162 /* the sbit blitter doesn't make a difference between pixmap */
1164 blit_sbit( map
, (FT_Byte
*)stream
->cursor
, line_bits
, pad_bytes
,
1165 x_offset
* pix_bits
, y_offset
);
1176 FT_Error
Load_SBit_Image( TT_SBit_Strike
* strike
,
1177 TT_SBit_Range
* range
,
1179 FT_ULong glyph_offset
,
1184 TT_SBit_Metrics
* metrics
)
1186 FT_Memory memory
= stream
->memory
;
1190 /* place stream at beginning of glyph data and read metrics */
1191 if ( FILE_Seek( ebdt_pos
+ glyph_offset
) )
1194 error
= Load_SBit_Metrics( stream
, range
, metrics
);
1198 /* this function is recursive. At the top-level call, the */
1199 /* field map.buffer is NULL. We thus begin by finding the */
1200 /* dimensions of the higher-level glyph to allocate the */
1201 /* final pixmap buffer */
1202 if ( map
->buffer
== 0 )
1207 map
->width
= metrics
->width
;
1208 map
->rows
= metrics
->height
;
1210 switch ( strike
->bit_depth
)
1213 map
->pixel_mode
= ft_pixel_mode_mono
;
1214 map
->pitch
= ( map
->width
+ 7 ) >> 3;
1218 map
->pixel_mode
= ft_pixel_mode_pal2
;
1219 map
->pitch
= ( map
->width
+ 3 ) >> 2;
1223 map
->pixel_mode
= ft_pixel_mode_pal4
;
1224 map
->pitch
= ( map
->width
+ 1 ) >> 1;
1228 map
->pixel_mode
= ft_pixel_mode_grays
;
1229 map
->pitch
= map
->width
;
1233 return TT_Err_Invalid_File_Format
;
1236 size
= map
->rows
* map
->pitch
;
1238 /* check that there is no empty image */
1240 goto Exit
; /* exit successfully! */
1242 if ( ALLOC( map
->buffer
, size
) )
1246 switch ( range
->image_format
)
1248 case 1: /* single sbit image - load it */
1253 return Load_SBit_Single( map
, x_offset
, y_offset
, strike
->bit_depth
,
1254 range
->image_format
, metrics
, stream
);
1256 case 8: /* compound format */
1257 FT_Skip_Stream( stream
, 1L );
1263 default: /* invalid image format */
1264 return TT_Err_Invalid_File_Format
;
1267 /* All right, we have a compound format. First of all, read */
1268 /* the array of elements. */
1270 TT_SBit_Component
* components
;
1271 TT_SBit_Component
* comp
;
1272 FT_UShort num_components
, count
;
1275 if ( READ_UShort( num_components
) ||
1276 ALLOC_ARRAY( components
, num_components
, TT_SBit_Component
) )
1279 count
= num_components
;
1281 if ( ACCESS_Frame( 4L * num_components
) )
1284 for ( comp
= components
; count
> 0; count
--, comp
++ )
1286 comp
->glyph_code
= GET_UShort();
1287 comp
->x_offset
= GET_Char();
1288 comp
->y_offset
= GET_Char();
1293 /* Now recursively load each element glyph */
1294 count
= num_components
;
1296 for ( ; count
> 0; count
--, comp
++ )
1298 TT_SBit_Range
* elem_range
;
1299 TT_SBit_Metrics elem_metrics
;
1300 FT_ULong elem_offset
;
1303 /* find the range for this element */
1304 error
= Find_SBit_Range( comp
->glyph_code
,
1311 /* now load the element, recursively */
1312 error
= Load_SBit_Image( strike
,
1317 x_offset
+ comp
->x_offset
,
1318 y_offset
+ comp
->y_offset
,
1334 /*************************************************************************/
1337 /* TT_Load_SBit_Image */
1340 /* Loads a given glyph sbit image from the font resource. This also */
1341 /* returns its metrics. */
1344 /* face :: The target face object. */
1346 /* x_ppem :: The horizontal resolution in points per EM. */
1348 /* y_ppem :: The vertical resolution in points per EM. */
1350 /* glyph_index :: The current glyph index. */
1352 /* load_flags :: The glyph load flags (the code checks for the flag */
1353 /* FT_LOAD_CROP_BITMAP */
1355 /* stream :: The input stream. */
1358 /* map :: The target pixmap. */
1360 /* metrics :: A big sbit metrics structure for the glyph image. */
1363 /* FreeType error code. 0 means success. Returns an error if no */
1364 /* glyph sbit exists for the index. */
1367 /* The `map.buffer' field is always freed before the glyph is loaded. */
1370 FT_Error
TT_Load_SBit_Image( TT_Face face
,
1373 FT_UInt glyph_index
,
1377 TT_SBit_Metrics
* metrics
)
1380 FT_Memory memory
= stream
->memory
;
1381 FT_ULong ebdt_pos
, glyph_offset
;
1383 TT_SBit_Strike
* strike
;
1384 TT_SBit_Range
* range
;
1387 /* Check whether there is a glyph sbit for the current index */
1388 error
= Find_SBit_Image( face
, glyph_index
, x_ppem
, y_ppem
,
1389 &range
, &strike
, &glyph_offset
);
1393 /* now, find the location of the `EBDT' table in */
1395 error
= face
->goto_table( face
, TTAG_EBDT
, stream
, 0 );
1397 error
= face
->goto_table( face
, TTAG_bdat
, stream
, 0 );
1401 ebdt_pos
= FILE_Pos();
1403 /* clear the bitmap & load the bitmap */
1404 if ( face
->root
.glyph
->flags
& ft_glyph_own_bitmap
)
1405 FREE( map
->buffer
);
1407 map
->rows
= map
->pitch
= map
->width
= 0;
1409 error
= Load_SBit_Image( strike
, range
, ebdt_pos
, glyph_offset
,
1410 map
, 0, 0, stream
, metrics
);
1414 /* the glyph slot owns this bitmap buffer */
1415 face
->root
.glyph
->flags
|= ft_glyph_own_bitmap
;
1417 /* setup vertical metrics if needed */
1418 if ( strike
->flags
& 1 )
1420 /* in case of a horizontal strike only */
1425 advance
= strike
->hori
.ascender
- strike
->hori
.descender
;
1428 /* some heuristic values */
1430 metrics
->vertBearingX
= -metrics
->width
/ 2;
1431 metrics
->vertBearingY
= advance
/ 10;
1432 metrics
->vertAdvance
= advance
* 12 / 10;
1435 /* Crop the bitmap now, unless specified otherwise */
1436 if ( load_flags
& FT_LOAD_CROP_BITMAP
)
1437 Crop_Bitmap( map
, metrics
);