1// region.go
2
3package cairo
4
5// #include <cairo.h>
6// #include <cairo-gobject.h>
7import "C"
8
9import (
10	"runtime"
11	"unsafe"
12
13	"github.com/gotk3/gotk3/glib"
14)
15
16func init() {
17	tm := []glib.TypeMarshaler{
18		// Enums
19		{glib.Type(C.cairo_gobject_region_overlap_get_type()), marshalRegionOverlap},
20
21		// Boxed
22		{glib.Type(C.cairo_gobject_region_get_type()), marshalRegion},
23	}
24	glib.RegisterGValueMarshalers(tm)
25}
26
27// RegionOverlap is a representation of Cairo's cairo_region_overlap_t.
28type RegionOverlap int
29
30const (
31	REGION_OVERLAP_IN   RegionOverlap = C.CAIRO_REGION_OVERLAP_IN
32	REGION_OVERLAP_OUT  RegionOverlap = C.CAIRO_REGION_OVERLAP_OUT
33	REGION_OVERLAP_PART RegionOverlap = C.CAIRO_REGION_OVERLAP_PART
34)
35
36func marshalRegionOverlap(p uintptr) (interface{}, error) {
37	c := C.g_value_get_enum((*C.GValue)(unsafe.Pointer(p)))
38	return RegionOverlap(c), nil
39}
40
41/*
42 * Rectangle
43 */
44
45// Rectangle is a representation of Cairo's cairo_rectangle_int_t.
46type Rectangle struct {
47	X, Y          int
48	Width, Height int
49}
50
51// commodity function to ceate Rectangle cairo object.
52func RectangleNew(x, y, width, height int) *Rectangle {
53	r := new(Rectangle)
54	r.X = x
55	r.Y = y
56	r.Width = width
57	r.Height = height
58	return r
59}
60
61func (v *Rectangle) native() *C.cairo_rectangle_int_t {
62	r := new(C.cairo_rectangle_int_t)
63	r.x = C.int(v.X)
64	r.y = C.int(v.Y)
65	r.width = C.int(v.Width)
66	r.height = C.int(v.Height)
67	return r
68}
69
70func toRectangle(cr *C.cairo_rectangle_int_t) *Rectangle {
71	return &Rectangle{
72		X: int(cr.x), Y: int(cr.y),
73		Width: int(cr.width), Height: int(cr.height)}
74}
75
76/*
77 * Region
78 */
79
80// Region is a representation of Cairo's cairo_region_t.
81type Region struct {
82	region *C.cairo_region_t
83}
84
85// native returns a pointer to the underlying cairo_region_t.
86func (v *Region) native() *C.cairo_region_t {
87	if v == nil {
88		return nil
89	}
90	return v.region
91}
92
93// Native returns a pointer to the underlying cairo_region_t.
94func (v *Region) Native() uintptr {
95	return uintptr(unsafe.Pointer(v.native()))
96}
97
98func marshalRegion(p uintptr) (interface{}, error) {
99	c := C.g_value_get_boxed((*C.GValue)(unsafe.Pointer(p)))
100	region := (*C.cairo_region_t)(unsafe.Pointer(c))
101	return wrapRegion(region), nil
102}
103
104func wrapRegion(region *C.cairo_region_t) *Region {
105	return &Region{region}
106}
107
108// newRegionFromNative that handle finalizer.
109func newRegionFromNative(regionNative *C.cairo_region_t) (*Region, error) {
110	ptr := wrapRegion(regionNative)
111	e := ptr.Status().ToError()
112	if e != nil {
113		return nil, e
114	}
115	runtime.SetFinalizer(ptr, (*Region).destroy)
116	return ptr, nil
117}
118
119// RegionCreate is a wrapper around cairo_region_create().
120func RegionCreate() (*Region, error) {
121
122	return newRegionFromNative(C.cairo_region_create())
123}
124
125// CreateRectangle is a wrapper around cairo_region_create_rectangle().
126func (v *Region) CreateRectangle(rectangle *Rectangle) (*Region, error) {
127
128	return newRegionFromNative(C.cairo_region_create_rectangle(
129		rectangle.native()))
130}
131
132// CreateRectangles is a wrapper around cairo_region_create_rectangles().
133func (v *Region) CreateRectangles(rectangles ...*Rectangle) (*Region, error) {
134
135	length := len(rectangles)
136
137	cRectangles := make([]C.cairo_rectangle_int_t, length)
138
139	for i := 0; i < length; i++ {
140		cRectangles[i] = *rectangles[i].native()
141	}
142
143	pRect := &cRectangles[0]
144
145	return newRegionFromNative(
146		C.cairo_region_create_rectangles(
147			pRect,
148			C.int(length)))
149}
150
151// Copy is a wrapper around cairo_region_copy().
152func (v *Region) Copy() (*Region, error) {
153
154	return newRegionFromNative(C.cairo_region_copy(v.native()))
155}
156
157// reference is a wrapper around cairo_region_reference().
158func (v *Region) reference() {
159	v.region = C.cairo_region_reference(v.native())
160}
161
162// destroy is a wrapper around cairo_region_destroy().
163func (v *Region) destroy() {
164	C.cairo_region_destroy(v.native())
165}
166
167// Status is a wrapper around cairo_region_status().
168func (v *Region) Status() Status {
169	c := C.cairo_region_status(v.native())
170	return Status(c)
171}
172
173// GetExtents is a wrapper around cairo_region_get_extents().
174func (v *Region) GetExtents(extents *Rectangle) {
175
176	C.cairo_region_get_extents(v.native(), extents.native())
177}
178
179// NumRectangles is a wrapper around cairo_region_num_rectangles().
180func (v *Region) NumRectangles() int {
181
182	return int(C.cairo_region_num_rectangles(v.native()))
183}
184
185// GetRectangle is a wrapper around cairo_region_get_rectangle().
186func (v *Region) GetRectangle(nth int) *Rectangle {
187
188	cr := new(C.cairo_rectangle_int_t)
189	C.cairo_region_get_rectangle(v.native(), C.int(nth), cr)
190
191	return toRectangle(cr)
192}
193
194// IsEmpty is a wrapper around cairo_region_is_empty().
195func (v *Region) IsEmpty() bool {
196
197	return gobool(C.cairo_region_is_empty(v.native()))
198}
199
200// ContainsPoint is a wrapper around cairo_region_contains_point().
201func (v *Region) ContainsPoint(x, y int) bool {
202
203	return gobool(C.cairo_region_contains_point(
204		v.native(), C.int(x), C.int(y)))
205}
206
207// ContainsRectangle is a wrapper around cairo_region_contains_rectangle().
208func (v *Region) ContainsRectangle(rectangle *Rectangle) RegionOverlap {
209
210	return RegionOverlap(
211		C.cairo_region_contains_rectangle(
212			v.native(), rectangle.native()))
213}
214
215// Equal is a wrapper around cairo_region_equal().
216func (v *Region) Equal(region *Region) bool {
217
218	return gobool(C.cairo_region_equal(v.native(), region.native()))
219}
220
221// Translate is a wrapper around cairo_region_translate().
222func (v *Region) Translate(dx, dy int) {
223
224	C.cairo_region_translate(v.native(), C.int(dx), C.int(dy))
225}
226
227// Intersect is a wrapper around cairo_region_intersect().
228// Note: contrary to the original statement, the source
229// 'Region' remains preserved.
230func (v *Region) Intersect(other *Region) (*Region, error) {
231
232	dst, err := v.Copy()
233	if err != nil {
234		return nil, err
235	}
236	err = Status(
237		C.cairo_region_intersect(
238			dst.native(),
239			other.native())).ToError()
240	if err != nil {
241		return nil, err
242	}
243
244	return dst, nil
245}
246
247// IntersectRectangle is a wrapper around cairo_region_intersect_rectangle().
248// Note: contrary to the original statement, the source 'Region' remains preserved.
249func (v *Region) IntersectRectangle(rectangle *Rectangle) (*Region, error) {
250
251	dst, err := v.Copy()
252	if err != nil {
253		return nil, err
254	}
255	err = Status(
256		C.cairo_region_intersect_rectangle(
257			dst.native(),
258			rectangle.native())).ToError()
259	if err != nil {
260		return nil, err
261	}
262
263	return dst, nil
264}
265
266// Substract is a wrapper around cairo_region_subtract().
267// Note: contrary to the original statement, the source
268// 'Region' remains preserved.
269func (v *Region) Substract(other *Region) (*Region, error) {
270
271	dst, err := v.Copy()
272	if err != nil {
273		return nil, err
274	}
275	err = Status(
276		C.cairo_region_subtract(
277			dst.native(),
278			other.native())).ToError()
279	if err != nil {
280		return nil, err
281	}
282
283	return dst, nil
284}
285
286// SubstractRectangle is a wrapper around cairo_region_subtract_rectangle().
287// Note: contrary to the original statement, the source 'Region' remains preserved.
288func (v *Region) SubstractRectangle(rectangle *Rectangle) (*Region, error) {
289
290	dst, err := v.Copy()
291	if err != nil {
292		return nil, err
293	}
294	err = Status(
295		C.cairo_region_subtract_rectangle(
296			dst.native(),
297			rectangle.native())).ToError()
298	if err != nil {
299		return nil, err
300	}
301
302	return dst, nil
303}
304
305// Union is a wrapper around cairo_region_union().
306// Note: contrary to the original statement, the source
307// 'Region' remains preserved.
308func (v *Region) Union(other *Region) (*Region, error) {
309
310	dst, err := v.Copy()
311	if err != nil {
312		return nil, err
313	}
314	err = Status(
315		C.cairo_region_union(
316			dst.native(),
317			other.native())).ToError()
318	if err != nil {
319		return nil, err
320	}
321
322	return dst, nil
323}
324
325// UnionRectangle is a wrapper around cairo_region_union_rectangle().
326// Note: contrary to the original statement, the source 'Region' remains preserved.
327func (v *Region) UnionRectangle(rectangle *Rectangle) (*Region, error) {
328
329	dst, err := v.Copy()
330	if err != nil {
331		return nil, err
332	}
333	err = Status(
334		C.cairo_region_union_rectangle(
335			dst.native(),
336			rectangle.native())).ToError()
337	if err != nil {
338		return nil, err
339	}
340
341	return dst, nil
342}
343
344// Xor is a wrapper around cairo_region_xor().
345// Note: contrary to the original statement, the source
346// 'Region' remains preserved.
347func (v *Region) Xor(other *Region) (*Region, error) {
348
349	dst, err := v.Copy()
350	if err != nil {
351		return nil, err
352	}
353	err = Status(
354		C.cairo_region_xor(
355			dst.native(),
356			other.native())).ToError()
357	if err != nil {
358		return nil, err
359	}
360
361	return dst, nil
362}
363
364// XorRectangle is a wrapper around cairo_region_xor_rectangle().
365// Note: contrary to the original statement, the source 'Region' remains preserved.
366func (v *Region) XorRectangle(rectangle *Rectangle) (*Region, error) {
367
368	dst, err := v.Copy()
369	if err != nil {
370		return nil, err
371	}
372	err = Status(
373		C.cairo_region_xor_rectangle(
374			dst.native(),
375			rectangle.native())).ToError()
376	if err != nil {
377		return nil, err
378	}
379
380	return dst, nil
381}
382