Switched to ARGB drawing in Areas on GTK+.
This commit is contained in:
parent
e3fdc76c5b
commit
ae4950bbd8
6
area.go
6
area.go
|
@ -340,8 +340,8 @@ 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)
|
// 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
|
// this does the conversion
|
||||||
// you need to convert somewhere; this memory is assumed to have a stride equal to the pixels per scanline (Windows gives us memory to use; other platforms we'll see)
|
// 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) {
|
func toARGB(i *image.RGBA, memory uintptr, memstride int) {
|
||||||
var realbits []byte
|
var realbits []byte
|
||||||
|
|
||||||
rbs := (*reflect.SliceHeader)(unsafe.Pointer(&realbits))
|
rbs := (*reflect.SliceHeader)(unsafe.Pointer(&realbits))
|
||||||
|
@ -352,6 +352,7 @@ func toARGB(i *image.RGBA, memory uintptr) {
|
||||||
q := 0
|
q := 0
|
||||||
for y := i.Rect.Min.Y; y < i.Rect.Max.Y; y++ {
|
for y := i.Rect.Min.Y; y < i.Rect.Max.Y; y++ {
|
||||||
nextp := p + i.Stride
|
nextp := p + i.Stride
|
||||||
|
nextq := q + memstride
|
||||||
for x := i.Rect.Min.X; x < i.Rect.Max.X; x++ {
|
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 + 3]) << 24 // A
|
||||||
argb |= uint32(i.Pix[p + 0]) << 16 // R
|
argb |= uint32(i.Pix[p + 0]) << 16 // R
|
||||||
|
@ -367,5 +368,6 @@ func toARGB(i *image.RGBA, memory uintptr) {
|
||||||
q += 4
|
q += 4
|
||||||
}
|
}
|
||||||
p = nextp
|
p = nextp
|
||||||
|
q = nextq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
31
area_unix.go
31
area_unix.go
|
@ -57,26 +57,27 @@ func our_area_draw_callback(widget *C.GtkWidget, cr *C.cairo_t, data C.gpointer)
|
||||||
return C.FALSE // signals handled without stopping the event chain (thanks to desrt again)
|
return C.FALSE // signals handled without stopping the event chain (thanks to desrt again)
|
||||||
}
|
}
|
||||||
i := s.handler.Paint(cliprect)
|
i := s.handler.Paint(cliprect)
|
||||||
// pixel order is [R G B A] (see Example 1 on https://developer.gnome.org/gdk-pixbuf/2.26/gdk-pixbuf-The-GdkPixbuf-Structure.html) so we don't have to convert anything
|
surface := C.cairo_image_surface_create(
|
||||||
// gdk-pixbuf is not alpha-premultiplied (thanks to desrt in irc.gimp.net/#gtk+)
|
C.CAIRO_FORMAT_ARGB32, // alpha-premultiplied; native byte order
|
||||||
pixbuf := C.gdk_pixbuf_new_from_data(
|
|
||||||
(*C.guchar)(unsafe.Pointer(pixelData(i))),
|
|
||||||
C.GDK_COLORSPACE_RGB,
|
|
||||||
C.TRUE, // has alpha channel
|
|
||||||
8, // bits per sample
|
|
||||||
C.int(i.Rect.Dx()),
|
C.int(i.Rect.Dx()),
|
||||||
C.int(i.Rect.Dy()),
|
C.int(i.Rect.Dy()))
|
||||||
C.int(i.Stride),
|
if status := C.cairo_surface_status(surface); status != C.CAIRO_STATUS_SUCCESS {
|
||||||
nil, nil) // do not free data
|
panic(fmt.Errorf("cairo_create_image_surface() failed: %s\n",
|
||||||
C.gdk_cairo_set_source_pixbuf(cr,
|
C.GoString(C.cairo_status_to_string(status))))
|
||||||
pixbuf,
|
}
|
||||||
C.gdouble(cliprect.Min.X),
|
// 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.gdouble(cliprect.Min.Y))
|
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)))
|
||||||
|
C.cairo_surface_mark_dirty(surface)
|
||||||
|
C.cairo_set_source_surface(cr,
|
||||||
|
surface,
|
||||||
|
0, 0) // origin of the surface
|
||||||
// that just set the brush that cairo uses: we have to actually draw now
|
// that just set the brush that cairo uses: we have to actually draw now
|
||||||
// (via https://developer.gnome.org/gtkmm-tutorial/stable/sec-draw-images.html.en)
|
// (via https://developer.gnome.org/gtkmm-tutorial/stable/sec-draw-images.html.en)
|
||||||
C.cairo_rectangle(cr, x, y, w, h) // breaking the nrom here since we have the double data already
|
C.cairo_rectangle(cr, x, y, w, h) // breaking the nrom here since we have the double data already
|
||||||
C.cairo_fill(cr)
|
C.cairo_fill(cr)
|
||||||
C.g_object_unref((C.gpointer)(unsafe.Pointer(pixbuf))) // free pixbuf
|
C.cairo_surface_destroy(surface) // free surface
|
||||||
return C.FALSE // signals handled without stopping the event chain (thanks to desrt again)
|
return C.FALSE // signals handled without stopping the event chain (thanks to desrt again)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue