Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/cairo/src/cairo-debug.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
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it either under the terms of the GNU Lesser General Public
7
 * License version 2.1 as published by the Free Software Foundation
8
 * (the "LGPL") or, at your option, under the terms of the Mozilla
9
 * Public License Version 1.1 (the "MPL"). If you do not alter this
10
 * notice, a recipient may use your version of this file under either
11
 * the MPL or the LGPL.
12
 *
13
 * You should have received a copy of the LGPL along with this library
14
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16
 * You should have received a copy of the MPL along with this library
17
 * in the file COPYING-MPL-1.1
18
 *
19
 * The contents of this file are subject to the Mozilla Public License
20
 * Version 1.1 (the "License"); you may not use this file except in
21
 * compliance with the License. You may obtain a copy of the License at
22
 * http://www.mozilla.org/MPL/
23
 *
24
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26
 * the specific language governing rights and limitations.
27
 *
28
 * The Original Code is the cairo graphics library.
29
 *
30
 * The Initial Developer of the Original Code is Red Hat, Inc.
31
 *
32
 * Contributor(s):
33
 *  Carl D. Worth <cworth@cworth.org>
34
 */
35
36
#include "cairoint.h"
37
#include "cairo-image-surface-private.h"
38
39
/**
40
 * cairo_debug_reset_static_data:
41
 *
42
 * Resets all static data within cairo to its original state,
43
 * (ie. identical to the state at the time of program invocation). For
44
 * example, all caches within cairo will be flushed empty.
45
 *
46
 * This function is intended to be useful when using memory-checking
47
 * tools such as valgrind. When valgrind's memcheck analyzes a
48
 * cairo-using program without a call to cairo_debug_reset_static_data(),
49
 * it will report all data reachable via cairo's static objects as
50
 * "still reachable". Calling cairo_debug_reset_static_data() just prior
51
 * to program termination will make it easier to get squeaky clean
52
 * reports from valgrind.
53
 *
54
 * WARNING: It is only safe to call this function when there are no
55
 * active cairo objects remaining, (ie. the appropriate destroy
56
 * functions have been called as necessary). If there are active cairo
57
 * objects, this call is likely to cause a crash, (eg. an assertion
58
 * failure due to a hash table being destroyed when non-empty).
59
 *
60
 * Since: 1.0
61
 **/
