package provide Freetype::ftimage 0.1

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

ffidl::typedef FT_Pos   long

ft::struct define FT_Vector {
    {x int - FT_Pos 1 FT_Pos}
    {y int - FT_Pos 1 FT_Pos}
}

ft::struct define FT_BBox {
    {xMin int - FT_Pos 1 FT_Pos}
    {yMin int - FT_Pos 1 FT_Pos}
    {xMax int - FT_Pos 1 FT_Pos}
    {yMax int - FT_Pos 1 FT_Pos}
}

set FT_PIXEL_MODE_NONE  0
set FT_PIXEL_MODE_MONO  1
set FT_PIXEL_MODE_GRAY  2
set FT_PIXEL_MODE_GRAY2 3
set FT_PIXEL_MODE_GRAY4 4
set FT_PIXEL_MODE_LCD   5
set FT_PIXEL_MODE_LCD_V 6
set FT_PIXEL_MODE_BGRA  7
set FT_PIXEL_MODE_MAX   8
set ft_pixel_mode_none  $FT_PIXEL_MODE_NONE
set ft_pixel_mode_mono  $FT_PIXEL_MODE_MONO
set ft_pixel_mode_grays $FT_PIXEL_MODE_GRAY
set ft_pixel_mode_pal2  $FT_PIXEL_MODE_GRAY2
set ft_pixel_mode_pal4  $FT_PIXEL_MODE_GRAY4

ft::struct define FT_Bitmap {
    {rows         int - int     1 int}
    {width        int - int     1 int}
    {pitch        int - int     1 int}
    {buffer       int - pointer 1 pointer}
    {num_grays    int - short   1 short}
    {pixel_mode   int - char    1 char}
    {palette_mode int - char    1 char}
    {palette      int - pointer 1 pointer}
}
oo::define FT_Bitmap method get {varName} {
    if {$varName eq "buffer"} {
        set num [expr {[next rows] * [next pitch]}]
        set ptr [next buffer]
        if {$num == 0 || $ptr == 0} {
            return {}
        } else {
            return [ffidl::peek $ptr $num]
        }
    }
    next $varName
}

oo::define FT_Bitmap method set {varName varValue} {
    if {$varName eq "buffer"} {
        ::ft::get_bytearray_pointer varValue adr len
        set p [::ffidl::malloc $len]
        ft::memcpy $p $adr $len
        lappend _allocated $p
        next $varName $p
        return [my get $varName]
    }
    next $varName $varValue
}

ft::struct define FT_Outline {
    {n_contours int    - short     1  short}
    {n_points   int    - short     1  short}
    {points     object * FT_Vector 1  pointer}
    {tags       int    * char      1  pointer}
    {contrours  int    * short     1  pointer}
    {flags      int    - int       1  int}
}
oo::define FT_Outline method get {varName} {
    switch -- $varName {
        "points"    {return [my _get_tcl_list_from_array_pointer $varName n_points]}
        "tags"      {return [my _get_tcl_list_from_array_pointer $varName n_points]}
        "contrours" {return [my _get_tcl_list_from_array_pointer $varName n_contours]}
    }
    next $varName
}
oo::define FT_Outline method set {varName varValue} {
    switch -- $varName {
        "points"    -
        "tags"      -
        "contrours" {error "read only"}
    }
    next $varName $varValue
}

#define FT_OUTLINE_CONTOURS_MAX  SHRT_MAX
#define FT_OUTLINE_POINTS_MAX    SHRT_MAX

set FT_OUTLINE_NONE             [expr 0x00]
set FT_OUTLINE_OWNER            [expr 0x01]
set FT_OUTLINE_EVEN_ODD_FILL    [expr 0x02]
set FT_OUTLINE_REVERSE_FILL     [expr 0x04]
set FT_OUTLINE_IGNORE_DROPOUTS  [expr 0x08]
set FT_OUTLINE_SMART_DROPOUTS   [expr 0x10]
set FT_OUTLINE_INCLUDE_STUBS    [expr 0x20]

set FT_OUTLINE_HIGH_PRECISION   [expr 0x100]
set FT_OUTLINE_SINGLE_PASS      [expr 0x200]

set ft_outline_none             $FT_OUTLINE_NONE
set ft_outline_owner            $FT_OUTLINE_OWNER
set ft_outline_even_odd_fill    $FT_OUTLINE_EVEN_ODD_FILL
set ft_outline_reverse_fill     $FT_OUTLINE_REVERSE_FILL
set ft_outline_ignore_dropouts  $FT_OUTLINE_IGNORE_DROPOUTS
set ft_outline_high_precision   $FT_OUTLINE_HIGH_PRECISION
set ft_outline_single_pass      $FT_OUTLINE_SINGLE_PASS

proc FT_CURVE_TAG {flag} {return [expr {$flag & 3}]}

set FT_CURVE_TAG_ON            1
set FT_CURVE_TAG_CONIC         0
set FT_CURVE_TAG_CUBIC         2

set FT_CURVE_TAG_HAS_SCANMODE  4

set FT_CURVE_TAG_TOUCH_X       8  ;# reserved for the TrueType hinter
set FT_CURVE_TAG_TOUCH_Y      16  ;# reserved for the TrueType hinter

set FT_CURVE_TAG_TOUCH_BOTH   [expr ($FT_CURVE_TAG_TOUCH_X | $FT_CURVE_TAG_TOUCH_Y)]

set FT_Curve_Tag_On       $FT_CURVE_TAG_ON
set FT_Curve_Tag_Conic    $FT_CURVE_TAG_CONIC
set FT_Curve_Tag_Cubic    $FT_CURVE_TAG_CUBIC
set FT_Curve_Tag_Touch_X  $FT_CURVE_TAG_TOUCH_X
set FT_Curve_Tag_Touch_Y  $FT_CURVE_TAG_TOUCH_Y

#TODO FT_Outline Function Pointers

ft::struct define FT_Outline_Funcs {
    {move_to  int - pointer 1 pointer}
    {line_to  int - pointer 1 pointer}
    {conic_to int - pointer 1 pointer}
    {cubic_to int - pointer 1 pointer}
    {shift    int - int     1 int}
    {delta    int - FT_Pos  1 FT_Pos}
}

proc FT_IMAGE_TAG {valueName x1 x2 x3 x4} {
    upvar $valueName value

    if {$x1 eq ""} {set v1 0} else {binary scan $x1 c v1}
    if {$x2 eq ""} {set v2 0} else {binary scan $x2 c v2}
    if {$x3 eq ""} {set v3 0} else {binary scan $x3 c v3}
    if {$x4 eq ""} {set v4 0} else {binary scan $x4 c v4}
    set value [expr {($v1 << 24) | ($v2 << 16) | ($v3 << 8) | $v4}]
}

FT_IMAGE_TAG FT_GLYPH_FORMAT_NONE "" "" "" ""
FT_IMAGE_TAG FT_GLYPH_FORMAT_COMPOSITE "c" "o" "m" "p" 
FT_IMAGE_TAG FT_GLYPH_FORMAT_BITMAP    "b" "i" "t" "s" 
FT_IMAGE_TAG FT_GLYPH_FORMAT_OUTLINE   "o" "u" "t" "l" 
FT_IMAGE_TAG FT_GLYPH_FORMAT_PLOTTER   "p" "l" "o" "t"

rename FT_IMAGE_TAG {}

ffidl::typedef FT_Glyph_Format int

set ft_glyph_format_none       $FT_GLYPH_FORMAT_NONE
set ft_glyph_format_composite  $FT_GLYPH_FORMAT_COMPOSITE
set ft_glyph_format_bitmap     $FT_GLYPH_FORMAT_BITMAP
set ft_glyph_format_outline    $FT_GLYPH_FORMAT_OUTLINE
set ft_glyph_format_plotter    $FT_GLYPH_FORMAT_PLOTTER


ft::struct define FT_Span {
    {x        int - short            1 short}
    {len      int - {unsigned short} 1 {unsigned short}}
    {coverage int - {unsigned char}  1 {unsigned char}}
}

#TODO FT_Span Callback Function Pointers
set FT_RASTER_FLAG_DEFAULT  [expr 0x0]
set FT_RASTER_FLAG_AA       [expr 0x1]
set FT_RASTER_FLAG_DIRECT   [expr 0x2]
set FT_RASTER_FLAG_CLIP     [expr 0x4]
set ft_raster_flag_default  $FT_RASTER_FLAG_DEFAULT
set ft_raster_flag_aa       $FT_RASTER_FLAG_AA
set ft_raster_flag_direct   $FT_RASTER_FLAG_DIRECT
set ft_raster_flag_clip     $FT_RASTER_FLAG_CLIP

ft::struct define FT_Raster_Params {
    {target      object * FT_Bitmap 1 pointer}
    {source      int    - pointer   1 pointer}
    {flags       int    - int       1 int}
    {gray_spans  int    - pointer   1 pointer}
    {blask_spans int    - pointer   1 pointer}
    {bit_test    int    - pointer   1 pointer}
    {bit_set     int    - pointer   1 pointer}
    {user        int    - pointer   1 pointer}
    {clip_box    object - FT_BBox   1 FT_BBox}
}

# TODO FT_Raster Callback Function Pointers

ft::struct define FT_Raster_Funcs {
    {glypy_format    int - int     1 int}
    {raster_new      int - pointer 1 pointer}
    {raster_reset    int - pointer 1 pointer}
    {raster_set_mode int - pointer 1 pointer}
    {raster_render   int - pointer 1 pointer}
    {raster_done     int - pointer 1 pointer}
}

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