Coverage Report

Created: 2025-07-23 08:13

/src/cairo/src/cairo-compositor.c
Line
Count
Source (jump to first uncovered line)
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 © 2011 Intel Corporation
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it either under the terms of the GNU Lesser General Public
8
 * License version 2.1 as published by the Free Software Foundation
9
 * (the "LGPL") or, at your option, under the terms of the Mozilla
10
 * Public License Version 1.1 (the "MPL"). If you do not alter this
11
 * notice, a recipient may use your version of this file under either
12
 * the MPL or the LGPL.
13
 *
14
 * You should have received a copy of the LGPL along with this library
15
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17
 * You should have received a copy of the MPL along with this library
18
 * in the file COPYING-MPL-1.1
19
 *
20
 * The contents of this file are subject to the Mozilla Public License
21
 * Version 1.1 (the "License"); you may not use this file except in
22
 * compliance with the License. You may obtain a copy of the License at
23
 * http://www.mozilla.org/MPL/
24
 *
25
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27
 * the specific language governing rights and limitations.
28
 *
29
 * The Original Code is the cairo graphics library.
30
 *
31
 * The Initial Developer of the Original Code is University of Southern
32
 * California.
33
 *
34
 * Contributor(s):
35
 *  Chris Wilson <chris@chris-wilson.co.uk>
36
 */
37
38
#include "cairoint.h"
39
40
#include "cairo-compositor-private.h"
41
#include "cairo-damage-private.h"
42
#include "cairo-error-private.h"
43
44
cairo_int_status_t
45
_cairo_compositor_paint (const cairo_compositor_t *compositor,
46
       cairo_surface_t    *surface,
47
       cairo_operator_t    op,
48
       const cairo_pattern_t    *source,
49
       const cairo_clip_t   *clip)
50
14
{
51
14
    cairo_composite_rectangles_t extents;
52
14
    cairo_int_status_t status;
53
54
14
    TRACE ((stderr, "%s\n", __FUNCTION__));
55
14
    status = _cairo_composite_rectangles_init_for_paint (&extents, surface,
56
14
               op, source,
57
14
               clip);
58
14
    if (unlikely (status))
59
0
  return status;
60
61
14
    do {
62
14
  while (compositor->paint == NULL)
63
0
      compositor = compositor->delegate;
64
65
14
  status = compositor->paint (compositor, &extents);
66
67
14
  compositor = compositor->delegate;
68
14
    } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
69
70
14
    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
71
0
  TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
72
0
    __FUNCTION__,
73
0
    extents.unbounded.x, extents.unbounded.y,
74
0
    extents.unbounded.width, extents.unbounded.height));
75
0
  surface->damage = _cairo_damage_add_rectangle (surface->damage,
76
0
                   &extents.unbounded);
77
0
    }
78
79
14
    _cairo_composite_rectangles_fini (&extents);
80
81
14
    return status;
82
14
}
83
84
cairo_int_status_t
85
_cairo_compositor_mask (const cairo_compositor_t  *compositor,
86
      cairo_surface_t     *surface,
87
      cairo_operator_t     op,
88
      const cairo_pattern_t   *source,
89
      const cairo_pattern_t   *mask,
90
      const cairo_clip_t    *clip)
91
2
{
92
2
    cairo_composite_rectangles_t extents;
93
2
    cairo_int_status_t status;
94
95
2
    TRACE ((stderr, "%s\n", __FUNCTION__));
96
2
    status = _cairo_composite_rectangles_init_for_mask (&extents, surface,
97
2
              op, source, mask,
98
2
              clip);
99
2
    if (unlikely (status))
100
0
  return status;
101
102
4
    do {
103
6
  while (compositor->mask == NULL)
104
2
      compositor = compositor->delegate;
105
106
4
  status = compositor->mask (compositor, &extents);
107
108
4
  compositor = compositor->delegate;
109
4
    } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
110
111
2
    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
112
0
  TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
113
0
    __FUNCTION__,
114
0
    extents.unbounded.x, extents.unbounded.y,
115
0
    extents.unbounded.width, extents.unbounded.height));
116
0
  surface->damage = _cairo_damage_add_rectangle (surface->damage,
117
0
                   &extents.unbounded);
118
0
    }
119
120
2
    _cairo_composite_rectangles_fini (&extents);
121
122
2
    return status;
123
2
}
124
125
static cairo_int_status_t
126
_cairo_compositor_stroke_impl (const cairo_compositor_t *compositor,
127
             cairo_surface_t    *surface,
128
             cairo_operator_t    op,
129
             const cairo_pattern_t    *source,
130
             const cairo_path_fixed_t *path,
131
             const cairo_stroke_style_t *style,
132
             const cairo_matrix_t   *ctm,
133
             const cairo_matrix_t   *ctm_inverse,
134
             double      tolerance,
135
             cairo_antialias_t     antialias,
136
             const cairo_clip_t   *clip)
137
0
{
138
0
    cairo_composite_rectangles_t extents;
139
0
    cairo_int_status_t status;
140
141
0
    TRACE ((stderr, "%s\n", __FUNCTION__));
142
143
0
    if (_cairo_pen_vertices_needed (tolerance, style->line_width/2, ctm) <= 1)
144
0
  return CAIRO_INT_STATUS_NOTHING_TO_DO;
145
146
0
    status = _cairo_composite_rectangles_init_for_stroke (&extents, surface,
147
0
                op, source,
148
0
                path, style, ctm,
149
0
                clip);
150
0
    if (unlikely (status))
151
0
  return status;
152
153
0
    do {
154
0
  while (compositor->stroke == NULL)
155
0
      compositor = compositor->delegate;
156
157
0
  status = compositor->stroke (compositor, &extents,
158
0
             path, style, ctm, ctm_inverse,
159
0
             tolerance, antialias);
160
161
0
  compositor = compositor->delegate;
162
0
    } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
163
164
0
    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
165
0
  TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
166
0
    __FUNCTION__,
167
0
    extents.unbounded.x, extents.unbounded.y,
168
0
    extents.unbounded.width, extents.unbounded.height));
169
0
  surface->damage = _cairo_damage_add_rectangle (surface->damage,
170
0
                   &extents.unbounded);
171
0
    }
172
173
0
    _cairo_composite_rectangles_fini (&extents);
174
175
0
    return status;
176
0
}
177
178
cairo_int_status_t
179
_cairo_compositor_stroke (const cairo_compositor_t  *compositor,
180
        cairo_surface_t   *surface,
181
        cairo_operator_t     op,
182
        const cairo_pattern_t *source,
183
        const cairo_path_fixed_t  *path,
184
        const cairo_stroke_style_t  *style,
185
        const cairo_matrix_t    *ctm,
186
        const cairo_matrix_t    *ctm_inverse,
187
        double       tolerance,
188
        cairo_antialias_t    antialias,
189
        const cairo_clip_t    *clip)
190
0
{
191
0
    if (!style->is_hairline)
192
0
  return _cairo_compositor_stroke_impl (compositor, surface,
193
0
                      op, source, path,
194
0
                style, ctm, ctm_inverse,
195
0
                tolerance, antialias, clip);
196
0
    else {
197
0
  cairo_stroke_style_t hairline_style;
198
0
  cairo_status_t status;
199
0
  cairo_matrix_t identity;
200
201
0
  status = _cairo_stroke_style_init_copy (&hairline_style, style);
202
0
  if (unlikely (status))
203
0
      return status;
204
  
205
0
  hairline_style.line_width = 1.0;
206
207
0
  cairo_matrix_init_identity (&identity);
208
209
0
  status = _cairo_compositor_stroke_impl (compositor, surface,
210
0
                  op, source, path,
211
0
                  &hairline_style, &identity, &identity,
212
0
                  tolerance, antialias, clip);
213
214
0
  _cairo_stroke_style_fini (&hairline_style);
215
216
0
  return status;
217
0
    }
218
0
}
219
220
cairo_int_status_t
221
_cairo_compositor_fill (const cairo_compositor_t  *compositor,
222
      cairo_surface_t     *surface,
223
      cairo_operator_t     op,
224
      const cairo_pattern_t   *source,
225
      const cairo_path_fixed_t  *path,
226
      cairo_fill_rule_t    fill_rule,
227
      double         tolerance,
228
      cairo_antialias_t    antialias,
229
      const cairo_clip_t    *clip)
230
6
{
231
6
    cairo_composite_rectangles_t extents;
232
6
    cairo_int_status_t status;
233
234
6
    TRACE ((stderr, "%s\n", __FUNCTION__));
235
6
    status = _cairo_composite_rectangles_init_for_fill (&extents, surface,
236
6
              op, source, path,
237
6
              clip);
238
6
    if (unlikely (status))
239
0
  return status;
240
241
6
    do {
242
6
  while (compositor->fill == NULL)
243
0
      compositor = compositor->delegate;
244
245
6
  status = compositor->fill (compositor, &extents,
246
6
           path, fill_rule, tolerance, antialias);
247
248
6
  compositor = compositor->delegate;
249
6
    } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
250
251
6
    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
252
0
  TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
253
0
    __FUNCTION__,
254
0
    extents.unbounded.x, extents.unbounded.y,
255
0
    extents.unbounded.width, extents.unbounded.height));
256
0
  surface->damage = _cairo_damage_add_rectangle (surface->damage,
257
0
                   &extents.unbounded);
258
0
    }
259
260
6
    _cairo_composite_rectangles_fini (&extents);
261
262
6
    return status;
263
6
}
264
265
cairo_int_status_t
266
_cairo_compositor_glyphs (const cairo_compositor_t    *compositor,
267
        cairo_surface_t     *surface,
268
        cairo_operator_t       op,
269
        const cairo_pattern_t     *source,
270
        cairo_glyph_t       *glyphs,
271
        int          num_glyphs,
272
        cairo_scaled_font_t     *scaled_font,
273
        const cairo_clip_t      *clip)
274
0
{
275
0
    cairo_composite_rectangles_t extents;
276
0
    cairo_bool_t overlap;
277
0
    cairo_int_status_t status;
278
279
0
    TRACE ((stderr, "%s\n", __FUNCTION__));
280
0
    status = _cairo_composite_rectangles_init_for_glyphs (&extents, surface,
281
0
                op, source,
282
0
                scaled_font,
283
0
                glyphs, num_glyphs,
284
0
                clip, &overlap);
285
0
    if (unlikely (status))
286
0
  return status;
287
288
0
    do {
289
0
  while (compositor->glyphs == NULL)
290
0
      compositor = compositor->delegate;
291
292
0
  status = compositor->glyphs (compositor, &extents,
293
0
             scaled_font, glyphs, num_glyphs, overlap);
294
295
0
  compositor = compositor->delegate;
296
0
    } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
297
298
0
    if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
299
0
  TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
300
0
    __FUNCTION__,
301
0
    extents.unbounded.x, extents.unbounded.y,
302
0
    extents.unbounded.width, extents.unbounded.height));
303
0
  surface->damage = _cairo_damage_add_rectangle (surface->damage,
304
0
                   &extents.unbounded);
305
0
    }
306
307
0
    _cairo_composite_rectangles_fini (&extents);
308
309
0
    return status;
310
0
}