package provide Freetype::tttables 0.1

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

ft::struct define TT_Header {
    {Table_Version       int - FT_Fixed  1 FT_Fixed}
    {Font_Revision       int - FT_Fixed  1 FT_Fixed}
    {CheckSum_Adjust     int - FT_Long   1 FT_Long}
    {Magic_Number        int - FT_Long   1 FT_Long}
    {Flags               int - FT_UShort 1 FT_UShort}
    {Units_Per_EM        int - FT_UShort 1 FT_UShort}
    {Created             int - FT_Long   2 pointer}
    {Modified            int - FT_Long   2  pointer}
    {xMin                int - FT_Short  1 FT_Short}
    {yMin                int - FT_Short  1 FT_Short}
    {xMax                int - FT_Short  1 FT_Short}
    {yMax                int - FT_Short  1 FT_Short}
    {Mac_Style           int - FT_UShort 1 FT_UShort}
    {Lowest_Rec_PPEM     int - FT_UShort 1 FT_UShort}
    {Font_Direction      int - FT_Short  1 FT_Short}
    {Index_To_Loc_Format int - FT_Short  1 FT_Short}
    {Glyph_Data_Format   int - FT_Short  1 FT_Short}
}

ft::struct define TT_HoriHeader {
    {Version                int - FT_Fixed  1 FT_Fixed}
    {Ascender               int - FT_Short  1 FT_Short} 
    {Descender              int - FT_Short  1 FT_Short}
    {Line_Gap               int - FT_Short  1 FT_Short}
    {advance_Width_Max      int - FT_UShort 1 FT_UShort}
    {min_Left_Side_Bearing  int - FT_Short  1 FT_Short}
    {min_Right_Side_Bearing int - FT_Short  1 FT_Short}
    {xMax_Extent            int - FT_Short  1 FT_Short}
    {caret_Slope_Rise       int - FT_Short  1 FT_Short}
    {caret_Slope_Run        int - FT_Short  1 FT_Short}
    {caret_Offset           int - FT_Short  1 FT_Short} 
    {Reserved               int - FT_Short  4 FT_Short}
    {metric_Data_Format     int - FT_Short  1 FT_Short}
    {number_Of_HMetrics     int - FT_UShort 1 FT_UShort}
    {long_metrics           int - pointer   1 pointer}
    {short_metrics          int - pointer   1 pointer}
}

ft::struct define TT_VertHeader {
    {Version                 int - FT_Fixed  1 FT_Fixed}
    {Ascender                int - FT_Short  1 FT_Short} 
    {Descender               int - FT_Short  1 FT_Short}
    {Line_Gap                int - FT_Short  1 FT_Short}
    {advance_Height_Max      int - FT_UShort 1 FT_UShort}
    {min_Top_Side_Bearing    int - FT_Short  1 FT_Short}
    {min_Bottom_Side_Bearing int - FT_Short  1 FT_Short}
    {yMax_Extent             int - FT_Short  1 FT_Short}
    {caret_Slope_Rise        int - FT_Short  1 FT_Short}
    {caret_Slope_Run         int - FT_Short  1 FT_Short}
    {caret_Offset            int - FT_Short  1 FT_Short} 
    {Reserved                int - FT_Short  4 FT_Short}
    {metric_Data_Format      int - FT_Short  1 FT_Short}
    {number_Of_VMetrics      int - FT_UShort 1 FT_UShort}
    {long_metrics            int - pointer   1 pointer}
    {short_metrics           int - pointer   1 pointer}
}

ft::struct define TT_OS2 {
    {version                 int - FT_UShort 1 FT_UShort}
    {xAvgCharWidth           int - FT_Short  1 FT_Short}
    {usWeightClass           int - FT_UShort 1 FT_UShort}
    {usWidthClass            int - FT_UShort 1 FT_UShort}
    {fsType                  int - FT_Short  1 FT_Short}
    {ySubscriptXSize         int - FT_Short  1 FT_Short}
    {ySubscriptYSize         int - FT_Short  1 FT_Short}
    {ySubscriptXOffset       int - FT_Short  1 FT_Short}
    {ySubscriptYOffset       int - FT_Short  1 FT_Short}
    {ySuperscriptXSize       int - FT_Short  1 FT_Short}
    {ySuperscriptYSize       int - FT_Short  1 FT_Short}
    {ySuperscriptXOffset     int - FT_Short  1 FT_Short}
    {ySuperscriptYOffset     int - FT_Short  1 FT_Short}
    {yStrikeoutSize          int - FT_Short  1 FT_Short}
    {yStrikeoutPosition      int - FT_Short  1 FT_Short}
    {sFamilyClass            int - FT_Short  1 FT_Short}
    {panose                  int - FT_Byte  10 FT_Byte}
    {ulUnicodeRange1         int - FT_ULong  1 FT_ULong}
    {ulUnicodeRange2         int - FT_ULong  1 FT_ULong}
    {ulUnicodeRange3         int - FT_ULong  1 FT_ULong}
    {ulUnicodeRange4         int - FT_ULong  1 FT_ULong}
    {achVendID               int - FT_Char   4 FT_Char}
    {fsSelection             int - FT_UShort 1 FT_UShort}
    {usFirstCharIndex        int - FT_UShort 1 FT_UShort}
    {usLastCharIndex         int - FT_UShort 1 FT_UShort}
    {sTypoAscender           int - FT_Short  1 FT_Short}
    {sTypoDescender          int - FT_Short  1 FT_Short}
    {sTypoLineGap            int - FT_Short  1 FT_Short}
    {usWinAscent             int - FT_UShort 1 FT_UShort}
    {usWinDescent            int - FT_UShort 1 FT_UShort}
    {ulCodePageRange1        int - FT_ULong  1 FT_ULong}
    {ulCodePageRange2        int - FT_ULong  1 FT_ULong}
    {sxHeight                int - FT_Short  1 FT_Short}
    {sCapHeight              int - FT_Short  1 FT_Short}
    {usDefaultChar           int - FT_UShort 1 FT_UShort}
    {usBreakChar             int - FT_UShort 1 FT_UShort}
    {usMaxContext            int - FT_UShort 1 FT_UShort}
    {usLowerOpticalPointSize int - FT_UShort 1 FT_UShort}
    {usUpperOpticalPointSize int - FT_UShort 1 FT_UShort}
}

ft::struct define TT_Postscript {
    {FormatType         int - FT_Fixed 1 FT_Fixed}
    {italicAngle        int - FT_Fixed 1 FT_Fixed}
    {underlinePosition  int - FT_Short 1 FT_Short}
    {underlineThickness int - FT_Short 1 FT_Short}
    {isFixedPitch       int - FT_ULong 1 FT_ULong}
    {minMemType42       int - FT_ULong 1 FT_ULong}
    {maxMemType42       int - FT_ULong 1 FT_ULong}
    {minMemType1        int - FT_ULong 1 FT_ULong}
    {maxMemType1        int - FT_ULong 1 FT_ULong}
}

ft::struct define TT_PCLT {
    {Version                int - FT_Fixed  1 FT_Fixed }
    {FontNumber             int - FT_ULong  1 FT_ULong }
    {Pitch                  int - FT_UShort 1 FT_UShort }
    {xHeight                int - FT_UShort 1 FT_UShort }
    {Style                  int - FT_UShort 1 FT_UShort }
    {TypeFamily             int - FT_UShort 1 FT_UShort }
    {CapHeight              int - FT_UShort 1 FT_UShort }
    {SymbolSet              int - FT_UShort 1 FT_UShort }
    {TypeFace            string - FT_Char 16 FT_Char }
    {CharacterComplement string - FT_Char  8 FT_Char }
    {FileName            string - FT_Char  6 FT_Char }
    {StrokeWeight           int - FT_Char  1 FT_Char }
    {WidthType              int - FT_Char  1 FT_Char }
    {SerifStyle             int - FT_Byte  1 FT_Byte }
    {Reserved               int - FT_Byte  1 FT_Byte }
}

ft::struct define TT_MaxProfile {
    {version               int - FT_Fixed  1 FT_Fixed}
    {numGlyphs             int - FT_UShort 1 FT_UShort}
    {maxPoints             int - FT_UShort 1 FT_UShort}
    {maxContours           int - FT_UShort 1 FT_UShort}
    {maxCompositePoints    int - FT_UShort 1 FT_UShort}
    {maxCompositeContours  int - FT_UShort 1 FT_UShort}
    {maxZones              int - FT_UShort 1 FT_UShort}
    {maxTwilightPoints     int - FT_UShort 1 FT_UShort}
    {maxStorage            int - FT_UShort 1 FT_UShort}
    {maxFunctionDefs       int - FT_UShort 1 FT_UShort}
    {maxInstructionDefs    int - FT_UShort 1 FT_UShort}
    {maxStackElements      int - FT_UShort 1 FT_UShort}
    {maxSizeOfInstructions int - FT_UShort 1 FT_UShort}
    {maxComponentElements  int - FT_UShort 1 FT_UShort}
    {maxComponentDepth     int - FT_UShort 1 FT_UShort}
}

