summaryrefslogtreecommitdiff
path: root/redo
diff options
context:
space:
mode:
Diffstat (limited to 'redo')
-rw-r--r--redo/area.go17
-rw-r--r--redo/area_unix.go2
-rw-r--r--redo/area_windows.c2
-rw-r--r--redo/area_windows.go5
-rw-r--r--redo/imagelist_unix.go2
-rw-r--r--redo/imagelist_windows.c4
6 files changed, 21 insertions, 11 deletions
diff --git a/redo/area.go b/redo/area.go
index 9849ef5..3719b30 100644
--- a/redo/area.go
+++ b/redo/area.go
@@ -5,6 +5,7 @@ package ui
import (
"fmt"
"image"
+ "image/draw"
"reflect"
"unsafe"
)
@@ -331,7 +332,7 @@ func pixelData(img *image.RGBA) *uint8 {
// some platforms require pixels in ARGB order in their native endianness (because they treat the pixel array as an array of uint32s)
// this does the conversion
// you need to convert somewhere (Windows and cairo give us memory to use; Windows has stride==width but cairo might not)
-func toARGB(i *image.RGBA, memory uintptr, memstride int) {
+func toARGB(i *image.RGBA, memory uintptr, memstride int, toNRGBA bool) {
var realbits []byte
rbs := (*reflect.SliceHeader)(unsafe.Pointer(&realbits))
@@ -340,14 +341,20 @@ func toARGB(i *image.RGBA, memory uintptr, memstride int) {
rbs.Cap = rbs.Len
p := pixelDataPos(i)
q := 0
+ iPix := i.Pix
+ if toNRGBA { // for Windows image lists
+ j := image.NewNRGBA(i.Rect)
+ draw.Draw(j, j.Rect, i, i.Rect.Min, draw.Src)
+ iPix = j.Pix
+ }
for y := i.Rect.Min.Y; y < i.Rect.Max.Y; y++ {
nextp := p + i.Stride
nextq := q + memstride
for x := i.Rect.Min.X; x < i.Rect.Max.X; x++ {
- argb := uint32(i.Pix[p+3]) << 24 // A
- argb |= uint32(i.Pix[p+0]) << 16 // R
- argb |= uint32(i.Pix[p+1]) << 8 // G
- argb |= uint32(i.Pix[p+2]) // B
+ argb := uint32(iPix[p+3]) << 24 // A
+ argb |= uint32(iPix[p+0]) << 16 // R
+ argb |= uint32(iPix[p+1]) << 8 // G
+ argb |= uint32(iPix[p+2]) // B
// the magic of conversion
native := (*[4]byte)(unsafe.Pointer(&argb))
realbits[q+0] = native[0]
diff --git a/redo/area_unix.go b/redo/area_unix.go
index 1cbc4e9..3c88f52 100644
--- a/redo/area_unix.go
+++ b/redo/area_unix.go
@@ -223,7 +223,7 @@ func our_area_draw_callback(widget *C.GtkWidget, cr *C.cairo_t, data C.gpointer)
// the flush and mark_dirty calls are required; see the cairo docs and https://git.gnome.org/browse/gtk+/tree/gdk/gdkcairo.c#n232 (thanks desrt in irc.gimp.net/#gtk+)
C.cairo_surface_flush(surface)
toARGB(i, uintptr(unsafe.Pointer(C.cairo_image_surface_get_data(surface))),
- int(C.cairo_image_surface_get_stride(surface)))
+ int(C.cairo_image_surface_get_stride(surface)), false) // not NRGBA
C.cairo_surface_mark_dirty(surface)
C.cairo_set_source_surface(cr,
surface,
diff --git a/redo/area_windows.c b/redo/area_windows.c
index e37538b..b8f1235 100644
--- a/redo/area_windows.c
+++ b/redo/area_windows.c
@@ -101,7 +101,7 @@ static void paintArea(HWND hwnd, void *data)
// first, we need to load the bitmap memory, because Windows makes it for us
// the pixels are arranged in RGBA order, but GDI requires BGRA
// this turns out to be just ARGB in little endian; let's convert into this memory
- dotoARGB(i, (void *) ppvBits);
+ dotoARGB(i, (void *) ppvBits, FALSE); // FALSE = not NRGBA
// the second thing is... make a device context for the bitmap :|
// Ninjifox just makes another compatible DC; we'll do the same
diff --git a/redo/area_windows.go b/redo/area_windows.go
index d2e13e4..e5e8ac0 100644
--- a/redo/area_windows.go
+++ b/redo/area_windows.go
@@ -118,10 +118,11 @@ func doPaint(xrect *C.RECT, hscroll C.int, vscroll C.int, data unsafe.Pointer, d
}
//export dotoARGB
-func dotoARGB(img unsafe.Pointer, ppvBits unsafe.Pointer) {
+func dotoARGB(img unsafe.Pointer, ppvBits unsafe.Pointer, toNRGBA C.BOOL) {
i := (*image.RGBA)(unsafe.Pointer(img))
+ t := toNRGBA != C.FALSE
// the bitmap Windows gives us has a stride == width
- toARGB(i, uintptr(ppvBits), i.Rect.Dx() * 4)
+ toARGB(i, uintptr(ppvBits), i.Rect.Dx() * 4, t)
}
//export areaWidthLONG
diff --git a/redo/imagelist_unix.go b/redo/imagelist_unix.go
index aeb7a13..246f281 100644
--- a/redo/imagelist_unix.go
+++ b/redo/imagelist_unix.go
@@ -37,7 +37,7 @@ func (i *imagelist) Append(img *image.RGBA) {
}
C.cairo_surface_flush(surface)
toARGB(img, uintptr(unsafe.Pointer(C.cairo_image_surface_get_data(surface))),
- int(C.cairo_image_surface_get_stride(surface)))
+ int(C.cairo_image_surface_get_stride(surface)), false) // not NRGBA
C.cairo_surface_mark_dirty(surface)
basepixbuf := C.gdk_pixbuf_get_from_surface(surface, 0, 0, C.gint(img.Rect.Dx()), C.gint(img.Rect.Dy()))
if basepixbuf == nil {
diff --git a/redo/imagelist_windows.c b/redo/imagelist_windows.c
index 4402268..f7bddb4 100644
--- a/redo/imagelist_windows.c
+++ b/redo/imagelist_windows.c
@@ -22,7 +22,9 @@ HBITMAP unscaledBitmap(void *i, intptr_t dx, intptr_t dy)
bitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &ppvBits, 0, 0);
if (bitmap == NULL)
xpanic("error creating HBITMAP for unscaled ImageList image copy", GetLastError());
- dotoARGB(i, (void *) ppvBits);
+ // image lists use non-premultiplied RGBA - see http://stackoverflow.com/a/25578789/3408572
+ // the TRUE here does the conversion
+ dotoARGB(i, (void *) ppvBits, TRUE);
return bitmap;
}