blob: af6a8d28786e07745df54618d2385dd6740410a0 [file] [log] [blame]
/***************************************************************************/
/* */
/* gxobjs.c */
/* */
/* AAT/TrueTypeGX objects manager (body). */
/* */
/* Copyright 2003 by */
/* Masatake YAMATO and Redhat K.K. */
/* */
/* This file 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. */
/* */
/***************************************************************************/
/***************************************************************************/
/* Development of the code in this file is support of */
/* Information-technology Promotion Agency, Japan. */
/***************************************************************************/
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TAGS_H
#include FT_LIST_H
#include FT_ERRORS_H
#include FT_LAYOUT_H
#include FT_INTERNAL_OBJECTS_H
#include FT_SERVICE_LAYOUT_H
#include FT_GXLAYOUT_H
#include "gxobjs.h"
#include "gxload.h"
#include "gxerrors.h"
#include "gxdriver.h"
#include "gxaccess.h"
#include "gxltypes.h"
extern const FT_Driver_ClassRec tt_driver_class;
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_gxobjs
static FT_Error
gx_face_init( FT_Stream stream,
GX_Face face,
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params );
static FT_Error
gx_font_load ( GX_Face face );
static void
gx_font_done( void * object );
static FT_Module_Interface
gx_module_get_interface ( FT_Module module,
const char* gx_interface );
static FT_Error
gx_face_get_kerning( FT_Face face,
FT_UInt left_glyph,
FT_UInt right_glyph,
FT_Vector* kerning );
static const FT_Service_LayoutRec gx_service_layout =
{
(FTL_Get_Font_Func) gxl_get_font,
(FTL_Get_EngineType_Func) gxl_get_engine_type,
(FTL_New_FeaturesRequest_Func) gxl_new_features_request,
(FTL_Done_FeaturesRequest_Func) gxl_done_features_request,
(FTL_Copy_FeaturesRequest_Func) gxl_copy_features_request,
(FTL_Get_LigatureCaret_Count_Func) gxl_get_ligature_caret_count,
(FTL_Get_LigatureCaret_Division_Func) gxl_get_ligature_caret_division,
(FTL_Substitute_Glyphs_Func) gxl_substitute_glyphs
};
static const FT_ServiceDescRec gx_services[] =
{
{ FT_SERVICE_ID_LAYOUT, &gx_service_layout },
{ NULL, NULL }
};
FT_LOCAL_DEF( FT_Error )
gx_driver_init( GX_Driver driver )
{
FT_Error error;
const void * module_name;
FT_Driver gx_driver_root = &driver->root;
FT_Driver_Class gx_driver_class = gx_driver_root->clazz;
module_name = gx_driver_class->root.module_name;
*gx_driver_class = tt_driver_class;
driver->root.clazz->root.module_name = module_name;
if (( error = ((FT_Module_Class*)gx_driver_class)->module_init( (FT_Module)driver ) ))
return error;
gx_driver_class->init_face = (FT_Face_InitFunc)gx_face_init;
gx_driver_class->get_kerning = gx_face_get_kerning;
((FT_Module_Class*)gx_driver_class)->get_interface = gx_module_get_interface;
return GX_Err_Ok;
}
static FT_Error
gx_face_init( FT_Stream stream,
GX_Face face,
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params )
{
FT_Error error;
/* TODO */
error = tt_driver_class.init_face ( stream, (FT_Face)face, face_index, num_params, params );
if ( error )
goto Exit;
error = gx_font_load ( face );
if ( error )
goto Exit;
Exit:
return error;
}
#define NEW_TABLE(tag) \
do \
{ \
if ( FT_NEW( font->tag ) ) \
goto Exit; \
\
FT_TRACE2 (( "\tloading %s...", #tag )); \
error = gx_table_load(face,stream,tag,font); \
if ( error ) \
{ \
if ( !(face->goto_table( face, TTAG_##tag, stream, 0 )) ) \
FT_TRACE2(("no table\n")); \
else if ( (TTAG_kern == TTAG_##tag) && \
(font->kern->version == 1) ) \
FT_TRACE2(("old kern\n")); \
else \
FT_TRACE2(("failed\n")); \
FT_FREE ( font->tag ); \
} \
else \
{ \
FT_TRACE2(("successful\n")); \
tables[set_index++] = (GX_Table)font->tag; \
} \
} while (0)
#define DONE_TABLE(tag) \
do \
{ \
if ( font->tag ) \
{ \
gx_table_done ( (GX_Table)font->tag, memory ); \
FT_FREE(font->tag); \
} \
} while ( 0 )
static FT_Error
gx_font_load( GX_Face face )
{
FT_Error error;
FT_Stream stream = face->root.stream;
FT_Memory memory = stream->memory;
GXL_Font font;
#define nTABLES 12
GX_Table tables[nTABLES];
FT_Int init_index, set_index = 0;
GXL_FeaturesRequest features_request;
for ( init_index = 0; init_index < nTABLES; init_index++ )
tables[init_index] = NULL;
if ( face->extra.data )
{
error = GX_Err_Busy_Extra_Data;
goto Exit;
}
if ( FT_NEW(font) )
goto Exit;
if (( error = FTL_Font_Init ( (FTL_Font)font, (FT_Face)face ) ))
goto Failure;
NEW_TABLE(feat);
NEW_TABLE(mort);
NEW_TABLE(morx);
NEW_TABLE(trak);
NEW_TABLE(kern);
NEW_TABLE(prop);
NEW_TABLE(lcar);
NEW_TABLE(opbd);
NEW_TABLE(bsln);
NEW_TABLE(fmtx);
NEW_TABLE(fdsc);
NEW_TABLE(just);
error = FT_Err_Unknown_File_Format;
if ((( font->mort ) || ( font->morx ))
&& ( font->feat ))
{
face->root.face_flags |= FT_FACE_FLAG_GLYPH_SUBSTITUTION;
error = GX_Err_Ok;
}
if ( font->kern )
{
face->root.face_flags |= FT_FACE_FLAG_KERNING;
error = GX_Err_Ok;
}
if ( error == GX_Err_Ok )
{
face->extra.finalizer = gx_font_done;
face->extra.data = font;
if (( error = FTL_New_FeaturesRequest ( (FT_Face)face,
(FTL_FeaturesRequest*)(&features_request) ) ))
goto Failure;
}
else
goto Failure;
Exit:
return error;
Failure:
for ( ; set_index > 0; set_index--)
{
if ( tables[set_index - 1] )
{
gx_table_done(tables[set_index - 1], memory);
FT_FREE(tables[set_index - 1]);
}
}
FT_FREE(font);
face->extra.finalizer = NULL;
face->extra.data = NULL;
return error;
}
static void
gx_font_done( void * object )
{
GXL_Font font = object;
FT_Face face = font->root.face;
FT_Memory memory = face->driver->root.memory; /* TODO */
DONE_TABLE(mort);
DONE_TABLE(morx);
DONE_TABLE(feat);
DONE_TABLE(trak);
DONE_TABLE(kern);
DONE_TABLE(prop);
DONE_TABLE(bsln);
DONE_TABLE(lcar);
DONE_TABLE(opbd);
DONE_TABLE(fmtx);
DONE_TABLE(fdsc);
DONE_TABLE(just);
FTL_Font_Finalize((FTL_Font)font);
FT_FREE(object);
}
static FT_Module_Interface
gx_module_get_interface( FT_Module module,
const char* gx_interface )
{
FT_Module_Interface gx;
gx = ft_service_list_lookup( gx_services, gx_interface );
if ( gx )
return gx;
/* TODO */
if ( tt_driver_class.root.get_interface )
return tt_driver_class.root.get_interface( module, gx_interface );
return NULL;
}
static FT_Error
gx_face_get_kerning( FT_Face face,
FT_UInt left_glyph,
FT_UInt right_glyph,
FT_Vector* kerning )
{
FT_Error error;
FTL_Font font;
GX_Kern kern;
FTL_Direction dir;
FTL_FeaturesRequest request;
kerning->x = 0;
kerning->y = 0;
if (( error = FTL_Get_Font ( face, &font ) ))
return error;
kern = ((GXL_Font)font)->kern;
if ( !kern )
/* Run old kerning handler */
return tt_driver_class.get_kerning ( face, left_glyph, right_glyph, kerning );
FTL_Font_Get_Current_FeaturesRequest( font, &request );
dir = FTL_Get_FeaturesRequest_Direction ( request );
return gx_kern_get_pair_kerning(kern,
left_glyph, right_glyph,
dir,
kerning);
}
/* END */