set ft_sfnt_head 0    ;# TT_Header
set ft_sfnt_maxp 1    ;# TT_MaxProfile
set ft_sfnt_os2  2    ;# TT_OS2
set ft_sfnt_hhea 3    ;# TT_HoriHeader
set ft_sfnt_vhea 4    ;# TT_VertHeader
set ft_sfnt_post 5    ;# TT_Postscript
set ft_sfnt_pclt 6    ;# TT_PCLT
set sfnt_max     7    ;# internal end mark
ffidl::typedef FT_Sfnt_Tag int


ffidl::callout _FT_GetSfnt_Table {pointer int} pointer \
    [::ffidl::symbol $::ft::lib FT_Get_Sfnt_Table]
proc FT_Get_Sfnt_Table {face tag} {
    set p [_FT_GetSfnt_Table [$face getPointer] $tag]
    if {$p == 0} {return {}}
    switch -- $tag {
        0 {return [TT_Header new $p]}
        1 {return [TT_MaxProfile new $p]}
        2 {return [TT_OS2 new $p]}
        3 {return [TT_HoriHeader new $p]}
        4 {return [TT_VertHeader new $p]}
        5 {return [TT_Postscript new $p]}
        6 {return [TT_PCLT new $p]}
    }
    error "unknown type $p"
}

ffidl::callout _FT_Load_Sfnt_Table {pointer int int pointer pointer-var} int \
    [::ffidl::symbol $::ft::lib FT_Load_Sfnt_Table]
proc FT_Load_Sfnt_Table {face tag offset bufferVarName lengthVarName} {
    upvar $bufferVarName buffer
    upvar $lengthVarName length
    if {[info exists buffer]} {
        ::ft::get_bytearray_pointer buffer adr len
    } else {
        set adr 0
    }
    if {[info exists length]} {
        set p2 [::ft::_bytearray_from FT_ULong $length]
    } else {
        set p2 [::ft::_bytearray_from FT_ULong 0]
    }
    set result [_FT_Load_Sfnt_Table [$face getPointer] $tag $offset $adr p2]
    if {$result == 0} {
        set length [::ft::_bytearray_to FT_ULong $p2]
    }
    return $result
}

ffidl::callout _FT_Sfnt_Table_Info {pointer int pointer pointer} int \
    [::ffidl::symbol $::ft::lib FT_Sfnt_Table_Info]
proc FT_Sfnt_Table_Info {face table_index tagVarName lengthVarName} {
    upvar $tagVarName tag
    upvar $lengthVarName length

    if {$tagVarName ne ""} {
        set bin1 [::ft::_bytearray_from FT_ULong 0]
        ::ft::get_bytearray_pointer bin1 p1 len
    } else {
        set p1 0
    }
    set bin2 [::ft::_bytearray_from FT_ULong 0]
    ::ft::get_bytearray_pointer bin2 p2 len


    set result [_FT_Sfnt_Table_Info [$face getPointer] $table_index $p1 $p2]
    if {$result == 0} {
        if {$tagVarName ne ""} {
            set tag    [::ft::_bytearray_to FT_ULong $bin1]
        }
        set length [::ft::_bytearray_to FT_ULong $bin2]
    }
    return $result
}

ffidl::callout _FT_Get_CMap_Language_ID {pointer} FT_ULong \
    [::ffidl::symbol $::ft::lib FT_Get_CMap_Language_ID]
proc FT_Get_CMap_Language_ID {charmap} {
    set result [_FT_Get_CMap_Language_ID [$charmap getPointer]]
    return $result
}

ffidl::callout _FT_Get_CMap_Format {pointer} FT_ULong \
    [::ffidl::symbol $::ft::lib FT_Get_CMap_Format]
proc FT_Get_CMap_Format {charmap} {
    set result [_FT_Get_CMap_Format [$charmap getPointer]]
    return $result
}

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