Coverage Report

Created: 2025-11-16 07:45

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