📄 ttsbit.c
字号:
/***************************************************************************/
/* */
/* ttsbit.c */
/* */
/* TrueType and OpenType embedded bitmap support (body). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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 <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TAGS_H
/*
* Alas, the memory-optimized sbit loader can't be used when implementing
* the `old internals' hack
*/
#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
#include "ttsbit0.c"
#else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TAGS_H
#include "ttsbit.h"
#include "sferrors.h"
/*************************************************************************/
/* */
/* 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_UInt 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 = (FT_Byte)( x_offset & 7 ); /* current write shift */
FT_Byte space = (FT_Byte)( 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)((FT_UShort)*source++ << ( 8 - loaded ));
loaded += 8;
}
/* now write one byte */
val = (FT_Byte)( acc >> 8 );
if ( shift )
{
cur[0] |= (FT_Byte)( val >> shift );
cur[1] |= (FT_Byte)( 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 ( (FT_Int)loaded < count )
{
acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
loaded += 8;
}
/* now write remaining bits */
val = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) );
cur[0] |= (FT_Byte)( val >> shift );
if ( count > space )
cur[1] |= (FT_Byte)( val << space );
acc <<= count;
loaded -= count;
}
/* now, skip to next line */
if ( byte_padded )
{
acc = 0;
loaded = 0; /* clear accumulator on byte-padded lines */
}
line_buff += line_incr;
}
}
static const FT_Frame_Field sbit_metrics_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE TT_SBit_MetricsRec
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> */
/* 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 ( FT_READ_ULONG( range->image_size ) )
return error;
return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics );
}
/*************************************************************************/
/* */
/* <Function> */
/* 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 ( FT_READ_ULONG( count ) )
goto Exit;
range->num_glyphs = count;
/* Allocate glyph offsets table if needed */
if ( load_offsets )
{
if ( FT_NEW_ARRAY( range->glyph_offsets, count ) )
goto Exit;
size = count * 4L;
}
else
size = count * 2L;
/* Allocate glyph codes table and access frame */
if ( FT_NEW_ARRAY ( range->glyph_codes, count ) ||
FT_FRAME_ENTER( size ) )
goto Exit;
for ( n = 0; n < count; n++ )
{
range->glyph_codes[n] = FT_GET_USHORT();
if ( load_offsets )
range->glyph_offsets[n] = (FT_ULong)range->image_offset +
FT_GET_USHORT();
}
FT_FRAME_EXIT();
Exit:
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* 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 = FT_BOOL( range->index_format == 1 );
if ( range->last_glyph < range->first_glyph )
{
error = SFNT_Err_Invalid_File_Format;
goto Exit;
}
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 ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) ||
FT_FRAME_ENTER( num_glyphs * size_elem ) )
goto Exit;
for ( n = 0; n < num_glyphs; n++ )
range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
( large ? FT_GET_ULONG()
: FT_GET_USHORT() ) );
FT_FRAME_EXIT();
}
break;
case 2: /* all glyphs have identical metrics */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -