📄 ttsbit.c
字号:
/***************************************************************************//* *//* ttsbit.c *//* *//* TrueType and OpenType embedded bitmap support (body). *//* *//* Copyright 1996-2000 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. *//* *//***************************************************************************/#include <freetype/internal/ftdebug.h>#include <freetype/internal/tterrors.h>#include <freetype/internal/ftstream.h>#include <freetype/tttags.h>#ifdef FT_FLAT_COMPILE#include "ttsbit.h"#else#include <sfnt/ttsbit.h>#endif /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ /* messages during execution. */ /* */#undef FT_COMPONENT#define FT_COMPONENT trace_ttsbit /*************************************************************************/ /* */ /* <Function> */ /* blit_sbit */ /* */ /* <Description> */ /* Blits a bitmap from an input stream into a given target. Supports */ /* x and y offsets as well as byte padded lines. */ /* */ /* <Input> */ /* target :: The target bitmap/pixmap. */ /* */ /* source :: The input packed bitmap data. */ /* */ /* line_bits :: The number of bits per line. */ /* */ /* byte_padded :: A flag which is true if lines are byte-padded. */ /* */ /* x_offset :: The horizontal offset. */ /* */ /* y_offset :: The vertical offset. */ /* */ /* <Note> */ /* IMPORTANT: The x and y offsets are relative to the top corner of */ /* the target bitmap (unlike the normal TrueType */ /* convention). A positive y offset indicates a downwards */ /* direction! */ /* */ 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 ) { FT_Byte* line_buff; FT_Int line_incr; FT_Int height; FT_UShort acc; FT_Byte loaded; /* first of all, compute starting write position */ line_incr = target->pitch; line_buff = target->buffer; if ( line_incr < 0 ) line_buff -= line_incr * ( target->rows - 1 ); line_buff += ( x_offset >> 3 ) + y_offset * line_incr; /***********************************************************************/ /* */ /* We use the extra-classic `accumulator' trick to extract the bits */ /* from the source byte stream. */ /* */ /* Namely, the variable `acc' is a 16-bit accumulator containing the */ /* last `loaded' bits from the input stream. The bits are shifted to */ /* the upmost position in `acc'. */ /* */ /***********************************************************************/ acc = 0; /* clear accumulator */ loaded = 0; /* no bits were loaded */ for ( height = target->rows; height > 0; height-- ) { FT_Byte* cur = line_buff; /* current write cursor */ FT_Int count = line_bits; /* # of bits to extract per line */ FT_Byte shift = x_offset & 7; /* current write shift */ FT_Byte space = 8 - shift; /* first of all, read individual source bytes */ if ( count >= 8 ) { count -= 8; { do { FT_Byte val; /* ensure that there are at least 8 bits in the accumulator */ if ( loaded < 8 ) { acc |= (FT_UShort)*source++ << ( 8 - loaded ); loaded += 8; } /* now write one byte */ val = (FT_Byte)( acc >> 8 ); if ( shift ) { cur[0] |= val >> shift; cur[1] |= val << space; } else cur[0] |= val; cur++; acc <<= 8; /* remove bits from accumulator */ loaded -= 8; count -= 8; } while ( count >= 0 ); } /* restore `count' to correct value */ count += 8; } /* now write remaining bits (count < 8) */ if ( count > 0 ) { FT_Byte val; /* ensure that there are at least `count' bits in the accumulator */ if ( loaded < count ) { acc |= (FT_UShort)*source++ << ( 8 - loaded ); loaded += 8; } /* now write remaining bits */ val = ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ); cur[0] |= val >> shift; if ( count > space ) cur[1] |= val << space; acc <<= count; loaded -= count; } /* now, skip to next line */ if ( byte_padded ) acc = loaded = 0; /* clear accumulator on byte-padded lines */ line_buff += line_incr; } } const FT_Frame_Field sbit_metrics_fields[] = {#undef FT_STRUCTURE#define FT_STRUCTURE TT_SBit_Metrics FT_FRAME_START( 8 ), FT_FRAME_BYTE( height ), FT_FRAME_BYTE( width ), FT_FRAME_CHAR( horiBearingX ), FT_FRAME_CHAR( horiBearingY ), FT_FRAME_BYTE( horiAdvance ), FT_FRAME_CHAR( vertBearingX ), FT_FRAME_CHAR( vertBearingY ), FT_FRAME_BYTE( vertAdvance ), FT_FRAME_END }; /*************************************************************************/ /* */ /* <Function> */ /* TT_Load_SBit_Const_Metrics */ /* */ /* <Description> */ /* Loads the metrics for `EBLC' index tables format 2 and 5. */ /* */ /* <Input> */ /* range :: The target range. */ /* */ /* stream :: The input stream. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ static FT_Error Load_SBit_Const_Metrics( TT_SBit_Range* range, FT_Stream stream ) { FT_Error error; if ( READ_ULong( range->image_size ) ) return error; return READ_Fields( sbit_metrics_fields, &range->metrics ); } /*************************************************************************/ /* */ /* <Function> */ /* TT_Load_SBit_Range_Codes */ /* */ /* <Description> */ /* Loads the range codes for `EBLC' index tables format 4 and 5. */ /* */ /* <Input> */ /* range :: The target range. */ /* */ /* stream :: The input stream. */ /* */ /* load_offsets :: A flag whether to load the glyph offset table. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ static FT_Error Load_SBit_Range_Codes( TT_SBit_Range* range, FT_Stream stream, FT_Bool load_offsets ) { FT_Error error; FT_ULong count, n, size; FT_Memory memory = stream->memory; if ( READ_ULong( count ) ) goto Exit; range->num_glyphs = count; /* Allocate glyph offsets table if needed */ if ( load_offsets ) { if ( ALLOC_ARRAY( range->glyph_offsets, count, FT_ULong ) ) goto Exit; size = count * 4L; } else size = count * 2L; /* Allocate glyph codes table and access frame */ if ( ALLOC_ARRAY ( range->glyph_codes, count, FT_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] = (FT_ULong)range->image_offset + GET_UShort(); } FORGET_Frame(); Exit: return error; } /*************************************************************************/ /* */ /* <Function> */ /* TT_Load_SBit_Range */ /* */ /* <Description> */ /* Loads a given `EBLC' index/range table. */ /* */ /* <Input> */ /* range :: The target range. */ /* */ /* stream :: The input stream. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ static FT_Error Load_SBit_Range( TT_SBit_Range* range, FT_Stream stream ) { FT_Error error; FT_Memory memory = stream->memory; switch( range->index_format ) { case 1: /* variable metrics with 4-byte offsets */ case 3: /* variable metrics with 2-byte offsets */ { FT_ULong num_glyphs, n; FT_Int size_elem; FT_Bool large = ( range->index_format == 1 ); num_glyphs = range->last_glyph - range->first_glyph + 1L; range->num_glyphs = num_glyphs; num_glyphs++; /* XXX: BEWARE - see spec */ size_elem = large ? 4 : 2; if ( ALLOC_ARRAY( range->glyph_offsets, num_glyphs, FT_ULong ) || ACCESS_Frame( num_glyphs * size_elem ) ) goto Exit; for ( n = 0; n < num_glyphs; n++ ) range->glyph_offsets[n] = (FT_ULong)( range->image_offset + ( large ? GET_ULong() : GET_UShort() ) ); FORGET_Frame(); } break; case 2: /* all glyphs have identical metrics */ error = Load_SBit_Const_Metrics( range, stream ); break; case 4: error = Load_SBit_Range_Codes( range, stream, 1 ); break; case 5: error = Load_SBit_Const_Metrics( range, stream ) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -