Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1892 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 © 2003 University of Southern California
3959 Serge 5
 * Copyright © 2009,2010,2011 Intel Corporation
1892 serge 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 University of Southern
33
 * California.
34
 *
35
 * Contributor(s):
36
 *	Carl D. Worth 
37
 *	Chris Wilson 
38
 */
39
 
40
#include "cairoint.h"
41
 
42
#include "cairo-boxes-private.h"
43
#include "cairo-clip-private.h"
44
#include "cairo-composite-rectangles-private.h"
3959 Serge 45
#include "cairo-compositor-private.h"
46
#include "cairo-default-context-private.h"
1892 serge 47
#include "cairo-error-private.h"
3959 Serge 48
#include "cairo-image-surface-inline.h"
49
#include "cairo-paginated-private.h"
50
#include "cairo-pattern-private.h"
51
#include "cairo-pixman-private.h"
52
#include "cairo-recording-surface-private.h"
1892 serge 53
#include "cairo-region-private.h"
54
#include "cairo-scaled-font-private.h"
55
#include "cairo-surface-snapshot-private.h"
56
#include "cairo-surface-subsurface-private.h"
57
 
58
/* Limit on the width / height of an image surface in pixels.  This is
59
 * mainly determined by coordinates of things sent to pixman at the
60
 * moment being in 16.16 format. */
61
#define MAX_IMAGE_SIZE 32767
62
 
63
/**
64
 * SECTION:cairo-image
65
 * @Title: Image Surfaces
66
 * @Short_Description: Rendering to memory buffers
67
 * @See_Also: #cairo_surface_t
68
 *
69
 * Image surfaces provide the ability to render to memory buffers
70
 * either allocated by cairo or by the calling code.  The supported
71
 * image formats are those defined in #cairo_format_t.
3959 Serge 72
 **/
1892 serge 73
 
74
/**
75
 * CAIRO_HAS_IMAGE_SURFACE:
76
 *
77
 * Defined if the image surface backend is available.
78
 * The image surface backend is always built in.
79
 * This macro was added for completeness in cairo 1.8.
80
 *
3959 Serge 81
 * Since: 1.8
82
 **/
1892 serge 83
 
84
static cairo_bool_t
85
_cairo_image_surface_is_size_valid (int width, int height)
86
{
87
    return 0 <= width  &&  width <= MAX_IMAGE_SIZE &&
88
 
89
}
90
 
91
cairo_format_t
92
_cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
93
{
94
    switch (pixman_format) {
95
    case PIXMAN_a8r8g8b8:
96
	return CAIRO_FORMAT_ARGB32;
3959 Serge 97
    case PIXMAN_x2r10g10b10:
98
	return CAIRO_FORMAT_RGB30;
1892 serge 99
    case PIXMAN_x8r8g8b8:
100
	return CAIRO_FORMAT_RGB24;
101
    case PIXMAN_a8:
102
	return CAIRO_FORMAT_A8;
103
    case PIXMAN_a1:
104
	return CAIRO_FORMAT_A1;
105
    case PIXMAN_r5g6b5:
106
	return CAIRO_FORMAT_RGB16_565;
3959 Serge 107
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
108
    case PIXMAN_r8g8b8a8: case PIXMAN_r8g8b8x8:
109
#endif
1892 serge 110
    case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: case PIXMAN_r8g8b8:
111
    case PIXMAN_b8g8r8:   case PIXMAN_b5g6r5:
112
    case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5:
113
    case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4:
114
    case PIXMAN_a4b4g4r4: case PIXMAN_x4b4g4r4: case PIXMAN_r3g3b2:
115
    case PIXMAN_b2g3r3:   case PIXMAN_a2r2g2b2: case PIXMAN_a2b2g2r2:
116
    case PIXMAN_c8:       case PIXMAN_g8:       case PIXMAN_x4a4:
117
    case PIXMAN_a4:       case PIXMAN_r1g2b1:   case PIXMAN_b1g2r1:
118
    case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
119
    case PIXMAN_g4:       case PIXMAN_g1:
120
    case PIXMAN_yuy2:     case PIXMAN_yv12:
121
    case PIXMAN_b8g8r8x8:
122
    case PIXMAN_b8g8r8a8:
3959 Serge 123
    case PIXMAN_a2b10g10r10:
1892 serge 124
    case PIXMAN_x2b10g10r10:
125
    case PIXMAN_a2r10g10b10:
3959 Serge 126
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
127
    case PIXMAN_x14r6g6b6:
128
#endif
1892 serge 129
    default:
130
	return CAIRO_FORMAT_INVALID;
131
    }
132
 
133
    return CAIRO_FORMAT_INVALID;
134
}
135
 
136
cairo_content_t
137
_cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
138
{
139
    cairo_content_t content;
140
 
141
    content = 0;
142
    if (PIXMAN_FORMAT_RGB (pixman_format))
143
	content |= CAIRO_CONTENT_COLOR;
144
    if (PIXMAN_FORMAT_A (pixman_format))
145
	content |= CAIRO_CONTENT_ALPHA;
146
 
147
    return content;
148
}
149
 
3959 Serge 150
void
151
_cairo_image_surface_init (cairo_image_surface_t *surface,
152
			   pixman_image_t	*pixman_image,
153
			   pixman_format_code_t	 pixman_format)
154
{
155
    surface->parent = NULL;
156
    surface->pixman_image = pixman_image;
157
 
158
    surface->pixman_format = pixman_format;
159
    surface->format = _cairo_format_from_pixman_format (pixman_format);
160
    surface->data = (uint8_t *) pixman_image_get_data (pixman_image);
161
    surface->owns_data = FALSE;
162
    surface->transparency = CAIRO_IMAGE_UNKNOWN;
163
    surface->color = CAIRO_IMAGE_UNKNOWN_COLOR;
164
 
165
    surface->width = pixman_image_get_width (pixman_image);
166
    surface->height = pixman_image_get_height (pixman_image);
167
    surface->stride = pixman_image_get_stride (pixman_image);
168
    surface->depth = pixman_image_get_depth (pixman_image);
169
 
170
    surface->base.is_clear = surface->width == 0 || surface->height == 0;
171
 
172
    surface->compositor = _cairo_image_spans_compositor_get ();
173
}
174
 
1892 serge 175
cairo_surface_t *
176
_cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
177
					      pixman_format_code_t	 pixman_format)
178
{
179
    cairo_image_surface_t *surface;
180
 
181
    surface = malloc (sizeof (cairo_image_surface_t));
182
    if (unlikely (surface == NULL))
183
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
184
 
185
    _cairo_surface_init (&surface->base,
186
			 &_cairo_image_surface_backend,
187
			 NULL, /* device */
188
			 _cairo_content_from_pixman_format (pixman_format));
189
 
3959 Serge 190
    _cairo_image_surface_init (surface, pixman_image, pixman_format);
1892 serge 191
 
192
    return &surface->base;
193
}
194
 
195
cairo_bool_t
196
_pixman_format_from_masks (cairo_format_masks_t *masks,
197
			   pixman_format_code_t *format_ret)
198
{
199
    pixman_format_code_t format;
200
    int format_type;
201
    int a, r, g, b;
202
    cairo_format_masks_t format_masks;
203
 
204
    a = _cairo_popcount (masks->alpha_mask);
205
    r = _cairo_popcount (masks->red_mask);
206
    g = _cairo_popcount (masks->green_mask);
207
    b = _cairo_popcount (masks->blue_mask);
208
 
209
    if (masks->red_mask) {
210
	if (masks->red_mask > masks->blue_mask)
211
	    format_type = PIXMAN_TYPE_ARGB;
212
	else
213
	    format_type = PIXMAN_TYPE_ABGR;
214
    } else if (masks->alpha_mask) {
215
	format_type = PIXMAN_TYPE_A;
216
    } else {
217
	return FALSE;
218
    }
219
 
220
    format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b);
221
 
222
    if (! pixman_format_supported_destination (format))
223
	return FALSE;
224
 
225
    /* Sanity check that we got out of PIXMAN_FORMAT exactly what we
226
     * expected. This avoid any problems from something bizarre like
227
     * alpha in the least-significant bits, or insane channel order,
228
     * or whatever. */
229
     if (!_pixman_format_to_masks (format, &format_masks) ||
230
         masks->bpp        != format_masks.bpp            ||
231
	 masks->red_mask   != format_masks.red_mask       ||
232
	 masks->green_mask != format_masks.green_mask     ||
233
	 masks->blue_mask  != format_masks.blue_mask)
234
     {
235
	 return FALSE;
236
     }
237
 
238
    *format_ret = format;
239
    return TRUE;
240
}
241
 
242
/* A mask consisting of N bits set to 1. */
243
#define MASK(N) ((1UL << (N))-1)
244
 
245
cairo_bool_t
246
_pixman_format_to_masks (pixman_format_code_t	 format,
247
			 cairo_format_masks_t	*masks)
248
{
249
    int a, r, g, b;
250
 
251
    masks->bpp = PIXMAN_FORMAT_BPP (format);
252
 
253
    /* Number of bits in each channel */
254
    a = PIXMAN_FORMAT_A (format);
255
    r = PIXMAN_FORMAT_R (format);
256
    g = PIXMAN_FORMAT_G (format);
257
    b = PIXMAN_FORMAT_B (format);
258
 
259
    switch (PIXMAN_FORMAT_TYPE (format)) {
260
    case PIXMAN_TYPE_ARGB:
261
        masks->alpha_mask = MASK (a) << (r + g + b);
262
        masks->red_mask   = MASK (r) << (g + b);
263
        masks->green_mask = MASK (g) << (b);
264
        masks->blue_mask  = MASK (b);
265
        return TRUE;
266
    case PIXMAN_TYPE_ABGR:
267
        masks->alpha_mask = MASK (a) << (b + g + r);
268
        masks->blue_mask  = MASK (b) << (g + r);
269
        masks->green_mask = MASK (g) << (r);
270
        masks->red_mask   = MASK (r);
271
        return TRUE;
272
#ifdef PIXMAN_TYPE_BGRA
273
    case PIXMAN_TYPE_BGRA:
274
        masks->blue_mask  = MASK (b) << (masks->bpp - b);
275
        masks->green_mask = MASK (g) << (masks->bpp - b - g);
276
        masks->red_mask   = MASK (r) << (masks->bpp - b - g - r);
277
        masks->alpha_mask = MASK (a);
278
        return TRUE;
279
#endif
280
    case PIXMAN_TYPE_A:
281
        masks->alpha_mask = MASK (a);
282
        masks->red_mask   = 0;
283
        masks->green_mask = 0;
284
        masks->blue_mask  = 0;
285
        return TRUE;
286
    case PIXMAN_TYPE_OTHER:
287
    case PIXMAN_TYPE_COLOR:
288
    case PIXMAN_TYPE_GRAY:
289
    case PIXMAN_TYPE_YUY2:
290
    case PIXMAN_TYPE_YV12:
291
    default:
292
        masks->alpha_mask = 0;
293
        masks->red_mask   = 0;
294
        masks->green_mask = 0;
295
        masks->blue_mask  = 0;
296
        return FALSE;
297
    }
298
}
299
 
300
pixman_format_code_t
301
_cairo_format_to_pixman_format_code (cairo_format_t format)
302
{
303
    pixman_format_code_t ret;
304
    switch (format) {
305
    case CAIRO_FORMAT_A1:
306
	ret = PIXMAN_a1;
307
	break;
308
    case CAIRO_FORMAT_A8:
309
	ret = PIXMAN_a8;
310
	break;
311
    case CAIRO_FORMAT_RGB24:
312
	ret = PIXMAN_x8r8g8b8;
313
	break;
3959 Serge 314
    case CAIRO_FORMAT_RGB30:
315
	ret = PIXMAN_x2r10g10b10;
316
	break;
1892 serge 317
    case CAIRO_FORMAT_RGB16_565:
318
	ret = PIXMAN_r5g6b5;
319
	break;
320
    case CAIRO_FORMAT_ARGB32:
321
    case CAIRO_FORMAT_INVALID:
322
    default:
323
	ret = PIXMAN_a8r8g8b8;
324
	break;
325
    }
326
    return ret;
327
}
328
 
329
cairo_surface_t *
330
_cairo_image_surface_create_with_pixman_format (unsigned char		*data,
331
						pixman_format_code_t	 pixman_format,
332
						int			 width,
333
						int			 height,
334
						int			 stride)
335
{
336
    cairo_surface_t *surface;
337
    pixman_image_t *pixman_image;
338
 
339
    if (! _cairo_image_surface_is_size_valid (width, height))
340
    {
341
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
342
    }
343
 
344
    pixman_image = pixman_image_create_bits (pixman_format, width, height,
345
					     (uint32_t *) data, stride);
346
 
347
    if (unlikely (pixman_image == NULL))
348
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
349
 
350
    surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
351
							    pixman_format);
352
    if (unlikely (surface->status)) {
353
	pixman_image_unref (pixman_image);
354
	return surface;
355
    }
356
 
357
    /* we can not make any assumptions about the initial state of user data */
358
    surface->is_clear = data == NULL;
359
    return surface;
360
}
361
 
362
/**
363
 * cairo_image_surface_create:
364
 * @format: format of pixels in the surface to create
365
 * @width: width of the surface, in pixels
366
 * @height: height of the surface, in pixels
367
 *
368
 * Creates an image surface of the specified format and
369
 * dimensions. Initially the surface contents are all
370
 * 0. (Specifically, within each pixel, each color or alpha channel
371
 * belonging to format will be 0. The contents of bits within a pixel,
372
 * but not belonging to the given format are undefined).
373
 *
374
 * Return value: a pointer to the newly created surface. The caller
375
 * owns the surface and should call cairo_surface_destroy() when done
376
 * with it.
377
 *
378
 * This function always returns a valid pointer, but it will return a
379
 * pointer to a "nil" surface if an error such as out of memory
380
 * occurs. You can use cairo_surface_status() to check for this.
3959 Serge 381
 *
382
 * Since: 1.0
1892 serge 383
 **/
384
cairo_surface_t *
385
cairo_image_surface_create (cairo_format_t	format,
386
			    int			width,
387
			    int			height)
388
{
389
    pixman_format_code_t pixman_format;
390
 
391
    if (! CAIRO_FORMAT_VALID (format))
392
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
393
 
394
    pixman_format = _cairo_format_to_pixman_format_code (format);
395
 
396
    return _cairo_image_surface_create_with_pixman_format (NULL, pixman_format,
397
							   width, height, -1);
398
}
399
slim_hidden_def (cairo_image_surface_create);
400
 
3959 Serge 401
    cairo_surface_t *
1892 serge 402
_cairo_image_surface_create_with_content (cairo_content_t	content,
403
					  int			width,
404
					  int			height)
405
{
406
    return cairo_image_surface_create (_cairo_format_from_content (content),
407
				       width, height);
408
}
409
 
410
/**
411
 * cairo_format_stride_for_width:
412
 * @format: A #cairo_format_t value
413
 * @width: The desired width of an image surface to be created.
414
 *
415
 * This function provides a stride value that will respect all
416
 * alignment requirements of the accelerated image-rendering code
417
 * within cairo. Typical usage will be of the form:
418
 *
419
 * 
420
 * int stride;
421
 * unsigned char *data;
422
 * #cairo_surface_t *surface;
423
 *
424
 * stride = cairo_format_stride_for_width (format, width);
425
 * data = malloc (stride * height);
426
 * surface = cairo_image_surface_create_for_data (data, format,
427
 *						  width, height,
428
 *						  stride);
429
 * 
430
 *
431
 * Return value: the appropriate stride to use given the desired
432
 * format and width, or -1 if either the format is invalid or the width
433
 * too large.
434
 *
435
 * Since: 1.6
436
 **/
3959 Serge 437
    int
1892 serge 438
cairo_format_stride_for_width (cairo_format_t	format,
439
			       int		width)
440
{
441
    int bpp;
442
 
443
    if (! CAIRO_FORMAT_VALID (format)) {
444
	_cairo_error_throw (CAIRO_STATUS_INVALID_FORMAT);
445
	return -1;
446
    }
447
 
448
    bpp = _cairo_format_bits_per_pixel (format);
449
    if ((unsigned) (width) >= (INT32_MAX - 7) / (unsigned) (bpp))
450
	return -1;
451
 
452
    return CAIRO_STRIDE_FOR_WIDTH_BPP (width, bpp);
453
}
454
slim_hidden_def (cairo_format_stride_for_width);
455
 
456
/**
457
 * cairo_image_surface_create_for_data:
458
 * @data: a pointer to a buffer supplied by the application in which
459
 *     to write contents. This pointer must be suitably aligned for any
460
 *     kind of variable, (for example, a pointer returned by malloc).
461
 * @format: the format of pixels in the buffer
462
 * @width: the width of the image to be stored in the buffer
463
 * @height: the height of the image to be stored in the buffer
464
 * @stride: the number of bytes between the start of rows in the
465
 *     buffer as allocated. This value should always be computed by
466
 *     cairo_format_stride_for_width() before allocating the data
467
 *     buffer.
468
 *
469
 * Creates an image surface for the provided pixel data. The output
470
 * buffer must be kept around until the #cairo_surface_t is destroyed
471
 * or cairo_surface_finish() is called on the surface.  The initial
472
 * contents of @data will be used as the initial image contents; you
473
 * must explicitly clear the buffer, using, for example,
474
 * cairo_rectangle() and cairo_fill() if you want it cleared.
475
 *
476
 * Note that the stride may be larger than
477
 * width*bytes_per_pixel to provide proper alignment for each pixel
478
 * and row. This alignment is required to allow high-performance rendering
479
 * within cairo. The correct way to obtain a legal stride value is to
480
 * call cairo_format_stride_for_width() with the desired format and
481
 * maximum image width value, and then use the resulting stride value
482
 * to allocate the data and to create the image surface. See
483
 * cairo_format_stride_for_width() for example code.
484
 *
485
 * Return value: a pointer to the newly created surface. The caller
486
 * owns the surface and should call cairo_surface_destroy() when done
487
 * with it.
488
 *
489
 * This function always returns a valid pointer, but it will return a
490
 * pointer to a "nil" surface in the case of an error such as out of
491
 * memory or an invalid stride value. In case of invalid stride value
492
 * the error status of the returned surface will be
493
 * %CAIRO_STATUS_INVALID_STRIDE.  You can use
494
 * cairo_surface_status() to check for this.
495
 *
496
 * See cairo_surface_set_user_data() for a means of attaching a
497
 * destroy-notification fallback to the surface if necessary.
3959 Serge 498
 *
499
 * Since: 1.0
1892 serge 500
 **/
3959 Serge 501
    cairo_surface_t *
1892 serge 502
cairo_image_surface_create_for_data (unsigned char     *data,
503
				     cairo_format_t	format,
504
				     int		width,
505
				     int		height,
506
				     int		stride)
507
{
508
    pixman_format_code_t pixman_format;
509
    int minstride;
510
 
511
    if (! CAIRO_FORMAT_VALID (format))
512
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
513
 
514
    if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0)
515
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
516
 
517
    if (! _cairo_image_surface_is_size_valid (width, height))
518
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
519
 
520
    minstride = cairo_format_stride_for_width (format, width);
521
    if (stride < 0) {
522
	if (stride > -minstride) {
523
	    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
524
	}
525
    } else {
526
	if (stride < minstride) {
527
	    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
528
	}
529
    }
530
 
531
    pixman_format = _cairo_format_to_pixman_format_code (format);
532
    return _cairo_image_surface_create_with_pixman_format (data,
533
							   pixman_format,
534
							   width, height,
535
							   stride);
536
}
537
slim_hidden_def (cairo_image_surface_create_for_data);
538
 
539
/**
540
 * cairo_image_surface_get_data:
541
 * @surface: a #cairo_image_surface_t
542
 *
543
 * Get a pointer to the data of the image surface, for direct
544
 * inspection or modification.
545
 *
3959 Serge 546
 * A call to cairo_surface_flush() is required before accessing the
547
 * pixel data to ensure that all pending drawing operations are
548
 * finished. A call to cairo_surface_mark_dirty() is required after
549
 * the data is modified.
550
 *
1892 serge 551
 * Return value: a pointer to the image data of this surface or %NULL
552
 * if @surface is not an image surface, or if cairo_surface_finish()
553
 * has been called.
554
 *
555
 * Since: 1.2
556
 **/
557
unsigned char *
558
cairo_image_surface_get_data (cairo_surface_t *surface)
559
{
560
    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
561
 
562
    if (! _cairo_surface_is_image (surface)) {
563
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
564
	return NULL;
565
    }
566
 
567
    return image_surface->data;
568
}
569
slim_hidden_def (cairo_image_surface_get_data);
570
 
571
/**
572
 * cairo_image_surface_get_format:
573
 * @surface: a #cairo_image_surface_t
574
 *
575
 * Get the format of the surface.
576
 *
577
 * Return value: the format of the surface
578
 *
579
 * Since: 1.2
580
 **/
581
cairo_format_t
582
cairo_image_surface_get_format (cairo_surface_t *surface)
583
{
584
    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
585
 
586
    if (! _cairo_surface_is_image (surface)) {
587
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
588
	return CAIRO_FORMAT_INVALID;
589
    }
590
 
591
    return image_surface->format;
592
}
593
slim_hidden_def (cairo_image_surface_get_format);
594
 
595
/**
596
 * cairo_image_surface_get_width:
597
 * @surface: a #cairo_image_surface_t
598
 *
599
 * Get the width of the image surface in pixels.
600
 *
601
 * Return value: the width of the surface in pixels.
3959 Serge 602
 *
603
 * Since: 1.0
1892 serge 604
 **/
605
int
606
cairo_image_surface_get_width (cairo_surface_t *surface)
607
{
608
    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
609
 
610
    if (! _cairo_surface_is_image (surface)) {
611
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
612
	return 0;
613
    }
614
 
615
    return image_surface->width;
616
}
617
slim_hidden_def (cairo_image_surface_get_width);
618
 
619
/**
620
 * cairo_image_surface_get_height:
621
 * @surface: a #cairo_image_surface_t
622
 *
623
 * Get the height of the image surface in pixels.
624
 *
625
 * Return value: the height of the surface in pixels.
3959 Serge 626
 *
627
 * Since: 1.0
1892 serge 628
 **/
629
int
630
cairo_image_surface_get_height (cairo_surface_t *surface)
631
{
632
    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
633
 
634
    if (! _cairo_surface_is_image (surface)) {
635
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
636
	return 0;
637
    }
638
 
639
    return image_surface->height;
640
}
641
slim_hidden_def (cairo_image_surface_get_height);
642
 
643
/**
644
 * cairo_image_surface_get_stride:
645
 * @surface: a #cairo_image_surface_t
646
 *
647
 * Get the stride of the image surface in bytes
648
 *
649
 * Return value: the stride of the image surface in bytes (or 0 if
650
 * @surface is not an image surface). The stride is the distance in
651
 * bytes from the beginning of one row of the image data to the
652
 * beginning of the next row.
653
 *
654
 * Since: 1.2
655
 **/
656
int
657
cairo_image_surface_get_stride (cairo_surface_t *surface)
658
{
659
 
660
    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
661
 
662
    if (! _cairo_surface_is_image (surface)) {
663
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
664
	return 0;
665
    }
666
 
667
    return image_surface->stride;
668
}
669
slim_hidden_def (cairo_image_surface_get_stride);
670
 
3959 Serge 671
    cairo_format_t
1892 serge 672
_cairo_format_from_content (cairo_content_t content)
673
{
674
    switch (content) {
675
    case CAIRO_CONTENT_COLOR:
676
	return CAIRO_FORMAT_RGB24;
677
    case CAIRO_CONTENT_ALPHA:
678
	return CAIRO_FORMAT_A8;
679
    case CAIRO_CONTENT_COLOR_ALPHA:
680
	return CAIRO_FORMAT_ARGB32;
681
    }
682
 
683
    ASSERT_NOT_REACHED;
684
    return CAIRO_FORMAT_INVALID;
685
}
686
 
3959 Serge 687
    cairo_content_t
1892 serge 688
_cairo_content_from_format (cairo_format_t format)
689
{
690
    switch (format) {
691
    case CAIRO_FORMAT_ARGB32:
692
	return CAIRO_CONTENT_COLOR_ALPHA;
3959 Serge 693
    case CAIRO_FORMAT_RGB30:
694
	return CAIRO_CONTENT_COLOR;
1892 serge 695
    case CAIRO_FORMAT_RGB24:
696
	return CAIRO_CONTENT_COLOR;
697
    case CAIRO_FORMAT_RGB16_565:
698
	return CAIRO_CONTENT_COLOR;
699
    case CAIRO_FORMAT_A8:
700
    case CAIRO_FORMAT_A1:
701
	return CAIRO_CONTENT_ALPHA;
702
    case CAIRO_FORMAT_INVALID:
703
	break;
704
    }
705
 
706
    ASSERT_NOT_REACHED;
707
    return CAIRO_CONTENT_COLOR_ALPHA;
708
}
709
 
3959 Serge 710
    int
1892 serge 711
_cairo_format_bits_per_pixel (cairo_format_t format)
712
{
713
    switch (format) {
714
    case CAIRO_FORMAT_ARGB32:
3959 Serge 715
    case CAIRO_FORMAT_RGB30:
1892 serge 716
    case CAIRO_FORMAT_RGB24:
717
	return 32;
718
    case CAIRO_FORMAT_RGB16_565:
719
	return 16;
720
    case CAIRO_FORMAT_A8:
721
	return 8;
722
    case CAIRO_FORMAT_A1:
723
	return 1;
724
    case CAIRO_FORMAT_INVALID:
725
    default:
726
	ASSERT_NOT_REACHED;
727
	return 0;
728
    }
729
}
730
 
3959 Serge 731
cairo_surface_t *
1892 serge 732
_cairo_image_surface_create_similar (void	       *abstract_other,
733
				     cairo_content_t	content,
734
				     int		width,
735
				     int		height)
736
{
737
    cairo_image_surface_t *other = abstract_other;
738
 
3959 Serge 739
    TRACE ((stderr, "%s (other=%u)\n", __FUNCTION__, other->base.unique_id));
740
 
1892 serge 741
    if (! _cairo_image_surface_is_size_valid (width, height))
742
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
743
 
744
    if (content == other->base.content) {
745
	return _cairo_image_surface_create_with_pixman_format (NULL,
746
							       other->pixman_format,
747
							       width, height,
748
							       0);
749
    }
750
 
751
    return _cairo_image_surface_create_with_content (content,
752
						     width, height);
753
}
754
 
3959 Serge 755
cairo_surface_t *
756
_cairo_image_surface_snapshot (void *abstract_surface)
1892 serge 757
{
3959 Serge 758
    cairo_image_surface_t *image = abstract_surface;
759
    cairo_image_surface_t *clone;
1892 serge 760
 
3959 Serge 761
    /* If we own the image, we can simply steal the memory for the snapshot */
762
    if (image->owns_data && image->base._finishing) {
763
	clone = (cairo_image_surface_t *)
764
	    _cairo_image_surface_create_for_pixman_image (image->pixman_image,
765
							  image->pixman_format);
766
	if (unlikely (clone->base.status))
767
	    return &clone->base;
1892 serge 768
 
3959 Serge 769
	image->pixman_image = NULL;
770
	image->owns_data = FALSE;
1892 serge 771
 
3959 Serge 772
	clone->transparency = image->transparency;
773
	clone->color = image->color;
1892 serge 774
 
3959 Serge 775
	clone->owns_data = TRUE;
776
	return &clone->base;
1892 serge 777
    }
778
 
3959 Serge 779
    clone = (cairo_image_surface_t *)
780
	_cairo_image_surface_create_with_pixman_format (NULL,
781
							image->pixman_format,
782
							image->width,
783
							image->height,
784
							0);
785
    if (unlikely (clone->base.status))
786
	return &clone->base;
1892 serge 787
 
3959 Serge 788
    if (clone->stride == image->stride) {
789
	memcpy (clone->data, image->data, clone->stride * clone->height);
1892 serge 790
    } else {
3959 Serge 791
	pixman_image_composite32 (PIXMAN_OP_SRC,
792
				  image->pixman_image, NULL, clone->pixman_image,
793
				  0, 0,
794
				  0, 0,
795
				  0, 0,
796
				  image->width, image->height);
1892 serge 797
    }
3959 Serge 798
    clone->base.is_clear = FALSE;
799
    return &clone->base;
1892 serge 800
}
801
 
3959 Serge 802
cairo_image_surface_t *
803
_cairo_image_surface_map_to_image (void *abstract_other,
804
				   const cairo_rectangle_int_t *extents)
1892 serge 805
{
3959 Serge 806
    cairo_image_surface_t *other = abstract_other;
1892 serge 807
    cairo_surface_t *surface;
3959 Serge 808
    uint8_t *data;
1892 serge 809
 
3959 Serge 810
    data = other->data;
811
    data += extents->y * other->stride;
812
    data += extents->x * PIXMAN_FORMAT_BPP (other->pixman_format)/ 8;
1892 serge 813
 
3959 Serge 814
    surface =
815
	_cairo_image_surface_create_with_pixman_format (data,
816
							other->pixman_format,
817
							extents->width,
818
							extents->height,
819
							other->stride);
1892 serge 820
 
3959 Serge 821
    cairo_surface_set_device_offset (surface, -extents->x, -extents->y);
822
    return (cairo_image_surface_t *) surface;
1892 serge 823
}
824
 
3959 Serge 825
cairo_int_status_t
826
_cairo_image_surface_unmap_image (void *abstract_surface,
827
				  cairo_image_surface_t *image)
1892 serge 828
{
3959 Serge 829
    cairo_surface_finish (&image->base);
830
    cairo_surface_destroy (&image->base);
1892 serge 831
 
3959 Serge 832
    return CAIRO_INT_STATUS_SUCCESS;
1892 serge 833
}
834
 
3959 Serge 835
cairo_status_t
836
_cairo_image_surface_finish (void *abstract_surface)
1892 serge 837
{
3959 Serge 838
    cairo_image_surface_t *surface = abstract_surface;
1892 serge 839
 
3959 Serge 840
    if (surface->pixman_image) {
841
	pixman_image_unref (surface->pixman_image);
842
	surface->pixman_image = NULL;
1892 serge 843
    }
844
 
3959 Serge 845
    if (surface->owns_data) {
846
	free (surface->data);
847
	surface->data = NULL;
1892 serge 848
    }
849
 
3959 Serge 850
    if (surface->parent) {
851
	cairo_surface_t *parent = surface->parent;
852
	surface->parent = NULL;
853
	cairo_surface_destroy (parent);
1892 serge 854
    }
855
 
856
    return CAIRO_STATUS_SUCCESS;
857
}
858
 
3959 Serge 859
void
860
_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface)
1892 serge 861
{
3959 Serge 862
    surface->owns_data = TRUE;
1892 serge 863
}
864
 
3959 Serge 865
cairo_surface_t *
866
_cairo_image_surface_source (void			*abstract_surface,
867
			     cairo_rectangle_int_t	*extents)
1892 serge 868
{
3959 Serge 869
    cairo_image_surface_t *surface = abstract_surface;
1892 serge 870
 
3959 Serge 871
    if (extents) {
872
	extents->x = extents->y = 0;
873
	extents->width = surface->width;
874
	extents->height = surface->height;
1892 serge 875
    }
876
 
3959 Serge 877
    return &surface->base;
1892 serge 878
}
879
 
3959 Serge 880
cairo_status_t
881
_cairo_image_surface_acquire_source_image (void                    *abstract_surface,
882
					   cairo_image_surface_t  **image_out,
883
					   void                   **image_extra)
1892 serge 884
{
3959 Serge 885
    *image_out = abstract_surface;
886
    *image_extra = NULL;
1892 serge 887
 
888
    return CAIRO_STATUS_SUCCESS;
889
}
890
 
3959 Serge 891
void
892
_cairo_image_surface_release_source_image (void                   *abstract_surface,
893
					   cairo_image_surface_t  *image,
894
					   void                   *image_extra)
1892 serge 895
{
896
}
897
 
3959 Serge 898
/* high level image interface */
899
cairo_bool_t
900
_cairo_image_surface_get_extents (void			  *abstract_surface,
901
				  cairo_rectangle_int_t   *rectangle)
1892 serge 902
{
3959 Serge 903
    cairo_image_surface_t *surface = abstract_surface;
1892 serge 904
 
3959 Serge 905
    rectangle->x = 0;
906
    rectangle->y = 0;
907
    rectangle->width  = surface->width;
908
    rectangle->height = surface->height;
1892 serge 909
 
910
    return TRUE;
911
}
912
 
3959 Serge 913
cairo_int_status_t
1892 serge 914
_cairo_image_surface_paint (void			*abstract_surface,
915
			    cairo_operator_t		 op,
916
			    const cairo_pattern_t	*source,
3959 Serge 917
			    const cairo_clip_t		*clip)
1892 serge 918
{
919
    cairo_image_surface_t *surface = abstract_surface;
920
 
3959 Serge 921
    TRACE ((stderr, "%s (surface=%d)\n",
922
	    __FUNCTION__, surface->base.unique_id));
1892 serge 923
 
3959 Serge 924
    return _cairo_compositor_paint (surface->compositor,
925
				    &surface->base, op, source, clip);
1892 serge 926
}
927
 
3959 Serge 928
cairo_int_status_t
1892 serge 929
_cairo_image_surface_mask (void				*abstract_surface,
930
			   cairo_operator_t		 op,
931
			   const cairo_pattern_t	*source,
932
			   const cairo_pattern_t	*mask,
3959 Serge 933
			   const cairo_clip_t		*clip)
1892 serge 934
{
935
    cairo_image_surface_t *surface = abstract_surface;
936
 
3959 Serge 937
    TRACE ((stderr, "%s (surface=%d)\n",
938
	    __FUNCTION__, surface->base.unique_id));
1892 serge 939
 
3959 Serge 940
    return _cairo_compositor_mask (surface->compositor,
941
				   &surface->base, op, source, mask, clip);
1892 serge 942
}
943
 
3959 Serge 944
cairo_int_status_t
1892 serge 945
_cairo_image_surface_stroke (void			*abstract_surface,
946
			     cairo_operator_t		 op,
947
			     const cairo_pattern_t	*source,
3959 Serge 948
			     const cairo_path_fixed_t	*path,
1892 serge 949
			     const cairo_stroke_style_t	*style,
950
			     const cairo_matrix_t	*ctm,
951
			     const cairo_matrix_t	*ctm_inverse,
952
			     double			 tolerance,
953
			     cairo_antialias_t		 antialias,
3959 Serge 954
			     const cairo_clip_t		*clip)
1892 serge 955
{
956
    cairo_image_surface_t *surface = abstract_surface;
957
 
3959 Serge 958
    TRACE ((stderr, "%s (surface=%d)\n",
959
	    __FUNCTION__, surface->base.unique_id));
1892 serge 960
 
3959 Serge 961
    return _cairo_compositor_stroke (surface->compositor, &surface->base,
962
				     op, source, path,
963
				     style, ctm, ctm_inverse,
964
				     tolerance, antialias, clip);
1892 serge 965
}
966
 
3959 Serge 967
cairo_int_status_t
1892 serge 968
_cairo_image_surface_fill (void				*abstract_surface,
969
			   cairo_operator_t		 op,
970
			   const cairo_pattern_t	*source,
3959 Serge 971
			   const cairo_path_fixed_t	*path,
1892 serge 972
			   cairo_fill_rule_t		 fill_rule,
973
			   double			 tolerance,
974
			   cairo_antialias_t		 antialias,
3959 Serge 975
			   const cairo_clip_t		*clip)
1892 serge 976
{
977
    cairo_image_surface_t *surface = abstract_surface;
978
 
3959 Serge 979
    TRACE ((stderr, "%s (surface=%d)\n",
980
	    __FUNCTION__, surface->base.unique_id));
1892 serge 981
 
3959 Serge 982
    return _cairo_compositor_fill (surface->compositor, &surface->base,
983
				   op, source, path,
984
				   fill_rule, tolerance, antialias,
985
				   clip);
1892 serge 986
}
987
 
3959 Serge 988
cairo_int_status_t
1892 serge 989
_cairo_image_surface_glyphs (void			*abstract_surface,
990
			     cairo_operator_t		 op,
991
			     const cairo_pattern_t	*source,
992
			     cairo_glyph_t		*glyphs,
993
			     int			 num_glyphs,
994
			     cairo_scaled_font_t	*scaled_font,
3959 Serge 995
			     const cairo_clip_t		*clip)
1892 serge 996
{
997
    cairo_image_surface_t *surface = abstract_surface;
998
 
3959 Serge 999
    TRACE ((stderr, "%s (surface=%d)\n",
1000
	    __FUNCTION__, surface->base.unique_id));
1892 serge 1001
 
3959 Serge 1002
    return _cairo_compositor_glyphs (surface->compositor, &surface->base,
1003
				     op, source,
1004
				     glyphs, num_glyphs, scaled_font,
1005
				     clip);
1892 serge 1006
}
1007
 