62
void
63
cairo_debug_reset_static_data (void)
64
0
{
65
0
    CAIRO_MUTEX_INITIALIZE ();
66
67
0
    _cairo_scaled_font_map_destroy ();
68
69
0
    _cairo_toy_font_face_reset_static_data ();
70
71
0
#if CAIRO_HAS_FT_FONT
72
0
    _cairo_ft_font_reset_static_data ();
73
0
#endif
74
75
#if CAIRO_HAS_WIN32_FONT
76
    _cairo_win32_font_reset_static_data ();
77
#endif
78
79
0
    _cairo_intern_string_reset_static_data ();
80
81
0
    _cairo_scaled_font_reset_static_data ();
82
83
0
    _cairo_pattern_reset_static_data ();
84
85
0
    _cairo_clip_reset_static_data ();
86
87
0
    _cairo_image_reset_static_data ();
88
89
0
    _cairo_image_compositor_reset_static_data ();
90
91
0
    _cairo_default_context_reset_static_data ();
92
93
0
    CAIRO_MUTEX_FINALIZE ();
94
0
}
95
96
#if HAVE_VALGRIND
97
void
98
_cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
99
{
100
    const cairo_image_surface_t *image = (cairo_image_surface_t *) surface;
101
    const uint8_t *bits;
102
    int row, width;
103
104
    if (surface == NULL)
105
  return;
106
107
    if (! RUNNING_ON_VALGRIND)
108
  return;
109
110
    bits = image->data;
111
    switch (image->format) {
112
    case CAIRO_FORMAT_A1:
113
  width = (image->width + 7)/8;
114
  break;
115
    case CAIRO_FORMAT_A8:
116
  width = image->width;
117
  break;
118
    case CAIRO_FORMAT_RGB16_565:
119
  width = image->width*2;
120
  break;
121
    case CAIRO_FORMAT_RGB24:
122
    case CAIRO_FORMAT_RGB30:
123
    case CAIRO_FORMAT_ARGB32:
124
  width = image->width*4;
125
  break;
126
    case CAIRO_FORMAT_RGB96F:
127
  width = image->width*12;
128
  break;
129
    case CAIRO_FORMAT_RGBA128F:
130
  width = image->width*16;
131
  break;
132
    case CAIRO_FORMAT_INVALID:
133
    default:
134
  /* XXX compute width from pixman bpp */
135
  return;
136
    }
137
138
    for (row = 0; row < image->height; row++) {
139
  VALGRIND_CHECK_MEM_IS_DEFINED (bits, width);
140
  /* and then silence any future valgrind warnings */
141
  VALGRIND_MAKE_MEM_DEFINED (bits, width);
142
  bits += image->stride;
143
    }
144
}
145
#endif
146
147
148
#if 0
149
void
150
_cairo_image_surface_write_to_ppm (cairo_image_surface_t *isurf, const char *fn)
151
{
152
    char *fmt;
153
    if (isurf->format == CAIRO_FORMAT_ARGB32 || isurf->format == CAIRO_FORMAT_RGB24)
154
        fmt = "P6";
155
    else if (isurf->format == CAIRO_FORMAT_A8)
156
        fmt = "P5";
157
    else
158
        return;
159
160
    FILE *fp = fopen(fn, "wb");
161
    if (!fp)
162
        return;
163
164
    fprintf (fp, "%s %d %d 255\n", fmt,isurf->width, isurf->height);
165
    for (int j = 0; j < isurf->height; j++) {
166
        unsigned char *row = isurf->data + isurf->stride * j;
167
        for (int i = 0; i < isurf->width; i++) {
168
            if (isurf->format == CAIRO_FORMAT_ARGB32 || isurf->format == CAIRO_FORMAT_RGB24) {
169
                unsigned char r = *row++;
170
                unsigned char g = *row++;
171
                unsigned char b = *row++;
172
                *row++;
173
                putc(r, fp);
174
                putc(g, fp);
175
                putc(b, fp);
176
            } else {
177
                unsigned char a = *row++;
178
                putc(a, fp);
179
            }
180
        }
181
    }
182
183
    fclose (fp);
184
185
    fprintf (stderr, "Wrote %s\n", fn);
186
}
187
#endif
188
189
static cairo_status_t
190
_print_move_to (void *closure,
191
    const cairo_point_t *point)
192
0
{
193
0
    fprintf (closure,
194
0
       " %f %f m",
195
0
       _cairo_fixed_to_double (point->x),
196
0
       _cairo_fixed_to_double (point->y));
197
198
0
    return CAIRO_STATUS_SUCCESS;
199
0
}
200
201
static cairo_status_t
202
_print_line_to (void *closure,
203
    const cairo_point_t *point)
204
0
{
205
0
    fprintf (closure,
206
0
       " %f %f l",
207
0
       _cairo_fixed_to_double (point->x),
208
0
       _cairo_fixed_to_double (point->y));
209
210
0
    return CAIRO_STATUS_SUCCESS;
211
0
}
212
213
static cairo_status_t
214
_print_curve_to (void *closure,
215
     const cairo_point_t *p1,
216
     const cairo_point_t *p2,
217
     const cairo_point_t *p3)
