Example #1
0
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)
}
Example #2
0
// 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
}
Example #3
0
// GetData returns a copy of the surfaces raw pixel data.
// This method also calls Flush.
func (self *Surface) GetData() []byte {
	self.Flush()
	dataPtr := C.cairo_image_surface_get_data(self.surface)
	if dataPtr == nil {
		panic("cairo.Surface.GetData(): can't access surface pixel data")
	}
	stride := C.cairo_image_surface_get_stride(self.surface)
	height := C.cairo_image_surface_get_height(self.surface)
	return C.GoBytes(unsafe.Pointer(dataPtr), stride*height)
}
Example #4
0
func (v *Surface) GetData() []byte {
	c_data := C.cairo_image_surface_get_data(v.native())
	c_data_len := int(C.cairo_image_surface_get_stride(v.native()) *
		C.cairo_image_surface_get_height(v.native()))
	hdr := reflect.SliceHeader{
		Data: uintptr(unsafe.Pointer(c_data)),
		Len:  c_data_len,
		Cap:  c_data_len,
	}
	goSlice := *(*[]byte)(unsafe.Pointer(&hdr))
	return goSlice
}
Example #5
0
// 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)
}
Example #6
0
// SetData sets the surfaces raw pixel data.
// This method also calls Flush and MarkDirty.
func (self *Surface) SetData(data []byte) {
	self.Flush()
	dataPtr := unsafe.Pointer(C.cairo_image_surface_get_data(self.surface))
	if dataPtr == nil {
		panic("cairo.Surface.SetData(): can't access surface pixel data")
	}
	stride := C.cairo_image_surface_get_stride(self.surface)
	height := C.cairo_image_surface_get_height(self.surface)
	if len(data) != int(stride*height) {
		panic("cairo.Surface.SetData(): invalid data size")
	}
	C.memcpy(dataPtr, unsafe.Pointer(&data[0]), C.size_t(stride*height))
	self.MarkDirty()
}
Example #7
0
// 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
}
Example #8
0
// 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)
}
Example #9
0
func (self *Surface) GetHeight() int {
	return int(C.cairo_image_surface_get_height(self.surface))
}
Example #10
0
// 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))
				}
			}
		}
	}
}