diff options
Diffstat (limited to 'Build/source/libs/libttf/extend/ftxsbit.c')
-rw-r--r-- | Build/source/libs/libttf/extend/ftxsbit.c | 1391 |
1 files changed, 1391 insertions, 0 deletions
diff --git a/Build/source/libs/libttf/extend/ftxsbit.c b/Build/source/libs/libttf/extend/ftxsbit.c new file mode 100644 index 00000000000..02162bd2e3f --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxsbit.c @@ -0,0 +1,1391 @@ +/******************************************************************* + * + * ftxsbit.c + * + * Embedded bitmap API extension + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * This extension is used to load the embedded bitmaps present + * in certain TrueType files. + * + ******************************************************************/ + +#include "ftxsbit.h" +#include "ttobjs.h" +#include "ttfile.h" +#include "ttload.h" +#include "ttmemory.h" +#include "tttags.h" +#include "ttextend.h" +#include "ttdebug.h" + + +#define SBIT_ID Build_Extension_ID( 's', 'b', 'i', 't' ) + + +/* Required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_bitmap + +/* In all functions, the stream is taken from the 'face' object */ +#define DEFINE_LOCALS DEFINE_LOAD_LOCALS( face->stream ) +#define DEFINE_LOCALS_WO_FRAME DEFINE_LOAD_LOCALS_WO_FRAME( face->stream ) + + +/*************************** + * + * miscellaneous functions + * + ***************************/ + +/******************************************************************* + * + * Function: Load_BitmapData + * + * Bit-aligned bitmap data -> Byte-aligned bitmap data when pad is 0 + * + ******************************************************************/ + + static + TT_Error Load_BitmapData( TT_SBit_Image* image, + Int image_size, + Byte x_offset, + Byte y_offset, + UShort source_width, + UShort source_height, + Bool byte_padded ) + { + DEFINE_LOCALS; + + Int count; /* number of bits left in rows */ + Int loaded; /* number of bits loaded in the accumulator */ + UShort buff; /* accumulator */ + + PByte line; /* target write cursor */ + PByte limit; + + + if ( ( y_offset + source_height > image->map.rows ) || + ( x_offset + source_width > image->map.width ) ) + return TT_Err_Invalid_Argument; + + if ( ACCESS_Frame( image_size ) ) + return error; + + buff = 0; + loaded = 0; + line = (PByte)image->map.bitmap + + y_offset * image->map.cols; + limit = (PByte)image->map.bitmap + + ( y_offset + source_height ) * image->map.cols; + + for ( ; line < limit; line += image->map.cols ) + { + PByte ptr; + + + ptr = line + x_offset / 8; + count = source_width; + + /* We may assume that `loaded' is less than 8 */ + buff >>= x_offset % 8; + loaded += x_offset % 8; + + /* first of all, read all consecutive bytes */ + while ( count >= 8 ) + { + if ( loaded < 8 ) + { + buff |= ((UShort)GET_Byte()) << (8 - loaded); + loaded += 8; + } + + *ptr++ |= (Byte)(buff >> 8); + buff <<= 8; + loaded -= 8; + count -= 8; + } + + /* now write remaining bits (i.e. end of line with count < 8) */ + if ( count > 0 ) + { + if ( loaded < count ) + { + buff |= ((UShort)GET_Byte()) << (8 - loaded); + loaded += 8; + } + + *ptr |= ((Byte)(buff >> 8)) & ~(0xFF >> count); + buff <<= count; + loaded -= count; + } + + if ( byte_padded ) + { + buff = 0; + loaded = 0; + } + } + + FORGET_Frame(); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function: Crop_Bitmap + * + ******************************************************************/ + + static + void Crop_Bitmap( TT_SBit_Image* image ) + { + /*******************************************************/ + /* In the following situation, some bounding boxes of */ + /* embedded bitmaps are too large. We need to crop it */ + /* to a reasonable size. */ + /* */ + /* --------- */ + /* | | ----- */ + /* | *** | |***| */ + /* | * | -----> | * | */ + /* | * | | * | */ + /* | * | | * | */ + /* | * | | * | */ + /* | *** | |***| */ + /* --------- ----- */ + /* */ + /*******************************************************/ + + Int rows, count; + Long line_len; + PByte line; + + + /********************************************************************/ + /* */ + /* first of all, check the top-most lines of the bitmap and remove */ + /* them if they're empty. */ + /* */ + { + line = (PByte)image->map.bitmap; + rows = image->map.rows; + line_len = image->map.cols; + + for ( count = 0; count < rows; count++ ) + { + PByte cur = line; + PByte limit = line + line_len; + + + for ( ; cur < limit; cur++ ) + if ( cur[0] ) + goto Found_Top; + + /* the current line was empty -- skip to next one */ + line = limit; + } + + Found_Top: + /* check that we have at least one filled line */ + if ( count >= rows ) + goto Empty_Bitmap; + + /* now, crop the empty upper lines */ + if ( count > 0 ) + { + line = (PByte)image->map.bitmap; + + MEM_Move( line, line + count*line_len, (rows-count) * line_len ); + + image->metrics.bbox.yMax -= count; + image->metrics.vertBearingY -= count; + image->metrics.horiBearingY -= count; + image->map.rows -= count; + rows -= count; + } + } + + /*******************************************************************/ + /* */ + /* second, crop the lower lines */ + /* */ + { + line = (PByte)image->map.bitmap + (rows-1) * line_len; + + for ( count = 0; count < rows; count++ ) + { + PByte cur = line; + PByte limit = line + line_len; + + + for ( ; cur < limit; cur++ ) + if ( cur[0] ) + goto Found_Bottom; + + /* the current line was empty -- skip to previous one */ + line -= line_len; + } + + Found_Bottom: + if ( count > 0 ) + { + image->metrics.bbox.yMin += count; + image->map.rows -= count; + rows -= count; + } + } + + /*******************************************************************/ + /* */ + /* third, get rid of the space on the left side of the glyph */ + /* */ + do + { + PByte limit; + + + line = (PByte)image->map.bitmap; + limit = line + rows * line_len; + + for ( ; line < limit; line += line_len ) + if ( line[0] & 0x80 ) + goto Found_Left; + + /* shift the whole glyph one pixel to the left */ + line = (PByte)image->map.bitmap; + limit = line + rows * line_len; + + for ( ; line < limit; line += line_len ) + { + Int n, width = image->map.width; + Byte old; + PByte cur = line; + + + old = cur[0] << 1; + + for ( n = 8; n < width; n += 8 ) + { + Byte val; + + + val = cur[1]; + cur[0] = old | (val >> 7); + old = val << 1; + cur++; + } + cur[0] = old; + } + + image->map.width--; + image->metrics.horiBearingX++; + image->metrics.vertBearingX++; + image->metrics.bbox.xMin++; + + } while ( image->map.width > 0 ); + + Found_Left: + + /*********************************************************************/ + /* */ + /* finally, crop the bitmap width to get rid of the space on the */ + /* right side of the glyph. */ + /* */ + do + { + Int right = image->map.width-1; + PByte limit; + Byte mask; + + + line = (PByte)image->map.bitmap + (right >> 3); + limit = line + rows*line_len; + mask = 0x80 >> (right & 7); + + for ( ; line < limit; line += line_len ) + if ( line[0] & mask ) + goto Found_Right; + + /* crop the whole glyph on the right */ + image->map.width--; + image->metrics.bbox.xMax--; + + } while ( image->map.width > 0 ); + + Found_Right: + /* all right, the bitmap was cropped */ + return; + + Empty_Bitmap: + image->map.width = 0; + image->map.rows = 0; + image->map.cols = 0; + image->map.size = 0; + } + +/************* + * + * Main body + * + *************/ + + + static + TT_Error Load_Range_Codes( TT_SBit_Range* range, + PFace face, + Bool load_offsets ) + { + DEFINE_LOCALS; + + ULong count, n, size; + + + (void)face; + + /* read glyph count */ + if ( ACCESS_Frame( 4L ) ) + goto Exit; + count = GET_ULong(); + FORGET_Frame(); + + range->num_glyphs = count; + + /* Allocate glyph offsets table if needed */ + if ( load_offsets ) + { + if ( ALLOC_ARRAY( range->glyph_offsets, count, ULong ) ) + goto Exit; + + size = count * 4L; + } + else + size = count * 2L; + + /* Allocate glyph codes table and access frame */ + if ( ALLOC_ARRAY ( range->glyph_codes, count, UShort ) || + ACCESS_Frame( size ) ) + goto Exit; + + for ( n = 0; n < count; n++ ) + { + range->glyph_codes[n] = GET_UShort(); + + if ( load_offsets ) + range->glyph_offsets[n] = (ULong)range->image_offset + GET_UShort(); + } + + FORGET_Frame(); + + Exit: + return error; + } + + + static + TT_Error Load_SBit_Range( TT_SBit_Strike* strike, + TT_SBit_Range* range, + PFace face ) + { + DEFINE_LOCALS; + + UShort format; + + + (void)face; + (void)strike; + + format = range->index_format; + PTRACE6(( "Index Format: %d\n", format )); + + switch( format ) + { + case 1: /* variable metrics with 4-byte offsets */ + case 3: /* variable metrics with 2-byte offsets */ + { + UShort num_glyphs, size_elem; + Bool large = (format == 1); + ULong* cur; + + num_glyphs = range->last_glyph - range->first_glyph + 1; + PTRACE5(( " num glyphs: %hu\n", num_glyphs )); + + range->num_glyphs = num_glyphs; + + num_glyphs++; /* BEWARE */ + + size_elem = large ? 4 : 2; + + if ( ALLOC_ARRAY( range->glyph_offsets, num_glyphs, ULong ) || + ACCESS_Frame( num_glyphs * size_elem ) ) + return error; + + cur = range->glyph_offsets; + + while ( num_glyphs > 0 ) + { + cur[0] = (TT_ULong)( range->image_offset + + (large ? GET_ULong() : GET_UShort()) ); + PTRACE7(( " offset: %d\n", cur[0] )); + cur++; + num_glyphs--; + } + + FORGET_Frame(); + } + break; + + case 2: /* all glyphs have identical metrics */ + case 4: + case 5: + { + error = 0; + + if ( format != 4 ) /* read constant metrics, formats 2 and 5 */ + { + TT_SBit_Metrics* metrics; + + + if ( ACCESS_Frame( 12L ) ) + return error; + + range->image_size = GET_ULong(); + metrics = &range->metrics; + + metrics->height = GET_Byte(); + metrics->width = GET_Byte(); + + metrics->horiBearingX = GET_Char(); + metrics->horiBearingY = GET_Char(); + metrics->horiAdvance = GET_Byte(); + + metrics->vertBearingX = GET_Char(); + metrics->vertBearingY = GET_Char(); + metrics->vertAdvance = GET_Byte(); + + FORGET_Frame(); + } + + if ( format != 2 ) /* load range codes, formats 4 and 5 */ + error = Load_Range_Codes( range, face, (format == 4) ); + } + break; + + default: + error = TT_Err_Invalid_File_Format; + } + + PTRACE3(( "Embedded Bitmap Location Tables loaded.\n" )); + + return error; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Eblc + * + * Description : Loads the Eblc table directory into face table. + * + * Input : face face record to look for + * + * Output : Error code. + * + ******************************************************************/ + + static + TT_Error Load_TrueType_Eblc( PFace face, + TT_EBLC* eblc ) + { + DEFINE_LOCALS; + + ULong eblc_offset; + UShort i; + Long table; + + TT_SBit_Strike* strike; + + + PTRACE2(( "Load_EBLC_Table( %08lx )\n", (long)face )); + + eblc->version = 0; + + /* Try to find the `EBLC' or `bloc' table in the font files. */ + /* Both tags describe the same table; `EBLC' is for OpenType */ + /* fonts while `bloc' is for TrueType GX fonts. Many fonts */ + /* contain both tags pointing to the same table. */ + + table = TT_LookUp_Table( face, TTAG_EBLC ); + if ( table < 0 ) + table = TT_LookUp_Table( face, TTAG_bloc ); + + if ( table < 0 ) + /* This table is optional */ + return TT_Err_Ok; + + eblc_offset = face->dirTables[table].Offset; + + if ( FILE_Seek( eblc_offset ) || + ACCESS_Frame( 8L ) ) + return error; + + eblc->version = GET_ULong(); + eblc->num_strikes = GET_ULong(); + + FORGET_Frame(); + + PTRACE2(( "-- Tables count: %12u\n", eblc->num_strikes )); + PTRACE2(( "-- Format version: %08lx\n", eblc->version )); + + if ( eblc->version != 0x00020000 ) + { + PERROR(( "Invalid file format!\n" )); + return TT_Err_Invalid_File_Format; + } + + if ( ALLOC_ARRAY( eblc->strikes, eblc->num_strikes, TT_SBit_Strike ) || + ACCESS_Frame( 48L * eblc->num_strikes ) ) + return error; + + strike = eblc->strikes; + + for ( i = 0; i < eblc->num_strikes; i++, strike++ ) + { /* loop through the tables and get all entries */ + ULong indexTablesSize; + TT_SBit_Line_Metrics* metrics; + Int count; + + + strike->ranges_offset = GET_ULong(); + indexTablesSize = GET_ULong(); /* dont' save */ + + strike->num_ranges = GET_ULong(); + strike->color_ref = GET_ULong(); + + /* load horizontal and vertical metrics */ + metrics = &strike->hori; + for ( count = 2; count > 0; count-- ) + { + metrics->ascender = GET_Char(); + metrics->descender = GET_Char(); + metrics->max_width = GET_Byte(); + + metrics->caret_slope_numerator = GET_Char(); + metrics->caret_slope_denominator = GET_Char(); + metrics->caret_offset = GET_Char(); + + metrics->min_origin_SB = GET_Char(); + metrics->min_advance_SB = GET_Char(); + metrics->max_before_BL = GET_Char(); + metrics->min_after_BL = GET_Char(); + metrics->pads[0] = GET_Char(); + metrics->pads[1] = GET_Char(); + + metrics = &strike->vert; + } + + strike->start_glyph = GET_UShort(); + strike->end_glyph = GET_UShort(); + strike->x_ppem = GET_Byte(); + strike->y_ppem = GET_Byte(); + strike->bit_depth = GET_Byte(); + strike->flags = GET_Char(); + + PTRACE4(( " start - end - ppemX - ppemY\n" )); + PTRACE4(( " %04d - %04d - %3u - %3u\n", + strike->start_glyph, + strike->end_glyph, + strike->x_ppem, + strike->y_ppem )); + } + + FORGET_Frame(); + + /* Load EBLC index ranges */ + strike = eblc->strikes; + + for ( i = 0; i < eblc->num_strikes; i++, strike++ ) + { + TT_SBit_Range* range; + UShort count = strike->num_ranges; + + + /* loop through the tables and get all entries */ + if ( ALLOC_ARRAY( strike->sbit_ranges, + strike->num_ranges, + TT_SBit_Range ) || + FILE_Seek( eblc_offset + strike->ranges_offset ) || + ACCESS_Frame( strike->num_ranges * 8L ) ) + return error; + + for ( range = strike->sbit_ranges; count > 0; count--, range++ ) + { + range->first_glyph = GET_UShort(); + range->last_glyph = GET_UShort(); + range->table_offset = eblc_offset + strike->ranges_offset + + GET_ULong(); + } + FORGET_Frame(); + + /* Now, read each index table */ + range = strike->sbit_ranges; + for ( count = strike->num_ranges; count > 0; count--, range++ ) + { + /* Read the header */ + if ( FILE_Seek( range->table_offset ) || + ACCESS_Frame( 8L ) ) + return error;; + + range->index_format = GET_UShort(); + range->image_format = GET_UShort(); + range->image_offset = GET_ULong(); + + FORGET_Frame(); + + error = Load_SBit_Range( strike, range, face ); + if (error) return error; + } + } + + return TT_Err_Ok; + } + + + static + void Free_TrueType_Eblc( TT_EBLC* eblc ) + { + if ( eblc ) + { + ULong i; + TT_SBit_Strike* strike = eblc->strikes; + + + strike = eblc->strikes; + + for ( i = eblc->num_strikes; i > 0; i--, strike++ ) + { + /* for each strike, release all glyph ranges */ + TT_SBit_Range* range = strike->sbit_ranges; + Int n; + + + for ( n = strike->num_ranges; n > 0; n--, range++ ) + { + /* release a range */ + FREE( range->glyph_offsets ); + FREE( range->glyph_codes ); + } + FREE( strike->sbit_ranges ); + strike->num_ranges = 0; + } + FREE( eblc->strikes ); + eblc->num_strikes = 0; + eblc->version = 0; + } + } + + + static + TT_Error Load_SBit_Metrics( TT_Big_Glyph_Metrics* metrics, + TT_SBit_Range* range, + ULong ebdt_offset ) + { + TT_Error error; + Byte height, width; + + + /* copy bitmap metrics for formats 2 and 5 */ + if ( ( ( range->index_format == 2 ) || ( range->index_format == 5 ) ) && + ( range->image_format == 5 ) ) + /* metrics are taken from current image bitmap */ + /* i.e. from `image.metrics' */ + { + TT_SBit_Metrics* rmetrics = &range->metrics; + + + metrics->bbox.xMin = rmetrics->horiBearingX; + metrics->bbox.xMax = metrics->bbox.xMin + rmetrics->width; + + metrics->bbox.yMax = rmetrics->horiBearingY; + metrics->bbox.yMin = metrics->bbox.yMax - rmetrics->height; + + metrics->horiBearingX = rmetrics->horiBearingX; + metrics->horiBearingY = metrics->bbox.yMax; + metrics->horiAdvance = rmetrics->horiAdvance; + + metrics->vertBearingX = rmetrics->vertBearingX; + metrics->vertBearingY = rmetrics->vertBearingY; + metrics->vertAdvance = rmetrics->vertAdvance; + + return TT_Err_Ok; + } + + switch ( range->image_format ) + { + case 1: + case 2: + case 6: + case 7: + case 8: + case 9: + { + Long length = 5L; + + + if ( range->image_format == 8 ) + length++; + + /* read the small metrics */ + if ( ACCESS_Frame( length ) ) + return error; + + height = GET_Byte(); + width = GET_Byte(); + + metrics->horiBearingX = GET_Char(); + metrics->horiBearingY = GET_Char(); + metrics->horiAdvance = GET_Byte(); + + FORGET_Frame(); + + metrics->bbox.xMin = metrics->horiBearingX; + metrics->bbox.yMax = metrics->horiBearingY; + metrics->bbox.xMax = metrics->bbox.xMin + width; + metrics->bbox.yMin = metrics->bbox.yMax - height; + + /* read the rest of the big metrics for the formats */ + /* that support it. */ + if ( ( range->image_format >= 6 ) && ( range->image_format != 8 ) ) + { + if ( ACCESS_Frame( 3L ) ) + return error; + + metrics->vertBearingX = (Int)GET_Char(); + metrics->vertBearingY = (Int)GET_Char(); + metrics->vertAdvance = (Int)GET_Char(); + + FORGET_Frame(); + } + else + { + /* XXX: How can we fill these when the information isn't */ + /* available? */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + } + } + break; + + case 5: /* metrics are taken from current image bitmap */ + /* i.e. from 'image.metrics' */ + break; + + default: + PERROR(( "Unsupported embedded bitmap format!\n" )); + return TT_Err_Invalid_File_Format; + } + + return TT_Err_Ok; + } + + + static + TT_Error Load_SBit_Image( TT_SBit_Strike strike, + UShort glyph_index, + Byte x_offset, + Byte y_offset, + ULong ebdt_offset, + TT_SBit_Image* image, + UShort component_depth ) + { + TT_Error error; + Byte height, width; + + ULong bitmap_offset; + + TT_SBit_Range* range = 0; + + TT_Big_Glyph_Metrics metrics; + + /********************************************************************/ + /* */ + /* Scan the strike's range for the position/metrics of the source */ + /* glyph. */ + { + UShort count = strike.num_ranges; + TT_SBit_Range* cur = strike.sbit_ranges; + + for ( ; count > 0; count--, cur++ ) + { + /* look for the glyph in the current range */ + switch ( cur->index_format ) + { + case 1: + case 2: + case 3: + if ( glyph_index >= cur->first_glyph && + glyph_index <= cur->last_glyph ) + { + UShort delta = glyph_index - cur->first_glyph; + + + range = cur; + bitmap_offset = cur->index_format == 2 + ? cur->image_offset + cur->image_size * delta + : cur->glyph_offsets[delta]; + goto Found; + } + break; + + case 4: + case 5: + { + UShort n; + + + for ( n = 0; n < cur->num_glyphs; n++ ) + if ( cur->glyph_codes[n] == glyph_index ) + { + range = cur; + bitmap_offset = cur->index_format == 4 + ? cur->glyph_offsets[n] + : cur->image_offset + cur->image_size * n; + goto Found; + } + } + break; + + default: + return TT_Err_Invalid_Glyph_Index; + } + } + /* Not found */ + return TT_Err_Invalid_Glyph_Index; + } + + Found: + if ( FILE_Seek( ebdt_offset + bitmap_offset ) ) + return error; + + /* First of all, load the metrics if needed */ + error = Load_SBit_Metrics( &metrics, range, ebdt_offset ); + if ( error ) + return error; + + width = metrics.bbox.xMax - metrics.bbox.xMin; + height = metrics.bbox.yMax - metrics.bbox.yMin; + + if ( !component_depth ) + { + image->metrics = metrics; + + image->map.width = width; + image->map.rows = height; + + image->map.cols = (width + 7) >> 3; + image->map.size = height * image->map.cols; + + if ( REALLOC( image->map.bitmap, image->map.size ) ) + return error; + + MEM_Set( image->map.bitmap, 0, image->map.size ); + } + + /* Now, load the data as needed */ + switch ( range->image_format ) + { + case 1: + case 6: /* byte-aligned data */ + error = Load_BitmapData( image, + height * (( width + 7 ) >> 3), + x_offset, y_offset, + width, height, + 1 ); + if ( error ) + return error; + break; + + case 2: + case 5: + case 7: + error = Load_BitmapData( image, + (width * height + 7) >> 3, + x_offset, y_offset, + width, height, 0 ); + if ( error ) + return error; + break; + + case 8: + case 9: + { + /* Now, load composite sbit glyphs */ + /* This code is not sophisticated */ + + TT_SBit_Component* component_array; + UShort num_components; + + Int i = 0; + + + if ( ACCESS_Frame( 2L ) ) + return error; + num_components = GET_UShort(); + FORGET_Frame(); + + MEM_Alloc( component_array, + sizeof ( TT_SBit_Component ) * num_components ); + + if ( ACCESS_Frame( 4L * num_components ) ) + return error; + + for ( i = 0; i < num_components; i++ ) + { + component_array[i].glyph_code = GET_UShort(); + component_array[i].x_offset = GET_Char(); + component_array[i].y_offset = GET_Char(); + } + + FORGET_Frame(); + + component_depth++; + + for ( i = 0; i < num_components; i++ ) + { + error = Load_SBit_Image( strike, component_array[i].glyph_code, + component_array[i].x_offset, + component_array[i].y_offset, + ebdt_offset, + image, + component_depth ); + if ( error ) + return error; + } + FREE( component_array ); + break; + + default: + return TT_Err_Invalid_File_Format; + } + } + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function: Load_TrueType_Ebdt + * + ******************************************************************/ + + static + TT_Error Load_TrueType_Ebdt( PFace face, + TT_SBit_Strike strike, + ULong glyph_index, + TT_SBit_Image* image ) + { + DEFINE_LOCALS; + + ULong ebdt_offset; + ULong version; + Long i; + + + /* Try to find the `EBDT' or `bdat' table in the font files. */ + /* Both tags describe the same table, `EBDT' is for OpenType */ + /* fonts, while `bdat' is for TrueType GX fonts. Many fonts */ + /* contain both tags pointing to the same table */ + + i = TT_LookUp_Table( face, TTAG_EBDT ); + if ( i < 0 ) + i = TT_LookUp_Table( face, TTAG_bdat ); + + if ( i < 0 ) + return TT_Err_Table_Missing; + + ebdt_offset = face->dirTables[i].Offset; + + if ( FILE_Seek( ebdt_offset ) || + ACCESS_Frame( 4L ) ) /* read into frame */ + return error; + + version = GET_ULong(); + FORGET_Frame(); + + PTRACE2(( "-- Format version : %08lx\n", version )); + if ( version != 0x00020000 ) + { + PERROR(( "Invalid file format!\n" )); + return TT_Err_Invalid_File_Format; + } + + /* This doesn't compile, I simply commented it out ?? - David */ + /* PTRACE4(( "-- Format: %d\n", range->image_format )); */ + + error = Load_SBit_Image( strike, + glyph_index, + 0, 0, + ebdt_offset, + image, + 0 ); + if ( error ) + return error; + + return TT_Err_Ok; + } + + + static TT_Error EBLC_Create( void* ext, + PFace face ) + { + TT_EBLC* eblc = (TT_EBLC*)ext; + + + /* by convention */ + if ( !eblc ) + return TT_Err_Ok; + + return Load_TrueType_Eblc( face, eblc ); + } + + + static TT_Error EBLC_Destroy( void* ext, + PFace face ) + { + TT_EBLC* eblc = (TT_EBLC*)ext; + + + (void)face; + + if ( eblc ) + Free_TrueType_Eblc( eblc ); + + return TT_Err_Ok; + } + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Init_SBit_Extension */ + /* */ + /* <Description> */ + /* Initialize the embedded bitmaps extension for the */ + /* FreeType engine. */ + /* */ + /* <Input> */ + /* engine :: handle to current FreeType library instance */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + TT_Error TT_Init_SBit_Extension( TT_Engine engine ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + + TT_Error error; + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + error = TT_Register_Extension( _engine, + SBIT_ID, + sizeof ( TT_EBLC ), + EBLC_Create, + EBLC_Destroy ); + + return error; + } + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Get_Face_Bitmaps */ + /* */ + /* <Description> */ + /* Loads the `EBLC' table from a font file, if any. */ + /* */ + /* <Input> */ + /* face :: handle to the source TrueType font/face */ + /* */ + /* <Output> */ + /* eblc_table :: a descriptor for the EBLC table */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function returns TT_Err_Table_Missing if the */ + /* font contains no embedded bitmaps. All fields in */ + /* `eblc_table' will then be set to 0. */ + /* */ + EXPORT_FUNC + TT_Error TT_Get_Face_Bitmaps( TT_Face face, + TT_EBLC* eblc_table ) + { + PFace faze = HANDLE_Face( face ); + TT_EBLC* eblc; + TT_Error error; + + + error = TT_Extension_Get( faze, SBIT_ID, (void**)&eblc ); + if ( !error ) + { + if ( eblc->version ) + { + *eblc_table = *eblc; + return TT_Err_Ok; + } + error = TT_Err_Table_Missing; + } + + eblc_table->version = 0; + eblc_table->num_strikes = 0; + eblc_table->strikes = 0; + + return error; + } + + +/******************************************************************* + * + * <Function> TT_Get_SBit_Strike + * + * <Description> + * Loads suitable strike (bitmap sizetable) for given instance. + * This strike includes sbitLineMetrics. + * + * <Input> + * face :: the source face + * instance :: the current size instance + * + * <Output> + * strike :: the bitmap strike descriptor + * + * <Return> + * TrueType error code. 0 means success. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_SBit_Strike( TT_Face face, + TT_Instance instance, + TT_SBit_Strike* strike ) + { + TT_Error error; + PFace faze = HANDLE_Face( face ); + PInstance ins = HANDLE_Instance( instance ); + + TT_EBLC* eblc; + TT_Int x_ppem, y_ppem; + + + if ( !strike || !ins || ins->owner != faze ) + return TT_Err_Invalid_Argument; + + error = TT_Extension_Get( faze, SBIT_ID, (void**)&eblc ); + if ( error ) + goto Exit; + + /********************************************************************/ + /* */ + /* Look for an sbit strike that matches the current x and y ppms */ + /* */ + { + UShort count = eblc->num_strikes; + TT_SBit_Strike* cur = eblc->strikes; + + + x_ppem = ins->metrics.x_ppem; + y_ppem = ins->metrics.y_ppem; + + MEM_Set( strike, 0, sizeof ( TT_SBit_Strike ) ); + + for ( ; count > 0; count--, cur++ ) + if ( cur->x_ppem == x_ppem && + cur->y_ppem == y_ppem ) + { + *strike = *cur; + break; + } + + /* return immediately if we didn't find an appropriate strike */ + if ( !strike->num_ranges ) + error = TT_Err_Invalid_PPem; + } + + Exit: + return error; + } + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Load_Glyph_Bitmap */ + /* */ + /* <Description> */ + /* Loads a given glyph embedded bitmap. */ + /* */ + /* <Input> */ + /* face :: handle to the source TrueType font/face */ + /* instance :: current size/transform instance */ + /* glyph_index :: index of source glyph */ + /* bitmap :: target embedded bitmap descriptor */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function returns an error if there is no */ + /* embedded bitmap for the glyph at the given */ + /* instance. */ + /* */ + EXPORT_FUNC + TT_Error TT_Load_Glyph_Bitmap( TT_Face face, + TT_Instance instance, + TT_UShort glyph_index, + TT_SBit_Image* image ) + { + TT_Stream stream; + TT_Error error; + + PFace faze = HANDLE_Face( face ); + PInstance ins = HANDLE_Instance( instance ); + + TT_SBit_Strike strike; + + + if ( ins->owner != faze ) + { + error = TT_Err_Invalid_Argument; + goto Fail; + } + + /********************************************************************/ + /* */ + /* Look for an sbit strike that matches the current x and y ppms */ + /* */ + error = TT_Get_SBit_Strike( face, instance, &strike ); + if ( error ) + goto Fail; + + /* return immediately if the glyph index isn't in the strike extent */ + if ( glyph_index < strike.start_glyph || + glyph_index > strike.end_glyph ) + { + error = TT_Err_Invalid_Glyph_Index; + goto Fail; + } + + { + image->bit_depth = 1; + + if ( !USE_Stream( faze->stream, stream ) ) + { + error = Load_TrueType_Ebdt( faze, strike, glyph_index, image ); + + DONE_Stream( stream ); + + /* exit successfully if we can */ + if ( !error ) + { + image->map.flow = TT_Flow_Down; + + Crop_Bitmap( image ); + + /* correct sbit metrics */ + { + TT_Big_Glyph_Metrics* metrics = &image->metrics; + + + metrics->bbox.xMin *= 64; + metrics->bbox.xMax *= 64; + + metrics->bbox.yMax *= 64; + metrics->bbox.yMin *= 64; + + metrics->horiBearingX *= 64; + metrics->horiBearingY *= 64; + metrics->horiAdvance *= 64; + + metrics->vertBearingX *= 64; + metrics->vertBearingY *= 64; + metrics->vertAdvance *= 64; + } + + goto Exit; + } + } + } + + Fail: + image->map.width = 0; + image->map.rows = 0; + image->map.cols = 0; + image->map.size = 0; + image->map.bitmap = 0; + image->map.flow = 0; + image->bit_depth = 0; + + Exit: + return error; + } + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_New_SBit_Image */ + /* */ + /* <Description> */ + /* Allocates a new embedded bitmap container. */ + /* */ + /* <Output> */ + /* image :: sbit image */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + TT_Error TT_New_SBit_Image( TT_SBit_Image** image ) + { + return MEM_Alloc( *image, sizeof ( **image ) ); + } + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Done_SBit_Image */ + /* */ + /* <Description> */ + /* Releases an embedded bitmap container. */ + /* */ + /* <Input> */ + /* image :: sbit image */ + /* */ + EXPORT_FUNC + void TT_Done_SBit_Image( TT_SBit_Image* image ) + { + FREE( image->map.bitmap ); + FREE( image ); + } + + +/* END */ |