218
0
{
219
0
    fprintf (closure,
220
0
       " %f %f %f %f %f %f c",
221
0
       _cairo_fixed_to_double (p1->x),
222
0
       _cairo_fixed_to_double (p1->y),
223
0
       _cairo_fixed_to_double (p2->x),
224
0
       _cairo_fixed_to_double (p2->y),
225
0
       _cairo_fixed_to_double (p3->x),
226
0
       _cairo_fixed_to_double (p3->y));
227
228
0
    return CAIRO_STATUS_SUCCESS;
229
0
}
230
231
static cairo_status_t
232
_print_close (void *closure)
233
0
{
234
0
    fprintf (closure, " h");
235
236
0
    return CAIRO_STATUS_SUCCESS;
237
0
}
238
239
void
240
_cairo_debug_print_path (FILE *stream, const cairo_path_fixed_t *path)
241
0
{
242
0
    cairo_status_t status;
243
0
    cairo_box_t box;
244
245
0
    fprintf (stream,
246
0
       "path: extents=(%f, %f), (%f, %f)\n",
247
0
      _cairo_fixed_to_double (path->extents.p1.x),
248
0
      _cairo_fixed_to_double (path->extents.p1.y),
249
0
      _cairo_fixed_to_double (path->extents.p2.x),
250
0
      _cairo_fixed_to_double (path->extents.p2.y));
251
252
0
    status = _cairo_path_fixed_interpret (path,
253
0
            _print_move_to,
254
0
            _print_line_to,
255
0
            _print_curve_to,
256
0
            _print_close,
257
0
            stream);
258
0
    assert (status == CAIRO_STATUS_SUCCESS);
259
260
0
    if (_cairo_path_fixed_is_box (path, &box)) {
261
0
  fprintf (stream, "[box (%d, %d), (%d, %d)]",
262
0
     box.p1.x, box.p1.y, box.p2.x, box.p2.y);
263
0
    }
264
265
0
    fprintf (stream, "\n");
266
0
}
267
268
void
269
_cairo_debug_print_polygon (FILE *stream, cairo_polygon_t *polygon)
270
0
{
271
0
    int n;
272
273
0
    fprintf (stream,
274
0
       "polygon: extents=(%f, %f), (%f, %f)\n",
275
0
      _cairo_fixed_to_double (polygon->extents.p1.x),
276
0
      _cairo_fixed_to_double (polygon->extents.p1.y),
277
0
      _cairo_fixed_to_double (polygon->extents.p2.x),
278
0
      _cairo_fixed_to_double (polygon->extents.p2.y));
279
0
    if (polygon->num_limits) {
280
0
  fprintf (stream,
281
0
     "       : limit=(%f, %f), (%f, %f) x %d\n",
282
0
     _cairo_fixed_to_double (polygon->limit.p1.x),
283
0
     _cairo_fixed_to_double (polygon->limit.p1.y),
284
0
     _cairo_fixed_to_double (polygon->limit.p2.x),
285
0
     _cairo_fixed_to_double (polygon->limit.p2.y),
286
0
     polygon->num_limits);
287
0
    }
288
289
0
    for (n = 0; n < polygon->num_edges; n++) {
290
0
  cairo_edge_t *edge = &polygon->edges[n];
291
292
0
  fprintf (stream,
293
0
     "  [%d] = [(%f, %f), (%f, %f)], top=%f, bottom=%f, dir=%d\n",
294
0
     n,
295
0
     _cairo_fixed_to_double (edge->line.p1.x),
296
0
     _cairo_fixed_to_double (edge->line.p1.y),
297
0
     _cairo_fixed_to_double (edge->line.p2.x),
298
0
     _cairo_fixed_to_double (edge->line.p2.y),
299
0
     _cairo_fixed_to_double (edge->top),
300
0
     _cairo_fixed_to_double (edge->bottom),
301
0
     edge->dir);
302
303
0
    }
304
0
}
305
306
void
307
_cairo_debug_print_matrix (FILE *file, const cairo_matrix_t *matrix)
308
0
{
309
0
    fprintf (file, "[%g %g %g %g %g %g]\n",
310
0
       matrix->xx, matrix->yx,
311
0
       matrix->xy, matrix->yy,
312
0
       matrix->x0, matrix->y0);
313
0
}
314
315
void
316
_cairo_debug_print_rect (FILE *file, const cairo_rectangle_int_t *rect)
317
0
{
318
0
    fprintf (file, "x: %d y: %d width: %d height: %d\n",
319
0
       rect->x, rect->y,
320
0
       rect->width, rect->height);
321
0
}