/***************************************************************************/ /* */ /* ftltypes.h */ /* */ /* Implementation of FreeType Layout API (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 #include FT_LAYOUT_H #include FT_INTERNAL_FTL_TYPES_H #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_OBJECTS_H #include FT_SERVICE_LAYOUT_H #include FT_LIST_H static void destroy_feaatures_requests ( FT_Memory memory, void * data, void * user ); static FT_Error ft_face_get_layout_service( FT_Face face, FT_Service_Layout *aservice ) { FT_Error error; *aservice = NULL; if ( !face ) return FT_Err_Invalid_Face_Handle; error = FT_Err_Invalid_Argument; FT_FACE_LOOKUP_SERVICE( face, *aservice, LAYOUT ); if ( *aservice ) error = FT_Err_Ok; return error; } FT_EXPORT_DEF( FT_Error ) FTL_Get_Font ( FT_Face face, FTL_Font * font ) { FT_Error error; FT_Service_Layout service; if (( error = ft_face_get_layout_service( face, &service ) )) return error; error = FT_Err_Invalid_Argument; if ( service->get_font ) error = service->get_font ( face, font ); return error; } FT_EXPORT_DEF( FT_Error ) FTL_Query_EngineType ( FT_Face face, FTL_EngineType * engine_type) { FT_Error error; FT_Service_Layout service; if ( !face ) return FT_Err_Invalid_Argument; if (( error = ft_face_get_layout_service( face, &service ) )) return error; error = FT_Err_Invalid_Argument; if ( service->get_engine_type ) { error = FT_Err_Ok; *engine_type = service->get_engine_type( face ); } return error; } FT_EXPORT_DEF( FT_Error ) FTL_New_FeaturesRequest ( FT_Face face, FTL_FeaturesRequest* request) { FT_Error error; FT_Service_Layout service; FTL_FeaturesRequest arequest = NULL; FT_ListNode node = NULL; FT_Memory memory; FTL_Font font; memory = face->driver->root.memory; if ( FT_NEW( node ) ) goto Exit; if (( error = ft_face_get_layout_service( face, &service ) )) goto Exit; if ( service->get_font ) { if (( error = service->get_font( face, &font ) )) goto Failure; } if ( service->new_features_request ) { if (( error = service->new_features_request( face, &arequest ) )) goto Failure; } else { if ( FT_NEW( arequest ) ) goto Exit; if (( error = FTL_FeaturesRequest_Init ( face, arequest ) )) { FT_FREE( arequest ); goto Failure; } } *request = arequest; node->data = arequest; FT_List_Add( &font->features_requests_list, node ); if ( !font->features_request ) font->features_request = arequest; error = FT_Err_Ok; Exit: return error; Failure: if ( arequest ) FT_FREE ( arequest ); if ( node ) FT_FREE( node ); return error; } FT_EXPORT_DEF( FT_Error ) FTL_FeaturesRequest_Init ( FT_Face face, FTL_FeaturesRequest request) { FT_Error error; FTL_Font font; if ( ( error = FTL_Get_Font( face, &font ) ) ) return error; request->font = font; request->direction = FTL_HORIZONTAL; return error; } FT_EXPORT_DEF( FT_Error ) FTL_Done_FeaturesRequest ( FTL_FeaturesRequest request ) { FT_Error error; FTL_Font font; FT_Face face; FT_Memory memory; FT_ListNode node; FT_Service_Layout service; font = request->font; FT_ASSERT(font); face = font->face; FT_ASSERT(face); memory = face->driver->root.memory; if (( error = ft_face_get_layout_service( face, &service ) )) return error; node = FT_List_Find( &font->features_requests_list, request ); FT_ASSERT(node); FT_List_Remove ( &font->features_requests_list, node ); FT_FREE( node ); if ( font->features_request == request ) { font->features_request = NULL; if ( font->features_requests_list.head ) font->features_request = (FTL_FeaturesRequest)(font->features_requests_list.head->data); } if ( service->done_features_request ) error = service->done_features_request( request ); else { error = FTL_FeaturesRequest_Finalize( request ); FT_FREE( request ); /* TODO */ } return error; } FT_EXPORT_DEF( FT_Error ) FTL_FeaturesRequest_Finalize ( FTL_FeaturesRequest request ) { return FT_Err_Ok; } FT_EXPORT_DEF ( FTL_Direction ) FTL_Get_FeaturesRequest_Direction ( FTL_FeaturesRequest request ) { FT_ASSERT( request ); return request->direction; } FT_EXPORT_DEF ( void ) FTL_Set_FeaturesRequest_Direction ( FTL_FeaturesRequest request, FTL_Direction direction) { FT_ASSERT( request ); request->direction = direction; } FT_EXPORT_DEF ( FT_Error ) FTL_Activate_FeaturesRequest ( FTL_FeaturesRequest request ) { FTL_Font font; if ( !request ) return FT_Err_Invalid_Argument; font = request->font; if ( !font ) return FT_Err_Invalid_Argument; font->features_request = request; return FT_Err_Ok; } FT_EXPORT_DEF( FT_Error ) FTL_Copy_FeaturesRequest ( FTL_FeaturesRequest from, FTL_FeaturesRequest to ) { FT_Error error; FT_Service_Layout service; if ( from->font != to->font ) return FT_Err_Invalid_Argument; if ( from == to ) return FT_Err_Ok; FT_ASSERT(from->font->face); if (( error = ft_face_get_layout_service( from->font->face, &service ) )) return error; if ( service->copy_features_request ) error = service->copy_features_request( from, to ); else error = FTL_FeaturesRequest_Copy ( from, to ); return error; } FT_EXPORT_DEF( FT_Error ) FTL_FeaturesRequest_Copy ( FTL_FeaturesRequest from, FTL_FeaturesRequest to ) { FTL_Set_FeaturesRequest_Direction(to, FTL_Get_FeaturesRequest_Direction(to)); return FT_Err_Ok; } FT_EXPORT_DEF( FT_Error ) FTL_Reset_FeaturesRequest ( FTL_FeaturesRequest request ) { FTL_Font font; FTL_FeaturesRequest default_request; if ( !request ) return FT_Err_Invalid_Argument; font = request->font; FT_ASSERT( font ); FTL_Font_Get_Default_FeaturesRequest( font, &default_request ); return FTL_Copy_FeaturesRequest( (FTL_FeaturesRequest)default_request, (FTL_FeaturesRequest)request ); } FT_EXPORT_DEF( FT_Error ) FTL_Font_Init ( FTL_Font font, FT_Face face ) { if ( (!font) || (!face) ) return FT_Err_Invalid_Argument; font->face = face; font->features_request = NULL; font->features_requests_list.head = NULL; font->features_requests_list.tail = NULL; return FT_Err_Ok; } FT_EXPORT_DEF( FT_Error ) FTL_Font_Finalize ( FTL_Font font ) { FT_Face face = font->face; FT_Memory memory = face->driver->root.memory; if ( !font ) return FT_Err_Invalid_Argument; FT_List_Finalize( &font->features_requests_list, (FT_List_Destructor)destroy_feaatures_requests, memory, NULL ); font->features_requests_list.head = NULL; font->features_requests_list.tail = NULL; font->features_request = NULL; font->face = NULL; return FT_Err_Ok; } static void destroy_feaatures_requests ( FT_Memory memory, void * data, void * user ) { FTL_Font font; FT_Face face; FTL_FeaturesRequest request = data; FT_Service_Layout service = NULL; FT_UNUSED(user); font = request->font; FT_ASSERT(font); face = font->face; FT_ASSERT(face); ft_face_get_layout_service( face, &service ); if ( service && service->done_features_request ) service->done_features_request( request ); else { FTL_FeaturesRequest_Finalize( request ); FT_FREE( request ); } } FT_EXPORT_DEF( FT_Error ) FTL_Font_Get_Default_FeaturesRequest ( FTL_Font font, FTL_FeaturesRequest * request ) { FT_ListNode node; if ( !font ) return FT_Err_Invalid_Argument; node = font->features_requests_list.head; *request = node->data; return FT_Err_Ok; } FT_EXPORT_DEF( FT_Error ) FTL_Font_Get_Current_FeaturesRequest ( FTL_Font font, FTL_FeaturesRequest * request ) { *request = font->features_request; FT_ASSERT ( *request ); return FT_Err_Ok; } FT_EXPORT_DEF( FT_UShort ) FTL_Get_LigatureCaret_Count ( FT_Face face, FT_UShort glyphID ) { FT_Error error; FT_Service_Layout service; if (( error = ft_face_get_layout_service( face, &service ) )) return 0; if ( service->get_ligature_caret_count ) return service->get_ligature_caret_count( face, glyphID ); else return 0; } FT_EXPORT_DEF( FT_UShort ) FTL_Get_LigatureCaret_Division ( FT_Face face, FT_UShort glyphID, FT_UShort nth ) { FT_Error error; FT_Service_Layout service; if (( error = ft_face_get_layout_service( face, &service ) )) return 0; if ( service->get_ligature_caret_division ) return service->get_ligature_caret_division( face, glyphID, nth ); else return 0; } FT_EXPORT_DEF( FT_Error ) FTL_New_Glyphs_Array ( FT_Memory memory, FTL_GlyphArray * garray ) { FT_Error error; FTL_GlyphArray agarray; if ( FT_NEW( agarray ) ) return error; agarray->memory = memory; agarray->glyphs = NULL; agarray->length = 0; agarray->allocated = 0; *garray = agarray; return FT_Err_Ok; } FT_EXPORT_DEF( FT_Error ) FTL_Set_Glyphs_Array_Length ( FTL_GlyphArray garray, FT_ULong new_length ) { FT_Error error; FT_Memory memory = garray->memory; if ( new_length > garray->allocated ) { if ( FT_RENEW_ARRAY( garray->glyphs, garray->allocated, new_length ) ) return error; garray->allocated = new_length; garray->length = new_length; } return FT_Err_Ok; } FT_EXPORT_DEF( FT_Error ) FTL_Copy_Glyphs_Array ( FTL_GlyphArray in, FTL_GlyphArray out ) { FT_Error error; FT_ULong i; if (( error = FTL_Set_Glyphs_Array_Length( out, in->length ) )) return error; for ( i = 0; i < in->length; i++ ) out->glyphs[i] = in->glyphs[i]; return FT_Err_Ok; } FT_EXPORT_DEF( FT_Error ) FTL_Done_Glyphs_Array ( FTL_GlyphArray garray ) { FT_Memory memory = garray->memory; FT_FREE( garray->glyphs ); FT_FREE( garray ); return FT_Err_Ok; } FT_EXPORT_DEF( FT_Error ) FTL_Substitute_Glyphs ( FT_Face face, FTL_GlyphArray in, FTL_GlyphArray out ) { FT_Error error; FT_Service_Layout service; FTL_Font font; FTL_FeaturesRequest request; if (( error = ft_face_get_layout_service( face, &service ) )) return error; if ( ( error = FTL_Get_Font ( face, &font ) ) ) return error; if ( ( error = FTL_Font_Get_Current_FeaturesRequest ( font, &request ) ) ) return error; if ( service->substitute_glyphs ) return service->substitute_glyphs( face, request, in, out ); else return FTL_Copy_Glyphs_Array(in, out); } /* END */