* 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:
David Turner 2002-10-05 14:57:03 +00:00
parent 4c09ae8002
commit 80171e06dd
14 changed files with 1071 additions and 161 deletions

View File

@ -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'.

View File

@ -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,

View File

@ -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
{

View File

@ -24,5 +24,6 @@
#include "pfrcmap.c"
#include "pfrobjs.c"
#include "pfrdrivr.c"
#include "pfrsbit.c"
/* END */

View File

@ -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,

View File

@ -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" ));

View File

@ -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
View 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
View 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__ */

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -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"""

View File

@ -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)