aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/go-skia/skia.go
diff options
context:
space:
mode:
authorGravatar Stephan Altmueller <stephana@google.com>2017-05-09 15:56:06 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-10 15:32:19 +0000
commitefa48d599de15d960d7335a4a93a6bbeb97d3c41 (patch)
tree6b95700087faeaaec0ea030d0fa5e17b515cebc1 /experimental/go-skia/skia.go
parent05fd8cf08970763832d6690ca1823168dd6f071f (diff)
Experimental Go bindings for Skia
This CL implements Go bindings for a subset of the functions in the C API. It implements a Go version of the C demo program in experimental/c-api-example/skia-c-example.c and the output is identical. (Checked by hand). The main purpose is to establish a pattern of calling the Skia C API that is memory safe and provides a idiomatic Go interface to Skia. Follow up CLs will cover the entire C API, add documentation and establish a pattern to distribute the bindings more easily. BUG= Change-Id: I96ff7c3715164c533202ce300ab0312b1b07f884 Change-Id: I96ff7c3715164c533202ce300ab0312b1b07f884 Reviewed-on: https://skia-review.googlesource.com/10032 Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Stephan Altmueller <stephana@google.com>
Diffstat (limited to 'experimental/go-skia/skia.go')
-rw-r--r--experimental/go-skia/skia.go223
1 files changed, 199 insertions, 24 deletions
diff --git a/experimental/go-skia/skia.go b/experimental/go-skia/skia.go
index 30730578a7..e477593dc8 100644
--- a/experimental/go-skia/skia.go
+++ b/experimental/go-skia/skia.go
@@ -1,38 +1,213 @@
-package main
-
-// First, build Skia this way:
-// ./gyp_skia -Dskia_shared_lib=1 && ninja -C out/Debug
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+package skia
/*
-#cgo LDFLAGS: -lGL
-#cgo LDFLAGS: -lGLU
-#cgo LDFLAGS: -lX11
-#cgo LDFLAGS: -ldl
-#cgo LDFLAGS: -lfontconfig
-#cgo LDFLAGS: -lfreetype
-#cgo LDFLAGS: -lgif
-#cgo LDFLAGS: -lm
-#cgo LDFLAGS: -lpng
-#cgo LDFLAGS: -lstdc++
-#cgo LDFLAGS: -lz
-
-#cgo LDFLAGS: -L ../../out/Debug/lib
-#cgo LDFLAGS: -Wl,-rpath=../../out/Debug/lib
+#cgo LDFLAGS: -L${SRCDIR}/../../out/Shared
+#cgo LDFLAGS: -Wl,-rpath=${SRCDIR}/../../out/Shared
#cgo LDFLAGS: -lskia
-
#cgo CFLAGS: -I../../include/c
+#include "sk_canvas.h"
+#include "sk_data.h"
+#include "sk_image.h"
+#include "sk_paint.h"
+#include "sk_path.h"
#include "sk_surface.h"
*/
import "C"
import (
"fmt"
+ "io"
+ "runtime"
+ "unsafe"
)
-func main() {
- p := C.sk_paint_new()
- defer C.sk_paint_delete(p)
- fmt.Println("OK!")
+// TODO(stephana): Add proper documentation to the types defined here.
+
+//////////////////////////////////////////////////////////////////////////
+// Surface
+//////////////////////////////////////////////////////////////////////////
+type Surface struct {
+ ptr *C.sk_surface_t
+}
+
+// func NewRasterSurface(width, height int32, alphaType AlphaType) (*Surface, error) {
+func NewRasterSurface(imgInfo *ImageInfo) (*Surface, error) {
+ ptr := C.sk_surface_new_raster(imgInfo.cPointer(), (*C.sk_surfaceprops_t)(nil))
+ if ptr == nil {
+ return nil, fmt.Errorf("Unable to create raster surface.")
+ }
+
+ ret := &Surface{ptr: ptr}
+ runtime.SetFinalizer(ret, func(s *Surface) {
+ C.sk_surface_unref(s.ptr)
+ })
+ return ret, nil
+}
+
+func (s *Surface) Canvas() *Canvas {
+ return &Canvas{
+ ptr: C.sk_surface_get_canvas(s.ptr),
+ keepParentAlive: s,
+ }
+}
+
+func (s *Surface) Image() *Image {
+ ret := &Image{
+ ptr: C.sk_surface_new_image_snapshot(s.ptr),
+ keepParentAlive: s,
+ }
+ runtime.SetFinalizer(ret, func(i *Image) {
+ C.sk_image_unref(i.ptr)
+ })
+ return ret
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Image
+//////////////////////////////////////////////////////////////////////////
+type Image struct {
+ ptr *C.sk_image_t
+ keepParentAlive *Surface
+}
+
+func (i *Image) WritePNG(w io.Writer) error {
+ data := C.sk_image_encode(i.ptr)
+ defer C.sk_data_unref(data)
+
+ dataPtr := C.sk_data_get_data(data)
+ dataSize := C.sk_data_get_size(data)
+ byteSlice := C.GoBytes(dataPtr, C.int(dataSize))
+ _, err := w.Write(byteSlice)
+ if err != nil {
+ return err
+ }
+ return nil
}
-// TODO: replace this with an idiomatic interface to Skia.
+//////////////////////////////////////////////////////////////////////////
+// Canvas
+//////////////////////////////////////////////////////////////////////////
+type Canvas struct {
+ ptr *C.sk_canvas_t
+ keepParentAlive *Surface
+}
+
+func (c *Canvas) DrawPaint(paint *Paint) {
+ C.sk_canvas_draw_paint(c.ptr, paint.ptr)
+}
+
+func (c *Canvas) DrawOval(rect *Rect, paint *Paint) {
+ // C.sk_canvas_draw_oval(c.ptr, (*C.sk_rect_t)(unsafe.Pointer(rect)), (*C.sk_paint_t)(paint.ptr))
+ C.sk_canvas_draw_oval(c.ptr, rect.cPointer(), paint.ptr)
+}
+
+func (c *Canvas) DrawRect(rect *Rect, paint *Paint) {
+ // C.sk_canvas_draw_rect(c.ptr, (*C.sk_rect_t)(unsafe.Pointer(rect)), (*C.sk_paint_t)(paint.ptr))
+ C.sk_canvas_draw_rect(c.ptr, rect.cPointer(), paint.ptr)
+}
+
+func (c *Canvas) DrawPath(path *Path, paint *Paint) {
+ // C.sk_canvas_draw_path(c.ptr, (*C.sk_path_t)(path.ptr), (*C.sk_paint_t)(paint.ptr))
+ C.sk_canvas_draw_path(c.ptr, path.ptr, paint.ptr)
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Paint
+//////////////////////////////////////////////////////////////////////////
+type Paint struct {
+ ptr *C.sk_paint_t
+}
+
+func NewPaint() *Paint {
+ ret := &Paint{ptr: C.sk_paint_new()}
+ runtime.SetFinalizer(ret, func(p *Paint) {
+ C.sk_paint_delete(p.ptr)
+ })
+ return ret
+}
+
+func (p *Paint) SetColor(color Color) {
+ C.sk_paint_set_color(p.ptr, C.sk_color_t(color))
+}
+
+func (p *Paint) SetAntiAlias(antiAlias bool) {
+ C.sk_paint_set_antialias(p.ptr, C._Bool(antiAlias))
+}
+
+func (p *Paint) SetStroke(val bool) {
+ C.sk_paint_set_stroke(p.ptr, C._Bool(val))
+}
+
+func (p *Paint) SetStrokeWidth(width float32) {
+ C.sk_paint_set_stroke_width(p.ptr, C.float(width))
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Path
+//////////////////////////////////////////////////////////////////////////
+type Path struct {
+ ptr *C.sk_path_t
+}
+
+func NewPath() *Path {
+ ret := &Path{ptr: C.sk_path_new()}
+ runtime.SetFinalizer(ret, func(p *Path) {
+ C.sk_path_delete(p.ptr)
+ })
+ return ret
+}
+
+func (p *Path) MoveTo(x, y float32) {
+ C.sk_path_move_to(p.ptr, C.float(x), C.float(y))
+}
+
+func (p *Path) LineTo(x, y float32) {
+ C.sk_path_line_to(p.ptr, C.float(x), C.float(y))
+}
+
+func (p *Path) QuadTo(x0, y0, x1, y1 float32) {
+ C.sk_path_quad_to(p.ptr, C.float(x0), C.float(y0), C.float(x1), C.float(y1))
+}
+
+func (p *Path) ConicTo(x0, y0, x1, y1, w float32) {
+ C.sk_path_conic_to(p.ptr, C.float(x0), C.float(y0), C.float(x1), C.float(y1), C.float(w))
+}
+
+func (p *Path) CubicTo(x0, y0, x1, y1, x2, y2 float32) {
+ C.sk_path_cubic_to(p.ptr, C.float(x0), C.float(y0), C.float(x1), C.float(y1), C.float(x2), C.float(y2))
+}
+
+func (p *Path) Close() {
+ C.sk_path_close(p.ptr)
+}
+
+// NewRect is a convenience function to define a Rect in a single line.
+func NewRect(left, top, right, bottom float32) *Rect {
+ return &Rect{
+ Left: left,
+ Top: top,
+ Right: right,
+ Bottom: bottom,
+ }
+}
+
+// cPointer casts the pointer to Rect to the corresponding C pointer.
+func (r *Rect) cPointer() *C.sk_rect_t {
+ return (*C.sk_rect_t)(unsafe.Pointer(r))
+}
+
+// cPointer casts the pointer to ImageInfo to the corresponding C pointer.
+func (i *ImageInfo) cPointer() *C.sk_imageinfo_t {
+ return (*C.sk_imageinfo_t)(unsafe.Pointer(i))
+}
+
+// Utility functions.
+func GetDefaultColortype() ColorType {
+ return ColorType(C.sk_colortype_get_default_8888())
+}