1package cairo 2 3// #include <stdlib.h> 4// #include <cairo.h> 5// #include <cairo-gobject.h> 6// #include <cairo-pdf.h> 7import "C" 8 9import ( 10 "runtime" 11 "unsafe" 12) 13 14/* 15 * cairo_surface_t 16 */ 17 18// Surface is a representation of Cairo's cairo_surface_t. 19type Surface struct { 20 surface *C.cairo_surface_t 21} 22 23func NewSurfaceFromPNG(fileName string) (*Surface, error) { 24 25 cstr := C.CString(fileName) 26 defer C.free(unsafe.Pointer(cstr)) 27 28 surfaceNative := C.cairo_image_surface_create_from_png(cstr) 29 30 status := Status(C.cairo_surface_status(surfaceNative)) 31 if status != STATUS_SUCCESS { 32 return nil, ErrorStatus(status) 33 } 34 35 return &Surface{surfaceNative}, nil 36} 37 38// CreateImageSurfaceForData is a wrapper around cairo_image_surface_create_for_data(). 39func CreateImageSurfaceForData(data []byte, format Format, width, height, stride int) (*Surface, error) { 40 surfaceNative := C.cairo_image_surface_create_for_data((*C.uchar)(unsafe.Pointer(&data[0])), 41 C.cairo_format_t(format), C.int(width), C.int(height), C.int(stride)) 42 43 status := Status(C.cairo_surface_status(surfaceNative)) 44 if status != STATUS_SUCCESS { 45 return nil, ErrorStatus(status) 46 } 47 48 s := wrapSurface(surfaceNative) 49 50 runtime.SetFinalizer(s, (*Surface).destroy) 51 52 return s, nil 53} 54 55// CreateImageSurface is a wrapper around cairo_image_surface_create(). 56func CreateImageSurface(format Format, width, height int) *Surface { 57 c := C.cairo_image_surface_create(C.cairo_format_t(format), 58 C.int(width), C.int(height)) 59 s := wrapSurface(c) 60 runtime.SetFinalizer(s, (*Surface).destroy) 61 return s 62} 63 64/// Create a new PDF surface. 65func CreatePDFSurface(fileName string, width float64, height float64) (*Surface, error) { 66 cstr := C.CString(fileName) 67 defer C.free(unsafe.Pointer(cstr)) 68 69 surfaceNative := C.cairo_pdf_surface_create(cstr, C.double(width), C.double(height)) 70 71 status := Status(C.cairo_surface_status(surfaceNative)) 72 if status != STATUS_SUCCESS { 73 return nil, ErrorStatus(status) 74 } 75 76 s := wrapSurface(surfaceNative) 77 78 runtime.SetFinalizer(s, (*Surface).destroy) 79 80 return s, nil 81} 82 83// native returns a pointer to the underlying cairo_surface_t. 84func (v *Surface) native() *C.cairo_surface_t { 85 if v == nil { 86 return nil 87 } 88 return v.surface 89} 90 91// Native returns a pointer to the underlying cairo_surface_t. 92func (v *Surface) Native() uintptr { 93 return uintptr(unsafe.Pointer(v.native())) 94} 95 96func (v *Surface) GetCSurface() *C.cairo_surface_t { 97 return v.native() 98} 99 100func marshalSurface(p uintptr) (interface{}, error) { 101 c := C.g_value_get_boxed((*C.GValue)(unsafe.Pointer(p))) 102 return WrapSurface(uintptr(c)), nil 103} 104 105func wrapSurface(surface *C.cairo_surface_t) *Surface { 106 return &Surface{surface} 107} 108 109// NewSurface creates a gotk3 cairo Surface from a pointer to a 110// C cairo_surface_t. This is primarily designed for use with other 111// gotk3 packages and should be avoided by applications. 112func NewSurface(s uintptr, needsRef bool) *Surface { 113 surface := WrapSurface(s) 114 if needsRef { 115 surface.reference() 116 } 117 runtime.SetFinalizer(surface, (*Surface).destroy) 118 return surface 119} 120 121func WrapSurface(s uintptr) *Surface { 122 ptr := (*C.cairo_surface_t)(unsafe.Pointer(s)) 123 return wrapSurface(ptr) 124} 125 126// Closes the surface. The surface must not be used afterwards. 127func (v *Surface) Close() { 128 v.destroy() 129} 130 131// CreateSimilar is a wrapper around cairo_surface_create_similar(). 132func (v *Surface) CreateSimilar(content Content, width, height int) *Surface { 133 c := C.cairo_surface_create_similar(v.native(), 134 C.cairo_content_t(content), C.int(width), C.int(height)) 135 s := wrapSurface(c) 136 runtime.SetFinalizer(s, (*Surface).destroy) 137 return s 138} 139 140// TODO cairo_surface_create_similar_image (since 1.12) 141 142// CreateForRectangle is a wrapper around cairo_surface_create_for_rectangle(). 143func (v *Surface) CreateForRectangle(x, y, width, height float64) *Surface { 144 c := C.cairo_surface_create_for_rectangle(v.native(), C.double(x), 145 C.double(y), C.double(width), C.double(height)) 146 s := wrapSurface(c) 147 runtime.SetFinalizer(s, (*Surface).destroy) 148 return s 149} 150 151// reference is a wrapper around cairo_surface_reference(). 152func (v *Surface) reference() { 153 v.surface = C.cairo_surface_reference(v.native()) 154} 155 156// destroy is a wrapper around cairo_surface_destroy(). 157func (v *Surface) destroy() { 158 if v.surface != nil { 159 C.cairo_surface_destroy(v.native()) 160 v.surface = nil 161 } 162} 163 164// Status is a wrapper around cairo_surface_status(). 165func (v *Surface) Status() Status { 166 c := C.cairo_surface_status(v.native()) 167 return Status(c) 168} 169 170// Flush is a wrapper around cairo_surface_flush(). 171func (v *Surface) Flush() { 172 C.cairo_surface_flush(v.native()) 173} 174 175// TODO(jrick) GetDevice (requires Device bindings) 176// cairo_surface_get_device 177 178// TODO(jrick) GetFontOptions (require FontOptions bindings) 179// cairo_surface_get_font_options 180 181// TODO(jrick) GetContent (requires Content bindings) 182// cairo_surface_get_content 183 184// MarkDirty is a wrapper around cairo_surface_mark_dirty(). 185func (v *Surface) MarkDirty() { 186 C.cairo_surface_mark_dirty(v.native()) 187} 188 189// MarkDirtyRectangle is a wrapper around cairo_surface_mark_dirty_rectangle(). 190func (v *Surface) MarkDirtyRectangle(x, y, width, height int) { 191 C.cairo_surface_mark_dirty_rectangle(v.native(), C.int(x), C.int(y), 192 C.int(width), C.int(height)) 193} 194 195// SetDeviceOffset is a wrapper around cairo_surface_set_device_offset(). 196func (v *Surface) SetDeviceOffset(x, y float64) { 197 C.cairo_surface_set_device_offset(v.native(), C.double(x), C.double(y)) 198} 199 200// GetDeviceOffset is a wrapper around cairo_surface_get_device_offset(). 201func (v *Surface) GetDeviceOffset() (x, y float64) { 202 var xOffset, yOffset C.double 203 C.cairo_surface_get_device_offset(v.native(), &xOffset, &yOffset) 204 return float64(xOffset), float64(yOffset) 205} 206 207// SetFallbackResolution is a wrapper around 208// cairo_surface_set_fallback_resolution(). 209func (v *Surface) SetFallbackResolution(xPPI, yPPI float64) { 210 C.cairo_surface_set_fallback_resolution(v.native(), C.double(xPPI), 211 C.double(yPPI)) 212} 213 214// GetFallbackResolution is a wrapper around cairo_surface_get_fallback_resolution(). 215func (v *Surface) GetFallbackResolution() (xPPI, yPPI float64) { 216 var x, y C.double 217 C.cairo_surface_get_fallback_resolution(v.native(), &x, &y) 218 return float64(x), float64(y) 219} 220 221// GetType is a wrapper around cairo_surface_get_type(). 222func (v *Surface) GetType() SurfaceType { 223 c := C.cairo_surface_get_type(v.native()) 224 return SurfaceType(c) 225} 226 227// TODO(jrick) SetUserData (depends on UserDataKey and DestroyFunc) 228// cairo_surface_set_user_data 229 230// TODO(jrick) GetUserData (depends on UserDataKey) 231// cairo_surface_get_user_data 232 233// CopyPage is a wrapper around cairo_surface_copy_page(). 234func (v *Surface) CopyPage() { 235 C.cairo_surface_copy_page(v.native()) 236} 237 238// ShowPage is a wrapper around cairo_surface_show_page(). 239func (v *Surface) ShowPage() { 240 C.cairo_surface_show_page(v.native()) 241} 242 243// HasShowTextGlyphs is a wrapper around cairo_surface_has_show_text_glyphs(). 244func (v *Surface) HasShowTextGlyphs() bool { 245 c := C.cairo_surface_has_show_text_glyphs(v.native()) 246 return gobool(c) 247} 248 249// TODO(jrick) SetMimeData (depends on DestroyFunc) 250// cairo_surface_set_mime_data 251 252// GetMimeData is a wrapper around cairo_surface_get_mime_data(). The 253// returned mimetype data is returned as a Go byte slice. 254func (v *Surface) GetMimeData(mimeType MimeType) []byte { 255 cstr := C.CString(string(mimeType)) 256 defer C.free(unsafe.Pointer(cstr)) 257 var data *C.uchar 258 var length C.ulong 259 C.cairo_surface_get_mime_data(v.native(), cstr, &data, &length) 260 return C.GoBytes(unsafe.Pointer(data), C.int(length)) 261} 262 263// WriteToPNG is a wrapper around cairo_surface_write_png(). It writes the Cairo 264// surface to the given file in PNG format. 265func (v *Surface) WriteToPNG(fileName string) error { 266 cstr := C.CString(fileName) 267 defer C.free(unsafe.Pointer(cstr)) 268 269 status := Status(C.cairo_surface_write_to_png(v.surface, cstr)) 270 271 if status != STATUS_SUCCESS { 272 return ErrorStatus(status) 273 } 274 275 return nil 276} 277 278// TODO(jrick) SupportsMimeType (since 1.12) 279// cairo_surface_supports_mime_type 280 281// TODO(jrick) MapToImage (since 1.12) 282// cairo_surface_map_to_image 283 284// TODO(jrick) UnmapImage (since 1.12) 285// cairo_surface_unmap_image 286 287// GetHeight is a wrapper around cairo_image_surface_get_height(). 288func (v *Surface) GetHeight() int { 289 return int(C.cairo_image_surface_get_height(v.surface)) 290} 291 292// GetWidth is a wrapper around cairo_image_surface_get_width(). 293func (v *Surface) GetWidth() int { 294 return int(C.cairo_image_surface_get_width(v.surface)) 295} 296 297// GetData is a wrapper around cairo_image_surface_get_data(). 298func (v *Surface) GetData() unsafe.Pointer { 299 return unsafe.Pointer(C.cairo_image_surface_get_data(v.surface)) 300} 301