package provide Freetype::ftmodapi 0.1

if {![info exists _source([file tail [info script]])]} {
package require Freetype::ft2build
package require $FT_FREETYPE

#module bit flags
set FT_MODULE_FONT_DRIVER 1 ;# this module is a font driver
set FT_MODULE_RENDERER    2 ;# this module is a renderer
set FT_MODULE_HINTER      4 ;# this module is a glyph hinter
set FT_MODULE_STYLER      8 ;# this module is a styler

set FT_MODULE_DRIVER_SCALABLE    [expr 0x100] ;# the driver supports scalable fonts
set FT_MODULE_DRIVER_NO_OUTLINES [expr 0x200] ;# the driver does not support vector outlines
set FT_MODULE_DRIVER_HAS_HINTER  [expr 0x400] ;# the driver provides its own hinter

# deprecated values
set ft_module_font_driver        $FT_MODULE_FONT_DRIVER
set ft_module_renderer           $FT_MODULE_RENDERER
set ft_module_hinter             $FT_MODULE_HINTER
set ft_module_styler             $FT_MODULE_STYLER

set ft_module_driver_scalable    $FT_MODULE_DRIVER_SCALABLE
set ft_module_driver_no_outlines $FT_MODULE_DRIVER_NO_OUTLINES
set ft_module_driver_has_hinter  $FT_MODULE_DRIVER_HAS_HINTER

ffidl::typedef FT_Module_Interface   pointer-proc
ffidl::typedef FT_Module_Constructor pointer-proc
ffidl::typedef FT_Module_Destructor  pointer-proc
ffidl::typedef FT_Module_Requester   pointer-proc

ft::struct define FT_Module_Class {
    {module_flags     int     - FT_ULong               1  FT_ULong}  
    {module_size      int     - FT_ULong               1  FT_ULong}
    {module_name      string  * char                   1  pointer}
    {module_version   int     - FT_Fixed               1  FT_Fixed}
    {module_requires  int     - FT_Fixed               1  FT_Fixed}
    {module_interface int     - pointer                1  pointer}
    {module_init      int     - FT_Module_Constructor  1  pointer}
    {module_done      int     - FT_Module_Destructor   1  pointer}
    {get_interface    int     - FT_Module_Requester    1  pointer}
}

::ffidl::callout _FT_Add_Module {pointer pointer} int \
    [::ffidl::symbol $::ft::lib FT_Add_Module]
proc FT_Add_Module {library clazz} {
    set result [_FT_Add_Module [$face getPointer] [$class getPointer]]
    return $result
}

::ffidl::callout _FT_Get_Module {pointer pointer-utf8} FT_Module \
    [::ffidl::symbol $::ft::lib FT_Get_Module]
proc FT_Get_Module {library module_name} {
    set result [_FT_Get_Module [$library getPointer] $module_name]
    if {$result == 0} {
        return [FT_Module new $result]
    } else {
        return {}
    }
}

::ffidl::callout _FT_Remove_Module {pointer pointer} int \
    [::ffidl::symbol $::ft::lib FT_Remove_Module]
proc FT_Remove_Module {library module} {
    set result [_FT_Remove_Module [$face getPointer] [$module getPointer]]
    return $result
}

# FIXME: value must be bytearray. the parameter is generic type.
# So we can not convert it to bytearray.
if {[catch {::ffidl::symbol $::ft::lib FT_Property_Set} _symbol] == 0} {
::ffidl::callout _FT_Property_Set {pointer pointer-utf8 pointer-utf8 pointer} int $_symbol
proc FT_Property_Set {library module_name property_name valueName} {
    upvar $valueName value

    if {[info object isa object $value]} {
        set p [$value getPointer]
    } elseif {[string is list $value]} {
        set bin {}
        for {set i 0} {$i < [llength $value]} {incr i} {
            set v [lindex $value $i]
            if {[info object isa object $v]} {
                set v [$v getPointer]
            }
            append bin [::ft::_bytearray_from int $v]
        }
        ::ft::get_bytearray_pointer bin p len
    } else {
        set bin [::ft::_bytearray_from int $value]
        ::ft::get_bytearray_pointer bin p len
    }

    set result [_FT_Property_Set [$library getPointer] $module_name $property_name $p]
    return $result
}
}

# FIXME: value must be bytearray and allocated enough size.
# the parameter is generic type.
if {[catch {::ffidl::symbol $::ft::lib FT_Property_Get} _symbol] == 0} {
::ffidl::callout _FT_Property_Get {pointer pointer-utf8 pointer-utf8 pointer} int $_symbol
proc FT_Property_Get {library module_name property_name valueName} {
    upvar $valueName value

    if {[info object isa object $value]} {
        set p [$value getPointer]
        set result [_FT_Property_Get [$library getPointer] $module_name $property_name $p]
    } elseif {[string is integer $value]} {
        set bin [::ft::_bytearray_from int $value]
        ::ft::get_bytearray_pointer bin p len
        set result [_FT_Property_Get [$library getPointer] $module_name $property_name $p]
        set value [::ft::_bytearray_to int $bin]
    } elseif {[string is list $value]} {
        set bin [::ft::_bytearray_from_list $value int]
        ::ft::get_bytearray_pointer bin p len
        set result [_FT_Property_Get [$library getPointer] $module_name $property_name $p]
        set value [::ft::_bytearray_to_list $bin int]
    } else {
    }
    return $result
}
}

if {[catch {::ffidl::symbol $::ft::lib FT_Reference_Library} _symbol] == 0} {
::ffidl::callout _FT_Reference_Library {pointer} int $_symbol
proc FT_Reference_Library {library} {
    set result [_FT_Reference_Library [$library getPointer]]
    return $result
}
}

::ffidl::callout _FT_New_Library {pointer pointer-var} int \
    [::ffidl::symbol $::ft::lib FT_New_Library]
proc FT_New_Library {memory libraryVarName} {
    set p [::ft::_bytearray_from_pointer 0]
    set result [_FT_New_Library [$memory getPointer] p]
    if {$result == 0} {
        uplevel [list set $libraryVarName [FT_Library new [::ft::_bytearray_to_pointer $p]]
    }
    return $result
}

::ffidl::callout _FT_Done_Library {pointer} int \
    [::ffidl::symbol $::ft::lib FT_Done_Library]
proc FT_Done_Library {library} {
    set result [_FT_Done_Library [$library getPointer]]
    return $result
}

::ffidl::callout _FT_Set_Debug_Hook {pointer FT_UInt pointer-proc} void \
    [::ffidl::symbol $::ft::lib FT_Set_Debug_Hook]
proc FT_Set_Debug_Hook {library hook_index debug_hook} {
    ::ffidl::callback $debug_hook {pointer} void
    _FT_Set_Debug_Hook [$library getPointer] $hook_index $debug_hook
    return
}

::ffidl::callout _FT_Add_Default_Modules {pointer} void \
    [::ffidl::symbol $::ft::lib FT_Add_Default_Modules]
proc FT_Add_Default_Modules {library} {
    _FT_Add_Default_Modules [$library getPointer]
    return
}

set FT_TRUETYPE_ENGINE_TYPE_NONE        0
set FT_TRUETYPE_ENGINE_TYPE_UNPATENTED  1
set FT_TRUETYPE_ENGINE_TYPE_PATENTED    2
ffidl::typedef FT_TrueTypeEngineType int

if {[catch {::ffidl::symbol $::ft::lib FT_Get_TrueType_Engine_Type} _symbol] == 0} {
::ffidl::callout _FT_Get_TrueType_Engine_Type {pointer} FT_TrueTypeEngineType $_symbol
proc FT_Get_TrueType_Engine_Type {library} {
    set result [_FT_Get_TrueType_Engine_Type [$library getPointer]]
    return $result
}
}


set _source([file tail [info script]]) 1
}
