1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* ttsbit.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* TrueType and OpenType embedded bitmap support (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 1996-2001, 2002 by */ 8*37da2899SCharles.Forsyth /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9*37da2899SCharles.Forsyth /* */ 10*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 11*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 12*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 14*37da2899SCharles.Forsyth /* understand and accept it fully. */ 15*37da2899SCharles.Forsyth /* */ 16*37da2899SCharles.Forsyth /***************************************************************************/ 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsyth #include <ft2build.h> 20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 21*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H 22*37da2899SCharles.Forsyth #include FT_TRUETYPE_TAGS_H 23*37da2899SCharles.Forsyth #include "ttsbit.h" 24*37da2899SCharles.Forsyth 25*37da2899SCharles.Forsyth #include "sferrors.h" 26*37da2899SCharles.Forsyth 27*37da2899SCharles.Forsyth 28*37da2899SCharles.Forsyth /*************************************************************************/ 29*37da2899SCharles.Forsyth /* */ 30*37da2899SCharles.Forsyth /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 31*37da2899SCharles.Forsyth /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 32*37da2899SCharles.Forsyth /* messages during execution. */ 33*37da2899SCharles.Forsyth /* */ 34*37da2899SCharles.Forsyth #undef FT_COMPONENT 35*37da2899SCharles.Forsyth #define FT_COMPONENT trace_ttsbit 36*37da2899SCharles.Forsyth 37*37da2899SCharles.Forsyth 38*37da2899SCharles.Forsyth /*************************************************************************/ 39*37da2899SCharles.Forsyth /* */ 40*37da2899SCharles.Forsyth /* <Function> */ 41*37da2899SCharles.Forsyth /* blit_sbit */ 42*37da2899SCharles.Forsyth /* */ 43*37da2899SCharles.Forsyth /* <Description> */ 44*37da2899SCharles.Forsyth /* Blits a bitmap from an input stream into a given target. Supports */ 45*37da2899SCharles.Forsyth /* x and y offsets as well as byte padded lines. */ 46*37da2899SCharles.Forsyth /* */ 47*37da2899SCharles.Forsyth /* <Input> */ 48*37da2899SCharles.Forsyth /* target :: The target bitmap/pixmap. */ 49*37da2899SCharles.Forsyth /* */ 50*37da2899SCharles.Forsyth /* source :: The input packed bitmap data. */ 51*37da2899SCharles.Forsyth /* */ 52*37da2899SCharles.Forsyth /* line_bits :: The number of bits per line. */ 53*37da2899SCharles.Forsyth /* */ 54*37da2899SCharles.Forsyth /* byte_padded :: A flag which is true if lines are byte-padded. */ 55*37da2899SCharles.Forsyth /* */ 56*37da2899SCharles.Forsyth /* x_offset :: The horizontal offset. */ 57*37da2899SCharles.Forsyth /* */ 58*37da2899SCharles.Forsyth /* y_offset :: The vertical offset. */ 59*37da2899SCharles.Forsyth /* */ 60*37da2899SCharles.Forsyth /* <Note> */ 61*37da2899SCharles.Forsyth /* IMPORTANT: The x and y offsets are relative to the top corner of */ 62*37da2899SCharles.Forsyth /* the target bitmap (unlike the normal TrueType */ 63*37da2899SCharles.Forsyth /* convention). A positive y offset indicates a downwards */ 64*37da2899SCharles.Forsyth /* direction! */ 65*37da2899SCharles.Forsyth /* */ 66*37da2899SCharles.Forsyth static void blit_sbit(FT_Bitmap * target,FT_Byte * source,FT_Int line_bits,FT_Bool byte_padded,FT_Int x_offset,FT_Int y_offset)67*37da2899SCharles.Forsyth blit_sbit( FT_Bitmap* target, 68*37da2899SCharles.Forsyth FT_Byte* source, 69*37da2899SCharles.Forsyth FT_Int line_bits, 70*37da2899SCharles.Forsyth FT_Bool byte_padded, 71*37da2899SCharles.Forsyth FT_Int x_offset, 72*37da2899SCharles.Forsyth FT_Int y_offset ) 73*37da2899SCharles.Forsyth { 74*37da2899SCharles.Forsyth FT_Byte* line_buff; 75*37da2899SCharles.Forsyth FT_Int line_incr; 76*37da2899SCharles.Forsyth FT_Int height; 77*37da2899SCharles.Forsyth 78*37da2899SCharles.Forsyth FT_UShort acc; 79*37da2899SCharles.Forsyth FT_UInt loaded; 80*37da2899SCharles.Forsyth 81*37da2899SCharles.Forsyth 82*37da2899SCharles.Forsyth /* first of all, compute starting write position */ 83*37da2899SCharles.Forsyth line_incr = target->pitch; 84*37da2899SCharles.Forsyth line_buff = target->buffer; 85*37da2899SCharles.Forsyth 86*37da2899SCharles.Forsyth if ( line_incr < 0 ) 87*37da2899SCharles.Forsyth line_buff -= line_incr * ( target->rows - 1 ); 88*37da2899SCharles.Forsyth 89*37da2899SCharles.Forsyth line_buff += ( x_offset >> 3 ) + y_offset * line_incr; 90*37da2899SCharles.Forsyth 91*37da2899SCharles.Forsyth /***********************************************************************/ 92*37da2899SCharles.Forsyth /* */ 93*37da2899SCharles.Forsyth /* We use the extra-classic `accumulator' trick to extract the bits */ 94*37da2899SCharles.Forsyth /* from the source byte stream. */ 95*37da2899SCharles.Forsyth /* */ 96*37da2899SCharles.Forsyth /* Namely, the variable `acc' is a 16-bit accumulator containing the */ 97*37da2899SCharles.Forsyth /* last `loaded' bits from the input stream. The bits are shifted to */ 98*37da2899SCharles.Forsyth /* the upmost position in `acc'. */ 99*37da2899SCharles.Forsyth /* */ 100*37da2899SCharles.Forsyth /***********************************************************************/ 101*37da2899SCharles.Forsyth 102*37da2899SCharles.Forsyth acc = 0; /* clear accumulator */ 103*37da2899SCharles.Forsyth loaded = 0; /* no bits were loaded */ 104*37da2899SCharles.Forsyth 105*37da2899SCharles.Forsyth for ( height = target->rows; height > 0; height-- ) 106*37da2899SCharles.Forsyth { 107*37da2899SCharles.Forsyth FT_Byte* cur = line_buff; /* current write cursor */ 108*37da2899SCharles.Forsyth FT_Int count = line_bits; /* # of bits to extract per line */ 109*37da2899SCharles.Forsyth FT_Byte shift = (FT_Byte)( x_offset & 7 ); /* current write shift */ 110*37da2899SCharles.Forsyth FT_Byte space = (FT_Byte)( 8 - shift ); 111*37da2899SCharles.Forsyth 112*37da2899SCharles.Forsyth 113*37da2899SCharles.Forsyth /* first of all, read individual source bytes */ 114*37da2899SCharles.Forsyth if ( count >= 8 ) 115*37da2899SCharles.Forsyth { 116*37da2899SCharles.Forsyth count -= 8; 117*37da2899SCharles.Forsyth { 118*37da2899SCharles.Forsyth do 119*37da2899SCharles.Forsyth { 120*37da2899SCharles.Forsyth FT_Byte val; 121*37da2899SCharles.Forsyth 122*37da2899SCharles.Forsyth 123*37da2899SCharles.Forsyth /* ensure that there are at least 8 bits in the accumulator */ 124*37da2899SCharles.Forsyth if ( loaded < 8 ) 125*37da2899SCharles.Forsyth { 126*37da2899SCharles.Forsyth acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded )); 127*37da2899SCharles.Forsyth loaded += 8; 128*37da2899SCharles.Forsyth } 129*37da2899SCharles.Forsyth 130*37da2899SCharles.Forsyth /* now write one byte */ 131*37da2899SCharles.Forsyth val = (FT_Byte)( acc >> 8 ); 132*37da2899SCharles.Forsyth if ( shift ) 133*37da2899SCharles.Forsyth { 134*37da2899SCharles.Forsyth cur[0] |= (FT_Byte)( val >> shift ); 135*37da2899SCharles.Forsyth cur[1] |= (FT_Byte)( val << space ); 136*37da2899SCharles.Forsyth } 137*37da2899SCharles.Forsyth else 138*37da2899SCharles.Forsyth cur[0] |= val; 139*37da2899SCharles.Forsyth 140*37da2899SCharles.Forsyth cur++; 141*37da2899SCharles.Forsyth acc <<= 8; /* remove bits from accumulator */ 142*37da2899SCharles.Forsyth loaded -= 8; 143*37da2899SCharles.Forsyth count -= 8; 144*37da2899SCharles.Forsyth 145*37da2899SCharles.Forsyth } while ( count >= 0 ); 146*37da2899SCharles.Forsyth } 147*37da2899SCharles.Forsyth 148*37da2899SCharles.Forsyth /* restore `count' to correct value */ 149*37da2899SCharles.Forsyth count += 8; 150*37da2899SCharles.Forsyth } 151*37da2899SCharles.Forsyth 152*37da2899SCharles.Forsyth /* now write remaining bits (count < 8) */ 153*37da2899SCharles.Forsyth if ( count > 0 ) 154*37da2899SCharles.Forsyth { 155*37da2899SCharles.Forsyth FT_Byte val; 156*37da2899SCharles.Forsyth 157*37da2899SCharles.Forsyth 158*37da2899SCharles.Forsyth /* ensure that there are at least `count' bits in the accumulator */ 159*37da2899SCharles.Forsyth if ( (FT_Int)loaded < count ) 160*37da2899SCharles.Forsyth { 161*37da2899SCharles.Forsyth acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded )); 162*37da2899SCharles.Forsyth loaded += 8; 163*37da2899SCharles.Forsyth } 164*37da2899SCharles.Forsyth 165*37da2899SCharles.Forsyth /* now write remaining bits */ 166*37da2899SCharles.Forsyth val = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) ); 167*37da2899SCharles.Forsyth cur[0] |= (FT_Byte)( val >> shift ); 168*37da2899SCharles.Forsyth 169*37da2899SCharles.Forsyth if ( count > space ) 170*37da2899SCharles.Forsyth cur[1] |= (FT_Byte)( val << space ); 171*37da2899SCharles.Forsyth 172*37da2899SCharles.Forsyth acc <<= count; 173*37da2899SCharles.Forsyth loaded -= count; 174*37da2899SCharles.Forsyth } 175*37da2899SCharles.Forsyth 176*37da2899SCharles.Forsyth /* now, skip to next line */ 177*37da2899SCharles.Forsyth if ( byte_padded ) 178*37da2899SCharles.Forsyth { 179*37da2899SCharles.Forsyth acc = 0; 180*37da2899SCharles.Forsyth loaded = 0; /* clear accumulator on byte-padded lines */ 181*37da2899SCharles.Forsyth } 182*37da2899SCharles.Forsyth 183*37da2899SCharles.Forsyth line_buff += line_incr; 184*37da2899SCharles.Forsyth } 185*37da2899SCharles.Forsyth } 186*37da2899SCharles.Forsyth 187*37da2899SCharles.Forsyth 188*37da2899SCharles.Forsyth const FT_Frame_Field sbit_metrics_fields[] = 189*37da2899SCharles.Forsyth { 190*37da2899SCharles.Forsyth #undef FT_STRUCTURE 191*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_SBit_MetricsRec 192*37da2899SCharles.Forsyth 193*37da2899SCharles.Forsyth FT_FRAME_START( 8 ), 194*37da2899SCharles.Forsyth FT_FRAME_BYTE( height ), 195*37da2899SCharles.Forsyth FT_FRAME_BYTE( width ), 196*37da2899SCharles.Forsyth 197*37da2899SCharles.Forsyth FT_FRAME_CHAR( horiBearingX ), 198*37da2899SCharles.Forsyth FT_FRAME_CHAR( horiBearingY ), 199*37da2899SCharles.Forsyth FT_FRAME_BYTE( horiAdvance ), 200*37da2899SCharles.Forsyth 201*37da2899SCharles.Forsyth FT_FRAME_CHAR( vertBearingX ), 202*37da2899SCharles.Forsyth FT_FRAME_CHAR( vertBearingY ), 203*37da2899SCharles.Forsyth FT_FRAME_BYTE( vertAdvance ), 204*37da2899SCharles.Forsyth FT_FRAME_END 205*37da2899SCharles.Forsyth }; 206*37da2899SCharles.Forsyth 207*37da2899SCharles.Forsyth 208*37da2899SCharles.Forsyth /*************************************************************************/ 209*37da2899SCharles.Forsyth /* */ 210*37da2899SCharles.Forsyth /* <Function> */ 211*37da2899SCharles.Forsyth /* TT_Load_SBit_Const_Metrics */ 212*37da2899SCharles.Forsyth /* */ 213*37da2899SCharles.Forsyth /* <Description> */ 214*37da2899SCharles.Forsyth /* Loads the metrics for `EBLC' index tables format 2 and 5. */ 215*37da2899SCharles.Forsyth /* */ 216*37da2899SCharles.Forsyth /* <Input> */ 217*37da2899SCharles.Forsyth /* range :: The target range. */ 218*37da2899SCharles.Forsyth /* */ 219*37da2899SCharles.Forsyth /* stream :: The input stream. */ 220*37da2899SCharles.Forsyth /* */ 221*37da2899SCharles.Forsyth /* <Return> */ 222*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 223*37da2899SCharles.Forsyth /* */ 224*37da2899SCharles.Forsyth static FT_Error Load_SBit_Const_Metrics(TT_SBit_Range range,FT_Stream stream)225*37da2899SCharles.Forsyth Load_SBit_Const_Metrics( TT_SBit_Range range, 226*37da2899SCharles.Forsyth FT_Stream stream ) 227*37da2899SCharles.Forsyth { 228*37da2899SCharles.Forsyth FT_Error error; 229*37da2899SCharles.Forsyth 230*37da2899SCharles.Forsyth 231*37da2899SCharles.Forsyth if ( FT_READ_ULONG( range->image_size ) ) 232*37da2899SCharles.Forsyth return error; 233*37da2899SCharles.Forsyth 234*37da2899SCharles.Forsyth return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics ); 235*37da2899SCharles.Forsyth } 236*37da2899SCharles.Forsyth 237*37da2899SCharles.Forsyth 238*37da2899SCharles.Forsyth /*************************************************************************/ 239*37da2899SCharles.Forsyth /* */ 240*37da2899SCharles.Forsyth /* <Function> */ 241*37da2899SCharles.Forsyth /* TT_Load_SBit_Range_Codes */ 242*37da2899SCharles.Forsyth /* */ 243*37da2899SCharles.Forsyth /* <Description> */ 244*37da2899SCharles.Forsyth /* Loads the range codes for `EBLC' index tables format 4 and 5. */ 245*37da2899SCharles.Forsyth /* */ 246*37da2899SCharles.Forsyth /* <Input> */ 247*37da2899SCharles.Forsyth /* range :: The target range. */ 248*37da2899SCharles.Forsyth /* */ 249*37da2899SCharles.Forsyth /* stream :: The input stream. */ 250*37da2899SCharles.Forsyth /* */ 251*37da2899SCharles.Forsyth /* load_offsets :: A flag whether to load the glyph offset table. */ 252*37da2899SCharles.Forsyth /* */ 253*37da2899SCharles.Forsyth /* <Return> */ 254*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 255*37da2899SCharles.Forsyth /* */ 256*37da2899SCharles.Forsyth static FT_Error Load_SBit_Range_Codes(TT_SBit_Range range,FT_Stream stream,FT_Bool load_offsets)257*37da2899SCharles.Forsyth Load_SBit_Range_Codes( TT_SBit_Range range, 258*37da2899SCharles.Forsyth FT_Stream stream, 259*37da2899SCharles.Forsyth FT_Bool load_offsets ) 260*37da2899SCharles.Forsyth { 261*37da2899SCharles.Forsyth FT_Error error; 262*37da2899SCharles.Forsyth FT_ULong count, n, size; 263*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 264*37da2899SCharles.Forsyth 265*37da2899SCharles.Forsyth 266*37da2899SCharles.Forsyth if ( FT_READ_ULONG( count ) ) 267*37da2899SCharles.Forsyth goto Exit; 268*37da2899SCharles.Forsyth 269*37da2899SCharles.Forsyth range->num_glyphs = count; 270*37da2899SCharles.Forsyth 271*37da2899SCharles.Forsyth /* Allocate glyph offsets table if needed */ 272*37da2899SCharles.Forsyth if ( load_offsets ) 273*37da2899SCharles.Forsyth { 274*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( range->glyph_offsets, count ) ) 275*37da2899SCharles.Forsyth goto Exit; 276*37da2899SCharles.Forsyth 277*37da2899SCharles.Forsyth size = count * 4L; 278*37da2899SCharles.Forsyth } 279*37da2899SCharles.Forsyth else 280*37da2899SCharles.Forsyth size = count * 2L; 281*37da2899SCharles.Forsyth 282*37da2899SCharles.Forsyth /* Allocate glyph codes table and access frame */ 283*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY ( range->glyph_codes, count ) || 284*37da2899SCharles.Forsyth FT_FRAME_ENTER( size ) ) 285*37da2899SCharles.Forsyth goto Exit; 286*37da2899SCharles.Forsyth 287*37da2899SCharles.Forsyth for ( n = 0; n < count; n++ ) 288*37da2899SCharles.Forsyth { 289*37da2899SCharles.Forsyth range->glyph_codes[n] = FT_GET_USHORT(); 290*37da2899SCharles.Forsyth 291*37da2899SCharles.Forsyth if ( load_offsets ) 292*37da2899SCharles.Forsyth range->glyph_offsets[n] = (FT_ULong)range->image_offset + 293*37da2899SCharles.Forsyth FT_GET_USHORT(); 294*37da2899SCharles.Forsyth } 295*37da2899SCharles.Forsyth 296*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 297*37da2899SCharles.Forsyth 298*37da2899SCharles.Forsyth Exit: 299*37da2899SCharles.Forsyth return error; 300*37da2899SCharles.Forsyth } 301*37da2899SCharles.Forsyth 302*37da2899SCharles.Forsyth 303*37da2899SCharles.Forsyth /*************************************************************************/ 304*37da2899SCharles.Forsyth /* */ 305*37da2899SCharles.Forsyth /* <Function> */ 306*37da2899SCharles.Forsyth /* TT_Load_SBit_Range */ 307*37da2899SCharles.Forsyth /* */ 308*37da2899SCharles.Forsyth /* <Description> */ 309*37da2899SCharles.Forsyth /* Loads a given `EBLC' index/range table. */ 310*37da2899SCharles.Forsyth /* */ 311*37da2899SCharles.Forsyth /* <Input> */ 312*37da2899SCharles.Forsyth /* range :: The target range. */ 313*37da2899SCharles.Forsyth /* */ 314*37da2899SCharles.Forsyth /* stream :: The input stream. */ 315*37da2899SCharles.Forsyth /* */ 316*37da2899SCharles.Forsyth /* <Return> */ 317*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 318*37da2899SCharles.Forsyth /* */ 319*37da2899SCharles.Forsyth static FT_Error Load_SBit_Range(TT_SBit_Range range,FT_Stream stream)320*37da2899SCharles.Forsyth Load_SBit_Range( TT_SBit_Range range, 321*37da2899SCharles.Forsyth FT_Stream stream ) 322*37da2899SCharles.Forsyth { 323*37da2899SCharles.Forsyth FT_Error error; 324*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 325*37da2899SCharles.Forsyth 326*37da2899SCharles.Forsyth 327*37da2899SCharles.Forsyth switch( range->index_format ) 328*37da2899SCharles.Forsyth { 329*37da2899SCharles.Forsyth case 1: /* variable metrics with 4-byte offsets */ 330*37da2899SCharles.Forsyth case 3: /* variable metrics with 2-byte offsets */ 331*37da2899SCharles.Forsyth { 332*37da2899SCharles.Forsyth FT_ULong num_glyphs, n; 333*37da2899SCharles.Forsyth FT_Int size_elem; 334*37da2899SCharles.Forsyth FT_Bool large = FT_BOOL( range->index_format == 1 ); 335*37da2899SCharles.Forsyth 336*37da2899SCharles.Forsyth 337*37da2899SCharles.Forsyth num_glyphs = range->last_glyph - range->first_glyph + 1L; 338*37da2899SCharles.Forsyth range->num_glyphs = num_glyphs; 339*37da2899SCharles.Forsyth num_glyphs++; /* XXX: BEWARE - see spec */ 340*37da2899SCharles.Forsyth 341*37da2899SCharles.Forsyth size_elem = large ? 4 : 2; 342*37da2899SCharles.Forsyth 343*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) || 344*37da2899SCharles.Forsyth FT_FRAME_ENTER( num_glyphs * size_elem ) ) 345*37da2899SCharles.Forsyth goto Exit; 346*37da2899SCharles.Forsyth 347*37da2899SCharles.Forsyth for ( n = 0; n < num_glyphs; n++ ) 348*37da2899SCharles.Forsyth range->glyph_offsets[n] = (FT_ULong)( range->image_offset + 349*37da2899SCharles.Forsyth ( large ? FT_GET_ULONG() 350*37da2899SCharles.Forsyth : FT_GET_USHORT() ) ); 351*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 352*37da2899SCharles.Forsyth } 353*37da2899SCharles.Forsyth break; 354*37da2899SCharles.Forsyth 355*37da2899SCharles.Forsyth case 2: /* all glyphs have identical metrics */ 356*37da2899SCharles.Forsyth error = Load_SBit_Const_Metrics( range, stream ); 357*37da2899SCharles.Forsyth break; 358*37da2899SCharles.Forsyth 359*37da2899SCharles.Forsyth case 4: 360*37da2899SCharles.Forsyth error = Load_SBit_Range_Codes( range, stream, 1 ); 361*37da2899SCharles.Forsyth break; 362*37da2899SCharles.Forsyth 363*37da2899SCharles.Forsyth case 5: 364*37da2899SCharles.Forsyth error = Load_SBit_Const_Metrics( range, stream ) || 365*37da2899SCharles.Forsyth Load_SBit_Range_Codes( range, stream, 0 ); 366*37da2899SCharles.Forsyth break; 367*37da2899SCharles.Forsyth 368*37da2899SCharles.Forsyth default: 369*37da2899SCharles.Forsyth error = SFNT_Err_Invalid_File_Format; 370*37da2899SCharles.Forsyth } 371*37da2899SCharles.Forsyth 372*37da2899SCharles.Forsyth Exit: 373*37da2899SCharles.Forsyth return error; 374*37da2899SCharles.Forsyth } 375*37da2899SCharles.Forsyth 376*37da2899SCharles.Forsyth 377*37da2899SCharles.Forsyth /*************************************************************************/ 378*37da2899SCharles.Forsyth /* */ 379*37da2899SCharles.Forsyth /* <Function> */ 380*37da2899SCharles.Forsyth /* tt_face_load_sbit_strikes */ 381*37da2899SCharles.Forsyth /* */ 382*37da2899SCharles.Forsyth /* <Description> */ 383*37da2899SCharles.Forsyth /* Loads the table of embedded bitmap sizes for this face. */ 384*37da2899SCharles.Forsyth /* */ 385*37da2899SCharles.Forsyth /* <Input> */ 386*37da2899SCharles.Forsyth /* face :: The target face object. */ 387*37da2899SCharles.Forsyth /* */ 388*37da2899SCharles.Forsyth /* stream :: The input stream. */ 389*37da2899SCharles.Forsyth /* */ 390*37da2899SCharles.Forsyth /* <Return> */ 391*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 392*37da2899SCharles.Forsyth /* */ 393*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_sbit_strikes(TT_Face face,FT_Stream stream)394*37da2899SCharles.Forsyth tt_face_load_sbit_strikes( TT_Face face, 395*37da2899SCharles.Forsyth FT_Stream stream ) 396*37da2899SCharles.Forsyth { 397*37da2899SCharles.Forsyth FT_Error error = 0; 398*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 399*37da2899SCharles.Forsyth FT_Fixed version; 400*37da2899SCharles.Forsyth FT_ULong num_strikes; 401*37da2899SCharles.Forsyth FT_ULong table_base; 402*37da2899SCharles.Forsyth 403*37da2899SCharles.Forsyth const FT_Frame_Field sbit_line_metrics_fields[] = 404*37da2899SCharles.Forsyth { 405*37da2899SCharles.Forsyth #undef FT_STRUCTURE 406*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_SBit_LineMetricsRec 407*37da2899SCharles.Forsyth 408*37da2899SCharles.Forsyth /* no FT_FRAME_START */ 409*37da2899SCharles.Forsyth FT_FRAME_CHAR( ascender ), 410*37da2899SCharles.Forsyth FT_FRAME_CHAR( descender ), 411*37da2899SCharles.Forsyth FT_FRAME_BYTE( max_width ), 412*37da2899SCharles.Forsyth 413*37da2899SCharles.Forsyth FT_FRAME_CHAR( caret_slope_numerator ), 414*37da2899SCharles.Forsyth FT_FRAME_CHAR( caret_slope_denominator ), 415*37da2899SCharles.Forsyth FT_FRAME_CHAR( caret_offset ), 416*37da2899SCharles.Forsyth 417*37da2899SCharles.Forsyth FT_FRAME_CHAR( min_origin_SB ), 418*37da2899SCharles.Forsyth FT_FRAME_CHAR( min_advance_SB ), 419*37da2899SCharles.Forsyth FT_FRAME_CHAR( max_before_BL ), 420*37da2899SCharles.Forsyth FT_FRAME_CHAR( min_after_BL ), 421*37da2899SCharles.Forsyth FT_FRAME_CHAR( pads[0] ), 422*37da2899SCharles.Forsyth FT_FRAME_CHAR( pads[1] ), 423*37da2899SCharles.Forsyth FT_FRAME_END 424*37da2899SCharles.Forsyth }; 425*37da2899SCharles.Forsyth 426*37da2899SCharles.Forsyth const FT_Frame_Field strike_start_fields[] = 427*37da2899SCharles.Forsyth { 428*37da2899SCharles.Forsyth #undef FT_STRUCTURE 429*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_SBit_StrikeRec 430*37da2899SCharles.Forsyth 431*37da2899SCharles.Forsyth /* no FT_FRAME_START */ 432*37da2899SCharles.Forsyth FT_FRAME_ULONG( ranges_offset ), 433*37da2899SCharles.Forsyth FT_FRAME_SKIP_LONG, 434*37da2899SCharles.Forsyth FT_FRAME_ULONG( num_ranges ), 435*37da2899SCharles.Forsyth FT_FRAME_ULONG( color_ref ), 436*37da2899SCharles.Forsyth FT_FRAME_END 437*37da2899SCharles.Forsyth }; 438*37da2899SCharles.Forsyth 439*37da2899SCharles.Forsyth const FT_Frame_Field strike_end_fields[] = 440*37da2899SCharles.Forsyth { 441*37da2899SCharles.Forsyth /* no FT_FRAME_START */ 442*37da2899SCharles.Forsyth FT_FRAME_USHORT( start_glyph ), 443*37da2899SCharles.Forsyth FT_FRAME_USHORT( end_glyph ), 444*37da2899SCharles.Forsyth FT_FRAME_BYTE ( x_ppem ), 445*37da2899SCharles.Forsyth FT_FRAME_BYTE ( y_ppem ), 446*37da2899SCharles.Forsyth FT_FRAME_BYTE ( bit_depth ), 447*37da2899SCharles.Forsyth FT_FRAME_CHAR ( flags ), 448*37da2899SCharles.Forsyth FT_FRAME_END 449*37da2899SCharles.Forsyth }; 450*37da2899SCharles.Forsyth 451*37da2899SCharles.Forsyth 452*37da2899SCharles.Forsyth face->num_sbit_strikes = 0; 453*37da2899SCharles.Forsyth 454*37da2899SCharles.Forsyth /* this table is optional */ 455*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_EBLC, stream, 0 ); 456*37da2899SCharles.Forsyth if ( error ) 457*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_bloc, stream, 0 ); 458*37da2899SCharles.Forsyth if ( error ) 459*37da2899SCharles.Forsyth goto Exit; 460*37da2899SCharles.Forsyth 461*37da2899SCharles.Forsyth table_base = FT_STREAM_POS(); 462*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 8L ) ) 463*37da2899SCharles.Forsyth goto Exit; 464*37da2899SCharles.Forsyth 465*37da2899SCharles.Forsyth version = FT_GET_LONG(); 466*37da2899SCharles.Forsyth num_strikes = FT_GET_ULONG(); 467*37da2899SCharles.Forsyth 468*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 469*37da2899SCharles.Forsyth 470*37da2899SCharles.Forsyth /* check version number and strike count */ 471*37da2899SCharles.Forsyth if ( version != 0x00020000L || 472*37da2899SCharles.Forsyth num_strikes >= 0x10000L ) 473*37da2899SCharles.Forsyth { 474*37da2899SCharles.Forsyth FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version!\n" )); 475*37da2899SCharles.Forsyth error = SFNT_Err_Invalid_File_Format; 476*37da2899SCharles.Forsyth 477*37da2899SCharles.Forsyth goto Exit; 478*37da2899SCharles.Forsyth } 479*37da2899SCharles.Forsyth 480*37da2899SCharles.Forsyth /* allocate the strikes table */ 481*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) ) 482*37da2899SCharles.Forsyth goto Exit; 483*37da2899SCharles.Forsyth 484*37da2899SCharles.Forsyth face->num_sbit_strikes = num_strikes; 485*37da2899SCharles.Forsyth 486*37da2899SCharles.Forsyth /* now read each strike table separately */ 487*37da2899SCharles.Forsyth { 488*37da2899SCharles.Forsyth TT_SBit_Strike strike = face->sbit_strikes; 489*37da2899SCharles.Forsyth FT_ULong count = num_strikes; 490*37da2899SCharles.Forsyth 491*37da2899SCharles.Forsyth 492*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 48L * num_strikes ) ) 493*37da2899SCharles.Forsyth goto Exit; 494*37da2899SCharles.Forsyth 495*37da2899SCharles.Forsyth while ( count > 0 ) 496*37da2899SCharles.Forsyth { 497*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike ) || 498*37da2899SCharles.Forsyth FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) || 499*37da2899SCharles.Forsyth FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) || 500*37da2899SCharles.Forsyth FT_STREAM_READ_FIELDS( strike_end_fields, strike ) ) 501*37da2899SCharles.Forsyth break; 502*37da2899SCharles.Forsyth 503*37da2899SCharles.Forsyth count--; 504*37da2899SCharles.Forsyth strike++; 505*37da2899SCharles.Forsyth } 506*37da2899SCharles.Forsyth 507*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 508*37da2899SCharles.Forsyth } 509*37da2899SCharles.Forsyth 510*37da2899SCharles.Forsyth /* allocate the index ranges for each strike table */ 511*37da2899SCharles.Forsyth { 512*37da2899SCharles.Forsyth TT_SBit_Strike strike = face->sbit_strikes; 513*37da2899SCharles.Forsyth FT_ULong count = num_strikes; 514*37da2899SCharles.Forsyth 515*37da2899SCharles.Forsyth 516*37da2899SCharles.Forsyth while ( count > 0 ) 517*37da2899SCharles.Forsyth { 518*37da2899SCharles.Forsyth TT_SBit_Range range; 519*37da2899SCharles.Forsyth FT_ULong count2 = strike->num_ranges; 520*37da2899SCharles.Forsyth 521*37da2899SCharles.Forsyth 522*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) ) 523*37da2899SCharles.Forsyth goto Exit; 524*37da2899SCharles.Forsyth 525*37da2899SCharles.Forsyth /* read each range */ 526*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) || 527*37da2899SCharles.Forsyth FT_FRAME_ENTER( strike->num_ranges * 8L ) ) 528*37da2899SCharles.Forsyth goto Exit; 529*37da2899SCharles.Forsyth 530*37da2899SCharles.Forsyth range = strike->sbit_ranges; 531*37da2899SCharles.Forsyth while ( count2 > 0 ) 532*37da2899SCharles.Forsyth { 533*37da2899SCharles.Forsyth range->first_glyph = FT_GET_USHORT(); 534*37da2899SCharles.Forsyth range->last_glyph = FT_GET_USHORT(); 535*37da2899SCharles.Forsyth range->table_offset = table_base + strike->ranges_offset + 536*37da2899SCharles.Forsyth FT_GET_ULONG(); 537*37da2899SCharles.Forsyth count2--; 538*37da2899SCharles.Forsyth range++; 539*37da2899SCharles.Forsyth } 540*37da2899SCharles.Forsyth 541*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 542*37da2899SCharles.Forsyth 543*37da2899SCharles.Forsyth /* Now, read each index table */ 544*37da2899SCharles.Forsyth count2 = strike->num_ranges; 545*37da2899SCharles.Forsyth range = strike->sbit_ranges; 546*37da2899SCharles.Forsyth while ( count2 > 0 ) 547*37da2899SCharles.Forsyth { 548*37da2899SCharles.Forsyth /* Read the header */ 549*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( range->table_offset ) || 550*37da2899SCharles.Forsyth FT_FRAME_ENTER( 8L ) ) 551*37da2899SCharles.Forsyth goto Exit; 552*37da2899SCharles.Forsyth 553*37da2899SCharles.Forsyth range->index_format = FT_GET_USHORT(); 554*37da2899SCharles.Forsyth range->image_format = FT_GET_USHORT(); 555*37da2899SCharles.Forsyth range->image_offset = FT_GET_ULONG(); 556*37da2899SCharles.Forsyth 557*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 558*37da2899SCharles.Forsyth 559*37da2899SCharles.Forsyth error = Load_SBit_Range( range, stream ); 560*37da2899SCharles.Forsyth if ( error ) 561*37da2899SCharles.Forsyth goto Exit; 562*37da2899SCharles.Forsyth 563*37da2899SCharles.Forsyth count2--; 564*37da2899SCharles.Forsyth range++; 565*37da2899SCharles.Forsyth } 566*37da2899SCharles.Forsyth 567*37da2899SCharles.Forsyth count--; 568*37da2899SCharles.Forsyth strike++; 569*37da2899SCharles.Forsyth } 570*37da2899SCharles.Forsyth } 571*37da2899SCharles.Forsyth 572*37da2899SCharles.Forsyth Exit: 573*37da2899SCharles.Forsyth return error; 574*37da2899SCharles.Forsyth } 575*37da2899SCharles.Forsyth 576*37da2899SCharles.Forsyth 577*37da2899SCharles.Forsyth /*************************************************************************/ 578*37da2899SCharles.Forsyth /* */ 579*37da2899SCharles.Forsyth /* <Function> */ 580*37da2899SCharles.Forsyth /* tt_face_free_sbit_strikes */ 581*37da2899SCharles.Forsyth /* */ 582*37da2899SCharles.Forsyth /* <Description> */ 583*37da2899SCharles.Forsyth /* Releases the embedded bitmap tables. */ 584*37da2899SCharles.Forsyth /* */ 585*37da2899SCharles.Forsyth /* <Input> */ 586*37da2899SCharles.Forsyth /* face :: The target face object. */ 587*37da2899SCharles.Forsyth /* */ 588*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) tt_face_free_sbit_strikes(TT_Face face)589*37da2899SCharles.Forsyth tt_face_free_sbit_strikes( TT_Face face ) 590*37da2899SCharles.Forsyth { 591*37da2899SCharles.Forsyth FT_Memory memory = face->root.memory; 592*37da2899SCharles.Forsyth TT_SBit_Strike strike = face->sbit_strikes; 593*37da2899SCharles.Forsyth TT_SBit_Strike strike_limit = strike + face->num_sbit_strikes; 594*37da2899SCharles.Forsyth 595*37da2899SCharles.Forsyth 596*37da2899SCharles.Forsyth if ( strike ) 597*37da2899SCharles.Forsyth { 598*37da2899SCharles.Forsyth for ( ; strike < strike_limit; strike++ ) 599*37da2899SCharles.Forsyth { 600*37da2899SCharles.Forsyth TT_SBit_Range range = strike->sbit_ranges; 601*37da2899SCharles.Forsyth TT_SBit_Range range_limit = range + strike->num_ranges; 602*37da2899SCharles.Forsyth 603*37da2899SCharles.Forsyth 604*37da2899SCharles.Forsyth if ( range ) 605*37da2899SCharles.Forsyth { 606*37da2899SCharles.Forsyth for ( ; range < range_limit; range++ ) 607*37da2899SCharles.Forsyth { 608*37da2899SCharles.Forsyth /* release the glyph offsets and codes tables */ 609*37da2899SCharles.Forsyth /* where appropriate */ 610*37da2899SCharles.Forsyth FT_FREE( range->glyph_offsets ); 611*37da2899SCharles.Forsyth FT_FREE( range->glyph_codes ); 612*37da2899SCharles.Forsyth } 613*37da2899SCharles.Forsyth } 614*37da2899SCharles.Forsyth FT_FREE( strike->sbit_ranges ); 615*37da2899SCharles.Forsyth strike->num_ranges = 0; 616*37da2899SCharles.Forsyth } 617*37da2899SCharles.Forsyth FT_FREE( face->sbit_strikes ); 618*37da2899SCharles.Forsyth } 619*37da2899SCharles.Forsyth face->num_sbit_strikes = 0; 620*37da2899SCharles.Forsyth } 621*37da2899SCharles.Forsyth 622*37da2899SCharles.Forsyth 623*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_set_sbit_strike(TT_Face face,FT_Int x_ppem,FT_Int y_ppem,FT_ULong * astrike_index)624*37da2899SCharles.Forsyth tt_face_set_sbit_strike( TT_Face face, 625*37da2899SCharles.Forsyth FT_Int x_ppem, 626*37da2899SCharles.Forsyth FT_Int y_ppem, 627*37da2899SCharles.Forsyth FT_ULong *astrike_index ) 628*37da2899SCharles.Forsyth { 629*37da2899SCharles.Forsyth FT_ULong i; 630*37da2899SCharles.Forsyth 631*37da2899SCharles.Forsyth 632*37da2899SCharles.Forsyth if ( x_ppem < 0 || x_ppem > 255 || 633*37da2899SCharles.Forsyth y_ppem < 1 || y_ppem > 255 ) 634*37da2899SCharles.Forsyth return SFNT_Err_Invalid_PPem; 635*37da2899SCharles.Forsyth 636*37da2899SCharles.Forsyth for ( i = 0; i < face->num_sbit_strikes; i++ ) 637*37da2899SCharles.Forsyth { 638*37da2899SCharles.Forsyth if ( ( face->sbit_strikes[i].y_ppem == y_ppem ) && 639*37da2899SCharles.Forsyth ( ( x_ppem == 0 ) || 640*37da2899SCharles.Forsyth ( face->sbit_strikes[i].x_ppem == x_ppem ) ) ) 641*37da2899SCharles.Forsyth { 642*37da2899SCharles.Forsyth *astrike_index = i; 643*37da2899SCharles.Forsyth return SFNT_Err_Ok; 644*37da2899SCharles.Forsyth } 645*37da2899SCharles.Forsyth } 646*37da2899SCharles.Forsyth 647*37da2899SCharles.Forsyth return SFNT_Err_Invalid_PPem; 648*37da2899SCharles.Forsyth } 649*37da2899SCharles.Forsyth 650*37da2899SCharles.Forsyth 651*37da2899SCharles.Forsyth /*************************************************************************/ 652*37da2899SCharles.Forsyth /* */ 653*37da2899SCharles.Forsyth /* <Function> */ 654*37da2899SCharles.Forsyth /* find_sbit_range */ 655*37da2899SCharles.Forsyth /* */ 656*37da2899SCharles.Forsyth /* <Description> */ 657*37da2899SCharles.Forsyth /* Scans a given strike's ranges and return, for a given glyph */ 658*37da2899SCharles.Forsyth /* index, the corresponding sbit range, and `EBDT' offset. */ 659*37da2899SCharles.Forsyth /* */ 660*37da2899SCharles.Forsyth /* <Input> */ 661*37da2899SCharles.Forsyth /* glyph_index :: The glyph index. */ 662*37da2899SCharles.Forsyth /* */ 663*37da2899SCharles.Forsyth /* strike :: The source/current sbit strike. */ 664*37da2899SCharles.Forsyth /* */ 665*37da2899SCharles.Forsyth /* <Output> */ 666*37da2899SCharles.Forsyth /* arange :: The sbit range containing the glyph index. */ 667*37da2899SCharles.Forsyth /* */ 668*37da2899SCharles.Forsyth /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ 669*37da2899SCharles.Forsyth /* */ 670*37da2899SCharles.Forsyth /* <Return> */ 671*37da2899SCharles.Forsyth /* FreeType error code. 0 means the glyph index was found. */ 672*37da2899SCharles.Forsyth /* */ 673*37da2899SCharles.Forsyth static FT_Error find_sbit_range(FT_UInt glyph_index,TT_SBit_Strike strike,TT_SBit_Range * arange,FT_ULong * aglyph_offset)674*37da2899SCharles.Forsyth find_sbit_range( FT_UInt glyph_index, 675*37da2899SCharles.Forsyth TT_SBit_Strike strike, 676*37da2899SCharles.Forsyth TT_SBit_Range *arange, 677*37da2899SCharles.Forsyth FT_ULong *aglyph_offset ) 678*37da2899SCharles.Forsyth { 679*37da2899SCharles.Forsyth TT_SBit_RangeRec *range, *range_limit; 680*37da2899SCharles.Forsyth 681*37da2899SCharles.Forsyth 682*37da2899SCharles.Forsyth /* check whether the glyph index is within this strike's */ 683*37da2899SCharles.Forsyth /* glyph range */ 684*37da2899SCharles.Forsyth if ( glyph_index < (FT_UInt)strike->start_glyph || 685*37da2899SCharles.Forsyth glyph_index > (FT_UInt)strike->end_glyph ) 686*37da2899SCharles.Forsyth goto Fail; 687*37da2899SCharles.Forsyth 688*37da2899SCharles.Forsyth /* scan all ranges in strike */ 689*37da2899SCharles.Forsyth range = strike->sbit_ranges; 690*37da2899SCharles.Forsyth range_limit = range + strike->num_ranges; 691*37da2899SCharles.Forsyth if ( !range ) 692*37da2899SCharles.Forsyth goto Fail; 693*37da2899SCharles.Forsyth 694*37da2899SCharles.Forsyth for ( ; range < range_limit; range++ ) 695*37da2899SCharles.Forsyth { 696*37da2899SCharles.Forsyth if ( glyph_index >= (FT_UInt)range->first_glyph && 697*37da2899SCharles.Forsyth glyph_index <= (FT_UInt)range->last_glyph ) 698*37da2899SCharles.Forsyth { 699*37da2899SCharles.Forsyth FT_UShort delta = (FT_UShort)( glyph_index - range->first_glyph ); 700*37da2899SCharles.Forsyth 701*37da2899SCharles.Forsyth 702*37da2899SCharles.Forsyth switch ( range->index_format ) 703*37da2899SCharles.Forsyth { 704*37da2899SCharles.Forsyth case 1: 705*37da2899SCharles.Forsyth case 3: 706*37da2899SCharles.Forsyth *aglyph_offset = range->glyph_offsets[delta]; 707*37da2899SCharles.Forsyth break; 708*37da2899SCharles.Forsyth 709*37da2899SCharles.Forsyth case 2: 710*37da2899SCharles.Forsyth *aglyph_offset = range->image_offset + 711*37da2899SCharles.Forsyth range->image_size * delta; 712*37da2899SCharles.Forsyth break; 713*37da2899SCharles.Forsyth 714*37da2899SCharles.Forsyth case 4: 715*37da2899SCharles.Forsyth case 5: 716*37da2899SCharles.Forsyth { 717*37da2899SCharles.Forsyth FT_ULong n; 718*37da2899SCharles.Forsyth 719*37da2899SCharles.Forsyth 720*37da2899SCharles.Forsyth for ( n = 0; n < range->num_glyphs; n++ ) 721*37da2899SCharles.Forsyth { 722*37da2899SCharles.Forsyth if ( (FT_UInt)range->glyph_codes[n] == glyph_index ) 723*37da2899SCharles.Forsyth { 724*37da2899SCharles.Forsyth if ( range->index_format == 4 ) 725*37da2899SCharles.Forsyth *aglyph_offset = range->glyph_offsets[n]; 726*37da2899SCharles.Forsyth else 727*37da2899SCharles.Forsyth *aglyph_offset = range->image_offset + 728*37da2899SCharles.Forsyth n * range->image_size; 729*37da2899SCharles.Forsyth goto Found; 730*37da2899SCharles.Forsyth } 731*37da2899SCharles.Forsyth } 732*37da2899SCharles.Forsyth } 733*37da2899SCharles.Forsyth 734*37da2899SCharles.Forsyth /* fall-through */ 735*37da2899SCharles.Forsyth default: 736*37da2899SCharles.Forsyth goto Fail; 737*37da2899SCharles.Forsyth } 738*37da2899SCharles.Forsyth 739*37da2899SCharles.Forsyth Found: 740*37da2899SCharles.Forsyth /* return successfully! */ 741*37da2899SCharles.Forsyth *arange = range; 742*37da2899SCharles.Forsyth return 0; 743*37da2899SCharles.Forsyth } 744*37da2899SCharles.Forsyth } 745*37da2899SCharles.Forsyth 746*37da2899SCharles.Forsyth Fail: 747*37da2899SCharles.Forsyth *arange = 0; 748*37da2899SCharles.Forsyth *aglyph_offset = 0; 749*37da2899SCharles.Forsyth 750*37da2899SCharles.Forsyth return SFNT_Err_Invalid_Argument; 751*37da2899SCharles.Forsyth } 752*37da2899SCharles.Forsyth 753*37da2899SCharles.Forsyth 754*37da2899SCharles.Forsyth /*************************************************************************/ 755*37da2899SCharles.Forsyth /* */ 756*37da2899SCharles.Forsyth /* <Function> */ 757*37da2899SCharles.Forsyth /* find_sbit_image */ 758*37da2899SCharles.Forsyth /* */ 759*37da2899SCharles.Forsyth /* <Description> */ 760*37da2899SCharles.Forsyth /* Checks whether an embedded bitmap (an `sbit') exists for a given */ 761*37da2899SCharles.Forsyth /* glyph, at a given strike. */ 762*37da2899SCharles.Forsyth /* */ 763*37da2899SCharles.Forsyth /* <Input> */ 764*37da2899SCharles.Forsyth /* face :: The target face object. */ 765*37da2899SCharles.Forsyth /* */ 766*37da2899SCharles.Forsyth /* glyph_index :: The glyph index. */ 767*37da2899SCharles.Forsyth /* */ 768*37da2899SCharles.Forsyth /* strike_index :: The current strike index. */ 769*37da2899SCharles.Forsyth /* */ 770*37da2899SCharles.Forsyth /* <Output> */ 771*37da2899SCharles.Forsyth /* arange :: The SBit range containing the glyph index. */ 772*37da2899SCharles.Forsyth /* */ 773*37da2899SCharles.Forsyth /* astrike :: The SBit strike containing the glyph index. */ 774*37da2899SCharles.Forsyth /* */ 775*37da2899SCharles.Forsyth /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ 776*37da2899SCharles.Forsyth /* */ 777*37da2899SCharles.Forsyth /* <Return> */ 778*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. Returns */ 779*37da2899SCharles.Forsyth /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */ 780*37da2899SCharles.Forsyth /* glyph. */ 781*37da2899SCharles.Forsyth /* */ 782*37da2899SCharles.Forsyth static FT_Error find_sbit_image(TT_Face face,FT_UInt glyph_index,FT_ULong strike_index,TT_SBit_Range * arange,TT_SBit_Strike * astrike,FT_ULong * aglyph_offset)783*37da2899SCharles.Forsyth find_sbit_image( TT_Face face, 784*37da2899SCharles.Forsyth FT_UInt glyph_index, 785*37da2899SCharles.Forsyth FT_ULong strike_index, 786*37da2899SCharles.Forsyth TT_SBit_Range *arange, 787*37da2899SCharles.Forsyth TT_SBit_Strike *astrike, 788*37da2899SCharles.Forsyth FT_ULong *aglyph_offset ) 789*37da2899SCharles.Forsyth { 790*37da2899SCharles.Forsyth FT_Error error; 791*37da2899SCharles.Forsyth TT_SBit_Strike strike; 792*37da2899SCharles.Forsyth 793*37da2899SCharles.Forsyth 794*37da2899SCharles.Forsyth if ( !face->sbit_strikes || 795*37da2899SCharles.Forsyth ( face->num_sbit_strikes <= strike_index ) ) 796*37da2899SCharles.Forsyth goto Fail; 797*37da2899SCharles.Forsyth 798*37da2899SCharles.Forsyth strike = &face->sbit_strikes[strike_index]; 799*37da2899SCharles.Forsyth 800*37da2899SCharles.Forsyth error = find_sbit_range( glyph_index, strike, 801*37da2899SCharles.Forsyth arange, aglyph_offset ); 802*37da2899SCharles.Forsyth if ( error ) 803*37da2899SCharles.Forsyth goto Fail; 804*37da2899SCharles.Forsyth 805*37da2899SCharles.Forsyth *astrike = strike; 806*37da2899SCharles.Forsyth 807*37da2899SCharles.Forsyth return SFNT_Err_Ok; 808*37da2899SCharles.Forsyth 809*37da2899SCharles.Forsyth Fail: 810*37da2899SCharles.Forsyth /* no embedded bitmap for this glyph in face */ 811*37da2899SCharles.Forsyth *arange = 0; 812*37da2899SCharles.Forsyth *astrike = 0; 813*37da2899SCharles.Forsyth *aglyph_offset = 0; 814*37da2899SCharles.Forsyth 815*37da2899SCharles.Forsyth return SFNT_Err_Invalid_Argument; 816*37da2899SCharles.Forsyth } 817*37da2899SCharles.Forsyth 818*37da2899SCharles.Forsyth 819*37da2899SCharles.Forsyth /*************************************************************************/ 820*37da2899SCharles.Forsyth /* */ 821*37da2899SCharles.Forsyth /* <Function> */ 822*37da2899SCharles.Forsyth /* load_sbit_metrics */ 823*37da2899SCharles.Forsyth /* */ 824*37da2899SCharles.Forsyth /* <Description> */ 825*37da2899SCharles.Forsyth /* Gets the big metrics for a given SBit. */ 826*37da2899SCharles.Forsyth /* */ 827*37da2899SCharles.Forsyth /* <Input> */ 828*37da2899SCharles.Forsyth /* stream :: The input stream. */ 829*37da2899SCharles.Forsyth /* */ 830*37da2899SCharles.Forsyth /* range :: The SBit range containing the glyph. */ 831*37da2899SCharles.Forsyth /* */ 832*37da2899SCharles.Forsyth /* <Output> */ 833*37da2899SCharles.Forsyth /* big_metrics :: A big SBit metrics structure for the glyph. */ 834*37da2899SCharles.Forsyth /* */ 835*37da2899SCharles.Forsyth /* <Return> */ 836*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. */ 837*37da2899SCharles.Forsyth /* */ 838*37da2899SCharles.Forsyth /* <Note> */ 839*37da2899SCharles.Forsyth /* The stream cursor must be positioned at the glyph's offset within */ 840*37da2899SCharles.Forsyth /* the `EBDT' table before the call. */ 841*37da2899SCharles.Forsyth /* */ 842*37da2899SCharles.Forsyth /* If the image format uses variable metrics, the stream cursor is */ 843*37da2899SCharles.Forsyth /* positioned just after the metrics header in the `EBDT' table on */ 844*37da2899SCharles.Forsyth /* function exit. */ 845*37da2899SCharles.Forsyth /* */ 846*37da2899SCharles.Forsyth static FT_Error load_sbit_metrics(FT_Stream stream,TT_SBit_Range range,TT_SBit_Metrics metrics)847*37da2899SCharles.Forsyth load_sbit_metrics( FT_Stream stream, 848*37da2899SCharles.Forsyth TT_SBit_Range range, 849*37da2899SCharles.Forsyth TT_SBit_Metrics metrics ) 850*37da2899SCharles.Forsyth { 851*37da2899SCharles.Forsyth FT_Error error = SFNT_Err_Ok; 852*37da2899SCharles.Forsyth 853*37da2899SCharles.Forsyth 854*37da2899SCharles.Forsyth switch ( range->image_format ) 855*37da2899SCharles.Forsyth { 856*37da2899SCharles.Forsyth case 1: 857*37da2899SCharles.Forsyth case 2: 858*37da2899SCharles.Forsyth case 8: 859*37da2899SCharles.Forsyth /* variable small metrics */ 860*37da2899SCharles.Forsyth { 861*37da2899SCharles.Forsyth TT_SBit_SmallMetricsRec smetrics; 862*37da2899SCharles.Forsyth 863*37da2899SCharles.Forsyth const FT_Frame_Field sbit_small_metrics_fields[] = 864*37da2899SCharles.Forsyth { 865*37da2899SCharles.Forsyth #undef FT_STRUCTURE 866*37da2899SCharles.Forsyth #define FT_STRUCTURE TT_SBit_SmallMetricsRec 867*37da2899SCharles.Forsyth 868*37da2899SCharles.Forsyth FT_FRAME_START( 5 ), 869*37da2899SCharles.Forsyth FT_FRAME_BYTE( height ), 870*37da2899SCharles.Forsyth FT_FRAME_BYTE( width ), 871*37da2899SCharles.Forsyth FT_FRAME_CHAR( bearingX ), 872*37da2899SCharles.Forsyth FT_FRAME_CHAR( bearingY ), 873*37da2899SCharles.Forsyth FT_FRAME_BYTE( advance ), 874*37da2899SCharles.Forsyth FT_FRAME_END 875*37da2899SCharles.Forsyth }; 876*37da2899SCharles.Forsyth 877*37da2899SCharles.Forsyth 878*37da2899SCharles.Forsyth /* read small metrics */ 879*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) ) 880*37da2899SCharles.Forsyth goto Exit; 881*37da2899SCharles.Forsyth 882*37da2899SCharles.Forsyth /* convert it to a big metrics */ 883*37da2899SCharles.Forsyth metrics->height = smetrics.height; 884*37da2899SCharles.Forsyth metrics->width = smetrics.width; 885*37da2899SCharles.Forsyth metrics->horiBearingX = smetrics.bearingX; 886*37da2899SCharles.Forsyth metrics->horiBearingY = smetrics.bearingY; 887*37da2899SCharles.Forsyth metrics->horiAdvance = smetrics.advance; 888*37da2899SCharles.Forsyth 889*37da2899SCharles.Forsyth /* these metrics are made up at a higher level when */ 890*37da2899SCharles.Forsyth /* needed. */ 891*37da2899SCharles.Forsyth metrics->vertBearingX = 0; 892*37da2899SCharles.Forsyth metrics->vertBearingY = 0; 893*37da2899SCharles.Forsyth metrics->vertAdvance = 0; 894*37da2899SCharles.Forsyth } 895*37da2899SCharles.Forsyth break; 896*37da2899SCharles.Forsyth 897*37da2899SCharles.Forsyth case 6: 898*37da2899SCharles.Forsyth case 7: 899*37da2899SCharles.Forsyth case 9: 900*37da2899SCharles.Forsyth /* variable big metrics */ 901*37da2899SCharles.Forsyth if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) ) 902*37da2899SCharles.Forsyth goto Exit; 903*37da2899SCharles.Forsyth break; 904*37da2899SCharles.Forsyth 905*37da2899SCharles.Forsyth case 5: 906*37da2899SCharles.Forsyth default: /* constant metrics */ 907*37da2899SCharles.Forsyth if ( range->index_format == 2 || range->index_format == 5 ) 908*37da2899SCharles.Forsyth *metrics = range->metrics; 909*37da2899SCharles.Forsyth else 910*37da2899SCharles.Forsyth return SFNT_Err_Invalid_File_Format; 911*37da2899SCharles.Forsyth } 912*37da2899SCharles.Forsyth 913*37da2899SCharles.Forsyth Exit: 914*37da2899SCharles.Forsyth return error; 915*37da2899SCharles.Forsyth } 916*37da2899SCharles.Forsyth 917*37da2899SCharles.Forsyth 918*37da2899SCharles.Forsyth /*************************************************************************/ 919*37da2899SCharles.Forsyth /* */ 920*37da2899SCharles.Forsyth /* <Function> */ 921*37da2899SCharles.Forsyth /* crop_bitmap */ 922*37da2899SCharles.Forsyth /* */ 923*37da2899SCharles.Forsyth /* <Description> */ 924*37da2899SCharles.Forsyth /* Crops a bitmap to its tightest bounding box, and adjusts its */ 925*37da2899SCharles.Forsyth /* metrics. */ 926*37da2899SCharles.Forsyth /* */ 927*37da2899SCharles.Forsyth /* <InOut> */ 928*37da2899SCharles.Forsyth /* map :: The bitmap. */ 929*37da2899SCharles.Forsyth /* */ 930*37da2899SCharles.Forsyth /* metrics :: The corresponding metrics structure. */ 931*37da2899SCharles.Forsyth /* */ 932*37da2899SCharles.Forsyth static void crop_bitmap(FT_Bitmap * map,TT_SBit_Metrics metrics)933*37da2899SCharles.Forsyth crop_bitmap( FT_Bitmap* map, 934*37da2899SCharles.Forsyth TT_SBit_Metrics metrics ) 935*37da2899SCharles.Forsyth { 936*37da2899SCharles.Forsyth /***********************************************************************/ 937*37da2899SCharles.Forsyth /* */ 938*37da2899SCharles.Forsyth /* In this situation, some bounding boxes of embedded bitmaps are too */ 939*37da2899SCharles.Forsyth /* large. We need to crop it to a reasonable size. */ 940*37da2899SCharles.Forsyth /* */ 941*37da2899SCharles.Forsyth /* --------- */ 942*37da2899SCharles.Forsyth /* | | ----- */ 943*37da2899SCharles.Forsyth /* | *** | |***| */ 944*37da2899SCharles.Forsyth /* | * | | * | */ 945*37da2899SCharles.Forsyth /* | * | ------> | * | */ 946*37da2899SCharles.Forsyth /* | * | | * | */ 947*37da2899SCharles.Forsyth /* | * | | * | */ 948*37da2899SCharles.Forsyth /* | *** | |***| */ 949*37da2899SCharles.Forsyth /* --------- ----- */ 950*37da2899SCharles.Forsyth /* */ 951*37da2899SCharles.Forsyth /***********************************************************************/ 952*37da2899SCharles.Forsyth 953*37da2899SCharles.Forsyth FT_Int rows, count; 954*37da2899SCharles.Forsyth FT_Long line_len; 955*37da2899SCharles.Forsyth FT_Byte* line; 956*37da2899SCharles.Forsyth 957*37da2899SCharles.Forsyth 958*37da2899SCharles.Forsyth /***********************************************************************/ 959*37da2899SCharles.Forsyth /* */ 960*37da2899SCharles.Forsyth /* first of all, check the top-most lines of the bitmap, and remove */ 961*37da2899SCharles.Forsyth /* them if they're empty. */ 962*37da2899SCharles.Forsyth /* */ 963*37da2899SCharles.Forsyth { 964*37da2899SCharles.Forsyth line = (FT_Byte*)map->buffer; 965*37da2899SCharles.Forsyth rows = map->rows; 966*37da2899SCharles.Forsyth line_len = map->pitch; 967*37da2899SCharles.Forsyth 968*37da2899SCharles.Forsyth 969*37da2899SCharles.Forsyth for ( count = 0; count < rows; count++ ) 970*37da2899SCharles.Forsyth { 971*37da2899SCharles.Forsyth FT_Byte* cur = line; 972*37da2899SCharles.Forsyth FT_Byte* limit = line + line_len; 973*37da2899SCharles.Forsyth 974*37da2899SCharles.Forsyth 975*37da2899SCharles.Forsyth for ( ; cur < limit; cur++ ) 976*37da2899SCharles.Forsyth if ( cur[0] ) 977*37da2899SCharles.Forsyth goto Found_Top; 978*37da2899SCharles.Forsyth 979*37da2899SCharles.Forsyth /* the current line was empty - skip to next one */ 980*37da2899SCharles.Forsyth line = limit; 981*37da2899SCharles.Forsyth } 982*37da2899SCharles.Forsyth 983*37da2899SCharles.Forsyth Found_Top: 984*37da2899SCharles.Forsyth /* check that we have at least one filled line */ 985*37da2899SCharles.Forsyth if ( count >= rows ) 986*37da2899SCharles.Forsyth goto Empty_Bitmap; 987*37da2899SCharles.Forsyth 988*37da2899SCharles.Forsyth /* now, crop the empty upper lines */ 989*37da2899SCharles.Forsyth if ( count > 0 ) 990*37da2899SCharles.Forsyth { 991*37da2899SCharles.Forsyth line = (FT_Byte*)map->buffer; 992*37da2899SCharles.Forsyth 993*37da2899SCharles.Forsyth FT_MEM_MOVE( line, line + count * line_len, 994*37da2899SCharles.Forsyth ( rows - count ) * line_len ); 995*37da2899SCharles.Forsyth 996*37da2899SCharles.Forsyth metrics->height = (FT_Byte)( metrics->height - count ); 997*37da2899SCharles.Forsyth metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count ); 998*37da2899SCharles.Forsyth metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count ); 999*37da2899SCharles.Forsyth 1000*37da2899SCharles.Forsyth map->rows -= count; 1001*37da2899SCharles.Forsyth rows -= count; 1002*37da2899SCharles.Forsyth } 1003*37da2899SCharles.Forsyth } 1004*37da2899SCharles.Forsyth 1005*37da2899SCharles.Forsyth /***********************************************************************/ 1006*37da2899SCharles.Forsyth /* */ 1007*37da2899SCharles.Forsyth /* second, crop the lower lines */ 1008*37da2899SCharles.Forsyth /* */ 1009*37da2899SCharles.Forsyth { 1010*37da2899SCharles.Forsyth line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len; 1011*37da2899SCharles.Forsyth 1012*37da2899SCharles.Forsyth for ( count = 0; count < rows; count++ ) 1013*37da2899SCharles.Forsyth { 1014*37da2899SCharles.Forsyth FT_Byte* cur = line; 1015*37da2899SCharles.Forsyth FT_Byte* limit = line + line_len; 1016*37da2899SCharles.Forsyth 1017*37da2899SCharles.Forsyth 1018*37da2899SCharles.Forsyth for ( ; cur < limit; cur++ ) 1019*37da2899SCharles.Forsyth if ( cur[0] ) 1020*37da2899SCharles.Forsyth goto Found_Bottom; 1021*37da2899SCharles.Forsyth 1022*37da2899SCharles.Forsyth /* the current line was empty - skip to previous one */ 1023*37da2899SCharles.Forsyth line -= line_len; 1024*37da2899SCharles.Forsyth } 1025*37da2899SCharles.Forsyth 1026*37da2899SCharles.Forsyth Found_Bottom: 1027*37da2899SCharles.Forsyth if ( count > 0 ) 1028*37da2899SCharles.Forsyth { 1029*37da2899SCharles.Forsyth metrics->height = (FT_Byte)( metrics->height - count ); 1030*37da2899SCharles.Forsyth rows -= count; 1031*37da2899SCharles.Forsyth map->rows -= count; 1032*37da2899SCharles.Forsyth } 1033*37da2899SCharles.Forsyth } 1034*37da2899SCharles.Forsyth 1035*37da2899SCharles.Forsyth /***********************************************************************/ 1036*37da2899SCharles.Forsyth /* */ 1037*37da2899SCharles.Forsyth /* third, get rid of the space on the left side of the glyph */ 1038*37da2899SCharles.Forsyth /* */ 1039*37da2899SCharles.Forsyth do 1040*37da2899SCharles.Forsyth { 1041*37da2899SCharles.Forsyth FT_Byte* limit; 1042*37da2899SCharles.Forsyth 1043*37da2899SCharles.Forsyth 1044*37da2899SCharles.Forsyth line = (FT_Byte*)map->buffer; 1045*37da2899SCharles.Forsyth limit = line + rows * line_len; 1046*37da2899SCharles.Forsyth 1047*37da2899SCharles.Forsyth for ( ; line < limit; line += line_len ) 1048*37da2899SCharles.Forsyth if ( line[0] & 0x80 ) 1049*37da2899SCharles.Forsyth goto Found_Left; 1050*37da2899SCharles.Forsyth 1051*37da2899SCharles.Forsyth /* shift the whole glyph one pixel to the left */ 1052*37da2899SCharles.Forsyth line = (FT_Byte*)map->buffer; 1053*37da2899SCharles.Forsyth limit = line + rows * line_len; 1054*37da2899SCharles.Forsyth 1055*37da2899SCharles.Forsyth for ( ; line < limit; line += line_len ) 1056*37da2899SCharles.Forsyth { 1057*37da2899SCharles.Forsyth FT_Int n, width = map->width; 1058*37da2899SCharles.Forsyth FT_Byte old; 1059*37da2899SCharles.Forsyth FT_Byte* cur = line; 1060*37da2899SCharles.Forsyth 1061*37da2899SCharles.Forsyth 1062*37da2899SCharles.Forsyth old = (FT_Byte)(cur[0] << 1); 1063*37da2899SCharles.Forsyth for ( n = 8; n < width; n += 8 ) 1064*37da2899SCharles.Forsyth { 1065*37da2899SCharles.Forsyth FT_Byte val; 1066*37da2899SCharles.Forsyth 1067*37da2899SCharles.Forsyth 1068*37da2899SCharles.Forsyth val = cur[1]; 1069*37da2899SCharles.Forsyth cur[0] = (FT_Byte)( old | ( val >> 7 ) ); 1070*37da2899SCharles.Forsyth old = (FT_Byte)( val << 1 ); 1071*37da2899SCharles.Forsyth cur++; 1072*37da2899SCharles.Forsyth } 1073*37da2899SCharles.Forsyth cur[0] = old; 1074*37da2899SCharles.Forsyth } 1075*37da2899SCharles.Forsyth 1076*37da2899SCharles.Forsyth map->width--; 1077*37da2899SCharles.Forsyth metrics->horiBearingX++; 1078*37da2899SCharles.Forsyth metrics->vertBearingX++; 1079*37da2899SCharles.Forsyth metrics->width--; 1080*37da2899SCharles.Forsyth 1081*37da2899SCharles.Forsyth } while ( map->width > 0 ); 1082*37da2899SCharles.Forsyth 1083*37da2899SCharles.Forsyth Found_Left: 1084*37da2899SCharles.Forsyth 1085*37da2899SCharles.Forsyth /***********************************************************************/ 1086*37da2899SCharles.Forsyth /* */ 1087*37da2899SCharles.Forsyth /* finally, crop the bitmap width to get rid of the space on the right */ 1088*37da2899SCharles.Forsyth /* side of the glyph. */ 1089*37da2899SCharles.Forsyth /* */ 1090*37da2899SCharles.Forsyth do 1091*37da2899SCharles.Forsyth { 1092*37da2899SCharles.Forsyth FT_Int right = map->width - 1; 1093*37da2899SCharles.Forsyth FT_Byte* limit; 1094*37da2899SCharles.Forsyth FT_Byte mask; 1095*37da2899SCharles.Forsyth 1096*37da2899SCharles.Forsyth 1097*37da2899SCharles.Forsyth line = (FT_Byte*)map->buffer + ( right >> 3 ); 1098*37da2899SCharles.Forsyth limit = line + rows * line_len; 1099*37da2899SCharles.Forsyth mask = (FT_Byte)( 0x80 >> ( right & 7 ) ); 1100*37da2899SCharles.Forsyth 1101*37da2899SCharles.Forsyth for ( ; line < limit; line += line_len ) 1102*37da2899SCharles.Forsyth if ( line[0] & mask ) 1103*37da2899SCharles.Forsyth goto Found_Right; 1104*37da2899SCharles.Forsyth 1105*37da2899SCharles.Forsyth /* crop the whole glyph to the right */ 1106*37da2899SCharles.Forsyth map->width--; 1107*37da2899SCharles.Forsyth metrics->width--; 1108*37da2899SCharles.Forsyth 1109*37da2899SCharles.Forsyth } while ( map->width > 0 ); 1110*37da2899SCharles.Forsyth 1111*37da2899SCharles.Forsyth Found_Right: 1112*37da2899SCharles.Forsyth /* all right, the bitmap was cropped */ 1113*37da2899SCharles.Forsyth return; 1114*37da2899SCharles.Forsyth 1115*37da2899SCharles.Forsyth Empty_Bitmap: 1116*37da2899SCharles.Forsyth map->width = 0; 1117*37da2899SCharles.Forsyth map->rows = 0; 1118*37da2899SCharles.Forsyth map->pitch = 0; 1119*37da2899SCharles.Forsyth map->pixel_mode = FT_PIXEL_MODE_MONO; 1120*37da2899SCharles.Forsyth } 1121*37da2899SCharles.Forsyth 1122*37da2899SCharles.Forsyth 1123*37da2899SCharles.Forsyth static FT_Error Load_SBit_Single(FT_Bitmap * map,FT_Int x_offset,FT_Int y_offset,FT_Int pix_bits,FT_UShort image_format,TT_SBit_Metrics metrics,FT_Stream stream)1124*37da2899SCharles.Forsyth Load_SBit_Single( FT_Bitmap* map, 1125*37da2899SCharles.Forsyth FT_Int x_offset, 1126*37da2899SCharles.Forsyth FT_Int y_offset, 1127*37da2899SCharles.Forsyth FT_Int pix_bits, 1128*37da2899SCharles.Forsyth FT_UShort image_format, 1129*37da2899SCharles.Forsyth TT_SBit_Metrics metrics, 1130*37da2899SCharles.Forsyth FT_Stream stream ) 1131*37da2899SCharles.Forsyth { 1132*37da2899SCharles.Forsyth FT_Error error; 1133*37da2899SCharles.Forsyth 1134*37da2899SCharles.Forsyth 1135*37da2899SCharles.Forsyth /* check that the source bitmap fits into the target pixmap */ 1136*37da2899SCharles.Forsyth if ( x_offset < 0 || x_offset + metrics->width > map->width || 1137*37da2899SCharles.Forsyth y_offset < 0 || y_offset + metrics->height > map->rows ) 1138*37da2899SCharles.Forsyth { 1139*37da2899SCharles.Forsyth error = SFNT_Err_Invalid_Argument; 1140*37da2899SCharles.Forsyth 1141*37da2899SCharles.Forsyth goto Exit; 1142*37da2899SCharles.Forsyth } 1143*37da2899SCharles.Forsyth 1144*37da2899SCharles.Forsyth { 1145*37da2899SCharles.Forsyth FT_Int glyph_width = metrics->width; 1146*37da2899SCharles.Forsyth FT_Int glyph_height = metrics->height; 1147*37da2899SCharles.Forsyth FT_Int glyph_size; 1148*37da2899SCharles.Forsyth FT_Int line_bits = pix_bits * glyph_width; 1149*37da2899SCharles.Forsyth FT_Bool pad_bytes = 0; 1150*37da2899SCharles.Forsyth 1151*37da2899SCharles.Forsyth 1152*37da2899SCharles.Forsyth /* compute size of glyph image */ 1153*37da2899SCharles.Forsyth switch ( image_format ) 1154*37da2899SCharles.Forsyth { 1155*37da2899SCharles.Forsyth case 1: /* byte-padded formats */ 1156*37da2899SCharles.Forsyth case 6: 1157*37da2899SCharles.Forsyth { 1158*37da2899SCharles.Forsyth FT_Int line_length; 1159*37da2899SCharles.Forsyth 1160*37da2899SCharles.Forsyth 1161*37da2899SCharles.Forsyth switch ( pix_bits ) 1162*37da2899SCharles.Forsyth { 1163*37da2899SCharles.Forsyth case 1: 1164*37da2899SCharles.Forsyth line_length = ( glyph_width + 7 ) >> 3; 1165*37da2899SCharles.Forsyth break; 1166*37da2899SCharles.Forsyth case 2: 1167*37da2899SCharles.Forsyth line_length = ( glyph_width + 3 ) >> 2; 1168*37da2899SCharles.Forsyth break; 1169*37da2899SCharles.Forsyth case 4: 1170*37da2899SCharles.Forsyth line_length = ( glyph_width + 1 ) >> 1; 1171*37da2899SCharles.Forsyth break; 1172*37da2899SCharles.Forsyth default: 1173*37da2899SCharles.Forsyth line_length = glyph_width; 1174*37da2899SCharles.Forsyth } 1175*37da2899SCharles.Forsyth 1176*37da2899SCharles.Forsyth glyph_size = glyph_height * line_length; 1177*37da2899SCharles.Forsyth pad_bytes = 1; 1178*37da2899SCharles.Forsyth } 1179*37da2899SCharles.Forsyth break; 1180*37da2899SCharles.Forsyth 1181*37da2899SCharles.Forsyth case 2: 1182*37da2899SCharles.Forsyth case 5: 1183*37da2899SCharles.Forsyth case 7: 1184*37da2899SCharles.Forsyth line_bits = glyph_width * pix_bits; 1185*37da2899SCharles.Forsyth glyph_size = ( glyph_height * line_bits + 7 ) >> 3; 1186*37da2899SCharles.Forsyth break; 1187*37da2899SCharles.Forsyth 1188*37da2899SCharles.Forsyth default: /* invalid format */ 1189*37da2899SCharles.Forsyth return SFNT_Err_Invalid_File_Format; 1190*37da2899SCharles.Forsyth } 1191*37da2899SCharles.Forsyth 1192*37da2899SCharles.Forsyth /* Now read data and draw glyph into target pixmap */ 1193*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( glyph_size ) ) 1194*37da2899SCharles.Forsyth goto Exit; 1195*37da2899SCharles.Forsyth 1196*37da2899SCharles.Forsyth /* don't forget to multiply `x_offset' by `map->pix_bits' as */ 1197*37da2899SCharles.Forsyth /* the sbit blitter doesn't make a difference between pixmap */ 1198*37da2899SCharles.Forsyth /* depths. */ 1199*37da2899SCharles.Forsyth blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes, 1200*37da2899SCharles.Forsyth x_offset * pix_bits, y_offset ); 1201*37da2899SCharles.Forsyth 1202*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 1203*37da2899SCharles.Forsyth } 1204*37da2899SCharles.Forsyth 1205*37da2899SCharles.Forsyth Exit: 1206*37da2899SCharles.Forsyth return error; 1207*37da2899SCharles.Forsyth } 1208*37da2899SCharles.Forsyth 1209*37da2899SCharles.Forsyth 1210*37da2899SCharles.Forsyth static FT_Error Load_SBit_Image(TT_SBit_Strike strike,TT_SBit_Range range,FT_ULong ebdt_pos,FT_ULong glyph_offset,FT_Bitmap * map,FT_Int x_offset,FT_Int y_offset,FT_Stream stream,TT_SBit_Metrics metrics)1211*37da2899SCharles.Forsyth Load_SBit_Image( TT_SBit_Strike strike, 1212*37da2899SCharles.Forsyth TT_SBit_Range range, 1213*37da2899SCharles.Forsyth FT_ULong ebdt_pos, 1214*37da2899SCharles.Forsyth FT_ULong glyph_offset, 1215*37da2899SCharles.Forsyth FT_Bitmap* map, 1216*37da2899SCharles.Forsyth FT_Int x_offset, 1217*37da2899SCharles.Forsyth FT_Int y_offset, 1218*37da2899SCharles.Forsyth FT_Stream stream, 1219*37da2899SCharles.Forsyth TT_SBit_Metrics metrics ) 1220*37da2899SCharles.Forsyth { 1221*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 1222*37da2899SCharles.Forsyth FT_Error error; 1223*37da2899SCharles.Forsyth 1224*37da2899SCharles.Forsyth 1225*37da2899SCharles.Forsyth /* place stream at beginning of glyph data and read metrics */ 1226*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) ) 1227*37da2899SCharles.Forsyth goto Exit; 1228*37da2899SCharles.Forsyth 1229*37da2899SCharles.Forsyth error = load_sbit_metrics( stream, range, metrics ); 1230*37da2899SCharles.Forsyth if ( error ) 1231*37da2899SCharles.Forsyth goto Exit; 1232*37da2899SCharles.Forsyth 1233*37da2899SCharles.Forsyth /* this function is recursive. At the top-level call, the */ 1234*37da2899SCharles.Forsyth /* field map.buffer is NULL. We thus begin by finding the */ 1235*37da2899SCharles.Forsyth /* dimensions of the higher-level glyph to allocate the */ 1236*37da2899SCharles.Forsyth /* final pixmap buffer */ 1237*37da2899SCharles.Forsyth if ( map->buffer == 0 ) 1238*37da2899SCharles.Forsyth { 1239*37da2899SCharles.Forsyth FT_Long size; 1240*37da2899SCharles.Forsyth 1241*37da2899SCharles.Forsyth 1242*37da2899SCharles.Forsyth map->width = metrics->width; 1243*37da2899SCharles.Forsyth map->rows = metrics->height; 1244*37da2899SCharles.Forsyth 1245*37da2899SCharles.Forsyth switch ( strike->bit_depth ) 1246*37da2899SCharles.Forsyth { 1247*37da2899SCharles.Forsyth case 1: 1248*37da2899SCharles.Forsyth map->pixel_mode = FT_PIXEL_MODE_MONO; 1249*37da2899SCharles.Forsyth map->pitch = ( map->width + 7 ) >> 3; 1250*37da2899SCharles.Forsyth break; 1251*37da2899SCharles.Forsyth 1252*37da2899SCharles.Forsyth case 2: 1253*37da2899SCharles.Forsyth map->pixel_mode = FT_PIXEL_MODE_GRAY2; 1254*37da2899SCharles.Forsyth map->pitch = ( map->width + 3 ) >> 2; 1255*37da2899SCharles.Forsyth break; 1256*37da2899SCharles.Forsyth 1257*37da2899SCharles.Forsyth case 4: 1258*37da2899SCharles.Forsyth map->pixel_mode = FT_PIXEL_MODE_GRAY4; 1259*37da2899SCharles.Forsyth map->pitch = ( map->width + 1 ) >> 1; 1260*37da2899SCharles.Forsyth break; 1261*37da2899SCharles.Forsyth 1262*37da2899SCharles.Forsyth case 8: 1263*37da2899SCharles.Forsyth map->pixel_mode = FT_PIXEL_MODE_GRAY; 1264*37da2899SCharles.Forsyth map->pitch = map->width; 1265*37da2899SCharles.Forsyth break; 1266*37da2899SCharles.Forsyth 1267*37da2899SCharles.Forsyth default: 1268*37da2899SCharles.Forsyth return SFNT_Err_Invalid_File_Format; 1269*37da2899SCharles.Forsyth } 1270*37da2899SCharles.Forsyth 1271*37da2899SCharles.Forsyth size = map->rows * map->pitch; 1272*37da2899SCharles.Forsyth 1273*37da2899SCharles.Forsyth /* check that there is no empty image */ 1274*37da2899SCharles.Forsyth if ( size == 0 ) 1275*37da2899SCharles.Forsyth goto Exit; /* exit successfully! */ 1276*37da2899SCharles.Forsyth 1277*37da2899SCharles.Forsyth if ( FT_ALLOC( map->buffer, size ) ) 1278*37da2899SCharles.Forsyth goto Exit; 1279*37da2899SCharles.Forsyth } 1280*37da2899SCharles.Forsyth 1281*37da2899SCharles.Forsyth switch ( range->image_format ) 1282*37da2899SCharles.Forsyth { 1283*37da2899SCharles.Forsyth case 1: /* single sbit image - load it */ 1284*37da2899SCharles.Forsyth case 2: 1285*37da2899SCharles.Forsyth case 5: 1286*37da2899SCharles.Forsyth case 6: 1287*37da2899SCharles.Forsyth case 7: 1288*37da2899SCharles.Forsyth return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth, 1289*37da2899SCharles.Forsyth range->image_format, metrics, stream ); 1290*37da2899SCharles.Forsyth 1291*37da2899SCharles.Forsyth case 8: /* compound format */ 1292*37da2899SCharles.Forsyth FT_Stream_Skip( stream, 1L ); 1293*37da2899SCharles.Forsyth /* fallthrough */ 1294*37da2899SCharles.Forsyth 1295*37da2899SCharles.Forsyth case 9: 1296*37da2899SCharles.Forsyth break; 1297*37da2899SCharles.Forsyth 1298*37da2899SCharles.Forsyth default: /* invalid image format */ 1299*37da2899SCharles.Forsyth return SFNT_Err_Invalid_File_Format; 1300*37da2899SCharles.Forsyth } 1301*37da2899SCharles.Forsyth 1302*37da2899SCharles.Forsyth /* All right, we have a compound format. First of all, read */ 1303*37da2899SCharles.Forsyth /* the array of elements. */ 1304*37da2899SCharles.Forsyth { 1305*37da2899SCharles.Forsyth TT_SBit_Component components; 1306*37da2899SCharles.Forsyth TT_SBit_Component comp; 1307*37da2899SCharles.Forsyth FT_UShort num_components, count; 1308*37da2899SCharles.Forsyth 1309*37da2899SCharles.Forsyth 1310*37da2899SCharles.Forsyth if ( FT_READ_USHORT( num_components ) || 1311*37da2899SCharles.Forsyth FT_NEW_ARRAY( components, num_components ) ) 1312*37da2899SCharles.Forsyth goto Exit; 1313*37da2899SCharles.Forsyth 1314*37da2899SCharles.Forsyth count = num_components; 1315*37da2899SCharles.Forsyth 1316*37da2899SCharles.Forsyth if ( FT_FRAME_ENTER( 4L * num_components ) ) 1317*37da2899SCharles.Forsyth goto Fail_Memory; 1318*37da2899SCharles.Forsyth 1319*37da2899SCharles.Forsyth for ( comp = components; count > 0; count--, comp++ ) 1320*37da2899SCharles.Forsyth { 1321*37da2899SCharles.Forsyth comp->glyph_code = FT_GET_USHORT(); 1322*37da2899SCharles.Forsyth comp->x_offset = FT_GET_CHAR(); 1323*37da2899SCharles.Forsyth comp->y_offset = FT_GET_CHAR(); 1324*37da2899SCharles.Forsyth } 1325*37da2899SCharles.Forsyth 1326*37da2899SCharles.Forsyth FT_FRAME_EXIT(); 1327*37da2899SCharles.Forsyth 1328*37da2899SCharles.Forsyth /* Now recursively load each element glyph */ 1329*37da2899SCharles.Forsyth count = num_components; 1330*37da2899SCharles.Forsyth comp = components; 1331*37da2899SCharles.Forsyth for ( ; count > 0; count--, comp++ ) 1332*37da2899SCharles.Forsyth { 1333*37da2899SCharles.Forsyth TT_SBit_Range elem_range; 1334*37da2899SCharles.Forsyth TT_SBit_MetricsRec elem_metrics; 1335*37da2899SCharles.Forsyth FT_ULong elem_offset; 1336*37da2899SCharles.Forsyth 1337*37da2899SCharles.Forsyth 1338*37da2899SCharles.Forsyth /* find the range for this element */ 1339*37da2899SCharles.Forsyth error = find_sbit_range( comp->glyph_code, 1340*37da2899SCharles.Forsyth strike, 1341*37da2899SCharles.Forsyth &elem_range, 1342*37da2899SCharles.Forsyth &elem_offset ); 1343*37da2899SCharles.Forsyth if ( error ) 1344*37da2899SCharles.Forsyth goto Fail_Memory; 1345*37da2899SCharles.Forsyth 1346*37da2899SCharles.Forsyth /* now load the element, recursively */ 1347*37da2899SCharles.Forsyth error = Load_SBit_Image( strike, 1348*37da2899SCharles.Forsyth elem_range, 1349*37da2899SCharles.Forsyth ebdt_pos, 1350*37da2899SCharles.Forsyth elem_offset, 1351*37da2899SCharles.Forsyth map, 1352*37da2899SCharles.Forsyth x_offset + comp->x_offset, 1353*37da2899SCharles.Forsyth y_offset + comp->y_offset, 1354*37da2899SCharles.Forsyth stream, 1355*37da2899SCharles.Forsyth &elem_metrics ); 1356*37da2899SCharles.Forsyth if ( error ) 1357*37da2899SCharles.Forsyth goto Fail_Memory; 1358*37da2899SCharles.Forsyth } 1359*37da2899SCharles.Forsyth 1360*37da2899SCharles.Forsyth Fail_Memory: 1361*37da2899SCharles.Forsyth FT_FREE( components ); 1362*37da2899SCharles.Forsyth } 1363*37da2899SCharles.Forsyth 1364*37da2899SCharles.Forsyth Exit: 1365*37da2899SCharles.Forsyth return error; 1366*37da2899SCharles.Forsyth } 1367*37da2899SCharles.Forsyth 1368*37da2899SCharles.Forsyth 1369*37da2899SCharles.Forsyth /*************************************************************************/ 1370*37da2899SCharles.Forsyth /* */ 1371*37da2899SCharles.Forsyth /* <Function> */ 1372*37da2899SCharles.Forsyth /* tt_face_load_sbit_image */ 1373*37da2899SCharles.Forsyth /* */ 1374*37da2899SCharles.Forsyth /* <Description> */ 1375*37da2899SCharles.Forsyth /* Loads a given glyph sbit image from the font resource. This also */ 1376*37da2899SCharles.Forsyth /* returns its metrics. */ 1377*37da2899SCharles.Forsyth /* */ 1378*37da2899SCharles.Forsyth /* <Input> */ 1379*37da2899SCharles.Forsyth /* face :: The target face object. */ 1380*37da2899SCharles.Forsyth /* */ 1381*37da2899SCharles.Forsyth /* strike_index :: The current strike index. */ 1382*37da2899SCharles.Forsyth /* */ 1383*37da2899SCharles.Forsyth /* glyph_index :: The current glyph index. */ 1384*37da2899SCharles.Forsyth /* */ 1385*37da2899SCharles.Forsyth /* load_flags :: The glyph load flags (the code checks for the flag */ 1386*37da2899SCharles.Forsyth /* FT_LOAD_CROP_BITMAP). */ 1387*37da2899SCharles.Forsyth /* */ 1388*37da2899SCharles.Forsyth /* stream :: The input stream. */ 1389*37da2899SCharles.Forsyth /* */ 1390*37da2899SCharles.Forsyth /* <Output> */ 1391*37da2899SCharles.Forsyth /* map :: The target pixmap. */ 1392*37da2899SCharles.Forsyth /* */ 1393*37da2899SCharles.Forsyth /* metrics :: A big sbit metrics structure for the glyph image. */ 1394*37da2899SCharles.Forsyth /* */ 1395*37da2899SCharles.Forsyth /* <Return> */ 1396*37da2899SCharles.Forsyth /* FreeType error code. 0 means success. Returns an error if no */ 1397*37da2899SCharles.Forsyth /* glyph sbit exists for the index. */ 1398*37da2899SCharles.Forsyth /* */ 1399*37da2899SCharles.Forsyth /* <Note> */ 1400*37da2899SCharles.Forsyth /* The `map.buffer' field is always freed before the glyph is loaded. */ 1401*37da2899SCharles.Forsyth /* */ 1402*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) tt_face_load_sbit_image(TT_Face face,FT_ULong strike_index,FT_UInt glyph_index,FT_UInt load_flags,FT_Stream stream,FT_Bitmap * map,TT_SBit_MetricsRec * metrics)1403*37da2899SCharles.Forsyth tt_face_load_sbit_image( TT_Face face, 1404*37da2899SCharles.Forsyth FT_ULong strike_index, 1405*37da2899SCharles.Forsyth FT_UInt glyph_index, 1406*37da2899SCharles.Forsyth FT_UInt load_flags, 1407*37da2899SCharles.Forsyth FT_Stream stream, 1408*37da2899SCharles.Forsyth FT_Bitmap *map, 1409*37da2899SCharles.Forsyth TT_SBit_MetricsRec *metrics ) 1410*37da2899SCharles.Forsyth { 1411*37da2899SCharles.Forsyth FT_Error error; 1412*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 1413*37da2899SCharles.Forsyth FT_ULong ebdt_pos, glyph_offset; 1414*37da2899SCharles.Forsyth 1415*37da2899SCharles.Forsyth TT_SBit_Strike strike; 1416*37da2899SCharles.Forsyth TT_SBit_Range range; 1417*37da2899SCharles.Forsyth 1418*37da2899SCharles.Forsyth 1419*37da2899SCharles.Forsyth /* Check whether there is a glyph sbit for the current index */ 1420*37da2899SCharles.Forsyth error = find_sbit_image( face, glyph_index, strike_index, 1421*37da2899SCharles.Forsyth &range, &strike, &glyph_offset ); 1422*37da2899SCharles.Forsyth if ( error ) 1423*37da2899SCharles.Forsyth goto Exit; 1424*37da2899SCharles.Forsyth 1425*37da2899SCharles.Forsyth /* now, find the location of the `EBDT' table in */ 1426*37da2899SCharles.Forsyth /* the font file */ 1427*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_EBDT, stream, 0 ); 1428*37da2899SCharles.Forsyth if ( error ) 1429*37da2899SCharles.Forsyth error = face->goto_table( face, TTAG_bdat, stream, 0 ); 1430*37da2899SCharles.Forsyth if (error) 1431*37da2899SCharles.Forsyth goto Exit; 1432*37da2899SCharles.Forsyth 1433*37da2899SCharles.Forsyth ebdt_pos = FT_STREAM_POS(); 1434*37da2899SCharles.Forsyth 1435*37da2899SCharles.Forsyth /* clear the bitmap & load the bitmap */ 1436*37da2899SCharles.Forsyth if ( face->root.glyph->flags & FT_GLYPH_OWN_BITMAP ) 1437*37da2899SCharles.Forsyth FT_FREE( map->buffer ); 1438*37da2899SCharles.Forsyth 1439*37da2899SCharles.Forsyth map->rows = map->pitch = map->width = 0; 1440*37da2899SCharles.Forsyth 1441*37da2899SCharles.Forsyth error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset, 1442*37da2899SCharles.Forsyth map, 0, 0, stream, metrics ); 1443*37da2899SCharles.Forsyth if ( error ) 1444*37da2899SCharles.Forsyth goto Exit; 1445*37da2899SCharles.Forsyth 1446*37da2899SCharles.Forsyth /* the glyph slot owns this bitmap buffer */ 1447*37da2899SCharles.Forsyth face->root.glyph->flags |= FT_GLYPH_OWN_BITMAP; 1448*37da2899SCharles.Forsyth 1449*37da2899SCharles.Forsyth /* setup vertical metrics if needed */ 1450*37da2899SCharles.Forsyth if ( strike->flags & 1 ) 1451*37da2899SCharles.Forsyth { 1452*37da2899SCharles.Forsyth /* in case of a horizontal strike only */ 1453*37da2899SCharles.Forsyth FT_Int advance; 1454*37da2899SCharles.Forsyth 1455*37da2899SCharles.Forsyth 1456*37da2899SCharles.Forsyth advance = strike->hori.ascender - strike->hori.descender; 1457*37da2899SCharles.Forsyth 1458*37da2899SCharles.Forsyth /* some heuristic values */ 1459*37da2899SCharles.Forsyth 1460*37da2899SCharles.Forsyth metrics->vertBearingX = (FT_Char)(-metrics->width / 2 ); 1461*37da2899SCharles.Forsyth metrics->vertBearingY = (FT_Char)( advance / 10 ); 1462*37da2899SCharles.Forsyth metrics->vertAdvance = (FT_Char)( advance * 12 / 10 ); 1463*37da2899SCharles.Forsyth } 1464*37da2899SCharles.Forsyth 1465*37da2899SCharles.Forsyth /* Crop the bitmap now, unless specified otherwise */ 1466*37da2899SCharles.Forsyth if ( load_flags & FT_LOAD_CROP_BITMAP ) 1467*37da2899SCharles.Forsyth crop_bitmap( map, metrics ); 1468*37da2899SCharles.Forsyth 1469*37da2899SCharles.Forsyth Exit: 1470*37da2899SCharles.Forsyth return error; 1471*37da2899SCharles.Forsyth } 1472*37da2899SCharles.Forsyth 1473*37da2899SCharles.Forsyth 1474*37da2899SCharles.Forsyth /* END */ 1475