Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1892 Rev 3959
Line 33... Line 33...
33
 *      Chris Wilson 
33
 *      Chris Wilson 
34
 */
34
 */
Line 35... Line 35...
35
 
35
 
Line -... Line 36...
-
 
36
#include "cairoint.h"
36
#include "cairoint.h"
37
 
-
 
38
#include "cairo-clip-inline.h"
37
 
39
#include "cairo-error-private.h"
38
#include "cairo-error-private.h"
40
#include "cairo-image-surface-private.h"
-
 
41
#include "cairo-recording-surface-private.h"
39
#include "cairo-recording-surface-private.h"
42
#include "cairo-surface-offset-private.h"
Line 40... Line 43...
40
#include "cairo-surface-offset-private.h"
43
#include "cairo-surface-snapshot-private.h"
Line 41... Line 44...
41
#include "cairo-surface-subsurface-private.h"
44
#include "cairo-surface-subsurface-private.h"
42
 
45
 
43
static const cairo_surface_backend_t _cairo_surface_subsurface_backend;
46
static const cairo_surface_backend_t _cairo_surface_subsurface_backend;
44
 
47
 
Line 45... Line 48...
45
static cairo_status_t
48
static cairo_status_t
-
 
49
_cairo_surface_subsurface_finish (void *abstract_surface)
Line 46... Line 50...
46
_cairo_surface_subsurface_finish (void *abstract_surface)
50
{
47
{
51
    cairo_surface_subsurface_t *surface = abstract_surface;
Line 48... Line 52...
48
    cairo_surface_subsurface_t *surface = abstract_surface;
52
 
49
 
53
    cairo_surface_destroy (surface->target);
50
    cairo_surface_destroy (surface->target);
54
    cairo_surface_destroy (surface->snapshot);
51
 
55
 
52
    return CAIRO_STATUS_SUCCESS;
56
    return CAIRO_STATUS_SUCCESS;
53
}
57
}
-
 
58
 
-
 
59
static cairo_surface_t *
-
 
60
_cairo_surface_subsurface_create_similar (void *other,
-
 
61
					  cairo_content_t content,
54
 
62
					  int width, int height)
55
static cairo_surface_t *
63
{
Line -... Line 64...
-
 
64
    cairo_surface_subsurface_t *surface = other;
-
 
65
 
-
 
66
    if (surface->target->backend->create_similar == NULL)
-
 
67
	return NULL;
-
 
68
 
-
 
69
    return surface->target->backend->create_similar (surface->target, content, width, height);
-
 
70
}
-
 
71
 
-
 
72
static cairo_surface_t *
-
 
73
_cairo_surface_subsurface_create_similar_image (void *other,
-
 
74
						cairo_format_t format,
-
 
75
						int width, int height)
-
 
76
{
-
 
77
    cairo_surface_subsurface_t *surface = other;
-
 
78
 
-
 
79
    if (surface->target->backend->create_similar_image == NULL)
-
 
80
	return NULL;
-
 
81
 
-
 
82
    return surface->target->backend->create_similar_image (surface->target,
-
 
83
							   format,
-
 
84
							   width, height);
-
 
85
}
-
 
86
 
-
 
87
static cairo_image_surface_t *
-
 
88
_cairo_surface_subsurface_map_to_image (void *abstract_surface,
-
 
89
					const cairo_rectangle_int_t *extents)
-
 
90
{
-
 
91
    cairo_surface_subsurface_t *surface = abstract_surface;
-
 
92
    cairo_rectangle_int_t target_extents;
-
 
93
 
-
 
94
    target_extents.x = extents->x + surface->extents.x;
-
 
95
    target_extents.y = extents->y + surface->extents.y;
-
 
96
    target_extents.width  = extents->width;
-
 
97
    target_extents.height = extents->height;
-
 
98
 
-
 
99
    return _cairo_surface_map_to_image (surface->target, &target_extents);
-
 
100
}
-
 
101
 
56
_cairo_surface_subsurface_create_similar (void *other,
102
static cairo_int_status_t
57
					  cairo_content_t content,
103
_cairo_surface_subsurface_unmap_image (void *abstract_surface,
58
					  int width, int height)
104
				       cairo_image_surface_t *image)
