Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/cairo/src/cairo-default-context.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2002 University of Southern California
5
 * Copyright © 2005 Red Hat, Inc.
6
 * Copyright © 2011 Intel Corporation
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it either under the terms of the GNU Lesser General Public
10
 * License version 2.1 as published by the Free Software Foundation
11
 * (the "LGPL") or, at your option, under the terms of the Mozilla
12
 * Public License Version 1.1 (the "MPL"). If you do not alter this
13
 * notice, a recipient may use your version of this file under either
14
 * the MPL or the LGPL.
15
 *
16
 * You should have received a copy of the LGPL along with this library
17
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19
 * You should have received a copy of the MPL along with this library
20
 * in the file COPYING-MPL-1.1
21
 *
22
 * The contents of this file are subject to the Mozilla Public License
23
 * Version 1.1 (the "License"); you may not use this file except in
24
 * compliance with the License. You may obtain a copy of the License at
25
 * http://www.mozilla.org/MPL/
26
 *
27
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29
 * the specific language governing rights and limitations.
30
 *
31
 * The Original Code is the cairo graphics library.
32
 *
33
 * The Initial Developer of the Original Code is University of Southern
34
 * California.
35
 *
36
 * Contributor(s):
37
 *  Carl D. Worth <cworth@cworth.org>
38
 *  Chris Wilson <chris@chris-wilson.co.uk>
39
 */
40
41
#include "cairoint.h"
42
43
#include "cairo-private.h"
44
#include "cairo-arc-private.h"
45
#include "cairo-backend-private.h"
46
#include "cairo-clip-inline.h"
47
#include "cairo-default-context-private.h"
48
#include "cairo-error-private.h"
49
#include "cairo-freed-pool-private.h"
50
#include "cairo-path-private.h"
51
#include "cairo-pattern-private.h"
52
53
0
#define CAIRO_TOLERANCE_MINIMUM _cairo_fixed_to_double(1)
54
55
#if !defined(INFINITY)
56
#define INFINITY HUGE_VAL
57
#endif
58
59
static freed_pool_t context_pool;
60
61
void
62
_cairo_default_context_reset_static_data (void)
63
0
{
64
0
    _freed_pool_reset (&context_pool);
65
0
}
66
67
void
68
_cairo_default_context_fini (cairo_default_context_t *cr)
69
8.13M
{
70
8.13M
    while (cr->gstate != &cr->gstate_tail[0]) {
71
26
  if (_cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist))
72
0
      break;
73
26
    }
74
75
8.13M
    _cairo_gstate_fini (cr->gstate);
76
8.13M
    cr->gstate_freelist = cr->gstate_freelist->next; /* skip over tail[1] */
77
8.13M
    while (cr->gstate_freelist != NULL) {
78
1
  cairo_gstate_t *gstate = cr->gstate_freelist;
79
1
  cr->gstate_freelist = gstate->next;
80
1
  free (gstate);
81
1
    }
82
83
8.13M
    _cairo_path_fixed_fini (cr->path);
84
85
8.13M
    _cairo_fini (&cr->base);
86
8.13M
}
87
88
static void
89
_cairo_default_context_destroy (void *abstract_cr)
90
8.13M
{
91
8.13M
    cairo_default_context_t *cr = abstract_cr;
92
93
8.13M
    _cairo_default_context_fini (cr);
94
95
    /* mark the context as invalid to protect against misuse */
96
8.13M
    cr->base.status = CAIRO_STATUS_NULL_POINTER;
97
8.13M
    _freed_pool_put (&context_pool, cr);
98
8.13M
}
99
100
static cairo_surface_t *
101
_cairo_default_context_get_original_target (void *abstract_cr)
102
8.61M
{
103
8.61M
    cairo_default_context_t *cr = abstract_cr;
104
105
8.61M
    return _cairo_gstate_get_original_target (cr->gstate);
106
8.61M
}
107
108
static cairo_surface_t *
109
_cairo_default_context_get_current_target (void *abstract_cr)
110
0
{
111
0
    cairo_default_context_t *cr = abstract_cr;
112
113
0
    return _cairo_gstate_get_target (cr->gstate);
114
0
}
115
116
static cairo_status_t
117
_cairo_default_context_save (void *abstract_cr)
118
19.4k
{
119
19.4k
    cairo_default_context_t *cr = abstract_cr;
120
121
19.4k
    return _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist);
122
19.4k
}
123
124
static cairo_status_t
125
_cairo_default_context_restore (void *abstract_cr)
126
19.4k
{
127
19.4k
    cairo_default_context_t *cr = abstract_cr;
128
129
19.4k
    if (unlikely (_cairo_gstate_is_group (cr->gstate)))
130
0
  return _cairo_error (CAIRO_STATUS_INVALID_RESTORE);
131
132
19.4k
    return _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
133
19.4k
}
134
135
static cairo_status_t
136
_cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
137
0
{
138
0
    cairo_default_context_t *cr = abstract_cr;
139
0
    cairo_surface_t *group_surface;
140
0
    cairo_clip_t *clip;
141
0
    cairo_status_t status;
142
143
0
    clip = _cairo_gstate_get_clip (cr->gstate);
144
0
    if (_cairo_clip_is_all_clipped (clip)) {
145
0
  group_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
146
0
  status = group_surface->status;
147
0
  if (unlikely (status))
148
0
      goto bail;
149
0
    } else {
150
0
  cairo_surface_t *parent_surface;
151
0
  cairo_rectangle_int_t extents;
152
0
  cairo_bool_t bounded, is_empty;
153
154
0
  parent_surface = _cairo_gstate_get_target (cr->gstate);
155
156
0
  if (unlikely (parent_surface->status))
157
0
      return parent_surface->status;
158
0
  if (unlikely (parent_surface->finished))
159
0
      return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
160
161
  /* Get the extents that we'll use in creating our new group surface */
162
0
  bounded = _cairo_surface_get_extents (parent_surface, &extents);
163
0
  if (clip)
164
      /* XXX: This assignment just fixes a compiler warning? */
165
0
      is_empty = _cairo_rectangle_intersect (&extents,
166
0
               _cairo_clip_get_extents (clip));
167
168
0
  if (!bounded) {
169
      /* XXX: Generic solution? */
170
0
      group_surface = cairo_recording_surface_create (content, NULL);
171
0
      extents.x = extents.y = 0;
172
0
  } else {
173
0
      group_surface = _cairo_surface_create_scratch (parent_surface,
174
0
                 content,
175
0
                 extents.width,
176
0
                 extents.height,
177
0
                 CAIRO_COLOR_TRANSPARENT);
178
0
  }
179
0
  status = group_surface->status;
180
0
  if (unlikely (status))
181
0
      goto bail;
182
183
  /* Set device offsets on the new surface so that logically it appears at
184
   * the same location on the parent surface -- when we pop_group this,
185
   * the source pattern will get fixed up for the appropriate target surface
186
   * device offsets, so we want to set our own surface offsets from /that/,
187
   * and not from the device origin. */
188
0
  cairo_surface_set_device_offset (group_surface,
189
0
           parent_surface->device_transform.x0 - extents.x,
190
0
           parent_surface->device_transform.y0 - extents.y);
191
192
0
  cairo_surface_set_device_scale (group_surface,
193
0
          parent_surface->device_transform.xx,
194
0
          parent_surface->device_transform.yy);
195
196
  /* If we have a current path, we need to adjust it to compensate for
197
   * the device offset just applied. */
198
0
  _cairo_path_fixed_translate (cr->path,
199
0
             _cairo_fixed_from_int (-extents.x),
200
0
             _cairo_fixed_from_int (-extents.y));
201
0
    }
202
203
    /* create a new gstate for the redirect */
204
0
    status = _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist);
205
0
    if (unlikely (status))
206
0
  goto bail;
207
208
0
    status = _cairo_gstate_redirect_target (cr->gstate, group_surface);
209
210
0
bail:
211
0
    cairo_surface_destroy (group_surface);
212
0
    return status;
213
0
}
214
215
static cairo_pattern_t *
216
_cairo_default_context_pop_group (void *abstract_cr)
217
0
{
218
0
    cairo_default_context_t *cr = abstract_cr;
219
0
    cairo_surface_t *group_surface;
220
0
    cairo_pattern_t *group_pattern;
221
0
    cairo_surface_t *parent_surface;
222
0
    cairo_matrix_t group_matrix;
223
0
    cairo_status_t status;
224
225
    /* Verify that we are at the right nesting level */
226
0
    if (unlikely (! _cairo_gstate_is_group (cr->gstate)))
227
0
  return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_POP_GROUP);
228
229
    /* Get a reference to the active surface before restoring */
230
0
    group_surface = _cairo_gstate_get_target (cr->gstate);
231
0
    group_surface = cairo_surface_reference (group_surface);
232
233
0
    status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
234
0
    assert (status == CAIRO_STATUS_SUCCESS);
235
236
0
    parent_surface = _cairo_gstate_get_target (cr->gstate);
237
238
0
    group_pattern = cairo_pattern_create_for_surface (group_surface);
239
0
    status = group_pattern->status;
240
0
    if (unlikely (status))
241
0
        goto done;
242
243
0
    _cairo_gstate_get_matrix (cr->gstate, &group_matrix);
244
0
    cairo_pattern_set_matrix (group_pattern, &group_matrix);
245
246
    /* If we have a current path, we need to adjust it to compensate for
247
     * the device offset just removed. */
248
0
    _cairo_path_fixed_translate (cr->path,
249
0
         _cairo_fixed_from_int (parent_surface->device_transform.x0 - group_surface->device_transform.x0),
250
0
         _cairo_fixed_from_int (parent_surface->device_transform.y0 - group_surface->device_transform.y0));
251
252
0
done:
253
0
    cairo_surface_destroy (group_surface);
254
255
0
    return group_pattern;
256
0
}
257
258
static cairo_status_t
259
_cairo_default_context_set_source (void *abstract_cr,
260
           cairo_pattern_t *source)
261
6.87M
{
262
6.87M
    cairo_default_context_t *cr = abstract_cr;
263
264
6.87M
    return _cairo_gstate_set_source (cr->gstate, source);
265
6.87M
}
266
267
static cairo_bool_t
268
_current_source_matches_solid (const cairo_pattern_t *pattern,
269
             double red,
270
             double green,
271
             double blue,
272
             double alpha)
273
7.58M
{
274
7.58M
    cairo_color_t color;
275
276
7.58M
    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
277
0
  return FALSE;
278
279
7.58M
    red   = _cairo_restrict_value (red,   0.0, 1.0);
280
7.58M
    green = _cairo_restrict_value (green, 0.0, 1.0);
281
7.58M
    blue  = _cairo_restrict_value (blue,  0.0, 1.0);
282
7.58M
    alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
283
284
7.58M
    _cairo_color_init_rgba (&color, red, green, blue, alpha);
285
7.58M
    return _cairo_color_equal (&color,
286
7.58M
             &((cairo_solid_pattern_t *) pattern)->color);
287
7.58M
}
288
289
static cairo_status_t
290
_cairo_default_context_set_source_rgba (void *abstract_cr, double red, double green, double blue, double alpha)
291
7.58M
{
292
7.58M
    cairo_default_context_t *cr = abstract_cr;
293
7.58M
    cairo_pattern_t *pattern;
294
7.58M
    cairo_status_t status;
295
296
7.58M
    if (_current_source_matches_solid (cr->gstate->source,
297
7.58M
               red, green, blue, alpha))
298
4.68M
  return CAIRO_STATUS_SUCCESS;
299
300
    /* push the current pattern to the freed lists */
301
2.89M
    _cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
302
303
2.89M
    pattern = cairo_pattern_create_rgba (red, green, blue, alpha);
304
2.89M
    if (unlikely (pattern->status))
305
0
  return pattern->status;
306
307
2.89M
    status = _cairo_default_context_set_source (cr, pattern);
308
2.89M
    cairo_pattern_destroy (pattern);
309
310
2.89M
    return status;
311
2.89M
}
312
313
static cairo_status_t
314
_cairo_default_context_set_source_surface (void *abstract_cr,
315
             cairo_surface_t *surface,
316
             double    x,
317
             double    y)
318
543k
{
319
543k
    cairo_default_context_t *cr = abstract_cr;
320
543k
    cairo_pattern_t *pattern;
321
543k
    cairo_matrix_t matrix;
322
543k
    cairo_status_t status;
323
324
    /* push the current pattern to the freed lists */
325
543k
    _cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
326
327
543k
    pattern = cairo_pattern_create_for_surface (surface);
328
543k
    if (unlikely (pattern->status)) {
329
0
        status = pattern->status;
330
0
        cairo_pattern_destroy (pattern);
331
0
        return status;
332
0
    }
333
334
543k
    cairo_matrix_init_translate (&matrix, -x, -y);
335
543k
    cairo_pattern_set_matrix (pattern, &matrix);
336
337
543k
    status = _cairo_default_context_set_source (cr, pattern);
338
543k
    cairo_pattern_destroy (pattern);
339
340
543k
    return status;
341
543k
}
342
343
static cairo_pattern_t *
344
_cairo_default_context_get_source (void *abstract_cr)
345
20.8k
{
346
20.8k
    cairo_default_context_t *cr = abstract_cr;
347
348
20.8k
    return _cairo_gstate_get_source (cr->gstate);
349
20.8k
}
350
351
static cairo_status_t
352
_cairo_default_context_set_tolerance (void *abstract_cr,
353
              double tolerance)
354
0
{
355
0
    cairo_default_context_t *cr = abstract_cr;
356
357
0
    if (tolerance < CAIRO_TOLERANCE_MINIMUM)
358
0
  tolerance = CAIRO_TOLERANCE_MINIMUM;
359
360
0
    return _cairo_gstate_set_tolerance (cr->gstate, tolerance);
361
0
}
362
363
static cairo_status_t
364
_cairo_default_context_set_operator (void *abstract_cr, cairo_operator_t op)
365
7.62M
{
366
7.62M
    cairo_default_context_t *cr = abstract_cr;
367
368
7.62M
    return _cairo_gstate_set_operator (cr->gstate, op);
369
7.62M
}
370
371
static cairo_status_t
372
_cairo_default_context_set_opacity (void *abstract_cr, double opacity)
373
0
{
374
0
    cairo_default_context_t *cr = abstract_cr;
375
376
0
    return _cairo_gstate_set_opacity (cr->gstate, opacity);
377
0
}
378
379
static cairo_status_t
380
_cairo_default_context_set_antialias (void *abstract_cr,
381
              cairo_antialias_t antialias)
382
7.60M
{
383
7.60M
    cairo_default_context_t *cr = abstract_cr;
384
385
7.60M
    return _cairo_gstate_set_antialias (cr->gstate, antialias);
386
7.60M
}
387
388
static cairo_status_t
389
_cairo_default_context_set_fill_rule (void *abstract_cr,
390
              cairo_fill_rule_t fill_rule)
391
7.60M
{
392
7.60M
    cairo_default_context_t *cr = abstract_cr;
393
394
7.60M
    return _cairo_gstate_set_fill_rule (cr->gstate, fill_rule);
395
7.60M
}
396
397
static cairo_status_t
398
_cairo_default_context_set_line_width (void *abstract_cr,
399
               double line_width)
400
7.66M
{
401
7.66M
    cairo_default_context_t *cr = abstract_cr;
402
403
7.66M
    return _cairo_gstate_set_line_width (cr->gstate, line_width);
404
7.66M
}
405
406
static cairo_status_t
407
_cairo_default_context_set_hairline (void *abstract_cr, cairo_bool_t set_hairline)
408
0
{
409
0
    cairo_default_context_t *cr = abstract_cr;
410
411
0
    return _cairo_gstate_set_hairline (cr->gstate, set_hairline);
412
0
}
413
414
static cairo_status_t
415
_cairo_default_context_set_line_cap (void *abstract_cr,
416
             cairo_line_cap_t line_cap)
417
55.7k
{
418
55.7k
    cairo_default_context_t *cr = abstract_cr;
419
420
55.7k
    return _cairo_gstate_set_line_cap (cr->gstate, line_cap);
421
55.7k
}
422
423
static cairo_status_t
424
_cairo_default_context_set_line_join (void *abstract_cr,
425
              cairo_line_join_t line_join)
426
55.7k
{
427
55.7k
    cairo_default_context_t *cr = abstract_cr;
428
429
55.7k
    return _cairo_gstate_set_line_join (cr->gstate, line_join);
430
55.7k
}
431
432
static cairo_status_t
433
_cairo_default_context_set_dash (void *abstract_cr,
434
         const double *dashes,
435
         int        num_dashes,
436
         double       offset)
437
0
{
438
0
    cairo_default_context_t *cr = abstract_cr;
439
440
0
    return _cairo_gstate_set_dash (cr->gstate,
441
0
           dashes, num_dashes, offset);
442
0
}
443
444
static cairo_status_t
445
_cairo_default_context_set_miter_limit (void *abstract_cr,
446
          double limit)
447
55.7k
{
448
55.7k
    cairo_default_context_t *cr = abstract_cr;
449
450
55.7k
    return _cairo_gstate_set_miter_limit (cr->gstate, limit);
451
55.7k
}
452
453
static cairo_antialias_t
454
_cairo_default_context_get_antialias (void *abstract_cr)
455
0
{
456
0
    cairo_default_context_t *cr = abstract_cr;
457
458
0
    return _cairo_gstate_get_antialias (cr->gstate);
459
0
}
460
461
static void
462
_cairo_default_context_get_dash (void *abstract_cr,
463
         double *dashes,
464
         int *num_dashes,
465
         double *offset)
466
0
{
467
0
    cairo_default_context_t *cr = abstract_cr;
468
469
0
    _cairo_gstate_get_dash (cr->gstate, dashes, num_dashes, offset);
470
0
}
471
472
static cairo_fill_rule_t
473
_cairo_default_context_get_fill_rule (void *abstract_cr)
474
0
{
475
0
    cairo_default_context_t *cr = abstract_cr;
476
477
0
    return _cairo_gstate_get_fill_rule (cr->gstate);
478
0
}
479
480
static double
481
_cairo_default_context_get_line_width (void *abstract_cr)
482
0
{
483
0
    cairo_default_context_t *cr = abstract_cr;
484
485
0
    return _cairo_gstate_get_line_width (cr->gstate);
486
0
}
487
488
static cairo_bool_t
489
_cairo_default_context_get_hairline (void *abstract_cr)
490
0
{
491
0
    cairo_default_context_t *cr = abstract_cr;
492
493
0
    return _cairo_gstate_get_hairline (cr->gstate);
494
0
}
495
496
static cairo_line_cap_t
497
_cairo_default_context_get_line_cap (void *abstract_cr)
498
0
{
499
0
    cairo_default_context_t *cr = abstract_cr;
500
501
0
    return _cairo_gstate_get_line_cap (cr->gstate);
502
0
}
503
504
static cairo_line_join_t
505
_cairo_default_context_get_line_join (void *abstract_cr)
506
0
{
507
0
    cairo_default_context_t *cr = abstract_cr;
508
509
0
    return _cairo_gstate_get_line_join (cr->gstate);
510
0
}
511
512
static double
513
_cairo_default_context_get_miter_limit (void *abstract_cr)
514
0
{
515
0
    cairo_default_context_t *cr = abstract_cr;
516
517
0
    return _cairo_gstate_get_miter_limit (cr->gstate);
518
0
}
519
520
static cairo_operator_t
521
_cairo_default_context_get_operator (void *abstract_cr)
522
0
{
523
0
    cairo_default_context_t *cr = abstract_cr;
524
525
0
    return _cairo_gstate_get_operator (cr->gstate);
526
0
}
527
528
static double
529
_cairo_default_context_get_opacity (void *abstract_cr)
530
0
{
531
0
    cairo_default_context_t *cr = abstract_cr;
532
533
0
    return _cairo_gstate_get_opacity (cr->gstate);
534
0
}
535
536
static double
537
_cairo_default_context_get_tolerance (void *abstract_cr)
538
677
{
539
677
    cairo_default_context_t *cr = abstract_cr;
540
541
677
    return _cairo_gstate_get_tolerance (cr->gstate);
542
677
}
543
544
545
/* Current transformation matrix */
546
547
static cairo_status_t
548
_cairo_default_context_translate (void *abstract_cr,
549
          double tx,
550
          double ty)
551
20.8k
{
552
20.8k
    cairo_default_context_t *cr = abstract_cr;
553
554
20.8k
    return _cairo_gstate_translate (cr->gstate, tx, ty);
555
20.8k
}
556
557
static cairo_status_t
558
_cairo_default_context_scale (void *abstract_cr,
559
            double sx,
560
            double sy)
561
20.8k
{
562
20.8k
    cairo_default_context_t *cr = abstract_cr;
563
564
20.8k
    return _cairo_gstate_scale (cr->gstate, sx, sy);
565
20.8k
}
566
567
static cairo_status_t
568
_cairo_default_context_rotate (void *abstract_cr,
569
             double theta)
570
0
{
571
0
    cairo_default_context_t *cr = abstract_cr;
572
573
0
    return _cairo_gstate_rotate (cr->gstate, theta);
574
0
}
575
576
static cairo_status_t
577
_cairo_default_context_transform (void *abstract_cr,
578
          const cairo_matrix_t *matrix)
579
0
{
580
0
    cairo_default_context_t *cr = abstract_cr;
581
582
0
    return _cairo_gstate_transform (cr->gstate, matrix);
583
0
}
584
585
static cairo_status_t
586
_cairo_default_context_set_matrix (void *abstract_cr,
587
           const cairo_matrix_t *matrix)
588
848k
{
589
848k
    cairo_default_context_t *cr = abstract_cr;
590
591
848k
    return _cairo_gstate_set_matrix (cr->gstate, matrix);
592
848k
}
593
594
static cairo_status_t
595
_cairo_default_context_set_identity_matrix (void *abstract_cr)
596
7.60M
{
597
7.60M
    cairo_default_context_t *cr = abstract_cr;
598
599
7.60M
    _cairo_gstate_identity_matrix (cr->gstate);
600
7.60M
    return CAIRO_STATUS_SUCCESS;
601
7.60M
}
602
603
static void
604
_cairo_default_context_get_matrix (void *abstract_cr,
605
           cairo_matrix_t *matrix)
606
0
{
607
0
    cairo_default_context_t *cr = abstract_cr;
608
609
0
    _cairo_gstate_get_matrix (cr->gstate, matrix);
610
0
}
611
612
static void
613
_cairo_default_context_user_to_device (void *abstract_cr,
614
               double *x,
615
               double *y)
616
0
{
617
0
    cairo_default_context_t *cr = abstract_cr;
618
619
0
    _cairo_gstate_user_to_device (cr->gstate, x, y);
620
0
}
621
622
static void
623
_cairo_default_context_user_to_device_distance (void *abstract_cr, double *dx, double *dy)
624
0
{
625
0
    cairo_default_context_t *cr = abstract_cr;
626
627
0
    _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy);
628
0
}
629
630
static void
631
_cairo_default_context_device_to_user (void *abstract_cr,
632
               double *x,
633
               double *y)
634
0
{
635
0
    cairo_default_context_t *cr = abstract_cr;
636
637
0
    _cairo_gstate_device_to_user (cr->gstate, x, y);
638
0
}
639
640
static void
641
_cairo_default_context_device_to_user_distance (void *abstract_cr,
642
            double *dx,
643
            double *dy)
644
0
{
645
0
    cairo_default_context_t *cr = abstract_cr;
646
647
0
    _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy);
648
0
}
649
650
static void
651
_cairo_default_context_backend_to_user (void *abstract_cr,
652
          double *x,
653
          double *y)
654
5.18k
{
655
5.18k
    cairo_default_context_t *cr = abstract_cr;
656
657
5.18k
    _cairo_gstate_backend_to_user (cr->gstate, x, y);
658
5.18k
}
659
660
static void
661
_cairo_default_context_backend_to_user_distance (void *abstract_cr, double *dx, double *dy)
662
0
{
663
0
    cairo_default_context_t *cr = abstract_cr;
664
665
0
    _cairo_gstate_backend_to_user_distance (cr->gstate, dx, dy);
666
0
}
667
668
static void
669
_cairo_default_context_user_to_backend (void *abstract_cr,
670
          double *x,
671
          double *y)
672
0
{
673
0
    cairo_default_context_t *cr = abstract_cr;
674
675
0
    _cairo_gstate_user_to_backend (cr->gstate, x, y);
676
0
}
677
678
static void
679
_cairo_default_context_user_to_backend_distance (void *abstract_cr,
680
             double *dx,
681
             double *dy)
682
0
{
683
0
    cairo_default_context_t *cr = abstract_cr;
684
685
0
    _cairo_gstate_user_to_backend_distance (cr->gstate, dx, dy);
686
0
}
687
688
/* Path constructor */
689
690
static cairo_status_t
691
_cairo_default_context_new_path (void *abstract_cr)
692
15.4M
{
693
15.4M
    cairo_default_context_t *cr = abstract_cr;
694
695
15.4M
    _cairo_path_fixed_fini (cr->path);
696
15.4M
    _cairo_path_fixed_init (cr->path);
697
698
15.4M
    return CAIRO_STATUS_SUCCESS;
699
15.4M
}
700
701
static cairo_status_t
702
_cairo_default_context_new_sub_path (void *abstract_cr)
703
0
{
704
0
    cairo_default_context_t *cr = abstract_cr;
705
706
0
    _cairo_path_fixed_new_sub_path (cr->path);
707
708
0
    return CAIRO_STATUS_SUCCESS;
709
0
}
710
711
static cairo_status_t
712
_cairo_default_context_move_to (void *abstract_cr, double x, double y)
713
9.50M
{
714
9.50M
    cairo_default_context_t *cr = abstract_cr;
715
9.50M
    cairo_fixed_t x_fixed, y_fixed;
716
717
9.50M
    _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
718
9.50M
    x_fixed = _cairo_fixed_from_double (x);
719
9.50M
    y_fixed = _cairo_fixed_from_double (y);
720
721
9.50M
    return _cairo_path_fixed_move_to (cr->path, x_fixed, y_fixed);
722
9.50M
}
723
724
static cairo_status_t
725
_cairo_default_context_line_to (void *abstract_cr, double x, double y)
726
123M
{
727
123M
    cairo_default_context_t *cr = abstract_cr;
728
123M
    cairo_fixed_t x_fixed, y_fixed;
729
730
123M
    _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
731
123M
    x_fixed = _cairo_fixed_from_double (x);
732
123M
    y_fixed = _cairo_fixed_from_double (y);
733
734
123M
    return _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
735
123M
}
736
737
static cairo_status_t
738
_cairo_default_context_curve_to (void *abstract_cr,
739
         double x1, double y1,
740
         double x2, double y2,
741
         double x3, double y3)
742
69.6k
{
743
69.6k
    cairo_default_context_t *cr = abstract_cr;
744
69.6k
    cairo_fixed_t x1_fixed, y1_fixed;
745
69.6k
    cairo_fixed_t x2_fixed, y2_fixed;
746
69.6k
    cairo_fixed_t x3_fixed, y3_fixed;
747
748
69.6k
    _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1);
749
69.6k
    _cairo_gstate_user_to_backend (cr->gstate, &x2, &y2);
750
69.6k
    _cairo_gstate_user_to_backend (cr->gstate, &x3, &y3);
751
752
69.6k
    x1_fixed = _cairo_fixed_from_double (x1);
753
69.6k
    y1_fixed = _cairo_fixed_from_double (y1);
754
755
69.6k
    x2_fixed = _cairo_fixed_from_double (x2);
756
69.6k
    y2_fixed = _cairo_fixed_from_double (y2);
757
758
69.6k
    x3_fixed = _cairo_fixed_from_double (x3);
759
69.6k
    y3_fixed = _cairo_fixed_from_double (y3);
760
761
69.6k
    return _cairo_path_fixed_curve_to (cr->path,
762
69.6k
               x1_fixed, y1_fixed,
763
69.6k
               x2_fixed, y2_fixed,
764
69.6k
               x3_fixed, y3_fixed);
765
69.6k
}
766
767
static cairo_status_t
768
_cairo_default_context_arc (void *abstract_cr,
769
          double xc, double yc, double radius,
770
          double angle1, double angle2,
771
          cairo_bool_t forward)
772
0
{
773
0
    cairo_default_context_t *cr = abstract_cr;
774
0
    cairo_status_t status;
775
776
    /* Do nothing, successfully, if radius is <= 0 */
777
0
    if (radius <= 0.0) {
778
0
  cairo_fixed_t x_fixed, y_fixed;
779
780
0
  _cairo_gstate_user_to_backend (cr->gstate, &xc, &yc);
781
0
  x_fixed = _cairo_fixed_from_double (xc);
782
0
  y_fixed = _cairo_fixed_from_double (yc);
783
0
  status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
784
0
  if (unlikely (status))
785
0
      return status;
786
787
0
  status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
788
0
  if (unlikely (status))
789
0
      return status;
790
791
0
  return CAIRO_STATUS_SUCCESS;
792
0
    }
793
794
0
    status = _cairo_default_context_line_to (cr,
795
0
               xc + radius * cos (angle1),
796
0
               yc + radius * sin (angle1));
797
798
0
    if (unlikely (status))
799
0
  return status;
800
801
0
    if (forward)
802
0
  _cairo_arc_path (&cr->base, xc, yc, radius, angle1, angle2);
803
0
    else
804
0
  _cairo_arc_path_negative (&cr->base, xc, yc, radius, angle1, angle2);
805
806
0
    return CAIRO_STATUS_SUCCESS; /* any error will have already been set on cr */
807
0
}
808
809
static cairo_status_t
810
_cairo_default_context_rel_move_to (void *abstract_cr, double dx, double dy)
811
0
{
812
0
    cairo_default_context_t *cr = abstract_cr;
813
0
    cairo_fixed_t dx_fixed, dy_fixed;
814
815
0
    _cairo_gstate_user_to_backend_distance (cr->gstate, &dx, &dy);
816
817
0
    dx_fixed = _cairo_fixed_from_double (dx);
818
0
    dy_fixed = _cairo_fixed_from_double (dy);
819
820
0
    return _cairo_path_fixed_rel_move_to (cr->path, dx_fixed, dy_fixed);
821
0
}
822
823
static cairo_status_t
824
_cairo_default_context_rel_line_to (void *abstract_cr, double dx, double dy)
825
8.10M
{
826
8.10M
    cairo_default_context_t *cr = abstract_cr;
827
8.10M
    cairo_fixed_t dx_fixed, dy_fixed;
828
829
8.10M
    _cairo_gstate_user_to_backend_distance (cr->gstate, &dx, &dy);
830
831
8.10M
    dx_fixed = _cairo_fixed_from_double (dx);
832
8.10M
    dy_fixed = _cairo_fixed_from_double (dy);
833
834
8.10M
    return _cairo_path_fixed_rel_line_to (cr->path, dx_fixed, dy_fixed);
835
8.10M
}
836
837
838
static cairo_status_t
839
_cairo_default_context_rel_curve_to (void *abstract_cr,
840
             double dx1, double dy1,
841
             double dx2, double dy2,
842
             double dx3, double dy3)
843
0
{
844
0
    cairo_default_context_t *cr = abstract_cr;
845
0
    cairo_fixed_t dx1_fixed, dy1_fixed;
846
0
    cairo_fixed_t dx2_fixed, dy2_fixed;
847
0
    cairo_fixed_t dx3_fixed, dy3_fixed;
848
849
0
    _cairo_gstate_user_to_backend_distance (cr->gstate, &dx1, &dy1);
850
0
    _cairo_gstate_user_to_backend_distance (cr->gstate, &dx2, &dy2);
851
0
    _cairo_gstate_user_to_backend_distance (cr->gstate, &dx3, &dy3);
852
853
0
    dx1_fixed = _cairo_fixed_from_double (dx1);
854
0
    dy1_fixed = _cairo_fixed_from_double (dy1);
855
856
0
    dx2_fixed = _cairo_fixed_from_double (dx2);
857
0
    dy2_fixed = _cairo_fixed_from_double (dy2);
858
859
0
    dx3_fixed = _cairo_fixed_from_double (dx3);
860
0
    dy3_fixed = _cairo_fixed_from_double (dy3);
861
862
0
    return _cairo_path_fixed_rel_curve_to (cr->path,
863
0
             dx1_fixed, dy1_fixed,
864
0
             dx2_fixed, dy2_fixed,
865
0
             dx3_fixed, dy3_fixed);
866
0
}
867
868
static cairo_status_t
869
_cairo_default_context_close_path (void *abstract_cr)
870
3.16M
{
871
3.16M
    cairo_default_context_t *cr = abstract_cr;
872
873
3.16M
    return _cairo_path_fixed_close_path (cr->path);
874
3.16M
}
875
876
static cairo_status_t
877
_cairo_default_context_rectangle (void *abstract_cr,
878
          double x, double y,
879
          double width, double height)
880
2.70M
{
881
2.70M
    cairo_default_context_t *cr = abstract_cr;
882
2.70M
    cairo_status_t status;
883
884
2.70M
    status = _cairo_default_context_move_to (cr, x, y);
885
2.70M
    if (unlikely (status))
886
0
  return status;
887
888
2.70M
    status = _cairo_default_context_rel_line_to (cr, width, 0);
889
2.70M
    if (unlikely (status))
890
0
  return status;
891
892
2.70M
    status = _cairo_default_context_rel_line_to (cr, 0, height);
893
2.70M
    if (unlikely (status))
894
0
  return status;
895
896
2.70M
    status = _cairo_default_context_rel_line_to (cr, -width, 0);
897
2.70M
    if (unlikely (status))
898
0
  return status;
899
900
2.70M
    return _cairo_default_context_close_path (cr);
901
2.70M
}
902
903
static void
904
_cairo_default_context_path_extents (void *abstract_cr,
905
             double *x1,
906
             double *y1,
907
             double *x2,
908
             double *y2)
909
7.58M
{
910
7.58M
    cairo_default_context_t *cr = abstract_cr;
911
912
7.58M
    _cairo_gstate_path_extents (cr->gstate,
913
7.58M
        cr->path,
914
7.58M
        x1, y1, x2, y2);
915
7.58M
}
916
917
static cairo_bool_t
918
_cairo_default_context_has_current_point (void *abstract_cr)
919
0
{
920
0
    cairo_default_context_t *cr = abstract_cr;
921
922
0
    return cr->path->has_current_point;
923
0
}
924
925
static cairo_bool_t
926
_cairo_default_context_get_current_point (void *abstract_cr,
927
            double *x,
928
            double *y)
929
0
{
930
0
    cairo_default_context_t *cr = abstract_cr;
931
0
    cairo_fixed_t x_fixed, y_fixed;
932
933
0
    if (_cairo_path_fixed_get_current_point (cr->path, &x_fixed, &y_fixed))
934
0
    {
935
0
  *x = _cairo_fixed_to_double (x_fixed);
936
0
  *y = _cairo_fixed_to_double (y_fixed);
937
0
  _cairo_gstate_backend_to_user (cr->gstate, x, y);
938
939
0
  return TRUE;
940
0
    }
941
0
    else
942
0
    {
943
0
  return FALSE;
944
0
    }
945
0
}
946
947
static cairo_path_t *
948
_cairo_default_context_copy_path (void *abstract_cr)
949
677
{
950
677
    cairo_default_context_t *cr = abstract_cr;
951
952
677
    return _cairo_path_create (cr->path, &cr->base);
953
677
}
954
955
static cairo_path_t *
956
_cairo_default_context_copy_path_flat (void *abstract_cr)
957
0
{
958
0
    cairo_default_context_t *cr = abstract_cr;
959
960
0
    return _cairo_path_create_flat (cr->path, &cr->base);
961
0
}
962
963
static cairo_status_t
964
_cairo_default_context_append_path (void *abstract_cr,
965
            const cairo_path_t *path)
966
677
{
967
677
    cairo_default_context_t *cr = abstract_cr;
968
969
677
    return _cairo_path_append_to_context (path, &cr->base);
970
677
}
971
972
static cairo_status_t
973
_cairo_default_context_paint (void *abstract_cr)
974
543k
{
975
543k
    cairo_default_context_t *cr = abstract_cr;
976
977
543k
    return _cairo_gstate_paint (cr->gstate);
978
543k
}
979
980
static cairo_status_t
981
_cairo_default_context_paint_with_alpha (void *abstract_cr,
982
           double alpha)
983
0
{
984
0
    cairo_default_context_t *cr = abstract_cr;
985
0
    cairo_solid_pattern_t pattern;
986
0
    cairo_status_t status;
987
0
    cairo_color_t color;
988
989
0
    if (CAIRO_ALPHA_IS_OPAQUE (alpha))
990
0
  return _cairo_gstate_paint (cr->gstate);
991
992
0
    if (CAIRO_ALPHA_IS_ZERO (alpha) &&
993
0
        _cairo_operator_bounded_by_mask (cr->gstate->op)) {
994
0
  return CAIRO_STATUS_SUCCESS;
995
0
    }
996
997
0
    _cairo_color_init_rgba (&color, 0., 0., 0., alpha);
998
0
    _cairo_pattern_init_solid (&pattern, &color);
999
1000
0
    status = _cairo_gstate_mask (cr->gstate, &pattern.base);
1001
0
    _cairo_pattern_fini (&pattern.base);
1002
1003
0
    return status;
1004
0
}
1005
1006
static cairo_status_t
1007
_cairo_default_context_mask (void *abstract_cr,
1008
           cairo_pattern_t *mask)
1009
4
{
1010
4
    cairo_default_context_t *cr = abstract_cr;
1011
1012
4
    return _cairo_gstate_mask (cr->gstate, mask);
1013
4
}
1014
1015
static cairo_status_t
1016
_cairo_default_context_stroke_preserve (void *abstract_cr)
1017
0
{
1018
0
    cairo_default_context_t *cr = abstract_cr;
1019
1020
0
    return _cairo_gstate_stroke (cr->gstate, cr->path);
1021
0
}
1022
1023
static cairo_status_t
1024
_cairo_default_context_stroke (void *abstract_cr)
1025
835k
{
1026
835k
    cairo_default_context_t *cr = abstract_cr;
1027
835k
    cairo_status_t status;
1028
1029
835k
    status = _cairo_gstate_stroke (cr->gstate, cr->path);
1030
835k
    if (unlikely (status))
1031
0
  return status;
1032
1033
835k
    return _cairo_default_context_new_path (cr);
1034
835k
}
1035
1036
static cairo_status_t
1037
_cairo_default_context_in_stroke (void *abstract_cr,
1038
          double x, double y,
1039
          cairo_bool_t *inside)
1040
0
{
1041
0
    cairo_default_context_t *cr = abstract_cr;
1042
1043
0
    return _cairo_gstate_in_stroke (cr->gstate,
1044
0
            cr->path,
1045
0
            x, y,
1046
0
            inside);
1047
0
}
1048
1049
static cairo_status_t
1050
_cairo_default_context_stroke_extents (void *abstract_cr,
1051
               double *x1, double *y1, double *x2, double *y2)
1052
0
{
1053
0
    cairo_default_context_t *cr = abstract_cr;
1054
1055
0
    return _cairo_gstate_stroke_extents (cr->gstate,
1056
0
           cr->path,
1057
0
           x1, y1, x2, y2);
1058
0
}
1059
1060
static cairo_status_t
1061
_cairo_default_context_fill_preserve (void *abstract_cr)
1062
6.37k
{
1063
6.37k
    cairo_default_context_t *cr = abstract_cr;
1064
1065
6.37k
    return _cairo_gstate_fill (cr->gstate, cr->path);
1066
6.37k
}
1067
1068
static cairo_status_t
1069
_cairo_default_context_fill (void *abstract_cr)
1070
6.72M
{
1071
6.72M
    cairo_default_context_t *cr = abstract_cr;
1072
6.72M
    cairo_status_t status;
1073
1074
6.72M
    status = _cairo_gstate_fill (cr->gstate, cr->path);
1075
6.72M
    if (unlikely (status))
1076
0
  return status;
1077
1078
6.72M
    return _cairo_default_context_new_path (cr);
1079
6.72M
}
1080
1081
static cairo_status_t
1082
_cairo_default_context_in_fill (void *abstract_cr,
1083
        double x, double y,
1084
        cairo_bool_t *inside)
1085
0
{
1086
0
    cairo_default_context_t *cr = abstract_cr;
1087
1088
0
    *inside = _cairo_gstate_in_fill (cr->gstate,
1089
0
             cr->path,
1090
0
             x, y);
1091
0
    return CAIRO_STATUS_SUCCESS;
1092
0
}
1093
1094
static cairo_status_t
1095
_cairo_default_context_fill_extents (void *abstract_cr,
1096
             double *x1, double *y1, double *x2, double *y2)
1097
0
{
1098
0
    cairo_default_context_t *cr = abstract_cr;
1099
1100
0
    return _cairo_gstate_fill_extents (cr->gstate,
1101
0
               cr->path,
1102
0
               x1, y1, x2, y2);
1103
0
}
1104
1105
static cairo_status_t
1106
_cairo_default_context_clip_preserve (void *abstract_cr)
1107
0
{
1108
0
    cairo_default_context_t *cr = abstract_cr;
1109
1110
0
    return _cairo_gstate_clip (cr->gstate, cr->path);
1111
0
}
1112
1113
static cairo_status_t
1114
_cairo_default_context_clip (void *abstract_cr)
1115
267k
{
1116
267k
    cairo_default_context_t *cr = abstract_cr;
1117
267k
    cairo_status_t status;
1118
1119
267k
    status = _cairo_gstate_clip (cr->gstate, cr->path);
1120
267k
    if (unlikely (status))
1121
0
  return status;
1122
1123
267k
    return _cairo_default_context_new_path (cr);
1124
267k
}
1125
1126
static cairo_status_t
1127
_cairo_default_context_in_clip (void *abstract_cr,
1128
        double x, double y,
1129
        cairo_bool_t *inside)
1130
0
{
1131
0
    cairo_default_context_t *cr = abstract_cr;
1132
1133
0
    *inside = _cairo_gstate_in_clip (cr->gstate, x, y);
1134
0
    return CAIRO_STATUS_SUCCESS;
1135
0
}
1136
1137
static cairo_status_t
1138
_cairo_default_context_reset_clip (void *abstract_cr)
1139
1
{
1140
1
    cairo_default_context_t *cr = abstract_cr;
1141
1142
1
    return _cairo_gstate_reset_clip (cr->gstate);
1143
1
}
1144
1145
static cairo_status_t
1146
_cairo_default_context_clip_extents (void *abstract_cr,
1147
             double *x1, double *y1, double *x2, double *y2)
1148
7.58M
{
1149
7.58M
    cairo_default_context_t *cr = abstract_cr;
1150
1151
7.58M
    if (! _cairo_gstate_clip_extents (cr->gstate, x1, y1, x2, y2)) {
1152
0
  *x1 = -INFINITY;
1153
0
  *y1 = -INFINITY;
1154
0
  *x2 = +INFINITY;
1155
0
  *y2 = +INFINITY;
1156
0
    }
1157
1158
7.58M
    return CAIRO_STATUS_SUCCESS;
1159
7.58M
}
1160
1161
static cairo_rectangle_list_t *
1162
_cairo_default_context_copy_clip_rectangle_list (void *abstract_cr)
1163
0
{
1164
0
    cairo_default_context_t *cr = abstract_cr;
1165
1166
0
    return _cairo_gstate_copy_clip_rectangle_list (cr->gstate);
1167
0
}
1168
1169
static cairo_status_t
1170
_cairo_default_context_copy_page (void *abstract_cr)
1171
0
{
1172
0
    cairo_default_context_t *cr = abstract_cr;
1173
1174
0
    return _cairo_gstate_copy_page (cr->gstate);
1175
0
}
1176
1177
static cairo_status_t
1178
_cairo_default_context_tag_begin (void *abstract_cr,
1179
          const char *tag_name, const char *attributes)
1180
0
{
1181
0
    cairo_default_context_t *cr = abstract_cr;
1182
1183
0
    return _cairo_gstate_tag_begin (cr->gstate, tag_name, attributes);
1184
0
}
1185
1186
static cairo_status_t
1187
_cairo_default_context_tag_end (void *abstract_cr,
1188
        const char *tag_name)
1189
0
{
1190
0
    cairo_default_context_t *cr = abstract_cr;
1191
1192
0
    return _cairo_gstate_tag_end (cr->gstate, tag_name);
1193
0
}
1194
1195
static cairo_status_t
1196
_cairo_default_context_show_page (void *abstract_cr)
1197
0
{
1198
0
    cairo_default_context_t *cr = abstract_cr;
1199
1200
0
    return _cairo_gstate_show_page (cr->gstate);
1201
0
}
1202
1203
static cairo_status_t
1204
_cairo_default_context_set_font_face (void *abstract_cr,
1205
              cairo_font_face_t *font_face)
1206
2.55M
{
1207
2.55M
    cairo_default_context_t *cr = abstract_cr;
1208
1209
2.55M
    return _cairo_gstate_set_font_face (cr->gstate, font_face);
1210
2.55M
}
1211
1212
static cairo_font_face_t *
1213
_cairo_default_context_get_font_face (void *abstract_cr)
1214
0
{
1215
0
    cairo_default_context_t *cr = abstract_cr;
1216
0
    cairo_font_face_t *font_face;
1217
0
    cairo_status_t status;
1218
1219
0
    status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
1220
0
    if (unlikely (status)) {
1221
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1222
0
  return (cairo_font_face_t *) &_cairo_font_face_nil;
1223
0
    }
1224
1225
0
    return font_face;
1226
0
}
1227
1228
static cairo_status_t
1229
_cairo_default_context_font_extents (void *abstract_cr,
1230
             cairo_font_extents_t *extents)
1231
0
{
1232
0
    cairo_default_context_t *cr = abstract_cr;
1233
1234
0
    return _cairo_gstate_get_font_extents (cr->gstate, extents);
1235
0
}
1236
1237
static cairo_status_t
1238
_cairo_default_context_set_font_size (void *abstract_cr,
1239
              double size)
1240
2.55M
{
1241
2.55M
    cairo_default_context_t *cr = abstract_cr;
1242
1243
2.55M
    return _cairo_gstate_set_font_size (cr->gstate, size);
1244
2.55M
}
1245
1246
static cairo_status_t
1247
_cairo_default_context_set_font_matrix (void *abstract_cr,
1248
          const cairo_matrix_t *matrix)
1249
2.55M
{
1250
2.55M
    cairo_default_context_t *cr = abstract_cr;
1251
1252
2.55M
    return _cairo_gstate_set_font_matrix (cr->gstate, matrix);
1253
2.55M
}
1254
1255
static void
1256
_cairo_default_context_get_font_matrix (void *abstract_cr,
1257
          cairo_matrix_t *matrix)
1258
0
{
1259
0
    cairo_default_context_t *cr = abstract_cr;
1260
1261
0
    _cairo_gstate_get_font_matrix (cr->gstate, matrix);
1262
0
}
1263
1264
static cairo_status_t
1265
_cairo_default_context_set_font_options (void *abstract_cr,
1266
           const cairo_font_options_t *options)
1267
23.4k
{
1268
23.4k
    cairo_default_context_t *cr = abstract_cr;
1269
1270
23.4k
    _cairo_gstate_set_font_options (cr->gstate, options);
1271
23.4k
    return CAIRO_STATUS_SUCCESS;
1272
23.4k
}
1273
1274
static void
1275
_cairo_default_context_get_font_options (void *abstract_cr,
1276
           cairo_font_options_t *options)
1277
0
{
1278
0
    cairo_default_context_t *cr = abstract_cr;
1279
1280
0
    _cairo_gstate_get_font_options (cr->gstate, options);
1281
0
}
1282
1283
static cairo_status_t
1284
_cairo_default_context_set_scaled_font (void *abstract_cr,
1285
          cairo_scaled_font_t *scaled_font)
1286
0
{
1287
0
    cairo_default_context_t *cr = abstract_cr;
1288
0
    cairo_bool_t was_previous;
1289
0
    cairo_status_t status;
1290
1291
0
    if (scaled_font == cr->gstate->scaled_font)
1292
0
  return CAIRO_STATUS_SUCCESS;
1293
1294
0
    was_previous = scaled_font == cr->gstate->previous_scaled_font;
1295
1296
0
    status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face);
1297
0
    if (unlikely (status))
1298
0
  return status;
1299
1300
0
    status = _cairo_gstate_set_font_matrix (cr->gstate, &scaled_font->font_matrix);
1301
0
    if (unlikely (status))
1302
0
  return status;
1303
1304
0
    _cairo_gstate_set_font_options (cr->gstate, &scaled_font->options);
1305
1306
0
    if (was_previous)
1307
0
  cr->gstate->scaled_font = cairo_scaled_font_reference (scaled_font);
1308
1309
0
    return CAIRO_STATUS_SUCCESS;
1310
0
}
1311
1312
static cairo_scaled_font_t *
1313
_cairo_default_context_get_scaled_font (void *abstract_cr)
1314
0
{
1315
0
    cairo_default_context_t *cr = abstract_cr;
1316
0
    cairo_scaled_font_t *scaled_font;
1317
0
    cairo_status_t status;
1318
1319
0
    status = _cairo_gstate_get_scaled_font (cr->gstate, &scaled_font);
1320
0
    if (unlikely (status))
1321
0
  return _cairo_scaled_font_create_in_error (status);
1322
1323
0
    return scaled_font;
1324
0
}
1325
1326
static cairo_status_t
1327
_cairo_default_context_glyphs (void *abstract_cr,
1328
             const cairo_glyph_t *glyphs,
1329
             int num_glyphs,
1330
             cairo_glyph_text_info_t *info)
1331
2.55M
{
1332
2.55M
    cairo_default_context_t *cr = abstract_cr;
1333
1334
2.55M
    return _cairo_gstate_show_text_glyphs (cr->gstate, glyphs, num_glyphs, info);
1335
2.55M
}
1336
1337
static cairo_status_t
1338
_cairo_default_context_glyph_path (void *abstract_cr,
1339
           const cairo_glyph_t *glyphs,
1340
           int num_glyphs)
1341
0
{
1342
0
    cairo_default_context_t *cr = abstract_cr;
1343
1344
0
    return _cairo_gstate_glyph_path (cr->gstate,
1345
0
             glyphs, num_glyphs,
1346
0
             cr->path);
1347
0
}
1348
1349
static cairo_status_t
1350
_cairo_default_context_glyph_extents (void                *abstract_cr,
1351
              const cairo_glyph_t    *glyphs,
1352
              int                    num_glyphs,
1353
              cairo_text_extents_t   *extents)
1354
0
{
1355
0
    cairo_default_context_t *cr = abstract_cr;
1356
1357
0
    return _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents);
1358
0
}
1359
1360
static const cairo_backend_t _cairo_default_context_backend = {
1361
    CAIRO_TYPE_DEFAULT,
1362
    _cairo_default_context_destroy,
1363
1364
    _cairo_default_context_get_original_target,
1365
    _cairo_default_context_get_current_target,
1366
1367
    _cairo_default_context_save,
1368
    _cairo_default_context_restore,
1369
1370
    _cairo_default_context_push_group,
1371
    _cairo_default_context_pop_group,
1372
1373
    _cairo_default_context_set_source_rgba,
1374
    _cairo_default_context_set_source_surface,
1375
    _cairo_default_context_set_source,
1376
    _cairo_default_context_get_source,
1377
1378
    _cairo_default_context_set_antialias,
1379
    _cairo_default_context_set_dash,
1380
    _cairo_default_context_set_fill_rule,
1381
    _cairo_default_context_set_line_cap,
1382
    _cairo_default_context_set_line_join,
1383
    _cairo_default_context_set_line_width,
1384
    _cairo_default_context_set_hairline,
1385
    _cairo_default_context_set_miter_limit,
1386
    _cairo_default_context_set_opacity,
1387
    _cairo_default_context_set_operator,
1388
    _cairo_default_context_set_tolerance,
1389
    _cairo_default_context_get_antialias,
1390
    _cairo_default_context_get_dash,
1391
    _cairo_default_context_get_fill_rule,
1392
    _cairo_default_context_get_line_cap,
1393
    _cairo_default_context_get_line_join,
1394
    _cairo_default_context_get_line_width,
1395
    _cairo_default_context_get_hairline,
1396
    _cairo_default_context_get_miter_limit,
1397
    _cairo_default_context_get_opacity,
1398
    _cairo_default_context_get_operator,
1399
    _cairo_default_context_get_tolerance,
1400
1401
    _cairo_default_context_translate,
1402
    _cairo_default_context_scale,
1403
    _cairo_default_context_rotate,
1404
    _cairo_default_context_transform,
1405
    _cairo_default_context_set_matrix,
1406
    _cairo_default_context_set_identity_matrix,
1407
    _cairo_default_context_get_matrix,
1408
1409
    _cairo_default_context_user_to_device,
1410
    _cairo_default_context_user_to_device_distance,
1411
    _cairo_default_context_device_to_user,
1412
    _cairo_default_context_device_to_user_distance,
1413
1414
    _cairo_default_context_user_to_backend,
1415
    _cairo_default_context_user_to_backend_distance,
1416
    _cairo_default_context_backend_to_user,
1417
    _cairo_default_context_backend_to_user_distance,
1418
1419
    _cairo_default_context_new_path,
1420
    _cairo_default_context_new_sub_path,
1421
    _cairo_default_context_move_to,
1422
    _cairo_default_context_rel_move_to,
1423
    _cairo_default_context_line_to,
1424
    _cairo_default_context_rel_line_to,
1425
    _cairo_default_context_curve_to,
1426
    _cairo_default_context_rel_curve_to,
1427
    NULL, /* arc-to */
1428
    NULL, /* rel-arc-to */
1429
    _cairo_default_context_close_path,
1430
    _cairo_default_context_arc,
1431
    _cairo_default_context_rectangle,
1432
    _cairo_default_context_path_extents,
1433
    _cairo_default_context_has_current_point,
1434
    _cairo_default_context_get_current_point,
1435
    _cairo_default_context_copy_path,
1436
    _cairo_default_context_copy_path_flat,
1437
    _cairo_default_context_append_path,
1438
1439
    NULL, /* stroke-to-path */
1440
1441
    _cairo_default_context_clip,
1442
    _cairo_default_context_clip_preserve,
1443
    _cairo_default_context_in_clip,
1444
    _cairo_default_context_clip_extents,
1445
    _cairo_default_context_reset_clip,
1446
    _cairo_default_context_copy_clip_rectangle_list,
1447
1448
    _cairo_default_context_paint,
1449
    _cairo_default_context_paint_with_alpha,
1450
    _cairo_default_context_mask,
1451
1452
    _cairo_default_context_stroke,
1453
    _cairo_default_context_stroke_preserve,
1454
    _cairo_default_context_in_stroke,
1455
    _cairo_default_context_stroke_extents,
1456
1457
    _cairo_default_context_fill,
1458
    _cairo_default_context_fill_preserve,
1459
    _cairo_default_context_in_fill,
1460
    _cairo_default_context_fill_extents,
1461
1462
    _cairo_default_context_set_font_face,
1463
    _cairo_default_context_get_font_face,
1464
    _cairo_default_context_set_font_size,
1465
    _cairo_default_context_set_font_matrix,
1466
    _cairo_default_context_get_font_matrix,
1467
    _cairo_default_context_set_font_options,
1468
    _cairo_default_context_get_font_options,
1469
    _cairo_default_context_set_scaled_font,
1470
    _cairo_default_context_get_scaled_font,
1471
    _cairo_default_context_font_extents,
1472
1473
    _cairo_default_context_glyphs,
1474
    _cairo_default_context_glyph_path,
1475
    _cairo_default_context_glyph_extents,
1476
1477
    _cairo_default_context_copy_page,
1478
    _cairo_default_context_show_page,
1479
1480
    _cairo_default_context_tag_begin,
1481
    _cairo_default_context_tag_end,
1482
};
1483
1484
cairo_status_t
1485
_cairo_default_context_init (cairo_default_context_t *cr, void *target)
1486
8.13M
{
1487
8.13M
    _cairo_init (&cr->base, &_cairo_default_context_backend);
1488
8.13M
    _cairo_path_fixed_init (cr->path);
1489
1490
8.13M
    cr->gstate = &cr->gstate_tail[0];
1491
8.13M
    cr->gstate_freelist = &cr->gstate_tail[1];
1492
8.13M
    cr->gstate_tail[1].next = NULL;
1493
1494
8.13M
    return _cairo_gstate_init (cr->gstate, target);
1495
8.13M
}
1496
1497
cairo_t *
1498
_cairo_default_context_create (void *target)
1499
8.13M
{
1500
8.13M
    cairo_default_context_t *cr;
1501
8.13M
    cairo_status_t status;
1502
1503
8.13M
    cr = _freed_pool_get (&context_pool);
1504
8.13M
    if (unlikely (cr == NULL)) {
1505
65
  cr = _cairo_malloc (sizeof (cairo_default_context_t));
1506
65
  if (unlikely (cr == NULL))
1507
0
      return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1508
65
    }
1509
1510
8.13M
    status = _cairo_default_context_init (cr, target);
1511
8.13M
    if (unlikely (status)) {
1512
0
  _freed_pool_put (&context_pool, cr);
1513
0
  return _cairo_create_in_error (status);
1514
0
    }
1515
1516
8.13M
    return &cr->base;
1517
8.13M
}