Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/cairo/src/cairo-surface-offset.c
Line
Count
Source (jump to first uncovered line)
1
/* cairo - a vector graphics library with display and print output
2
 *
3
 * Copyright © 2005 Red Hat, Inc
4
 * Copyright © 2007 Adrian Johnson
5
 * Copyright © 2009 Chris Wilson
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 Red Hat, Inc.
33
 *
34
 * Contributor(s):
35
 *      Chris Wilson <chris@chris-wilson.co.uk>
36
 */
37
38
#include "cairoint.h"
39
40
#include "cairo-clip-inline.h"
41
#include "cairo-error-private.h"
42
#include "cairo-pattern-private.h"
43
#include "cairo-surface-offset-private.h"
44
45
/* A collection of routines to facilitate drawing to an alternate surface. */
46
47
static void
48
_copy_transformed_pattern (cairo_pattern_t *pattern,
49
         const cairo_pattern_t *original,
50
         const cairo_matrix_t  *ctm_inverse)
51
0
{
52
0
    _cairo_pattern_init_static_copy (pattern, original);
53
54
0
    if (! _cairo_matrix_is_identity (ctm_inverse))
55
0
  _cairo_pattern_transform (pattern, ctm_inverse);
56
0
}
57
58
cairo_status_t
59
_cairo_surface_offset_paint (cairo_surface_t    *target,
60
           int x, int y,
61
           cairo_operator_t    op,
62
           const cairo_pattern_t  *source,
63
           const cairo_clip_t   *clip)
64
0
{
65
0
    cairo_status_t status;
66
0
    cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
67
0
    cairo_pattern_union_t source_copy;
68
69
0
    if (unlikely (target->status))
70
0
  return target->status;
71
72
0
    if (_cairo_clip_is_all_clipped (clip))
73
0
  return CAIRO_STATUS_SUCCESS;
74
75
0
    if (x | y) {
76
0
  cairo_matrix_t m;
77
78
0
  dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
79
80
0
  cairo_matrix_init_translate (&m, x, y);
81
0
  _copy_transformed_pattern (&source_copy.base, source, &m);
82
0
  source = &source_copy.base;
83
0
    }
84
85
0
    status = _cairo_surface_paint (target, op, source, dev_clip);
86
87
0
    if (dev_clip != clip)
88
0
  _cairo_clip_destroy (dev_clip);
89
90
0
    return status;
91
0
}
92
93
cairo_status_t
94
_cairo_surface_offset_mask (cairo_surface_t   *target,
95
          int x, int y,
96
          cairo_operator_t     op,
97
          const cairo_pattern_t *source,
98
          const cairo_pattern_t *mask,
99
          const cairo_clip_t    *clip)
100
0
{
101
0
    cairo_status_t status;
102
0
    cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
103
0
    cairo_pattern_union_t source_copy;
104
0
    cairo_pattern_union_t mask_copy;
105
106
0
    if (unlikely (target->status))
107
0
  return target->status;
108
109
0
    if (_cairo_clip_is_all_clipped (clip))
110
0
  return CAIRO_STATUS_SUCCESS;
111
112
0
    if (x | y) {
113
0
  cairo_matrix_t m;
114
115
0
  dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
116
117
0
  cairo_matrix_init_translate (&m, x, y);
118
0
  _copy_transformed_pattern (&source_copy.base, source, &m);
119
0
  _copy_transformed_pattern (&mask_copy.base, mask, &m);
120
0
  source = &source_copy.base;
121
0
  mask = &mask_copy.base;
122
0
    }
123
124
0
    status = _cairo_surface_mask (target, op,
125
0
          source, mask,
126
0
          dev_clip);
127
128
0
    if (dev_clip != clip)
129
0
  _cairo_clip_destroy (dev_clip);
130
131
0
    return status;
132
0
}
133
134
cairo_status_t
135
_cairo_surface_offset_stroke (cairo_surface_t   *surface,
136
            int x, int y,
137
            cairo_operator_t     op,
138
            const cairo_pattern_t *source,
139
            const cairo_path_fixed_t  *path,
140
            const cairo_stroke_style_t*stroke_style,
141
            const cairo_matrix_t  *ctm,
142
            const cairo_matrix_t  *ctm_inverse,
143
            double       tolerance,
144
            cairo_antialias_t    antialias,
145
            const cairo_clip_t    *clip)
146
16
{
147
16
    cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path;
148
16
    cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
149
16
    cairo_matrix_t dev_ctm = *ctm;
150
16
    cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
151
16
    cairo_pattern_union_t source_copy;
152
16
    cairo_status_t status;
153
154
16
    if (unlikely (surface->status))
155
0
  return surface->status;
156
157
16
    if (_cairo_clip_is_all_clipped (clip))
158
16
  return CAIRO_STATUS_SUCCESS;
159
160
0
    if (x | y) {
161
0
  cairo_matrix_t m;
162
163
0
  dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
164
165
0
  status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
166
0
  if (unlikely (status))
167
0
      goto FINISH;
168
169
0
  _cairo_path_fixed_translate (&path_copy,
170
0
             _cairo_fixed_from_int (-x),
171
0
             _cairo_fixed_from_int (-y));
172
0
  dev_path = &path_copy;
173
174
0
  cairo_matrix_init_translate (&m, -x, -y);
175
0
  cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
176
177
0
  cairo_matrix_init_translate (&m, x, y);
178
0
  _copy_transformed_pattern (&source_copy.base, source, &m);
179
0
  source = &source_copy.base;
180
0
  cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse);
181
0
    }
182
183
0
    status = _cairo_surface_stroke (surface, op, source,
184
0
            dev_path, stroke_style,
185
0
            &dev_ctm, &dev_ctm_inverse,
186
0
            tolerance, antialias,
187
0
            dev_clip);
188
189
0
FINISH:
190
0
    if (dev_path != path)
191
0
  _cairo_path_fixed_fini (dev_path);
192
0
    if (dev_clip != clip)
193
0
  _cairo_clip_destroy (dev_clip);
194
195
0
    return status;
196
0
}
197
198
cairo_status_t
199
_cairo_surface_offset_fill (cairo_surface_t *surface,
200
          int x, int y,
201
          cairo_operator_t   op,
202
          const cairo_pattern_t*source,
203
          const cairo_path_fixed_t  *path,
204
          cairo_fill_rule_t  fill_rule,
205
          double     tolerance,
206
          cairo_antialias_t  antialias,
207
          const cairo_clip_t  *clip)
208
0
{
209
0
    cairo_status_t status;
210
0
    cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path;
211
0
    cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
212
0
    cairo_pattern_union_t source_copy;
213
214
0
    if (unlikely (surface->status))
215
0
  return surface->status;
216
217
0
    if (_cairo_clip_is_all_clipped (clip))
218
0
  return CAIRO_STATUS_SUCCESS;
219
220
0
    if (x | y) {
221
0
  cairo_matrix_t m;
222
223
0
  dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
224
225
0
  status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
226
0
  if (unlikely (status))
227
0
      goto FINISH;
228
229
0
  _cairo_path_fixed_translate (&path_copy,
230
0
             _cairo_fixed_from_int (-x),
231
0
             _cairo_fixed_from_int (-y));
232
0
  dev_path = &path_copy;
233
234
0
  cairo_matrix_init_translate (&m, x, y);
235
0
  _copy_transformed_pattern (&source_copy.base, source, &m);
236
0
  source = &source_copy.base;
237
0
    }
238
239
0
    status = _cairo_surface_fill (surface, op, source,
240
0
          dev_path, fill_rule,
241
0
          tolerance, antialias,
242
0
          dev_clip);
243
244
0
FINISH:
245
0
    if (dev_path != path)
246
0
  _cairo_path_fixed_fini (dev_path);
247
0
    if (dev_clip != clip)
248
0
  _cairo_clip_destroy (dev_clip);
249
250
0
    return status;
251
0
}
252
253
cairo_status_t
254
_cairo_surface_offset_glyphs (cairo_surface_t   *surface,
255
            int x, int y,
256
            cairo_operator_t     op,
257
            const cairo_pattern_t *source,
258
            cairo_scaled_font_t *scaled_font,
259
            cairo_glyph_t   *glyphs,
260
            int      num_glyphs,
261
            const cairo_clip_t  *clip)
262
0
{
263
0
    cairo_status_t status;
264
0
    cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
265
0
    cairo_pattern_union_t source_copy;
266
0
    cairo_glyph_t *dev_glyphs;
267
0
    int i;
268
269
0
    if (unlikely (surface->status))
270
0
  return surface->status;
271
272
0
    if (_cairo_clip_is_all_clipped (clip))
273
0
  return CAIRO_STATUS_SUCCESS;
274
275
0
    dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
276
0
    if (dev_glyphs == NULL)
277
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
278
279
0
    memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
280
281
0
    if (x | y) {
282
0
  cairo_matrix_t m;
283
284
0
  dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
285
286
0
  cairo_matrix_init_translate (&m, x, y);
287
0
  _copy_transformed_pattern (&source_copy.base, source, &m);
288
0
  source = &source_copy.base;
289
290
0
  for (i = 0; i < num_glyphs; i++) {
291
0
      dev_glyphs[i].x -= x;
292
0
      dev_glyphs[i].y -= y;
293
0
  }
294
0
    }
295
296
0
    status = _cairo_surface_show_text_glyphs (surface, op, source,
297
0
                NULL, 0,
298
0
                dev_glyphs, num_glyphs,
299
0
                NULL, 0, 0,
300
0
                scaled_font,
301
0
                dev_clip);
302
303
0
    if (dev_clip != clip)
304
0
  _cairo_clip_destroy (dev_clip);
305
0
    free (dev_glyphs);
306
307
0
    return status;
308
0
}