4 Star 20 Fork 4

七叶 / atk

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
interp_unix.go 18.51 KB
一键复制 编辑 原始数据 按行查看 历史
七叶 提交于 2019-04-09 09:53 . macos force link 8.6
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
// Copyright 2018 visualfc. All rights reserved.
// +build !windows
package interp
import (
"errors"
"fmt"
"image"
"image/color"
"image/draw"
"os"
"unsafe"
)
/*
#cgo darwin CFLAGS: -I/Library/Frameworks/Tcl.framework/Headers -I/Library/Frameworks/Tk.framework/Headers
#cgo darwin LDFLAGS: -F/Library/Frameworks -framework tcl -framework tk
#cgo linux CFLAGS: -I/usr/include/tcl
#cgo linux LDFLAGS: -ltcl -ltk
#include <tcl.h>
#include <tk.h>
#include <stdlib.h>
extern int _go_async_event_handler(Tcl_Event*, int);
static Tcl_Event* _c_create_async_event()
{
Tcl_Event *ev = (Tcl_Event*)Tcl_Alloc(sizeof(Tcl_Event));
ev->proc = &_go_async_event_handler;
ev->nextPtr = 0;
return ev;
}
static void _c_send_async_event(Tcl_ThreadId tid, Tcl_Event *ev)
{
Tcl_ThreadQueueEvent(tid, ev, TCL_QUEUE_TAIL);
Tcl_ThreadAlert(tid);
}
extern int _go_tcl_objcmd_proc(void *clientData, Tcl_Interp *interp, int objc, void *objv);
extern void _go_tcl_deletecmd_proc(void *clientData);
static int _c_tcl_objcmd_proc(void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
{
return _go_tcl_objcmd_proc(clientData, interp, objc, (Tcl_Obj**)objv);
}
static Tcl_Command _c_create_obj_command(Tcl_Interp *interp, char *name, void* clientData)
{
return Tcl_CreateObjCommand(interp,name,_c_tcl_objcmd_proc,clientData,&_go_tcl_deletecmd_proc);
}
extern int _go_tcl_actioncmd_proc(void *clientData, Tcl_Interp *interp, int objc, void *objv);
extern void _go_tcl_deleteaction_proc(void *clientData);
static int _c_tcl_actioncmd_proc(void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
{
return _go_tcl_actioncmd_proc(clientData, interp, objc, (Tcl_Obj**)objv);
}
static Tcl_Command _c_create_action_command(Tcl_Interp *interp, char *name, void* clientData)
{
return Tcl_CreateObjCommand(interp,name,_c_tcl_actioncmd_proc,clientData,&_go_tcl_deleteaction_proc);
}
static void _c_wrong_num_args(Tcl_Interp *interp, int objc, void *objv, char *message)
{
Tcl_WrongNumArgs(interp, objc, (Tcl_Obj**)objv, message) ;
}
*/
import "C"
var (
mainLoopThreadId C.Tcl_ThreadId
)
//export _go_tcl_objcmd_proc
func _go_tcl_objcmd_proc(clientData unsafe.Pointer, interp *C.Tcl_Interp, objc C.int, objv unsafe.Pointer) C.int {
objs := (*(*[1 << 20]*C.Tcl_Obj)(objv))[1:objc:objc]
var args []string
for _, obj := range objs {
args = append(args, objToString(interp, obj))
}
result, err := globalCommandMap.Invoke(uintptr(clientData), args)
if err != nil {
cs := C.CString(err.Error())
defer C.free(unsafe.Pointer(cs))
C._c_wrong_num_args(interp, 1, objv, cs)
return TCL_ERROR
}
if result != "" {
C.Tcl_SetObjResult(interp, stringToObj(result))
}
return TCL_OK
}
//export _go_tcl_deletecmd_proc
func _go_tcl_deletecmd_proc(clientData unsafe.Pointer) {
globalCommandMap.UnRegister(uintptr(clientData))
return
}
//export _go_tcl_actioncmd_proc
func _go_tcl_actioncmd_proc(clientData unsafe.Pointer, interp *C.Tcl_Interp, objc C.int, objv unsafe.Pointer) C.int {
objs := (*(*[1 << 20]*C.Tcl_Obj)(objv))[1:objc:objc]
var args []string
for _, obj := range objs {
args = append(args, objToString(interp, obj))
}
err := globalActionMap.Invoke(uintptr(clientData), args)
if err != nil {
cs := C.CString(err.Error())
defer C.free(unsafe.Pointer(cs))
C._c_wrong_num_args(interp, 1, objv, cs)
return TCL_ERROR
}
return TCL_OK
}
//export _go_tcl_deleteaction_proc
func _go_tcl_deleteaction_proc(clientData unsafe.Pointer) {
globalActionMap.UnRegister(uintptr(clientData))
return
}
//export _go_async_event_handler
func _go_async_event_handler(ev *C.Tcl_Event, flags C.int) C.int {
if flags != C.TK_ALL_EVENTS {
return 0
}
if fn, ok := globalAsyncEvent.Load(unsafe.Pointer(ev)); ok {
fn.(func())()
globalAsyncEvent.Delete(unsafe.Pointer(ev))
}
return 1
}
func IsMainThread() bool {
return C.Tcl_GetCurrentThread() == mainLoopThreadId
}
func async_send_event(tid C.Tcl_ThreadId, fn func()) {
ev := C._c_create_async_event()
globalAsyncEvent.Store(unsafe.Pointer(ev), fn)
C._c_send_async_event(tid, ev)
}
func Async(fn func()) {
if fn == nil {
return
}
async_send_event(mainLoopThreadId, fn)
}
func MainLoop(fn func()) {
mainLoopThreadId = C.Tcl_GetCurrentThread()
if fn != nil {
fn()
}
C.Tk_MainLoop()
mainLoopThreadId = nil
}
type Interp struct {
interp *C.Tcl_Interp
supportTk86 bool
}
func NewInterp() (*Interp, error) {
interp := C.Tcl_CreateInterp()
if interp == nil {
return nil, errors.New("Tcl_CreateInterp failed")
}
return &Interp{interp, false}, nil
}
func (p *Interp) SupportTk86() bool {
return p.supportTk86
}
func (p *Interp) InitTcl(tcl_library string) error {
if tcl_library != "" {
p.Eval(fmt.Sprintf("set tcl_library {%s}", tcl_library))
}
if C.Tcl_Init(p.interp) != TCL_OK {
err := errors.New("Tcl_Init failed")
return err
}
return nil
}
func (p *Interp) InitTk(tk_library string) error {
if tk_library != "" {
p.Eval(fmt.Sprintf("set tk_library {%s}", tk_library))
}
if C.Tk_Init(p.interp) != TCL_OK {
err := errors.New("Tk_Init failed")
return err
}
p.supportTk86 = p.TkVersion() >= "8.6"
return nil
}
func (p *Interp) Destroy() error {
if p == nil || p.interp == nil {
return os.ErrInvalid
}
C.Tcl_DeleteInterp(p.interp)
p.interp = nil
return nil
}
func (p *Interp) GetObjResult() *Obj {
return &Obj{C.Tcl_GetObjResult(p.interp), p.interp}
}
func (p *Interp) GetListObjResult() *ListObj {
return &ListObj{C.Tcl_GetObjResult(p.interp), p.interp}
}
func (p *Interp) Eval(script string) error {
cs := C.CString(script)
defer C.free(unsafe.Pointer(cs))
if C.Tcl_EvalEx(p.interp, cs, C.int(len(script)), 0) != TCL_OK {
err := errors.New(p.GetStringResult())
return err
}
return nil
}
func (p *Interp) CreateCommand(name string, fn func([]string) (string, error)) (uintptr, error) {
cs := C.CString(name)
defer C.free(unsafe.Pointer(cs))
id := globalCommandMap.Register(fn)
cmd := C._c_create_obj_command(p.interp, cs, unsafe.Pointer(id))
if cmd == nil {
err := fmt.Errorf("CreateCommand %v failed", name)
return 0, err
}
return id, nil
}
func (p *Interp) InvokeCommand(id uintptr, args []string) (string, error) {
return globalCommandMap.Invoke(id, args)
}
func (p *Interp) CreateAction(name string, fn func([]string)) (uintptr, error) {
cs := C.CString(name)
defer C.free(unsafe.Pointer(cs))
id := globalActionMap.Register(fn)
cmd := C._c_create_action_command(p.interp, cs, unsafe.Pointer(id))
if cmd == nil {
err := fmt.Errorf("CreateAction %v failed", name)
return 0, err
}
return id, nil
}
func (p *Interp) InvokeAction(id uintptr, args []string) error {
return globalActionMap.Invoke(id, args)
}
func (p *Interp) GetVar(name string, global bool) *Obj {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
var flag C.int = C.TCL_LEAVE_ERR_MSG
if global {
flag |= C.TCL_GLOBAL_ONLY
}
obj := C.Tcl_GetVar2Ex(p.interp, cname, nil, flag)
if obj == nil {
return nil
}
return &Obj{obj, p.interp}
}
func (p *Interp) GetList(name string, global bool) *ListObj {
return (*ListObj)(p.GetVar(name, global))
}
func (p *Interp) SetStringList(name string, list []string, global bool) error {
obj := NewListObj(p)
obj.AppendStringList(list)
return p.SetVarObj(name, (*Obj)(obj), global)
}
func (p *Interp) AppendStringListList(name string, list []string, global bool) error {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
var flag C.int = C.TCL_LEAVE_ERR_MSG | C.TCL_APPEND_VALUE | C.TCL_LIST_ELEMENT
if global {
flag |= C.TCL_GLOBAL_ONLY
}
for _, value := range list {
cvalue := C.CString(value)
C.Tcl_SetVar(p.interp, cname, cvalue, flag)
C.free(unsafe.Pointer(cvalue))
}
return nil
}
func (p *Interp) AppendStringList(name string, value string, global bool) error {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
cvalue := C.CString(value)
defer C.free(unsafe.Pointer(cvalue))
var flag C.int = C.TCL_LEAVE_ERR_MSG | C.TCL_APPEND_VALUE | C.TCL_LIST_ELEMENT
if global {
flag |= C.TCL_GLOBAL_ONLY
}
r := C.Tcl_SetVar(p.interp, cname, cvalue, flag)
if r == nil {
return p.GetErrorResult()
}
return nil
}
func (p *Interp) SetVarObj(name string, obj *Obj, global bool) error {
if obj == nil {
return os.ErrInvalid
}
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
var flag C.int = C.TCL_LEAVE_ERR_MSG
if global {
flag |= C.TCL_GLOBAL_ONLY
}
r := C.Tcl_SetVar2Ex(p.interp, cname, nil, obj.obj, flag)
if r == nil {
return p.GetErrorResult()
}
return nil
}
func (p *Interp) SetVarListObj(name string, obj *ListObj, global bool) error {
return p.SetVarObj(name, (*Obj)(obj), global)
}
func (p *Interp) SetStringVar(name string, value string, global bool) error {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
cvalue := C.CString(value)
defer C.free(unsafe.Pointer(cvalue))
var flag C.int = C.TCL_LEAVE_ERR_MSG
if global {
flag |= C.TCL_GLOBAL_ONLY
}
r := C.Tcl_SetVar(p.interp, cname, cvalue, flag)
if r == nil {
return p.GetErrorResult()
}
return nil
}
func (p *Interp) AppendStringVar(name string, value string, global bool) error {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
cvalue := C.CString(value)
defer C.free(unsafe.Pointer(cvalue))
var flag C.int = C.TCL_LEAVE_ERR_MSG | C.TCL_APPEND_VALUE
if global {
flag |= C.TCL_GLOBAL_ONLY
}
r := C.Tcl_SetVar(p.interp, cname, cvalue, flag)
if r == nil {
return p.GetErrorResult()
}
return nil
}
func (p *Interp) UnsetVar(name string, global bool) error {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
var flag C.int = C.TCL_LEAVE_ERR_MSG
if global {
flag |= C.TCL_GLOBAL_ONLY
}
r := C.Tcl_UnsetVar(p.interp, cname, flag)
if r != C.TCL_OK {
return p.GetErrorResult()
}
return nil
}
type Obj struct {
obj *C.Tcl_Obj
interp *C.Tcl_Interp
}
func (o *Obj) ToFloat64() float64 {
var out C.double
status := C.Tcl_GetDoubleFromObj(o.interp, o.obj, &out)
if status == C.TCL_OK {
return float64(out)
}
return 0
}
func (o *Obj) ToInt64() int64 {
var out C.Tcl_WideInt
status := C.Tcl_GetWideIntFromObj(o.interp, o.obj, &out)
if status == TCL_OK {
return int64(out)
}
return 0
}
func (o *Obj) ToInt() int {
return int(o.ToInt64())
}
func (o *Obj) ToUint() uint {
return uint(o.ToInt64())
}
func (o *Obj) ToBool() bool {
var out C.int
status := C.Tcl_GetBooleanFromObj(o.interp, o.obj, &out)
if status == C.TCL_OK {
return out == 1
}
return false
}
func (o *Obj) ToString() string {
var n C.int
out := C.Tcl_GetStringFromObj(o.obj, &n)
return C.GoStringN(out, n)
}
func NewStringObj(value string, p *Interp) *Obj {
cs := C.CString(value)
defer C.free(unsafe.Pointer(cs))
return &Obj{C.Tcl_NewStringObj(cs, C.int(len(value))), p.interp}
}
func NewFloat64Obj(value float64, p *Interp) *Obj {
return &Obj{C.Tcl_NewDoubleObj(C.double(value)), p.interp}
}
func NewInt64Obj(value int64, p *Interp) *Obj {
return &Obj{C.Tcl_NewWideIntObj(C.Tcl_WideInt(value)), p.interp}
}
func NewIntObj(value int, p *Interp) *Obj {
return &Obj{C.Tcl_NewWideIntObj(C.Tcl_WideInt(value)), p.interp}
}
func NewBoolObj(value bool, p *Interp) *Obj {
if value {
return &Obj{C.Tcl_NewBooleanObj(1), p.interp}
} else {
return &Obj{C.Tcl_NewBooleanObj(0), p.interp}
}
}
func objToString(interp *C.Tcl_Interp, obj *C.Tcl_Obj) string {
var n C.int
out := C.Tcl_GetStringFromObj(obj, &n)
return C.GoStringN(out, n)
}
func stringToObj(value string) *C.Tcl_Obj {
cs := C.CString(value)
defer C.free(unsafe.Pointer(cs))
return C.Tcl_NewStringObj(cs, C.int(len(value)))
}
type ListObj Obj
func NewListObj(p *Interp) *ListObj {
o := C.Tcl_NewListObj(0, nil)
return &ListObj{o, p.interp}
}
func (o *ListObj) Length() int {
var length C.int
C.Tcl_ListObjLength(o.interp, o.obj, &length)
return int(length)
}
func (o *ListObj) IndexObj(index int) *Obj {
var obj *C.Tcl_Obj
r := C.Tcl_ListObjIndex(o.interp, o.obj, C.int(index), &obj)
if r != C.TCL_OK || obj == nil {
return nil
}
return &Obj{obj, o.interp}
}
func (o *ListObj) IndexString(index int) string {
var obj *C.Tcl_Obj
r := C.Tcl_ListObjIndex(o.interp, o.obj, C.int(index), &obj)
if r != C.TCL_OK || obj == nil {
return ""
}
return objToString(o.interp, obj)
}
func (o *ListObj) ToObjList() (list []*Obj) {
var objs **C.Tcl_Obj
var objnum C.int
C.Tcl_ListObjGetElements(o.interp, o.obj, &objnum, &objs)
if objnum == 0 {
return
}
lst := (*[1 << 30]*C.Tcl_Obj)(unsafe.Pointer(objs))[:int(objnum):int(objnum)]
for _, v := range lst {
list = append(list, &Obj{v, o.interp})
}
return
}
func (o *ListObj) ToStringList() (list []string) {
var objs **C.Tcl_Obj
var objnum C.int
C.Tcl_ListObjGetElements(o.interp, o.obj, &objnum, &objs)
if objnum == 0 {
return
}
lst := (*[1 << 30]*C.Tcl_Obj)(unsafe.Pointer(objs))[:int(objnum):int(objnum)]
var n C.int
for _, obj := range lst {
out := C.Tcl_GetStringFromObj(obj, &n)
list = append(list, C.GoStringN(out, n))
}
return
}
func (o *ListObj) ToIntList() (list []int) {
var objs **C.Tcl_Obj
var objnum C.int
C.Tcl_ListObjGetElements(o.interp, o.obj, &objnum, &objs)
if objnum == 0 {
return
}
lst := (*[1 << 30]*C.Tcl_Obj)(unsafe.Pointer(objs))[:int(objnum):int(objnum)]
var out C.Tcl_WideInt
for _, obj := range lst {
C.Tcl_GetWideIntFromObj(o.interp, obj, &out)
list = append(list, int(out))
}
return
}
func (o *ListObj) SetStringList(list []string) {
C.Tcl_SetListObj(o.obj, 0, nil)
o.AppendStringList(list)
}
func (o *ListObj) AppendStringList(list []string) {
for _, v := range list {
cs := C.CString(v)
obj := C.Tcl_NewStringObj(cs, C.int(len(v)))
C.Tcl_ListObjAppendElement(o.interp, o.obj, obj)
C.free(unsafe.Pointer(cs))
}
}
func (o *ListObj) AppendObj(obj *Obj) bool {
if obj == nil {
return false
}
C.Tcl_ListObjAppendElement(o.interp, o.obj, obj.obj)
return true
}
func (o *ListObj) AppendString(s string) {
C.Tcl_ListObjAppendElement(o.interp, o.obj, stringToObj(s))
}
func (o *ListObj) InsertObj(index int, obj *Obj) {
C.Tcl_ListObjReplace(o.interp, o.obj, C.int(index), 0, 1, &obj.obj)
}
func (o *ListObj) InsertString(index int, s string) {
obj := stringToObj(s)
C.Tcl_ListObjReplace(o.interp, o.obj, C.int(index), 0, 1, &obj)
}
func (o *ListObj) SetIndexObj(index int, obj *Obj) bool {
if obj == nil {
return false
}
C.Tcl_ListObjReplace(o.interp, o.obj, C.int(index), 1, 1, &obj.obj)
return true
}
func (o *ListObj) SetIndexString(index int, s string) {
obj := stringToObj(s)
C.Tcl_ListObjReplace(o.interp, o.obj, C.int(index), 1, 1, &obj)
}
func (o *ListObj) Remove(first int, count int) {
C.Tcl_ListObjReplace(o.interp, o.obj, C.int(first), C.int(count), 0, nil)
}
type Photo struct {
handle C.Tk_PhotoHandle
interp *Interp
}
func FindPhoto(interp *Interp, imageName string) *Photo {
cs := C.CString(imageName)
defer C.free(unsafe.Pointer(cs))
handle := C.Tk_FindPhoto(interp.interp, cs)
if handle == nil {
return nil
}
return &Photo{handle, interp}
}
func (p *Photo) Blank() {
C.Tk_PhotoBlank(p.handle)
}
func (p *Photo) SetSize(width int, height int) error {
status := C.Tk_PhotoSetSize(p.interp.interp, p.handle, C.int(width), C.int(height))
if status != C.TCL_OK {
return p.interp.GetErrorResult()
}
return nil
}
func (p *Photo) Size() (int, int) {
var width, height C.int
C.Tk_PhotoGetSize(p.handle, &width, &height)
return int(width), int(height)
}
func (p *Photo) Expand(width int, height int) error {
status := C.Tk_PhotoExpand(p.interp.interp, p.handle, C.int(width), C.int(height))
if status != C.TCL_OK {
return p.interp.GetErrorResult()
}
return nil
}
func (p *Photo) ToImage() image.Image {
var block C.Tk_PhotoImageBlock
C.Tk_PhotoGetImage(p.handle, &block)
if block.width == 0 || block.height == 0 {
return nil
}
r := image.Rect(0, 0, int(block.width), int(block.height))
pix := C.GoBytes(unsafe.Pointer(block.pixelPtr), C.int(4*block.width*block.height))
return &image.NRGBA{pix, 4 * int(block.width), r}
}
func (p *Photo) PutImage(img image.Image, tk85alphacolor color.Color) error {
if img == nil || img.Bounds().Empty() {
return os.ErrInvalid
}
var pixelPtr unsafe.Pointer
var stride int
if p.interp.supportTk86 {
dstImage, ok := img.(*image.NRGBA)
if !ok {
dstImage = image.NewNRGBA(img.Bounds())
draw.Draw(dstImage, dstImage.Bounds(), img, img.Bounds().Min, draw.Src)
}
stride = dstImage.Stride
pixelPtr = toCBytes(dstImage.Pix)
} else {
var r, g, b uint8
if tk85alphacolor != nil {
clr := color.RGBAModel.Convert(tk85alphacolor).(color.RGBA)
r, g, b = clr.R, clr.G, clr.B
}
dstImage := image.NewRGBA(img.Bounds())
for i := 0; i < len(dstImage.Pix); i += 4 {
dstImage.Pix[i+0] = r
dstImage.Pix[i+1] = g
dstImage.Pix[i+2] = b
dstImage.Pix[i+3] = 0xff
}
draw.Draw(dstImage, dstImage.Bounds(), img, img.Bounds().Min, draw.Over)
stride = dstImage.Stride
pixelPtr = toCBytes(dstImage.Pix)
}
defer C.free(pixelPtr)
width := img.Bounds().Dx()
height := img.Bounds().Dy()
offset := [4]C.int{0, 1, 2, 3}
block := C.Tk_PhotoImageBlock{
(*C.uchar)(pixelPtr),
C.int(width),
C.int(height),
C.int(stride),
4,
offset,
}
status := C.Tk_PhotoPutBlock(p.interp.interp, p.handle, &block,
0, 0, C.int(width), C.int(height),
C.TK_PHOTO_COMPOSITE_SET)
if status != C.TCL_OK {
return p.interp.GetErrorResult()
}
return nil
}
func (p *Photo) PutZoomedImage(img image.Image, zoomX, zoomY, subsampleX, subsampleY int, tk85alphacolor color.Color) error {
if img == nil || img.Bounds().Empty() {
return os.ErrInvalid
}
var pixelPtr unsafe.Pointer
var stride int
if p.interp.supportTk86 {
dstImage, ok := img.(*image.NRGBA)
if !ok {
dstImage = image.NewNRGBA(img.Bounds())
draw.Draw(dstImage, dstImage.Bounds(), img, img.Bounds().Min, draw.Src)
}
stride = dstImage.Stride
pixelPtr = toCBytes(dstImage.Pix)
} else {
var r, g, b uint8
if tk85alphacolor != nil {
clr := color.RGBAModel.Convert(tk85alphacolor).(color.RGBA)
r, g, b = clr.R, clr.G, clr.B
}
dstImage := image.NewRGBA(img.Bounds())
for i := 0; i < len(dstImage.Pix); i += 4 {
dstImage.Pix[i+0] = r
dstImage.Pix[i+1] = g
dstImage.Pix[i+2] = b
dstImage.Pix[i+3] = 0xff
}
draw.Draw(dstImage, dstImage.Bounds(), img, img.Bounds().Min, draw.Over)
stride = dstImage.Stride
pixelPtr = toCBytes(dstImage.Pix)
}
defer C.free(pixelPtr)
width := img.Bounds().Dx()
height := img.Bounds().Dy()
offset := [4]C.int{0, 1, 2, 3}
block := C.Tk_PhotoImageBlock{
(*C.uchar)(pixelPtr),
C.int(width),
C.int(height),
C.int(stride),
4,
offset,
}
status := C.Tk_PhotoPutZoomedBlock(p.interp.interp, p.handle, &block,
0, 0, C.int(width), C.int(height),
C.int(zoomX), C.int(zoomY), C.int(subsampleX), C.int(subsampleY),
C.TK_PHOTO_COMPOSITE_SET)
if status != C.TCL_OK {
return p.interp.GetErrorResult()
}
return nil
}
Go
1
https://gitee.com/visualfc/atk.git
git@gitee.com:visualfc/atk.git
visualfc
atk
atk
572ab07f9a00

搜索帮助