Line data Source code
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 <chris@chris-wilson.co.uk>
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 0 : _copy_transformed_pattern (cairo_pattern_t *pattern,
47 : const cairo_pattern_t *original,
48 : const cairo_matrix_t *ctm_inverse)
49 : {
50 0 : _cairo_pattern_init_static_copy (pattern, original);
51 :
52 : /* Device transform should already have been applied before cairo_surface_wrapper_* functions
53 : * are called in _cairo_gstate_copy_transformed_pattern which all the gstate drawing
54 : * functions call through _cairo_gstate_copy_transformed_source and such. */
55 :
56 0 : if (! _cairo_matrix_is_identity (ctm_inverse))
57 0 : _cairo_pattern_transform (pattern, ctm_inverse);
58 0 : }
59 :
60 : static inline cairo_bool_t
61 0 : _cairo_surface_wrapper_needs_device_transform (cairo_surface_wrapper_t *wrapper)
62 : {
63 0 : return ! _cairo_matrix_is_identity (&wrapper->target->device_transform);
64 : }
65 :
66 : static cairo_bool_t
67 0 : _cairo_surface_wrapper_needs_extents_transform (cairo_surface_wrapper_t *wrapper)
68 : {
69 0 : return wrapper->has_extents && (wrapper->extents.x | wrapper->extents.y);
70 : }
71 :
72 : cairo_status_t
73 0 : _cairo_surface_wrapper_acquire_source_image (cairo_surface_wrapper_t *wrapper,
74 : cairo_image_surface_t **image_out,
75 : void **image_extra)
76 : {
77 0 : if (unlikely (wrapper->target->status))
78 0 : return wrapper->target->status;
79 :
80 0 : return _cairo_surface_acquire_source_image (wrapper->target,
81 : image_out, image_extra);
82 : }
83 :
84 : void
85 0 : _cairo_surface_wrapper_release_source_image (cairo_surface_wrapper_t *wrapper,
86 : cairo_image_surface_t *image,
87 : void *image_extra)
88 : {
89 0 : _cairo_surface_release_source_image (wrapper->target, image, image_extra);
90 0 : }
91 :
92 : cairo_status_t
93 0 : _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
94 : cairo_operator_t op,
95 : const cairo_pattern_t *source,
96 : cairo_clip_t *clip)
97 : {
98 : cairo_status_t status;
99 0 : cairo_clip_t clip_copy, *dev_clip = clip;
100 : cairo_pattern_union_t source_copy;
101 : cairo_clip_t target_clip;
102 :
103 0 : if (unlikely (wrapper->target->status))
104 0 : return wrapper->target->status;
105 :
106 0 : if (wrapper->has_extents) {
107 0 : _cairo_clip_init_copy (&target_clip, clip);
108 0 : status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
109 0 : if (unlikely (status))
110 0 : goto FINISH;
111 :
112 0 : dev_clip = clip = &target_clip;
113 : }
114 :
115 0 : if (clip && clip->all_clipped) {
116 0 : status = CAIRO_STATUS_SUCCESS;
117 0 : goto FINISH;
118 : }
119 :
120 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
121 0 : _cairo_surface_wrapper_needs_extents_transform (wrapper))
122 : {
123 : cairo_matrix_t m;
124 :
125 0 : cairo_matrix_init_identity (&m);
126 :
127 0 : if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
128 0 : cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
129 :
130 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper))
131 0 : cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
132 :
133 0 : if (clip != NULL) {
134 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
135 0 : if (unlikely (status))
136 0 : goto FINISH;
137 :
138 0 : dev_clip = &clip_copy;
139 : }
140 :
141 0 : status = cairo_matrix_invert (&m);
142 0 : assert (status == CAIRO_STATUS_SUCCESS);
143 :
144 0 : _copy_transformed_pattern (&source_copy.base, source, &m);
145 0 : source = &source_copy.base;
146 : }
147 :
148 0 : status = _cairo_surface_paint (wrapper->target, op, source, dev_clip);
149 :
150 : FINISH:
151 0 : if (wrapper->has_extents)
152 0 : _cairo_clip_reset (&target_clip);
153 0 : if (dev_clip != clip)
154 0 : _cairo_clip_reset (dev_clip);
155 0 : return status;
156 : }
157 :
158 : cairo_status_t
159 0 : _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
160 : cairo_operator_t op,
161 : const cairo_pattern_t *source,
162 : const cairo_pattern_t *mask,
163 : cairo_clip_t *clip)
164 : {
165 : cairo_status_t status;
166 0 : cairo_clip_t clip_copy, *dev_clip = clip;
167 : cairo_pattern_union_t source_copy;
168 : cairo_pattern_union_t mask_copy;
169 : cairo_clip_t target_clip;
170 :
171 0 : if (unlikely (wrapper->target->status))
172 0 : return wrapper->target->status;
173 :
174 0 : if (wrapper->has_extents) {
175 0 : _cairo_clip_init_copy (&target_clip, clip);
176 0 : status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
177 0 : if (unlikely (status))
178 0 : goto FINISH;
179 :
180 0 : dev_clip = clip = &target_clip;
181 : }
182 :
183 0 : if (clip && clip->all_clipped) {
184 0 : status = CAIRO_STATUS_SUCCESS;
185 0 : goto FINISH;
186 : }
187 :
188 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
189 0 : _cairo_surface_wrapper_needs_extents_transform (wrapper))
190 : {
191 : cairo_matrix_t m;
192 :
193 0 : cairo_matrix_init_identity (&m);
194 :
195 0 : if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
196 0 : cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
197 :
198 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper))
199 0 : cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
200 :
201 0 : if (clip != NULL) {
202 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
203 0 : if (unlikely (status))
204 0 : goto FINISH;
205 :
206 0 : dev_clip = &clip_copy;
207 : }
208 :
209 0 : status = cairo_matrix_invert (&m);
210 0 : assert (status == CAIRO_STATUS_SUCCESS);
211 :
212 0 : _copy_transformed_pattern (&source_copy.base, source, &m);
213 0 : source = &source_copy.base;
214 :
215 0 : _copy_transformed_pattern (&mask_copy.base, mask, &m);
216 0 : mask = &mask_copy.base;
217 : }
218 :
219 0 : status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip);
220 :
221 : FINISH:
222 0 : if (wrapper->has_extents)
223 0 : _cairo_clip_reset (&target_clip);
224 0 : if (dev_clip != clip)
225 0 : _cairo_clip_reset (dev_clip);
226 0 : return status;
227 : }
228 :
229 : cairo_status_t
230 0 : _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
231 : cairo_operator_t op,
232 : const cairo_pattern_t *source,
233 : cairo_path_fixed_t *path,
234 : const cairo_stroke_style_t *stroke_style,
235 : const cairo_matrix_t *ctm,
236 : const cairo_matrix_t *ctm_inverse,
237 : double tolerance,
238 : cairo_antialias_t antialias,
239 : cairo_clip_t *clip)
240 : {
241 : cairo_status_t status;
242 0 : cairo_path_fixed_t path_copy, *dev_path = path;
243 0 : cairo_clip_t clip_copy, *dev_clip = clip;
244 0 : cairo_matrix_t dev_ctm = *ctm;
245 0 : cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
246 : cairo_pattern_union_t source_copy;
247 : cairo_clip_t target_clip;
248 :
249 0 : if (unlikely (wrapper->target->status))
250 0 : return wrapper->target->status;
251 :
252 0 : if (wrapper->has_extents) {
253 0 : _cairo_clip_init_copy (&target_clip, clip);
254 0 : status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
255 0 : if (unlikely (status))
256 0 : goto FINISH;
257 :
258 0 : dev_clip = clip = &target_clip;
259 : }
260 :
261 0 : if (clip && clip->all_clipped) {
262 0 : status = CAIRO_STATUS_SUCCESS;
263 0 : goto FINISH;
264 : }
265 :
266 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
267 0 : _cairo_surface_wrapper_needs_extents_transform (wrapper))
268 0 : {
269 : cairo_matrix_t m;
270 :
271 0 : cairo_matrix_init_identity (&m);
272 :
273 0 : if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
274 0 : cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
275 :
276 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper))
277 0 : cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
278 :
279 0 : status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
280 0 : if (unlikely (status))
281 0 : goto FINISH;
282 :
283 0 : _cairo_path_fixed_transform (&path_copy, &m);
284 0 : dev_path = &path_copy;
285 :
286 0 : if (clip != NULL) {
287 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
288 0 : if (unlikely (status))
289 0 : goto FINISH;
290 :
291 0 : dev_clip = &clip_copy;
292 : }
293 :
294 0 : cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
295 :
296 0 : status = cairo_matrix_invert (&m);
297 0 : assert (status == CAIRO_STATUS_SUCCESS);
298 :
299 0 : cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse);
300 :
301 0 : _copy_transformed_pattern (&source_copy.base, source, &m);
302 0 : source = &source_copy.base;
303 : }
304 : else
305 : {
306 0 : if (clip != NULL) {
307 0 : dev_clip = &clip_copy;
308 0 : _cairo_clip_init_copy (&clip_copy, clip);
309 : }
310 : }
311 :
312 0 : status = _cairo_surface_stroke (wrapper->target, op, source,
313 : dev_path, stroke_style,
314 : &dev_ctm, &dev_ctm_inverse,
315 : tolerance, antialias,
316 : dev_clip);
317 :
318 : FINISH:
319 0 : if (dev_path != path)
320 0 : _cairo_path_fixed_fini (dev_path);
321 0 : if (wrapper->has_extents)
322 0 : _cairo_clip_reset (&target_clip);
323 0 : if (dev_clip != clip)
324 0 : _cairo_clip_reset (dev_clip);
325 0 : return status;
326 : }
327 :
328 : cairo_status_t
329 0 : _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
330 : cairo_operator_t fill_op,
331 : const cairo_pattern_t *fill_source,
332 : cairo_fill_rule_t fill_rule,
333 : double fill_tolerance,
334 : cairo_antialias_t fill_antialias,
335 : cairo_path_fixed_t *path,
336 : cairo_operator_t stroke_op,
337 : const cairo_pattern_t *stroke_source,
338 : const cairo_stroke_style_t *stroke_style,
339 : const cairo_matrix_t *stroke_ctm,
340 : const cairo_matrix_t *stroke_ctm_inverse,
341 : double stroke_tolerance,
342 : cairo_antialias_t stroke_antialias,
343 : cairo_clip_t *clip)
344 : {
345 : cairo_status_t status;
346 0 : cairo_path_fixed_t path_copy, *dev_path = path;
347 0 : cairo_clip_t clip_copy, *dev_clip = clip;
348 0 : cairo_matrix_t dev_ctm = *stroke_ctm;
349 0 : cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
350 : cairo_pattern_union_t stroke_source_copy;
351 : cairo_pattern_union_t fill_source_copy;
352 : cairo_clip_t target_clip;
353 :
354 0 : if (unlikely (wrapper->target->status))
355 0 : return wrapper->target->status;
356 :
357 0 : if (wrapper->has_extents) {
358 0 : _cairo_clip_init_copy (&target_clip, clip);
359 0 : status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
360 0 : if (unlikely (status))
361 0 : goto FINISH;
362 :
363 0 : dev_clip = clip = &target_clip;
364 : }
365 :
366 0 : if (clip && clip->all_clipped) {
367 0 : status = CAIRO_STATUS_SUCCESS;
368 0 : goto FINISH;
369 : }
370 :
371 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
372 0 : _cairo_surface_wrapper_needs_extents_transform (wrapper))
373 0 : {
374 : cairo_matrix_t m;
375 :
376 0 : cairo_matrix_init_identity (&m);
377 :
378 0 : if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
379 0 : cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
380 :
381 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper))
382 0 : cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
383 :
384 0 : status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
385 0 : if (unlikely (status))
386 0 : goto FINISH;
387 :
388 0 : _cairo_path_fixed_transform (&path_copy, &m);
389 0 : dev_path = &path_copy;
390 :
391 0 : if (clip != NULL) {
392 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
393 0 : if (unlikely (status))
394 0 : goto FINISH;
395 :
396 0 : dev_clip = &clip_copy;
397 : }
398 :
399 0 : cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
400 :
401 0 : status = cairo_matrix_invert (&m);
402 0 : assert (status == CAIRO_STATUS_SUCCESS);
403 :
404 0 : cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse);
405 :
406 0 : _copy_transformed_pattern (&stroke_source_copy.base, stroke_source, &m);
407 0 : stroke_source = &stroke_source_copy.base;
408 :
409 0 : _copy_transformed_pattern (&fill_source_copy.base, fill_source, &m);
410 0 : fill_source = &fill_source_copy.base;
411 : }
412 : else
413 : {
414 0 : if (clip != NULL) {
415 0 : dev_clip = &clip_copy;
416 0 : _cairo_clip_init_copy (&clip_copy, clip);
417 : }
418 : }
419 :
420 0 : status = _cairo_surface_fill_stroke (wrapper->target,
421 : fill_op, fill_source, fill_rule,
422 : fill_tolerance, fill_antialias,
423 : dev_path,
424 : stroke_op, stroke_source,
425 : stroke_style,
426 : &dev_ctm, &dev_ctm_inverse,
427 : stroke_tolerance, stroke_antialias,
428 : dev_clip);
429 :
430 : FINISH:
431 0 : if (dev_path != path)
432 0 : _cairo_path_fixed_fini (dev_path);
433 0 : if (wrapper->has_extents)
434 0 : _cairo_clip_reset (&target_clip);
435 0 : if (dev_clip != clip)
436 0 : _cairo_clip_reset (dev_clip);
437 0 : return status;
438 : }
439 :
440 : cairo_status_t
441 0 : _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
442 : cairo_operator_t op,
443 : const cairo_pattern_t *source,
444 : cairo_path_fixed_t *path,
445 : cairo_fill_rule_t fill_rule,
446 : double tolerance,
447 : cairo_antialias_t antialias,
448 : cairo_clip_t *clip)
449 : {
450 : cairo_status_t status;
451 0 : cairo_path_fixed_t path_copy, *dev_path = path;
452 0 : cairo_clip_t clip_copy, *dev_clip = clip;
453 : cairo_pattern_union_t source_copy;
454 : cairo_clip_t target_clip;
455 :
456 0 : if (unlikely (wrapper->target->status))
457 0 : return wrapper->target->status;
458 :
459 0 : if (wrapper->has_extents) {
460 0 : _cairo_clip_init_copy (&target_clip, clip);
461 0 : status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
462 0 : if (unlikely (status))
463 0 : goto FINISH;
464 :
465 0 : dev_clip = clip = &target_clip;
466 : }
467 :
468 0 : if (clip && clip->all_clipped) {
469 0 : status = CAIRO_STATUS_SUCCESS;
470 0 : goto FINISH;
471 : }
472 :
473 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
474 0 : _cairo_surface_wrapper_needs_extents_transform (wrapper))
475 0 : {
476 : cairo_matrix_t m;
477 :
478 0 : cairo_matrix_init_identity (&m);
479 :
480 0 : if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
481 0 : cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
482 :
483 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper))
484 0 : cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
485 :
486 0 : status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
487 0 : if (unlikely (status))
488 0 : goto FINISH;
489 :
490 0 : _cairo_path_fixed_transform (&path_copy, &m);
491 0 : dev_path = &path_copy;
492 :
493 0 : if (clip != NULL) {
494 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
495 0 : if (unlikely (status))
496 0 : goto FINISH;
497 :
498 0 : dev_clip = &clip_copy;
499 : }
500 :
501 0 : status = cairo_matrix_invert (&m);
502 0 : assert (status == CAIRO_STATUS_SUCCESS);
503 :
504 0 : _copy_transformed_pattern (&source_copy.base, source, &m);
505 0 : source = &source_copy.base;
506 : }
507 : else
508 : {
509 0 : if (clip != NULL) {
510 0 : dev_clip = &clip_copy;
511 0 : _cairo_clip_init_copy (&clip_copy, clip);
512 : }
513 : }
514 :
515 0 : status = _cairo_surface_fill (wrapper->target, op, source,
516 : dev_path, fill_rule,
517 : tolerance, antialias,
518 : dev_clip);
519 :
520 : FINISH:
521 0 : if (dev_path != path)
522 0 : _cairo_path_fixed_fini (dev_path);
523 0 : if (wrapper->has_extents)
524 0 : _cairo_clip_reset (&target_clip);
525 0 : if (dev_clip != clip)
526 0 : _cairo_clip_reset (dev_clip);
527 0 : return status;
528 : }
529 :
530 : cairo_status_t
531 0 : _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
532 : cairo_operator_t op,
533 : const cairo_pattern_t *source,
534 : const char *utf8,
535 : int utf8_len,
536 : cairo_glyph_t *glyphs,
537 : int num_glyphs,
538 : const cairo_text_cluster_t *clusters,
539 : int num_clusters,
540 : cairo_text_cluster_flags_t cluster_flags,
541 : cairo_scaled_font_t *scaled_font,
542 : cairo_clip_t *clip)
543 : {
544 : cairo_status_t status;
545 0 : cairo_clip_t clip_copy, *dev_clip = clip;
546 0 : cairo_glyph_t *dev_glyphs = glyphs;
547 : cairo_pattern_union_t source_copy;
548 : cairo_clip_t target_clip;
549 :
550 0 : if (unlikely (wrapper->target->status))
551 0 : return wrapper->target->status;
552 :
553 0 : if (glyphs == NULL || num_glyphs == 0)
554 0 : return CAIRO_STATUS_SUCCESS;
555 :
556 0 : if (wrapper->has_extents) {
557 0 : _cairo_clip_init_copy (&target_clip, clip);
558 0 : status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
559 0 : if (unlikely (status))
560 0 : goto FINISH;
561 :
562 0 : dev_clip = clip = &target_clip;
563 : }
564 :
565 0 : if (clip && clip->all_clipped) {
566 0 : status = CAIRO_STATUS_SUCCESS;
567 0 : goto FINISH;
568 : }
569 :
570 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
571 0 : _cairo_surface_wrapper_needs_extents_transform (wrapper))
572 0 : {
573 : cairo_matrix_t m;
574 : int i;
575 :
576 0 : cairo_matrix_init_identity (&m);
577 :
578 0 : if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
579 0 : cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
580 :
581 0 : if (_cairo_surface_wrapper_needs_device_transform (wrapper))
582 0 : cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
583 :
584 0 : if (clip != NULL) {
585 0 : status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
586 0 : if (unlikely (status))
587 0 : goto FINISH;
588 :
589 0 : dev_clip = &clip_copy;
590 : }
591 :
592 0 : dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
593 0 : if (dev_glyphs == NULL) {
594 0 : status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
595 0 : goto FINISH;
596 : }
597 :
598 0 : for (i = 0; i < num_glyphs; i++) {
599 0 : dev_glyphs[i] = glyphs[i];
600 0 : cairo_matrix_transform_point (&m, &dev_glyphs[i].x, &dev_glyphs[i].y);
601 : }
602 :
603 0 : status = cairo_matrix_invert (&m);
604 0 : assert (status == CAIRO_STATUS_SUCCESS);
605 :
606 0 : _copy_transformed_pattern (&source_copy.base, source, &m);
607 0 : source = &source_copy.base;
608 : }
609 : else
610 : {
611 0 : if (clip != NULL) {
612 0 : dev_clip = &clip_copy;
613 0 : _cairo_clip_init_copy (&clip_copy, clip);
614 : }
615 : }
616 :
617 0 : status = _cairo_surface_show_text_glyphs (wrapper->target, op, source,
618 : utf8, utf8_len,
619 : dev_glyphs, num_glyphs,
620 : clusters, num_clusters,
621 : cluster_flags,
622 : scaled_font,
623 : dev_clip);
624 :
625 : FINISH:
626 0 : if (dev_clip != clip)
627 0 : _cairo_clip_reset (dev_clip);
628 0 : if (wrapper->has_extents)
629 0 : _cairo_clip_reset (&target_clip);
630 0 : if (dev_glyphs != glyphs)
631 0 : free (dev_glyphs);
632 0 : return status;
633 : }
634 :
635 : cairo_surface_t *
636 0 : _cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper,
637 : cairo_content_t content,
638 : int width,
639 : int height)
640 : {
641 0 : return _cairo_surface_create_similar_scratch (wrapper->target,
642 : content, width, height);
643 : }
644 :
645 : cairo_bool_t
646 0 : _cairo_surface_wrapper_get_extents (cairo_surface_wrapper_t *wrapper,
647 : cairo_rectangle_int_t *extents)
648 : {
649 0 : if (wrapper->has_extents) {
650 0 : if (_cairo_surface_get_extents (wrapper->target, extents))
651 0 : _cairo_rectangle_intersect (extents, &wrapper->extents);
652 : else
653 0 : *extents = wrapper->extents;
654 :
655 0 : return TRUE;
656 : } else {
657 0 : return _cairo_surface_get_extents (wrapper->target, extents);
658 : }
659 : }
660 :
661 : void
662 0 : _cairo_surface_wrapper_set_extents (cairo_surface_wrapper_t *wrapper,
663 : const cairo_rectangle_int_t *extents)
664 : {
665 0 : if (extents != NULL) {
666 0 : wrapper->extents = *extents;
667 0 : wrapper->has_extents = TRUE;
668 : } else {
669 0 : wrapper->has_extents = FALSE;
670 : }
671 0 : }
672 :
673 : void
674 0 : _cairo_surface_wrapper_get_font_options (cairo_surface_wrapper_t *wrapper,
675 : cairo_font_options_t *options)
676 : {
677 0 : cairo_surface_get_font_options (wrapper->target, options);
678 0 : }
679 :
680 : cairo_surface_t *
681 0 : _cairo_surface_wrapper_snapshot (cairo_surface_wrapper_t *wrapper)
682 : {
683 0 : return _cairo_surface_snapshot (wrapper->target);
684 : }
685 :
686 : cairo_bool_t
687 0 : _cairo_surface_wrapper_has_show_text_glyphs (cairo_surface_wrapper_t *wrapper)
688 : {
689 0 : return cairo_surface_has_show_text_glyphs (wrapper->target);
690 : }
691 :
692 : void
693 0 : _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper,
694 : cairo_surface_t *target)
695 : {
696 0 : wrapper->target = cairo_surface_reference (target);
697 0 : wrapper->has_extents = FALSE;
698 0 : }
699 :
700 : void
701 0 : _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper)
702 : {
703 0 : cairo_surface_destroy (wrapper->target);
704 0 : }
705 :
706 : cairo_status_t
707 0 : _cairo_surface_wrapper_flush (cairo_surface_wrapper_t *wrapper)
708 : {
709 0 : if (wrapper->target->backend->flush) {
710 0 : return wrapper->target->backend->flush(wrapper->target);
711 : }
712 0 : return CAIRO_STATUS_SUCCESS;
713 : }
|