2002-04-20 07:38:33 +02:00
|
|
|
/***************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* pfrgload.c */
|
|
|
|
/* */
|
|
|
|
/* FreeType PFR glyph loader (body). */
|
|
|
|
/* */
|
2007-06-05 07:27:54 +02:00
|
|
|
/* Copyright 2002, 2003, 2005, 2007 by */
|
2002-04-20 07:38:33 +02:00
|
|
|
/* 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. */
|
|
|
|
/* */
|
|
|
|
/***************************************************************************/
|
|
|
|
|
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
#include "pfrgload.h"
|
* 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 16:57:03 +02:00
|
|
|
#include "pfrsbit.h"
|
2002-04-20 07:38:33 +02:00
|
|
|
#include "pfrload.h" /* for macro definitions */
|
2002-04-19 17:13:47 +02:00
|
|
|
#include FT_INTERNAL_DEBUG_H
|
|
|
|
|
2002-04-28 12:25:55 +02:00
|
|
|
#include "pfrerror.h"
|
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
#undef FT_COMPONENT
|
|
|
|
#define FT_COMPONENT trace_pfr
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
|
|
|
/***** *****/
|
|
|
|
/***** PFR GLYPH BUILDER *****/
|
|
|
|
/***** *****/
|
|
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
|
|
|
|
FT_LOCAL_DEF( void )
|
|
|
|
pfr_glyph_init( PFR_Glyph glyph,
|
|
|
|
FT_GlyphLoader loader )
|
|
|
|
{
|
|
|
|
FT_ZERO( glyph );
|
|
|
|
|
|
|
|
glyph->loader = loader;
|
|
|
|
glyph->path_begun = 0;
|
|
|
|
|
|
|
|
FT_GlyphLoader_Rewind( loader );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FT_LOCAL_DEF( void )
|
|
|
|
pfr_glyph_done( PFR_Glyph glyph )
|
|
|
|
{
|
|
|
|
FT_Memory memory = glyph->loader->memory;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
FT_FREE( glyph->x_control );
|
|
|
|
glyph->y_control = NULL;
|
|
|
|
|
|
|
|
glyph->max_xy_control = 0;
|
2007-06-05 07:27:54 +02:00
|
|
|
#if 0
|
2002-04-19 17:13:47 +02:00
|
|
|
glyph->num_x_control = 0;
|
|
|
|
glyph->num_y_control = 0;
|
2007-06-05 07:27:54 +02:00
|
|
|
#endif
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
FT_FREE( glyph->subs );
|
|
|
|
|
|
|
|
glyph->max_subs = 0;
|
|
|
|
glyph->num_subs = 0;
|
|
|
|
|
|
|
|
glyph->loader = NULL;
|
|
|
|
glyph->path_begun = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
/* close current contour, if any */
|
2002-04-19 17:13:47 +02:00
|
|
|
static void
|
|
|
|
pfr_glyph_close_contour( PFR_Glyph glyph )
|
|
|
|
{
|
|
|
|
FT_GlyphLoader loader = glyph->loader;
|
|
|
|
FT_Outline* outline = &loader->current.outline;
|
|
|
|
FT_Int last, first;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
if ( !glyph->path_begun )
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* compute first and last point indices in current glyph outline */
|
|
|
|
last = outline->n_points - 1;
|
|
|
|
first = 0;
|
|
|
|
if ( outline->n_contours > 0 )
|
2002-04-20 07:38:33 +02:00
|
|
|
first = outline->contours[outline->n_contours - 1];
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
/* if the last point falls on the same location than the first one */
|
|
|
|
/* we need to delete it */
|
|
|
|
if ( last > first )
|
|
|
|
{
|
|
|
|
FT_Vector* p1 = outline->points + first;
|
|
|
|
FT_Vector* p2 = outline->points + last;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
if ( p1->x == p2->x && p1->y == p2->y )
|
|
|
|
{
|
|
|
|
outline->n_points--;
|
|
|
|
last--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* don't add empty contours */
|
|
|
|
if ( last >= first )
|
2002-04-20 07:38:33 +02:00
|
|
|
outline->contours[outline->n_contours++] = (short)last;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
glyph->path_begun = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
/* reset glyph to start the loading of a new glyph */
|
2002-04-19 17:13:47 +02:00
|
|
|
static void
|
|
|
|
pfr_glyph_start( PFR_Glyph glyph )
|
|
|
|
{
|
|
|
|
glyph->path_begun = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static FT_Error
|
|
|
|
pfr_glyph_line_to( PFR_Glyph glyph,
|
|
|
|
FT_Vector* to )
|
|
|
|
{
|
|
|
|
FT_GlyphLoader loader = glyph->loader;
|
|
|
|
FT_Outline* outline = &loader->current.outline;
|
|
|
|
FT_Error error;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
|
|
|
/* check that we have begun a new path */
|
2002-04-19 17:13:47 +02:00
|
|
|
FT_ASSERT( glyph->path_begun != 0 );
|
|
|
|
|
2005-10-28 18:14:14 +02:00
|
|
|
error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 0 );
|
2002-04-19 17:13:47 +02:00
|
|
|
if ( !error )
|
|
|
|
{
|
|
|
|
FT_UInt n = outline->n_points;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
outline->points[n] = *to;
|
* massive re-formatting changes to many, many source files. I don't
want to list them all here. The operations performed were all logical
transformations of the sources:
- trying to convert all enums and constants to CAPITALIZED_STYLE, with
#define definitions like
#define my_old_constants MY_NEW_CONSTANT
- big, big update of the documentation comments
* include/freetype/freetype.h, src/base/ftobjs.c, src/smooth/ftsmooth.c,
include/freetype/ftimage.h: adding support for LCD-optimized rendering
though the new constants/enums:
FT_RENDER_MODE_LCD, FT_RENDER_MODE_LCD_V
FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_LCD_V
this is still work in progress, don't expect everything to work correctly
though most of the features have been implemented.
* adding new FT_LOAD_XXX flags, used to specify both hinting and rendering
targets:
FT_LOAD_TARGET_NORMAL :: anti-aliased hinting & rendering
FT_LOAD_TARGET_MONO :: monochrome bitmaps
FT_LOAD_TARGET_LCD :: horizontal RGB/BGR decimated hinting & rendering
FT_LOAD_TARGET_LCD_V :: vertical RGB/BGR decimated hinting & rendering
note that FT_LOAD_TARGET_NORMAL is 0, which means that the default
behaviour of the font engine is _unchanged_.
2002-08-27 22:20:29 +02:00
|
|
|
outline->tags [n] = FT_CURVE_TAG_ON;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
outline->n_points++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static FT_Error
|
|
|
|
pfr_glyph_curve_to( PFR_Glyph glyph,
|
|
|
|
FT_Vector* control1,
|
|
|
|
FT_Vector* control2,
|
|
|
|
FT_Vector* to )
|
|
|
|
{
|
|
|
|
FT_GlyphLoader loader = glyph->loader;
|
|
|
|
FT_Outline* outline = &loader->current.outline;
|
|
|
|
FT_Error error;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
|
|
|
/* check that we have begun a new path */
|
2002-04-19 17:13:47 +02:00
|
|
|
FT_ASSERT( glyph->path_begun != 0 );
|
|
|
|
|
2005-10-28 18:14:14 +02:00
|
|
|
error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );
|
2002-04-19 17:13:47 +02:00
|
|
|
if ( !error )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
FT_Vector* vec = outline->points + outline->n_points;
|
|
|
|
FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points;
|
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
vec[0] = *control1;
|
|
|
|
vec[1] = *control2;
|
|
|
|
vec[2] = *to;
|
* massive re-formatting changes to many, many source files. I don't
want to list them all here. The operations performed were all logical
transformations of the sources:
- trying to convert all enums and constants to CAPITALIZED_STYLE, with
#define definitions like
#define my_old_constants MY_NEW_CONSTANT
- big, big update of the documentation comments
* include/freetype/freetype.h, src/base/ftobjs.c, src/smooth/ftsmooth.c,
include/freetype/ftimage.h: adding support for LCD-optimized rendering
though the new constants/enums:
FT_RENDER_MODE_LCD, FT_RENDER_MODE_LCD_V
FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_LCD_V
this is still work in progress, don't expect everything to work correctly
though most of the features have been implemented.
* adding new FT_LOAD_XXX flags, used to specify both hinting and rendering
targets:
FT_LOAD_TARGET_NORMAL :: anti-aliased hinting & rendering
FT_LOAD_TARGET_MONO :: monochrome bitmaps
FT_LOAD_TARGET_LCD :: horizontal RGB/BGR decimated hinting & rendering
FT_LOAD_TARGET_LCD_V :: vertical RGB/BGR decimated hinting & rendering
note that FT_LOAD_TARGET_NORMAL is 0, which means that the default
behaviour of the font engine is _unchanged_.
2002-08-27 22:20:29 +02:00
|
|
|
tag[0] = FT_CURVE_TAG_CUBIC;
|
|
|
|
tag[1] = FT_CURVE_TAG_CUBIC;
|
|
|
|
tag[2] = FT_CURVE_TAG_ON;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
outline->n_points = (FT_Short)( outline->n_points + 3 );
|
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static FT_Error
|
|
|
|
pfr_glyph_move_to( PFR_Glyph glyph,
|
|
|
|
FT_Vector* to )
|
|
|
|
{
|
|
|
|
FT_GlyphLoader loader = glyph->loader;
|
|
|
|
FT_Error error;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
/* close current contour if any */
|
|
|
|
pfr_glyph_close_contour( glyph );
|
|
|
|
|
|
|
|
/* indicate that a new contour has started */
|
|
|
|
glyph->path_begun = 1;
|
|
|
|
|
2003-12-12 16:38:39 +01:00
|
|
|
/* check that there is space for a new contour and a new point */
|
2005-10-28 18:14:14 +02:00
|
|
|
error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 1 );
|
2002-04-19 17:13:47 +02:00
|
|
|
if ( !error )
|
|
|
|
/* add new start point */
|
|
|
|
error = pfr_glyph_line_to( glyph, to );
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
pfr_glyph_end( PFR_Glyph glyph )
|
|
|
|
{
|
|
|
|
/* close current contour if any */
|
|
|
|
pfr_glyph_close_contour( glyph );
|
|
|
|
|
|
|
|
/* merge the current glyph into the stack */
|
|
|
|
FT_GlyphLoader_Add( glyph->loader );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
|
|
|
/***** *****/
|
|
|
|
/***** PFR GLYPH LOADER *****/
|
|
|
|
/***** *****/
|
|
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
/* load a simple glyph */
|
2002-04-19 17:13:47 +02:00
|
|
|
static FT_Error
|
|
|
|
pfr_glyph_load_simple( PFR_Glyph glyph,
|
|
|
|
FT_Byte* p,
|
|
|
|
FT_Byte* limit )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
FT_Error error = 0;
|
2002-04-19 17:13:47 +02:00
|
|
|
FT_Memory memory = glyph->loader->memory;
|
|
|
|
FT_UInt flags, x_count, y_count, i, count, mask;
|
|
|
|
FT_Int x;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
|
|
|
PFR_CHECK( 1 );
|
|
|
|
flags = PFR_NEXT_BYTE( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
/* test for composite glyphs */
|
2007-06-05 07:27:54 +02:00
|
|
|
if ( flags & PFR_GLYPH_IS_COMPOUND )
|
|
|
|
goto Failure;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
x_count = 0;
|
|
|
|
y_count = 0;
|
|
|
|
|
|
|
|
if ( flags & PFR_GLYPH_1BYTE_XYCOUNT )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 1 );
|
|
|
|
count = PFR_NEXT_BYTE( p );
|
|
|
|
x_count = ( count & 15 );
|
|
|
|
y_count = ( count >> 4 );
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( flags & PFR_GLYPH_XCOUNT )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 1 );
|
|
|
|
x_count = PFR_NEXT_BYTE( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( flags & PFR_GLYPH_YCOUNT )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 1 );
|
|
|
|
y_count = PFR_NEXT_BYTE( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
count = x_count + y_count;
|
|
|
|
|
|
|
|
/* re-allocate array when necessary */
|
|
|
|
if ( count > glyph->max_xy_control )
|
|
|
|
{
|
2003-12-24 02:10:46 +01:00
|
|
|
FT_UInt new_max = FT_PAD_CEIL( count, 8 );
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
|
|
|
if ( FT_RENEW_ARRAY( glyph->x_control,
|
|
|
|
glyph->max_xy_control,
|
|
|
|
new_max ) )
|
2002-04-19 17:13:47 +02:00
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
glyph->max_xy_control = new_max;
|
|
|
|
}
|
|
|
|
|
|
|
|
glyph->y_control = glyph->x_control + x_count;
|
|
|
|
|
|
|
|
mask = 0;
|
|
|
|
x = 0;
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
for ( i = 0; i < count; i++ )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
if ( ( i & 7 ) == 0 )
|
2002-04-19 17:13:47 +02:00
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 1 );
|
|
|
|
mask = PFR_NEXT_BYTE( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
2002-06-22 11:36:53 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
if ( mask & 1 )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 2 );
|
|
|
|
x = PFR_NEXT_SHORT( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 1 );
|
|
|
|
x += PFR_NEXT_BYTE( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
2002-06-22 11:36:53 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
glyph->x_control[i] = x;
|
|
|
|
|
|
|
|
mask >>= 1;
|
|
|
|
}
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
/* XXX: for now we ignore the secondary stroke and edge definitions */
|
|
|
|
/* since we don't want to support native PFR hinting */
|
|
|
|
/* */
|
2002-04-19 17:13:47 +02:00
|
|
|
if ( flags & PFR_GLYPH_EXTRA_ITEMS )
|
|
|
|
{
|
|
|
|
error = pfr_extra_items_skip( &p, limit );
|
2002-04-20 07:38:33 +02:00
|
|
|
if ( error )
|
|
|
|
goto Exit;
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pfr_glyph_start( glyph );
|
|
|
|
|
|
|
|
/* now load a simple glyph */
|
|
|
|
{
|
|
|
|
FT_Vector pos[4];
|
|
|
|
FT_Vector* cur;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
pos[0].x = pos[0].y = 0;
|
|
|
|
pos[3] = pos[0];
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
FT_Int format, args_format = 0, args_count, n;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
/***************************************************************/
|
|
|
|
/* read instruction */
|
|
|
|
/* */
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 1 );
|
|
|
|
format = PFR_NEXT_BYTE( p );
|
|
|
|
|
|
|
|
switch ( format >> 4 )
|
2002-04-19 17:13:47 +02:00
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
case 0: /* end glyph */
|
|
|
|
FT_TRACE6(( "- end glyph" ));
|
|
|
|
args_count = 0;
|
|
|
|
break;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
case 1: /* general line operation */
|
|
|
|
FT_TRACE6(( "- general line" ));
|
|
|
|
goto Line1;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
case 4: /* move to inside contour */
|
|
|
|
FT_TRACE6(( "- move to inside" ));
|
|
|
|
goto Line1;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
case 5: /* move to outside contour */
|
|
|
|
FT_TRACE6(( "- move to outside" ));
|
|
|
|
Line1:
|
|
|
|
args_format = format & 15;
|
|
|
|
args_count = 1;
|
|
|
|
break;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
case 2: /* horizontal line to */
|
|
|
|
FT_TRACE6(( "- horizontal line to cx.%d", format & 15 ));
|
|
|
|
pos[0].y = pos[3].y;
|
|
|
|
pos[0].x = glyph->x_control[format & 15];
|
|
|
|
pos[3] = pos[0];
|
|
|
|
args_count = 0;
|
|
|
|
break;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
case 3: /* vertical line to */
|
|
|
|
FT_TRACE6(( "- vertical line to cy.%d", format & 15 ));
|
|
|
|
pos[0].x = pos[3].x;
|
|
|
|
pos[0].y = glyph->y_control[format & 15];
|
|
|
|
pos[3] = pos[0];
|
|
|
|
args_count = 0;
|
|
|
|
break;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
case 6: /* horizontal to vertical curve */
|
|
|
|
FT_TRACE6(( "- hv curve " ));
|
|
|
|
args_format = 0xB8E;
|
|
|
|
args_count = 3;
|
|
|
|
break;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
case 7: /* vertical to horizontal curve */
|
|
|
|
FT_TRACE6(( "- vh curve" ));
|
|
|
|
args_format = 0xE2B;
|
|
|
|
args_count = 3;
|
|
|
|
break;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
default: /* general curve to */
|
|
|
|
FT_TRACE6(( "- general curve" ));
|
|
|
|
args_count = 4;
|
|
|
|
args_format = format & 15;
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************/
|
|
|
|
/* now read arguments */
|
|
|
|
/* */
|
|
|
|
cur = pos;
|
|
|
|
for ( n = 0; n < args_count; n++ )
|
|
|
|
{
|
2007-06-05 07:27:54 +02:00
|
|
|
FT_UInt idx;
|
|
|
|
FT_Int delta;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
/* read the X argument */
|
|
|
|
switch ( args_format & 3 )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
case 0: /* 8-bit index */
|
|
|
|
PFR_CHECK( 1 );
|
2002-08-06 23:47:40 +02:00
|
|
|
idx = PFR_NEXT_BYTE( p );
|
2007-06-05 07:27:54 +02:00
|
|
|
if ( idx > x_count )
|
|
|
|
goto Failure;
|
2002-08-06 23:47:40 +02:00
|
|
|
cur->x = glyph->x_control[idx];
|
|
|
|
FT_TRACE7(( " cx#%d", idx ));
|
2002-04-20 07:38:33 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: /* 16-bit value */
|
|
|
|
PFR_CHECK( 2 );
|
|
|
|
cur->x = PFR_NEXT_SHORT( p );
|
|
|
|
FT_TRACE7(( " x.%d", cur->x ));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2: /* 8-bit delta */
|
|
|
|
PFR_CHECK( 1 );
|
|
|
|
delta = PFR_NEXT_INT8( p );
|
|
|
|
cur->x = pos[3].x + delta;
|
|
|
|
FT_TRACE7(( " dx.%d", delta ));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
FT_TRACE7(( " |" ));
|
|
|
|
cur->x = pos[3].x;
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* read the Y argument */
|
2002-04-20 07:38:33 +02:00
|
|
|
switch ( ( args_format >> 2 ) & 3 )
|
2002-04-19 17:13:47 +02:00
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
case 0: /* 8-bit index */
|
|
|
|
PFR_CHECK( 1 );
|
2002-08-06 23:47:40 +02:00
|
|
|
idx = PFR_NEXT_BYTE( p );
|
2007-06-05 07:27:54 +02:00
|
|
|
if ( idx > y_count )
|
|
|
|
goto Failure;
|
2002-08-06 23:47:40 +02:00
|
|
|
cur->y = glyph->y_control[idx];
|
|
|
|
FT_TRACE7(( " cy#%d", idx ));
|
2002-04-20 07:38:33 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: /* 16-bit absolute value */
|
|
|
|
PFR_CHECK( 2 );
|
|
|
|
cur->y = PFR_NEXT_SHORT( p );
|
|
|
|
FT_TRACE7(( " y.%d", cur->y ));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2: /* 8-bit delta */
|
|
|
|
PFR_CHECK( 1 );
|
|
|
|
delta = PFR_NEXT_INT8( p );
|
|
|
|
cur->y = pos[3].y + delta;
|
|
|
|
FT_TRACE7(( " dy.%d", delta ));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
FT_TRACE7(( " -" ));
|
|
|
|
cur->y = pos[3].y;
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* read the additional format flag for the general curve */
|
|
|
|
if ( n == 0 && args_count == 4 )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 1 );
|
|
|
|
args_format = PFR_NEXT_BYTE( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
args_count--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
args_format >>= 4;
|
|
|
|
|
|
|
|
/* save the previous point */
|
|
|
|
pos[3] = cur[0];
|
|
|
|
cur++;
|
|
|
|
}
|
|
|
|
|
|
|
|
FT_TRACE7(( "\n" ));
|
|
|
|
|
|
|
|
/***********************************************************/
|
|
|
|
/* finally, execute instruction */
|
|
|
|
/* */
|
2002-04-20 07:38:33 +02:00
|
|
|
switch ( format >> 4 )
|
2002-04-19 17:13:47 +02:00
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
case 0: /* end glyph => EXIT */
|
|
|
|
pfr_glyph_end( glyph );
|
|
|
|
goto Exit;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
case 1: /* line operations */
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
error = pfr_glyph_line_to( glyph, pos );
|
|
|
|
goto Test_Error;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
case 4: /* move to inside contour */
|
|
|
|
case 5: /* move to outside contour */
|
|
|
|
error = pfr_glyph_move_to( glyph, pos );
|
|
|
|
goto Test_Error;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
default: /* curve operations */
|
|
|
|
error = pfr_glyph_curve_to( glyph, pos, pos + 1, pos + 2 );
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
Test_Error: /* test error condition */
|
|
|
|
if ( error )
|
|
|
|
goto Exit;
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
} /* for (;;) */
|
|
|
|
}
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
|
2007-06-05 07:27:54 +02:00
|
|
|
Failure:
|
2002-04-19 17:13:47 +02:00
|
|
|
Too_Short:
|
2002-04-28 12:25:55 +02:00
|
|
|
error = PFR_Err_Invalid_Table;
|
|
|
|
FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" ));
|
2002-04-19 17:13:47 +02:00
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
/* load a composite/compound glyph */
|
2002-04-19 17:13:47 +02:00
|
|
|
static FT_Error
|
|
|
|
pfr_glyph_load_compound( PFR_Glyph glyph,
|
|
|
|
FT_Byte* p,
|
|
|
|
FT_Byte* limit )
|
|
|
|
{
|
|
|
|
FT_Error error = 0;
|
|
|
|
FT_GlyphLoader loader = glyph->loader;
|
|
|
|
FT_Memory memory = loader->memory;
|
|
|
|
PFR_SubGlyph subglyph;
|
|
|
|
FT_UInt flags, i, count, org_count;
|
|
|
|
FT_Int x_pos, y_pos;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
|
|
|
PFR_CHECK( 1 );
|
|
|
|
flags = PFR_NEXT_BYTE( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
/* test for composite glyphs */
|
2007-06-05 07:27:54 +02:00
|
|
|
if ( !( flags & PFR_GLYPH_IS_COMPOUND ) )
|
|
|
|
goto Failure;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
count = flags & 0x3F;
|
|
|
|
|
|
|
|
/* ignore extra items when present */
|
|
|
|
/* */
|
|
|
|
if ( flags & PFR_GLYPH_EXTRA_ITEMS )
|
|
|
|
{
|
|
|
|
error = pfr_extra_items_skip( &p, limit );
|
|
|
|
if (error) goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we can't rely on the FT_GlyphLoader to load sub-glyphs, because */
|
2002-04-20 07:38:33 +02:00
|
|
|
/* the PFR format is dumb, using direct file offsets to point to the */
|
|
|
|
/* sub-glyphs (instead of glyph indices). Sigh. */
|
2002-04-19 17:13:47 +02:00
|
|
|
/* */
|
2002-04-20 07:38:33 +02:00
|
|
|
/* For now, we load the list of sub-glyphs into a different array */
|
2002-04-19 17:13:47 +02:00
|
|
|
/* but this will prevent us from using the auto-hinter at its best */
|
2002-04-20 07:38:33 +02:00
|
|
|
/* quality. */
|
2002-04-19 17:13:47 +02:00
|
|
|
/* */
|
|
|
|
org_count = glyph->num_subs;
|
|
|
|
|
|
|
|
if ( org_count + count > glyph->max_subs )
|
|
|
|
{
|
|
|
|
FT_UInt new_max = ( org_count + count + 3 ) & -4;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
glyph->max_subs = new_max;
|
|
|
|
}
|
|
|
|
|
|
|
|
subglyph = glyph->subs + org_count;
|
|
|
|
|
|
|
|
for ( i = 0; i < count; i++, subglyph++ )
|
|
|
|
{
|
|
|
|
FT_UInt format;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-06-22 15:35:41 +02:00
|
|
|
x_pos = 0;
|
|
|
|
y_pos = 0;
|
2002-06-22 11:36:53 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 1 );
|
|
|
|
format = PFR_NEXT_BYTE( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
/* read scale when available */
|
|
|
|
subglyph->x_scale = 0x10000L;
|
|
|
|
if ( format & PFR_SUBGLYPH_XSCALE )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 2 );
|
|
|
|
subglyph->x_scale = PFR_NEXT_SHORT( p ) << 4;
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
subglyph->y_scale = 0x10000L;
|
|
|
|
if ( format & PFR_SUBGLYPH_YSCALE )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 2 );
|
|
|
|
subglyph->y_scale = PFR_NEXT_SHORT( p ) << 4;
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* read offset */
|
|
|
|
switch ( format & 3 )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
case 1:
|
|
|
|
PFR_CHECK( 2 );
|
|
|
|
x_pos = PFR_NEXT_SHORT( p );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
PFR_CHECK( 1 );
|
|
|
|
x_pos += PFR_NEXT_INT8( p );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
;
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
switch ( ( format >> 2 ) & 3 )
|
2002-04-19 17:13:47 +02:00
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
case 1:
|
|
|
|
PFR_CHECK( 2 );
|
|
|
|
y_pos = PFR_NEXT_SHORT( p );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
PFR_CHECK( 1 );
|
|
|
|
y_pos += PFR_NEXT_INT8( p );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
;
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
2002-06-22 11:36:53 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
subglyph->x_delta = x_pos;
|
|
|
|
subglyph->y_delta = y_pos;
|
|
|
|
|
|
|
|
/* read glyph position and size now */
|
|
|
|
if ( format & PFR_SUBGLYPH_2BYTE_SIZE )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 2 );
|
|
|
|
subglyph->gps_size = PFR_NEXT_USHORT( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 1 );
|
|
|
|
subglyph->gps_size = PFR_NEXT_BYTE( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( format & PFR_SUBGLYPH_3BYTE_OFFSET )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 3 );
|
|
|
|
subglyph->gps_offset = PFR_NEXT_LONG( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
PFR_CHECK( 2 );
|
|
|
|
subglyph->gps_offset = PFR_NEXT_USHORT( p );
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
glyph->num_subs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
|
2007-06-05 07:27:54 +02:00
|
|
|
Failure:
|
2002-04-19 17:13:47 +02:00
|
|
|
Too_Short:
|
2002-04-28 12:25:55 +02:00
|
|
|
error = PFR_Err_Invalid_Table;
|
|
|
|
FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" ));
|
2002-04-19 17:13:47 +02:00
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static FT_Error
|
2002-04-20 07:38:33 +02:00
|
|
|
pfr_glyph_load_rec( PFR_Glyph glyph,
|
|
|
|
FT_Stream stream,
|
|
|
|
FT_ULong gps_offset,
|
|
|
|
FT_ULong offset,
|
|
|
|
FT_ULong size )
|
2002-04-19 17:13:47 +02:00
|
|
|
{
|
|
|
|
FT_Error error;
|
|
|
|
FT_Byte* p;
|
|
|
|
FT_Byte* limit;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
if ( FT_STREAM_SEEK( gps_offset + offset ) ||
|
|
|
|
FT_FRAME_ENTER( size ) )
|
2002-04-20 07:38:33 +02:00
|
|
|
goto Exit;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
p = (FT_Byte*)stream->cursor;
|
2002-04-19 17:13:47 +02:00
|
|
|
limit = p + size;
|
|
|
|
|
|
|
|
if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND )
|
|
|
|
{
|
|
|
|
FT_Int n, old_count, count;
|
|
|
|
FT_GlyphLoader loader = glyph->loader;
|
|
|
|
FT_Outline* base = &loader->base.outline;
|
|
|
|
|
|
|
|
|
|
|
|
old_count = glyph->num_subs;
|
|
|
|
|
|
|
|
/* this is a compound glyph - load it */
|
|
|
|
error = pfr_glyph_load_compound( glyph, p, limit );
|
|
|
|
|
|
|
|
FT_FRAME_EXIT();
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
if ( error )
|
|
|
|
goto Exit;
|
2002-04-19 17:13:47 +02:00
|
|
|
|
|
|
|
count = glyph->num_subs - old_count;
|
|
|
|
|
|
|
|
/* now, load each individual glyph */
|
|
|
|
for ( n = 0; n < count; n++ )
|
|
|
|
{
|
|
|
|
FT_Int i, old_points, num_points;
|
|
|
|
PFR_SubGlyph subglyph;
|
|
|
|
|
|
|
|
|
|
|
|
subglyph = glyph->subs + old_count + n;
|
|
|
|
old_points = base->n_points;
|
|
|
|
|
|
|
|
error = pfr_glyph_load_rec( glyph, stream, gps_offset,
|
2002-04-20 07:38:33 +02:00
|
|
|
subglyph->gps_offset,
|
|
|
|
subglyph->gps_size );
|
2002-04-19 17:13:47 +02:00
|
|
|
if ( error )
|
|
|
|
goto Exit;
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
/* note that `glyph->subs' might have been re-allocated */
|
2002-04-19 17:13:47 +02:00
|
|
|
subglyph = glyph->subs + old_count + n;
|
|
|
|
num_points = base->n_points - old_points;
|
|
|
|
|
|
|
|
/* translate and eventually scale the new glyph points */
|
|
|
|
if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L )
|
|
|
|
{
|
|
|
|
FT_Vector* vec = base->points + old_points;
|
|
|
|
|
|
|
|
|
|
|
|
for ( i = 0; i < num_points; i++, vec++ )
|
|
|
|
{
|
2002-04-20 07:38:33 +02:00
|
|
|
vec->x = FT_MulFix( vec->x, subglyph->x_scale ) +
|
|
|
|
subglyph->x_delta;
|
|
|
|
vec->y = FT_MulFix( vec->y, subglyph->y_scale ) +
|
|
|
|
subglyph->y_delta;
|
2002-04-19 17:13:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FT_Vector* vec = loader->base.outline.points + old_points;
|
|
|
|
|
|
|
|
|
|
|
|
for ( i = 0; i < num_points; i++, vec++ )
|
|
|
|
{
|
|
|
|
vec->x += subglyph->x_delta;
|
|
|
|
vec->y += subglyph->y_delta;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* proceed to next sub-glyph */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* load a simple glyph */
|
|
|
|
error = pfr_glyph_load_simple( glyph, p, limit );
|
|
|
|
|
|
|
|
FT_FRAME_EXIT();
|
|
|
|
}
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
* 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 16:57:03 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
2002-04-20 07:38:33 +02:00
|
|
|
pfr_glyph_load( PFR_Glyph glyph,
|
|
|
|
FT_Stream stream,
|
|
|
|
FT_ULong gps_offset,
|
|
|
|
FT_ULong offset,
|
|
|
|
FT_ULong size )
|
2002-04-19 17:13:47 +02:00
|
|
|
{
|
|
|
|
/* initialize glyph loader */
|
|
|
|
FT_GlyphLoader_Rewind( glyph->loader );
|
|
|
|
|
2005-02-10 16:06:00 +01:00
|
|
|
glyph->num_subs = 0;
|
|
|
|
|
2002-04-19 17:13:47 +02:00
|
|
|
/* load the glyph, recursively when needed */
|
|
|
|
return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size );
|
|
|
|
}
|
|
|
|
|
2002-04-20 07:38:33 +02:00
|
|
|
|
|
|
|
/* END */
|