📄 ftxsbit.c
字号:
/******************************************************************* * * 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -