| /***************************************************************************/ |
| /* */ |
| /* 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 <ft2build.h> |
| #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 */ |