0
# Patterns
1
2
Pattern classes define the paint sources used in Cairo drawing operations. Patterns determine how areas are colored when filling shapes or stroking paths. Cairo supports solid colors, gradients, surface-based patterns, and advanced patterns like mesh gradients. All patterns can be transformed and have different extend modes for tiling behavior.
3
4
## Capabilities
5
6
### Base Pattern Class
7
8
```python { .api }
9
class Pattern:
10
def get_extend(self) -> Extend:
11
"""Get extend mode for pattern."""
12
13
def set_extend(self, extend: Extend) -> None:
14
"""Set extend mode (NONE, REPEAT, REFLECT, PAD)."""
15
16
def get_filter(self) -> Filter:
17
"""Get filter mode for pattern scaling."""
18
19
def set_filter(self, filter: Filter) -> None:
20
"""Set filter mode (FAST, GOOD, BEST, NEAREST, BILINEAR, GAUSSIAN)."""
21
22
def get_matrix(self) -> Matrix:
23
"""Get transformation matrix for pattern."""
24
25
def set_matrix(self, matrix: Matrix) -> None:
26
"""Set transformation matrix for pattern."""
27
28
def get_color_stop_count(self) -> int:
29
"""Get number of color stops in gradient pattern."""
30
31
def get_color_stop_rgba(self, index: int) -> tuple[float, float, float, float, float]:
32
"""Get color stop at index (offset, red, green, blue, alpha)."""
33
34
def get_rgba(self) -> tuple[float, float, float, float]:
35
"""Get RGBA values for solid pattern."""
36
37
def get_surface(self) -> Surface:
38
"""Get surface for surface pattern."""
39
```
40
41
### Solid Color Patterns
42
43
```python { .api }
44
class SolidPattern(Pattern):
45
def __init__(self, red: float, green: float, blue: float, alpha: float = 1.0) -> None:
46
"""Create solid color pattern.
47
48
Args:
49
red: Red component (0.0 to 1.0)
50
green: Green component (0.0 to 1.0)
51
blue: Blue component (0.0 to 1.0)
52
alpha: Alpha component (0.0 to 1.0)
53
"""
54
```
55
56
### Surface Patterns
57
58
```python { .api }
59
class SurfacePattern(Pattern):
60
def __init__(self, surface: Surface) -> None:
61
"""Create pattern from surface.
62
63
Args:
64
surface: Source surface for pattern
65
"""
66
```
67
68
### Gradient Patterns
69
70
```python { .api }
71
class Gradient(Pattern):
72
def add_color_stop_rgb(self, offset: float, red: float, green: float, blue: float) -> None:
73
"""Add RGB color stop to gradient.
74
75
Args:
76
offset: Position along gradient (0.0 to 1.0)
77
red: Red component (0.0 to 1.0)
78
green: Green component (0.0 to 1.0)
79
blue: Blue component (0.0 to 1.0)
80
"""
81
82
def add_color_stop_rgba(self, offset: float, red: float, green: float, blue: float, alpha: float) -> None:
83
"""Add RGBA color stop to gradient.
84
85
Args:
86
offset: Position along gradient (0.0 to 1.0)
87
red: Red component (0.0 to 1.0)
88
green: Green component (0.0 to 1.0)
89
blue: Blue component (0.0 to 1.0)
90
alpha: Alpha component (0.0 to 1.0)
91
"""
92
93
class LinearGradient(Gradient):
94
def __init__(self, x0: float, y0: float, x1: float, y1: float) -> None:
95
"""Create linear gradient between two points.
96
97
Args:
98
x0: X coordinate of start point
99
y0: Y coordinate of start point
100
x1: X coordinate of end point
101
y1: Y coordinate of end point
102
"""
103
104
def get_linear_points(self) -> tuple[float, float, float, float]:
105
"""Get linear gradient endpoints (x0, y0, x1, y1)."""
106
107
class RadialGradient(Gradient):
108
def __init__(self, cx0: float, cy0: float, radius0: float, cx1: float, cy1: float, radius1: float) -> None:
109
"""Create radial gradient between two circles.
110
111
Args:
112
cx0: X coordinate of first circle center
113
cy0: Y coordinate of first circle center
114
radius0: Radius of first circle
115
cx1: X coordinate of second circle center
116
cy1: Y coordinate of second circle center
117
radius1: Radius of second circle
118
"""
119
120
def get_radial_circles(self) -> tuple[float, float, float, float, float, float]:
121
"""Get radial gradient circles (cx0, cy0, radius0, cx1, cy1, radius1)."""
122
```
123
124
### Mesh Patterns
125
126
```python { .api }
127
class MeshPattern(Pattern):
128
def __init__(self) -> None:
129
"""Create empty mesh pattern."""
130
131
def begin_patch(self) -> None:
132
"""Begin new patch in mesh pattern."""
133
134
def end_patch(self) -> None:
135
"""End current patch."""
136
137
def move_to(self, x: float, y: float) -> None:
138
"""Move to point in current patch."""
139
140
def line_to(self, x: float, y: float) -> None:
141
"""Add line to current patch."""
142
143
def curve_to(self, x1: float, y1: float, x2: float, y2: float, x3: float, y3: float) -> None:
144
"""Add curve to current patch."""
145
146
def set_control_point(self, point_num: int, x: float, y: float) -> None:
147
"""Set control point in current patch."""
148
149
def set_corner_color_rgb(self, corner_num: int, red: float, green: float, blue: float) -> None:
150
"""Set RGB color for patch corner."""
151
152
def set_corner_color_rgba(self, corner_num: int, red: float, green: float, blue: float, alpha: float) -> None:
153
"""Set RGBA color for patch corner."""
154
155
def get_patch_count(self) -> int:
156
"""Get number of patches in mesh."""
157
158
def get_path(self, patch_num: int) -> Path:
159
"""Get path for specified patch."""
160
161
def get_control_point(self, patch_num: int, point_num: int) -> tuple[float, float]:
162
"""Get control point for specified patch."""
163
164
def get_corner_color_rgba(self, patch_num: int, corner_num: int) -> tuple[float, float, float, float]:
165
"""Get corner color for specified patch."""
166
```
167
168
### Raster Source Patterns
169
170
```python { .api }
171
class RasterSourcePattern(Pattern):
172
def __init__(self, user_data: Any, content: Content, width: int, height: int) -> None:
173
"""Create raster source pattern with callback functions.
174
175
Args:
176
user_data: User data passed to callback functions
177
content: Content type (COLOR, ALPHA, COLOR_ALPHA)
178
width: Pattern width
179
height: Pattern height
180
"""
181
182
def set_callback_data(self, user_data: Any) -> None:
183
"""Set user data for callback functions."""
184
185
def get_callback_data(self) -> Any:
186
"""Get user data for callback functions."""
187
188
def set_acquire(self, acquire_func: Callable, release_func: Callable) -> None:
189
"""Set acquire and release callback functions."""
190
191
def set_snapshot(self, snapshot_func: Callable) -> None:
192
"""Set snapshot callback function."""
193
194
def set_copy(self, copy_func: Callable) -> None:
195
"""Set copy callback function."""
196
197
def set_finish(self, finish_func: Callable) -> None:
198
"""Set finish callback function."""
199
```
200
201
## Usage Examples
202
203
### Solid Color Patterns
204
205
```python
206
import cairo
207
208
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 400, 300)
209
ctx = cairo.Context(surface)
210
211
# Using set_source_rgb/rgba (creates SolidPattern internally)
212
ctx.set_source_rgb(0.8, 0.2, 0.2)
213
ctx.rectangle(50, 50, 100, 80)
214
ctx.fill()
215
216
# Creating SolidPattern explicitly
217
pattern = cairo.SolidPattern(0.2, 0.2, 0.8, 0.7) # Semi-transparent blue
218
ctx.set_source(pattern)
219
ctx.rectangle(200, 50, 100, 80)
220
ctx.fill()
221
222
surface.write_to_png("solid_patterns.png")
223
```
224
225
### Linear Gradients
226
227
```python
228
import cairo
229
230
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 400, 300)
231
ctx = cairo.Context(surface)
232
233
# Create linear gradient from left to right
234
gradient = cairo.LinearGradient(0, 0, 400, 0)
235
gradient.add_color_stop_rgb(0, 1, 0, 0) # Red at start
236
gradient.add_color_stop_rgb(0.5, 1, 1, 0) # Yellow at middle
237
gradient.add_color_stop_rgb(1, 0, 0, 1) # Blue at end
238
239
ctx.set_source(gradient)
240
ctx.rectangle(0, 0, 400, 300)
241
ctx.fill()
242
243
surface.write_to_png("linear_gradient.png")
244
```
245
246
### Radial Gradients
247
248
```python
249
import cairo
250
251
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 400, 300)
252
ctx = cairo.Context(surface)
253
254
# Create radial gradient from center outward
255
gradient = cairo.RadialGradient(200, 150, 20, 200, 150, 100)
256
gradient.add_color_stop_rgba(0, 1, 1, 1, 1) # White center
257
gradient.add_color_stop_rgba(0.7, 0.8, 0.4, 0.2, 0.8) # Orange
258
gradient.add_color_stop_rgba(1, 0.2, 0.2, 0.2, 0.5) # Dark transparent edge
259
260
ctx.set_source(gradient)
261
ctx.arc(200, 150, 120, 0, 2 * 3.14159)
262
ctx.fill()
263
264
surface.write_to_png("radial_gradient.png")
265
```
266
267
### Surface Patterns
268
269
```python
270
import cairo
271
272
# Create source surface with pattern
273
pattern_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 50, 50)
274
pattern_ctx = cairo.Context(pattern_surface)
275
276
# Draw a simple pattern
277
pattern_ctx.set_source_rgb(0.8, 0.8, 0.9)
278
pattern_ctx.paint()
279
pattern_ctx.set_source_rgb(0.2, 0.4, 0.8)
280
pattern_ctx.rectangle(10, 10, 30, 30)
281
pattern_ctx.fill()
282
283
# Use as pattern with different extend modes
284
main_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 400, 300)
285
ctx = cairo.Context(main_surface)
286
287
pattern = cairo.SurfacePattern(pattern_surface)
288
289
# Repeat pattern
290
pattern.set_extend(cairo.EXTEND_REPEAT)
291
ctx.set_source(pattern)
292
ctx.rectangle(0, 0, 200, 150)
293
ctx.fill()
294
295
# Reflect pattern
296
pattern.set_extend(cairo.EXTEND_REFLECT)
297
ctx.set_source(pattern)
298
ctx.rectangle(200, 0, 200, 150)
299
ctx.fill()
300
301
# Pad pattern
302
pattern.set_extend(cairo.EXTEND_PAD)
303
ctx.set_source(pattern)
304
ctx.rectangle(0, 150, 200, 150)
305
ctx.fill()
306
307
main_surface.write_to_png("surface_patterns.png")
308
```
309
310
### Mesh Gradients
311
312
```python
313
import cairo
314
315
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 400, 300)
316
ctx = cairo.Context(surface)
317
318
# Create mesh pattern
319
mesh = cairo.MeshPattern()
320
321
# First patch - a quadrilateral with different colors at corners
322
mesh.begin_patch()
323
mesh.move_to(100, 100)
324
mesh.line_to(300, 100)
325
mesh.line_to(300, 200)
326
mesh.line_to(100, 200)
327
328
# Set corner colors
329
mesh.set_corner_color_rgb(0, 1, 0, 0) # Red
330
mesh.set_corner_color_rgb(1, 0, 1, 0) # Green
331
mesh.set_corner_color_rgb(2, 0, 0, 1) # Blue
332
mesh.set_corner_color_rgb(3, 1, 1, 0) # Yellow
333
mesh.end_patch()
334
335
# Second patch with curves
336
mesh.begin_patch()
337
mesh.move_to(100, 200)
338
mesh.curve_to(100, 250, 150, 250, 200, 200)
339
mesh.curve_to(250, 250, 300, 250, 300, 200)
340
mesh.line_to(300, 200)
341
mesh.line_to(100, 200)
342
343
mesh.set_corner_color_rgb(0, 1, 1, 0) # Yellow
344
mesh.set_corner_color_rgb(1, 1, 0, 1) # Magenta
345
mesh.set_corner_color_rgb(2, 0, 1, 1) # Cyan
346
mesh.set_corner_color_rgb(3, 1, 0.5, 0) # Orange
347
mesh.end_patch()
348
349
ctx.set_source(mesh)
350
ctx.paint()
351
352
surface.write_to_png("mesh_gradient.png")
353
```
354
355
### Pattern Transformations
356
357
```python
358
import cairo
359
import math
360
361
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 400, 300)
362
ctx = cairo.Context(surface)
363
364
# Create a linear gradient
365
gradient = cairo.LinearGradient(0, 0, 100, 0)
366
gradient.add_color_stop_rgb(0, 1, 0, 0)
367
gradient.add_color_stop_rgb(1, 0, 0, 1)
368
369
# Apply transformation to pattern
370
matrix = cairo.Matrix()
371
matrix.rotate(math.pi / 4) # 45 degree rotation
372
matrix.scale(2, 1) # Scale horizontally
373
gradient.set_matrix(matrix)
374
375
ctx.set_source(gradient)
376
ctx.rectangle(50, 50, 300, 200)
377
ctx.fill()
378
379
surface.write_to_png("transformed_pattern.png")
380
```
381
382
### Pattern Filtering and Extending
383
384
```python
385
import cairo
386
387
# Create small pattern surface
388
pattern_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 20, 20)
389
pattern_ctx = cairo.Context(pattern_surface)
390
pattern_ctx.set_source_rgb(0.8, 0.2, 0.2)
391
pattern_ctx.arc(10, 10, 8, 0, 2 * 3.14159)
392
pattern_ctx.fill()
393
394
# Main surface
395
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 400, 300)
396
ctx = cairo.Context(surface)
397
398
pattern = cairo.SurfacePattern(pattern_surface)
399
400
# Test different filter modes
401
ctx.save()
402
pattern.set_filter(cairo.FILTER_NEAREST)
403
pattern.set_extend(cairo.EXTEND_REPEAT)
404
ctx.set_source(pattern)
405
ctx.rectangle(0, 0, 200, 150)
406
ctx.fill()
407
ctx.restore()
408
409
ctx.save()
410
pattern.set_filter(cairo.FILTER_BILINEAR)
411
ctx.set_source(pattern)
412
ctx.rectangle(200, 0, 200, 150)
413
ctx.fill()
414
ctx.restore()
415
416
# Scale pattern up to see filtering effects
417
matrix = cairo.Matrix()
418
matrix.scale(0.5, 0.5) # Make pattern twice as large
419
pattern.set_matrix(matrix)
420
421
ctx.save()
422
pattern.set_filter(cairo.FILTER_NEAREST)
423
ctx.set_source(pattern)
424
ctx.rectangle(0, 150, 200, 150)
425
ctx.fill()
426
ctx.restore()
427
428
ctx.save()
429
pattern.set_filter(cairo.FILTER_BILINEAR)
430
ctx.set_source(pattern)
431
ctx.rectangle(200, 150, 200, 150)
432
ctx.fill()
433
ctx.restore()
434
435
surface.write_to_png("pattern_filtering.png")
436
```