* src/pfr/pfrsbit.h, src/pfr/pfrsbit.c, src/pfr/pfrload.c,
src/pfr/pfrgload.c, src/pfr/pfrobjs.c, src/pfr/pfrtypes.h, Jamfile, src/base/ftobjs.c: adding support for embedded bitmaps to the PFR driver, and rewriting its kerning loader / handler to use all kerning pairs in a physical font (and not just the first item). * src/tools/docmaker/content.py, src/tools/docmaker/sources.py, src/tools/docmaker/tohtml.py: fixing a few nasty bugs * src/sfnt/ttcmap0.c: the validator for format 4 sub-tables is now capable of dealing with invalid "length" fields at the start of the sub-table. This allows fonts like "mg______.ttf" (i.e. Marriage) to return accurate charmaps.
This commit is contained in:
parent
4c09ae8002
commit
80171e06dd
16
ChangeLog
16
ChangeLog
@ -1,3 +1,19 @@
|
||||
2002-10-05 David Turner <david@freetype.org>
|
||||
|
||||
* src/pfr/pfrsbit.h, src/pfr/pfrsbit.c, src/pfr/pfrload.c,
|
||||
src/pfr/pfrgload.c, src/pfr/pfrobjs.c, src/pfr/pfrtypes.h,
|
||||
Jamfile, src/base/ftobjs.c: adding support for embedded bitmaps to
|
||||
the PFR driver, and rewriting its kerning loader / handler to use all
|
||||
kerning pairs in a physical font (and not just the first item).
|
||||
|
||||
* src/tools/docmaker/content.py, src/tools/docmaker/sources.py,
|
||||
src/tools/docmaker/tohtml.py: fixing a few nasty bugs
|
||||
|
||||
* src/sfnt/ttcmap0.c: the validator for format 4 sub-tables is
|
||||
now capable of dealing with invalid "length" fields at the start
|
||||
of the sub-table. This allows fonts like "mg______.ttf" (i.e.
|
||||
Marriage) to return accurate charmaps.
|
||||
|
||||
2002-10-05 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
* src/smooth/ftgrays.c (SUBPIXELS): Add cast to `TPos'.
|
||||
|
@ -433,6 +433,7 @@
|
||||
/* disable scaling, hinting, and transformation */
|
||||
load_flags |= FT_LOAD_NO_SCALE |
|
||||
FT_LOAD_NO_HINTING |
|
||||
FT_LOAD_NO_BITMAP |
|
||||
FT_LOAD_IGNORE_TRANSFORM;
|
||||
|
||||
/* disable bitmap rendering */
|
||||
@ -466,7 +467,8 @@
|
||||
/* XXX: This is really a temporary hack that should disappear */
|
||||
/* promptly with FreeType 2.1! */
|
||||
/* */
|
||||
if ( FT_HAS_FIXED_SIZES( face ) )
|
||||
if ( FT_HAS_FIXED_SIZES( face ) &&
|
||||
( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
|
||||
{
|
||||
error = driver->clazz->load_glyph( slot, face->size,
|
||||
glyph_index,
|
||||
|
@ -10,7 +10,7 @@ SubDirHdrs [ FT2_SubDir src pfr ] ;
|
||||
|
||||
if $(FT2_MULTI)
|
||||
{
|
||||
_sources = pfrdrivr pfrgload pfrload pfrobjs pfrcmap ;
|
||||
_sources = pfrdrivr pfrgload pfrload pfrobjs pfrcmap pfrsbit ;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -24,5 +24,6 @@
|
||||
#include "pfrcmap.c"
|
||||
#include "pfrobjs.c"
|
||||
#include "pfrdrivr.c"
|
||||
#include "pfrsbit.c"
|
||||
|
||||
/* END */
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
|
||||
#include "pfrgload.h"
|
||||
#include "pfrsbit.h"
|
||||
#include "pfrload.h" /* for macro definitions */
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
@ -676,6 +677,9 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static FT_Error
|
||||
pfr_glyph_load_rec( PFR_Glyph glyph,
|
||||
FT_Stream stream,
|
||||
@ -776,6 +780,9 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error )
|
||||
pfr_glyph_load( PFR_Glyph glyph,
|
||||
FT_Stream stream,
|
||||
|
@ -52,7 +52,7 @@
|
||||
FT_Error error = 0;
|
||||
FT_Byte* p = *pp;
|
||||
FT_UInt num_items, item_type, item_size;
|
||||
|
||||
|
||||
|
||||
PFR_CHECK( 1 );
|
||||
num_items = PFR_NEXT_BYTE( p );
|
||||
@ -62,11 +62,11 @@
|
||||
PFR_CHECK( 2 );
|
||||
item_size = PFR_NEXT_BYTE( p );
|
||||
item_type = PFR_NEXT_BYTE( p );
|
||||
|
||||
|
||||
PFR_CHECK( item_size );
|
||||
|
||||
if ( item_list )
|
||||
{
|
||||
{
|
||||
PFR_ExtraItem extra = item_list;
|
||||
|
||||
|
||||
@ -76,19 +76,19 @@
|
||||
{
|
||||
error = extra->parser( p, p + item_size, item_data );
|
||||
if ( error ) goto Exit;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
p += item_size;
|
||||
}
|
||||
|
||||
Exit:
|
||||
*pp = p;
|
||||
return error;
|
||||
|
||||
|
||||
Too_Short:
|
||||
FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" ));
|
||||
error = PFR_Err_Invalid_Table;
|
||||
@ -204,17 +204,17 @@
|
||||
FT_Error error;
|
||||
FT_UInt count;
|
||||
FT_UInt result = 0;
|
||||
|
||||
|
||||
|
||||
if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) )
|
||||
goto Exit;
|
||||
|
||||
|
||||
result = count;
|
||||
|
||||
|
||||
Exit:
|
||||
*acount = result;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error )
|
||||
@ -252,30 +252,30 @@
|
||||
FT_Byte* p;
|
||||
FT_Byte* limit;
|
||||
FT_UInt local;
|
||||
|
||||
|
||||
|
||||
if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
|
||||
goto Exit;
|
||||
|
||||
p = stream->cursor;
|
||||
limit = p + size;
|
||||
|
||||
|
||||
PFR_CHECK(13);
|
||||
|
||||
|
||||
log_font->matrix[0] = PFR_NEXT_LONG( p );
|
||||
log_font->matrix[1] = PFR_NEXT_LONG( p );
|
||||
log_font->matrix[2] = PFR_NEXT_LONG( p );
|
||||
log_font->matrix[3] = PFR_NEXT_LONG( p );
|
||||
|
||||
|
||||
flags = PFR_NEXT_BYTE( p );
|
||||
|
||||
|
||||
local = 0;
|
||||
if ( flags & PFR_LOG_STROKE )
|
||||
{
|
||||
local++;
|
||||
if ( flags & PFR_LOG_2BYTE_STROKE )
|
||||
local++;
|
||||
|
||||
|
||||
if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
|
||||
local += 3;
|
||||
}
|
||||
@ -293,18 +293,18 @@
|
||||
log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE )
|
||||
? PFR_NEXT_SHORT( p )
|
||||
: PFR_NEXT_BYTE( p );
|
||||
|
||||
|
||||
if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER )
|
||||
log_font->miter_limit = PFR_NEXT_LONG( p );
|
||||
}
|
||||
|
||||
|
||||
if ( flags & PFR_LOG_BOLD )
|
||||
{
|
||||
log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD )
|
||||
? PFR_NEXT_SHORT( p )
|
||||
: PFR_NEXT_BYTE( p );
|
||||
}
|
||||
|
||||
|
||||
if ( flags & PFR_LOG_EXTRA_ITEMS )
|
||||
{
|
||||
error = pfr_extra_items_skip( &p, limit );
|
||||
@ -326,7 +326,7 @@
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
|
||||
|
||||
Too_Short:
|
||||
FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" ));
|
||||
error = PFR_Err_Invalid_Table;
|
||||
@ -355,7 +355,7 @@
|
||||
FT_UInt n, count, size1;
|
||||
FT_Error error = 0;
|
||||
|
||||
|
||||
|
||||
PFR_CHECK( 5 );
|
||||
|
||||
p += 3; /* skip bctSize */
|
||||
@ -366,12 +366,12 @@
|
||||
if ( phy_font->num_strikes + count > phy_font->max_strikes )
|
||||
{
|
||||
FT_UInt new_max = (phy_font->num_strikes + count + 3) & -4;
|
||||
|
||||
|
||||
if ( FT_RENEW_ARRAY( phy_font->strikes,
|
||||
phy_font->num_strikes,
|
||||
new_max ) )
|
||||
goto Exit;
|
||||
|
||||
|
||||
phy_font->max_strikes = new_max;
|
||||
}
|
||||
|
||||
@ -421,15 +421,15 @@
|
||||
}
|
||||
|
||||
phy_font->num_strikes += count;
|
||||
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
|
||||
|
||||
Too_Short:
|
||||
error = PFR_Err_Invalid_Table;
|
||||
FT_ERROR(( "pfr_extra_item_load_bitmap_info: invalid bitmap info table\n" ));
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* load font ID, i.e. name */
|
||||
@ -441,18 +441,18 @@
|
||||
FT_Error error = 0;
|
||||
FT_Memory memory = phy_font->memory;
|
||||
FT_UInt len = (FT_UInt)( limit - p );
|
||||
|
||||
|
||||
|
||||
if ( phy_font->font_id != NULL )
|
||||
goto Exit;
|
||||
|
||||
|
||||
if ( FT_ALLOC( phy_font->font_id, len+1 ) )
|
||||
goto Exit;
|
||||
|
||||
/* copy font ID name, and terminate it for safety */
|
||||
FT_MEM_COPY( phy_font->font_id, p, len );
|
||||
phy_font->font_id[len] = 0;
|
||||
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
@ -472,35 +472,37 @@
|
||||
|
||||
if ( phy_font->vertical.stem_snaps != NULL )
|
||||
goto Exit;
|
||||
|
||||
|
||||
PFR_CHECK( 1 );
|
||||
count = PFR_NEXT_BYTE( p );
|
||||
|
||||
|
||||
num_vert = count & 15;
|
||||
num_horz = count >> 4;
|
||||
count = num_vert + num_horz;
|
||||
|
||||
|
||||
PFR_CHECK( count * 2 );
|
||||
|
||||
|
||||
if ( FT_NEW_ARRAY( snaps, count ) )
|
||||
goto Exit;
|
||||
|
||||
|
||||
phy_font->vertical.stem_snaps = snaps;
|
||||
phy_font->horizontal.stem_snaps = snaps + num_vert;
|
||||
|
||||
|
||||
for ( ; count > 0; count--, snaps++ )
|
||||
*snaps = FT_NEXT_SHORT( p );
|
||||
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
|
||||
|
||||
Too_Short:
|
||||
error = PFR_Err_Invalid_Table;
|
||||
FT_ERROR(( "pfr_exta_item_load_stem_snaps: invalid stem snaps table\n" ));
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
/* load kerning pair data */
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
pfr_extra_item_load_kerning_pairs( FT_Byte* p,
|
||||
@ -516,24 +518,25 @@
|
||||
FT_Memory memory = phy_font->memory;
|
||||
|
||||
|
||||
/* allocate a new kerning item */
|
||||
/* XXX: there may be multiple extra items for kerning */
|
||||
if ( phy_font->kern_pairs != NULL )
|
||||
goto Exit;
|
||||
|
||||
FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
|
||||
|
||||
|
||||
PFR_CHECK( 4 );
|
||||
|
||||
num_pairs = PFR_NEXT_BYTE( p );
|
||||
base_adj = PFR_NEXT_SHORT( p );
|
||||
flags = PFR_NEXT_BYTE( p );
|
||||
|
||||
|
||||
#ifndef PFR_CONFIG_NO_CHECKS
|
||||
count = 3;
|
||||
|
||||
|
||||
if ( flags & PFR_KERN_2BYTE_CHAR )
|
||||
count += 2;
|
||||
|
||||
|
||||
if ( flags & PFR_KERN_2BYTE_ADJ )
|
||||
count += 1;
|
||||
|
||||
@ -542,10 +545,10 @@
|
||||
|
||||
if ( FT_NEW_ARRAY( pairs, num_pairs ) )
|
||||
goto Exit;
|
||||
|
||||
|
||||
phy_font->num_kern_pairs = num_pairs;
|
||||
phy_font->kern_pairs = pairs;
|
||||
|
||||
|
||||
for (count = num_pairs ; count > 0; count--, pairs++ )
|
||||
{
|
||||
if ( flags & PFR_KERN_2BYTE_CHAR )
|
||||
@ -558,7 +561,7 @@
|
||||
pairs->glyph1 = PFR_NEXT_BYTE( p );
|
||||
pairs->glyph2 = PFR_NEXT_BYTE( p );
|
||||
}
|
||||
|
||||
|
||||
if ( flags & PFR_KERN_2BYTE_ADJ )
|
||||
pairs->kerning.x = base_adj + PFR_NEXT_SHORT( p );
|
||||
else
|
||||
@ -569,17 +572,111 @@
|
||||
FT_TRACE2(( "kerning %d <-> %d : %ld\n",
|
||||
pairs->glyph1, pairs->glyph2, pairs->kerning.x ));
|
||||
}
|
||||
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
|
||||
|
||||
Too_Short:
|
||||
error = PFR_Err_Invalid_Table;
|
||||
FT_ERROR(( "pfr_extra_item_load_kerning_pairs: "
|
||||
"invalid kerning pairs table\n" ));
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* load kerning pair data */
|
||||
FT_CALLBACK_DEF( FT_Error )
|
||||
pfr_extra_item_load_kerning_pairs( FT_Byte* p,
|
||||
FT_Byte* limit,
|
||||
PFR_PhyFont phy_font )
|
||||
{
|
||||
PFR_KernItem item;
|
||||
FT_Error error = 0;
|
||||
FT_Memory memory = phy_font->memory;
|
||||
|
||||
FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
|
||||
|
||||
if ( FT_NEW( item ) )
|
||||
goto Exit;
|
||||
|
||||
PFR_CHECK( 4 );
|
||||
|
||||
item->pair_count = PFR_NEXT_BYTE( p );
|
||||
item->base_adj = PFR_NEXT_SHORT( p );
|
||||
item->flags = PFR_NEXT_BYTE( p );
|
||||
item->offset = phy_font->offset + ( p - phy_font->cursor );
|
||||
|
||||
#ifndef PFR_CONFIG_NO_CHECKS
|
||||
item->pair_size = 3;
|
||||
|
||||
if ( item->flags & PFR_KERN_2BYTE_CHAR )
|
||||
item->pair_size += 2;
|
||||
|
||||
if ( item->flags & PFR_KERN_2BYTE_ADJ )
|
||||
item->pair_size += 1;
|
||||
|
||||
PFR_CHECK( item->pair_count * item->pair_size );
|
||||
#endif
|
||||
|
||||
/* load first and last pairs into the item to speed up */
|
||||
/* lookup later... */
|
||||
if ( item->pair_count > 0 )
|
||||
{
|
||||
FT_UInt char1, char2;
|
||||
FT_Byte* q;
|
||||
|
||||
if ( item->flags & PFR_KERN_2BYTE_CHAR )
|
||||
{
|
||||
q = p;
|
||||
char1 = PFR_NEXT_USHORT(q);
|
||||
char2 = PFR_NEXT_USHORT(q);
|
||||
|
||||
item->pair1 = PFR_KERN_INDEX(char1,char2);
|
||||
|
||||
q = p + item->pair_size*(item->pair_count-1);
|
||||
char1 = PFR_NEXT_USHORT(q);
|
||||
char2 = PFR_NEXT_USHORT(q);
|
||||
|
||||
item->pair2 = PFR_KERN_INDEX(char1,char2);
|
||||
}
|
||||
else
|
||||
{
|
||||
q = p;
|
||||
char1 = PFR_NEXT_BYTE(q);
|
||||
char2 = PFR_NEXT_BYTE(q);
|
||||
|
||||
item->pair1 = PFR_KERN_INDEX(char1,char2);
|
||||
|
||||
q = p + item->pair_size*(item->pair_count-1);
|
||||
char1 = PFR_NEXT_BYTE(q);
|
||||
char2 = PFR_NEXT_BYTE(q);
|
||||
|
||||
item->pair2 = PFR_KERN_INDEX(char1,char2);
|
||||
}
|
||||
|
||||
/* add new item to the current list */
|
||||
item->next = NULL;
|
||||
*phy_font->kern_items_tail = item;
|
||||
phy_font->kern_items_tail = &item->next;
|
||||
phy_font->num_kern_pairs += item->pair_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* empty item !! */
|
||||
FT_FREE( item );
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
|
||||
Too_Short:
|
||||
FT_FREE( item );
|
||||
|
||||
error = PFR_Err_Invalid_Table;
|
||||
FT_ERROR(( "pfr_extra_item_load_kerning_pairs: "
|
||||
"invalid kerning pairs table\n" ));
|
||||
goto Exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const PFR_ExtraItemRec pfr_phy_font_extra_items[] =
|
||||
{
|
||||
@ -607,7 +704,7 @@
|
||||
FT_FREE( phy_font->strikes );
|
||||
phy_font->num_strikes = 0;
|
||||
phy_font->max_strikes = 0;
|
||||
|
||||
|
||||
FT_FREE( phy_font->chars );
|
||||
phy_font->num_chars = 0;
|
||||
phy_font->chars_offset = 0;
|
||||
@ -615,10 +712,22 @@
|
||||
FT_FREE( phy_font->blue_values );
|
||||
phy_font->num_blue_values = 0;
|
||||
|
||||
FT_FREE( phy_font->kern_pairs );
|
||||
{
|
||||
PFR_KernItem item, next;
|
||||
|
||||
item = phy_font->kern_items;
|
||||
while (item)
|
||||
{
|
||||
next = item->next;
|
||||
FT_FREE( item );
|
||||
item = next;
|
||||
}
|
||||
phy_font->kern_items = NULL;
|
||||
phy_font->kern_items_tail = NULL;
|
||||
}
|
||||
phy_font->num_kern_pairs = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error )
|
||||
pfr_phy_font_load( PFR_PhyFont phy_font,
|
||||
@ -636,9 +745,14 @@
|
||||
phy_font->memory = memory;
|
||||
phy_font->offset = offset;
|
||||
|
||||
phy_font->kern_items = NULL;
|
||||
phy_font->kern_items_tail = &phy_font->kern_items;
|
||||
|
||||
if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
|
||||
goto Exit;
|
||||
|
||||
phy_font->cursor = stream->cursor;
|
||||
|
||||
p = stream->cursor;
|
||||
limit = p + size;
|
||||
|
||||
@ -664,15 +778,15 @@
|
||||
{
|
||||
error = pfr_extra_items_parse( &p, limit,
|
||||
pfr_phy_font_extra_items, phy_font );
|
||||
|
||||
|
||||
if ( error )
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
|
||||
/* skip the aux bytes */
|
||||
PFR_CHECK( 3 );
|
||||
num_aux = PFR_NEXT_ULONG( p );
|
||||
|
||||
|
||||
PFR_CHECK( num_aux );
|
||||
p += num_aux;
|
||||
|
||||
@ -684,7 +798,7 @@
|
||||
phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
|
||||
|
||||
PFR_CHECK( count * 2 );
|
||||
|
||||
|
||||
if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
|
||||
goto Fail;
|
||||
|
||||
@ -713,19 +827,19 @@
|
||||
Size = 1 + 1 + 2;
|
||||
if ( flags & PFR_PHY_2BYTE_CHARCODE )
|
||||
Size += 1;
|
||||
|
||||
|
||||
if ( flags & PFR_PHY_PROPORTIONAL )
|
||||
Size += 2;
|
||||
|
||||
|
||||
if ( flags & PFR_PHY_ASCII_CODE )
|
||||
Size += 1;
|
||||
|
||||
|
||||
if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
|
||||
Size += 1;
|
||||
|
||||
|
||||
if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
|
||||
Size += 1;
|
||||
|
||||
|
||||
PFR_CHECK( count * Size );
|
||||
|
||||
for ( n = 0; n < count; n++ )
|
||||
@ -763,9 +877,13 @@
|
||||
Fail:
|
||||
FT_FRAME_EXIT();
|
||||
|
||||
/* save position of bitmap info */
|
||||
phy_font->bct_offset = FT_STREAM_POS();
|
||||
phy_font->cursor = NULL;
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
|
||||
|
||||
Too_Short:
|
||||
error = PFR_Err_Invalid_Table;
|
||||
FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "pfrload.h"
|
||||
#include "pfrgload.h"
|
||||
#include "pfrcmap.h"
|
||||
#include "pfrsbit.h"
|
||||
#include FT_OUTLINE_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
@ -129,7 +130,11 @@
|
||||
else
|
||||
root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
|
||||
|
||||
/* XXX: kerning and embedded bitmap support isn't there yet */
|
||||
if ( phy_font->num_strikes > 0 )
|
||||
root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
|
||||
|
||||
if ( phy_font->num_kern_pairs > 0 )
|
||||
root->face_flags |= FT_FACE_FLAG_KERNING;
|
||||
|
||||
root->family_name = phy_font->font_id;
|
||||
root->style_name = NULL; /* no style name in font file */
|
||||
@ -242,6 +247,14 @@
|
||||
/* check that the glyph index is correct */
|
||||
FT_ASSERT( gindex < face->phy_font.num_chars );
|
||||
|
||||
/* try to load an embedded bitmap */
|
||||
if ( (load_flags & (FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP)) == 0 )
|
||||
{
|
||||
error = pfr_slot_load_bitmap( slot, size, gindex );
|
||||
if ( error == 0 )
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
gchar = face->phy_font.chars + gindex;
|
||||
slot->root.format = FT_GLYPH_FORMAT_OUTLINE;
|
||||
outline->n_points = 0;
|
||||
@ -325,6 +338,7 @@
|
||||
metrics->horiBearingY = cbox.yMax - metrics->height;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -341,9 +355,7 @@
|
||||
kerning pairs are sorted. We might want to sort it just to make
|
||||
sure */
|
||||
|
||||
#undef PFR_KERN_INDEX
|
||||
#define PFR_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
|
||||
|
||||
#if 0
|
||||
/* find the kerning for a given glyph pair */
|
||||
FT_LOCAL_DEF( FT_Error )
|
||||
pfr_face_get_kerning( PFR_Face face,
|
||||
@ -386,5 +398,87 @@
|
||||
Exit:
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
/* find the kerning for a given glyph pair */
|
||||
FT_LOCAL_DEF( FT_Error )
|
||||
pfr_face_get_kerning( PFR_Face face,
|
||||
FT_UInt glyph1,
|
||||
FT_UInt glyph2,
|
||||
FT_Vector* kerning )
|
||||
{
|
||||
FT_Error error;
|
||||
PFR_PhyFont phy_font = &face->phy_font;
|
||||
PFR_KernItem item = phy_font->kern_items;
|
||||
FT_UInt32 idx = PFR_KERN_INDEX( glyph1, glyph2 );
|
||||
|
||||
kerning->x = 0;
|
||||
kerning->y = 0;
|
||||
|
||||
/* find the kerning item containing our pair */
|
||||
while ( item )
|
||||
{
|
||||
if ( item->pair1 <= idx && idx <= item->pair2 )
|
||||
goto Found_Item;
|
||||
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
/* not found */
|
||||
goto Exit;
|
||||
|
||||
Found_Item:
|
||||
{
|
||||
/* perform simply binary search within the item */
|
||||
FT_UInt min, mid, max;
|
||||
FT_Stream stream = face->root.stream;
|
||||
FT_Byte* p;
|
||||
|
||||
if ( FT_STREAM_SEEK( item->offset ) ||
|
||||
FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
|
||||
goto Exit;
|
||||
|
||||
min = 0;
|
||||
max = item->pair_count;
|
||||
while ( min < max )
|
||||
{
|
||||
FT_UInt char1, char2, charcode;
|
||||
|
||||
mid = (min + max) >> 1;
|
||||
p = stream->cursor + mid*item->pair_size;
|
||||
|
||||
if ( item->flags & PFR_KERN_2BYTE_CHAR )
|
||||
{
|
||||
char1 = FT_NEXT_USHORT(p);
|
||||
char2 = FT_NEXT_USHORT(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
char1 = FT_NEXT_USHORT(p);
|
||||
char2 = FT_NEXT_USHORT(p);
|
||||
}
|
||||
charcode = PFR_KERN_INDEX(char1,char2);
|
||||
|
||||
if ( idx == charcode )
|
||||
{
|
||||
if ( item->flags & PFR_KERN_2BYTE_ADJ )
|
||||
kerning->x = item->base_adj + FT_NEXT_SHORT(p);
|
||||
else
|
||||
kerning->x = item->base_adj + FT_NEXT_CHAR(p);
|
||||
|
||||
break;
|
||||
}
|
||||
if ( idx > charcode )
|
||||
min = mid+1;
|
||||
else
|
||||
max = mid;
|
||||
}
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
}
|
||||
|
||||
Exit:
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* END */
|
||||
|
629
src/pfr/pfrsbit.c
Normal file
629
src/pfr/pfrsbit.c
Normal file
@ -0,0 +1,629 @@
|
||||
#include "pfrsbit.h"
|
||||
#include "pfrload.h"
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
#include FT_INTERNAL_STREAM_H
|
||||
|
||||
#include "pfrerror.h"
|
||||
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_pfr
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** PFR BIT WRITER *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct PFR_BitWriter_
|
||||
{
|
||||
FT_Byte* line; /* current line start */
|
||||
FT_Int pitch; /* line size in bytes */
|
||||
FT_Int width; /* width in pixels/bits */
|
||||
FT_Int rows; /* number of remaining rows to scan */
|
||||
FT_Int total; /* total number of bits to draw */
|
||||
|
||||
} PFR_BitWriterRec, *PFR_BitWriter;
|
||||
|
||||
|
||||
static void
|
||||
pfr_bitwriter_init( PFR_BitWriter writer,
|
||||
FT_Bitmap* target,
|
||||
FT_Bool decreasing )
|
||||
{
|
||||
writer->line = target->buffer;
|
||||
writer->pitch = target->pitch;
|
||||
writer->width = target->width;
|
||||
writer->rows = target->rows;
|
||||
writer->total = writer->width * writer->rows;
|
||||
|
||||
if ( !decreasing )
|
||||
{
|
||||
writer->line += writer->pitch * ( target->rows-1 );
|
||||
writer->pitch = -writer->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pfr_bitwriter_decode_bytes( PFR_BitWriter writer,
|
||||
FT_Byte* p,
|
||||
FT_Byte* limit )
|
||||
{
|
||||
FT_Int n, reload;
|
||||
FT_Int left = writer->width;
|
||||
FT_Byte* cur = writer->line;
|
||||
FT_UInt mask = 0x80;
|
||||
FT_UInt val = 0;
|
||||
FT_UInt c = 0;
|
||||
|
||||
n = (FT_Int)(limit - p)*8;
|
||||
if ( n > writer->total )
|
||||
n = writer->total;
|
||||
|
||||
reload = n & 7;
|
||||
|
||||
for ( ; n > 0; n-- )
|
||||
{
|
||||
if ( (n & 7) == reload )
|
||||
val = *p++;
|
||||
|
||||
if ( val & 0x80 )
|
||||
c |= mask;
|
||||
|
||||
val <<= 1;
|
||||
mask >>= 1;
|
||||
|
||||
if ( --left <= 0 )
|
||||
{
|
||||
cur[0] = (FT_Byte) c;
|
||||
left = writer->width;
|
||||
mask = 0x80;
|
||||
|
||||
writer->line += writer->pitch;
|
||||
cur = writer->line;
|
||||
c = 0;
|
||||
}
|
||||
else if ( mask == 0 )
|
||||
{
|
||||
cur[0] = c;
|
||||
mask = 0x80;
|
||||
c = 0;
|
||||
cur ++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( mask != 0x80 )
|
||||
cur[0] = c;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pfr_bitwriter_decode_rle1( PFR_BitWriter writer,
|
||||
FT_Byte* p,
|
||||
FT_Byte* limit )
|
||||
{
|
||||
FT_Int n, phase, count, counts[2], reload;
|
||||
FT_Int left = writer->width;
|
||||
FT_Byte* cur = writer->line;
|
||||
FT_UInt mask = 0x80;
|
||||
FT_UInt c = 0;
|
||||
|
||||
n = writer->total;
|
||||
|
||||
phase = 1;
|
||||
counts[0] = 0;
|
||||
counts[1] = 0;
|
||||
count = 0;
|
||||
reload = 1;
|
||||
|
||||
for ( ; n > 0; n-- )
|
||||
{
|
||||
if ( reload )
|
||||
{
|
||||
do
|
||||
{
|
||||
if ( phase )
|
||||
{
|
||||
FT_Int v;
|
||||
|
||||
if ( p >= limit )
|
||||
break;
|
||||
|
||||
v = *p++;
|
||||
counts[0] = (v >> 4);
|
||||
counts[1] = (v & 15);
|
||||
phase = 0;
|
||||
count = counts[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
phase = 1;
|
||||
count = counts[1];
|
||||
}
|
||||
}
|
||||
while ( count == 0 );
|
||||
}
|
||||
|
||||
if ( phase )
|
||||
c |= mask;
|
||||
|
||||
mask >>= 1;
|
||||
|
||||
if ( --left <= 0 )
|
||||
{
|
||||
cur[0] = (FT_Byte) c;
|
||||
left = writer->width;
|
||||
mask = 0x80;
|
||||
|
||||
writer->line += writer->pitch;
|
||||
cur = writer->line;
|
||||
c = 0;
|
||||
}
|
||||
else if ( mask == 0 )
|
||||
{
|
||||
cur[0] = c;
|
||||
mask = 0x80;
|
||||
c = 0;
|
||||
cur ++;
|
||||
}
|
||||
|
||||
reload = ( --count <= 0 );
|
||||
}
|
||||
|
||||
if ( mask != 0x80 )
|
||||
cur[0] = (FT_Byte) c;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pfr_bitwriter_decode_rle2( PFR_BitWriter writer,
|
||||
FT_Byte* p,
|
||||
FT_Byte* limit )
|
||||
{
|
||||
FT_Int n, phase, count, reload;
|
||||
FT_Int left = writer->width;
|
||||
FT_Byte* cur = writer->line;
|
||||
FT_UInt mask = 0x80;
|
||||
FT_UInt c = 0;
|
||||
|
||||
n = writer->total;
|
||||
|
||||
phase = 1;
|
||||
count = 0;
|
||||
reload = 1;
|
||||
|
||||
for ( ; n > 0; n-- )
|
||||
{
|
||||
if ( reload )
|
||||
{
|
||||
do
|
||||
{
|
||||
if ( p >= limit )
|
||||
break;
|
||||
|
||||
count = *p++;
|
||||
phase = phase ^ 1;
|
||||
}
|
||||
while ( count == 0 );
|
||||
}
|
||||
|
||||
if ( phase )
|
||||
c |= mask;
|
||||
|
||||
mask >>= 1;
|
||||
|
||||
if ( --left <= 0 )
|
||||
{
|
||||
cur[0] = (FT_Byte) c;
|
||||
c = 0;
|
||||
mask = 0x80;
|
||||
left = writer->width;
|
||||
|
||||
writer->line += writer->pitch;
|
||||
cur = writer->line;
|
||||
}
|
||||
else if ( mask == 0 )
|
||||
{
|
||||
cur[0] = c;
|
||||
c = 0;
|
||||
mask = 0x80;
|
||||
cur ++;
|
||||
}
|
||||
|
||||
reload = ( --count <= 0 );
|
||||
}
|
||||
|
||||
if ( mask != 0x80 )
|
||||
cur[0] = (FT_Byte) c;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** BITMAP DATA DECODING *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static void
|
||||
pfr_lookup_bitmap_data( FT_Byte* base,
|
||||
FT_Byte* limit,
|
||||
FT_Int count,
|
||||
FT_Byte flags,
|
||||
FT_UInt char_code,
|
||||
FT_ULong* found_offset,
|
||||
FT_ULong* found_size )
|
||||
{
|
||||
FT_UInt left, right, char_len;
|
||||
FT_Bool two = (flags & 1);
|
||||
FT_Byte* buff;
|
||||
|
||||
char_len = 4;
|
||||
if ( two ) char_len += 1;
|
||||
if ( flags & 2) char_len += 1;
|
||||
if ( flags & 4) char_len += 1;
|
||||
|
||||
left = 0;
|
||||
right = count;
|
||||
|
||||
while ( left < right )
|
||||
{
|
||||
FT_UInt middle, code;
|
||||
|
||||
middle = (left + right) >> 1;
|
||||
buff = base + middle*char_len;
|
||||
|
||||
/* check that we're not outside of the table */
|
||||
/* this is possible with broken fonts... */
|
||||
if ( buff + char_len > limit )
|
||||
goto Fail;
|
||||
|
||||
if (two) code = PFR_NEXT_USHORT(buff);
|
||||
else code = PFR_NEXT_BYTE(buff);
|
||||
|
||||
if ( code == char_code )
|
||||
goto Found_It;
|
||||
|
||||
if ( code < char_code )
|
||||
left = middle;
|
||||
else
|
||||
right = middle;
|
||||
}
|
||||
|
||||
Fail:
|
||||
/* Not found */
|
||||
*found_size = 0;
|
||||
*found_offset = 0;
|
||||
return;
|
||||
|
||||
Found_It:
|
||||
if (flags & 2) *found_size = PFR_NEXT_USHORT(buff);
|
||||
else *found_size = PFR_NEXT_BYTE(buff);
|
||||
|
||||
if (flags & 4) *found_offset = PFR_NEXT_ULONG(buff);
|
||||
else *found_offset = PFR_NEXT_USHORT(buff);
|
||||
}
|
||||
|
||||
|
||||
/* load bitmap metrics. "*padvance" must be set to the default value */
|
||||
/* before calling this function... */
|
||||
/* */
|
||||
static FT_Error
|
||||
pfr_load_bitmap_metrics( FT_Byte** pdata,
|
||||
FT_Byte* limit,
|
||||
FT_Long scaled_advance,
|
||||
FT_Long *axpos,
|
||||
FT_Long *aypos,
|
||||
FT_UInt *axsize,
|
||||
FT_UInt *aysize,
|
||||
FT_Long *aadvance,
|
||||
FT_UInt *aformat )
|
||||
{
|
||||
FT_Error error = 0;
|
||||
FT_Byte flags;
|
||||
FT_Char b;
|
||||
FT_Byte* p = *pdata;
|
||||
FT_Long xpos, ypos, advance;
|
||||
FT_UInt xsize, ysize;
|
||||
|
||||
PFR_CHECK(1);
|
||||
flags = PFR_NEXT_BYTE(p);
|
||||
|
||||
xpos = 0;
|
||||
ypos = 0;
|
||||
xsize = 0;
|
||||
ysize = 0;
|
||||
advance = 0;
|
||||
|
||||
switch (flags & 3)
|
||||
{
|
||||
case 0:
|
||||
PFR_CHECK(1);
|
||||
b = PFR_NEXT_INT8(p);
|
||||
xpos = b >> 4;
|
||||
ypos = ((FT_Char)(b << 4)) >> 4;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
PFR_CHECK(2);
|
||||
xpos = PFR_NEXT_INT8(p);
|
||||
ypos = PFR_NEXT_INT8(p);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
PFR_CHECK(4);
|
||||
xpos = PFR_NEXT_SHORT(p);
|
||||
ypos = PFR_NEXT_SHORT(p);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
PFR_CHECK(6);
|
||||
xpos = PFR_NEXT_LONG(p);
|
||||
ypos = PFR_NEXT_LONG(p);
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
flags >>= 2;
|
||||
switch (flags & 3)
|
||||
{
|
||||
case 0:
|
||||
/* blank image */
|
||||
xsize = 0;
|
||||
ysize = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
PFR_CHECK(1);
|
||||
b = PFR_NEXT_BYTE(p);
|
||||
xsize = (b >> 4) & 0xF;
|
||||
ysize = b & 0xF;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
PFR_CHECK(2);
|
||||
xsize = PFR_NEXT_BYTE(p);
|
||||
ysize = PFR_NEXT_BYTE(p);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
PFR_CHECK(4);
|
||||
xsize = PFR_NEXT_USHORT(p);
|
||||
ysize = PFR_NEXT_USHORT(p);
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
flags >>= 2;
|
||||
switch (flags & 3)
|
||||
{
|
||||
case 0:
|
||||
advance = scaled_advance;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
PFR_CHECK(1);
|
||||
advance = PFR_NEXT_INT8(p) << 8;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
PFR_CHECK(2);
|
||||
advance = PFR_NEXT_SHORT(p);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
PFR_CHECK(3);
|
||||
advance = PFR_NEXT_LONG(p);
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
*axpos = xpos;
|
||||
*aypos = ypos;
|
||||
*axsize = xsize;
|
||||
*aysize = ysize;
|
||||
*aadvance = advance;
|
||||
*aformat = flags >> 2;
|
||||
*pdata = p;
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
|
||||
Too_Short:
|
||||
error = PFR_Err_Invalid_Table;
|
||||
FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
|
||||
static FT_Error
|
||||
pfr_load_bitmap_bits( FT_Byte* p,
|
||||
FT_Byte* limit,
|
||||
FT_UInt format,
|
||||
FT_UInt decreasing,
|
||||
FT_Bitmap* target )
|
||||
{
|
||||
FT_Error error = 0;
|
||||
PFR_BitWriterRec writer;
|
||||
|
||||
if ( target->rows > 0 && target->width > 0 )
|
||||
{
|
||||
pfr_bitwriter_init( &writer, target, decreasing );
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case 0: /* packed bits */
|
||||
pfr_bitwriter_decode_bytes( &writer, p, limit );
|
||||
break;
|
||||
|
||||
case 1: /* RLE1 */
|
||||
pfr_bitwriter_decode_rle1( &writer, p, limit );
|
||||
break;
|
||||
|
||||
case 2: /* RLE2 */
|
||||
pfr_bitwriter_decode_rle2( &writer, p, limit );
|
||||
break;
|
||||
|
||||
default:
|
||||
FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" ));
|
||||
error = FT_Err_Invalid_File_Format;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** BITMAP LOADING *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL( FT_Error )
|
||||
pfr_slot_load_bitmap( PFR_Slot glyph,
|
||||
PFR_Size size,
|
||||
FT_UInt glyph_index )
|
||||
{
|
||||
FT_Error error;
|
||||
PFR_Face face = (PFR_Face) glyph->root.face;
|
||||
FT_Stream stream = face->root.stream;
|
||||
PFR_PhyFont phys = &face->phy_font;
|
||||
FT_ULong gps_offset;
|
||||
FT_ULong gps_size;
|
||||
PFR_Char character;
|
||||
PFR_Strike strike;
|
||||
|
||||
character = &phys->chars[glyph_index];
|
||||
|
||||
/* Look-up a bitmap strike corresponding to the current */
|
||||
/* character dimensions */
|
||||
|
||||
{
|
||||
FT_UInt n;
|
||||
|
||||
strike = phys->strikes;
|
||||
for ( n = 0; n < phys->num_strikes; n++ )
|
||||
{
|
||||
if ( strike->x_ppm == (FT_UInt) size->root.metrics.x_ppem &&
|
||||
strike->y_ppm == (FT_UInt) size->root.metrics.y_ppem )
|
||||
{
|
||||
goto Found_Strike;
|
||||
}
|
||||
strike++;
|
||||
}
|
||||
|
||||
/* couldn't find it */
|
||||
return FT_Err_Invalid_Argument;
|
||||
}
|
||||
|
||||
Found_Strike:
|
||||
|
||||
/* Now lookup the glyph's position within the file */
|
||||
{
|
||||
FT_UInt char_len;
|
||||
|
||||
char_len = 4;
|
||||
if ( strike->flags & 1 ) char_len += 1;
|
||||
if ( strike->flags & 2 ) char_len += 1;
|
||||
if ( strike->flags & 4 ) char_len += 1;
|
||||
|
||||
/* Access data directly in the frame to speed lookups */
|
||||
if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
|
||||
FT_FRAME_ENTER( char_len * strike->num_bitmaps ) )
|
||||
goto Exit;
|
||||
|
||||
pfr_lookup_bitmap_data( stream->cursor,
|
||||
stream->limit,
|
||||
strike->num_bitmaps,
|
||||
strike->flags,
|
||||
character->char_code,
|
||||
&gps_offset,
|
||||
&gps_size );
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
|
||||
if (gps_size == 0)
|
||||
{
|
||||
/* Could not find a bitmap program string for this glyph */
|
||||
error = FT_Err_Invalid_Argument;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the bitmap metrics */
|
||||
{
|
||||
FT_Long xpos, ypos, advance;
|
||||
FT_UInt xsize, ysize, format;
|
||||
FT_Byte* p;
|
||||
|
||||
advance = FT_MulDiv( size->root.metrics.x_ppem << 8,
|
||||
character->advance,
|
||||
phys->metrics_resolution );
|
||||
|
||||
/* XXX: handle linearHoriAdvance correctly !! */
|
||||
|
||||
if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
|
||||
FT_FRAME_ENTER( gps_size ) )
|
||||
goto Exit;
|
||||
|
||||
p = stream->cursor;
|
||||
error = pfr_load_bitmap_metrics( &p, stream->limit,
|
||||
advance,
|
||||
&xpos, &ypos,
|
||||
&xsize, &ysize,
|
||||
&advance, &format );
|
||||
if ( !error )
|
||||
{
|
||||
glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
|
||||
|
||||
/* Set up glyph bitmap and metrics */
|
||||
glyph->root.bitmap.width = (FT_Int) xsize;
|
||||
glyph->root.bitmap.rows = (FT_Int) ysize;
|
||||
glyph->root.bitmap.pitch = (FT_Long)(xsize+7) >> 3;
|
||||
glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
|
||||
|
||||
glyph->root.metrics.width = (FT_Long)xsize << 6;
|
||||
glyph->root.metrics.height = (FT_Long)ysize << 6;
|
||||
glyph->root.metrics.horiBearingX = xpos << 6;
|
||||
glyph->root.metrics.horiBearingY = ypos << 6;
|
||||
glyph->root.metrics.horiAdvance = ((advance >> 2) + 32) & -64;
|
||||
glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
|
||||
glyph->root.metrics.vertBearingY = 0;
|
||||
glyph->root.metrics.vertAdvance = size->root.metrics.height;
|
||||
|
||||
glyph->root.bitmap_left = xpos;
|
||||
glyph->root.bitmap_top = ypos + ysize;
|
||||
|
||||
/* Allocate and read bitmap data */
|
||||
{
|
||||
FT_Memory memory = face->root.memory;
|
||||
FT_Long len = glyph->root.bitmap.pitch*ysize;
|
||||
|
||||
if ( !FT_ALLOC( glyph->root.bitmap.buffer, len ) )
|
||||
{
|
||||
error = pfr_load_bitmap_bits( p,
|
||||
stream->limit,
|
||||
format,
|
||||
(face->header.color_flags & 2),
|
||||
&glyph->root.bitmap );
|
||||
}
|
||||
}
|
||||
}
|
||||
FT_FRAME_EXIT();
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
32
src/pfr/pfrsbit.h
Normal file
32
src/pfr/pfrsbit.h
Normal file
@ -0,0 +1,32 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* pfrsbit.c */
|
||||
/* */
|
||||
/* FreeType PFR bitmap loader */
|
||||
/* */
|
||||
/* Copyright 2002 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
#ifndef __PFRSBIT_H__
|
||||
#define __PFRSBIT_H__
|
||||
|
||||
#include "pfrobjs.h"
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
FT_LOCAL( FT_Error )
|
||||
pfr_slot_load_bitmap( PFR_Slot glyph,
|
||||
PFR_Size size,
|
||||
FT_UInt glyph_index );
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* __PFR_SBIT_H__ */
|
@ -52,19 +52,19 @@ FT_BEGIN_HEADER
|
||||
FT_UInt max_blue_values;
|
||||
FT_UInt max_x_orus;
|
||||
FT_UInt max_y_orus;
|
||||
|
||||
|
||||
FT_UInt phy_font_max_size_high;
|
||||
FT_UInt color_flags;
|
||||
|
||||
|
||||
FT_UInt32 bct_max_size;
|
||||
FT_UInt32 bct_set_max_size;
|
||||
FT_UInt32 bct_set_max_size;
|
||||
FT_UInt32 phy_bct_set_max_size;
|
||||
|
||||
|
||||
FT_UInt num_phy_fonts;
|
||||
FT_UInt max_vert_stem_snap;
|
||||
FT_UInt max_horz_stem_snap;
|
||||
FT_UInt max_chars;
|
||||
|
||||
|
||||
} PFR_HeaderRec, *PFR_Header;
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@ FT_BEGIN_HEADER
|
||||
{
|
||||
PFR_FLAG_BLACK_PIXEL = 1,
|
||||
PFR_FLAG_INVERT_BITMAP = 2
|
||||
|
||||
|
||||
} PFR_HeaderFlags;
|
||||
|
||||
|
||||
@ -83,16 +83,16 @@ FT_BEGIN_HEADER
|
||||
{
|
||||
FT_UInt32 size;
|
||||
FT_UInt32 offset;
|
||||
|
||||
|
||||
FT_Int32 matrix[4];
|
||||
FT_UInt stroke_flags;
|
||||
FT_Int stroke_thickness;
|
||||
FT_Int bold_thickness;
|
||||
FT_Int32 miter_limit;
|
||||
|
||||
|
||||
FT_UInt32 phys_size;
|
||||
FT_UInt32 phys_offset;
|
||||
|
||||
|
||||
} PFR_LogFontRec, *PFR_LogFont;
|
||||
|
||||
|
||||
@ -104,7 +104,7 @@ FT_BEGIN_HEADER
|
||||
PFR_LOG_2BYTE_STROKE = 8,
|
||||
PFR_LOG_STROKE = 4,
|
||||
PFR_LINE_JOIN_MASK = 3
|
||||
|
||||
|
||||
} PFR_LogFlags;
|
||||
|
||||
|
||||
@ -113,7 +113,7 @@ FT_BEGIN_HEADER
|
||||
PFR_LINE_JOIN_MITER = 0,
|
||||
PFR_LINE_JOIN_ROUND = 1,
|
||||
PFR_LINE_JOIN_BEVEL = 2
|
||||
|
||||
|
||||
} PFR_LineJoinFlags;
|
||||
|
||||
|
||||
@ -124,7 +124,7 @@ FT_BEGIN_HEADER
|
||||
PFR_BITMAP_3BYTE_OFFSET = 4,
|
||||
PFR_BITMAP_2BYTE_SIZE = 2,
|
||||
PFR_BITMAP_2BYTE_CHARCODE = 1
|
||||
|
||||
|
||||
} PFR_BitmapFlags;
|
||||
|
||||
|
||||
@ -133,7 +133,7 @@ FT_BEGIN_HEADER
|
||||
FT_UInt char_code;
|
||||
FT_UInt gps_size;
|
||||
FT_UInt32 gps_offset;
|
||||
|
||||
|
||||
} PFR_BitmapCharRec, *PFR_BitmapChar;
|
||||
|
||||
|
||||
@ -153,17 +153,17 @@ FT_BEGIN_HEADER
|
||||
FT_UInt x_ppm;
|
||||
FT_UInt y_ppm;
|
||||
FT_UInt flags;
|
||||
|
||||
|
||||
FT_UInt32 gps_size;
|
||||
FT_UInt32 gps_offset;
|
||||
|
||||
|
||||
FT_UInt32 bct_size;
|
||||
FT_UInt32 bct_offset;
|
||||
|
||||
|
||||
/* optional */
|
||||
FT_UInt num_bitmaps;
|
||||
PFR_BitmapChar bitmaps;
|
||||
|
||||
|
||||
} PFR_StrikeRec, *PFR_Strike;
|
||||
|
||||
|
||||
@ -175,7 +175,7 @@ FT_BEGIN_HEADER
|
||||
FT_Int advance;
|
||||
FT_UInt gps_size;
|
||||
FT_UInt32 gps_offset;
|
||||
|
||||
|
||||
} PFR_CharRec, *PFR_Char;
|
||||
|
||||
|
||||
@ -186,11 +186,27 @@ FT_BEGIN_HEADER
|
||||
FT_UInt standard;
|
||||
FT_UInt num_stem_snaps;
|
||||
FT_Int* stem_snaps;
|
||||
|
||||
|
||||
} PFR_DimensionRec, *PFR_Dimension;
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
typedef struct PFR_KernItemRec_* PFR_KernItem;
|
||||
typedef struct PFR_KernItemRec_
|
||||
{
|
||||
PFR_KernItem next;
|
||||
FT_UInt pair_count;
|
||||
FT_UInt pair_size;
|
||||
FT_Int base_adj;
|
||||
FT_UInt flags;
|
||||
FT_UInt32 offset;
|
||||
FT_UInt32 pair1;
|
||||
FT_UInt32 pair2;
|
||||
|
||||
} PFR_KernItemRec;
|
||||
|
||||
#define PFR_KERN_INDEX( g1, g2 ) ( ( (FT_UInt32)(g1) << 16 ) | (FT_UInt16)(g2) )
|
||||
|
||||
typedef struct PFR_KernPairRec_
|
||||
{
|
||||
FT_UInt glyph1;
|
||||
@ -212,7 +228,7 @@ FT_BEGIN_HEADER
|
||||
FT_BBox bbox;
|
||||
FT_UInt flags;
|
||||
FT_UInt standard_advance;
|
||||
|
||||
|
||||
PFR_DimensionRec horizontal;
|
||||
PFR_DimensionRec vertical;
|
||||
|
||||
@ -221,18 +237,23 @@ FT_BEGIN_HEADER
|
||||
FT_UInt num_strikes;
|
||||
FT_UInt max_strikes;
|
||||
PFR_StrikeRec* strikes;
|
||||
|
||||
|
||||
FT_UInt num_blue_values;
|
||||
FT_Int *blue_values;
|
||||
FT_UInt blue_fuzz;
|
||||
FT_UInt blue_scale;
|
||||
|
||||
|
||||
FT_UInt num_chars;
|
||||
FT_UInt32 chars_offset;
|
||||
PFR_Char chars;
|
||||
|
||||
FT_UInt num_kern_pairs;
|
||||
PFR_KernPairRec *kern_pairs;
|
||||
PFR_KernItem kern_items;
|
||||
PFR_KernItem* kern_items_tail;
|
||||
|
||||
/* not part of the spec, but used during load */
|
||||
FT_UInt32 bct_offset;
|
||||
FT_Byte* cursor;
|
||||
|
||||
} PFR_PhyFontRec, *PFR_PhyFont;
|
||||
|
||||
@ -254,7 +275,7 @@ FT_BEGIN_HEADER
|
||||
{
|
||||
PFR_KERN_2BYTE_ADJ = 0x01,
|
||||
PFR_KERN_2BYTE_CHAR = 0x02
|
||||
|
||||
|
||||
} PFR_KernFlags;
|
||||
|
||||
|
||||
@ -267,7 +288,7 @@ FT_BEGIN_HEADER
|
||||
PFR_GLYPH_1BYTE_XYCOUNT = 0x04,
|
||||
PFR_GLYPH_XCOUNT = 0x02,
|
||||
PFR_GLYPH_YCOUNT = 0x01
|
||||
|
||||
|
||||
} PFR_GlyphFlags;
|
||||
|
||||
|
||||
@ -276,7 +297,7 @@ FT_BEGIN_HEADER
|
||||
{
|
||||
FT_UInt org;
|
||||
FT_UInt cur;
|
||||
|
||||
|
||||
} PFR_CoordRec, *PFR_Coord;
|
||||
|
||||
|
||||
@ -288,7 +309,7 @@ FT_BEGIN_HEADER
|
||||
FT_Int y_delta;
|
||||
FT_UInt32 gps_offset;
|
||||
FT_UInt gps_size;
|
||||
|
||||
|
||||
} PFR_SubGlyphRec, *PFR_SubGlyph;
|
||||
|
||||
|
||||
@ -298,14 +319,14 @@ FT_BEGIN_HEADER
|
||||
PFR_SUBGLYPH_2BYTE_SIZE = 0x40,
|
||||
PFR_SUBGLYPH_YSCALE = 0x20,
|
||||
PFR_SUBGLYPH_XSCALE = 0x10
|
||||
|
||||
|
||||
} PFR_SubGlyphFlags;
|
||||
|
||||
|
||||
typedef struct PFR_GlyphRec_
|
||||
{
|
||||
FT_Byte format;
|
||||
|
||||
|
||||
FT_UInt num_x_control;
|
||||
FT_UInt num_y_control;
|
||||
FT_UInt max_xy_control;
|
||||
@ -316,10 +337,10 @@ FT_BEGIN_HEADER
|
||||
FT_UInt num_subs;
|
||||
FT_UInt max_subs;
|
||||
PFR_SubGlyphRec* subs;
|
||||
|
||||
|
||||
FT_GlyphLoader loader;
|
||||
FT_Bool path_begun;
|
||||
|
||||
|
||||
} PFR_GlyphRec, *PFR_Glyph;
|
||||
|
||||
|
||||
|
@ -597,10 +597,19 @@
|
||||
FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;
|
||||
FT_UInt num_segs;
|
||||
|
||||
|
||||
if ( table + length > valid->limit || length < 16 )
|
||||
/* in certain fonts, the 'length' field is invalid and goes */
|
||||
/* out of bound. We try to correct this here... */
|
||||
if ( length < 16 )
|
||||
FT_INVALID_TOO_SHORT;
|
||||
|
||||
if ( table + length > valid->limit )
|
||||
{
|
||||
if ( valid->level >= FT_VALIDATE_TIGHT )
|
||||
FT_INVALID_TOO_SHORT;
|
||||
|
||||
length = (FT_UInt)( valid->limit - table );
|
||||
}
|
||||
|
||||
p = table + 6;
|
||||
num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */
|
||||
|
||||
|
@ -132,7 +132,7 @@ class DocField:
|
||||
m = re_code_end.match( l )
|
||||
if m and len(m.group(1)) <= margin:
|
||||
# that's it, we finised the code sequence
|
||||
code = DocCode( margin, cur_lines )
|
||||
code = DocCode( 0, cur_lines )
|
||||
self.items.append( code )
|
||||
margin = -1
|
||||
cur_lines = []
|
||||
@ -289,9 +289,9 @@ class DocSection:
|
||||
self.description = block.get_markup_items( "description" )
|
||||
self.order = block.get_markup_words( "order" )
|
||||
return
|
||||
|
||||
|
||||
def reorder( self ):
|
||||
|
||||
|
||||
self.block_names = sort_order_list( self.block_names, self.order )
|
||||
|
||||
|
||||
@ -300,7 +300,7 @@ class ContentProcessor:
|
||||
def __init__( self ):
|
||||
"""initialize a block content processor"""
|
||||
self.reset()
|
||||
|
||||
|
||||
self.sections = {} # dictionary of documentation sections
|
||||
self.section = None # current documentation section
|
||||
|
||||
@ -379,7 +379,7 @@ class ContentProcessor:
|
||||
blocks = source_processor.blocks
|
||||
count = len(blocks)
|
||||
for n in range(count):
|
||||
|
||||
|
||||
source = blocks[n]
|
||||
if source.content:
|
||||
# this is a documentation comment, we need to catch
|
||||
@ -392,8 +392,8 @@ class ContentProcessor:
|
||||
m = m+1
|
||||
|
||||
doc_block = DocBlock( source, follow, self )
|
||||
|
||||
|
||||
|
||||
|
||||
def finish( self ):
|
||||
|
||||
# process all sections to extract their abstract, description
|
||||
@ -430,13 +430,13 @@ class ContentProcessor:
|
||||
chap = DocChapter( None )
|
||||
chap.sections = others
|
||||
self.chapters.append( chap )
|
||||
|
||||
|
||||
|
||||
|
||||
class DocBlock:
|
||||
|
||||
def __init__( self, source, follow, processor ):
|
||||
|
||||
|
||||
processor.reset()
|
||||
|
||||
self.source = source
|
||||
@ -451,8 +451,8 @@ class DocBlock:
|
||||
self.type = self.markups[0].tag
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
# compute block name from first markup paragraph
|
||||
try:
|
||||
markup = self.markups[0]
|
||||
@ -492,7 +492,7 @@ class DocBlock:
|
||||
# now strip the leading and trailing empty lines from the sources
|
||||
start = 0
|
||||
end = len( source )-1
|
||||
|
||||
|
||||
while start < end and not string.strip( source[start] ):
|
||||
start = start + 1
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
# "<Function>", "<Type>", etc..
|
||||
#
|
||||
# the routines used to process the content of documentation blocks
|
||||
# are not contained here, but in "doccontent.py"
|
||||
# are not contained here, but in "content.py"
|
||||
#
|
||||
# the classes and methods found here only deal with text parsing
|
||||
# and basic documentation block extraction
|
||||
@ -76,11 +76,11 @@ re_source_block_format1 = SourceBlockFormat( 1, start, column, start )
|
||||
#
|
||||
# format 2 documentation comment blocks look like the following:
|
||||
#
|
||||
# /************************************
|
||||
# /************************************ (at least 2 asterisks)
|
||||
# *
|
||||
# *
|
||||
# *
|
||||
# *
|
||||
# *
|
||||
# *
|
||||
# *
|
||||
# **/ (1 or more asterisks at the end)
|
||||
#
|
||||
# we define a few regular expressions here to detect them
|
||||
@ -94,12 +94,12 @@ start = r'''
|
||||
column = r'''
|
||||
\s* # any number of whitespace
|
||||
\*{1} # followed by precisely one asterisk
|
||||
(.*) # followed by anything (group1)
|
||||
(.*) # then anything (group1)
|
||||
'''
|
||||
|
||||
end = r'''
|
||||
\s* # any number of whitespace
|
||||
\*+/ # followed by at least on asterisk, then '/'
|
||||
\*+/ # followed by at least one asterisk, then '/'
|
||||
'''
|
||||
|
||||
re_source_block_format2 = SourceBlockFormat( 2, start, column, end )
|
||||
@ -151,7 +151,7 @@ re_source_crossref = re.compile( r'(\W*)(\w*)' )
|
||||
#
|
||||
# a list of reserved source keywords
|
||||
#
|
||||
re_source_keywords = re.compile( '''( typedef |
|
||||
re_source_keywords = re.compile( '''( typedef |
|
||||
struct |
|
||||
enum |
|
||||
union |
|
||||
@ -232,18 +232,18 @@ class SourceBlock:
|
||||
|
||||
# debugging only - not used in normal operations
|
||||
def dump( self ):
|
||||
|
||||
|
||||
if self.content:
|
||||
print "{{{content start---"
|
||||
for l in self.content:
|
||||
print l
|
||||
print "---content end}}}"
|
||||
return
|
||||
|
||||
|
||||
fmt = ""
|
||||
if self.format:
|
||||
fmt = repr(self.format.id) + " "
|
||||
|
||||
|
||||
for line in self.lines:
|
||||
print line
|
||||
|
||||
@ -281,22 +281,22 @@ class SourceProcessor:
|
||||
|
||||
def parse_file( self, filename ):
|
||||
"""parse a C source file, and adds its blocks to the processor's list"""
|
||||
|
||||
|
||||
self.reset()
|
||||
|
||||
|
||||
self.filename = filename
|
||||
|
||||
|
||||
fileinput.close()
|
||||
self.format = None
|
||||
self.lineno = 0
|
||||
self.lines = []
|
||||
|
||||
for line in fileinput.input( filename ):
|
||||
|
||||
|
||||
# strip trailing newlines, important on Windows machines !!
|
||||
if line[-1] == '\012':
|
||||
line = line[0:-1]
|
||||
|
||||
|
||||
if self.format == None:
|
||||
self.process_normal_line( line )
|
||||
|
||||
@ -304,25 +304,25 @@ class SourceProcessor:
|
||||
if self.format.end.match( line ):
|
||||
# that's a normal block end, add it to lines and
|
||||
# create a new block
|
||||
self.lines.append( line )
|
||||
# self.lines.append( line )
|
||||
self.add_block_lines()
|
||||
|
||||
|
||||
elif self.format.column.match( line ):
|
||||
# that's a normal column line, add it to 'lines'
|
||||
self.lines.append( line )
|
||||
|
||||
|
||||
else:
|
||||
# humm.. this is an unexcepted block end,
|
||||
# create a new block, but don't process the line
|
||||
self.add_block_lines()
|
||||
|
||||
|
||||
# we need to process the line again
|
||||
self.process_normal_line( line )
|
||||
|
||||
|
||||
# record the last lines
|
||||
self.add_block_lines()
|
||||
|
||||
|
||||
|
||||
|
||||
def process_normal_line( self, line ):
|
||||
"""process a normal line and check if it's the start of a new block"""
|
||||
@ -334,18 +334,18 @@ class SourceProcessor:
|
||||
|
||||
self.lines.append( line )
|
||||
|
||||
|
||||
|
||||
|
||||
def add_block_lines( self ):
|
||||
"""add the current accumulated lines, and create a new block"""
|
||||
if self.lines != []:
|
||||
block = SourceBlock( self, self.filename, self.lineno, self.lines )
|
||||
|
||||
|
||||
self.blocks.append( block )
|
||||
self.format = None
|
||||
self.lines = []
|
||||
|
||||
|
||||
|
||||
# debugging only, not used in normal operations
|
||||
def dump( self ):
|
||||
"""print all blocks in a processor"""
|
||||
|
@ -273,29 +273,10 @@ class HtmlFormatter(Formatter):
|
||||
|
||||
def print_html_field_list( self, fields ):
|
||||
print "<table valign=top cellpadding=3>"
|
||||
|
||||
# compute the maximum length of each field name
|
||||
# if it is
|
||||
#
|
||||
max = 0
|
||||
for field in fields:
|
||||
l = len( field.name )
|
||||
if l > max:
|
||||
max = l
|
||||
|
||||
head = "<tr valign=top><td><b>"
|
||||
inter = "</b></td><td>"
|
||||
foot = "</td></tr>"
|
||||
if max > 18:
|
||||
head = "<tr><td colspan=2><b>"
|
||||
inter = "</b></td></tr><tr><td width=5%></td><td>"
|
||||
foot = "<p></td></tr>"
|
||||
|
||||
for field in fields:
|
||||
print head + field.name + inter
|
||||
print "<tr valign=top><td><b>" + field.name + "</b></td><td>"
|
||||
self.print_html_items( field.items )
|
||||
print foot
|
||||
|
||||
print "</td></tr>"
|
||||
print "</table>"
|
||||
|
||||
|
||||
@ -338,7 +319,7 @@ class HtmlFormatter(Formatter):
|
||||
count = len( self.block_index )
|
||||
rows = (count + self.columns - 1)/self.columns
|
||||
|
||||
print "<center><table border=0 cellpadding=0 cellspacing=2>"
|
||||
print "<center><table border=0 cellpadding=0 cellspacing=0>"
|
||||
for r in range(rows):
|
||||
line = "<tr>"
|
||||
for c in range(self.columns):
|
||||
@ -416,9 +397,9 @@ class HtmlFormatter(Formatter):
|
||||
|
||||
# print section synopsys
|
||||
print section_synopsis_header
|
||||
print "<center><table cellspacing=5 cellpadding=2 border=0>"
|
||||
print "<center><table cellspacing=5 cellpadding=0 border=0>"
|
||||
|
||||
maxwidth = 1
|
||||
maxwidth = 0
|
||||
for b in section.blocks.values():
|
||||
if len(b.name) > maxwidth:
|
||||
maxwidth = len(b.name)
|
||||
|
Loading…
Reference in New Issue
Block a user