func cNewImageSurface(s *C.cairo_surface_t) (Surface, error) { format := Format(C.cairo_image_surface_get_format(s)) width := int(C.cairo_image_surface_get_width(s)) height := int(C.cairo_image_surface_get_height(s)) stride := int(C.cairo_image_surface_get_stride(s)) return newImg(s, format, width, height, stride) }
// pdf, ps, and svg surfaces use the current surface (page) func (g *Graphic) Image() (image.Image, error) { var surface *C.cairo_surface_t switch g.format { case "eps", "pdf", "ps", "svg": // map vector surfaces to an image surface surface = C.cairo_surface_map_to_image(g.surface, nil) defer C.cairo_surface_unmap_image(g.surface, surface) status := C.cairo_surface_status(surface) err := statusToError(status) if err != nil { return nil, err } case "png", "jpeg": // no conversion needed surface = g.surface } width := int(C.cairo_image_surface_get_width(surface)) height := int(C.cairo_image_surface_get_height(surface)) stride := int(C.cairo_image_surface_get_stride(surface)) format := C.cairo_image_surface_get_format(surface) dataPtr := C.cairo_image_surface_get_data(surface) data := C.GoBytes(unsafe.Pointer(dataPtr), C.int(stride*height)) var img image.Image switch format { case C.CAIRO_FORMAT_ARGB32: img = &extimage.ARGB{ Pix: data, Stride: stride, Rect: image.Rect(0, 0, width, height), } case C.CAIRO_FORMAT_RGB24: img = &extimage.RGB{ Pix: data, Stride: stride, Rect: image.Rect(0, 0, width, height), } case C.CAIRO_FORMAT_A8: img = &image.Alpha{ Pix: data, Stride: stride, Rect: image.Rect(0, 0, width, height), } default: // known unsupported formats: // CAIRO_FORMAT_INVALID = -1, // CAIRO_FORMAT_A1 = 3, // CAIRO_FORMAT_RGB16_565 = 4, // CAIRO_FORMAT_RGB30 = 5 panic(fmt.Sprintf("unsupported cairo image surface format: %d", int(format))) } return img, nil }
// GetSnapshotCustom runs asynchronously, taking a snapshot of the WebView. // Upon completion, resultCallback will be called with a copy of the underlying // bitmap backing store for the frame, or with an error encountered during // execution. // // See also: webkit_web_view_get_snapshot at // http://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebView.html#webkit-web-view-get-snapshot func (v *WebView) GetSnapshotCustom(region SnapshotRegion, options SnapshotOptions, resultCallback func(result *image.RGBA, err error)) { var cCallback C.GAsyncReadyCallback var userData C.gpointer var err error if resultCallback != nil { callback := func(result *C.GAsyncResult) { var snapErr *C.GError snapResult := C.webkit_web_view_get_snapshot_finish(v.webView, result, &snapErr) if snapResult == nil { defer C.g_error_free(snapErr) msg := C.GoString((*C.char)(snapErr.message)) resultCallback(nil, errors.New(msg)) return } defer C.cairo_surface_destroy(snapResult) if C.cairo_surface_get_type(snapResult) != cairoSurfaceTypeImage || C.cairo_image_surface_get_format(snapResult) != cairoImageSurfaceFormatARGB32 { panic("Snapshot in unexpected format") } w := int(C.cairo_image_surface_get_width(snapResult)) h := int(C.cairo_image_surface_get_height(snapResult)) stride := int(C.cairo_image_surface_get_stride(snapResult)) C.cairo_surface_flush(snapResult) data := unsafe.Pointer(C.cairo_image_surface_get_data(snapResult)) //(miha) fix endianes depended byte order, and copy to go slice at the same time. data_fixed := make([]byte, stride*h) C.gowk2_cairo_endian_depended_ARGB32_to_RGBA((*C.uchar)(data), (*C.uchar)(&data_fixed[0]), C.uint(stride*h)) rgba := &image.RGBA{data_fixed, stride, image.Rect(0, 0, w, h)} // slower but doesn't use Go pointers inside C. See https://github.com/golang/go/issues/8310 !!!!!!! //C.gowk2_cairo_endian_depended_ARGB32_to_RGBA((*C.uchar)(data), C.uint(stride*h)) //rgba := &image.RGBA{C.GoBytes(data, C.int(stride*h)), stride, image.Rect(0, 0, w, h)} resultCallback(rgba, nil) } cCallback, userData, err = newGAsyncReadyCallback(callback) if err != nil { panic(err) } } C.webkit_web_view_get_snapshot(v.webView, (C.WebKitSnapshotRegion)(region), (C.WebKitSnapshotOptions)(options), nil, cCallback, userData) }
// Load an image from a PNG file func Load(path string) (*Image, error) { var img Image img.Surf = C.cairo_image_surface_create_from_png(C.CString(path)) switch C.cairo_image_surface_get_format(img.Surf) { case C.CAIRO_FORMAT_A8: img.ColorSpace = MODE_A8 case C.CAIRO_FORMAT_RGB24: img.ColorSpace = MODE_RGB case C.CAIRO_FORMAT_ARGB32: img.ColorSpace = MODE_RGBA default: fmt.Println("ERROR: Format not supported") return nil, error("Format not supported") } img.W = int(C.cairo_image_surface_get_width(img.Surf)) img.H = int(C.cairo_image_surface_get_height(img.Surf)) img.Ctx = C.cairo_create(img.Surf) return &img, nil }
// GetSnapshot runs asynchronously, taking a snapshot of the WebView. // Upon completion, resultCallback will be called with a copy of the underlying // bitmap backing store for the frame, or with an error encountered during // execution. // // See also: webkit_web_view_get_snapshot at // http://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebView.html#webkit-web-view-get-snapshot func (v *WebView) GetSnapshot(resultCallback func(result *image.RGBA, err error)) { var cCallback C.GAsyncReadyCallback var userData C.gpointer var err error if resultCallback != nil { callback := func(result *C.GAsyncResult) { var snapErr *C.GError snapResult := C.webkit_web_view_get_snapshot_finish(v.webView, result, &snapErr) if snapResult == nil { defer C.g_error_free(snapErr) msg := C.GoString((*C.char)(snapErr.message)) resultCallback(nil, errors.New(msg)) return } defer C.cairo_surface_destroy(snapResult) if C.cairo_surface_get_type(snapResult) != cairoSurfaceTypeImage || C.cairo_image_surface_get_format(snapResult) != cairoImageSurfaceFormatARB32 { panic("Snapshot in unexpected format") } w := int(C.cairo_image_surface_get_width(snapResult)) h := int(C.cairo_image_surface_get_height(snapResult)) stride := int(C.cairo_image_surface_get_stride(snapResult)) data := unsafe.Pointer(C.cairo_image_surface_get_data(snapResult)) rgba := &image.RGBA{C.GoBytes(data, C.int(stride*h)), stride, image.Rect(0, 0, w, h)} resultCallback(rgba, nil) } cCallback, userData, err = newGAsyncReadyCallback(callback) if err != nil { panic(err) } } C.webkit_web_view_get_snapshot(v.webView, (C.WebKitSnapshotRegion)(1), // FullDocument is the only working region at this point (C.WebKitSnapshotOptions)(0), nil, cCallback, userData) }
func (self *Surface) GetWidth() int { return int(C.cairo_image_surface_get_width(self.surface)) }
// GetSnapshot runs asynchronously, taking a snapshot of the WebView. // Upon completion, resultCallback will be called with a copy of the underlying // bitmap backing store for the frame, or with an error encountered during // execution. // // See also: webkit_web_view_get_snapshot at // http://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebView.html#webkit-web-view-get-snapshot func (v *WebView) GetSnapshot(resultCallback func(result *image.RGBA, err error)) { var cCallback C.GAsyncReadyCallback var userData C.gpointer var err error if resultCallback != nil { callback := func(result *C.GAsyncResult) { var snapErr *C.GError snapResult := C.webkit_web_view_get_snapshot_finish(v.webView, result, &snapErr) if snapResult == nil { defer C.g_error_free(snapErr) msg := C.GoString((*C.char)(snapErr.message)) resultCallback(nil, errors.New(msg)) return } defer C.cairo_surface_destroy(snapResult) if C.cairo_surface_get_type(snapResult) != cairoSurfaceTypeImage || C.cairo_image_surface_get_format(snapResult) != cairoImageSurfaceFormatARGB32 { panic("Snapshot in unexpected format") } w := int(C.cairo_image_surface_get_width(snapResult)) h := int(C.cairo_image_surface_get_height(snapResult)) stride := int(C.cairo_image_surface_get_stride(snapResult)) data := unsafe.Pointer(C.cairo_image_surface_get_data(snapResult)) surfaceBytes := C.GoBytes(data, C.int(stride*h)) // convert from b,g,r,a or a,r,g,b(local endianness) to r,g,b,a testint, _ := binary.ReadUvarint(bytes.NewBuffer([]byte{0x1, 0})) if testint == 0x1 { // Little: b,g,r,a -> r,g,b,a for i := 0; i < w*h; i++ { b := surfaceBytes[4*i+0] r := surfaceBytes[4*i+2] surfaceBytes[4*i+0] = r surfaceBytes[4*i+2] = b } } else { // Big: a,r,g,b -> r,g,b,a for i := 0; i < w*h; i++ { a := surfaceBytes[4*i+0] r := surfaceBytes[4*i+1] g := surfaceBytes[4*i+2] b := surfaceBytes[4*i+3] surfaceBytes[4*i+0] = r surfaceBytes[4*i+1] = g surfaceBytes[4*i+2] = b surfaceBytes[4*i+3] = a } } rgba := &image.RGBA{surfaceBytes, stride, image.Rect(0, 0, w, h)} resultCallback(rgba, nil) } cCallback, userData, err = newGAsyncReadyCallback(callback) if err != nil { panic(err) } } C.webkit_web_view_get_snapshot(v.webView, (C.WebKitSnapshotRegion)(1), // FullDocument is the only working region at this point (C.WebKitSnapshotOptions)(0), nil, cCallback, userData) }
//export go_genericGAsyncCallback func go_genericGAsyncCallback(source *C.GObject, result *C.GAsyncResult, callbackId *C.char) { key := C.GoString(callbackId) if obj, ok := cgoget(key); ok { switch obj.(type) { case *RunJavaScriptResponse: var jserr *C.GError response := obj.(*RunJavaScriptResponse) if response.Autoremove { defer cgounregister(key) } if jsResult := C.webkit_web_view_run_javascript_finish(response.CWebView, result, &jserr); jsResult == nil { defer C.g_error_free(jserr) msg := C.GoString((*C.char)(jserr.message)) response.Reply(nil, errors.New(msg)) } else { ctxRaw := gojs.RawGlobalContext(unsafe.Pointer(C.webkit_javascript_result_get_global_context(jsResult))) jsValRaw := gojs.RawValue(unsafe.Pointer(C.webkit_javascript_result_get_value(jsResult))) ctx := (*gojs.Context)(gojs.NewGlobalContextFrom(ctxRaw)) jsVal := ctx.NewValueFrom(jsValRaw) response.Reply(jsVal, nil) } case *GetSnapshotAsImageResponse: var snapErr *C.GError response := obj.(*GetSnapshotAsImageResponse) if response.Autoremove { defer cgounregister(key) } if snapResult := C.webkit_web_view_get_snapshot_finish(response.CWebView, result, &snapErr); snapResult == nil { defer C.g_error_free(snapErr) msg := C.GoString((*C.char)(snapErr.message)) response.Reply(nil, errors.New(msg)) } else { defer C.cairo_surface_destroy(snapResult) if C.cairo_surface_get_type(snapResult) != cairoSurfaceTypeImage || C.cairo_image_surface_get_format(snapResult) != cairoImageSurfaceFormatARGB32 { response.Reply(nil, errors.New("Snapshot in unexpected format")) return } w := int(C.cairo_image_surface_get_width(snapResult)) h := int(C.cairo_image_surface_get_height(snapResult)) stride := int(C.cairo_image_surface_get_stride(snapResult)) data := unsafe.Pointer(C.cairo_image_surface_get_data(snapResult)) surfaceBytes := C.GoBytes(data, C.int(stride*h)) // convert from b,g,r,a or a,r,g,b(local endianness) to r,g,b,a testint, _ := binary.ReadUvarint(bytes.NewBuffer([]byte{0x1, 0})) if testint == 0x1 { // Little: b,g,r,a -> r,g,b,a for i := 0; i < w*h; i++ { b := surfaceBytes[4*i+0] r := surfaceBytes[4*i+2] surfaceBytes[4*i+0] = r surfaceBytes[4*i+2] = b } } else { // Big: a,r,g,b -> r,g,b,a for i := 0; i < w*h; i++ { a := surfaceBytes[4*i+0] r := surfaceBytes[4*i+1] g := surfaceBytes[4*i+2] b := surfaceBytes[4*i+3] surfaceBytes[4*i+0] = r surfaceBytes[4*i+1] = g surfaceBytes[4*i+2] = b surfaceBytes[4*i+3] = a } } rgba := &image.RGBA{ Pix: surfaceBytes, Stride: stride, Rect: image.Rect(0, 0, w, h), } response.Reply(rgba, nil) } case *GetSnapshotAsCairoSurfaceResponse: var snapErr *C.GError response := obj.(*GetSnapshotAsCairoSurfaceResponse) snapResult := C.webkit_web_view_get_snapshot_finish(response.CWebView, result, &snapErr) if snapResult == nil { defer C.g_error_free(snapErr) msg := C.GoString((*C.char)(snapErr.message)) response.Reply(nil, errors.New(msg)) } else { surface := cairo.NewSurface(uintptr(unsafe.Pointer(snapResult)), false) if status := surface.Status(); status == cairo.STATUS_SUCCESS { response.Reply(surface, nil) } else { response.Reply(nil, fmt.Errorf("Cairo surface error %d", status)) } } } } }