59
{
105
{
60
    cairo_surface_subsurface_t *surface = other;
106
    cairo_surface_subsurface_t *surface = abstract_surface;
61
    return surface->target->backend->create_similar (surface->target, content, width, height);
107
    return _cairo_surface_unmap_image (surface->target, image);
62
}
108
}
63
 
109
 
64
static cairo_int_status_t
110
static cairo_int_status_t
65
_cairo_surface_subsurface_paint (void *abstract_surface,
111
_cairo_surface_subsurface_paint (void *abstract_surface,
66
				 cairo_operator_t op,
-
 
67
				 const cairo_pattern_t *source,
-
 
68
				 cairo_clip_t *clip)
-
 
69
{
-
 
70
    cairo_surface_subsurface_t *surface = abstract_surface;
-
 
Line -... Line 112...
-
 
112
				 cairo_operator_t op,
71
    cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
113
				 const cairo_pattern_t *source,
72
    cairo_status_t status;
114
				 const cairo_clip_t *clip)
73
    cairo_clip_t target_clip;
115
{
74
 
-
 
75
    _cairo_clip_init_copy (&target_clip, clip);
116
    cairo_surface_subsurface_t *surface = abstract_surface;
76
    status = _cairo_clip_rectangle (&target_clip, &rect);
117
    cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
77
    if (unlikely (status))
118
    cairo_status_t status;
Line 78... Line 119...
78
	goto CLEANUP;
119
    cairo_clip_t *target_clip;
79
 
120
 
80
    status = _cairo_surface_offset_paint (surface->target,
121
    target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect);
81
					 -surface->extents.x, -surface->extents.y,
122
    status = _cairo_surface_offset_paint (surface->target,
82
					  op, source, &target_clip);
123
					 -surface->extents.x, -surface->extents.y,
83
  CLEANUP:
124
					  op, source, target_clip);
84
    _cairo_clip_fini (&target_clip);
125
    _cairo_clip_destroy (target_clip);
85
    return status;
126
    return status;
86
}
127
}
87
 
128
 
88
static cairo_int_status_t
129
static cairo_int_status_t
89
_cairo_surface_subsurface_mask (void *abstract_surface,
-
 
90
				cairo_operator_t op,
-
 
91
				const cairo_pattern_t *source,
-
 
92
				const cairo_pattern_t *mask,
-
 
93
				cairo_clip_t *clip)
-
 
Line -... Line 130...
-
 
130
_cairo_surface_subsurface_mask (void *abstract_surface,
94
{
131
				cairo_operator_t op,
95
    cairo_surface_subsurface_t *surface = abstract_surface;
132
				const cairo_pattern_t *source,
96
    cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
133
				const cairo_pattern_t *mask,
97
    cairo_status_t status;
-
 
98
    cairo_clip_t target_clip;
134
				const cairo_clip_t *clip)
99
 
135
{
100
    _cairo_clip_init_copy (&target_clip, clip);
136
    cairo_surface_subsurface_t *surface = abstract_surface;
Line 101... Line 137...
101
    status = _cairo_clip_rectangle (&target_clip, &rect);
137
    cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
102
    if (unlikely (status))
138
    cairo_status_t status;
103
	goto CLEANUP;
139
    cairo_clip_t *target_clip;
104
 
140
 
105
    status = _cairo_surface_offset_mask (surface->target,
141
    target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect);
106
					 -surface->extents.x, -surface->extents.y,
142
    status = _cairo_surface_offset_mask (surface->target,
107
					 op, source, mask, &target_clip);
143
					 -surface->extents.x, -surface->extents.y,
108
  CLEANUP:
144
					 op, source, mask, target_clip);
109
    _cairo_clip_fini (&target_clip);
145
    _cairo_clip_destroy (target_clip);
110
    return status;
146
    return status;
111
}
147
}
112
 
148
 
