Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1892 | serge | 1 | /* cairo - a vector graphics library with display and print output |
2 | * |
||
3 | * Copyright © 2005 Red Hat, Inc |
||
4 | * Copyright © 2007 Adrian Johnson |
||
5 | * Copyright © 2009 Chris Wilson |
||
6 | * |
||
7 | * This library is free software; you can redistribute it and/or |
||
8 | * modify it either under the terms of the GNU Lesser General Public |
||
9 | * License version 2.1 as published by the Free Software Foundation |
||
10 | * (the "LGPL") or, at your option, under the terms of the Mozilla |
||
11 | * Public License Version 1.1 (the "MPL"). If you do not alter this |
||
12 | * notice, a recipient may use your version of this file under either |
||
13 | * the MPL or the LGPL. |
||
14 | * |
||
15 | * You should have received a copy of the LGPL along with this library |
||
16 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
||
17 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
||
18 | * You should have received a copy of the MPL along with this library |
||
19 | * in the file COPYING-MPL-1.1 |
||
20 | * |
||
21 | * The contents of this file are subject to the Mozilla Public License |
||
22 | * Version 1.1 (the "License"); you may not use this file except in |
||
23 | * compliance with the License. You may obtain a copy of the License at |
||
24 | * http://www.mozilla.org/MPL/ |
||
25 | * |
||
26 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
||
27 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
||
28 | * the specific language governing rights and limitations. |
||
29 | * |
||
30 | * The Original Code is the cairo graphics library. |
||
31 | * |
||
32 | * The Initial Developer of the Original Code is Red Hat, Inc. |
||
33 | * |
||
34 | * Contributor(s): |
||
35 | * Chris Wilson |
||
36 | */ |
||
37 | |||
38 | #include "cairoint.h" |
||
39 | |||
40 | #include "cairo-error-private.h" |
||
41 | #include "cairo-surface-wrapper-private.h" |
||
42 | |||
43 | /* A collection of routines to facilitate surface wrapping */ |
||
44 | |||
45 | static void |
||
46 | _copy_transformed_pattern (cairo_pattern_t *pattern, |
||
47 | const cairo_pattern_t *original, |
||
48 | const cairo_matrix_t *ctm_inverse) |
||
49 | { |
||
50 | _cairo_pattern_init_static_copy (pattern, original); |
||
51 | |||
52 | /* apply device_transform first so that it is transformed by ctm_inverse */ |
||
53 | if (original->type == CAIRO_PATTERN_TYPE_SURFACE) { |
||
54 | cairo_surface_pattern_t *surface_pattern; |
||
55 | cairo_surface_t *surface; |
||
56 | |||
57 | surface_pattern = (cairo_surface_pattern_t *) original; |
||
58 | surface = surface_pattern->surface; |
||
59 | |||
60 | if (_cairo_surface_has_device_transform (surface)) |
||
61 | _cairo_pattern_transform (pattern, &surface->device_transform); |
||
62 | } |
||
63 | |||
64 | if (! _cairo_matrix_is_identity (ctm_inverse)) |
||
65 | _cairo_pattern_transform (pattern, ctm_inverse); |
||
66 | } |
||
67 | |||
68 | static inline cairo_bool_t |
||
69 | _cairo_surface_wrapper_needs_device_transform (cairo_surface_wrapper_t *wrapper) |
||
70 | { |
||
71 | return ! _cairo_matrix_is_identity (&wrapper->target->device_transform); |
||
72 | } |
||
73 | |||
74 | static cairo_bool_t |
||
75 | _cairo_surface_wrapper_needs_extents_transform (cairo_surface_wrapper_t *wrapper) |
||
76 | { |
||
77 | return wrapper->has_extents && (wrapper->extents.x | wrapper->extents.y); |
||
78 | } |
||
79 | |||
80 | cairo_status_t |
||
81 | _cairo_surface_wrapper_acquire_source_image (cairo_surface_wrapper_t *wrapper, |
||
82 | cairo_image_surface_t **image_out, |
||
83 | void **image_extra) |
||
84 | { |
||
85 | if (unlikely (wrapper->target->status)) |
||
86 | return wrapper->target->status; |
||
87 | |||
88 | return _cairo_surface_acquire_source_image (wrapper->target, |
||
89 | image_out, image_extra); |
||
90 | } |
||
91 | |||
92 | void |
||
93 | _cairo_surface_wrapper_release_source_image (cairo_surface_wrapper_t *wrapper, |
||
94 | cairo_image_surface_t *image, |
||
95 | void *image_extra) |
||
96 | { |
||
97 | _cairo_surface_release_source_image (wrapper->target, image, image_extra); |
||
98 | } |
||
99 | |||
100 | cairo_status_t |
||
101 | _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, |
||
102 | cairo_operator_t op, |
||
103 | const cairo_pattern_t *source, |
||
104 | cairo_clip_t *clip) |
||
105 | { |
||
106 | cairo_status_t status; |
||
107 | cairo_clip_t clip_copy, *dev_clip = clip; |
||
108 | cairo_pattern_union_t source_copy; |
||
109 | cairo_clip_t target_clip; |
||
110 | |||
111 | if (unlikely (wrapper->target->status)) |
||
112 | return wrapper->target->status; |
||
113 | |||
114 | if (wrapper->has_extents) { |
||
115 | _cairo_clip_init_copy (&target_clip, clip); |
||
116 | status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); |
||
117 | if (unlikely (status)) |
||
118 | goto FINISH; |
||
119 | |||
120 | dev_clip = clip = &target_clip; |
||
121 | } |
||
122 | |||
123 | if (clip && clip->all_clipped) { |
||
124 | status = CAIRO_STATUS_SUCCESS; |
||
125 | goto FINISH; |
||
126 | } |
||
127 | |||
128 | if (_cairo_surface_wrapper_needs_device_transform (wrapper) || |
||
129 | _cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
130 | { |
||
131 | cairo_matrix_t m; |
||
132 | |||
133 | cairo_matrix_init_identity (&m); |
||
134 | |||
135 | if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
136 | cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); |
||
137 | |||
138 | if (_cairo_surface_wrapper_needs_device_transform (wrapper)) |
||
139 | cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); |
||
140 | |||
141 | if (clip != NULL) { |
||
142 | status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); |
||
143 | if (unlikely (status)) |
||
144 | goto FINISH; |
||
145 | |||
146 | dev_clip = &clip_copy; |
||
147 | } |
||
148 | |||
149 | status = cairo_matrix_invert (&m); |
||
150 | assert (status == CAIRO_STATUS_SUCCESS); |
||
151 | |||
152 | _copy_transformed_pattern (&source_copy.base, source, &m); |
||
153 | source = &source_copy.base; |
||
154 | } |
||
155 | |||
156 | status = _cairo_surface_paint (wrapper->target, op, source, dev_clip); |
||
157 | |||
158 | FINISH: |
||
159 | if (wrapper->has_extents) |
||
160 | _cairo_clip_reset (&target_clip); |
||
161 | if (dev_clip != clip) |
||
162 | _cairo_clip_reset (dev_clip); |
||
163 | return status; |
||
164 | } |
||
165 | |||
166 | cairo_status_t |
||
167 | _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper, |
||
168 | cairo_operator_t op, |
||
169 | const cairo_pattern_t *source, |
||
170 | const cairo_pattern_t *mask, |
||
171 | cairo_clip_t *clip) |
||
172 | { |
||
173 | cairo_status_t status; |
||
174 | cairo_clip_t clip_copy, *dev_clip = clip; |
||
175 | cairo_pattern_union_t source_copy; |
||
176 | cairo_pattern_union_t mask_copy; |
||
177 | cairo_clip_t target_clip; |
||
178 | |||
179 | if (unlikely (wrapper->target->status)) |
||
180 | return wrapper->target->status; |
||
181 | |||
182 | if (wrapper->has_extents) { |
||
183 | _cairo_clip_init_copy (&target_clip, clip); |
||
184 | status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); |
||
185 | if (unlikely (status)) |
||
186 | goto FINISH; |
||
187 | |||
188 | dev_clip = clip = &target_clip; |
||
189 | } |
||
190 | |||
191 | if (clip && clip->all_clipped) { |
||
192 | status = CAIRO_STATUS_SUCCESS; |
||
193 | goto FINISH; |
||
194 | } |
||
195 | |||
196 | if (_cairo_surface_wrapper_needs_device_transform (wrapper) || |
||
197 | _cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
198 | { |
||
199 | cairo_matrix_t m; |
||
200 | |||
201 | cairo_matrix_init_identity (&m); |
||
202 | |||
203 | if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
204 | cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); |
||
205 | |||
206 | if (_cairo_surface_wrapper_needs_device_transform (wrapper)) |
||
207 | cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); |
||
208 | |||
209 | if (clip != NULL) { |
||
210 | status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); |
||
211 | if (unlikely (status)) |
||
212 | goto FINISH; |
||
213 | |||
214 | dev_clip = &clip_copy; |
||
215 | } |
||
216 | |||
217 | status = cairo_matrix_invert (&m); |
||
218 | assert (status == CAIRO_STATUS_SUCCESS); |
||
219 | |||
220 | _copy_transformed_pattern (&source_copy.base, source, &m); |
||
221 | source = &source_copy.base; |
||
222 | |||
223 | _copy_transformed_pattern (&mask_copy.base, mask, &m); |
||
224 | mask = &mask_copy.base; |
||
225 | } |
||
226 | |||
227 | status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip); |
||
228 | |||
229 | FINISH: |
||
230 | if (wrapper->has_extents) |
||
231 | _cairo_clip_reset (&target_clip); |
||
232 | if (dev_clip != clip) |
||
233 | _cairo_clip_reset (dev_clip); |
||
234 | return status; |
||
235 | } |
||
236 | |||
237 | cairo_status_t |
||
238 | _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, |
||
239 | cairo_operator_t op, |
||
240 | const cairo_pattern_t *source, |
||
241 | cairo_path_fixed_t *path, |
||
242 | const cairo_stroke_style_t *stroke_style, |
||
243 | const cairo_matrix_t *ctm, |
||
244 | const cairo_matrix_t *ctm_inverse, |
||
245 | double tolerance, |
||
246 | cairo_antialias_t antialias, |
||
247 | cairo_clip_t *clip) |
||
248 | { |
||
249 | cairo_status_t status; |
||
250 | cairo_path_fixed_t path_copy, *dev_path = path; |
||
251 | cairo_clip_t clip_copy, *dev_clip = clip; |
||
252 | cairo_matrix_t dev_ctm = *ctm; |
||
253 | cairo_matrix_t dev_ctm_inverse = *ctm_inverse; |
||
254 | cairo_pattern_union_t source_copy; |
||
255 | cairo_clip_t target_clip; |
||
256 | |||
257 | if (unlikely (wrapper->target->status)) |
||
258 | return wrapper->target->status; |
||
259 | |||
260 | if (wrapper->has_extents) { |
||
261 | _cairo_clip_init_copy (&target_clip, clip); |
||
262 | status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); |
||
263 | if (unlikely (status)) |
||
264 | goto FINISH; |
||
265 | |||
266 | dev_clip = clip = &target_clip; |
||
267 | } |
||
268 | |||
269 | if (clip && clip->all_clipped) { |
||
270 | status = CAIRO_STATUS_SUCCESS; |
||
271 | goto FINISH; |
||
272 | } |
||
273 | |||
274 | if (_cairo_surface_wrapper_needs_device_transform (wrapper) || |
||
275 | _cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
276 | { |
||
277 | cairo_matrix_t m; |
||
278 | |||
279 | cairo_matrix_init_identity (&m); |
||
280 | |||
281 | if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
282 | cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); |
||
283 | |||
284 | if (_cairo_surface_wrapper_needs_device_transform (wrapper)) |
||
285 | cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); |
||
286 | |||
287 | status = _cairo_path_fixed_init_copy (&path_copy, dev_path); |
||
288 | if (unlikely (status)) |
||
289 | goto FINISH; |
||
290 | |||
291 | _cairo_path_fixed_transform (&path_copy, &m); |
||
292 | dev_path = &path_copy; |
||
293 | |||
294 | if (clip != NULL) { |
||
295 | status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); |
||
296 | if (unlikely (status)) |
||
297 | goto FINISH; |
||
298 | |||
299 | dev_clip = &clip_copy; |
||
300 | } |
||
301 | |||
302 | cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m); |
||
303 | |||
304 | status = cairo_matrix_invert (&m); |
||
305 | assert (status == CAIRO_STATUS_SUCCESS); |
||
306 | |||
307 | cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse); |
||
308 | |||
309 | _copy_transformed_pattern (&source_copy.base, source, &m); |
||
310 | source = &source_copy.base; |
||
311 | } |
||
312 | else |
||
313 | { |
||
314 | if (clip != NULL) { |
||
315 | dev_clip = &clip_copy; |
||
316 | _cairo_clip_init_copy (&clip_copy, clip); |
||
317 | } |
||
318 | } |
||
319 | |||
320 | status = _cairo_surface_stroke (wrapper->target, op, source, |
||
321 | dev_path, stroke_style, |
||
322 | &dev_ctm, &dev_ctm_inverse, |
||
323 | tolerance, antialias, |
||
324 | dev_clip); |
||
325 | |||
326 | FINISH: |
||
327 | if (dev_path != path) |
||
328 | _cairo_path_fixed_fini (dev_path); |
||
329 | if (wrapper->has_extents) |
||
330 | _cairo_clip_reset (&target_clip); |
||
331 | if (dev_clip != clip) |
||
332 | _cairo_clip_reset (dev_clip); |
||
333 | return status; |
||
334 | } |
||
335 | |||
336 | cairo_status_t |
||
337 | _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, |
||
338 | cairo_operator_t fill_op, |
||
339 | const cairo_pattern_t *fill_source, |
||
340 | cairo_fill_rule_t fill_rule, |
||
341 | double fill_tolerance, |
||
342 | cairo_antialias_t fill_antialias, |
||
343 | cairo_path_fixed_t *path, |
||
344 | cairo_operator_t stroke_op, |
||
345 | const cairo_pattern_t *stroke_source, |
||
346 | const cairo_stroke_style_t *stroke_style, |
||
347 | const cairo_matrix_t *stroke_ctm, |
||
348 | const cairo_matrix_t *stroke_ctm_inverse, |
||
349 | double stroke_tolerance, |
||
350 | cairo_antialias_t stroke_antialias, |
||
351 | cairo_clip_t *clip) |
||
352 | { |
||
353 | cairo_status_t status; |
||
354 | cairo_path_fixed_t path_copy, *dev_path = path; |
||
355 | cairo_clip_t clip_copy, *dev_clip = clip; |
||
356 | cairo_matrix_t dev_ctm = *stroke_ctm; |
||
357 | cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse; |
||
358 | cairo_pattern_union_t stroke_source_copy; |
||
359 | cairo_pattern_union_t fill_source_copy; |
||
360 | cairo_clip_t target_clip; |
||
361 | |||
362 | if (unlikely (wrapper->target->status)) |
||
363 | return wrapper->target->status; |
||
364 | |||
365 | if (wrapper->has_extents) { |
||
366 | _cairo_clip_init_copy (&target_clip, clip); |
||
367 | status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); |
||
368 | if (unlikely (status)) |
||
369 | goto FINISH; |
||
370 | |||
371 | dev_clip = clip = &target_clip; |
||
372 | } |
||
373 | |||
374 | if (clip && clip->all_clipped) { |
||
375 | status = CAIRO_STATUS_SUCCESS; |
||
376 | goto FINISH; |
||
377 | } |
||
378 | |||
379 | if (_cairo_surface_wrapper_needs_device_transform (wrapper) || |
||
380 | _cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
381 | { |
||
382 | cairo_matrix_t m; |
||
383 | |||
384 | cairo_matrix_init_identity (&m); |
||
385 | |||
386 | if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
387 | cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); |
||
388 | |||
389 | if (_cairo_surface_wrapper_needs_device_transform (wrapper)) |
||
390 | cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); |
||
391 | |||
392 | status = _cairo_path_fixed_init_copy (&path_copy, dev_path); |
||
393 | if (unlikely (status)) |
||
394 | goto FINISH; |
||
395 | |||
396 | _cairo_path_fixed_transform (&path_copy, &m); |
||
397 | dev_path = &path_copy; |
||
398 | |||
399 | if (clip != NULL) { |
||
400 | status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); |
||
401 | if (unlikely (status)) |
||
402 | goto FINISH; |
||
403 | |||
404 | dev_clip = &clip_copy; |
||
405 | } |
||
406 | |||
407 | cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m); |
||
408 | |||
409 | status = cairo_matrix_invert (&m); |
||
410 | assert (status == CAIRO_STATUS_SUCCESS); |
||
411 | |||
412 | cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse); |
||
413 | |||
414 | _copy_transformed_pattern (&stroke_source_copy.base, stroke_source, &m); |
||
415 | stroke_source = &stroke_source_copy.base; |
||
416 | |||
417 | _copy_transformed_pattern (&fill_source_copy.base, fill_source, &m); |
||
418 | fill_source = &fill_source_copy.base; |
||
419 | } |
||
420 | else |
||
421 | { |
||
422 | if (clip != NULL) { |
||
423 | dev_clip = &clip_copy; |
||
424 | _cairo_clip_init_copy (&clip_copy, clip); |
||
425 | } |
||
426 | } |
||
427 | |||
428 | status = _cairo_surface_fill_stroke (wrapper->target, |
||
429 | fill_op, fill_source, fill_rule, |
||
430 | fill_tolerance, fill_antialias, |
||
431 | dev_path, |
||
432 | stroke_op, stroke_source, |
||
433 | stroke_style, |
||
434 | &dev_ctm, &dev_ctm_inverse, |
||
435 | stroke_tolerance, stroke_antialias, |
||
436 | dev_clip); |
||
437 | |||
438 | FINISH: |
||
439 | if (dev_path != path) |
||
440 | _cairo_path_fixed_fini (dev_path); |
||
441 | if (wrapper->has_extents) |
||
442 | _cairo_clip_reset (&target_clip); |
||
443 | if (dev_clip != clip) |
||
444 | _cairo_clip_reset (dev_clip); |
||
445 | return status; |
||
446 | } |
||
447 | |||
448 | cairo_status_t |
||
449 | _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, |
||
450 | cairo_operator_t op, |
||
451 | const cairo_pattern_t *source, |
||
452 | cairo_path_fixed_t *path, |
||
453 | cairo_fill_rule_t fill_rule, |
||
454 | double tolerance, |
||
455 | cairo_antialias_t antialias, |
||
456 | cairo_clip_t *clip) |
||
457 | { |
||
458 | cairo_status_t status; |
||
459 | cairo_path_fixed_t path_copy, *dev_path = path; |
||
460 | cairo_clip_t clip_copy, *dev_clip = clip; |
||
461 | cairo_pattern_union_t source_copy; |
||
462 | cairo_clip_t target_clip; |
||
463 | |||
464 | if (unlikely (wrapper->target->status)) |
||
465 | return wrapper->target->status; |
||
466 | |||
467 | if (wrapper->has_extents) { |
||
468 | _cairo_clip_init_copy (&target_clip, clip); |
||
469 | status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); |
||
470 | if (unlikely (status)) |
||
471 | goto FINISH; |
||
472 | |||
473 | dev_clip = clip = &target_clip; |
||
474 | } |
||
475 | |||
476 | if (clip && clip->all_clipped) { |
||
477 | status = CAIRO_STATUS_SUCCESS; |
||
478 | goto FINISH; |
||
479 | } |
||
480 | |||
481 | if (_cairo_surface_wrapper_needs_device_transform (wrapper) || |
||
482 | _cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
483 | { |
||
484 | cairo_matrix_t m; |
||
485 | |||
486 | cairo_matrix_init_identity (&m); |
||
487 | |||
488 | if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
489 | cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); |
||
490 | |||
491 | if (_cairo_surface_wrapper_needs_device_transform (wrapper)) |
||
492 | cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); |
||
493 | |||
494 | status = _cairo_path_fixed_init_copy (&path_copy, dev_path); |
||
495 | if (unlikely (status)) |
||
496 | goto FINISH; |
||
497 | |||
498 | _cairo_path_fixed_transform (&path_copy, &m); |
||
499 | dev_path = &path_copy; |
||
500 | |||
501 | if (clip != NULL) { |
||
502 | status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); |
||
503 | if (unlikely (status)) |
||
504 | goto FINISH; |
||
505 | |||
506 | dev_clip = &clip_copy; |
||
507 | } |
||
508 | |||
509 | status = cairo_matrix_invert (&m); |
||
510 | assert (status == CAIRO_STATUS_SUCCESS); |
||
511 | |||
512 | _copy_transformed_pattern (&source_copy.base, source, &m); |
||
513 | source = &source_copy.base; |
||
514 | } |
||
515 | else |
||
516 | { |
||
517 | if (clip != NULL) { |
||
518 | dev_clip = &clip_copy; |
||
519 | _cairo_clip_init_copy (&clip_copy, clip); |
||
520 | } |
||
521 | } |
||
522 | |||
523 | status = _cairo_surface_fill (wrapper->target, op, source, |
||
524 | dev_path, fill_rule, |
||
525 | tolerance, antialias, |
||
526 | dev_clip); |
||
527 | |||
528 | FINISH: |
||
529 | if (dev_path != path) |
||
530 | _cairo_path_fixed_fini (dev_path); |
||
531 | if (wrapper->has_extents) |
||
532 | _cairo_clip_reset (&target_clip); |
||
533 | if (dev_clip != clip) |
||
534 | _cairo_clip_reset (dev_clip); |
||
535 | return status; |
||
536 | } |
||
537 | |||
538 | cairo_status_t |
||
539 | _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, |
||
540 | cairo_operator_t op, |
||
541 | const cairo_pattern_t *source, |
||
542 | const char *utf8, |
||
543 | int utf8_len, |
||
544 | cairo_glyph_t *glyphs, |
||
545 | int num_glyphs, |
||
546 | const cairo_text_cluster_t *clusters, |
||
547 | int num_clusters, |
||
548 | cairo_text_cluster_flags_t cluster_flags, |
||
549 | cairo_scaled_font_t *scaled_font, |
||
550 | cairo_clip_t *clip) |
||
551 | { |
||
552 | cairo_status_t status; |
||
553 | cairo_clip_t clip_copy, *dev_clip = clip; |
||
554 | cairo_glyph_t *dev_glyphs = glyphs; |
||
555 | cairo_pattern_union_t source_copy; |
||
556 | cairo_clip_t target_clip; |
||
557 | |||
558 | if (unlikely (wrapper->target->status)) |
||
559 | return wrapper->target->status; |
||
560 | |||
561 | if (glyphs == NULL || num_glyphs == 0) |
||
562 | return CAIRO_STATUS_SUCCESS; |
||
563 | |||
564 | if (wrapper->has_extents) { |
||
565 | _cairo_clip_init_copy (&target_clip, clip); |
||
566 | status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); |
||
567 | if (unlikely (status)) |
||
568 | goto FINISH; |
||
569 | |||
570 | dev_clip = clip = &target_clip; |
||
571 | } |
||
572 | |||
573 | if (clip && clip->all_clipped) { |
||
574 | status = CAIRO_STATUS_SUCCESS; |
||
575 | goto FINISH; |
||
576 | } |
||
577 | |||
578 | if (_cairo_surface_wrapper_needs_device_transform (wrapper) || |
||
579 | _cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
580 | { |
||
581 | cairo_matrix_t m; |
||
582 | int i; |
||
583 | |||
584 | cairo_matrix_init_identity (&m); |
||
585 | |||
586 | if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) |
||
587 | cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); |
||
588 | |||
589 | if (_cairo_surface_wrapper_needs_device_transform (wrapper)) |
||
590 | cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); |
||
591 | |||
592 | if (clip != NULL) { |
||
593 | status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); |
||
594 | if (unlikely (status)) |
||
595 | goto FINISH; |
||
596 | |||
597 | dev_clip = &clip_copy; |
||
598 | } |
||
599 | |||
600 | dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); |
||
601 | if (dev_glyphs == NULL) { |
||
602 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
||
603 | goto FINISH; |
||
604 | } |
||
605 | |||
606 | for (i = 0; i < num_glyphs; i++) { |
||
607 | dev_glyphs[i] = glyphs[i]; |
||
608 | cairo_matrix_transform_point (&m, &dev_glyphs[i].x, &dev_glyphs[i].y); |
||
609 | } |
||
610 | |||
611 | status = cairo_matrix_invert (&m); |
||
612 | assert (status == CAIRO_STATUS_SUCCESS); |
||
613 | |||
614 | _copy_transformed_pattern (&source_copy.base, source, &m); |
||
615 | source = &source_copy.base; |
||
616 | } |
||
617 | else |
||
618 | { |
||
619 | if (clip != NULL) { |
||
620 | dev_clip = &clip_copy; |
||
621 | _cairo_clip_init_copy (&clip_copy, clip); |
||
622 | } |
||
623 | } |
||
624 | |||
625 | status = _cairo_surface_show_text_glyphs (wrapper->target, op, source, |
||
626 | utf8, utf8_len, |
||
627 | dev_glyphs, num_glyphs, |
||
628 | clusters, num_clusters, |
||
629 | cluster_flags, |
||
630 | scaled_font, |
||
631 | dev_clip); |
||
632 | |||
633 | FINISH: |
||
634 | if (dev_clip != clip) |
||
635 | _cairo_clip_reset (dev_clip); |
||
636 | if (wrapper->has_extents) |
||
637 | _cairo_clip_reset (&target_clip); |
||
638 | if (dev_glyphs != glyphs) |
||
639 | free (dev_glyphs); |
||
640 | return status; |
||
641 | } |
||
642 | |||
643 | cairo_surface_t * |
||
644 | _cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper, |
||
645 | cairo_content_t content, |
||
646 | int width, |
||
647 | int height) |
||
648 | { |
||
649 | return _cairo_surface_create_similar_scratch (wrapper->target, |
||
650 | content, width, height); |
||
651 | } |
||
652 | |||
653 | cairo_bool_t |
||
654 | _cairo_surface_wrapper_get_extents (cairo_surface_wrapper_t *wrapper, |
||
655 | cairo_rectangle_int_t *extents) |
||
656 | { |
||
657 | if (wrapper->has_extents) { |
||
658 | if (_cairo_surface_get_extents (wrapper->target, extents)) |
||
659 | _cairo_rectangle_intersect (extents, &wrapper->extents); |
||
660 | else |
||
661 | *extents = wrapper->extents; |
||
662 | |||
663 | return TRUE; |
||
664 | } else { |
||
665 | return _cairo_surface_get_extents (wrapper->target, extents); |
||
666 | } |
||
667 | } |
||
668 | |||
669 | void |
||
670 | _cairo_surface_wrapper_set_extents (cairo_surface_wrapper_t *wrapper, |
||
671 | const cairo_rectangle_int_t *extents) |
||
672 | { |
||
673 | if (extents != NULL) { |
||
674 | wrapper->extents = *extents; |
||
675 | wrapper->has_extents = TRUE; |
||
676 | } else { |
||
677 | wrapper->has_extents = FALSE; |
||
678 | } |
||
679 | } |
||
680 | |||
681 | void |
||
682 | _cairo_surface_wrapper_get_font_options (cairo_surface_wrapper_t *wrapper, |
||
683 | cairo_font_options_t *options) |
||
684 | { |
||
685 | cairo_surface_get_font_options (wrapper->target, options); |
||
686 | } |
||
687 | |||
688 | cairo_surface_t * |
||
689 | _cairo_surface_wrapper_snapshot (cairo_surface_wrapper_t *wrapper) |
||
690 | { |
||
691 | return _cairo_surface_snapshot (wrapper->target); |
||
692 | } |
||
693 | |||
694 | cairo_bool_t |
||
695 | _cairo_surface_wrapper_has_show_text_glyphs (cairo_surface_wrapper_t *wrapper) |
||
696 | { |
||
697 | return cairo_surface_has_show_text_glyphs (wrapper->target); |
||
698 | } |
||
699 | |||
700 | void |
||
701 | _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper, |
||
702 | cairo_surface_t *target) |
||
703 | { |
||
704 | wrapper->target = cairo_surface_reference (target); |
||
705 | wrapper->has_extents = FALSE; |
||
706 | } |
||
707 | |||
708 | void |
||
709 | _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper) |
||
710 | { |
||
711 | cairo_surface_destroy (wrapper->target); |
||
712 | }> |