1 | #!/usr/bin/python |
---|
2 | |
---|
3 | from __future__ import division |
---|
4 | import gtk |
---|
5 | import cairo |
---|
6 | import math |
---|
7 | |
---|
8 | IDENTITY = 0 |
---|
9 | ROTATE_90 = 1 |
---|
10 | SCALE = 2 |
---|
11 | ROTATE = 3 |
---|
12 | |
---|
13 | TRANSFORMS = [ |
---|
14 | IDENTITY, |
---|
15 | ROTATE_90, |
---|
16 | SCALE, |
---|
17 | ROTATE |
---|
18 | ] |
---|
19 | |
---|
20 | SOURCE_ALPHAS = [ False, True ] |
---|
21 | |
---|
22 | FILTERS = [ cairo.FILTER_NEAREST, cairo.FILTER_BILINEAR ] |
---|
23 | |
---|
24 | SOURCE_SIZE = 16 |
---|
25 | DEST_SIZE = 100 |
---|
26 | PAD = 10 |
---|
27 | |
---|
28 | TOTAL_SIZE = 4 * (DEST_SIZE + PAD) + PAD |
---|
29 | |
---|
30 | transform = None |
---|
31 | source_alpha = None |
---|
32 | source_filter = None |
---|
33 | |
---|
34 | def draw_sample(cr, x, y, transform, filter, source_alpha): |
---|
35 | cr.save() |
---|
36 | cr.translate(x, y) |
---|
37 | cr.rectangle(0, 0, DEST_SIZE, DEST_SIZE) |
---|
38 | cr.clip() |
---|
39 | |
---|
40 | if source_alpha: |
---|
41 | source = cairo.ImageSurface(cairo.FORMAT_ARGB32, SOURCE_SIZE, SOURCE_SIZE) |
---|
42 | else: |
---|
43 | source = cairo.ImageSurface(cairo.FORMAT_RGB24, SOURCE_SIZE, SOURCE_SIZE) |
---|
44 | |
---|
45 | source_cr = cairo.Context(source) |
---|
46 | source_cr.set_source_rgba(0, 0, 1) |
---|
47 | source_cr.paint() |
---|
48 | |
---|
49 | hole_x = hole_y = SOURCE_SIZE // 4 |
---|
50 | hole_width = hole_height = SOURCE_SIZE // 2 |
---|
51 | |
---|
52 | # Add some rectangles on the source image at the corners |
---|
53 | source_cr.rectangle(0, 0, hole_x, hole_y) |
---|
54 | source_cr.rectangle(hole_x + hole_width, 0, SOURCE_SIZE - (hole_x + hole_width), hole_y) |
---|
55 | source_cr.rectangle(0, hole_y + hole_height, hole_x, SOURCE_SIZE - (hole_y + hole_height)) |
---|
56 | source_cr.rectangle(hole_x + hole_width, hole_y + hole_height, SOURCE_SIZE - (hole_x + hole_width), SOURCE_SIZE - (hole_y + hole_height)) |
---|
57 | source_cr.set_source_rgba(0, 1, 0) |
---|
58 | source_cr.fill() |
---|
59 | |
---|
60 | if source_alpha: |
---|
61 | # Cut a whole out of the middle |
---|
62 | source_cr.set_operator(cairo.OPERATOR_DEST_OUT) |
---|
63 | source_cr.rectangle(hole_x, hole_y, hole_width, hole_height) |
---|
64 | source_cr.set_source_rgba(1, 1, 1) |
---|
65 | source_cr.fill() |
---|
66 | |
---|
67 | cr.translate(DEST_SIZE // 2, DEST_SIZE // 2) |
---|
68 | |
---|
69 | if transform == IDENTITY: |
---|
70 | pass |
---|
71 | elif transform == ROTATE_90: |
---|
72 | cr.rotate(math.pi / 2) |
---|
73 | elif transform == SCALE: |
---|
74 | cr.scale(11/3, 11/3) |
---|
75 | elif transform == ROTATE: |
---|
76 | cr.rotate(math.pi / 3) |
---|
77 | cr.scale(11/3, 11/3) |
---|
78 | |
---|
79 | cr.translate(- SOURCE_SIZE // 2, - SOURCE_SIZE // 2) |
---|
80 | |
---|
81 | # # Draw a shape in red under the bounds of the surface |
---|
82 | |
---|
83 | # cr.move_to(0, 0) |
---|
84 | # cr.line_to(SOURCE_SIZE, 0) |
---|
85 | # cr.line_to(SOURCE_SIZE, SOURCE_SIZE) |
---|
86 | # cr.line_to(0, SOURCE_SIZE) |
---|
87 | # cr.close_path() |
---|
88 | |
---|
89 | # if source_alpha: |
---|
90 | # # Cut the hole out of the shape |
---|
91 | # cr.move_to(hole_x, hole_y) |
---|
92 | # cr.line_to(hole_x, hole_y + hole_height) |
---|
93 | # cr.line_to(hole_x + hole_height, hole_y + hole_height) |
---|
94 | # cr.line_to(hole_x + hole_height, hole_y) |
---|
95 | # cr.close_path() |
---|
96 | |
---|
97 | # cr.set_source_rgba(1, 0, 0) |
---|
98 | # cr.fill() |
---|
99 | |
---|
100 | # Draw the transformed surface |
---|
101 | |
---|
102 | cr.set_source_surface(source) |
---|
103 | cr.get_source().set_filter(filter) |
---|
104 | # cr.set_operator(cairo.OPERATOR_SOURCE) |
---|
105 | cr.paint() |
---|
106 | |
---|
107 | cr.restore() |
---|
108 | |
---|
109 | def draw(cr): |
---|
110 | cr.set_source_rgba(1, 1, 1) |
---|
111 | cr.paint() |
---|
112 | |
---|
113 | y = PAD |
---|
114 | for source_alpha in SOURCE_ALPHAS: |
---|
115 | for filter in FILTERS: |
---|
116 | x = PAD |
---|
117 | for transform in TRANSFORMS: |
---|
118 | draw_sample(cr, x, y, transform, filter, source_alpha) |
---|
119 | x += DEST_SIZE + PAD |
---|
120 | y += DEST_SIZE + PAD |
---|
121 | |
---|
122 | def on_expose(widget, event): |
---|
123 | cr = widget.window.cairo_create() |
---|
124 | draw(cr) |
---|
125 | |
---|
126 | def dump_image(): |
---|
127 | width, height = w.size_request() |
---|
128 | surface = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height) |
---|
129 | cr = cairo.Context(surface) |
---|
130 | draw(cr) |
---|
131 | surface.write_to_png("/tmp/test-repeat-none-image.png") |
---|
132 | |
---|
133 | def dump_pixmap(): |
---|
134 | cmap = gtk.gdk.screen_get_default().get_rgb_colormap() |
---|
135 | out = gtk.gdk.Pixmap(None, TOTAL_SIZE, TOTAL_SIZE, cmap.get_visual().depth) |
---|
136 | out.set_colormap(cmap) |
---|
137 | cr = out.cairo_create() |
---|
138 | draw(cr) |
---|
139 | cr.get_target().write_to_png("/tmp/test-repeat-none-pixmap.png") |
---|
140 | |
---|
141 | def reset(): |
---|
142 | w.set_size_request(TOTAL_SIZE, TOTAL_SIZE) |
---|
143 | w.queue_draw() |
---|
144 | |
---|
145 | def on_key_press(widget, event): |
---|
146 | if event.keyval in (gtk.keysyms.d, gtk.keysyms.D): |
---|
147 | dump_image() |
---|
148 | return True |
---|
149 | if event.keyval in (gtk.keysyms.p, gtk.keysyms.P): |
---|
150 | dump_pixmap() |
---|
151 | return True |
---|
152 | elif event.keyval in (gtk.keysyms.r, gtk.keysyms.R): |
---|
153 | reset() |
---|
154 | return True |
---|
155 | elif event.keyval in (gtk.keysyms.q, gtk.keysyms.Q): |
---|
156 | gtk.main_quit() |
---|
157 | return True |
---|
158 | elif event.keyval in (gtk.keysyms.Escape,): |
---|
159 | transform = None |
---|
160 | source_alpha = None |
---|
161 | filter = None |
---|
162 | reset() |
---|
163 | return True |
---|
164 | |
---|
165 | return False |
---|
166 | |
---|
167 | w = gtk.Window() |
---|
168 | w.set_app_paintable(True) |
---|
169 | w.set_resizable(False) |
---|
170 | |
---|
171 | reset() |
---|
172 | |
---|
173 | w.connect('expose-event', on_expose) |
---|
174 | w.connect('key-press-event', on_key_press) |
---|
175 | |
---|
176 | w.show() |
---|
177 | gtk.main() |
---|