113
static cairo_int_status_t
149
static cairo_int_status_t
114
_cairo_surface_subsurface_fill (void			*abstract_surface,
150
_cairo_surface_subsurface_fill (void			*abstract_surface,
115
				cairo_operator_t	 op,
-
 
116
				const cairo_pattern_t	*source,
-
 
117
				cairo_path_fixed_t	*path,
-
 
118
				cairo_fill_rule_t	 fill_rule,
-
 
119
				double			 tolerance,
-
 
Line -... Line 151...
-
 
151
				cairo_operator_t	 op,
120
				cairo_antialias_t	 antialias,
152
				const cairo_pattern_t	*source,
121
				cairo_clip_t		*clip)
153
				const cairo_path_fixed_t	*path,
122
{
154
				cairo_fill_rule_t	 fill_rule,
123
    cairo_surface_subsurface_t *surface = abstract_surface;
155
				double			 tolerance,
124
    cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
-
 
125
    cairo_status_t status;
156
				cairo_antialias_t	 antialias,
126
    cairo_clip_t target_clip;
157
				const cairo_clip_t		*clip)
127
 
158
{
Line 128... Line 159...
128
    _cairo_clip_init_copy (&target_clip, clip);
159
    cairo_surface_subsurface_t *surface = abstract_surface;
129
    status = _cairo_clip_rectangle (&target_clip, &rect);
160
    cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
130
    if (unlikely (status))
161
    cairo_status_t status;
131
	goto CLEANUP;
162
    cairo_clip_t *target_clip;
132
 
163
 
133
    status = _cairo_surface_offset_fill (surface->target,
164
    target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect);
134
					 -surface->extents.x, -surface->extents.y,
165
    status = _cairo_surface_offset_fill (surface->target,
135
					 op, source, path, fill_rule, tolerance, antialias,
166
					 -surface->extents.x, -surface->extents.y,
136
					 &target_clip);
167
					 op, source, path, fill_rule, tolerance, antialias,
137
  CLEANUP:
168
					 target_clip);
138
    _cairo_clip_fini (&target_clip);
169
    _cairo_clip_destroy (target_clip);
139
    return status;
170
    return status;
140
}
171
}
141
 
172
 
142
static cairo_int_status_t
173
static cairo_int_status_t
143
_cairo_surface_subsurface_stroke (void				*abstract_surface,
174
_cairo_surface_subsurface_stroke (void				*abstract_surface,
144
				  cairo_operator_t		 op,
-
 
145
				  const cairo_pattern_t		*source,
-
 
146
				  cairo_path_fixed_t		*path,
-
 
147
				  const cairo_stroke_style_t	*stroke_style,
-
 
148
				  const cairo_matrix_t		*ctm,
-
 
Line -... Line 175...
-
 
175
				  cairo_operator_t		 op,
149
				  const cairo_matrix_t		*ctm_inverse,
176
				  const cairo_pattern_t		*source,
150
				  double			 tolerance,
177
				  const cairo_path_fixed_t		*path,
151
				  cairo_antialias_t		 antialias,
178
				  const cairo_stroke_style_t	*stroke_style,
152
				  cairo_clip_t			*clip)
179
				  const cairo_matrix_t		*ctm,
153
{
180
				  const cairo_matrix_t		*ctm_inverse,
154
    cairo_surface_subsurface_t *surface = abstract_surface;
-
 
155
    cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
181
				  double			 tolerance,
156
    cairo_status_t status;
182
				  cairo_antialias_t		 antialias,
157
    cairo_clip_t target_clip;
183
				  const cairo_clip_t			*clip)
Line 158... Line 184...
158
 
184
{
159
    _cairo_clip_init_copy (&target_clip, clip);
185
    cairo_surface_subsurface_t *surface = abstract_surface;
160
    status = _cairo_clip_rectangle (&target_clip, &rect);
186
    cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
161
    if (unlikely (status))
187
    cairo_status_t status;
162
	goto CLEANUP;
188
    cairo_clip_t *target_clip;
163
 
189
 
164
    status = _cairo_surface_offset_stroke (surface->target,
190
    target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect);
165
					   -surface->extents.x, -surface->extents.y,
191
    status = _cairo_surface_offset_stroke (surface->target,
166
					   op, source, path, stroke_style, ctm, ctm_inverse,
-
 
167
					   tolerance, antialias,
192
					   -surface->extents.x, -surface->extents.y,
168
					   &target_clip);
193
					   op, source, path, stroke_style, ctm, ctm_inverse,
169
  CLEANUP:
194
					   tolerance, antialias,
170
    _cairo_clip_fini (&target_clip);
195
					   target_clip);
171
    return status;
196
    _cairo_clip_destroy (target_clip);
172
}
-
 
173
 
-
 
174
static cairo_int_status_t
-
 
175
_cairo_surface_subsurface_glyphs (void			*abstract_surface,
-
 
176
				  cairo_operator_t	 op,
-
 
Line -... Line 197...
-
 
197
    return status;
177
				  const cairo_pattern_t	*source,
198
}
178
				  cairo_glyph_t		*glyphs,
199
 
179
				  int			 num_glyphs,
200
static cairo_int_status_t
180
				  cairo_scaled_font_t	*scaled_font,
201
_cairo_surface_subsurface_glyphs (void			*abstract_surface,
181
				  cairo_clip_t		*clip,
202
				  cairo_operator_t	 op,
182
				  int *remaining_glyphs)
-
 
183
{
-
 
184
    cairo_surface_subsurface_t *surface = abstract_surface;
203
				  const cairo_pattern_t	*source,
185
    cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
204
				  cairo_glyph_t		*glyphs,
186
    cairo_status_t status;
205
				  int			 num_glyphs,
Line 187... Line 206...
187
    cairo_clip_t target_clip;
206
				  cairo_scaled_font_t	*scaled_font,
188
 
207
				  const cairo_clip_t	*clip)
189
    _cairo_clip_init_copy (&target_clip, clip);
208
{
190
    status = _cairo_clip_rectangle (&target_clip, &rect);
209
    cairo_surface_subsurface_t *surface = abstract_surface;
191
    if (unlikely (status))
-
 
192
	goto CLEANUP;
-
 
193
 
-
 
194
    status = _cairo_surface_offset_glyphs (surface->target,
-
 
195
					   -surface->extents.x, -surface->extents.y,
210
    cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
196
					   op, source,
-
 
197
					   scaled_font, glyphs, num_glyphs,
-
 
198
					   &target_clip);
211
    cairo_status_t status;
Line 199... Line 212...
199
    *remaining_glyphs = 0;
212
    cairo_clip_t *target_clip;
200
  CLEANUP:
213
 
201
    _cairo_clip_fini (&target_clip);
214
    target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect);
Line 269... Line 282...
269
 
282
 
270
    if (surface->target->backend->get_font_options != NULL)
283
    if (surface->target->backend->get_font_options != NULL)
271
	surface->target->backend->get_font_options (surface->target, options);
284
	surface->target->backend->get_font_options (surface->target, options);
Line 272... Line -...
272
}
-
 
273
 
285
}
274
struct extra {
-
 
275
    cairo_image_surface_t *image;
-
 
276
    void *image_extra;
-
 
277
};
-
 
278
 
286
 
279
static void
287
static cairo_surface_t *
280
cairo_surface_paint_to_target (cairo_surface_t            *target,
288
_cairo_surface_subsurface_source (void *abstract_surface,
281
                               cairo_surface_subsurface_t *subsurface)
289
				  cairo_rectangle_int_t *extents)
282
{
-
 
283
    cairo_t *cr;
290
{
Line 284... Line -...
284
    
-
 
285
    cr = cairo_create (target);
291
    cairo_surface_subsurface_t *surface = abstract_surface;
286
 
292
    cairo_surface_t *source;
287
    cairo_set_source_surface (cr,
293
 
288
                              subsurface->target,
-
 
289
                              - subsurface->extents.x,
-
 
Line 290... Line 294...
290
                              - subsurface->extents.y);
294
    source = _cairo_surface_get_source (surface->target, extents);
291
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
295
    if (extents)
Line 292... Line 296...
292
    cairo_paint (cr);
296
	*extents = surface->extents;
293
    
297
 
294
    cairo_destroy (cr);
298
    return source;
295
}
299
}
296
 
300
 
297
static cairo_status_t
-
 
298
_cairo_surface_subsurface_acquire_source_image (void                    *abstract_surface,
301
static cairo_status_t
-
 
302
_cairo_surface_subsurface_acquire_source_image (void                    *abstract_surface,
299
						cairo_image_surface_t  **image_out,
303
						cairo_image_surface_t  **image_out,
300
						void                   **extra_out)
304
						void                   **extra_out)
301
{
-
 
302
    cairo_rectangle_int_t target_extents;
-
 
303
    cairo_surface_subsurface_t *surface = abstract_surface;
-
 
304
    cairo_image_surface_t *image;
-
 
305
    cairo_status_t status;
-
 
306
    struct extra *extra;
-
 
307
    uint8_t *data;
-
 
308
    cairo_bool_t ret;
-
 
309
 
-
 
310
    if (surface->target->type == CAIRO_SURFACE_TYPE_RECORDING) {
-
 
311
	cairo_recording_surface_t *meta = (cairo_recording_surface_t *) surface->target;
-
 
312
	cairo_surface_t *snapshot;
-
 
313
 
-
 
314
	snapshot = _cairo_surface_has_snapshot (&surface->base,
-
 
315
						&_cairo_image_surface_backend);
-
 
Line 316... Line -...
316
	if (snapshot != NULL) {
-
 
317
	    *image_out = (cairo_image_surface_t *) cairo_surface_reference (snapshot);
-
 
318
	    *extra_out = NULL;
-
 
319
	    return CAIRO_STATUS_SUCCESS;
-
 
320
	}
305
{
321
 
306
    cairo_surface_subsurface_t *surface = abstract_surface;
322
	if (! _cairo_surface_has_snapshot (&meta->base,
307
    cairo_surface_pattern_t pattern;
323
					   &_cairo_image_surface_backend))
308
    cairo_surface_t *image;
324
	{
309
    cairo_status_t status;
325
	    image = (cairo_image_surface_t *)
-
 
326
		_cairo_image_surface_create_with_content (meta->content,
-
 
327
							  surface->extents.width,
-
 
328
							  surface->extents.height);
-
 
329
	    if (unlikely (image->base.status))
-
 
330
		return image->base.status;
-
 
331
 
-
 
332
            cairo_surface_paint_to_target (&image->base, surface);
-
 
333
 
-
 
334
	    _cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
-
 
335
 
-
 
336
	    *image_out = image;
-
 
337
	    *extra_out = NULL;
-
 
338
	    return CAIRO_STATUS_SUCCESS;
-
 
339
	}
-
 
340
    }
-
 
341
 
-
 
342
    extra = malloc (sizeof (struct extra));
-
 
343
    if (unlikely (extra == NULL))
-
 
344
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
345
 
-
 
346
    status = _cairo_surface_acquire_source_image (surface->target, &extra->image, &extra->image_extra);
-
 
347
    if (unlikely (status))
-
 
348
	goto CLEANUP;
-
 
349
 
-
 
350
    ret = _cairo_surface_get_extents (&extra->image->base, &target_extents);
-
 
351
    assert (ret);
-
 
352
 
-
 
353
    /* only copy if we need to perform sub-byte manipulation */
-
 
354
    if (PIXMAN_FORMAT_BPP (extra->image->pixman_format) >= 8 &&
-
 
355
	target_extents.x <= surface->extents.x &&
-
 
356
	target_extents.y <= surface->extents.y &&
-
 
357
	surface->extents.x + surface->extents.width <= target_extents.x + target_extents.width &&
-
 
358
	surface->extents.y + surface->extents.height <= target_extents.y + target_extents.height) {
-
 
359
 
-
 
360
	assert ((PIXMAN_FORMAT_BPP (extra->image->pixman_format) % 8) == 0);
-
 
361
 
-
 
362
	data = extra->image->data + surface->extents.y * extra->image->stride;
-
 
363
	data += PIXMAN_FORMAT_BPP (extra->image->pixman_format) / 8 * surface->extents.x;
-
 
364
 
-
 
365
	image = (cairo_image_surface_t *)
-
 
366
	    _cairo_image_surface_create_with_pixman_format (data,
-
 
367
							    extra->image->pixman_format,
-
 
368
							    surface->extents.width,
-
 
369
							    surface->extents.height,
-
 
370
							    extra->image->stride);
-
 
371
	if (unlikely ((status = image->base.status)))
-
 
372
	    goto CLEANUP_IMAGE;
-
 
373
 
-
 
374
        image->base.is_clear = FALSE;
-
 
375
    } else {
-
 
376
	image = (cairo_image_surface_t *)
-
 
377
	    _cairo_image_surface_create_with_pixman_format (NULL,
-
 
Line 378... Line 310...
378
							    extra->image->pixman_format,
310
 
-
 
311
    image = _cairo_image_surface_create_with_content (surface->base.content,
-
 
312
						      surface->extents.width,
-
 
313
						      surface->extents.height);
-
 
314
    if (unlikely (image->status))
-
 
315
	return image->status;
-
 
316
 
-
 
317
    _cairo_pattern_init_for_surface (&pattern, surface->target);
-
 
318
    cairo_matrix_init_translate (&pattern.base.matrix,
-
 
319
				 surface->extents.x,
-
 
320
				 surface->extents.y);
-
 
321
    pattern.base.filter = CAIRO_FILTER_NEAREST;
379
							    surface->extents.width,
322
    status = _cairo_surface_paint (image,
Line 380... Line 323...
380
							    surface->extents.height,
323
				   CAIRO_OPERATOR_SOURCE,
381
							    0);
324
				   &pattern.base, NULL);
382
	if (unlikely ((status = image->base.status)))
325
    _cairo_pattern_fini (&pattern.base);
383
	    goto CLEANUP_IMAGE;
-
 
384
 
-
 
385
        cairo_surface_paint_to_target (&image->base, surface);
-
 
386
    }
-
 
387
 
-
 
388
    *image_out = image;
-
 
389
    *extra_out = extra;
326
    if (unlikely (status)) {
Line 390... Line 327...
390
    return CAIRO_STATUS_SUCCESS;
327
	cairo_surface_destroy (image);
391
 
328
	return status;
392
CLEANUP_IMAGE:
329
    }
393
    _cairo_surface_release_source_image (surface->target, extra->image, extra->image_extra);
330
 
394
CLEANUP:
331
    *image_out = (cairo_image_surface_t *)image;
395
    free (extra);
-
 
396
    return status;
-
 
397
}
-
 
398
 
-
 
399
static void
-
 
400
_cairo_surface_subsurface_release_source_image (void                   *abstract_surface,
-
 
401
						cairo_image_surface_t  *image,
-
 
402
						void                   *abstract_extra)
-
 
403
{
-
 
404
    cairo_surface_subsurface_t *surface = abstract_surface;
332
    *extra_out = NULL;
405
 
333
    return CAIRO_STATUS_SUCCESS;
Line 406... Line 334...
406
    if (abstract_extra != NULL) {
334
}
407
	struct extra *extra = abstract_extra;
335
 
408
 
336
static void
409
	_cairo_surface_release_source_image (surface->target, extra->image, extra->image_extra);
337
_cairo_surface_subsurface_release_source_image (void                   *abstract_surface,
410
	free (extra);
338
						cairo_image_surface_t  *image,
-
 
339
						void                   *abstract_extra)
-
 
340
{
Line 411... Line 341...
411
    }
341
    cairo_surface_destroy (&image->base);
412
 
-
 
413
    cairo_surface_destroy (&image->base);
-
 
Line 414... Line 342...
414
}
342
}
415
 
343
 
416
static cairo_surface_t *
344
static cairo_surface_t *
417
_cairo_surface_subsurface_snapshot (void *abstract_surface)
345
_cairo_surface_subsurface_snapshot (void *abstract_surface)
418
{
-
 
419
    cairo_surface_subsurface_t *surface = abstract_surface;
346
{
420
    cairo_surface_subsurface_t *snapshot;
347
    cairo_surface_subsurface_t *surface = abstract_surface;
Line -... Line 348...
-
 
348
    cairo_surface_pattern_t pattern;
-
 
349
    cairo_surface_t *clone;
-
 
350
    cairo_status_t status;
-
 
351
 
421
 
352
    TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, surface->target->unique_id));
-
 
353
 
-
 
354
    clone = _cairo_surface_create_similar_scratch (surface->target,
-
 
355
						   surface->target->content,
-
 
356
						   surface->extents.width,
422
    snapshot = malloc (sizeof (cairo_surface_subsurface_t));
357
						   surface->extents.height);
-
 
358
    if (unlikely (clone->status))
423
    if (unlikely (snapshot == NULL))
359
	return clone;
424
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
360
 
Line 425... Line -...
425
 
-
 
426
    _cairo_surface_init (&snapshot->base,
361
    _cairo_pattern_init_for_surface (&pattern, surface->target);
-
 
362
    cairo_matrix_init_translate (&pattern.base.matrix,
Line -... Line 363...
-
 
363
				 surface->extents.x, surface->extents.y);
-
 
364
    pattern.base.filter = CAIRO_FILTER_NEAREST;
-
 
365
    status = _cairo_surface_paint (clone,
427
			 &_cairo_surface_subsurface_backend,
366
				   CAIRO_OPERATOR_SOURCE,
-
 
367
				   &pattern.base, NULL);
428
			 NULL, /* device */
368
    _cairo_pattern_fini (&pattern.base);
Line 429... Line 369...
429
			 surface->target->content);
369
 
430
    snapshot->target = _cairo_surface_snapshot (surface->target);
370
    if (unlikely (status)) {
431
    if (unlikely (snapshot->target->status)) {
-
 
432
	cairo_status_t status;
371
	cairo_surface_destroy (clone);
Line -... Line 372...
-
 
372
	clone = _cairo_surface_create_in_error (status);
-
 
373
    }
-
 
374
 
-
 
375
    return clone;
-
 
376
}
-
 
377
 
-
 
378
static cairo_t *
-
 
379
_cairo_surface_subsurface_create_context(void *target)
433
 
380
{
434
	status = snapshot->target->status;
381
    cairo_surface_subsurface_t *surface = target;
435
	free (snapshot);
-
 
436
	return _cairo_surface_create_in_error (status);
-
 
437
    }
-
 
438
 
-
 
439
    snapshot->base.type = snapshot->target->type;
-
 
440
    snapshot->extents = surface->extents;
382
    return surface->target->backend->create_context (&surface->base);
441
 
-
 
-
 
383
}
442
    return &snapshot->base;
384
 
443
}
385
static const cairo_surface_backend_t _cairo_surface_subsurface_backend = {
-
 
386
    CAIRO_SURFACE_TYPE_SUBSURFACE,
444
 
387
    _cairo_surface_subsurface_finish,
445
static const cairo_surface_backend_t _cairo_surface_subsurface_backend = {
-
 
446
    CAIRO_SURFACE_TYPE_SUBSURFACE,
388
 
-
 
389
    _cairo_surface_subsurface_create_context,
447
    _cairo_surface_subsurface_create_similar,
390
 
448
    _cairo_surface_subsurface_finish,
391
    _cairo_surface_subsurface_create_similar,
449
 
-
 
450
    _cairo_surface_subsurface_acquire_source_image,
-
 
Line 451... Line 392...
451
    _cairo_surface_subsurface_release_source_image,
392
    _cairo_surface_subsurface_create_similar_image,
452
    NULL, NULL, /* acquire, release dest */
393
    _cairo_surface_subsurface_map_to_image,
453
    NULL, /* clone similar */
394
    _cairo_surface_subsurface_unmap_image,
454
    NULL, /* composite */
395
 
-
 
396
    _cairo_surface_subsurface_source,
455
    NULL, /* fill rectangles */
397
    _cairo_surface_subsurface_acquire_source_image,
456
    NULL, /* composite trapezoids */
-
 
457
    NULL, /* create span renderer */
-
 
458
    NULL, /* check span renderer */
398
    _cairo_surface_subsurface_release_source_image,
Line 459... Line 399...
459
    NULL, /* copy_page */
399
    _cairo_surface_subsurface_snapshot,
460
    NULL, /* show_page */
400
 
461
    _cairo_surface_subsurface_get_extents,
401
    NULL, /* copy_page */
Line 511... Line 451...
511
				    double x, double y,
451
				    double x, double y,
512
				    double width, double height)
452
				    double width, double height)
513
{
453
{
514
    cairo_surface_subsurface_t *surface;
454
    cairo_surface_subsurface_t *surface;
Line -... Line 455...
-
 
455
 
-
 
456
    if (unlikely (width < 0 || height < 0))
-
 
457
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
515
 
458
 
516
    if (unlikely (target->status))
459
    if (unlikely (target->status))
517
	return _cairo_surface_create_in_error (target->status);
460
	return _cairo_surface_create_in_error (target->status);
518
    if (unlikely (target->finished))
461
    if (unlikely (target->finished))
Line 534... Line 477...
534
    /* XXX forced integer alignment */
477
    /* XXX forced integer alignment */
535
    surface->extents.x = ceil (x);
478
    surface->extents.x = ceil (x);
536
    surface->extents.y = ceil (y);
479
    surface->extents.y = ceil (y);
537
    surface->extents.width = floor (x + width) - surface->extents.x;
480
    surface->extents.width = floor (x + width) - surface->extents.x;
538
    surface->extents.height = floor (y + height) - surface->extents.y;
481
    surface->extents.height = floor (y + height) - surface->extents.y;
-
 
482
    if ((surface->extents.width | surface->extents.height) < 0)
-
 
483
	surface->extents.width = surface->extents.height = 0;
Line 539... Line 484...
539
 
484
 
540
    if (target->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
485
    if (target->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
541
	/* Maintain subsurfaces as 1-depth */
486
	/* Maintain subsurfaces as 1-depth */
542
	cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) target;
487
	cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) target;
543
	surface->extents.x += sub->extents.x;
488
	surface->extents.x += sub->extents.x;
544
	surface->extents.y += sub->extents.y;
489
	surface->extents.y += sub->extents.y;
545
	target = sub->target;
490
	target = sub->target;
Line 546... Line 491...
546
    }
491
    }
-
 
492
 
-
 
493
    surface->target = cairo_surface_reference (target);
-
 
494
    surface->base.type = surface->target->type;
-
 
495
 
-
 
496
    surface->snapshot = NULL;
-
 
497
 
-
 
498
    return &surface->base;
-
 
499
}
-
 
500
 
-
 
501
cairo_surface_t *
-
 
502
_cairo_surface_create_for_rectangle_int (cairo_surface_t *target,
-
 
503
					 const cairo_rectangle_int_t *extents)
-
 
504
{
-
 
505
    cairo_surface_subsurface_t *surface;
-
 
506
 
-
 
507
    if (unlikely (target->status))
-
 
508
	return _cairo_surface_create_in_error (target->status);
-
 
509
    if (unlikely (target->finished))
-
 
510
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
-
 
511
 
-
 
512
    assert (target->backend->type != CAIRO_SURFACE_TYPE_SUBSURFACE);
-
 
513
 
-
 
514
    surface = malloc (sizeof (cairo_surface_subsurface_t));
-
 
515
    if (unlikely (surface == NULL))
-
 
516
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
 
517
 
-
 
518
    assert (_cairo_matrix_is_translation (&target->device_transform));
-
 
519
 
-
 
520
    _cairo_surface_init (&surface->base,
-
 
521
			 &_cairo_surface_subsurface_backend,
-
 
522
			 NULL, /* device */
-
 
523
			 target->content);
-
 
524
 
-
 
525
    surface->extents = *extents;
-
 
526
    surface->extents.x += target->device_transform.x0;
-
 
527
    surface->extents.y += target->device_transform.y0;
-
 
528
 
-
 
529
    surface->target = cairo_surface_reference (target);
-
 
530
    surface->base.type = surface->target->type;
Line 547... Line 531...
547
 
531
 
548
    surface->target = cairo_surface_reference (target);
532
    surface->snapshot = NULL;
549
 
533
 
-
 
534
    return &surface->base;
-
 
535
}
-
 
536
/* XXX observe mark-dirty */
-
 
537
 
-
 
538
static void
-
 
539
_cairo_surface_subsurface_detach_snapshot (cairo_surface_t *surface)
-
 
540
{
-
 
541
    cairo_surface_subsurface_t *ss = (cairo_surface_subsurface_t *) surface;
-
 
542
 
-
 
543
    TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, ss->target->unique_id));
-
 
544
 
-
 
545
    cairo_surface_destroy (ss->snapshot);
-
 
546
    ss->snapshot = NULL;
-
 
547
}
-
 
548
 
-
 
549
void
-
 
550
_cairo_surface_subsurface_set_snapshot (cairo_surface_t *surface,
-
 
551
					cairo_surface_t *snapshot)
-
 
552
{
-
 
553
    cairo_surface_subsurface_t *ss = (cairo_surface_subsurface_t *) surface;
-
 
554
 
-
 
555
    TRACE ((stderr, "%s: target=%d, snapshot=%d\n", __FUNCTION__,
-
 
556
	    ss->target->unique_id, snapshot->unique_id));
-
 
557
 
-
 
558
    /* FIXME: attaching the subsurface as a snapshot to its target creates
-
 
559
     * a reference cycle.  Let's make this call as a no-op until that bug
-
 
560
     * is fixed.
-
 
561
     */
-
 
562
    return;
-
 
563
 
-
 
564
    if (ss->snapshot)
-
 
565
	_cairo_surface_detach_snapshot (ss->snapshot);
-
 
566
 
-
 
567
    ss->snapshot = cairo_surface_reference (snapshot);
-
 
568