3959 Serge 1008
void
1892 serge 1009
_cairo_image_surface_get_font_options (void                  *abstract_surface,
1010
				       cairo_font_options_t  *options)
1011
{
1012
    _cairo_font_options_init_default (options);
1013
 
1014
    cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
3959 Serge 1015
    _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
1892 serge 1016
}
1017
 
3959 Serge 1018
const cairo_surface_backend_t _cairo_image_surface_backend = {
1019
    CAIRO_SURFACE_TYPE_IMAGE,
1020
    _cairo_image_surface_finish,
1892 serge 1021
 
3959 Serge 1022
    _cairo_default_context_create,
1892 serge 1023
 
3959 Serge 1024
    _cairo_image_surface_create_similar,
1025
    NULL, /* create similar image */
1026
    _cairo_image_surface_map_to_image,
1027
    _cairo_image_surface_unmap_image,
1892 serge 1028
 
3959 Serge 1029
    _cairo_image_surface_source,
1892 serge 1030
    _cairo_image_surface_acquire_source_image,
1031
    _cairo_image_surface_release_source_image,
3959 Serge 1032
    _cairo_image_surface_snapshot,
1892 serge 1033
 
1034
    NULL, /* copy_page */
1035
    NULL, /* show_page */
3959 Serge 1036
 
1892 serge 1037
    _cairo_image_surface_get_extents,
1038
    _cairo_image_surface_get_font_options,
3959 Serge 1039
 
1892 serge 1040
    NULL, /* flush */
3959 Serge 1041
    NULL,
1892 serge 1042
 
1043
    _cairo_image_surface_paint,
1044
    _cairo_image_surface_mask,
1045
    _cairo_image_surface_stroke,
1046
    _cairo_image_surface_fill,
3959 Serge 1047
    NULL, /* fill-stroke */
1892 serge 1048
    _cairo_image_surface_glyphs,
1049
};
1050
 
1051
/* A convenience function for when one needs to coerce an image
1052
 * surface to an alternate format. */
1053
cairo_image_surface_t *
1054
_cairo_image_surface_coerce (cairo_image_surface_t *surface)
1055
{
1056
    return _cairo_image_surface_coerce_to_format (surface,
1057
		                                  _cairo_format_from_content (surface->base.content));
1058
}
1059
 
1060
/* A convenience function for when one needs to coerce an image
1061
 * surface to an alternate format. */
1062
cairo_image_surface_t *
1063
_cairo_image_surface_coerce_to_format (cairo_image_surface_t *surface,
1064
			               cairo_format_t	      format)
1065
{
1066
    cairo_image_surface_t *clone;
1067
    cairo_status_t status;
1068
 
1069
    status = surface->base.status;
1070
    if (unlikely (status))
1071
	return (cairo_image_surface_t *)_cairo_surface_create_in_error (status);
1072
 
1073
    if (surface->format == format)
1074
	return (cairo_image_surface_t *)cairo_surface_reference(&surface->base);
1075
 
1076
    clone = (cairo_image_surface_t *)
1077
	cairo_image_surface_create (format, surface->width, surface->height);
1078
    if (unlikely (clone->base.status))
1079
	return clone;
1080
 
1081
    pixman_image_composite32 (PIXMAN_OP_SRC,
1082
                              surface->pixman_image, NULL, clone->pixman_image,
1083
                              0, 0,
1084
                              0, 0,
1085
                              0, 0,
1086
                              surface->width, surface->height);
1087
    clone->base.is_clear = FALSE;
1088
 
1089
    clone->base.device_transform =
1090
	surface->base.device_transform;
1091
    clone->base.device_transform_inverse =
1092
	surface->base.device_transform_inverse;
1093
 
1094
    return clone;
1095
}
1096
 
3959 Serge 1097
cairo_image_surface_t *
1098
_cairo_image_surface_create_from_image (cairo_image_surface_t *other,
1099
					pixman_format_code_t format,
1100
					int x, int y,
1101
					int width, int height, int stride)
1102
{
1103
    cairo_image_surface_t *surface;
1104
    cairo_status_t status;
1105
    pixman_image_t *image;
1106
    void *mem = NULL;
1107
 
1108
    status = other->base.status;
1109
    if (unlikely (status))
1110
	goto cleanup;
1111
 
1112
    if (stride) {
1113
	mem = _cairo_malloc_ab (height, stride);
1114
	if (unlikely (mem == NULL)) {
1115
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1116
	    goto cleanup;
1117
	}
1118
    }
1119
 
1120
    image = pixman_image_create_bits (format, width, height, mem, stride);
1121
    if (unlikely (image == NULL)) {
1122
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1123
	goto cleanup_mem;
1124
    }
1125
 
1126
    surface = (cairo_image_surface_t *)
1127
	_cairo_image_surface_create_for_pixman_image (image, format);
1128
    if (unlikely (surface->base.status)) {
1129
	status = surface->base.status;
1130
	goto cleanup_image;
1131
    }
1132
 
1133
    pixman_image_composite32 (PIXMAN_OP_SRC,
1134
                              other->pixman_image, NULL, image,
1135
                              x, y,
1136
                              0, 0,
1137
                              0, 0,
1138
                              width, height);
1139
    surface->base.is_clear = FALSE;
1140
    surface->owns_data = mem != NULL;
1141
 
1142
    return surface;
1143
 
1144
cleanup_image:
1145
    pixman_image_unref (image);
1146
cleanup_mem:
1147
    free (mem);
1148
cleanup:
1149
    return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
1150
}
1151
 
1892 serge 1152
cairo_image_transparency_t
3959 Serge 1153
_cairo_image_analyze_transparency (cairo_image_surface_t *image)
1892 serge 1154
{
1155
    int x, y;
1156
 
1157
    if (image->transparency != CAIRO_IMAGE_UNKNOWN)
1158
	return image->transparency;
1159
 
1160
    if ((image->base.content & CAIRO_CONTENT_ALPHA) == 0)
1161
	return image->transparency = CAIRO_IMAGE_IS_OPAQUE;
1162
 
3959 Serge 1163
    if (image->base.is_clear)
1164
	return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
1165
 
1892 serge 1166
    if ((image->base.content & CAIRO_CONTENT_COLOR) == 0) {
3959 Serge 1167
	if (image->format == CAIRO_FORMAT_A1) {
1892 serge 1168
	    return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
3959 Serge 1169
	} else if (image->format == CAIRO_FORMAT_A8) {
1170
	    for (y = 0; y < image->height; y++) {
1171
		uint8_t *alpha = (uint8_t *) (image->data + y * image->stride);
1172
 
1173
		for (x = 0; x < image->width; x++, alpha++) {
1174
		    if (*alpha > 0 && *alpha < 255)
1175
			return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
1176
		}
1177
	    }
1178
	    return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
1179
	} else {
1892 serge 1180
	    return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
3959 Serge 1181
	}
1892 serge 1182
    }
1183
 
1184
    if (image->format == CAIRO_FORMAT_RGB16_565) {
1185
	image->transparency = CAIRO_IMAGE_IS_OPAQUE;
1186
	return CAIRO_IMAGE_IS_OPAQUE;
1187
    }
1188
 
1189
    if (image->format != CAIRO_FORMAT_ARGB32)
1190
	return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
1191
 
1192
    image->transparency = CAIRO_IMAGE_IS_OPAQUE;
1193
    for (y = 0; y < image->height; y++) {
1194
	uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
1195
 
1196
	for (x = 0; x < image->width; x++, pixel++) {
1197
	    int a = (*pixel & 0xff000000) >> 24;
1198
	    if (a > 0 && a < 255) {
1199
		return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
1200
	    } else if (a == 0) {
1201
		image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
1202
	    }
1203
	}
1204
    }
1205
 
1206
    return image->transparency;
1207
}
3959 Serge 1208
 
1209
cairo_image_color_t
1210
_cairo_image_analyze_color (cairo_image_surface_t      *image)
1211
{
1212
    int x, y;
1213
 
1214
    if (image->color != CAIRO_IMAGE_UNKNOWN_COLOR)
1215
	return image->color;
1216
 
1217
    if (image->format == CAIRO_FORMAT_A1)
1218
	return image->color = CAIRO_IMAGE_IS_MONOCHROME;
1219
 
1220
    if (image->format == CAIRO_FORMAT_A8)
1221
	return image->color = CAIRO_IMAGE_IS_GRAYSCALE;
1222
 
1223
    if (image->format == CAIRO_FORMAT_ARGB32) {
1224
	image->color = CAIRO_IMAGE_IS_MONOCHROME;
1225
	for (y = 0; y < image->height; y++) {
1226
	    uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
1227
 
1228
	    for (x = 0; x < image->width; x++, pixel++) {
1229
		int a = (*pixel & 0xff000000) >> 24;
1230
		int r = (*pixel & 0x00ff0000) >> 16;
1231
		int g = (*pixel & 0x0000ff00) >> 8;
1232
		int b = (*pixel & 0x000000ff);
1233
		if (a == 0) {
1234
		    r = g = b = 0;
1235
		} else {
1236
		    r = (r * 255 + a / 2) / a;
1237
		    g = (g * 255 + a / 2) / a;
1238
		    b = (b * 255 + a / 2) / a;
1239
		}
1240
		if (!(r == g && g == b))
1241
		    return image->color = CAIRO_IMAGE_IS_COLOR;
1242
		else if (r > 0 && r < 255)
1243
		    image->color = CAIRO_IMAGE_IS_GRAYSCALE;
1244
	    }
1245
	}
1246
	return image->color;
1247
    }
1248
 
1249
    if (image->format == CAIRO_FORMAT_RGB24) {
1250
	image->color = CAIRO_IMAGE_IS_MONOCHROME;
1251
	for (y = 0; y < image->height; y++) {
1252
	    uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
1253
 
1254
	    for (x = 0; x < image->width; x++, pixel++) {
1255
		int r = (*pixel & 0x00ff0000) >> 16;
1256
		int g = (*pixel & 0x0000ff00) >>  8;
1257
		int b = (*pixel & 0x000000ff);
1258
		if (!(r == g && g == b))
1259
		    return image->color = CAIRO_IMAGE_IS_COLOR;
1260
		else if (r > 0 && r < 255)
1261
		    image->color = CAIRO_IMAGE_IS_GRAYSCALE;
1262
	    }
1263
	}
1264
	return image->color;
1265
    }
1266
 
1267
    return image->color = CAIRO_IMAGE_IS_COLOR;
1268
}
1269
 
1270
cairo_image_surface_t *
1271
_cairo_image_surface_clone_subimage (cairo_surface_t             *surface,
1272
				     const cairo_rectangle_int_t *extents)
1273
{
1274
    cairo_surface_t *image;
1275
    cairo_surface_pattern_t pattern;
1276
    cairo_status_t status;
1277
 
1278
    image = cairo_surface_create_similar_image (surface,
1279
						_cairo_format_from_content (surface->content),
1280
						extents->width,
1281
						extents->height);
1282
    if (image->status)
1283
	return to_image_surface (image);
1284
 
1285
    /* TODO: check me with non-identity device_transform. Should we
1286
     * clone the scaling, too? */
1287
    cairo_surface_set_device_offset (image,
1288
				     -extents->x,
1289
				     -extents->y);
1290
 
1291
    _cairo_pattern_init_for_surface (&pattern, surface);
1292
    pattern.base.filter = CAIRO_FILTER_NEAREST;
1293
 
1294
    status = _cairo_surface_paint (image,
1295
				   CAIRO_OPERATOR_SOURCE,
1296
				   &pattern.base,
1297
				   NULL);
1298
 
1299
    _cairo_pattern_fini (&pattern.base);
1300
 
1301
    if (unlikely (status))
1302
	goto error;
1303
 
1304
    /* We use the parent as a flag during map-to-image/umap-image that the
1305
     * resultant image came from a fallback rather than as direct call
1306
     * to the backend's map_to_image(). Whilst we use it as a simple flag,
1307
     * we need to make sure the parent surface obeys the reference counting
1308
     * semantics and is consistent for all callers.
1309
     */
1310
    _cairo_image_surface_set_parent (to_image_surface (image),
1311
				     cairo_surface_reference (surface));
1312
 
1313
    return to_image_surface (image);
1314
 
1315
error:
1316
    cairo_surface_destroy (image);
1317
    return to_image_surface (_cairo_surface_create_in_error (status));
1318
}