📄 pshrec.c
字号:
/***************************************************************************/
/* */
/* pshrec.c */
/* */
/* FreeType PostScript hints recorder (body). */
/* */
/* Copyright 2001, 2002, 2003, 2004 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_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include "pshrec.h"
#include "pshalgo.h"
#include "pshnterr.h"
#undef FT_COMPONENT
#define FT_COMPONENT trace_pshrec
#ifdef DEBUG_HINTER
PS_Hints ps_debug_hints = 0;
int ps_debug_no_horz_hints = 0;
int ps_debug_no_vert_hints = 0;
#endif
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** PS_HINT MANAGEMENT *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* destroy hints table */
static void
ps_hint_table_done( PS_Hint_Table table,
FT_Memory memory )
{
FT_FREE( table->hints );
table->num_hints = 0;
table->max_hints = 0;
}
/* ensure that a table can contain "count" elements */
static FT_Error
ps_hint_table_ensure( PS_Hint_Table table,
FT_UInt count,
FT_Memory memory )
{
FT_UInt old_max = table->max_hints;
FT_UInt new_max = count;
FT_Error error = 0;
if ( new_max > old_max )
{
/* try to grow the table */
new_max = FT_PAD_CEIL( new_max, 8 );
if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) )
table->max_hints = new_max;
}
return error;
}
static FT_Error
ps_hint_table_alloc( PS_Hint_Table table,
FT_Memory memory,
PS_Hint *ahint )
{
FT_Error error = 0;
FT_UInt count;
PS_Hint hint = 0;
count = table->num_hints;
count++;
if ( count >= table->max_hints )
{
error = ps_hint_table_ensure( table, count, memory );
if ( error )
goto Exit;
}
hint = table->hints + count - 1;
hint->pos = 0;
hint->len = 0;
hint->flags = 0;
table->num_hints = count;
Exit:
*ahint = hint;
return error;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** PS_MASK MANAGEMENT *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* destroy mask */
static void
ps_mask_done( PS_Mask mask,
FT_Memory memory )
{
FT_FREE( mask->bytes );
mask->num_bits = 0;
mask->max_bits = 0;
mask->end_point = 0;
}
/* ensure that a mask can contain "count" bits */
static FT_Error
ps_mask_ensure( PS_Mask mask,
FT_UInt count,
FT_Memory memory )
{
FT_UInt old_max = ( mask->max_bits + 7 ) >> 3;
FT_UInt new_max = ( count + 7 ) >> 3;
FT_Error error = 0;
if ( new_max > old_max )
{
new_max = FT_PAD_CEIL( new_max, 8 );
if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) )
mask->max_bits = new_max * 8;
}
return error;
}
/* test a bit value in a given mask */
static FT_Int
ps_mask_test_bit( PS_Mask mask,
FT_Int idx )
{
if ( (FT_UInt)idx >= mask->num_bits )
return 0;
return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) );
}
/* clear a given bit */
static void
ps_mask_clear_bit( PS_Mask mask,
FT_Int idx )
{
FT_Byte* p;
if ( (FT_UInt)idx >= mask->num_bits )
return;
p = mask->bytes + ( idx >> 3 );
p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) );
}
/* set a given bit, possibly grow the mask */
static FT_Error
ps_mask_set_bit( PS_Mask mask,
FT_Int idx,
FT_Memory memory )
{
FT_Error error = 0;
FT_Byte* p;
if ( idx < 0 )
goto Exit;
if ( (FT_UInt)idx >= mask->num_bits )
{
error = ps_mask_ensure( mask, idx + 1, memory );
if ( error )
goto Exit;
mask->num_bits = idx + 1;
}
p = mask->bytes + ( idx >> 3 );
p[0] = (FT_Byte)( p[0] | ( 0x80 >> ( idx & 7 ) ) );
Exit:
return error;
}
/* destroy mask table */
static void
ps_mask_table_done( PS_Mask_Table table,
FT_Memory memory )
{
FT_UInt count = table->max_masks;
PS_Mask mask = table->masks;
for ( ; count > 0; count--, mask++ )
ps_mask_done( mask, memory );
FT_FREE( table->masks );
table->num_masks = 0;
table->max_masks = 0;
}
/* ensure that a mask table can contain "count" masks */
static FT_Error
ps_mask_table_ensure( PS_Mask_Table table,
FT_UInt count,
FT_Memory memory )
{
FT_UInt old_max = table->max_masks;
FT_UInt new_max = count;
FT_Error error = 0;
if ( new_max > old_max )
{
new_max = FT_PAD_CEIL( new_max, 8 );
if ( !FT_RENEW_ARRAY( table->masks, old_max, new_max ) )
table->max_masks = new_max;
}
return error;
}
/* allocate a new mask in a table */
static FT_Error
ps_mask_table_alloc( PS_Mask_Table table,
FT_Memory memory,
PS_Mask *amask )
{
FT_UInt count;
FT_Error error = 0;
PS_Mask mask = 0;
count = table->num_masks;
count++;
if ( count > table->max_masks )
{
error = ps_mask_table_ensure( table, count, memory );
if ( error )
goto Exit;
}
mask = table->masks + count - 1;
mask->num_bits = 0;
mask->end_point = 0;
table->num_masks = count;
Exit:
*amask = mask;
return error;
}
/* return last hint mask in a table, create one if the table is empty */
static FT_Error
ps_mask_table_last( PS_Mask_Table table,
FT_Memory memory,
PS_Mask *amask )
{
FT_Error error = 0;
FT_UInt count;
PS_Mask mask;
count = table->num_masks;
if ( count == 0 )
{
error = ps_mask_table_alloc( table, memory, &mask );
if ( error )
goto Exit;
}
else
mask = table->masks + count - 1;
Exit:
*amask = mask;
return error;
}
/* set a new mask to a given bit range */
static FT_Error
ps_mask_table_set_bits( PS_Mask_Table table,
FT_Byte* source,
FT_UInt bit_pos,
FT_UInt bit_count,
FT_Memory memory )
{
FT_Error error = 0;
PS_Mask mask;
error = ps_mask_table_last( table, memory, &mask );
if ( error )
goto Exit;
error = ps_mask_ensure( mask, bit_count, memory );
if ( error )
goto Exit;
mask->num_bits = bit_count;
/* now, copy bits */
{
FT_Byte* read = source + ( bit_pos >> 3 );
FT_Int rmask = 0x80 >> ( bit_pos & 7 );
FT_Byte* write = mask->bytes;
FT_Int wmask = 0x80;
FT_Int val;
for ( ; bit_count > 0; bit_count-- )
{
val = write[0] & ~wmask;
if ( read[0] & rmask )
val |= wmask;
write[0] = (FT_Byte)val;
rmask >>= 1;
if ( rmask == 0 )
{
read++;
rmask = 0x80;
}
wmask >>= 1;
if ( wmask == 0 )
{
write++;
wmask = 0x80;
}
}
}
Exit:
return error;
}
/* test whether two masks in a table intersect */
static FT_Int
ps_mask_table_test_intersect( PS_Mask_Table table,
FT_Int index1,
FT_Int index2 )
{
PS_Mask mask1 = table->masks + index1;
PS_Mask mask2 = table->masks + index2;
FT_Byte* p1 = mask1->bytes;
FT_Byte* p2 = mask2->bytes;
FT_UInt count1 = mask1->num_bits;
FT_UInt count2 = mask2->num_bits;
FT_UInt count;
count = ( count1 <= count2 ) ? count1 : count2;
for ( ; count >= 8; count -= 8 )
{
if ( p1[0] & p2[0] )
return 1;
p1++;
p2++;
}
if ( count == 0 )
return 0;
return ( p1[0] & p2[0] ) & ~( 0xFF >> count );
}
/* merge two masks, used by ps_mask_table_merge_all */
static FT_Error
ps_mask_table_merge( PS_Mask_Table table,
FT_Int index1,
FT_Int index2,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -