Implement Mac OS X AreaHandler.Paint().
This commit is contained in:
parent
a1830c8883
commit
6a40011f85
|
@ -5,6 +5,7 @@ package ui
|
|||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
"image"
|
||||
)
|
||||
|
||||
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
|
||||
|
@ -12,6 +13,7 @@ import (
|
|||
//// #include <HIToolbox/Events.h>
|
||||
// #include "objc_darwin.h"
|
||||
// extern void areaView_drawRect(id, struct xrect);
|
||||
// extern BOOL areaView_isFlipped(id, SEL);
|
||||
import "C"
|
||||
|
||||
const (
|
||||
|
@ -22,6 +24,7 @@ var (
|
|||
_goArea C.id
|
||||
|
||||
_drawRect = sel_getUid("drawRect:")
|
||||
_isFlipped = sel_getUid("isFlipped")
|
||||
)
|
||||
|
||||
func mkAreaClass() error {
|
||||
|
@ -29,20 +32,44 @@ func mkAreaClass() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("error creating Area backend class: %v", err)
|
||||
}
|
||||
// // TODO rename this function (it overrides anyway)
|
||||
// addAreaViewDrawMethod() is in bleh_darwin.m
|
||||
ok := C.addAreaViewDrawMethod(areaclass)
|
||||
if ok != C.BOOL(C.YES) {
|
||||
return fmt.Errorf("error overriding Area drawRect: method; reason unknown")
|
||||
}
|
||||
// TODO rename this function (it overrides anyway)
|
||||
err = addDelegateMethod(areaclass, _isFlipped,
|
||||
C.areaView_isFlipped, area_boolret)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error overriding Area isFlipped method: %v", err)
|
||||
}
|
||||
_goArea = objc_getClass(__goArea)
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
_drawAtPoint = sel_getUid("drawAtPoint:")
|
||||
)
|
||||
|
||||
//export areaView_drawRect
|
||||
func areaView_drawRect(self C.id, rect C.struct_xrect) {
|
||||
// TODO
|
||||
fmt.Println(rect)
|
||||
s := getSysData(self)
|
||||
// TODO clear clip rect
|
||||
cliprect := image.Rect(int(rect.x), int(rect.y), int(rect.width), int(rect.height))
|
||||
max := C.objc_msgSend_stret_rect_noargs(self, _frame)
|
||||
cliprect = image.Rect(0, 0, int(max.width), int(max.height)).Intersect(cliprect)
|
||||
if cliprect.Empty() { // no intersection; nothing to paint
|
||||
return
|
||||
}
|
||||
i := s.handler.Paint(cliprect)
|
||||
C.drawImage(
|
||||
unsafe.Pointer(&i.Pix[0]), C.int64_t(i.Rect.Dx()), C.int64_t(i.Rect.Dy()), C.int64_t(i.Stride),
|
||||
C.int64_t(cliprect.Min.X), C.int64_t(cliprect.Min.Y))
|
||||
}
|
||||
|
||||
//export areaView_isFlipped
|
||||
func areaView_isFlipped(self C.id, sel C.SEL) C.BOOL {
|
||||
return C.BOOL(C.YES)
|
||||
}
|
||||
|
||||
// TODO combine these with the listbox functions?
|
||||
|
@ -92,5 +119,5 @@ func makeAreaClass(name string) (C.Class, error) {
|
|||
}
|
||||
|
||||
var (
|
||||
// delegate_rect in bleh_darwin.m
|
||||
area_boolret = []C.char{'c', '@', ':', 0} // BOOL (*)(id, SEL)
|
||||
)
|
||||
|
|
|
@ -19,6 +19,8 @@ Go wrapper functions (bleh_darwin.go) call these directly and take care of stdin
|
|||
#include <Foundation/NSGeometry.h>
|
||||
#include <AppKit/NSKeyValueBinding.h>
|
||||
#include <AppKit/NSEvent.h>
|
||||
#include <AppKit/NSGraphics.h>
|
||||
#include <AppKit/NSBitmapImageRep.h>
|
||||
|
||||
/* exception to the above: cgo doesn't like Nil and delegate_darwin.go has //export so I can't have this there */
|
||||
Class NilClass = Nil;
|
||||
|
@ -127,6 +129,15 @@ struct xsize objc_msgSend_stret_size_noargs(id obj, SEL sel)
|
|||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
and again for NSPoint
|
||||
*/
|
||||
|
||||
id objc_msgSend_point(id obj, SEL sel, int64_t x, int64_t y)
|
||||
{
|
||||
return objc_msgSend(obj, sel, NSMakePoint((CGFloat) x, (CGFloat) y));
|
||||
}
|
||||
|
||||
/*
|
||||
This is a doozy: it deals with a NSUInteger array needed for this one selector, and converts them all into a uintptr_t array so we can use it from Go. The two arrays are created at runtime with malloc(); only the NSUInteger one is freed here, while Go frees the returned one. It's not optimal.
|
||||
*/
|
||||
|
@ -217,3 +228,53 @@ BOOL addAreaViewDrawMethod(Class what)
|
|||
}
|
||||
return class_addMethod(what, drawRect, (IMP) _areaView_drawRect, avdrType);
|
||||
}
|
||||
|
||||
/*
|
||||
the NSBitmapImageRep constructor is complex; put it here
|
||||
the only way to draw a NSBitmapImageRep in a flipped NSView is to use the most complex drawing method; put it here too
|
||||
*/
|
||||
|
||||
static id c_NSBitmapImageRep;
|
||||
static SEL s_alloc;
|
||||
static SEL s_initWithBitmapDataPlanes;
|
||||
static SEL s_drawInRect;
|
||||
static SEL s_release;
|
||||
static BOOL drawImage_init = NO;
|
||||
|
||||
id drawImage(void *pixels, int64_t width, int64_t height, int64_t stride, int64_t xdest, int64_t ydest)
|
||||
{
|
||||
unsigned char *planes[1]; /* NSBitmapImageRep wants an array of planes; we have one plane */
|
||||
id bitmap;
|
||||
|
||||
if (drawImage_init == NO) {
|
||||
c_NSBitmapImageRep = objc_getClass("NSBitmapImageRep");
|
||||
s_alloc = sel_getUid("alloc");
|
||||
s_initWithBitmapDataPlanes = sel_getUid("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:");
|
||||
s_drawInRect = sel_getUid("drawInRect:fromRect:operation:fraction:respectFlipped:hints:");
|
||||
s_release = sel_getUid("release");
|
||||
drawImage_init = YES;
|
||||
}
|
||||
bitmap = objc_msgSend(c_NSBitmapImageRep, s_alloc);
|
||||
planes[0] = (unsigned char *) pixels;
|
||||
bitmap = objc_msgSend(bitmap, s_initWithBitmapDataPlanes,
|
||||
planes, /* initWithBitmapDataPlanes: */
|
||||
(NSInteger) width, /* pixelsWide: */
|
||||
(NSInteger) height, /* pixelsHigh: */
|
||||
(NSInteger) 8, /* bitsPerSample: */
|
||||
(NSInteger) 4, /* samplesPerPixel: */
|
||||
(BOOL) YES, /* hasAlpha: */
|
||||
(BOOL) NO, /* isPlanar: */
|
||||
NSCalibratedRGBColorSpace, /* colorSpaceName: | TODO NSDeviceRGBColorSpace? */
|
||||
(NSBitmapFormat) NSAlphaNonpremultipliedBitmapFormat, /* bitmapFormat: | this is where the flag for placing alpha first would go if alpha came first; the default is alpha last, which is how we're doing things (otherwise the docs say "Color planes are arranged in the standard order—for example, red before green before blue for RGB color.") */
|
||||
(NSInteger) stride, /* bytesPerRow: */
|
||||
(NSInteger) 32); /* bitsPerPixel: */
|
||||
objc_msgSend(bitmap, s_drawInRect,
|
||||
NSMakeRect((CGFloat) xdest, (CGFloat) ydest,
|
||||
(CGFloat) width, (CGFloat) height), /* drawInRect: */
|
||||
NSZeroRect, /* fromRect: | draw whole image */
|
||||
(NSCompositingOperation) NSCompositeSourceOver, /* op: */
|
||||
(CGFloat) 1.0, /* fraction: */
|
||||
(BOOL) YES, /* respectFlipped: */
|
||||
nil); /* hints: */
|
||||
objc_msgSend(bitmap, s_release);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ extern id _objc_msgSend_rect_bool(id obj, SEL sel, int64_t x, int64_t y, int64_t
|
|||
extern id objc_msgSend_id_int(id obj, SEL sel, id a, intptr_t b);
|
||||
extern id objc_msgSend_id_uint(id obj, SEL sel, id a, uintptr_t b);
|
||||
m2(id_bool, id, BOOL)
|
||||
extern id objc_msgSend_point(id obj, SEL sel, int64_t x, int64_t y);
|
||||
|
||||
m3(id_id_id, id, id, id)
|
||||
m3(sel_id_bool, SEL, id, BOOL)
|
||||
|
@ -106,5 +107,6 @@ extern id makeDummyEvent();
|
|||
|
||||
/* for area_darwin.go */
|
||||
extern BOOL addAreaViewDrawMethod(Class);
|
||||
extern id drawImage(void *, int64_t, int64_t, int64_t, int64_t, int64_t);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue