1import cairo
2import pytest
3import ctypes
4import platform
5
6
7@pytest.fixture
8def context():
9    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 42, 42)
10    return cairo.Context(surface)
11
12
13@pytest.mark.skipif(not hasattr(cairo.Context, "tag_begin"),
14                    reason="too old cairo")
15def test_tags(context):
16    context.tag_begin("foo", "bar=quux")
17    context.tag_end("foo")
18
19
20def test_cmp_hash(context):
21    other = cairo.Context(context.get_target())
22    assert context != other
23    hash(context)
24
25
26def test_get_antialias(context):
27    assert context.get_antialias() == cairo.Antialias.DEFAULT
28    assert isinstance(context.get_antialias(), cairo.Antialias)
29
30
31def test_get_fill_rule(context):
32    assert context.get_fill_rule() == cairo.FillRule.WINDING
33    assert isinstance(context.get_fill_rule(), cairo.FillRule)
34
35
36def test_get_line_cap(context):
37    assert context.get_line_cap() == cairo.LineCap.BUTT
38    assert isinstance(context.get_line_cap(), cairo.LineCap)
39
40
41def test_get_line_join(context):
42    assert context.get_line_join() == cairo.LineJoin.MITER
43    assert isinstance(context.get_line_join(), cairo.LineJoin)
44
45
46def test_get_operator(context):
47    assert context.get_operator() == cairo.Operator.OVER
48    assert isinstance(context.get_operator(), cairo.Operator)
49
50
51def test_get_set_operator_limits(context):
52    max_int = 2 ** (ctypes.sizeof(ctypes.c_int()) * 8 - 1) - 1
53    min_int = -max_int - 1
54
55    for val in [-1, 0, max_int, min_int]:
56        context.set_operator(val)
57        assert context.get_operator() == val
58
59
60# https://bitbucket.org/pypy/pypy/issues/2741
61@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
62def test_show_text_glyphs():
63    surface = cairo.PDFSurface(None, 300, 300)
64    context = cairo.Context(surface)
65    context.scale(300, 300)
66    context.select_font_face("Sans", cairo.FONT_SLANT_NORMAL,
67                             cairo.FONT_WEIGHT_NORMAL)
68    context.set_font_size(0.08)
69    context.set_line_width(0.09)
70    sf = context.get_scaled_font()
71    glyphs, clusters, flags = sf.text_to_glyphs(0.5, 0.5, "foobar")
72    context.show_text_glyphs("foobar", glyphs, clusters, flags)
73
74    glyphs, clusters, flags = sf.text_to_glyphs(0.5, 0.5, "")
75    context.show_text_glyphs("", glyphs, clusters, flags)
76
77    with pytest.raises(TypeError):
78        context.show_text_glyphs(object(), glyphs, clusters, flags)
79
80    with pytest.raises(TypeError):
81        context.show_text_glyphs("", [object()], clusters, flags)
82
83    with pytest.raises(TypeError):
84        context.show_text_glyphs("", object(), clusters, flags)
85
86    with pytest.raises(TypeError):
87        context.show_text_glyphs("", glyphs, [object()], flags)
88
89    with pytest.raises(TypeError):
90        context.show_text_glyphs("", glyphs, object(), flags)
91
92
93def test_append_path(context):
94    context.line_to(1, 2)
95    p = context.copy_path()
96    context.new_path()
97    context.append_path(p)
98    assert str(context.copy_path()) == str(p)
99    with pytest.raises(TypeError):
100        context.append_path(object())
101
102
103def test_arc(context):
104    assert not list(context.copy_path())
105    context.arc(0, 0, 0, 0, 0)
106    assert list(context.copy_path())
107    with pytest.raises(TypeError):
108        context.arc(object())
109
110
111def test_arc_negative(context):
112    assert not list(context.copy_path())
113    context.arc_negative(0, 0, 0, 0, 0)
114    assert list(context.copy_path())
115    with pytest.raises(TypeError):
116        context.arc_negative(object())
117
118
119def test_clip_extents(context):
120    assert context.clip_extents() == (0.0, 0.0, 42.0, 42.0)
121
122
123def test_in_clip():
124    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
125    context = cairo.Context(surface)
126    assert context.in_clip(50, 50)
127    context.clip()
128    assert not context.in_clip(50, 50)
129    context.reset_clip()
130    assert context.in_clip(50, 50)
131
132    with pytest.raises(TypeError):
133        context.in_clip(None, None)
134
135
136def test_device_to_user(context):
137    assert context.device_to_user(0, 0) == (0, 0)
138    with pytest.raises(TypeError):
139        context.device_to_user(None, None)
140
141
142def test_device_to_user_distance(context):
143    assert context.device_to_user_distance(0, 0) == (0, 0)
144    with pytest.raises(TypeError):
145        context.device_to_user_distance(None, None)
146
147
148def test_fill_extents(context):
149    context.line_to(1, 1)
150    context.line_to(1, 0)
151    context.line_to(0, 0)
152    context.line_to(0, 1)
153    context.line_to(1, 1)
154    assert context.fill_extents() == (0, 0, 1, 1)
155
156
157def test_curve_to(context):
158    with pytest.raises(TypeError):
159        context.curve_to(1, 2, 3, 4, 5, object())
160
161
162def test_set_get_dash(context):
163    assert context.get_dash() == ((), 0)
164    assert context.get_dash_count() == 0
165
166    context.set_dash([0, 1, 2, 3], 10)
167    assert context.get_dash() == ((0.0, 1.0, 2.0, 3.0), 4.0)
168    assert context.get_dash_count() == 4
169
170    with pytest.raises(TypeError):
171        context.set_dash()
172
173    with pytest.raises(TypeError):
174        context.set_dash(1, 10)
175
176    with pytest.raises(TypeError):
177        context.set_dash([object()], 1)
178
179
180def test_glyph_extents(context):
181    with pytest.raises(TypeError):
182        context.glyph_extents(None)
183    with pytest.raises(TypeError):
184        context.glyph_extents()
185
186
187def test_glyph_path(context):
188    with pytest.raises(TypeError):
189        context.glyph_path(None)
190    with pytest.raises(TypeError):
191        context.glyph_path()
192
193
194def test_in_stroke(context):
195    context.line_to(0, 0)
196    context.line_to(1, 1)
197    assert context.in_stroke(0, 0)
198    assert not context.in_stroke(0, 2)
199    with pytest.raises(TypeError):
200        context.in_stroke(object(), 0)
201
202
203def test_current_point(context):
204    assert not context.has_current_point()
205    assert context.get_current_point() == (0, 0)
206    context.move_to(10, 10)
207    assert context.has_current_point()
208    assert context.get_current_point() == (10, 10)
209
210
211def test_in_fill(context):
212    assert not context.in_fill(0.1, 0.1)
213    with pytest.raises(TypeError):
214        context.in_fill(0.1, object())
215
216
217def test_line_to(context):
218    with pytest.raises(TypeError):
219        context.line_to(0.1, object())
220
221
222def test_mask(context):
223    pattern = cairo.SolidPattern(0, 0, 0)
224    context.mask(pattern)
225    with pytest.raises(TypeError):
226        context.mask(object())
227
228
229def test_mask_surface(context):
230    context.mask_surface(context.get_target(), 0, 0)
231    with pytest.raises(TypeError):
232        context.mask_surface(object(), 0, 0)
233
234
235def test_paint_with_alpha(context):
236    context.paint_with_alpha(0.5)
237    with pytest.raises(TypeError):
238        context.paint_with_alpha(object())
239
240
241def test_path_extents(context):
242    context.line_to(1, 1)
243    context.line_to(1, 0)
244    context.line_to(0, 0)
245    context.line_to(0, 1)
246    context.line_to(1, 1)
247    assert context.path_extents() == (0.0, 0.0, 1.0, 1.0)
248
249
250def test_push_pop_group(context):
251    context.push_group()
252    context.pop_group()
253
254    context.push_group()
255    context.pop_group_to_source()
256
257    with pytest.raises(TypeError):
258        context.push_group_with_content(object())
259
260    context.push_group_with_content(cairo.Content.COLOR)
261    context.pop_group()
262
263    with pytest.raises(cairo.Error):
264        context.pop_group()
265
266
267def test_rectangle(context):
268    context.rectangle(1, 2, 4, 5)
269    assert context.path_extents() == (1.0, 2.0, 5.0, 7.0)
270    with pytest.raises(TypeError):
271        context.rectangle(1, 2, 3, object())
272
273
274def test_rotate(context):
275    context.rotate(0.3)
276    with pytest.raises(TypeError):
277        context.rotate(object())
278
279
280def test_rel_curve_to(context):
281    context.line_to(0, 0)
282    context.rel_curve_to(0, 0, 0, 0, 0, 0)
283    with pytest.raises(TypeError):
284        context.rel_curve_to(object(), 0, 0, 0, 0, 0)
285
286
287def test_move_to(context):
288    context.move_to(10, 10)
289    assert context.get_current_point() == (10, 10)
290    with pytest.raises(TypeError):
291        context.move_to(object(), 0)
292
293
294def test_rel_line_to(context):
295    context.line_to(0, 0)
296    context.rel_line_to(1, 1)
297    with pytest.raises(TypeError):
298        context.rel_line_to(object(), 0)
299
300
301def test_rel_move_to(context):
302    context.line_to(0, 0)
303    context.rel_move_to(1, 1)
304    with pytest.raises(TypeError):
305        context.rel_move_to(object(), 0)
306
307
308def test_save_restore(context):
309    context.save()
310    context.restore()
311
312
313def test_scale(context):
314    context.scale(2, 2)
315    with pytest.raises(TypeError):
316        context.scale(object(), 0)
317
318
319# https://bitbucket.org/pypy/pypy/issues/2741
320@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
321def test_select_font_face(context):
322    context.select_font_face("")
323    with pytest.raises(TypeError):
324        context.select_font_face(None)
325
326
327def test_set_antialias(context):
328    context.set_antialias(cairo.Antialias.SUBPIXEL)
329    assert context.get_antialias() == cairo.Antialias.SUBPIXEL
330    with pytest.raises(TypeError):
331        context.set_antialias(object())
332
333
334def test_set_fill_rule(context):
335    context.set_fill_rule(cairo.FillRule.EVEN_ODD)
336    assert context.get_fill_rule() == cairo.FillRule.EVEN_ODD
337    with pytest.raises(TypeError):
338        context.set_fill_rule(object())
339
340
341def test_set_font_face(context):
342    assert context.get_font_face()
343    context.set_font_face(None)
344    assert context.get_font_face()
345    ff = context.get_font_face()
346    context.set_font_face(ff)
347    assert context.get_font_face() == ff
348    with pytest.raises(TypeError):
349        context.set_font_face(object())
350
351
352def test_set_font_matrix(context):
353    m = cairo.Matrix()
354    context.set_font_matrix(m)
355    assert context.get_font_matrix() == m
356    with pytest.raises(TypeError):
357        context.set_font_matrix(object())
358
359
360def test_set_line_cap(context):
361    context.set_line_cap(cairo.LineCap.SQUARE)
362    assert context.get_line_cap() == cairo.LineCap.SQUARE
363    with pytest.raises(TypeError):
364        context.set_line_cap(object())
365
366
367def test_set_line_join(context):
368    context.set_line_join(cairo.LineJoin.BEVEL)
369    assert context.get_line_join() == cairo.LineJoin.BEVEL
370    with pytest.raises(TypeError):
371        context.set_line_join(object())
372
373
374def test_set_line_width(context):
375    context.set_line_width(42)
376    assert context.get_line_width() == 42
377    with pytest.raises(TypeError):
378        context.set_line_width(object())
379
380
381def test_set_matrix(context):
382    m = cairo.Matrix()
383    context.set_matrix(m)
384    assert context.get_matrix() == m
385    with pytest.raises(TypeError):
386        context.set_matrix(object())
387
388
389def test_set_miter_limit(context):
390    context.set_miter_limit(42)
391    assert context.get_miter_limit() == 42
392    with pytest.raises(TypeError):
393        context.set_miter_limit(object())
394
395
396def test_set_scaled_font(context):
397    context.set_scaled_font(context.get_scaled_font())
398    with pytest.raises(TypeError):
399        context.set_scaled_font(object())
400
401
402def test_set_font_options(context):
403    context.set_font_options(context.get_font_options())
404    with pytest.raises(TypeError):
405        context.set_font_options(object())
406
407
408def test_set_font_size(context):
409    context.set_font_size(42)
410    assert context.get_font_matrix() == cairo.Matrix(42, 0, 0, 42, 0, 0)
411    with pytest.raises(TypeError):
412        context.set_font_size(object())
413
414
415def test_set_source(context):
416    p = cairo.SolidPattern(0, 0, 0)
417    context.set_source(p)
418    assert context.get_source() == p
419    with pytest.raises(TypeError):
420        context.set_source(object())
421
422
423def test_set_source_rgb(context):
424    with pytest.raises(TypeError):
425        context.set_source_rgb(1, 1, object())
426
427
428def test_get_source_rgba(context):
429    context.set_source_rgba(1, 1, 1)
430    assert context.get_source().get_rgba() == (1, 1, 1, 1)
431    context.set_source_rgba(1, 1, 1, 0.5)
432    assert context.get_source().get_rgba() == (1, 1, 1, 0.5)
433    with pytest.raises(TypeError):
434        context.set_source_rgba(1, 1, object())
435
436
437def test_set_source_surface(context):
438    with pytest.raises(TypeError):
439        context.set_source_surface(object())
440
441
442def test_set_tolerance(context):
443    context.set_tolerance(42)
444    assert context.get_tolerance() == 42
445    with pytest.raises(TypeError):
446        context.set_tolerance(object())
447
448
449def test_show_glyphs(context):
450    with pytest.raises(TypeError):
451        context.show_glyphs()
452
453    with pytest.raises(TypeError):
454        context.show_glyphs(object())
455
456    context.show_glyphs([], 0)
457
458
459def test_show_text(context):
460    with pytest.raises(TypeError):
461        context.show_text()
462
463
464def test_stroke_extents(context):
465    assert context.stroke_extents() == (0.0, 0.0, 0.0, 0.0)
466
467
468def test_text_extents(context):
469    with pytest.raises(TypeError):
470        context.text_extents()
471
472
473# https://bitbucket.org/pypy/pypy/issues/2741
474@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="PyPy")
475def test_text_path(context):
476    context.text_path("foo")
477    with pytest.raises(TypeError):
478        context.text_path(object())
479
480
481def test_transform(context):
482    context.transform(cairo.Matrix())
483    with pytest.raises(TypeError):
484        context.transform(object())
485
486
487def test_translate(context):
488    context.translate(0.5, 0.5)
489    with pytest.raises(TypeError):
490        context.translate(0.5, object())
491
492
493def test_user_to_device(context):
494    assert context.user_to_device(0, 0) == (0, 0)
495    with pytest.raises(TypeError):
496        context.user_to_device(0, object())
497
498
499def test_user_to_device_distance(context):
500    assert context.user_to_device_distance(0, 0) == (0, 0)
501    with pytest.raises(TypeError):
502        context.user_to_device_distance(0, object())
503
504
505def test_context(context):
506    with pytest.raises(TypeError):
507        cairo.Context(None)
508
509    assert not context == object()
510
511
512def test_simple(context):
513    context.clip_preserve()
514    context.copy_page()
515    context.copy_path_flat()
516    context.fill()
517    context.fill_preserve()
518    context.font_extents()
519    context.identity_matrix()
520    context.new_sub_path()
521    context.show_page()
522    context.stroke_preserve()
523
524    assert context.get_dash_count() == 0
525    assert isinstance(context.get_font_matrix(), cairo.Matrix)
526
527    assert context.get_group_target()
528    context.get_line_width()
529
530    assert isinstance(context.get_tolerance(), float)
531    assert isinstance(context.get_miter_limit(), float)
532    assert isinstance(context.get_matrix(), cairo.Matrix)
533