parameter sign-ness in callback function * include/freetype/config/ftmodule.h, include/freetype/internal/fttrace.h, src/Jamfile, src/pfr/*: adding a PFR font driver to the FreeType sources. Not that it doesn't support embedded bitmaps or kerning tables for now.. * include/freetype/internal/ftmemory.h: adding the FT_MEM_ZERO and FT_ZERO macros * include/freetype/internal/ftstream.h: adding the FT_NEXT_OFF3, FT_NEXT_UOFF3, FT_NEXT_OFF3_LE and FT_NEXT_UOFF3_LE to parse in-memory 24-bit integers.BRANCH-2-1-5
parent
b97e32c7ad
commit
596ba53283
25 changed files with 2604 additions and 3 deletions
@ -0,0 +1,23 @@ |
||||
# FreeType 2 src/pfr Jamfile (c) 2002 David Turner |
||||
# |
||||
|
||||
SubDir FT2_TOP src pfr ; |
||||
|
||||
SubDirHdrs [ FT2_SubDir src pfr ] ; |
||||
|
||||
{ |
||||
local _sources ; |
||||
|
||||
if $(FT2_MULTI) |
||||
{ |
||||
_sources = pfrdrivr pfrgload pfrload pfrobjs pfrcmap ; |
||||
} |
||||
else |
||||
{ |
||||
_sources = pfr ; |
||||
} |
||||
|
||||
Library $(FT2_LIB) : $(_sources).c ; |
||||
} |
||||
|
||||
# end of src/pfr Jamfile |
@ -0,0 +1,23 @@ |
||||
# |
||||
# FreeType 2 PFR driver compilation rules for VMS |
||||
# |
||||
|
||||
|
||||
# Copyright 1996-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. |
||||
|
||||
|
||||
CFLAGS=$(COMP_FLAGS)$(DEBUG)/include=([--.include],[--.src.pfr]) |
||||
|
||||
OBJS=pfr.obj |
||||
|
||||
all : $(OBJS) |
||||
library [--.lib]freetype.olb $(OBJS) |
||||
|
||||
# EOF |
@ -0,0 +1,22 @@ |
||||
#
|
||||
# FreeType 2 PFR module definition
|
||||
#
|
||||
|
||||
|
||||
# Copyright 1996-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.
|
||||
|
||||
|
||||
make_module_list: add_pfr_driver |
||||
|
||||
add_pfr_driver: |
||||
$(OPEN_DRIVER)pfr_driver_class$(CLOSE_DRIVER)
|
||||
$(ECHO_DRIVER)pfr $(ECHO_DRIVER_DESC)PFR/TrueDoc font files with extension *.pfr$(ECHO_DRIVER_DONE)
|
||||
|
||||
# EOF
|
@ -0,0 +1,28 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* pfr.c */ |
||||
/* */ |
||||
/* FreeType PFR driver component */ |
||||
/* */ |
||||
/* Copyright 1996-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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
#define FT_MAKE_OPTION_SINGLE_OBJECT |
||||
|
||||
#include <ft2build.h> |
||||
|
||||
#include "pfrload.c" |
||||
#include "pfrgload.c" |
||||
#include "pfrcmap.c" |
||||
#include "pfrobjs.c" |
||||
#include "pfrdrivr.c" |
||||
|
||||
/* END */ |
@ -0,0 +1,129 @@ |
||||
#include "pfrcmap.h" |
||||
#include "pfrobjs.h" |
||||
#include FT_INTERNAL_DEBUG_H |
||||
|
||||
FT_CALLBACK_DEF( FT_Error ) |
||||
pfr_cmap_init( PFR_CMap cmap ) |
||||
{ |
||||
PFR_Face face = (PFR_Face)FT_CMAP_FACE(cmap); |
||||
|
||||
|
||||
cmap->num_chars = face->phy_font.num_chars; |
||||
cmap->chars = face->phy_font.chars; |
||||
|
||||
/* just for safety, check that the character entries are correctly */ |
||||
/* sorted in increasing character code order.. */ |
||||
{ |
||||
FT_UInt n; |
||||
|
||||
for ( n = 1; n < cmap->num_chars; n++ ) |
||||
{ |
||||
if ( cmap->chars[n-1].char_code >= cmap->chars[n].char_code ) |
||||
FT_ASSERT(0); |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
|
||||
FT_CALLBACK_DEF( void ) |
||||
pfr_cmap_done( PFR_CMap cmap ) |
||||
{ |
||||
cmap->chars = NULL; |
||||
cmap->num_chars = 0; |
||||
} |
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_UInt ) |
||||
pfr_cmap_char_index( PFR_CMap cmap, |
||||
FT_UInt32 char_code ) |
||||
{ |
||||
FT_UInt min = 0; |
||||
FT_UInt max = cmap->num_chars; |
||||
FT_UInt mid; |
||||
PFR_Char gchar; |
||||
|
||||
|
||||
while ( min < max ) |
||||
{ |
||||
mid = min + ( max - min ) / 2; |
||||
gchar = cmap->chars + mid; |
||||
|
||||
if ( gchar->char_code == char_code ) |
||||
return mid; |
||||
|
||||
if ( gchar->char_code < char_code ) |
||||
min = mid + 1; |
||||
else |
||||
max = mid; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
FT_CALLBACK_DEF( FT_UInt ) |
||||
pfr_cmap_char_next( PFR_CMap cmap, |
||||
FT_UInt32 *pchar_code ) |
||||
{ |
||||
FT_UInt result = 0; |
||||
FT_UInt32 char_code = *pchar_code + 1; |
||||
|
||||
|
||||
Restart: |
||||
{ |
||||
FT_UInt min = 0; |
||||
FT_UInt max = cmap->num_chars; |
||||
FT_UInt mid; |
||||
PFR_Char gchar; |
||||
|
||||
|
||||
while ( min < max ) |
||||
{ |
||||
mid = min + ( ( max - min ) >> 1 ); |
||||
gchar = cmap->chars + mid; |
||||
|
||||
if ( gchar->char_code == char_code ) |
||||
{ |
||||
result = mid; |
||||
if ( result != 0 ) |
||||
goto Exit; |
||||
|
||||
char_code++; |
||||
goto Restart; |
||||
} |
||||
|
||||
if ( gchar->char_code < char_code ) |
||||
min = mid+1; |
||||
else |
||||
max = mid; |
||||
} |
||||
|
||||
/* we didn't find it, but we have a pair just above it */ |
||||
char_code = 0; |
||||
|
||||
if ( min < cmap->num_chars ) |
||||
{ |
||||
gchar = cmap->chars + min; |
||||
result = min; |
||||
if ( result != 0 ) |
||||
char_code = gchar->char_code; |
||||
} |
||||
} |
||||
|
||||
Exit: |
||||
*pchar_code = char_code; |
||||
return result; |
||||
} |
||||
|
||||
|
||||
FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec |
||||
pfr_cmap_class_rec = |
||||
{ |
||||
sizeof ( PFR_CMapRec ), |
||||
|
||||
(FT_CMap_InitFunc) pfr_cmap_init, |
||||
(FT_CMap_DoneFunc) pfr_cmap_done, |
||||
(FT_CMap_CharIndexFunc) pfr_cmap_char_index, |
||||
(FT_CMap_CharNextFunc) pfr_cmap_char_next |
||||
}; |
@ -0,0 +1,23 @@ |
||||
#ifndef __PFR_CMAP_H__ |
||||
#define __PFR_CMAP_H__ |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_INTERNAL_OBJECTS_H |
||||
#include "pfrtypes.h" |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
typedef struct PFR_CMapRec_ |
||||
{ |
||||
FT_CMapRec cmap; |
||||
FT_UInt num_chars; |
||||
PFR_Char chars; |
||||
|
||||
} PFR_CMapRec, *PFR_CMap; |
||||
|
||||
|
||||
FT_CALLBACK_TABLE const FT_CMap_ClassRec pfr_cmap_class_rec; |
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __PFR_CMAP_H__ */ |
@ -0,0 +1,52 @@ |
||||
#include <ft2build.h> |
||||
#include FT_INTERNAL_DEBUG_H |
||||
#include FT_INTERNAL_STREAM_H |
||||
#include "pfrdrivr.h" |
||||
#include "pfrobjs.h" |
||||
|
||||
|
||||
FT_CALLBACK_TABLE_DEF |
||||
const FT_Driver_ClassRec pfr_driver_class = |
||||
{ |
||||
{ |
||||
ft_module_font_driver | |
||||
ft_module_driver_scalable, |
||||
|
||||
sizeof( FT_DriverRec ), |
||||
|
||||
"pfr", |
||||
0x10000L, |
||||
0x20000L, |
||||
|
||||
0, /* format interface */ |
||||
|
||||
(FT_Module_Constructor) NULL, |
||||
(FT_Module_Destructor) NULL, |
||||
(FT_Module_Requester) NULL |
||||
}, |
||||
|
||||
sizeof( PFR_FaceRec ), |
||||
sizeof( PFR_SizeRec ), |
||||
sizeof( PFR_SlotRec ), |
||||
|
||||
(FT_Face_InitFunc) pfr_face_init, |
||||
(FT_Face_DoneFunc) pfr_face_done, |
||||
(FT_Size_InitFunc) NULL, |
||||
(FT_Size_DoneFunc) NULL, |
||||
(FT_Slot_InitFunc) pfr_slot_init, |
||||
(FT_Slot_DoneFunc) pfr_slot_done, |
||||
|
||||
(FT_Size_ResetPointsFunc) NULL, |
||||
(FT_Size_ResetPixelsFunc) NULL, |
||||
(FT_Slot_LoadFunc) pfr_slot_load, |
||||
(FT_CharMap_CharIndexFunc) NULL, |
||||
|
||||
(FT_Face_GetKerningFunc) 0, |
||||
(FT_Face_AttachFunc) 0, |
||||
(FT_Face_GetAdvancesFunc) 0, |
||||
|
||||
(FT_CharMap_CharNextFunc) NULL |
||||
}; |
||||
|
||||
|
||||
|
@ -0,0 +1,38 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* pfrdrivr.h */ |
||||
/* */ |
||||
/* High-level Type PFR driver interface */ |
||||
/* */ |
||||
/* Copyright 1996-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 __PFR_DRIVER_H__ |
||||
#define __PFR_DRIVER_H__ |
||||
|
||||
|
||||
#include <ft2build.h> |
||||
#include FT_INTERNAL_DRIVER_H |
||||
|
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
|
||||
FT_EXPORT_VAR( const FT_Driver_ClassRec ) pfr_driver_class; |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __PFR_DRIVER_H__ */ |
||||
|
||||
|
||||
/* END */ |
@ -0,0 +1,751 @@ |
||||
#include "pfrgload.h" |
||||
#include "pfrload.h" /* for macro definitions */ |
||||
#include FT_INTERNAL_DEBUG_H |
||||
|
||||
#undef FT_COMPONENT |
||||
#define FT_COMPONENT trace_pfr |
||||
|
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
/***** *****/ |
||||
/***** PFR GLYPH BUILDER *****/ |
||||
/***** *****/ |
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
|
||||
|
||||
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; |
||||
|
||||
FT_FREE( glyph->x_control ); |
||||
glyph->y_control = NULL; |
||||
|
||||
glyph->max_xy_control = 0; |
||||
glyph->num_x_control = 0; |
||||
glyph->num_y_control = 0; |
||||
|
||||
FT_FREE( glyph->subs ); |
||||
|
||||
glyph->max_subs = 0; |
||||
glyph->num_subs = 0; |
||||
|
||||
glyph->loader = NULL; |
||||
glyph->path_begun = 0; |
||||
} |
||||
|
||||
|
||||
/* close current contour, if any */ |
||||
static void |
||||
pfr_glyph_close_contour( PFR_Glyph glyph ) |
||||
{ |
||||
FT_GlyphLoader loader = glyph->loader; |
||||
FT_Outline* outline = &loader->current.outline; |
||||
FT_Int last, first; |
||||
|
||||
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 ) |
||||
first = outline->contours[ outline->n_contours-1 ]; |
||||
|
||||
/* 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; |
||||
|
||||
if ( p1->x == p2->x && p1->y == p2->y ) |
||||
{ |
||||
outline->n_points--; |
||||
last--; |
||||
} |
||||
} |
||||
|
||||
/* don't add empty contours */ |
||||
if ( last >= first ) |
||||
outline->contours[ outline->n_contours++ ] = (short) last; |
||||
|
||||
glyph->path_begun = 0; |
||||
} |
||||
|
||||
|
||||
|
||||
/* reset glyph to start the loading of a new glyph */ |
||||
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; |
||||
|
||||
/* check that we've begun a new path */ |
||||
FT_ASSERT( glyph->path_begun != 0 ); |
||||
|
||||
error = FT_GlyphLoader_CheckPoints( loader, 1, 0 ); |
||||
if ( !error ) |
||||
{ |
||||
FT_UInt n = outline->n_points; |
||||
|
||||
outline->points[n] = *to; |
||||
outline->tags [n] = FT_Curve_Tag_On; |
||||
|
||||
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; |
||||
|
||||
/* check that we've begun a new path */ |
||||
FT_ASSERT( glyph->path_begun != 0 ); |
||||
|
||||
error = FT_GlyphLoader_CheckPoints( loader, 3, 0 ); |
||||
if ( !error ) |
||||
{ |
||||
FT_Vector* vec = outline->points + outline->n_points; |
||||
FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points; |
||||
|
||||
vec[0] = *control1; |
||||
vec[1] = *control2; |
||||
vec[2] = *to; |
||||
tag[0] = FT_Curve_Tag_Cubic; |
||||
tag[1] = FT_Curve_Tag_Cubic; |
||||
tag[2] = FT_Curve_Tag_On; |
||||
|
||||
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; |
||||
|
||||
/* close current contour if any */ |
||||
pfr_glyph_close_contour( glyph ); |
||||
|
||||
/* indicate that a new contour has started */ |
||||
glyph->path_begun = 1; |
||||
|
||||
/* check that there is room for a new contour and a new point */ |
||||
error = FT_GlyphLoader_CheckPoints( loader, 1, 1 ); |
||||
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 ); |
||||
} |
||||
|
||||
|
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
/***** *****/ |
||||
/***** PFR GLYPH LOADER *****/ |
||||
/***** *****/ |
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
|
||||
/* Load a simple glyph */ |
||||
|
||||
static FT_Error |
||||
pfr_glyph_load_simple( PFR_Glyph glyph, |
||||
FT_Byte* p, |
||||
FT_Byte* limit ) |
||||
{ |
||||
FT_Error error = 0; |
||||
FT_Memory memory = glyph->loader->memory; |
||||
FT_UInt flags, x_count, y_count, i, count, mask; |
||||
FT_Int x; |
||||
|
||||
PFR_CHECK(1); |
||||
flags = PFR_NEXT_BYTE(p); |
||||
|
||||
/* test for composite glyphs */ |
||||
FT_ASSERT( (flags & PFR_GLYPH_IS_COMPOUND) == 0 ); |
||||
|
||||
x_count = 0; |
||||
y_count = 0; |
||||
|
||||
if ( flags & PFR_GLYPH_1BYTE_XYCOUNT ) |
||||
{ |
||||
PFR_CHECK(1); |
||||
count = PFR_NEXT_BYTE(p); |
||||
x_count = (count & 15); |
||||
y_count = (count >> 4); |
||||
} |
||||
else |
||||
{ |
||||
if ( flags & PFR_GLYPH_XCOUNT ) |
||||
{ |
||||
PFR_CHECK(1); |
||||
x_count = PFR_NEXT_BYTE(p); |
||||
} |
||||
|
||||
if ( flags & PFR_GLYPH_YCOUNT ) |
||||
{ |
||||
PFR_CHECK(1); |
||||
y_count = PFR_NEXT_BYTE(p); |
||||
} |
||||
} |
||||
|
||||
count = x_count + y_count; |
||||
|
||||
/* re-allocate array when necessary */ |
||||
if ( count > glyph->max_xy_control ) |
||||
{ |
||||
FT_UInt new_max = (count+7) & -8; |
||||
|
||||
if ( FT_RENEW_ARRAY( glyph->x_control, glyph->max_xy_control, new_max ) ) |
||||
goto Exit; |
||||
|
||||
glyph->max_xy_control = new_max; |
||||
} |
||||
|
||||
glyph->y_control = glyph->x_control + x_count; |
||||
|
||||
mask = 0; |
||||
x = 0; |
||||
for ( i = 0; i < count; i++ ) |
||||
{ |
||||
if ( (i & 7) == 0 ) |
||||
{ |
||||
PFR_CHECK(1); |
||||
mask = PFR_NEXT_BYTE(p); |
||||
} |
||||
|
||||
if ( mask & 1 ) |
||||
{ |
||||
PFR_CHECK(2); |
||||
x = PFR_NEXT_SHORT(p); |
||||
} |
||||
else |
||||
{ |
||||
PFR_CHECK(1); |
||||
x += PFR_NEXT_BYTE(p); |
||||
} |
||||
|
||||
glyph->x_control[i] = x; |
||||
|
||||
mask >>= 1; |
||||
} |
||||
|
||||
/* XXXX: for now we ignore the secondary stroke and edge definitions */ |
||||
/* since we don't want to support native PFR hinting.. */ |
||||
/* */ |
||||
if ( flags & PFR_GLYPH_EXTRA_ITEMS ) |
||||
{ |
||||
error = pfr_extra_items_skip( &p, limit ); |
||||
if (error) goto Exit; |
||||
} |
||||
|
||||
|
||||
pfr_glyph_start( glyph ); |
||||
|
||||
/* now load a simple glyph */ |
||||
{ |
||||
FT_Vector pos[4]; |
||||
FT_Vector* cur; |
||||
|
||||
pos[0].x = pos[0].y = 0; |
||||
pos[3] = pos[0]; |
||||
|
||||
for (;;) |
||||
{ |
||||
FT_Int format, args_format = 0, args_count, n; |
||||
|
||||
/***************************************************************/ |
||||
/* read instruction */ |
||||
/* */ |
||||
PFR_CHECK(1); |
||||
format = PFR_NEXT_BYTE(p); |
||||
switch (format >> 4) |
||||
{ |
||||
case 0: /* end glyph */ |
||||
FT_TRACE6(( "- end glyph" )); |
||||
args_count = 0; |
||||
break; |
||||
|
||||
case 1: /* general line operation */ |
||||
FT_TRACE6(( "- general line" )); |
||||
goto Line1; |
||||
|
||||
case 4: /* move to inside contour */ |
||||
FT_TRACE6(( "- move to inside" )); |
||||
goto Line1; |
||||
|
||||
case 5: /* move to outside contour */ |
||||
FT_TRACE6(( "- move to outside" )); |
||||
Line1: |
||||
args_format = format & 15; |
||||
args_count = 1; |
||||
break; |
||||
|
||||
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; |
||||
|
||||
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; |
||||
|
||||
case 6: /* horizontal to vertical curve */ |
||||
FT_TRACE6(( "- hv curve " )); |
||||
args_format = 0xB8E; |
||||
args_count = 3; |
||||
break; |
||||
|
||||
case 7: /* vertical to horizontal curve */ |
||||
FT_TRACE6(( "- vh curve" )); |
||||
args_format = 0xE2B; |
||||
args_count = 3; |
||||
break; |
||||
|
||||
default: /* general curve to */ |
||||
FT_TRACE6(( "- general curve" )); |
||||
args_count = 4; |
||||
args_format = (format & 15); |
||||
} |
||||
|
||||
/***********************************************************/ |
||||
/* now read arguments */ |
||||
/* */ |
||||
cur = pos; |
||||
for ( n = 0; n < args_count; n++ ) |
||||
{ |
||||
FT_Int index, delta; |
||||
|
||||
/* read the X argument */ |
||||
switch ( args_format & 3 ) |
||||
{ |
||||
case 0: /* 8-bit index */ |
||||
PFR_CHECK(1); |
||||
index = PFR_NEXT_BYTE(p); |
||||
cur->x = glyph->x_control[index]; |
||||
FT_TRACE7(( " cx#%d", index )); |
||||
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; |
||||
} |
||||
|
||||
/* read the Y argument */ |
||||
switch ( (args_format >> 2) & 3 ) |
||||
{ |
||||
case 0: /* 8-bit index */ |
||||
PFR_CHECK(1); |
||||
index = PFR_NEXT_BYTE(p); |
||||
cur->y = glyph->y_control[index]; |
||||
FT_TRACE7(( " cy#%d", index )); |
||||
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; |
||||
} |
||||
|
||||
/* read the additional format flag for the general curve */ |
||||
if ( n == 0 && args_count == 4 ) |
||||
{ |
||||
PFR_CHECK(1); |
||||
args_format = PFR_NEXT_BYTE(p); |
||||
args_count--; |
||||
} |
||||
else |
||||
args_format >>= 4; |
||||
|
||||
/* save the previous point */ |
||||
pos[3] = cur[0]; |
||||
cur++; |
||||
} |
||||
|
||||
FT_TRACE7(( "\n" )); |
||||
|
||||
/***********************************************************/ |
||||
/* finally, execute instruction */ |
||||
/* */ |
||||
switch (format >> 4) |
||||
{ |
||||
case 0: /* end glyph => EXIT */ |
||||
pfr_glyph_end( glyph ); |
||||
goto Exit; |
||||
|
||||
case 1: /* line operations */ |
||||
case 2: |
||||
case 3: |
||||
error = pfr_glyph_line_to( glyph, pos ); |
||||
goto Test_Error; |
||||
|
||||
case 4: /* move to inside contour */ |
||||
case 5: /* move to outside contour */ |
||||
error = pfr_glyph_move_to( glyph, pos ); |
||||
goto Test_Error; |
||||
|
||||
default: /* curve operations */ |
||||
error = pfr_glyph_curve_to( glyph, pos, pos+1, pos+2 ); |
||||
|
||||
Test_Error: /* test error condition */ |
||||
if (error) |
||||
goto Exit; |
||||
} |
||||
} /* for (;;) */ |
||||
} |
||||
|
||||
Exit: |
||||
return error; |
||||
|
||||
Too_Short: |
||||
error = FT_Err_Invalid_Table; |
||||
FT_ERROR(( "pfr_glyph_load: invalid glyph data\n" )); |
||||
goto Exit; |
||||
} |
||||
|
||||
|
||||
|
||||
/* load a composite/compound glyph */ |
||||
|
||||
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; |
||||
|
||||
PFR_CHECK(1); |
||||
flags = PFR_NEXT_BYTE(p); |
||||
|
||||
/* test for composite glyphs */ |
||||
FT_ASSERT( (flags & PFR_GLYPH_IS_COMPOUND) != 0 ); |
||||
|
||||
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 */ |
||||
/* the PFR format is so damn stupid that it uses direct file offsets */ |
||||
/* to point to the sub-glyphs (instead of glyph indices).. */ |
||||
/* */ |
||||
/* for now, we'll load the list of sub-glyphs in a different array */ |
||||
/* but this will prevent us from using the auto-hinter at its best */ |
||||
/* quality.. */ |
||||
/* */ |
||||
org_count = glyph->num_subs; |
||||
|
||||
if ( org_count + count > glyph->max_subs ) |
||||
{ |
||||
FT_UInt new_max = ( org_count + count + 3 ) & -4; |
||||
|
||||
if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) ) |
||||
goto Exit; |
||||
|
||||
glyph->max_subs = new_max; |
||||
} |
||||
|
||||
subglyph = glyph->subs + org_count; |
||||
x_pos = 0; |
||||
y_pos = 0; |
||||
|
||||
for ( i = 0; i < count; i++, subglyph++ ) |
||||
{ |
||||
FT_UInt format; |
||||
|
||||
PFR_CHECK(1); |
||||
format = PFR_NEXT_BYTE(p); |
||||
|
||||
/* read scale when available */ |
||||
subglyph->x_scale = 0x10000L; |
||||
if ( format & PFR_SUBGLYPH_XSCALE ) |
||||
{ |
||||
PFR_CHECK(2); |
||||
subglyph->x_scale = PFR_NEXT_SHORT(p) << 4; |
||||
} |
||||
|
||||
subglyph->y_scale = 0x10000L; |
||||
if ( format & PFR_SUBGLYPH_YSCALE ) |
||||
{ |
||||
PFR_CHECK(2); |
||||
subglyph->y_scale = PFR_NEXT_SHORT(p) << 4; |
||||
} |
||||
|
||||
/* read offset */ |
||||
switch ( format & 3 ) |
||||
{ |
||||
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: |
||||
; |
||||
} |
||||
|
||||
switch ( (format >> 2) & 3 ) |
||||
{ |
||||
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: |
||||
; |
||||
} |
||||
|
||||
subglyph->x_delta = x_pos; |
||||
subglyph->y_delta = y_pos; |
||||
|
||||
/* read glyph position and size now */ |
||||
if ( format & PFR_SUBGLYPH_2BYTE_SIZE ) |
||||
{ |
||||
PFR_CHECK(2); |
||||
subglyph->gps_size = PFR_NEXT_USHORT(p); |
||||
} |
||||
else |
||||
{ |
||||
PFR_CHECK(1); |
||||
subglyph->gps_size = PFR_NEXT_BYTE(p); |
||||
} |
||||
|
||||
if ( format & PFR_SUBGLYPH_3BYTE_OFFSET ) |
||||
{ |
||||
PFR_CHECK(3); |
||||
subglyph->gps_offset = PFR_NEXT_LONG(p); |
||||
} |
||||
else |
||||
{ |
||||
PFR_CHECK(2); |
||||
subglyph->gps_offset = PFR_NEXT_USHORT(p); |
||||
} |
||||
|
||||
glyph->num_subs++; |
||||
} |
||||
|
||||
|
||||
Exit: |
||||
return error; |
||||
|
||||
Too_Short: |
||||
error = FT_Err_Invalid_Table; |
||||
FT_ERROR(( "pfr_glyph_load: invalid glyph data\n" )); |
||||
goto Exit; |
||||
} |
||||
|
||||
|
||||
|
||||
static FT_Error |
||||
pfr_glyph_load_rec( PFR_Glyph glyph, |
||||
FT_Stream stream, |
||||
FT_ULong gps_offset, |
||||
FT_ULong offset, |
||||
FT_ULong size ) |
||||
{ |
||||
FT_Error error; |
||||
FT_Byte* p; |
||||
FT_Byte* limit; |
||||
|
||||
if ( FT_STREAM_SEEK( gps_offset + offset ) || |
||||
FT_FRAME_ENTER( size ) ) |
||||
goto Exit; |
||||
|
||||
p = (FT_Byte*) stream->cursor; |
||||
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(); |
||||
|
||||
if ( error ) goto Exit; |
||||
|
||||
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, |
||||
subglyph->gps_offset, subglyph->gps_size ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* note that the 'glyph->subs' might have been re-allocated */ |
||||
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++ ) |
||||
{ |
||||
vec->x = FT_MulFix( vec->x, subglyph->x_scale ) + subglyph->x_delta; |
||||
vec->y = FT_MulFix( vec->y, subglyph->y_scale ) + subglyph->y_delta; |
||||
} |
||||
} |
||||
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; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
pfr_glyph_load( PFR_Glyph glyph, |
||||
FT_Stream stream, |
||||
FT_ULong gps_offset, |
||||
FT_ULong offset, |
||||
FT_ULong size ) |
||||
{ |
||||
/* initialize glyph loader */ |
||||
FT_GlyphLoader_Rewind( glyph->loader ); |
||||
|
||||
/* load the glyph, recursively when needed */ |
||||
return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size ); |
||||
} |
||||
|
@ -0,0 +1,27 @@ |
||||
#ifndef __PFR_GLYPH_LOAD_H__ |
||||
#define __PFR_GLYPH_LOAD_H__ |
||||
|
||||
#include "pfrtypes.h" |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
FT_LOCAL( void ) |
||||
pfr_glyph_init( PFR_Glyph glyph, |
||||
FT_GlyphLoader loader ); |
||||
|
||||
FT_LOCAL( void ) |
||||
pfr_glyph_done( PFR_Glyph glyph ); |
||||
|
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
pfr_glyph_load( PFR_Glyph glyph, |
||||
FT_Stream stream, |
||||
FT_ULong gps_offset, |
||||
FT_ULong offset, |
||||
FT_ULong size ); |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
|
||||
#endif /* __PFR_GLYPH_LOAD_H__ */ |
@ -0,0 +1,657 @@ |
||||
#include "pfrload.h" |
||||
#include FT_INTERNAL_DEBUG_H |
||||
#include FT_INTERNAL_STREAM_H |
||||
|
||||
#undef FT_COMPONENT |
||||
#define FT_COMPONENT trace_pfr |
||||
|
||||
/***********************************************************************/ |
||||
/***********************************************************************/ |
||||
/***** *****/ |
||||
/***** EXTRA ITEMS *****/ |
||||
/***** *****/ |
||||
/***********************************************************************/ |
||||
/***********************************************************************/ |
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
pfr_extra_items_skip( FT_Byte* *pp, FT_Byte* limit ) |
||||
{ |
||||
return pfr_extra_items_parse( pp, limit, NULL, NULL ); |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
pfr_extra_items_parse( FT_Byte* *pp, |
||||
FT_Byte* limit, |
||||
PFR_ExtraItem item_list, |
||||
FT_Pointer item_data ) |
||||
{ |
||||
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); |
||||
for ( ; num_items > 0; num_items-- ) |
||||
{ |
||||
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; |
||||
|
||||
for ( extra = item_list; extra->parser != NULL; extra++ ) |
||||
{ |
||||
if ( extra->type == item_type ) |
||||
{ |
||||
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.skip: invalid extra items table\n" )); |
||||
error = FT_Err_Invalid_Table; |
||||
goto Exit; |
||||
} |
||||
|
||||
|
||||
|
||||
/***********************************************************************/ |
||||
/***********************************************************************/ |
||||
/***** *****/ |
||||
/***** PFR HEADER *****/ |
||||
/***** *****/ |
||||
/***********************************************************************/ |
||||
/***********************************************************************/ |
||||
|
||||
static const FT_Frame_Field pfr_header_fields[] = |
||||
{ |
||||
#undef FT_STRUCTURE |
||||
#define FT_STRUCTURE PFR_HeaderRec |
||||
|
||||
FT_FRAME_START(58), |
||||
FT_FRAME_ULONG (signature), |
||||
FT_FRAME_USHORT(version), |
||||
FT_FRAME_USHORT(signature2), |
||||
FT_FRAME_USHORT(header_size), |
||||
|
||||
FT_FRAME_USHORT(log_dir_size), |
||||
FT_FRAME_USHORT(log_dir_offset), |
||||
|
||||
FT_FRAME_USHORT(log_font_max_size), |
||||
FT_FRAME_UOFF3 (log_font_section_size), |
||||
FT_FRAME_UOFF3 (log_font_section_offset), |
||||
|
||||
FT_FRAME_USHORT(phy_font_max_size), |
||||
FT_FRAME_UOFF3 (phy_font_section_size), |
||||
FT_FRAME_UOFF3 (phy_font_section_offset), |
||||
|
||||
FT_FRAME_USHORT(gps_max_size), |
||||
FT_FRAME_UOFF3 (gps_section_size), |
||||
FT_FRAME_UOFF3 (gps_section_offset), |
||||
|
||||
FT_FRAME_BYTE (max_blue_values), |
||||
FT_FRAME_BYTE (max_x_orus), |
||||
FT_FRAME_BYTE (max_y_orus), |
||||
|
||||
FT_FRAME_BYTE (phy_font_max_size_high), |
||||
FT_FRAME_BYTE (color_flags), |
||||
|
||||
FT_FRAME_UOFF3 (bct_max_size), |
||||
FT_FRAME_UOFF3 (bct_set_max_size), |
||||
FT_FRAME_UOFF3 (phy_bct_set_max_size), |
||||
|
||||
FT_FRAME_USHORT(num_phy_fonts), |
||||
FT_FRAME_BYTE (max_vert_stem_snap), |
||||
FT_FRAME_BYTE (max_horz_stem_snap), |
||||
FT_FRAME_USHORT(max_chars), |
||||
FT_FRAME_END |
||||
}; |
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
pfr_header_load( PFR_Header header, |
||||
FT_Stream stream ) |
||||
{ |
||||
FT_Error error; |
||||
|
||||
/* read header directly */ |
||||
if ( !FT_STREAM_SEEK( 0 ) && |
||||
!FT_STREAM_READ_FIELDS( pfr_header_fields, header ) ) |
||||
{ |
||||
/* make a few adjustments to the header */ |
||||
header->phy_font_max_size += |
||||
(FT_UInt32)header->phy_font_max_size_high << 16; |
||||
} |
||||
|
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Bool ) |
||||
pfr_header_check( PFR_Header header ) |
||||
{ |
||||
FT_Bool result = 1; |
||||
|
||||
/* check signature and header size */ |
||||
if ( header->signature != 0x50465230 || /* "PFR0" */ |
||||
header->version > 4 || |
||||
header->header_size < 58 || |
||||
header->signature2 != 0x0d0a ) /* CR/LF */ |
||||
{ |
||||
result = 0; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
|
||||
/***********************************************************************/ |
||||
/***********************************************************************/ |
||||
/***** *****/ |
||||
/***** PFR LOGICAL FONTS *****/ |
||||
/***** *****/ |
||||
/***********************************************************************/ |
||||
/***********************************************************************/ |
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
pfr_log_font_count( FT_Stream stream, |
||||
FT_UInt32 section_offset, |
||||
FT_UInt *acount ) |
||||
{ |
||||
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 ) |
||||
pfr_log_font_load( PFR_LogFont log_font, |
||||
FT_Stream stream, |
||||
FT_UInt index, |
||||
FT_UInt32 section_offset, |
||||
FT_Bool size_increment ) |
||||
{ |
||||
FT_UInt num_log_fonts; |
||||
FT_UInt flags; |
||||
FT_UInt32 offset; |
||||
FT_UInt32 size; |
||||
FT_Error error; |
||||
|
||||
if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT(num_log_fonts) ) |
||||
goto Exit; |
||||
|
||||
if ( index >= num_log_fonts ) |
||||
return FT_Err_Invalid_Argument; |
||||
|
||||
if ( FT_STREAM_SKIP( index*5 ) || |
||||
FT_READ_USHORT(size) || |
||||
FT_READ_UOFF3 (offset) ) |
||||
goto Exit; |
||||
|
||||
/* save logical font size and offset */ |
||||
log_font->size = size; |
||||
log_font->offset = offset; |
||||
|
||||
/* now, check the rest of the table before loading it */ |
||||
{ |
||||
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; |
||||
} |
||||
if ( flags & PFR_LOG_BOLD ) |
||||
{ |
||||
local++; |
||||
if ( flags & PFR_LOG_2BYTE_BOLD ) |
||||
local++; |
||||
} |
||||
|
||||
PFR_CHECK(local); |
||||
|
||||
if ( flags & PFR_LOG_STROKE ) |
||||
{ |
||||
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 ); |
||||
if (error) goto Fail; |
||||
} |
||||
|
||||
PFR_CHECK(5); |
||||
log_font->phys_size = PFR_NEXT_USHORT(p); |
||||
log_font->phys_offset = PFR_NEXT_ULONG(p); |
||||
if ( size_increment ) |
||||
{ |
||||
PFR_CHECK(1); |
||||
log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE(p) << 16; |
||||
} |
||||
} |
||||
|
||||
Fail: |
||||
FT_FRAME_EXIT(); |
||||
|
||||
Exit: |
||||
return error; |
||||
|
||||
Too_Short: |
||||
FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" )); |
||||
error = FT_Err_Invalid_Table; |
||||
goto Fail; |
||||
} |
||||
|
||||
|
||||
/***********************************************************************/ |
||||
/***********************************************************************/ |
||||
/***** *****/ |
||||
/***** PFR PHYSICAL FONTS *****/ |
||||
/***** *****/ |
||||
/***********************************************************************/ |
||||
/***********************************************************************/ |
||||
|
||||
|
||||
/* load bitmap strikes lists */ |
||||
FT_CALLBACK_DEF( FT_Error ) |
||||
pfr_extra_item_load_bitmap_info( FT_Byte* p, |
||||
FT_Byte* limit, |
||||
PFR_PhyFont phy_font ) |
||||
{ |
||||
FT_Memory memory = phy_font->memory; |
||||
PFR_Strike strike; |
||||
FT_UInt flags0; |
||||
FT_UInt n, count, size1; |
||||
FT_Error error = 0; |
||||
|
||||
PFR_CHECK(5); |
||||
|
||||
p += 3; /* skip bctSize */ |
||||
flags0 = PFR_NEXT_BYTE(p); |
||||
count = PFR_NEXT_BYTE(p); |
||||
|
||||
/* re-allocate when needed */ |
||||
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; |
||||
} |
||||
|
||||
size1 = 1 + 1 + 1 + 2 + 2 + 1; |
||||
if ( flags0 & PFR_STRIKE_2BYTE_XPPM ) |
||||
size1++; |
||||
|
||||
if ( flags0 & PFR_STRIKE_2BYTE_YPPM ) |
||||
size1++; |
||||
|
||||
if ( flags0 & PFR_STRIKE_3BYTE_SIZE ) |
||||
size1++; |
||||
|
||||
if ( flags0 & PFR_STRIKE_3BYTE_OFFSET ) |
||||
size1++; |
||||
|
||||
if ( flags0 & PFR_STRIKE_2BYTE_COUNT ) |
||||
size1++; |
||||
|
||||
strike = phy_font->strikes + phy_font->num_strikes; |
||||
|
||||
PFR_CHECK( count*size1 ); |
||||
|
||||
for ( n = 0; n < count; n++, strike++ ) |
||||
{ |
||||
strike->x_ppm = ( flags0 & PFR_STRIKE_2BYTE_XPPM ) |
||||
? PFR_NEXT_USHORT(p) |
||||
: PFR_NEXT_BYTE(p); |
||||
|
||||
strike->y_ppm = ( flags0 & PFR_STRIKE_2BYTE_YPPM ) |
||||
? PFR_NEXT_USHORT(p) |
||||
: PFR_NEXT_BYTE(p); |
||||
|
||||
strike->flags = PFR_NEXT_BYTE(p); |
||||
|
||||
strike->bct_size = ( flags0 & PFR_STRIKE_3BYTE_SIZE ) |
||||
? PFR_NEXT_ULONG(p) |
||||
: PFR_NEXT_USHORT(p); |
||||
|
||||
strike->bct_offset = ( flags0 & PFR_STRIKE_3BYTE_OFFSET ) |
||||
? PFR_NEXT_ULONG(p) |
||||
: PFR_NEXT_USHORT(p); |
||||
|
||||
strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT ) |
||||
? PFR_NEXT_USHORT(p) |
||||
: PFR_NEXT_BYTE(p); |
||||
} |
||||
|
||||
phy_font->num_strikes += count; |
||||
|
||||
Exit: |
||||
return error; |
||||
|
||||
Too_Short: |
||||
error = FT_Err_Invalid_Table; |
||||
FT_ERROR(( "pfr.extra_item_load: invalid bitmap info table\n" )); |
||||
goto Exit; |
||||
}
|
||||
|
||||
|
||||
/* load font ID, i.e. name */ |
||||
FT_CALLBACK_DEF( FT_Error ) |
||||
pfr_extra_item_load_font_id( FT_Byte* p, |
||||
FT_Byte* limit, |
||||
PFR_PhyFont phy_font ) |
||||
{ |
||||
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; |
||||
} |
||||
|
||||
|
||||
/* load stem snap tables */ |
||||
FT_CALLBACK_DEF( FT_Error ) |
||||
pfr_extra_item_load_stem_snaps( FT_Byte* p, |
||||
FT_Byte* limit, |
||||
PFR_PhyFont phy_font ) |
||||
{ |
||||
FT_UInt count, num_vert, num_horz; |
||||
FT_Int* snaps; |
||||
FT_Error error = 0; |
||||
FT_Memory memory = phy_font->memory; |
||||
|
||||
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 = FT_Err_Invalid_Table; |
||||
FT_ERROR(( "pfr.exta_item_load: invalid stem snaps table\n" )); |
||||
goto Exit; |
||||
}
|
||||
|
||||
|
||||
static const PFR_ExtraItemRec pfr_phy_font_extra_items[] = |
||||
{ |
||||
{ 1, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_bitmap_info }, |
||||
{ 2, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_font_id }, |
||||
{ 3, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_stem_snaps }, |
||||
{ 0, NULL } |
||||
}; |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FT_LOCAL_DEF( void ) |
||||
pfr_phy_font_done( PFR_PhyFont phy_font, |
||||
FT_Memory memory ) |
||||
{ |
||||
if ( phy_font->font_id ) |
||||
FT_FREE( phy_font->font_id ); |
||||
|
||||
FT_FREE( phy_font->vertical.stem_snaps ); |
||||
phy_font->vertical.num_stem_snaps = 0; |
||||
|
||||
phy_font->horizontal.stem_snaps = NULL; |
||||
phy_font->horizontal.num_stem_snaps = 0; |
||||
|
||||
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; |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
pfr_phy_font_load( PFR_PhyFont phy_font, |
||||
FT_Stream stream, |
||||
FT_UInt32 offset, |
||||
FT_UInt32 size ) |
||||
{ |
||||
FT_Error error; |
||||
FT_Memory memory = stream->memory; |
||||
FT_UInt flags, num_aux; |
||||
FT_Byte* p; |
||||
FT_Byte* limit; |
||||
|
||||
phy_font->memory = memory; |
||||
phy_font->offset = offset; |
||||
|
||||
if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) ) |
||||
goto Exit; |
||||
|
||||
p = stream->cursor; |
||||
limit = p + size; |
||||
|
||||
PFR_CHECK( 15 ); |
||||
phy_font->font_ref_number = PFR_NEXT_USHORT(p); |
||||
phy_font->outline_resolution = PFR_NEXT_USHORT(p); |
||||
phy_font->metrics_resolution = PFR_NEXT_USHORT(p); |
||||
phy_font->bbox.xMin = PFR_NEXT_SHORT(p); |
||||
phy_font->bbox.yMin = PFR_NEXT_SHORT(p); |
||||
phy_font->bbox.xMax = PFR_NEXT_SHORT(p); |
||||
phy_font->bbox.yMax = PFR_NEXT_SHORT(p); |
||||
phy_font->flags = flags = PFR_NEXT_BYTE(p); |
||||
|
||||
/* get the standard advance for non-proprotional fonts */ |
||||
if ( !(flags & PFR_PHY_PROPORTIONAL) ) |
||||
{ |
||||
PFR_CHECK(2); |
||||
phy_font->standard_advance = PFR_NEXT_SHORT(p); |
||||
} |
||||
|
||||
/* load the extra items when present */ |
||||
if ( flags & PFR_PHY_EXTRA_ITEMS ) |
||||
{ |
||||
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; |
||||
|
||||
/* read the blue values */ |
||||
{ |
||||
FT_UInt n, count; |
||||
|
||||
PFR_CHECK( 1 ); |
||||
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; |
||||
|
||||
for ( n = 0; n < count; n++ ) |
||||
phy_font->blue_values[n] = PFR_NEXT_SHORT(p); |
||||
} |
||||
|
||||
PFR_CHECK(8); |
||||
phy_font->blue_fuzz = PFR_NEXT_BYTE(p); |
||||
phy_font->blue_scale = PFR_NEXT_BYTE(p); |
||||
|
||||
phy_font->vertical.standard = PFR_NEXT_USHORT(p); |
||||
phy_font->horizontal.standard = PFR_NEXT_USHORT(p); |
||||
|
||||
/* read the character descriptors */ |
||||
{ |
||||
FT_UInt n, count, size; |
||||
|
||||
phy_font->num_chars = count = PFR_NEXT_USHORT(p); |
||||
phy_font->chars_offset = offset + (p - stream->cursor); |
||||
|
||||
if ( FT_NEW_ARRAY( phy_font->chars, count ) ) |
||||
goto Fail; |
||||
|
||||
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++ ) |
||||
{ |
||||
PFR_Char cur = &phy_font->chars[n]; |
||||
|
||||
cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE ) |
||||
? PFR_NEXT_USHORT(p) |
||||
: PFR_NEXT_BYTE(p); |
||||
|
||||
cur->advance = ( flags & PFR_PHY_PROPORTIONAL ) |
||||
? PFR_NEXT_SHORT(p) |
||||
: phy_font->standard_advance; |
||||
|
||||
#if 0 |
||||
cur->ascii = ( flags & PFR_PHY_ASCII_CODE ) |
||||
? PFR_NEXT_BYTE(p) |
||||
: 0; |
||||
#else |
||||
if ( flags & PFR_PHY_ASCII_CODE ) |
||||
p += 1; |
||||
#endif |
||||
cur->gps_size = ( flags & PFR_PHY_2BYTE_GPS_SIZE ) |
||||
? PFR_NEXT_USHORT(p) |
||||
: PFR_NEXT_BYTE(p); |
||||
|
||||
cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET ) |
||||
? PFR_NEXT_ULONG(p) |
||||
: PFR_NEXT_USHORT(p); |
||||
} |
||||
} |
||||
|
||||
/* that's it !! */ |
||||
Fail: |
||||
FT_FRAME_EXIT(); |
||||
|
||||
Exit: |
||||
return error; |
||||
|
||||
Too_Short: |
||||
error = FT_Err_Invalid_Table; |
||||
FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" )); |
||||
goto Fail; |
||||
} |
||||
|
||||
|
@ -0,0 +1,89 @@ |
||||
#ifndef __PFR_LOAD_H__ |
||||
#define __PFR_LOAD_H__ |
||||
|
||||
#include "pfrobjs.h" |
||||
#include FT_INTERNAL_STREAM_H |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
#ifdef PFR_CONFIG_NO_CHECKS |
||||
# define PFR_CHECK(x) do { } while (0) |
||||
#else |
||||
# define PFR_CHECK(x) do { if ( p + (x) > limit ) goto Too_Short; } while (0) |
||||
#endif |
||||
|
||||
#define PFR_NEXT_BYTE(p) FT_NEXT_BYTE(p) |
||||
#define PFR_NEXT_INT8(p) FT_NEXT_CHAR(p) |
||||
#define PFR_NEXT_SHORT(p) FT_NEXT_SHORT(p) |
||||
#define PFR_NEXT_USHORT(p) FT_NEXT_USHORT(p) |
||||
#define PFR_NEXT_LONG(p) FT_NEXT_OFF3(p) |
||||
#define PFR_NEXT_ULONG(p) FT_NEXT_UOFF3(p) |
||||
|
||||
/* handling extra items */ |
||||
|
||||
typedef FT_Error (*PFR_ExtraItem_ParseFunc)( FT_Byte* p, |
||||
FT_Byte* limit, |
||||
FT_Pointer data ); |
||||
typedef struct PFR_ExtraItemRec_ |
||||
{ |
||||
FT_UInt type; |
||||
PFR_ExtraItem_ParseFunc parser; |
||||
|
||||
} PFR_ExtraItemRec; |
||||
|
||||
typedef const struct PFR_ExtraItemRec_* PFR_ExtraItem; |
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
pfr_extra_items_skip( FT_Byte* *pp, FT_Byte* limit ); |
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
pfr_extra_items_parse( FT_Byte* *pp, |
||||
FT_Byte* limit, |
||||
PFR_ExtraItem item_list, |
||||
FT_Pointer item_data ); |
||||
|
||||
|
||||
/* load a PFR header */ |
||||
FT_LOCAL( FT_Error ) |
||||
pfr_header_load( PFR_Header header, |
||||
FT_Stream stream ); |
||||
|
||||
/* check a PFR header */ |
||||
FT_LOCAL( FT_Bool ) |
||||
pfr_header_check( PFR_Header header ); |
||||
|
||||
|
||||
|
||||
/* return number of logical fonts in this file */ |
||||
FT_LOCAL( FT_Error ) |
||||
pfr_log_font_count( FT_Stream stream, |
||||
FT_UInt32 log_section_offset, |
||||
FT_UInt *acount ); |
||||
|
||||
|
||||
/* load a pfr logical font entry */ |
||||
FT_LOCAL( FT_Error ) |
||||
pfr_log_font_load( PFR_LogFont log_font, |
||||
FT_Stream stream, |
||||
FT_UInt face_index, |
||||
FT_UInt32 section_offset, |
||||
FT_Bool size_increment ); |
||||
|
||||
|
||||
/* load a physical font entry */ |
||||
FT_LOCAL( FT_Error ) |
||||
pfr_phy_font_load( PFR_PhyFont phy_font, |
||||
FT_Stream stream, |
||||
FT_UInt32 offset, |
||||
FT_UInt32 size ); |
||||
|
||||
/* finalize a physical font */ |
||||
FT_LOCAL( void ) |
||||
pfr_phy_font_done( PFR_PhyFont phy_font, |
||||
FT_Memory memory ); |
||||
|
||||
/* */ |
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __PFR_LOAD_H__ */ |
@ -0,0 +1,280 @@ |
||||
#include "pfrobjs.h" |
||||
#include "pfrload.h" |
||||
#include "pfrgload.h" |
||||
#include "pfrcmap.h" |
||||
#include FT_OUTLINE_H |
||||
#include FT_INTERNAL_DEBUG_H |
||||
|
||||
#undef FT_COMPONENT |
||||
#define FT_COMPONENT trace_pfr |
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/***** *****/ |
||||
/***** FACE OBJECT METHODS *****/ |
||||
/***** *****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
FT_LOCAL_DEF( void ) |
||||
pfr_face_done( PFR_Face face ) |
||||
{ |
||||
/* finalize the physical font record */ |
||||
pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY(face) ); |
||||
|
||||
/* no need to finalize the logical font or the header */ |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
pfr_face_init( FT_Stream stream, |
||||
PFR_Face face, |
||||
FT_Int face_index ) |
||||
{ |
||||
FT_Error error; |
||||
|
||||
/* load the header and check it */ |
||||
error = pfr_header_load( &face->header, stream ); |
||||
if ( error ) goto Exit; |
||||
|
||||
if ( !pfr_header_check( &face->header ) ) |
||||
{ |
||||
FT_TRACE4(( "PFR.Face.Init: not a valid PFR font\n" )); |
||||
error = FT_Err_Invalid_Argument; |
||||
goto Exit; |
||||
} |
||||
|
||||
/* check face index */ |
||||
{ |
||||
FT_UInt num_faces; |
||||
|
||||
error = pfr_log_font_count( stream, |
||||
face->header.log_dir_offset, |
||||
&num_faces ); |
||||
if ( error ) goto Exit; |
||||
|
||||
face->root.num_faces = num_faces; |
||||
} |
||||
|
||||
if ( face_index < 0 ) |
||||
goto Exit; |
||||
|
||||
if ( face_index >= face->root.num_faces ) |
||||
{ |
||||
FT_ERROR(( "PFR.Face.Init: invalid face index\n" )); |
||||
error = FT_Err_Invalid_Argument; |
||||
goto Exit; |
||||
} |
||||
|
||||
/* load the face */ |
||||
error = pfr_log_font_load( |
||||
&face->log_font, stream, face_index, |
||||
face->header.log_dir_offset, |
||||
FT_BOOL( face->header.phy_font_max_size_high != 0 ) ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* now load the physical font descriptor */ |
||||
error = pfr_phy_font_load( &face->phy_font, stream, |
||||
face->log_font.phys_offset, |
||||
face->log_font.phys_size ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* now, set-up all root face fields */ |
||||
{ |
||||
FT_Face root = FT_FACE(face); |
||||
PFR_PhyFont phy_font = &face->phy_font; |
||||
|
||||
root->face_index = face_index; |
||||
root->num_glyphs = phy_font->num_chars; |
||||
root->face_flags = FT_FACE_FLAG_SCALABLE; |
||||
|
||||
if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 ) |
||||
root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; |
||||
|
||||
if ( phy_font->flags & PFR_PHY_VERTICAL ) |
||||
root->face_flags |= FT_FACE_FLAG_HORIZONTAL; |
||||
else |
||||
root->face_flags |= FT_FACE_FLAG_VERTICAL; |
||||
|
||||
/* XXXX: kerning and embedded bitmap support isn't there yet */ |
||||
|
||||
root->family_name = phy_font->font_id; |
||||
root->style_name = NULL; /* no style name in font file */ |
||||
|
||||
root->num_fixed_sizes = 0; |
||||
root->available_sizes = 0; |
||||
|
||||
root->bbox = phy_font->bbox; |
||||
root->units_per_EM = (FT_UShort) phy_font->outline_resolution; |
||||
root->ascender = (FT_Short) phy_font->bbox.yMax; |
||||
root->descender = (FT_Short) phy_font->bbox.yMin; |
||||
root->height = (FT_Short)( ((root->ascender - root->descender)*12) / 10 ); |
||||
|
||||
/* now compute maximum advance width */ |
||||
if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 ) |
||||
root->max_advance_width = (FT_Short) phy_font->standard_advance; |
||||
else |
||||
{ |
||||
FT_Int max = 0; |
||||
FT_UInt count = phy_font->num_chars; |
||||
PFR_Char gchar = phy_font->chars; |
||||
|
||||
for ( ; count > 0; count--, gchar++ ) |
||||
{ |
||||
if ( max < gchar->advance ) |
||||
max = gchar->advance; |
||||
} |
||||
|
||||
root->max_advance_width = (FT_Short) max; |
||||
} |
||||
|
||||
root->max_advance_height = root->height; |
||||
|
||||
root->underline_position = (FT_Short)( - root->units_per_EM/10 ); |
||||
root->underline_thickness = (FT_Short)( root->units_per_EM/30 ); |
||||
|
||||
/* create charmap */ |
||||
{ |
||||
FT_CharMapRec charmap; |
||||
|
||||
charmap.face = root; |
||||
charmap.platform_id = 3; |
||||
charmap.encoding_id = 1; |
||||
charmap.encoding = ft_encoding_unicode; |
||||
|
||||
FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL ); |
||||
} |
||||
} |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/***** *****/ |
||||
/***** SLOT OBJECT METHOD *****/ |
||||
/***** *****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
pfr_slot_init( PFR_Slot slot ) |
||||
{ |
||||
FT_GlyphLoader loader = slot->root.internal->loader; |
||||
|
||||
pfr_glyph_init( &slot->glyph, loader ); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF( void ) |
||||
pfr_slot_done( PFR_Slot slot ) |
||||
{ |
||||
pfr_glyph_done( &slot->glyph ); |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
pfr_slot_load( PFR_Slot slot, |
||||
PFR_Size size, |
||||
FT_UInt gindex, |
||||
FT_Int load_flags ) |
||||
{ |
||||
FT_Error error; |
||||
PFR_Face face = (PFR_Face) slot->root.face; |
||||
PFR_Char gchar = face->phy_font.chars + gindex; |
||||
FT_Outline* outline = &slot->root.outline; |
||||
FT_ULong gps_offset; |
||||
|
||||
/* check that the glyph index is correct */ |
||||
FT_ASSERT( gindex < face->phy_font.num_chars ); |
||||
|
||||
slot->root.format = ft_glyph_format_outline; |
||||
outline->n_points = 0; |
||||
outline->n_contours = 0; |
||||
gps_offset = face->header.gps_section_offset; |
||||
|
||||
|
||||
/* load the glyph outline ( FT_LOAD_NO_RECURSE isn't supported ) */ |
||||
error = pfr_glyph_load( &slot->glyph, face->root.stream, |
||||
gps_offset, gchar->gps_offset, gchar->gps_size ); |
||||
|
||||
if (!error) |
||||
{ |
||||
FT_BBox cbox; |
||||
FT_Outline* outline = &slot->root.outline; |
||||
FT_Glyph_Metrics* metrics = &slot->root.metrics; |
||||
FT_Pos advance; |
||||
FT_Int em_metrics, em_outline; |
||||
FT_Bool scaling; |
||||
|
||||
scaling = FT_BOOL( (load_flags & FT_LOAD_NO_SCALE) == 0 ); |
||||
|
||||
/* copy outline data */ |
||||
*outline = slot->glyph.loader->base.outline; |
||||
|
||||
outline->flags &= ~ft_outline_owner; |
||||
outline->flags |= ft_outline_reverse_fill; |
||||
|
||||
if ( size && size->root.metrics.y_ppem < 24 ) |
||||
outline->flags |= ft_outline_high_precision; |
||||
|
||||
/* compute the advance vector */ |
||||
metrics->horiAdvance = 0; |
||||
metrics->vertAdvance = 0; |
||||
|
||||
advance = gchar->advance; |
||||
em_metrics = face->phy_font.metrics_resolution; |
||||
em_outline = face->phy_font.outline_resolution; |
||||
|
||||
if ( em_metrics != em_outline ) |
||||
advance = FT_MulDiv( advance, em_outline, em_metrics ); |
||||
|
||||
if ( face->phy_font.flags & PFR_PHY_VERTICAL ) |
||||
metrics->vertAdvance = gchar->advance; |
||||
else |
||||
metrics->horiAdvance = gchar->advance; |
||||
|
||||
slot->root.linearHoriAdvance = metrics->horiAdvance; |
||||
slot->root.linearVertAdvance = metrics->vertAdvance; |
||||
|
||||
/* make-up vertical metrics (?) */ |
||||
metrics->vertBearingX = 0; |
||||
metrics->vertBearingY = 0; |
||||
|
||||
/* scale when needed */ |
||||
if ( scaling ) |
||||
{ |
||||
FT_Int n; |
||||
FT_Fixed x_scale = size->root.metrics.x_scale; |
||||
FT_Fixed y_scale = size->root.metrics.y_scale; |
||||
FT_Vector* vec = outline->points; |
||||
|
||||
/* scale outline points */ |
||||
for ( n = 0; n < outline->n_points; n++, vec++ ) |
||||
{ |
||||
vec->x = FT_MulFix( vec->x, x_scale ); |
||||
vec->y = FT_MulFix( vec->y, y_scale ); |
||||
} |
||||
|
||||
/* scale the advance */ |
||||
metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); |
||||
metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); |
||||
} |
||||
|
||||
/* compute the rest of the metrics */ |
||||
FT_Outline_Get_CBox( outline, &cbox ); |
||||
|
||||
metrics->width = cbox.xMax - cbox.xMin; |
||||
metrics->height = cbox.yMax - cbox.yMin; |
||||
metrics->horiBearingX = cbox.xMin; |
||||
metrics->horiBearingY = cbox.yMax - metrics->height; |
||||
} |
||||
|
||||
return error; |
||||
} |
@ -0,0 +1,68 @@ |
||||
#ifndef __PFR_OBJS_H__ |
||||
#define __PFR_OBJS_H__ |
||||
|
||||
#include "pfrtypes.h" |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
typedef struct PFR_FaceRec_* PFR_Face; |
||||
|
||||
typedef struct PFR_SizeRec_* PFR_Size; |
||||
|
||||
typedef struct PFR_SlotRec_* PFR_Slot; |
||||
|
||||
|
||||
|
||||
typedef struct PFR_FaceRec_ |
||||
{ |
||||
FT_FaceRec root; |
||||
PFR_HeaderRec header; |
||||
PFR_LogFontRec log_font; |
||||
PFR_PhyFontRec phy_font; |
||||
|
||||
} PFR_FaceRec; |
||||
|
||||
|
||||
typedef struct PFR_SizeRec_ |
||||
{ |
||||
FT_SizeRec root; |
||||
|
||||
} PFR_SizeRec; |
||||
|
||||
|
||||
typedef struct PFR_SlotRec_ |
||||
{ |
||||
FT_GlyphSlotRec root; |
||||
PFR_GlyphRec glyph; |
||||
|
||||
} PFR_SlotRec; |
||||
|
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
pfr_face_init( FT_Stream stream, |
||||
PFR_Face face, |
||||
FT_Int face_index ); |
||||
|
||||
|
||||
FT_LOCAL( void ) |
||||
pfr_face_done( PFR_Face face ); |
||||
|
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
pfr_slot_init( PFR_Slot slot ); |
||||
|
||||
|
||||
FT_LOCAL( void ) |
||||
pfr_slot_done( PFR_Slot slot ); |
||||
|
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
pfr_slot_load( PFR_Slot slot, |
||||
PFR_Size size, |
||||
FT_UInt gindex, |
||||
FT_Int load_flags ); |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __PFR_OBJS_H__ */ |
@ -0,0 +1,289 @@ |
||||
#ifndef __PFR_TYPES_H__ |
||||
#define __PFR_TYPES_H__ |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_INTERNAL_OBJECTS_H |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
/************************************************************************/ |
||||
|
||||
/* the PFR Header structure */ |
||||
typedef struct PFR_HeaderRec_ |
||||
{ |
||||
FT_UInt32 signature; |
||||
FT_UInt version; |
||||
FT_UInt signature2; |
||||
FT_UInt header_size; |
||||
|
||||
FT_UInt log_dir_size; |
||||
FT_UInt log_dir_offset; |
||||
|
||||
FT_UInt log_font_max_size; |
||||
FT_UInt32 log_font_section_size; |
||||
FT_UInt32 log_font_section_offset; |
||||
|
||||
FT_UInt32 phy_font_max_size; |
||||
FT_UInt32 phy_font_section_size; |
||||
FT_UInt32 phy_font_section_offset; |
||||
|
||||
FT_UInt gps_max_size; |
||||
FT_UInt32 gps_section_size; |
||||
FT_UInt32 gps_section_offset; |
||||
|
||||
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 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; |
||||
|
||||
|
||||
/* used in 'color_flags' field of the PFR_Header */ |
||||
typedef enum PFR_HeaderFlags_ |
||||
{ |
||||
PFR_FLAG_BLACK_PIXEL = 1, |
||||
PFR_FLAG_INVERT_BITMAP = 2 |
||||
|
||||
} PFR_HeaderFlags; |
||||
|
||||
|
||||
/************************************************************************/ |
||||
|
||||
typedef struct PFR_LogFontRec_ |
||||
{ |
||||
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; |
||||
|
||||
|
||||
typedef enum PFR_LogFlags_ |
||||
{ |
||||
PFR_LOG_EXTRA_ITEMS = 0x40, |
||||
PFR_LOG_2BYTE_BOLD = 0x20, |
||||
PFR_LOG_BOLD = 0x10, |
||||
PFR_LOG_2BYTE_STROKE = 8, |
||||
PFR_LOG_STROKE = 4, |
||||
PFR_LINE_JOIN_MASK = 3 |
||||
|
||||
} PFR_LogFlags; |
||||
|
||||
|
||||
typedef enum PFR_LineJoinFlags_ |
||||
{ |
||||
PFR_LINE_JOIN_MITER = 0, |
||||
PFR_LINE_JOIN_ROUND = 1, |
||||
PFR_LINE_JOIN_BEVEL = 2 |
||||
|
||||
} PFR_LineJoinFlags; |
||||
|
||||
|
||||
/************************************************************************/ |
||||
|
||||
typedef enum PFR_BitmapFlags_ |
||||
{ |
||||
PFR_BITMAP_3BYTE_OFFSET = 4, |
||||
PFR_BITMAP_2BYTE_SIZE = 2, |
||||
PFR_BITMAP_2BYTE_CHARCODE = 1 |
||||
|
||||
} PFR_BitmapFlags; |
||||
|
||||
|
||||
typedef struct PFR_BitmapCharRec_ |
||||
{ |
||||
FT_UInt char_code; |
||||
FT_UInt gps_size; |
||||
FT_UInt32 gps_offset; |
||||
|
||||
} PFR_BitmapCharRec, *PFR_BitmapChar; |
||||
|
||||
|
||||
typedef enum PFR_StrikeFlags_ |
||||
{ |
||||
PFR_STRIKE_2BYTE_COUNT = 0x10, |
||||
PFR_STRIKE_3BYTE_OFFSET = 0x08, |
||||
PFR_STRIKE_3BYTE_SIZE = 0x04, |
||||
PFR_STRIKE_2BYTE_YPPM = 0x02, |
||||
PFR_STRIKE_2BYTE_XPPM = 0x01 |
||||
|
||||
} PFR_StrikeFlags; |
||||
|
||||
|
||||
typedef struct PFR_StrikeRec_ |
||||
{ |
||||
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; |
||||
|
||||
|
||||
|
||||
/************************************************************************/ |
||||
|
||||
typedef struct PFR_CharRec_ |
||||
{ |
||||
FT_UInt char_code; |
||||
FT_Int advance; |
||||
FT_UInt gps_size; |
||||
FT_UInt32 gps_offset; |
||||
|
||||
} PFR_CharRec, *PFR_Char; |
||||
|
||||
|
||||
/************************************************************************/ |
||||
|
||||
typedef struct PFR_DimensionRec_ |
||||
{ |
||||
FT_UInt standard; |
||||
FT_UInt num_stem_snaps; |
||||
FT_Int* stem_snaps; |
||||
|
||||
} PFR_DimensionRec, *PFR_Dimension; |
||||
|
||||
|
||||
/************************************************************************/ |
||||
|
||||
typedef struct PFR_PhyFontRec_ |
||||
{ |
||||
FT_Memory memory; |
||||
FT_UInt32 offset; |
||||
|
||||
FT_UInt font_ref_number; |
||||
FT_UInt outline_resolution; |
||||
FT_UInt metrics_resolution; |
||||
FT_BBox bbox; |
||||
FT_UInt flags; |
||||
FT_UInt standard_advance; |
||||
|
||||
PFR_DimensionRec horizontal; |
||||
PFR_DimensionRec vertical; |
||||
|
||||
FT_String* font_id; |
||||
|
||||
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; |
||||
|
||||
} PFR_PhyFontRec, *PFR_PhyFont; |
||||
|
||||
typedef enum PFR_PhyFlags_ |
||||
{ |
||||
PFR_PHY_EXTRA_ITEMS = 0x80, |
||||
PFR_PHY_3BYTE_GPS_OFFSET = 0x20, |
||||
PFR_PHY_2BYTE_GPS_SIZE = 0x10, |
||||
PFR_PHY_ASCII_CODE = 0x08, |
||||
PFR_PHY_PROPORTIONAL = 0x04, |
||||
PFR_PHY_2BYTE_CHARCODE = 0x02, |
||||
PFR_PHY_VERTICAL = 0x01 |
||||
|
||||
} PFR_PhyFlags; |
||||
|
||||
/************************************************************************/ |
||||
|
||||
typedef enum PFR_GlyphFlags_ |
||||
{ |
||||
PFR_GLYPH_IS_COMPOUND = 0x80, |
||||
PFR_GLYPH_EXTRA_ITEMS = 0x08, |
||||
PFR_GLYPH_1BYTE_XYCOUNT = 0x04, |
||||
PFR_GLYPH_XCOUNT = 0x02, |
||||
PFR_GLYPH_YCOUNT = 0x01 |
||||
|
||||
} PFR_GlyphFlags; |
||||
|
||||
/* controlled coordinate */ |
||||
typedef struct PFR_CoordRec_ |
||||
{ |
||||
FT_UInt org; |
||||
FT_UInt cur; |
||||
|
||||
} PFR_CoordRec, *PFR_Coord; |
||||
|
||||
|
||||
typedef struct PFR_SubGlyphRec_ |
||||
{ |
||||
FT_Fixed x_scale; |
||||
FT_Fixed y_scale; |
||||
FT_Int x_delta; |
||||
FT_Int y_delta; |
||||
FT_UInt32 gps_offset; |
||||
FT_UInt gps_size; |
||||
|
||||
} PFR_SubGlyphRec, *PFR_SubGlyph; |
||||
|
||||
|
||||
typedef enum PFR_SubgGlyphFlags_ |
||||
{ |
||||
PFR_SUBGLYPH_3BYTE_OFFSET = 0x80, |
||||
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; |
||||
FT_Pos* x_control; |
||||
FT_Pos* y_control; |
||||
|
||||
|
||||
FT_UInt num_subs; |
||||
FT_UInt max_subs; |
||||
PFR_SubGlyphRec* subs; |
||||
|
||||
FT_GlyphLoader loader; |
||||
FT_Bool path_begun; |
||||
|
||||
} PFR_GlyphRec, *PFR_Glyph; |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __PFR_TYPES_H__ */ |
@ -0,0 +1,70 @@ |
||||
#
|
||||
# FreeType 2 PFR driver configuration rules
|
||||
#
|
||||
|
||||
|
||||
# Copyright 1996-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.
|
||||
|
||||
|
||||
# Pfr driver directory
|
||||
#
|
||||
PFR_DIR := $(SRC_)pfr
|
||||
PFR_DIR_ := $(PFR_DIR)$(SEP)
|
||||
|
||||
|
||||
# compilation flags for the driver
|
||||
#
|
||||
PFR_COMPILE := $(FT_COMPILE) $I$(PFR_DIR)
|
||||
|
||||
|
||||
# Pfr driver sources (i.e., C files)
|
||||
#
|
||||
PFR_DRV_SRC := $(PFR_DIR_)pfrload.c \
|
||||
$(PFR_DIR_)pfrgload.c \
|
||||
$(PFR_DIR_)pfrcmap.c \
|
||||
$(PFR_DIR_)pfrdrivr.c \
|
||||
$(PFR_DIR_)pfrobjs.c
|
||||
|
||||
# Pfr driver headers
|
||||
#
|
||||
PFR_DRV_H := $(PFR_DRV_SRC:%.c=%.h)
|
||||
|
||||
|
||||
# Pfr driver object(s)
|
||||
#
|
||||
# PFR_DRV_OBJ_M is used during `multi' builds
|
||||
# PFR_DRV_OBJ_S is used during `single' builds
|
||||
#
|
||||
PFR_DRV_OBJ_M := $(PFR_DRV_SRC:$(PFR_DIR_)%.c=$(OBJ_)%.$O)
|
||||
PFR_DRV_OBJ_S := $(OBJ_)pfr.$O
|
||||
|
||||
# Pfr driver source file for single build
|
||||
#
|
||||
PFR_DRV_SRC_S := $(PFR_DIR_)pfr.c
|
||||
|
||||
|
||||
# Pfr driver - single object
|
||||
#
|
||||
$(PFR_DRV_OBJ_S): $(PFR_DRV_SRC_S) $(PFR_DRV_SRC) $(FREETYPE_H) $(PFR_DRV_H) |
||||
$(PFR_COMPILE) $T$@ $(PFR_DRV_SRC_S)
|
||||
|
||||
|
||||
# Pfr driver - multiple objects
|
||||
#
|
||||
$(OBJ_)%.$O: $(PFR_DIR_)%.c $(FREETYPE_H) $(PFR_DRV_H) |
||||
$(PFR_COMPILE) $T$@ $<
|
||||
|
||||
|
||||
# update main driver object lists
|
||||
#
|
||||
DRV_OBJS_S += $(PFR_DRV_OBJ_S)
|
||||
DRV_OBJS_M += $(PFR_DRV_OBJ_M)
|
||||
|
||||
# EOF
|
Loading…
Reference in new issue