Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ |
2 | /* cairo - a vector graphics library with display and print output |
||
3 | * |
||
4 | * Copyright © 2009 Chris Wilson |
||
5 | * |
||
6 | * This library is free software; you can redistribute it and/or |
||
7 | * modify it either under the terms of the GNU Lesser General Public |
||
8 | * License version 2.1 as published by the Free Software Foundation |
||
9 | * (the "LGPL") or, at your option, under the terms of the Mozilla |
||
10 | * Public License Version 1.1 (the "MPL"). If you do not alter this |
||
11 | * notice, a recipient may use your version of this file under either |
||
12 | * the MPL or the LGPL. |
||
13 | * |
||
14 | * You should have received a copy of the LGPL along with this library |
||
15 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
||
16 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
||
17 | * You should have received a copy of the MPL along with this library |
||
18 | * in the file COPYING-MPL-1.1 |
||
19 | * |
||
20 | * The contents of this file are subject to the Mozilla Public License |
||
21 | * Version 1.1 (the "License"); you may not use this file except in |
||
22 | * compliance with the License. You may obtain a copy of the License at |
||
23 | * http://www.mozilla.org/MPL/ |
||
24 | * |
||
25 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
||
26 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
||
27 | * the specific language governing rights and limitations. |
||
28 | * |
||
29 | * The Original Code is the cairo graphics library. |
||
30 | * |
||
31 | * The Initial Developer of the Original Code is Chris Wilson. |
||
32 | * |
||
33 | * Contributor(s): |
||
34 | * Chris Wilson |
||
35 | */ |
||
36 | |||
37 | /* This surface is intended to produce a verbose, hierarchical, DAG XML file |
||
38 | * representing a single surface. It is intended to be used by debuggers, |
||
39 | * such as cairo-sphinx, or by application test-suites that what a log of |
||
40 | * operations. |
||
41 | */ |
||
42 | |||
43 | #include "cairoint.h" |
||
44 | |||
45 | #include "cairo-xml.h" |
||
46 | |||
47 | #include "cairo-clip-private.h" |
||
48 | #include "cairo-device-private.h" |
||
49 | #include "cairo-default-context-private.h" |
||
50 | #include "cairo-image-surface-private.h" |
||
51 | #include "cairo-error-private.h" |
||
52 | #include "cairo-output-stream-private.h" |
||
53 | #include "cairo-recording-surface-inline.h" |
||
54 | |||
55 | #define static cairo_warn static |
||
56 | |||
57 | typedef struct _cairo_xml_surface cairo_xml_surface_t; |
||
58 | |||
59 | typedef struct _cairo_xml { |
||
60 | cairo_device_t base; |
||
61 | |||
62 | cairo_output_stream_t *stream; |
||
63 | int indent; |
||
64 | } cairo_xml_t; |
||
65 | |||
66 | struct _cairo_xml_surface { |
||
67 | cairo_surface_t base; |
||
68 | |||
69 | double width, height; |
||
70 | }; |
||
71 | |||
72 | slim_hidden_proto (cairo_xml_for_recording_surface); |
||
73 | |||
74 | static const cairo_surface_backend_t _cairo_xml_surface_backend; |
||
75 | |||
76 | static const char * |
||
77 | _operator_to_string (cairo_operator_t op) |
||
78 | { |
||
79 | static const char *names[] = { |
||
80 | "CLEAR", /* CAIRO_OPERATOR_CLEAR */ |
||
81 | |||
82 | "SOURCE", /* CAIRO_OPERATOR_SOURCE */ |
||
83 | "OVER", /* CAIRO_OPERATOR_OVER */ |
||
84 | "IN", /* CAIRO_OPERATOR_IN */ |
||
85 | "OUT", /* CAIRO_OPERATOR_OUT */ |
||
86 | "ATOP", /* CAIRO_OPERATOR_ATOP */ |
||
87 | |||
88 | "DEST", /* CAIRO_OPERATOR_DEST */ |
||
89 | "DEST_OVER", /* CAIRO_OPERATOR_DEST_OVER */ |
||
90 | "DEST_IN", /* CAIRO_OPERATOR_DEST_IN */ |
||
91 | "DEST_OUT", /* CAIRO_OPERATOR_DEST_OUT */ |
||
92 | "DEST_ATOP", /* CAIRO_OPERATOR_DEST_ATOP */ |
||
93 | |||
94 | "XOR", /* CAIRO_OPERATOR_XOR */ |
||
95 | "ADD", /* CAIRO_OPERATOR_ADD */ |
||
96 | "SATURATE", /* CAIRO_OPERATOR_SATURATE */ |
||
97 | |||
98 | "MULTIPLY", /* CAIRO_OPERATOR_MULTIPLY */ |
||
99 | "SCREEN", /* CAIRO_OPERATOR_SCREEN */ |
||
100 | "OVERLAY", /* CAIRO_OPERATOR_OVERLAY */ |
||
101 | "DARKEN", /* CAIRO_OPERATOR_DARKEN */ |
||
102 | "LIGHTEN", /* CAIRO_OPERATOR_LIGHTEN */ |
||
103 | "DODGE", /* CAIRO_OPERATOR_COLOR_DODGE */ |
||
104 | "BURN", /* CAIRO_OPERATOR_COLOR_BURN */ |
||
105 | "HARD_LIGHT", /* CAIRO_OPERATOR_HARD_LIGHT */ |
||
106 | "SOFT_LIGHT", /* CAIRO_OPERATOR_SOFT_LIGHT */ |
||
107 | "DIFFERENCE", /* CAIRO_OPERATOR_DIFFERENCE */ |
||
108 | "EXCLUSION", /* CAIRO_OPERATOR_EXCLUSION */ |
||
109 | "HSL_HUE", /* CAIRO_OPERATOR_HSL_HUE */ |
||
110 | "HSL_SATURATION", /* CAIRO_OPERATOR_HSL_SATURATION */ |
||
111 | "HSL_COLOR", /* CAIRO_OPERATOR_HSL_COLOR */ |
||
112 | "HSL_LUMINOSITY" /* CAIRO_OPERATOR_HSL_LUMINOSITY */ |
||
113 | }; |
||
114 | assert (op < ARRAY_LENGTH (names)); |
||
115 | return names[op]; |
||
116 | } |
||
117 | |||
118 | static const char * |
||
119 | _extend_to_string (cairo_extend_t extend) |
||
120 | { |
||
121 | static const char *names[] = { |
||
122 | "EXTEND_NONE", /* CAIRO_EXTEND_NONE */ |
||
123 | "EXTEND_REPEAT", /* CAIRO_EXTEND_REPEAT */ |
||
124 | "EXTEND_REFLECT", /* CAIRO_EXTEND_REFLECT */ |
||
125 | "EXTEND_PAD" /* CAIRO_EXTEND_PAD */ |
||
126 | }; |
||
127 | assert (extend < ARRAY_LENGTH (names)); |
||
128 | return names[extend]; |
||
129 | } |
||
130 | |||
131 | static const char * |
||
132 | _filter_to_string (cairo_filter_t filter) |
||
133 | { |
||
134 | static const char *names[] = { |
||
135 | "FILTER_FAST", /* CAIRO_FILTER_FAST */ |
||
136 | "FILTER_GOOD", /* CAIRO_FILTER_GOOD */ |
||
137 | "FILTER_BEST", /* CAIRO_FILTER_BEST */ |
||
138 | "FILTER_NEAREST", /* CAIRO_FILTER_NEAREST */ |
||
139 | "FILTER_BILINEAR", /* CAIRO_FILTER_BILINEAR */ |
||
140 | "FILTER_GAUSSIAN", /* CAIRO_FILTER_GAUSSIAN */ |
||
141 | }; |
||
142 | assert (filter < ARRAY_LENGTH (names)); |
||
143 | return names[filter]; |
||
144 | } |
||
145 | |||
146 | static const char * |
||
147 | _fill_rule_to_string (cairo_fill_rule_t rule) |
||
148 | { |
||
149 | static const char *names[] = { |
||
150 | "WINDING", /* CAIRO_FILL_RULE_WINDING */ |
||
151 | "EVEN_ODD" /* CAIRO_FILL_RILE_EVEN_ODD */ |
||
152 | }; |
||
153 | assert (rule < ARRAY_LENGTH (names)); |
||
154 | return names[rule]; |
||
155 | } |
||
156 | |||
157 | static const char * |
||
158 | _antialias_to_string (cairo_antialias_t antialias) |
||
159 | { |
||
160 | static const char *names[] = { |
||
161 | "DEFAULT", /* CAIRO_ANTIALIAS_DEFAULT */ |
||
162 | "NONE", /* CAIRO_ANTIALIAS_NONE */ |
||
163 | "GRAY", /* CAIRO_ANTIALIAS_GRAY */ |
||
164 | "SUBPIXEL", /* CAIRO_ANTIALIAS_SUBPIXEL */ |
||
165 | "FAST", /* CAIRO_ANTIALIAS_FAST */ |
||
166 | "GOOD", /* CAIRO_ANTIALIAS_GOOD */ |
||
167 | "BEST", /* CAIRO_ANTIALIAS_BEST */ |
||
168 | }; |
||
169 | assert (antialias < ARRAY_LENGTH (names)); |
||
170 | return names[antialias]; |
||
171 | } |
||
172 | |||
173 | static const char * |
||
174 | _line_cap_to_string (cairo_line_cap_t line_cap) |
||
175 | { |
||
176 | static const char *names[] = { |
||
177 | "LINE_CAP_BUTT", /* CAIRO_LINE_CAP_BUTT */ |
||
178 | "LINE_CAP_ROUND", /* CAIRO_LINE_CAP_ROUND */ |
||
179 | "LINE_CAP_SQUARE" /* CAIRO_LINE_CAP_SQUARE */ |
||
180 | }; |
||
181 | assert (line_cap < ARRAY_LENGTH (names)); |
||
182 | return names[line_cap]; |
||
183 | } |
||
184 | |||
185 | static const char * |
||
186 | _line_join_to_string (cairo_line_join_t line_join) |
||
187 | { |
||
188 | static const char *names[] = { |
||
189 | "LINE_JOIN_MITER", /* CAIRO_LINE_JOIN_MITER */ |
||
190 | "LINE_JOIN_ROUND", /* CAIRO_LINE_JOIN_ROUND */ |
||
191 | "LINE_JOIN_BEVEL", /* CAIRO_LINE_JOIN_BEVEL */ |
||
192 | }; |
||
193 | assert (line_join < ARRAY_LENGTH (names)); |
||
194 | return names[line_join]; |
||
195 | } |
||
196 | |||
197 | static const char * |
||
198 | _content_to_string (cairo_content_t content) |
||
199 | { |
||
200 | switch (content) { |
||
201 | case CAIRO_CONTENT_ALPHA: return "ALPHA"; |
||
202 | case CAIRO_CONTENT_COLOR: return "COLOR"; |
||
203 | default: |
||
204 | case CAIRO_CONTENT_COLOR_ALPHA: return "COLOR_ALPHA"; |
||
205 | } |
||
206 | } |
||
207 | |||
208 | static const char * |
||
209 | _format_to_string (cairo_format_t format) |
||
210 | { |
||
211 | switch (format) { |
||
212 | case CAIRO_FORMAT_ARGB32: return "ARGB32"; |
||
213 | case CAIRO_FORMAT_RGB30: return "RGB30"; |
||
214 | case CAIRO_FORMAT_RGB24: return "RGB24"; |
||
215 | case CAIRO_FORMAT_RGB16_565: return "RGB16_565"; |
||
216 | case CAIRO_FORMAT_A8: return "A8"; |
||
217 | case CAIRO_FORMAT_A1: return "A1"; |
||
218 | case CAIRO_FORMAT_INVALID: return "INVALID"; |
||
219 | } |
||
220 | ASSERT_NOT_REACHED; |
||
221 | return "INVALID"; |
||
222 | } |
||
223 | |||
224 | static cairo_status_t |
||
225 | _device_flush (void *abstract_device) |
||
226 | { |
||
227 | cairo_xml_t *xml = abstract_device; |
||
228 | cairo_status_t status; |
||
229 | |||
230 | status = _cairo_output_stream_flush (xml->stream); |
||
231 | |||
232 | return status; |
||
233 | } |
||
234 | |||
235 | static void |
||
236 | _device_destroy (void *abstract_device) |
||
237 | { |
||
238 | cairo_xml_t *xml = abstract_device; |
||
239 | cairo_status_t status; |
||
240 | |||
241 | status = _cairo_output_stream_destroy (xml->stream); |
||
242 | |||
243 | free (xml); |
||
244 | } |
||
245 | |||
246 | static const cairo_device_backend_t _cairo_xml_device_backend = { |
||
247 | CAIRO_DEVICE_TYPE_XML, |
||
248 | |||
249 | NULL, NULL, /* lock, unlock */ |
||
250 | |||
251 | _device_flush, |
||
252 | NULL, /* finish */ |
||
253 | _device_destroy |
||
254 | }; |
||
255 | |||
256 | static cairo_device_t * |
||
257 | _cairo_xml_create_internal (cairo_output_stream_t *stream) |
||
258 | { |
||
259 | cairo_xml_t *xml; |
||
260 | |||
261 | xml = malloc (sizeof (cairo_xml_t)); |
||
262 | if (unlikely (xml == NULL)) |
||
263 | return _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); |
||
264 | |||
265 | memset (xml, 0, sizeof (cairo_xml_t)); |
||
266 | |||
267 | _cairo_device_init (&xml->base, &_cairo_xml_device_backend); |
||
268 | |||
269 | xml->indent = 0; |
||
270 | xml->stream = stream; |
||
271 | |||
272 | return &xml->base; |
||
273 | } |
||
274 | |||
275 | static void |
||
276 | _cairo_xml_indent (cairo_xml_t *xml, int indent) |
||
277 | { |
||
278 | xml->indent += indent; |
||
279 | assert (xml->indent >= 0); |
||
280 | } |
||
281 | |||
282 | static void CAIRO_PRINTF_FORMAT (2, 3) |
||
283 | _cairo_xml_printf (cairo_xml_t *xml, const char *fmt, ...) |
||
284 | { |
||
285 | va_list ap; |
||
286 | char indent[80]; |
||
287 | int len; |
||
288 | |||
289 | len = MIN (xml->indent, ARRAY_LENGTH (indent)); |
||
290 | memset (indent, ' ', len); |
||
291 | _cairo_output_stream_write (xml->stream, indent, len); |
||
292 | |||
293 | va_start (ap, fmt); |
||
294 | _cairo_output_stream_vprintf (xml->stream, fmt, ap); |
||
295 | va_end (ap); |
||
296 | |||
297 | _cairo_output_stream_write (xml->stream, "\n", 1); |
||
298 | } |
||
299 | |||
300 | static void CAIRO_PRINTF_FORMAT (2, 3) |
||
301 | _cairo_xml_printf_start (cairo_xml_t *xml, const char *fmt, ...) |
||
302 | { |
||
303 | char indent[80]; |
||
304 | int len; |
||
305 | |||
306 | len = MIN (xml->indent, ARRAY_LENGTH (indent)); |
||
307 | memset (indent, ' ', len); |
||
308 | _cairo_output_stream_write (xml->stream, indent, len); |
||
309 | |||
310 | if (fmt != NULL) { |
||
311 | va_list ap; |
||
312 | |||
313 | va_start (ap, fmt); |
||
314 | _cairo_output_stream_vprintf (xml->stream, fmt, ap); |
||
315 | va_end (ap); |
||
316 | } |
||
317 | } |
||
318 | |||
319 | static void CAIRO_PRINTF_FORMAT (2, 3) |
||
320 | _cairo_xml_printf_continue (cairo_xml_t *xml, const char *fmt, ...) |
||
321 | { |
||
322 | va_list ap; |
||
323 | |||
324 | va_start (ap, fmt); |
||
325 | _cairo_output_stream_vprintf (xml->stream, fmt, ap); |
||
326 | va_end (ap); |
||
327 | } |
||
328 | |||
329 | static void CAIRO_PRINTF_FORMAT (2, 3) |
||
330 | _cairo_xml_printf_end (cairo_xml_t *xml, const char *fmt, ...) |
||
331 | { |
||
332 | if (fmt != NULL) { |
||
333 | va_list ap; |
||
334 | |||
335 | va_start (ap, fmt); |
||
336 | _cairo_output_stream_vprintf (xml->stream, fmt, ap); |
||
337 | va_end (ap); |
||
338 | } |
||
339 | |||
340 | _cairo_output_stream_write (xml->stream, "\n", 1); |
||
341 | } |
||
342 | |||
343 | static cairo_surface_t * |
||
344 | _cairo_xml_surface_create_similar (void *abstract_surface, |
||
345 | cairo_content_t content, |
||
346 | int width, |
||
347 | int height) |
||
348 | { |
||
349 | cairo_rectangle_t extents; |
||
350 | |||
351 | extents.x = extents.y = 0; |
||
352 | extents.width = width; |
||
353 | extents.height = height; |
||
354 | |||
355 | return cairo_recording_surface_create (content, &extents); |
||
356 | } |
||
357 | |||
358 | static cairo_bool_t |
||
359 | _cairo_xml_surface_get_extents (void *abstract_surface, |
||
360 | cairo_rectangle_int_t *rectangle) |
||
361 | { |
||
362 | cairo_xml_surface_t *surface = abstract_surface; |
||
363 | |||
364 | if (surface->width < 0 || surface->height < 0) |
||
365 | return FALSE; |
||
366 | |||
367 | rectangle->x = 0; |
||
368 | rectangle->y = 0; |
||
369 | rectangle->width = surface->width; |
||
370 | rectangle->height = surface->height; |
||
371 | |||
372 | return TRUE; |
||
373 | } |
||
374 | |||
375 | static cairo_status_t |
||
376 | _cairo_xml_move_to (void *closure, |
||
377 | const cairo_point_t *p1) |
||
378 | { |
||
379 | _cairo_xml_printf_continue (closure, " %f %f m", |
||
380 | _cairo_fixed_to_double (p1->x), |
||
381 | _cairo_fixed_to_double (p1->y)); |
||
382 | |||
383 | return CAIRO_STATUS_SUCCESS; |
||
384 | } |
||
385 | |||
386 | static cairo_status_t |
||
387 | _cairo_xml_line_to (void *closure, |
||
388 | const cairo_point_t *p1) |
||
389 | { |
||
390 | _cairo_xml_printf_continue (closure, " %f %f l", |
||
391 | _cairo_fixed_to_double (p1->x), |
||
392 | _cairo_fixed_to_double (p1->y)); |
||
393 | |||
394 | return CAIRO_STATUS_SUCCESS; |
||
395 | } |
||
396 | |||
397 | static cairo_status_t |
||
398 | _cairo_xml_curve_to (void *closure, |
||
399 | const cairo_point_t *p1, |
||
400 | const cairo_point_t *p2, |
||
401 | const cairo_point_t *p3) |
||
402 | { |
||
403 | _cairo_xml_printf_continue (closure, " %f %f %f %f %f %f c", |
||
404 | _cairo_fixed_to_double (p1->x), |
||
405 | _cairo_fixed_to_double (p1->y), |
||
406 | _cairo_fixed_to_double (p2->x), |
||
407 | _cairo_fixed_to_double (p2->y), |
||
408 | _cairo_fixed_to_double (p3->x), |
||
409 | _cairo_fixed_to_double (p3->y)); |
||
410 | |||
411 | return CAIRO_STATUS_SUCCESS; |
||
412 | } |
||
413 | |||
414 | static cairo_status_t |
||
415 | _cairo_xml_close_path (void *closure) |
||
416 | { |
||
417 | _cairo_xml_printf_continue (closure, " h"); |
||
418 | |||
419 | return CAIRO_STATUS_SUCCESS; |
||
420 | } |
||
421 | |||
422 | static void |
||
423 | _cairo_xml_emit_path (cairo_xml_t *xml, |
||
424 | const cairo_path_fixed_t *path) |
||
425 | { |
||
426 | cairo_status_t status; |
||
427 | |||
428 | _cairo_xml_printf_start (xml, " |
||
429 | status = _cairo_path_fixed_interpret (path, |
||
430 | _cairo_xml_move_to, |
||
431 | _cairo_xml_line_to, |
||
432 | _cairo_xml_curve_to, |
||
433 | _cairo_xml_close_path, |
||
434 | xml); |
||
435 | assert (status == CAIRO_STATUS_SUCCESS); |
||
436 | _cairo_xml_printf_end (xml, ""); |
||
437 | } |
||
438 | |||
439 | static void |
||
440 | _cairo_xml_emit_string (cairo_xml_t *xml, |
||
441 | const char *node, |
||
442 | const char *data) |
||
443 | { |
||
444 | _cairo_xml_printf (xml, "<%s>%s%s>", node, data, node); |
||
445 | } |
||
446 | |||
447 | static void |
||
448 | _cairo_xml_emit_double (cairo_xml_t *xml, |
||
449 | const char *node, |
||
450 | double data) |
||
451 | { |
||
452 | _cairo_xml_printf (xml, "<%s>%f%s>", node, data, node); |
||
453 | } |
||
454 | |||
455 | static cairo_xml_t * |
||
456 | to_xml (cairo_xml_surface_t *surface) |
||
457 | { |
||
458 | return (cairo_xml_t *) surface->base.device; |
||
459 | } |
||
460 | |||
461 | static cairo_status_t |
||
462 | _cairo_xml_surface_emit_clip_boxes (cairo_xml_surface_t *surface, |
||
463 | cairo_clip_t *clip) |
||
464 | { |
||
465 | cairo_box_t *box; |
||
466 | cairo_status_t status; |
||
467 | cairo_xml_t *xml; |
||
468 | int n; |
||
469 | |||
470 | if (clip->num_boxes == 0) |
||
471 | return CAIRO_STATUS_SUCCESS; |
||
472 | |||
473 | /* skip the trivial clip covering the surface extents */ |
||
474 | if (surface->width >= 0 && surface->height >= 0 && clip->num_boxes == 1) { |
||
475 | box = &clip->boxes[0]; |
||
476 | if (box->p1.x <= 0 && box->p1.y <= 0 && |
||
477 | box->p2.x - box->p1.x >= _cairo_fixed_from_double (surface->width) && |
||
478 | box->p2.y - box->p1.y >= _cairo_fixed_from_double (surface->height)) |
||
479 | { |
||
480 | return CAIRO_STATUS_SUCCESS; |
||
481 | } |
||
482 | } |
||
483 | |||
484 | xml = to_xml (surface); |
||
485 | |||
486 | _cairo_xml_printf (xml, " |
||
487 | _cairo_xml_indent (xml, 2); |
||
488 | |||
489 | _cairo_xml_printf (xml, " |
||
490 | _cairo_xml_indent (xml, 2); |
||
491 | for (n = 0; n < clip->num_boxes; n++) { |
||
492 | box = &clip->boxes[n]; |
||
493 | |||
494 | _cairo_xml_printf_start (xml, "%f %f m", |
||
495 | _cairo_fixed_to_double (box->p1.x), |
||
496 | _cairo_fixed_to_double (box->p1.y)); |
||
497 | _cairo_xml_printf_continue (xml, " %f %f l", |
||
498 | _cairo_fixed_to_double (box->p2.x), |
||
499 | _cairo_fixed_to_double (box->p1.y)); |
||
500 | _cairo_xml_printf_continue (xml, " %f %f l", |
||
501 | _cairo_fixed_to_double (box->p2.x), |
||
502 | _cairo_fixed_to_double (box->p2.y)); |
||
503 | _cairo_xml_printf_continue (xml, " %f %f l", |
||
504 | _cairo_fixed_to_double (box->p1.x), |
||
505 | _cairo_fixed_to_double (box->p2.y)); |
||
506 | _cairo_xml_printf_end (xml, " h"); |
||
507 | } |
||
508 | _cairo_xml_indent (xml, -2); |
||
509 | _cairo_xml_printf (xml, ""); |
||
510 | _cairo_xml_emit_double (xml, "tolerance", 1.0); |
||
511 | _cairo_xml_emit_string (xml, "antialias", |
||
512 | _antialias_to_string (CAIRO_ANTIALIAS_NONE)); |
||
513 | _cairo_xml_emit_string (xml, "fill-rule", |
||
514 | _fill_rule_to_string (CAIRO_FILL_RULE_WINDING)); |
||
515 | |||
516 | _cairo_xml_indent (xml, -2); |
||
517 | _cairo_xml_printf (xml, ""); |
||
518 | |||
519 | return CAIRO_STATUS_SUCCESS; |
||
520 | } |
||
521 | |||
522 | static cairo_status_t |
||
523 | _cairo_xml_surface_emit_clip_path (cairo_xml_surface_t *surface, |
||
524 | cairo_clip_path_t *clip_path) |
||
525 | { |
||
526 | cairo_box_t box; |
||
527 | cairo_status_t status; |
||
528 | cairo_xml_t *xml; |
||
529 | |||
530 | if (clip_path == NULL) |
||
531 | return CAIRO_STATUS_SUCCESS; |
||
532 | |||
533 | status = _cairo_xml_surface_emit_clip_path (surface, clip_path->prev); |
||
534 | if (unlikely (status)) |
||
535 | return status; |
||
536 | |||
537 | /* skip the trivial clip covering the surface extents */ |
||
538 | if (surface->width >= 0 && surface->height >= 0 && |
||
539 | _cairo_path_fixed_is_box (&clip_path->path, &box)) |
||
540 | { |
||
541 | if (box.p1.x <= 0 && box.p1.y <= 0 && |
||
542 | box.p2.x - box.p1.x >= _cairo_fixed_from_double (surface->width) && |
||
543 | box.p2.y - box.p1.y >= _cairo_fixed_from_double (surface->height)) |
||
544 | { |
||
545 | return CAIRO_STATUS_SUCCESS; |
||
546 | } |
||
547 | } |
||
548 | |||
549 | xml = to_xml (surface); |
||
550 | |||
551 | _cairo_xml_printf_start (xml, " |
||
552 | _cairo_xml_indent (xml, 2); |
||
553 | |||
554 | _cairo_xml_emit_path (xml, &clip_path->path); |
||
555 | _cairo_xml_emit_double (xml, "tolerance", clip_path->tolerance); |
||
556 | _cairo_xml_emit_string (xml, "antialias", |
||
557 | _antialias_to_string (clip_path->antialias)); |
||
558 | _cairo_xml_emit_string (xml, "fill-rule", |
||
559 | _fill_rule_to_string (clip_path->fill_rule)); |
||
560 | |||
561 | _cairo_xml_indent (xml, -2); |
||
562 | _cairo_xml_printf_end (xml, ""); |
||
563 | |||
564 | return CAIRO_STATUS_SUCCESS; |
||
565 | } |
||
566 | |||
567 | static cairo_status_t |
||
568 | _cairo_xml_surface_emit_clip (cairo_xml_surface_t *surface, |
||
569 | const cairo_clip_t *clip) |
||
570 | { |
||
571 | cairo_status_t status; |
||
572 | |||
573 | if (clip == NULL) |
||
574 | return CAIRO_STATUS_SUCCESS; |
||
575 | |||
576 | status = _cairo_xml_surface_emit_clip_boxes (surface, clip); |
||
577 | if (unlikely (status)) |
||
578 | return status; |
||
579 | |||
580 | return _cairo_xml_surface_emit_clip_path (surface, clip->path); |
||
581 | } |
||
582 | |||
583 | static cairo_status_t |
||
584 | _cairo_xml_emit_solid (cairo_xml_t *xml, |
||
585 | const cairo_solid_pattern_t *solid) |
||
586 | { |
||
587 | _cairo_xml_printf (xml, " |
||
588 | solid->color.red, |
||
589 | solid->color.green, |
||
590 | solid->color.blue, |
||
591 | solid->color.alpha); |
||
592 | return CAIRO_STATUS_SUCCESS; |
||
593 | } |
||
594 | |||
595 | static void |
||
596 | _cairo_xml_emit_matrix (cairo_xml_t *xml, |
||
597 | const cairo_matrix_t *matrix) |
||
598 | { |
||
599 | if (! _cairo_matrix_is_identity (matrix)) { |
||
600 | _cairo_xml_printf (xml, " |
||
601 | matrix->xx, matrix->yx, |
||
602 | matrix->xy, matrix->yy, |
||
603 | matrix->x0, matrix->y0); |
||
604 | } |
||
605 | } |
||
606 | |||
607 | static void |
||
608 | _cairo_xml_emit_gradient (cairo_xml_t *xml, |
||
609 | const cairo_gradient_pattern_t *gradient) |
||
610 | { |
||
611 | unsigned int i; |
||
612 | |||
613 | for (i = 0; i < gradient->n_stops; i++) { |
||
614 | _cairo_xml_printf (xml, |
||
615 | " |
||
616 | gradient->stops[i].offset, |
||
617 | gradient->stops[i].color.red, |
||
618 | gradient->stops[i].color.green, |
||
619 | gradient->stops[i].color.blue, |
||
620 | gradient->stops[i].color.alpha); |
||
621 | } |
||
622 | } |
||
623 | |||
624 | static cairo_status_t |
||
625 | _cairo_xml_emit_linear (cairo_xml_t *xml, |
||
626 | const cairo_linear_pattern_t *linear) |
||
627 | { |
||
628 | _cairo_xml_printf (xml, |
||
629 | " |
||
630 | linear->pd1.x, linear->pd1.y, |
||
631 | linear->pd2.x, linear->pd2.y); |
||
632 | _cairo_xml_indent (xml, 2); |
||
633 | _cairo_xml_emit_gradient (xml, &linear->base); |
||
634 | _cairo_xml_indent (xml, -2); |
||
635 | _cairo_xml_printf (xml, ""); |
||
636 | return CAIRO_STATUS_SUCCESS; |
||
637 | } |
||
638 | |||
639 | static cairo_status_t |
||
640 | _cairo_xml_emit_radial (cairo_xml_t *xml, |
||
641 | const cairo_radial_pattern_t *radial) |
||
642 | { |
||
643 | _cairo_xml_printf (xml, |
||
644 | " |
||
645 | radial->cd1.center.x, radial->cd1.center.y, radial->cd1.radius, |
||
646 | radial->cd2.center.x, radial->cd2.center.y, radial->cd2.radius); |
||
647 | _cairo_xml_indent (xml, 2); |
||
648 | _cairo_xml_emit_gradient (xml, &radial->base); |
||
649 | _cairo_xml_indent (xml, -2); |
||
650 | _cairo_xml_printf (xml, ""); |
||
651 | return CAIRO_STATUS_SUCCESS; |
||
652 | } |
||
653 | |||
654 | static cairo_status_t |
||
655 | _write_func (void *closure, const unsigned char *data, unsigned len) |
||
656 | { |
||
657 | _cairo_output_stream_write (closure, data, len); |
||
658 | return CAIRO_STATUS_SUCCESS; |
||
659 | } |
||
660 | |||
661 | static cairo_status_t |
||
662 | _cairo_xml_emit_image (cairo_xml_t *xml, |
||
663 | cairo_image_surface_t *image) |
||
664 | { |
||
665 | cairo_output_stream_t *stream; |
||
666 | cairo_status_t status; |
||
667 | |||
668 | _cairo_xml_printf_start (xml, |
||
669 | " |
||
670 | image->width, image->height, |
||
671 | _format_to_string (image->format)); |
||
672 | |||
673 | stream = _cairo_base64_stream_create (xml->stream); |
||
674 | status = cairo_surface_write_to_png_stream (&image->base, |
||
675 | _write_func, stream); |
||
676 | assert (status == CAIRO_STATUS_SUCCESS); |
||
677 | status = _cairo_output_stream_destroy (stream); |
||
678 | if (unlikely (status)) |
||
679 | return status; |
||
680 | |||
681 | _cairo_xml_printf_end (xml, ""); |
||
682 | |||
683 | return CAIRO_STATUS_SUCCESS; |
||
684 | } |
||
685 | |||
686 | static cairo_status_t |
||
687 | _cairo_xml_emit_surface (cairo_xml_t *xml, |
||
688 | const cairo_surface_pattern_t *pattern) |
||
689 | { |
||
690 | cairo_surface_t *source = pattern->surface; |
||
691 | cairo_status_t status; |
||
692 | |||
693 | if (_cairo_surface_is_recording (source)) { |
||
694 | status = cairo_xml_for_recording_surface (&xml->base, source); |
||
695 | } else { |
||
696 | cairo_image_surface_t *image; |
||
697 | void *image_extra; |
||
698 | |||
699 | status = _cairo_surface_acquire_source_image (source, |
||
700 | &image, &image_extra); |
||
701 | if (unlikely (status)) |
||
702 | return status; |
||
703 | |||
704 | status = _cairo_xml_emit_image (xml, image); |
||
705 | |||
706 | _cairo_surface_release_source_image (source, image, image_extra); |
||
707 | } |
||
708 | |||
709 | return status; |
||
710 | } |
||
711 | |||
712 | static cairo_status_t |
||
713 | _cairo_xml_emit_pattern (cairo_xml_t *xml, |
||
714 | const char *source_or_mask, |
||
715 | const cairo_pattern_t *pattern) |
||
716 | { |
||
717 | cairo_status_t status; |
||
718 | |||
719 | _cairo_xml_printf (xml, "<%s-pattern>", source_or_mask); |
||
720 | _cairo_xml_indent (xml, 2); |
||
721 | |||
722 | switch (pattern->type) { |
||
723 | case CAIRO_PATTERN_TYPE_SOLID: |
||
724 | status = _cairo_xml_emit_solid (xml, (cairo_solid_pattern_t *) pattern); |
||
725 | break; |
||
726 | case CAIRO_PATTERN_TYPE_LINEAR: |
||
727 | status = _cairo_xml_emit_linear (xml, (cairo_linear_pattern_t *) pattern); |
||
728 | break; |
||
729 | case CAIRO_PATTERN_TYPE_RADIAL: |
||
730 | status = _cairo_xml_emit_radial (xml, (cairo_radial_pattern_t *) pattern); |
||
731 | break; |
||
732 | case CAIRO_PATTERN_TYPE_SURFACE: |
||
733 | status = _cairo_xml_emit_surface (xml, (cairo_surface_pattern_t *) pattern); |
||
734 | break; |
||
735 | default: |
||
736 | ASSERT_NOT_REACHED; |
||
737 | status = CAIRO_INT_STATUS_UNSUPPORTED; |
||
738 | break; |
||
739 | } |
||
740 | |||
741 | if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) { |
||
742 | _cairo_xml_emit_matrix (xml, &pattern->matrix); |
||
743 | _cairo_xml_printf (xml, |
||
744 | " |
||
745 | _extend_to_string (pattern->extend)); |
||
746 | _cairo_xml_printf (xml, |
||
747 | " |
||
748 | _filter_to_string (pattern->filter)); |
||
749 | } |
||
750 | |||
751 | _cairo_xml_indent (xml, -2); |
||
752 | _cairo_xml_printf (xml, "%s-pattern>", source_or_mask); |
||
753 | |||
754 | return status; |
||
755 | } |
||
756 | |||
757 | static cairo_int_status_t |
||
758 | _cairo_xml_surface_paint (void *abstract_surface, |
||
759 | cairo_operator_t op, |
||
760 | const cairo_pattern_t *source, |
||
761 | const cairo_clip_t *clip) |
||
762 | { |
||
763 | cairo_xml_surface_t *surface = abstract_surface; |
||
764 | cairo_xml_t *xml = to_xml (surface); |
||
765 | cairo_status_t status; |
||
766 | |||
767 | _cairo_xml_printf (xml, " |
||
768 | _cairo_xml_indent (xml, 2); |
||
769 | |||
770 | _cairo_xml_emit_string (xml, "operator", _operator_to_string (op)); |
||
771 | |||
772 | status = _cairo_xml_surface_emit_clip (surface, clip); |
||
773 | if (unlikely (status)) |
||
774 | return status; |
||
775 | |||
776 | status = _cairo_xml_emit_pattern (xml, "source", source); |
||
777 | if (unlikely (status)) |
||
778 | return status; |
||
779 | |||
780 | _cairo_xml_indent (xml, -2); |
||
781 | _cairo_xml_printf (xml, ""); |
||
782 | |||
783 | return CAIRO_STATUS_SUCCESS; |
||
784 | } |
||
785 | |||
786 | static cairo_int_status_t |
||
787 | _cairo_xml_surface_mask (void *abstract_surface, |
||
788 | cairo_operator_t op, |
||
789 | const cairo_pattern_t *source, |
||
790 | const cairo_pattern_t *mask, |
||
791 | const cairo_clip_t *clip) |
||
792 | { |
||
793 | cairo_xml_surface_t *surface = abstract_surface; |
||
794 | cairo_xml_t *xml = to_xml (surface); |
||
795 | cairo_status_t status; |
||
796 | |||
797 | _cairo_xml_printf (xml, " |
||
798 | _cairo_xml_indent (xml, 2); |
||
799 | |||
800 | _cairo_xml_emit_string (xml, "operator", _operator_to_string (op)); |
||
801 | |||
802 | status = _cairo_xml_surface_emit_clip (surface, clip); |
||
803 | if (unlikely (status)) |
||
804 | return status; |
||
805 | |||
806 | status = _cairo_xml_emit_pattern (xml, "source", source); |
||
807 | if (unlikely (status)) |
||
808 | return status; |
||
809 | |||
810 | status = _cairo_xml_emit_pattern (xml, "mask", mask); |
||
811 | if (unlikely (status)) |
||
812 | return status; |
||
813 | |||
814 | _cairo_xml_indent (xml, -2); |
||
815 | _cairo_xml_printf (xml, ""); |
||
816 | |||
817 | return CAIRO_STATUS_SUCCESS; |
||
818 | } |
||
819 | |||
820 | static cairo_int_status_t |
||
821 | _cairo_xml_surface_stroke (void *abstract_surface, |
||
822 | cairo_operator_t op, |
||
823 | const cairo_pattern_t *source, |
||
824 | const cairo_path_fixed_t *path, |
||
825 | const cairo_stroke_style_t *style, |
||
826 | const cairo_matrix_t *ctm, |
||
827 | const cairo_matrix_t *ctm_inverse, |
||
828 | double tolerance, |
||
829 | cairo_antialias_t antialias, |
||
830 | const cairo_clip_t *clip) |
||
831 | { |
||
832 | cairo_xml_surface_t *surface = abstract_surface; |
||
833 | cairo_xml_t *xml = to_xml (surface); |
||
834 | cairo_status_t status; |
||
835 | |||
836 | _cairo_xml_printf (xml, " |
||
837 | _cairo_xml_indent (xml, 2); |
||
838 | |||
839 | _cairo_xml_emit_string (xml, "operator", _operator_to_string (op)); |
||
840 | _cairo_xml_emit_double (xml, "line-width", style->line_width); |
||
841 | _cairo_xml_emit_double (xml, "miter-limit", style->miter_limit); |
||
842 | _cairo_xml_emit_string (xml, "line-cap", _line_cap_to_string (style->line_cap)); |
||
843 | _cairo_xml_emit_string (xml, "line-join", _line_join_to_string (style->line_join)); |
||
844 | |||
845 | status = _cairo_xml_surface_emit_clip (surface, clip); |
||
846 | if (unlikely (status)) |
||
847 | return status; |
||
848 | |||
849 | status = _cairo_xml_emit_pattern (xml, "source", source); |
||
850 | if (unlikely (status)) |
||
851 | return status; |
||
852 | |||
853 | if (style->num_dashes) { |
||
854 | unsigned int i; |
||
855 | |||
856 | _cairo_xml_printf_start (xml, " |
||
857 | style->dash_offset); |
||
858 | for (i = 0; i < style->num_dashes; i++) |
||
859 | _cairo_xml_printf_continue (xml, "%f ", style->dash[i]); |
||
860 | |||
861 | _cairo_xml_printf_end (xml, ""); |
||
862 | } |
||
863 | |||
864 | _cairo_xml_emit_path (xml, path); |
||
865 | _cairo_xml_emit_double (xml, "tolerance", tolerance); |
||
866 | _cairo_xml_emit_string (xml, "antialias", _antialias_to_string (antialias)); |
||
867 | |||
868 | _cairo_xml_emit_matrix (xml, ctm); |
||
869 | |||
870 | _cairo_xml_indent (xml, -2); |
||
871 | _cairo_xml_printf (xml, ""); |
||
872 | |||
873 | return CAIRO_STATUS_SUCCESS; |
||
874 | } |
||
875 | |||
876 | static cairo_int_status_t |
||
877 | _cairo_xml_surface_fill (void *abstract_surface, |
||
878 | cairo_operator_t op, |
||
879 | const cairo_pattern_t *source, |
||
880 | const cairo_path_fixed_t*path, |
||
881 | cairo_fill_rule_t fill_rule, |
||
882 | double tolerance, |
||
883 | cairo_antialias_t antialias, |
||
884 | const cairo_clip_t *clip) |
||
885 | { |
||
886 | cairo_xml_surface_t *surface = abstract_surface; |
||
887 | cairo_xml_t *xml = to_xml (surface); |
||
888 | cairo_status_t status; |
||
889 | |||
890 | _cairo_xml_printf (xml, " |
||
891 | _cairo_xml_indent (xml, 2); |
||
892 | |||
893 | _cairo_xml_emit_string (xml, "operator", _operator_to_string (op)); |
||
894 | |||
895 | status = _cairo_xml_surface_emit_clip (surface, clip); |
||
896 | if (unlikely (status)) |
||
897 | return status; |
||
898 | |||
899 | status = _cairo_xml_emit_pattern (xml, "source", source); |
||
900 | if (unlikely (status)) |
||
901 | return status; |
||
902 | |||
903 | _cairo_xml_emit_path (xml, path); |
||
904 | _cairo_xml_emit_double (xml, "tolerance", tolerance); |
||
905 | _cairo_xml_emit_string (xml, "antialias", _antialias_to_string (antialias)); |
||
906 | _cairo_xml_emit_string (xml, "fill-rule", _fill_rule_to_string (fill_rule)); |
||
907 | |||
908 | _cairo_xml_indent (xml, -2); |
||
909 | _cairo_xml_printf (xml, ""); |
||
910 | |||
911 | return CAIRO_STATUS_SUCCESS; |
||
912 | } |
||
913 | |||
914 | #if CAIRO_HAS_FT_FONT |
||
915 | #include "cairo-ft-private.h" |
||
916 | static cairo_status_t |
||
917 | _cairo_xml_emit_type42_font (cairo_xml_t *xml, |
||
918 | cairo_scaled_font_t *scaled_font) |
||
919 | { |
||
920 | const cairo_scaled_font_backend_t *backend; |
||
921 | cairo_output_stream_t *base64_stream; |
||
922 | cairo_output_stream_t *zlib_stream; |
||
923 | cairo_status_t status, status2; |
||
924 | unsigned long size; |
||
925 | uint32_t len; |
||
926 | uint8_t *buf; |
||
927 | |||
928 | backend = scaled_font->backend; |
||
929 | if (backend->load_truetype_table == NULL) |
||
930 | return CAIRO_INT_STATUS_UNSUPPORTED; |
||
931 | |||
932 | size = 0; |
||
933 | status = backend->load_truetype_table (scaled_font, 0, 0, NULL, &size); |
||
934 | if (unlikely (status)) |
||
935 | return status; |
||
936 | |||
937 | buf = malloc (size); |
||
938 | if (unlikely (buf == NULL)) |
||
939 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
||
940 | |||
941 | status = backend->load_truetype_table (scaled_font, 0, 0, buf, &size); |
||
942 | if (unlikely (status)) { |
||
943 | free (buf); |
||
944 | return status; |
||
945 | } |
||
946 | |||
947 | _cairo_xml_printf_start (xml, "", |
||
948 | _cairo_ft_scaled_font_get_load_flags (scaled_font)); |
||
949 | |||
950 | |||
951 | base64_stream = _cairo_base64_stream_create (xml->stream); |
||
952 | len = size; |
||
953 | _cairo_output_stream_write (base64_stream, &len, sizeof (len)); |
||
954 | |||
955 | zlib_stream = _cairo_deflate_stream_create (base64_stream); |
||
956 | |||
957 | _cairo_output_stream_write (zlib_stream, buf, size); |
||
958 | free (buf); |
||
959 | |||
960 | status2 = _cairo_output_stream_destroy (zlib_stream); |
||
961 | if (status == CAIRO_STATUS_SUCCESS) |
||
962 | status = status2; |
||
963 | |||
964 | status2 = _cairo_output_stream_destroy (base64_stream); |
||
965 | if (status == CAIRO_STATUS_SUCCESS) |
||
966 | status = status2; |
||
967 | |||
968 | _cairo_xml_printf_end (xml, ""); |
||
969 | |||
970 | return status; |
||
971 | } |
||
972 | #else |
||
973 | static cairo_status_t |
||
974 | _cairo_xml_emit_type42_font (cairo_xml_t *xml, |
||
975 | cairo_scaled_font_t *scaled_font) |
||
976 | { |
||
977 | return CAIRO_INT_STATUS_UNSUPPORTED; |
||
978 | } |
||
979 | #endif |
||
980 | |||
981 | static cairo_status_t |
||
982 | _cairo_xml_emit_type3_font (cairo_xml_t *xml, |
||
983 | cairo_scaled_font_t *scaled_font, |
||
984 | cairo_glyph_t *glyphs, |
||
985 | int num_glyphs) |
||
986 | { |
||
987 | _cairo_xml_printf_start (xml, ""); |
||
988 | _cairo_xml_printf_end (xml, ""); |
||
989 | |||
990 | return CAIRO_STATUS_SUCCESS; |
||
991 | } |
||
992 | |||
993 | static cairo_status_t |
||
994 | _cairo_xml_emit_scaled_font (cairo_xml_t *xml, |
||
995 | cairo_scaled_font_t *scaled_font, |
||
996 | cairo_glyph_t *glyphs, |
||
997 | int num_glyphs) |
||
998 | { |
||
999 | cairo_int_status_t status; |
||
1000 | |||
1001 | _cairo_xml_printf (xml, " |
||
1002 | _cairo_xml_indent (xml, 2); |
||
1003 | |||
1004 | status = _cairo_xml_emit_type42_font (xml, scaled_font); |
||
1005 | if (status == CAIRO_INT_STATUS_UNSUPPORTED) { |
||
1006 | status = _cairo_xml_emit_type3_font (xml, scaled_font, |
||
1007 | glyphs, num_glyphs); |
||
1008 | } |
||
1009 | |||
1010 | _cairo_xml_indent (xml, -2); |
||
1011 | _cairo_xml_printf (xml, " |
||
1012 | |||
1013 | return status; |
||
1014 | } |
||
1015 | |||
1016 | static cairo_int_status_t |
||
1017 | _cairo_xml_surface_glyphs (void *abstract_surface, |
||
1018 | cairo_operator_t op, |
||
1019 | const cairo_pattern_t *source, |
||
1020 | cairo_glyph_t *glyphs, |
||
1021 | int num_glyphs, |
||
1022 | cairo_scaled_font_t *scaled_font, |
||
1023 | const cairo_clip_t *clip) |
||
1024 | { |
||
1025 | cairo_xml_surface_t *surface = abstract_surface; |
||
1026 | cairo_xml_t *xml = to_xml (surface); |
||
1027 | cairo_status_t status; |
||
1028 | int i; |
||
1029 | |||
1030 | _cairo_xml_printf (xml, " |
||
1031 | _cairo_xml_indent (xml, 2); |
||
1032 | |||
1033 | _cairo_xml_emit_string (xml, "operator", _operator_to_string (op)); |
||
1034 | |||
1035 | status = _cairo_xml_surface_emit_clip (surface, clip); |
||
1036 | if (unlikely (status)) |
||
1037 | return status; |
||
1038 | |||
1039 | status = _cairo_xml_emit_pattern (xml, "source", source); |
||
1040 | if (unlikely (status)) |
||
1041 | return status; |
||
1042 | |||
1043 | status = _cairo_xml_emit_scaled_font (xml, scaled_font, glyphs, num_glyphs); |
||
1044 | if (unlikely (status)) |
||
1045 | return status; |
||
1046 | |||
1047 | for (i = 0; i < num_glyphs; i++) { |
||
1048 | _cairo_xml_printf (xml, " |
||
1049 | glyphs[i].index, |
||
1050 | glyphs[i].x, |
||
1051 | glyphs[i].y); |
||
1052 | } |
||
1053 | |||
1054 | _cairo_xml_indent (xml, -2); |
||
1055 | _cairo_xml_printf (xml, ""); |
||
1056 | |||
1057 | return CAIRO_STATUS_SUCCESS; |
||
1058 | } |
||
1059 | |||
1060 | static const cairo_surface_backend_t |
||
1061 | _cairo_xml_surface_backend = { |
||
1062 | CAIRO_SURFACE_TYPE_XML, |
||
1063 | NULL, |
||
1064 | |||
1065 | _cairo_default_context_create, |
||
1066 | |||
1067 | _cairo_xml_surface_create_similar, |
||
1068 | NULL, /* create_similar_image */ |
||
1069 | NULL, /* map_to_image */ |
||
1070 | NULL, /* unmap_image */ |
||
1071 | |||
1072 | _cairo_surface_default_source, |
||
1073 | NULL, /* acquire source image */ |
||
1074 | NULL, /* release source image */ |
||
1075 | NULL, /* snapshot */ |
||
1076 | |||
1077 | NULL, /* copy page */ |
||
1078 | NULL, /* show page */ |
||
1079 | |||
1080 | _cairo_xml_surface_get_extents, |
||
1081 | NULL, /* get_font_options */ |
||
1082 | |||
1083 | NULL, /* flush */ |
||
1084 | NULL, /* mark_dirty_rectangle */ |
||
1085 | |||
1086 | _cairo_xml_surface_paint, |
||
1087 | _cairo_xml_surface_mask, |
||
1088 | _cairo_xml_surface_stroke, |
||
1089 | _cairo_xml_surface_fill, |
||
1090 | NULL, /* fill_stroke */ |
||
1091 | _cairo_xml_surface_glyphs, |
||
1092 | }; |
||
1093 | |||
1094 | static cairo_surface_t * |
||
1095 | _cairo_xml_surface_create_internal (cairo_device_t *device, |
||
1096 | cairo_content_t content, |
||
1097 | double width, |
||
1098 | double height) |
||
1099 | { |
||
1100 | cairo_xml_surface_t *surface; |
||
1101 | |||
1102 | surface = malloc (sizeof (cairo_xml_surface_t)); |
||
1103 | if (unlikely (surface == NULL)) |
||
1104 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
||
1105 | |||
1106 | _cairo_surface_init (&surface->base, |
||
1107 | &_cairo_xml_surface_backend, |
||
1108 | device, |
||
1109 | content); |
||
1110 | |||
1111 | surface->width = width; |
||
1112 | surface->height = height; |
||
1113 | |||
1114 | return &surface->base; |
||
1115 | } |
||
1116 | |||
1117 | cairo_device_t * |
||
1118 | cairo_xml_create (const char *filename) |
||
1119 | { |
||
1120 | cairo_output_stream_t *stream; |
||
1121 | cairo_status_t status; |
||
1122 | |||
1123 | stream = _cairo_output_stream_create_for_filename (filename); |
||
1124 | if ((status = _cairo_output_stream_get_status (stream))) |
||
1125 | return _cairo_device_create_in_error (status); |
||
1126 | |||
1127 | return _cairo_xml_create_internal (stream); |
||
1128 | } |
||
1129 | |||
1130 | cairo_device_t * |
||
1131 | cairo_xml_create_for_stream (cairo_write_func_t write_func, |
||
1132 | void *closure) |
||
1133 | { |
||
1134 | cairo_output_stream_t *stream; |
||
1135 | cairo_status_t status; |
||
1136 | |||
1137 | stream = _cairo_output_stream_create (write_func, NULL, closure); |
||
1138 | if ((status = _cairo_output_stream_get_status (stream))) |
||
1139 | return _cairo_device_create_in_error (status); |
||
1140 | |||
1141 | return _cairo_xml_create_internal (stream); |
||
1142 | } |
||
1143 | |||
1144 | cairo_surface_t * |
||
1145 | cairo_xml_surface_create (cairo_device_t *device, |
||
1146 | cairo_content_t content, |
||
1147 | double width, double height) |
||
1148 | { |
||
1149 | if (unlikely (device->backend->type != CAIRO_DEVICE_TYPE_XML)) |
||
1150 | return _cairo_surface_create_in_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); |
||
1151 | |||
1152 | if (unlikely (device->status)) |
||
1153 | return _cairo_surface_create_in_error (device->status); |
||
1154 | |||
1155 | return _cairo_xml_surface_create_internal (device, content, width, height); |
||
1156 | } |
||
1157 | |||
1158 | cairo_status_t |
||
1159 | cairo_xml_for_recording_surface (cairo_device_t *device, |
||
1160 | cairo_surface_t *recording_surface) |
||
1161 | { |
||
1162 | cairo_box_t bbox; |
||
1163 | cairo_rectangle_int_t extents; |
||
1164 | cairo_surface_t *surface; |
||
1165 | cairo_xml_t *xml; |
||
1166 | cairo_status_t status; |
||
1167 | |||
1168 | if (unlikely (device->status)) |
||
1169 | return device->status; |
||
1170 | |||
1171 | if (unlikely (recording_surface->status)) |
||
1172 | return recording_surface->status; |
||
1173 | |||
1174 | if (unlikely (device->backend->type != CAIRO_DEVICE_TYPE_XML)) |
||
1175 | return _cairo_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); |
||
1176 | |||
1177 | if (unlikely (! _cairo_surface_is_recording (recording_surface))) |
||
1178 | return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); |
||
1179 | |||
1180 | status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface, |
||
1181 | &bbox, NULL); |
||
1182 | if (unlikely (status)) |
||
1183 | return status; |
||
1184 | |||
1185 | _cairo_box_round_to_rectangle (&bbox, &extents); |
||
1186 | surface = _cairo_xml_surface_create_internal (device, |
||
1187 | recording_surface->content, |
||
1188 | extents.width, |
||
1189 | extents.height); |
||
1190 | if (unlikely (surface->status)) |
||
1191 | return surface->status; |
||
1192 | |||
1193 | xml = (cairo_xml_t *) device; |
||
1194 | |||
1195 | _cairo_xml_printf (xml, |
||
1196 | " |
||
1197 | _content_to_string (recording_surface->content), |
||
1198 | extents.width, extents.height); |
||
1199 | _cairo_xml_indent (xml, 2); |
||
1200 | |||
1201 | cairo_surface_set_device_offset (surface, -extents.x, -extents.y); |
||
1202 | status = _cairo_recording_surface_replay (recording_surface, surface); |
||
1203 | cairo_surface_destroy (surface); |
||
1204 | |||
1205 | _cairo_xml_indent (xml, -2); |
||
1206 | _cairo_xml_printf (xml, ""); |
||
1207 | |||
1208 | return status; |
||
1209 | } |
||
1210 | slim_hidden_def (cairo_xml_for_recording_surface);>>>=>=>>=>=>>>>>>>>>> |