1package cairo 2 3// #include <stdlib.h> 4// #include <cairo.h> 5// #include <cairo-gobject.h> 6import "C" 7 8import ( 9 "reflect" 10 "runtime" 11 "unsafe" 12) 13 14// Context is a representation of Cairo's cairo_t. 15type Context struct { 16 context *C.cairo_t 17} 18 19// native returns a pointer to the underlying cairo_t. 20func (v *Context) native() *C.cairo_t { 21 if v == nil { 22 return nil 23 } 24 return v.context 25} 26 27func (v *Context) GetCContext() *C.cairo_t { 28 return v.native() 29} 30 31// Native returns a pointer to the underlying cairo_t. 32func (v *Context) Native() uintptr { 33 return uintptr(unsafe.Pointer(v.native())) 34} 35 36func marshalContext(p uintptr) (interface{}, error) { 37 c := C.g_value_get_boxed((*C.GValue)(unsafe.Pointer(p))) 38 context := (*C.cairo_t)(unsafe.Pointer(c)) 39 return wrapContext(context), nil 40} 41 42func wrapContext(context *C.cairo_t) *Context { 43 return &Context{context} 44} 45 46func WrapContext(p uintptr) *Context { 47 context := (*C.cairo_t)(unsafe.Pointer(p)) 48 return wrapContext(context) 49} 50 51// Closes the context. The context must not be used afterwards. 52func (v *Context) Close() { 53 v.destroy() 54} 55 56// Create is a wrapper around cairo_create(). 57func Create(target *Surface) *Context { 58 c := C.cairo_create(target.native()) 59 ctx := wrapContext(c) 60 runtime.SetFinalizer(ctx, (*Context).destroy) 61 return ctx 62} 63 64// reference is a wrapper around cairo_reference(). 65func (v *Context) reference() { 66 v.context = C.cairo_reference(v.native()) 67} 68 69// destroy is a wrapper around cairo_destroy(). 70func (v *Context) destroy() { 71 if v.context != nil { 72 C.cairo_destroy(v.native()) 73 v.context = nil 74 } 75} 76 77// Status is a wrapper around cairo_status(). 78func (v *Context) Status() Status { 79 c := C.cairo_status(v.native()) 80 return Status(c) 81} 82 83// Save is a wrapper around cairo_save(). 84func (v *Context) Save() { 85 C.cairo_save(v.native()) 86} 87 88// Restore is a wrapper around cairo_restore(). 89func (v *Context) Restore() { 90 C.cairo_restore(v.native()) 91} 92 93// GetTarget is a wrapper around cairo_get_target(). 94func (v *Context) GetTarget() *Surface { 95 c := C.cairo_get_target(v.native()) 96 s := wrapSurface(c) 97 s.reference() 98 runtime.SetFinalizer(s, (*Surface).destroy) 99 return s 100} 101 102// PushGroup is a wrapper around cairo_push_group(). 103func (v *Context) PushGroup() { 104 C.cairo_push_group(v.native()) 105} 106 107// PushGroupWithContent is a wrapper around cairo_push_group_with_content(). 108func (v *Context) PushGroupWithContent(content Content) { 109 C.cairo_push_group_with_content(v.native(), C.cairo_content_t(content)) 110} 111 112// TODO(jrick) PopGroup (depends on Pattern) 113// cairo_pop_group 114 115// PopGroupToSource is a wrapper around cairo_pop_group_to_source(). 116func (v *Context) PopGroupToSource() { 117 C.cairo_pop_group_to_source(v.native()) 118} 119 120// GetGroupTarget is a wrapper around cairo_get_group_target(). 121func (v *Context) GetGroupTarget() *Surface { 122 c := C.cairo_get_group_target(v.native()) 123 s := wrapSurface(c) 124 s.reference() 125 runtime.SetFinalizer(s, (*Surface).destroy) 126 return s 127} 128 129// SetSource is a wrapper around cairo_set_source(). 130func (v *Context) SetSource(p *Pattern) { 131 C.cairo_set_source(v.native(), p.native()) 132} 133 134// SetSourceRGB is a wrapper around cairo_set_source_rgb(). 135func (v *Context) SetSourceRGB(red, green, blue float64) { 136 C.cairo_set_source_rgb(v.native(), C.double(red), C.double(green), 137 C.double(blue)) 138} 139 140// SetSourceRGBA is a wrapper around cairo_set_source_rgba(). 141func (v *Context) SetSourceRGBA(red, green, blue, alpha float64) { 142 C.cairo_set_source_rgba(v.native(), C.double(red), C.double(green), 143 C.double(blue), C.double(alpha)) 144} 145 146// TODO(jrick) SetSource (depends on Pattern) 147// cairo_set_source 148 149// SetSourceSurface is a wrapper around cairo_set_source_surface(). 150func (v *Context) SetSourceSurface(surface *Surface, x, y float64) { 151 C.cairo_set_source_surface(v.native(), surface.native(), C.double(x), 152 C.double(y)) 153} 154 155// TODO(jrick) GetSource (depends on Pattern) 156// cairo_get_source 157 158// SetAntialias is a wrapper around cairo_set_antialias(). 159func (v *Context) SetAntialias(antialias Antialias) { 160 C.cairo_set_antialias(v.native(), C.cairo_antialias_t(antialias)) 161} 162 163// GetAntialias is a wrapper around cairo_get_antialias(). 164func (v *Context) GetAntialias() Antialias { 165 c := C.cairo_get_antialias(v.native()) 166 return Antialias(c) 167} 168 169// SetDash is a wrapper around cairo_set_dash(). 170func (v *Context) SetDash(dashes []float64, offset float64) { 171 header := (*reflect.SliceHeader)(unsafe.Pointer(&dashes)) 172 cdashes := (*C.double)(unsafe.Pointer(header.Data)) 173 C.cairo_set_dash(v.native(), cdashes, C.int(header.Len), 174 C.double(offset)) 175} 176 177// GetDashCount is a wrapper around cairo_get_dash_count(). 178func (v *Context) GetDashCount() int { 179 c := C.cairo_get_dash_count(v.native()) 180 return int(c) 181} 182 183// GetDash is a wrapper around cairo_get_dash(). 184func (v *Context) GetDash() (dashes []float64, offset float64) { 185 dashCount := v.GetDashCount() 186 cdashes := (*C.double)(C.calloc(8, C.size_t(dashCount))) 187 var coffset C.double 188 C.cairo_get_dash(v.native(), cdashes, &coffset) 189 header := (*reflect.SliceHeader)((unsafe.Pointer(&dashes))) 190 header.Data = uintptr(unsafe.Pointer(cdashes)) 191 header.Len = dashCount 192 header.Cap = dashCount 193 return dashes, float64(coffset) 194} 195 196// SetFillRule is a wrapper around cairo_set_fill_rule(). 197func (v *Context) SetFillRule(fillRule FillRule) { 198 C.cairo_set_fill_rule(v.native(), C.cairo_fill_rule_t(fillRule)) 199} 200 201// GetFillRule is a wrapper around cairo_get_fill_rule(). 202func (v *Context) GetFillRule() FillRule { 203 c := C.cairo_get_fill_rule(v.native()) 204 return FillRule(c) 205} 206 207// SetLineCap is a wrapper around cairo_set_line_cap(). 208func (v *Context) SetLineCap(lineCap LineCap) { 209 C.cairo_set_line_cap(v.native(), C.cairo_line_cap_t(lineCap)) 210} 211 212// GetLineCap is a wrapper around cairo_get_line_cap(). 213func (v *Context) GetLineCap() LineCap { 214 c := C.cairo_get_line_cap(v.native()) 215 return LineCap(c) 216} 217 218// SetLineJoin is a wrapper around cairo_set_line_join(). 219func (v *Context) SetLineJoin(lineJoin LineJoin) { 220 C.cairo_set_line_join(v.native(), C.cairo_line_join_t(lineJoin)) 221} 222 223// GetLineJoin is a wrapper around cairo_get_line_join(). 224func (v *Context) GetLineJoin() LineJoin { 225 c := C.cairo_get_line_join(v.native()) 226 return LineJoin(c) 227} 228 229// SetLineWidth is a wrapper around cairo_set_line_width(). 230func (v *Context) SetLineWidth(width float64) { 231 C.cairo_set_line_width(v.native(), C.double(width)) 232} 233 234// GetLineWidth is a wrapper cairo_get_line_width(). 235func (v *Context) GetLineWidth() float64 { 236 c := C.cairo_get_line_width(v.native()) 237 return float64(c) 238} 239 240// SetMiterLimit is a wrapper around cairo_set_miter_limit(). 241func (v *Context) SetMiterLimit(limit float64) { 242 C.cairo_set_miter_limit(v.native(), C.double(limit)) 243} 244 245// GetMiterLimit is a wrapper around cairo_get_miter_limit(). 246func (v *Context) GetMiterLimit() float64 { 247 c := C.cairo_get_miter_limit(v.native()) 248 return float64(c) 249} 250 251// SetOperator is a wrapper around cairo_set_operator(). 252func (v *Context) SetOperator(op Operator) { 253 C.cairo_set_operator(v.native(), C.cairo_operator_t(op)) 254} 255 256// GetOperator is a wrapper around cairo_get_operator(). 257func (v *Context) GetOperator() Operator { 258 c := C.cairo_get_operator(v.native()) 259 return Operator(c) 260} 261 262// SetTolerance is a wrapper around cairo_set_tolerance(). 263func (v *Context) SetTolerance(tolerance float64) { 264 C.cairo_set_tolerance(v.native(), C.double(tolerance)) 265} 266 267// GetTolerance is a wrapper around cairo_get_tolerance(). 268func (v *Context) GetTolerance() float64 { 269 c := C.cairo_get_tolerance(v.native()) 270 return float64(c) 271} 272 273// Clip is a wrapper around cairo_clip(). 274func (v *Context) Clip() { 275 C.cairo_clip(v.native()) 276} 277 278// ClipPreserve is a wrapper around cairo_clip_preserve(). 279func (v *Context) ClipPreserve() { 280 C.cairo_clip_preserve(v.native()) 281} 282 283// ClipExtents is a wrapper around cairo_clip_extents(). 284func (v *Context) ClipExtents() (x1, y1, x2, y2 float64) { 285 var cx1, cy1, cx2, cy2 C.double 286 C.cairo_clip_extents(v.native(), &cx1, &cy1, &cx2, &cy2) 287 return float64(cx1), float64(cy1), float64(cx2), float64(cy2) 288} 289 290// InClip is a wrapper around cairo_in_clip(). 291func (v *Context) InClip(x, y float64) bool { 292 c := C.cairo_in_clip(v.native(), C.double(x), C.double(y)) 293 return gobool(c) 294} 295 296// ResetClip is a wrapper around cairo_reset_clip(). 297func (v *Context) ResetClip() { 298 C.cairo_reset_clip(v.native()) 299} 300 301// Rectangle is a wrapper around cairo_rectangle(). 302func (v *Context) Rectangle(x, y, w, h float64) { 303 C.cairo_rectangle(v.native(), C.double(x), C.double(y), C.double(w), C.double(h)) 304} 305 306// Arc is a wrapper around cairo_arc(). 307func (v *Context) Arc(xc, yc, radius, angle1, angle2 float64) { 308 C.cairo_arc(v.native(), C.double(xc), C.double(yc), C.double(radius), C.double(angle1), C.double(angle2)) 309} 310 311// ArcNegative is a wrapper around cairo_arc_negative(). 312func (v *Context) ArcNegative(xc, yc, radius, angle1, angle2 float64) { 313 C.cairo_arc_negative(v.native(), C.double(xc), C.double(yc), C.double(radius), C.double(angle1), C.double(angle2)) 314} 315 316// LineTo is a wrapper around cairo_line_to(). 317func (v *Context) LineTo(x, y float64) { 318 C.cairo_line_to(v.native(), C.double(x), C.double(y)) 319} 320 321// CurveTo is a wrapper around cairo_curve_to(). 322func (v *Context) CurveTo(x1, y1, x2, y2, x3, y3 float64) { 323 C.cairo_curve_to(v.native(), C.double(x1), C.double(y1), C.double(x2), C.double(y2), C.double(x3), C.double(y3)) 324} 325 326// MoveTo is a wrapper around cairo_move_to(). 327func (v *Context) MoveTo(x, y float64) { 328 C.cairo_move_to(v.native(), C.double(x), C.double(y)) 329} 330 331// TODO(jrick) CopyClipRectangleList (depends on RectangleList) 332// cairo_copy_clip_rectangle_list 333 334// Fill is a wrapper around cairo_fill(). 335func (v *Context) Fill() { 336 C.cairo_fill(v.native()) 337} 338 339// ClosePath is a wrapper around cairo_close_path(). 340func (v *Context) ClosePath() { 341 C.cairo_close_path(v.native()) 342} 343 344// NewPath is a wrapper around cairo_new_path(). 345func (v *Context) NewPath() { 346 C.cairo_new_path(v.native()) 347} 348 349// GetCurrentPoint is a wrapper around cairo_get_current_point(). 350func (v *Context) GetCurrentPoint() (x, y float64) { 351 C.cairo_get_current_point(v.native(), (*C.double)(&x), (*C.double)(&y)) 352 return 353} 354 355// FillPreserve is a wrapper around cairo_fill_preserve(). 356func (v *Context) FillPreserve() { 357 C.cairo_fill_preserve(v.native()) 358} 359 360// FillExtents is a wrapper around cairo_fill_extents(). 361func (v *Context) FillExtents() (x1, y1, x2, y2 float64) { 362 var cx1, cy1, cx2, cy2 C.double 363 C.cairo_fill_extents(v.native(), &cx1, &cy1, &cx2, &cy2) 364 return float64(cx1), float64(cy1), float64(cx2), float64(cy2) 365} 366 367// InFill is a wrapper around cairo_in_fill(). 368func (v *Context) InFill(x, y float64) bool { 369 c := C.cairo_in_fill(v.native(), C.double(x), C.double(y)) 370 return gobool(c) 371} 372 373// TODO(jrick) Mask (depends on Pattern) 374// cairo_mask_surface 375 376// MaskSurface is a wrapper around cairo_mask_surface(). 377func (v *Context) MaskSurface(surface *Surface, surfaceX, surfaceY float64) { 378 C.cairo_mask_surface(v.native(), surface.native(), C.double(surfaceX), 379 C.double(surfaceY)) 380} 381 382// Paint is a wrapper around cairo_paint(). 383func (v *Context) Paint() { 384 C.cairo_paint(v.native()) 385} 386 387// PaintWithAlpha is a wrapper around cairo_paint_with_alpha(). 388func (v *Context) PaintWithAlpha(alpha float64) { 389 C.cairo_paint_with_alpha(v.native(), C.double(alpha)) 390} 391 392// Stroke is a wrapper around cairo_stroke(). 393func (v *Context) Stroke() { 394 C.cairo_stroke(v.native()) 395} 396 397// StrokePreserve is a wrapper around cairo_stroke_preserve(). 398func (v *Context) StrokePreserve() { 399 C.cairo_stroke_preserve(v.native()) 400} 401 402// StrokeExtents is a wrapper around cairo_stroke_extents(). 403func (v *Context) StrokeExtents() (x1, y1, x2, y2 float64) { 404 var cx1, cy1, cx2, cy2 C.double 405 C.cairo_stroke_extents(v.native(), &cx1, &cy1, &cx2, &cy2) 406 return float64(cx1), float64(cy1), float64(cx2), float64(cy2) 407} 408 409// InStroke is a wrapper around cairo_in_stroke(). 410func (v *Context) InStroke(x, y float64) bool { 411 c := C.cairo_in_stroke(v.native(), C.double(x), C.double(y)) 412 return gobool(c) 413} 414 415// CopyPage is a wrapper around cairo_copy_page(). 416func (v *Context) CopyPage() { 417 C.cairo_copy_page(v.native()) 418} 419 420// ShowPage is a wrapper around cairo_show_page(). 421func (v *Context) ShowPage() { 422 C.cairo_show_page(v.native()) 423} 424