Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/cairo/src/cairo-default-context.c
Line
Count
Source
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
14.5M
{
70
14.5M
    while (cr->gstate != &cr->gstate_tail[0]) {
71
35
  if (_cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist))
72
0
      break;
73
35
    }
74
75
14.5M
    _cairo_gstate_fini (cr->gstate);
76
14.5M
    cr->gstate_freelist = cr->gstate_freelist->next; /* skip over tail[1] */
77
14.5M
    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
14.5M
    _cairo_path_fixed_fini (cr->path);
84
85
14.5M
    _cairo_fini (&cr->base);
86
14.5M
}
87
88
static void
89
_cairo_default_context_destroy (void *abstract_cr)
90
14.5M
{
91
14.5M
    cairo_default_context_t *cr = abstract_cr;
92
93
14.5M
    _cairo_default_context_fini (cr);
94
95
    /* mark the context as invalid to protect against misuse */
96
14.5M
    cr->base.status = CAIRO_STATUS_NULL_POINTER;
97
14.5M
    _freed_pool_put (&context_pool, cr);
98
14.5M
}
99
100
static cairo_surface_t *
101
_cairo_default_context_get_original_target (void *abstract_cr)
102
13.8M
{
103
13.8M
    cairo_default_context_t *cr = abstract_cr;
104
105
13.8M
    return _cairo_gstate_get_original_target (cr->gstate);
106
13.8M
}
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
18.3k
{
119
18.3k
    cairo_default_context_t *cr = abstract_cr;
120
121
18.3k
    return _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist);
122
18.3k
}
123
124
static cairo_status_t
125
_cairo_default_context_restore (void *abstract_cr)
126
18.3k
{
127
18.3k
    cairo_default_context_t *cr = abstract_cr;
128
129
18.3k
    if (unlikely (_cairo_gstate_is_group (cr->gstate)))
130
0
  return _cairo_error (CAIRO_STATUS_INVALID_RESTORE);
131
132
18.3k
    return _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
133
18.3k
}
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
12.1M
{
262
12.1M
    cairo_default_context_t *cr = abstract_cr;
263
264
12.1M
    return _cairo_gstate_set_source (cr->gstate, source);
265
12.1M
}
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
14.0M
{
274
14.0M
    cairo_color_t color;
275
276
14.0M
    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
277
0
  return FALSE;
278
279
14.0M
    red   = _cairo_restrict_value (red,   0.0, 1.0);
280
14.0M
    green = _cairo_restrict_value (green, 0.0, 1.0);
281
14.0M
    blue  = _cairo_restrict_value (blue,  0.0, 1.0);
282
14.0M
    alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
283
284
14.0M
    _cairo_color_init_rgba (&color, red, green, blue, alpha);
285
14.0M
    return _cairo_color_equal (&color,
286
14.0M
             &((cairo_solid_pattern_t *) pattern)->color);
287
14.0M
}
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
14.0M
{
292
14.0M
    cairo_default_context_t *cr = abstract_cr;
293
14.0M
    cairo_pattern_t *pattern;
294
14.0M
    cairo_status_t status;
295
296
14.0M
    if (_current_source_matches_solid (cr->gstate->source,
297
14.0M
               red, green, blue, alpha))
298
8.50M
  return CAIRO_STATUS_SUCCESS;
299
300
    /* push the current pattern to the freed lists */
301
5.55M
    _cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
302
303
5.55M
    pattern = cairo_pattern_create_rgba (red, green, blue, alpha);
304
5.55M
    if (unlikely (pattern->status))
305
0
  return pattern->status;
306
307
5.55M
    status = _cairo_default_context_set_source (cr, pattern);
308
5.55M
    cairo_pattern_destroy (pattern);
309
310
5.55M
    return status;
311
5.55M
}
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
516k
{
319
516k
    cairo_default_context_t *cr = abstract_cr;
320
516k
    cairo_pattern_t *pattern;
321
516k
    cairo_matrix_t matrix;
322
516k
    cairo_status_t status;
323
324
    /* push the current pattern to the freed lists */
325
516k
    _cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
326
327
516k
    pattern = cairo_pattern_create_for_surface (surface);
328
516k
    if (unlikely (pattern->status)) {
329
0
        status = pattern->status;
330
0
        cairo_pattern_destroy (pattern);
331
0
        return status;
332
0
    }
333
334
516k
    cairo_matrix_init_translate (&matrix, -x, -y);
335
516k
    cairo_pattern_set_matrix (pattern, &matrix);
336
337
516k
    status = _cairo_default_context_set_source (cr, pattern);
338
516k
    cairo_pattern_destroy (pattern);
339
340
516k
    return status;
341
516k
}
342
343
static cairo_pattern_t *
344
_cairo_default_context_get_source (void *abstract_cr)
345
19.2k
{
346
19.2k
    cairo_default_context_t *cr = abstract_cr;
347
348
19.2k
    return _cairo_gstate_get_source (cr->gstate);
349
19.2k
}
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
24.7M
{
366
24.7M
    cairo_default_context_t *cr = abstract_cr;
367
368
24.7M
    return _cairo_gstate_set_operator (cr->gstate, op);
369
24.7M
}
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
12.6M
{
383
12.6M
    cairo_default_context_t *cr = abstract_cr;
384
385
12.6M
    return _cairo_gstate_set_antialias (cr->gstate, antialias);
386
12.6M
}
387
388
static cairo_status_t
389
_cairo_default_context_set_fill_rule (void *abstract_cr,
390
              cairo_fill_rule_t fill_rule)
391
12.6M
{
392
12.6M
    cairo_default_context_t *cr = abstract_cr;
393
394
12.6M
    return _cairo_gstate_set_fill_rule (cr->gstate, fill_rule);
395
12.6M
}
396
397
static cairo_status_t
398
_cairo_default_context_set_line_width (void *abstract_cr,
399
               double line_width)
400
12.8M
{
401
12.8M
    cairo_default_context_t *cr = abstract_cr;
402
403
12.8M
    return _cairo_gstate_set_line_width (cr->gstate, line_width);
404
12.8M
}
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
270k
{
418
270k
    cairo_default_context_t *cr = abstract_cr;
419
420
270k
    return _cairo_gstate_set_line_cap (cr->gstate, line_cap);
421
270k
}
422
423
static cairo_status_t
424
_cairo_default_context_set_line_join (void *abstract_cr,
425
              cairo_line_join_t line_join)
426
270k
{
427
270k
    cairo_default_context_t *cr = abstract_cr;
428
429
270k
    return _cairo_gstate_set_line_join (cr->gstate, line_join);
430
270k
}
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
270k
{
448
270k
    cairo_default_context_t *cr = abstract_cr;
449
450
270k
    return _cairo_gstate_set_miter_limit (cr->gstate, limit);
451
270k
}
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
551
{
539
551
    cairo_default_context_t *cr = abstract_cr;
540
541
551
    return _cairo_gstate_get_tolerance (cr->gstate);
542
551
}
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
19.2k
{
552
19.2k
    cairo_default_context_t *cr = abstract_cr;
553
554
19.2k
    return _cairo_gstate_translate (cr->gstate, tx, ty);
555
19.2k
}
556
557
static cairo_status_t
558
_cairo_default_context_scale (void *abstract_cr,
559
            double sx,
560
            double sy)
561
19.2k
{
562
19.2k
    cairo_default_context_t *cr = abstract_cr;
563
564
19.2k
    return _cairo_gstate_scale (cr->gstate, sx, sy);
565
19.2k
}
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
1.04M
{
589
1.04M
    cairo_default_context_t *cr = abstract_cr;
590
591
1.04M
    return _cairo_gstate_set_matrix (cr->gstate, matrix);
592
1.04M
}
593
594
static cairo_status_t
595
_cairo_default_context_set_identity_matrix (void *abstract_cr)
596
12.6M
{
597
12.6M
    cairo_default_context_t *cr = abstract_cr;
598
599
12.6M
    _cairo_gstate_identity_matrix (cr->gstate);
600
12.6M
    return CAIRO_STATUS_SUCCESS;
601
12.6M
}
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
3.82k
{
655
3.82k
    cairo_default_context_t *cr = abstract_cr;
656
657
3.82k
    _cairo_gstate_backend_to_user (cr->gstate, x, y);
658
3.82k
}
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
28.1M
{
693
28.1M
    cairo_default_context_t *cr = abstract_cr;
694
695
28.1M
    _cairo_path_fixed_fini (cr->path);
696
28.1M
    _cairo_path_fixed_init (cr->path);
697
698
28.1M
    return CAIRO_STATUS_SUCCESS;
699
28.1M
}
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
20.2M
{
714
20.2M
    cairo_default_context_t *cr = abstract_cr;
715
20.2M
    cairo_fixed_t x_fixed, y_fixed;
716
20.2M
    double width;
717
718
20.2M
    _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
719
20.2M
    width = _cairo_gstate_get_line_width (cr->gstate);
720
20.2M
    x_fixed = _cairo_fixed_from_double_clamped (x, width);
721
20.2M
    y_fixed = _cairo_fixed_from_double_clamped (y, width);
722
723
20.2M
    return _cairo_path_fixed_move_to (cr->path, x_fixed, y_fixed);
724
20.2M
}
725
726
static cairo_status_t
727
_cairo_default_context_line_to (void *abstract_cr, double x, double y)
728
204M
{
729
204M
    cairo_default_context_t *cr = abstract_cr;
730
204M
    cairo_fixed_t x_fixed, y_fixed;
731
204M
    double width;
732
733
204M
    _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
734
204M
    width = _cairo_gstate_get_line_width (cr->gstate);
735
204M
    x_fixed = _cairo_fixed_from_double_clamped (x, width);
736
204M
    y_fixed = _cairo_fixed_from_double_clamped (y, width);
737
738
204M
    return _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
739
204M
}
740
741
static cairo_status_t
742
_cairo_default_context_curve_to (void *abstract_cr,
743
         double x1, double y1,
744
         double x2, double y2,
745
         double x3, double y3)
746
3.57M
{
747
3.57M
    cairo_default_context_t *cr = abstract_cr;
748
3.57M
    cairo_fixed_t x1_fixed, y1_fixed;
749
3.57M
    cairo_fixed_t x2_fixed, y2_fixed;
750
3.57M
    cairo_fixed_t x3_fixed, y3_fixed;
751
3.57M
    double width;
752
753
3.57M
    _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1);
754
3.57M
    _cairo_gstate_user_to_backend (cr->gstate, &x2, &y2);
755
3.57M
    _cairo_gstate_user_to_backend (cr->gstate, &x3, &y3);
756
3.57M
    width = _cairo_gstate_get_line_width (cr->gstate);
757
758
3.57M
    x1_fixed = _cairo_fixed_from_double_clamped (x1, width);
759
3.57M
    y1_fixed = _cairo_fixed_from_double_clamped (y1, width);
760
761
3.57M
    x2_fixed = _cairo_fixed_from_double_clamped (x2, width);
762
3.57M
    y2_fixed = _cairo_fixed_from_double_clamped (y2, width);
763
764
3.57M
    x3_fixed = _cairo_fixed_from_double_clamped (x3, width);
765
3.57M
    y3_fixed = _cairo_fixed_from_double_clamped (y3, width);
766
767
3.57M
    return _cairo_path_fixed_curve_to (cr->path,
768
3.57M
               x1_fixed, y1_fixed,
769
3.57M
               x2_fixed, y2_fixed,
770
3.57M
               x3_fixed, y3_fixed);
771
3.57M
}
772
773
static cairo_status_t
774
_cairo_default_context_arc (void *abstract_cr,
775
          double xc, double yc, double radius,
776
          double angle1, double angle2,
777
          cairo_bool_t forward)
778
0
{
779
0
    cairo_default_context_t *cr = abstract_cr;
780
0
    cairo_status_t status;
781
782
    /* Do nothing, successfully, if radius is <= 0 */
783
0
    if (radius <= 0.0) {
784
0
  cairo_fixed_t x_fixed, y_fixed;
785
786
0
  _cairo_gstate_user_to_backend (cr->gstate, &xc, &yc);
787
0
  x_fixed = _cairo_fixed_from_double (xc);
788
0
  y_fixed = _cairo_fixed_from_double (yc);
789
0
  status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
790
0
  if (unlikely (status))
791
0
      return status;
792
793
0
  status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
794
0
  if (unlikely (status))
795
0
      return status;
796
797
0
  return CAIRO_STATUS_SUCCESS;
798
0
    }
799
800
0
    status = _cairo_default_context_line_to (cr,
801
0
               xc + radius * cos (angle1),
802
0
               yc + radius * sin (angle1));
803
804
0
    if (unlikely (status))
805
0
  return status;
806
807
0
    if (forward)
808
0
  _cairo_arc_path (&cr->base, xc, yc, radius, angle1, angle2);
809
0
    else
810
0
  _cairo_arc_path_negative (&cr->base, xc, yc, radius, angle1, angle2);
811
812
0
    return CAIRO_STATUS_SUCCESS; /* any error will have already been set on cr */
813
0
}
814
815
static cairo_status_t
816
_cairo_default_context_rel_move_to (void *abstract_cr, double dx, double dy)
817
0
{
818
0
    cairo_default_context_t *cr = abstract_cr;
819
0
    cairo_fixed_t dx_fixed, dy_fixed;
820
821
0
    _cairo_gstate_user_to_backend_distance (cr->gstate, &dx, &dy);
822
823
0
    dx_fixed = _cairo_fixed_from_double (dx);
824
0
    dy_fixed = _cairo_fixed_from_double (dy);
825
826
0
    return _cairo_path_fixed_rel_move_to (cr->path, dx_fixed, dy_fixed);
827
0
}
828
829
static cairo_status_t
830
_cairo_default_context_rel_line_to (void *abstract_cr, double dx, double dy)
831
22.1M
{
832
22.1M
    cairo_default_context_t *cr = abstract_cr;
833
22.1M
    cairo_fixed_t dx_fixed, dy_fixed;
834
835
22.1M
    _cairo_gstate_user_to_backend_distance (cr->gstate, &dx, &dy);
836
837
22.1M
    dx_fixed = _cairo_fixed_from_double (dx);
838
22.1M
    dy_fixed = _cairo_fixed_from_double (dy);
839
840
22.1M
    return _cairo_path_fixed_rel_line_to (cr->path, dx_fixed, dy_fixed);
841
22.1M
}
842
843
844
static cairo_status_t
845
_cairo_default_context_rel_curve_to (void *abstract_cr,
846
             double dx1, double dy1,
847
             double dx2, double dy2,
848
             double dx3, double dy3)
849
0
{
850
0
    cairo_default_context_t *cr = abstract_cr;
851
0
    cairo_fixed_t dx1_fixed, dy1_fixed;
852
0
    cairo_fixed_t dx2_fixed, dy2_fixed;
853
0
    cairo_fixed_t dx3_fixed, dy3_fixed;
854
855
0
    _cairo_gstate_user_to_backend_distance (cr->gstate, &dx1, &dy1);
856
0
    _cairo_gstate_user_to_backend_distance (cr->gstate, &dx2, &dy2);
857
0
    _cairo_gstate_user_to_backend_distance (cr->gstate, &dx3, &dy3);
858
859
0
    dx1_fixed = _cairo_fixed_from_double (dx1);
860
0
    dy1_fixed = _cairo_fixed_from_double (dy1);
861
862
0
    dx2_fixed = _cairo_fixed_from_double (dx2);
863
0
    dy2_fixed = _cairo_fixed_from_double (dy2);
864
865
0
    dx3_fixed = _cairo_fixed_from_double (dx3);
866
0
    dy3_fixed = _cairo_fixed_from_double (dy3);
867
868
0
    return _cairo_path_fixed_rel_curve_to (cr->path,
869
0
             dx1_fixed, dy1_fixed,
870
0
             dx2_fixed, dy2_fixed,
871
0
             dx3_fixed, dy3_fixed);
872
0
}
873
874
static cairo_status_t
875
_cairo_default_context_close_path (void *abstract_cr)
876
10.7M
{
877
10.7M
    cairo_default_context_t *cr = abstract_cr;
878
879
10.7M
    return _cairo_path_fixed_close_path (cr->path);
880
10.7M
}
881
882
static cairo_status_t
883
_cairo_default_context_rectangle (void *abstract_cr,
884
          double x, double y,
885
          double width, double height)
886
7.37M
{
887
7.37M
    cairo_default_context_t *cr = abstract_cr;
888
7.37M
    cairo_status_t status;
889
890
7.37M
    status = _cairo_default_context_move_to (cr, x, y);
891
7.37M
    if (unlikely (status))
892
0
  return status;
893
894
7.37M
    status = _cairo_default_context_rel_line_to (cr, width, 0);
895
7.37M
    if (unlikely (status))
896
0
  return status;
897
898
7.37M
    status = _cairo_default_context_rel_line_to (cr, 0, height);
899
7.37M
    if (unlikely (status))
900
0
  return status;
901
902
7.37M
    status = _cairo_default_context_rel_line_to (cr, -width, 0);
903
7.37M
    if (unlikely (status))
904
0
  return status;
905
906
7.37M
    return _cairo_default_context_close_path (cr);
907
7.37M
}
908
909
static void
910
_cairo_default_context_path_extents (void *abstract_cr,
911
             double *x1,
912
             double *y1,
913
             double *x2,
914
             double *y2)
915
12.5M
{
916
12.5M
    cairo_default_context_t *cr = abstract_cr;
917
918
12.5M
    _cairo_gstate_path_extents (cr->gstate,
919
12.5M
        cr->path,
920
12.5M
        x1, y1, x2, y2);
921
12.5M
}
922
923
static cairo_bool_t
924
_cairo_default_context_has_current_point (void *abstract_cr)
925
0
{
926
0
    cairo_default_context_t *cr = abstract_cr;
927
928
0
    return cr->path->has_current_point;
929
0
}
930
931
static cairo_bool_t
932
_cairo_default_context_get_current_point (void *abstract_cr,
933
            double *x,
934
            double *y)
935
0
{
936
0
    cairo_default_context_t *cr = abstract_cr;
937
0
    cairo_fixed_t x_fixed, y_fixed;
938
939
0
    if (_cairo_path_fixed_get_current_point (cr->path, &x_fixed, &y_fixed))
940
0
    {
941
0
  *x = _cairo_fixed_to_double (x_fixed);
942
0
  *y = _cairo_fixed_to_double (y_fixed);
943
0
  _cairo_gstate_backend_to_user (cr->gstate, x, y);
944
945
0
  return TRUE;
946
0
    }
947
0
    else
948
0
    {
949
0
  return FALSE;
950
0
    }
951
0
}
952
953
static cairo_path_t *
954
_cairo_default_context_copy_path (void *abstract_cr)
955
551
{
956
551
    cairo_default_context_t *cr = abstract_cr;
957
958
551
    return _cairo_path_create (cr->path, &cr->base);
959
551
}
960
961
static cairo_path_t *
962
_cairo_default_context_copy_path_flat (void *abstract_cr)
963
0
{
964
0
    cairo_default_context_t *cr = abstract_cr;
965
966
0
    return _cairo_path_create_flat (cr->path, &cr->base);
967
0
}
968
969
static cairo_status_t
970
_cairo_default_context_append_path (void *abstract_cr,
971
            const cairo_path_t *path)
972
551
{
973
551
    cairo_default_context_t *cr = abstract_cr;
974
975
551
    return _cairo_path_append_to_context (path, &cr->base);
976
551
}
977
978
static cairo_status_t
979
_cairo_default_context_paint (void *abstract_cr)
980
516k
{
981
516k
    cairo_default_context_t *cr = abstract_cr;
982
983
516k
    return _cairo_gstate_paint (cr->gstate);
984
516k
}
985
986
static cairo_status_t
987
_cairo_default_context_paint_with_alpha (void *abstract_cr,
988
           double alpha)
989
0
{
990
0
    cairo_default_context_t *cr = abstract_cr;
991
0
    cairo_solid_pattern_t pattern;
992
0
    cairo_status_t status;
993
0
    cairo_color_t color;
994
995
0
    if (CAIRO_ALPHA_IS_OPAQUE (alpha))
996
0
  return _cairo_gstate_paint (cr->gstate);
997
998
0
    if (CAIRO_ALPHA_IS_ZERO (alpha) &&
999
0
        _cairo_operator_bounded_by_mask (cr->gstate->op)) {
1000
0
  return CAIRO_STATUS_SUCCESS;
1001
0
    }
1002
1003
0
    _cairo_color_init_rgba (&color, 0., 0., 0., alpha);
1004
0
    _cairo_pattern_init_solid (&pattern, &color);
1005
1006
0
    status = _cairo_gstate_mask (cr->gstate, &pattern.base);
1007
0
    _cairo_pattern_fini (&pattern.base);
1008
1009
0
    return status;
1010
0
}
1011
1012
static cairo_status_t
1013
_cairo_default_context_mask (void *abstract_cr,
1014
           cairo_pattern_t *mask)
1015
0
{
1016
0
    cairo_default_context_t *cr = abstract_cr;
1017
1018
0
    return _cairo_gstate_mask (cr->gstate, mask);
1019
0
}
1020
1021
static cairo_status_t
1022
_cairo_default_context_stroke_preserve (void *abstract_cr)
1023
0
{
1024
0
    cairo_default_context_t *cr = abstract_cr;
1025
1026
0
    return _cairo_gstate_stroke (cr->gstate, cr->path);
1027
0
}
1028
1029
static cairo_status_t
1030
_cairo_default_context_stroke (void *abstract_cr)
1031
1.04M
{
1032
1.04M
    cairo_default_context_t *cr = abstract_cr;
1033
1.04M
    cairo_status_t status;
1034
1035
1.04M
    status = _cairo_gstate_stroke (cr->gstate, cr->path);
1036
1.04M
    if (unlikely (status))
1037
0
  return status;
1038
1039
1.04M
    return _cairo_default_context_new_path (cr);
1040
1.04M
}
1041
1042
static cairo_status_t
1043
_cairo_default_context_in_stroke (void *abstract_cr,
1044
          double x, double y,
1045
          cairo_bool_t *inside)
1046
0
{
1047
0
    cairo_default_context_t *cr = abstract_cr;
1048
1049
0
    return _cairo_gstate_in_stroke (cr->gstate,
1050
0
            cr->path,
1051
0
            x, y,
1052
0
            inside);
1053
0
}
1054
1055
static cairo_status_t
1056
_cairo_default_context_stroke_extents (void *abstract_cr,
1057
               double *x1, double *y1, double *x2, double *y2)
1058
0
{
1059
0
    cairo_default_context_t *cr = abstract_cr;
1060
1061
0
    return _cairo_gstate_stroke_extents (cr->gstate,
1062
0
           cr->path,
1063
0
           x1, y1, x2, y2);
1064
0
}
1065
1066
static cairo_status_t
1067
_cairo_default_context_fill_preserve (void *abstract_cr)
1068
6.24k
{
1069
6.24k
    cairo_default_context_t *cr = abstract_cr;
1070
1071
6.24k
    return _cairo_gstate_fill (cr->gstate, cr->path);
1072
6.24k
}
1073
1074
static cairo_status_t
1075
_cairo_default_context_fill (void *abstract_cr)
1076
12.9M
{
1077
12.9M
    cairo_default_context_t *cr = abstract_cr;
1078
12.9M
    cairo_status_t status;
1079
1080
12.9M
    status = _cairo_gstate_fill (cr->gstate, cr->path);
1081
12.9M
    if (unlikely (status))
1082
0
  return status;
1083
1084
12.9M
    return _cairo_default_context_new_path (cr);
1085
12.9M
}
1086
1087
static cairo_status_t
1088
_cairo_default_context_in_fill (void *abstract_cr,
1089
        double x, double y,
1090
        cairo_bool_t *inside)
1091
0
{
1092
0
    cairo_default_context_t *cr = abstract_cr;
1093
1094
0
    *inside = _cairo_gstate_in_fill (cr->gstate,
1095
0
             cr->path,
1096
0
             x, y);
1097
0
    return CAIRO_STATUS_SUCCESS;
1098
0
}
1099
1100
static cairo_status_t
1101
_cairo_default_context_fill_extents (void *abstract_cr,
1102
             double *x1, double *y1, double *x2, double *y2)
1103
0
{
1104
0
    cairo_default_context_t *cr = abstract_cr;
1105
1106
0
    return _cairo_gstate_fill_extents (cr->gstate,
1107
0
               cr->path,
1108
0
               x1, y1, x2, y2);
1109
0
}
1110
1111
static cairo_status_t
1112
_cairo_default_context_clip_preserve (void *abstract_cr)
1113
0
{
1114
0
    cairo_default_context_t *cr = abstract_cr;
1115
1116
0
    return _cairo_gstate_clip (cr->gstate, cr->path);
1117
0
}
1118
1119
static cairo_status_t
1120
_cairo_default_context_clip (void *abstract_cr)
1121
1.48M
{
1122
1.48M
    cairo_default_context_t *cr = abstract_cr;
1123
1.48M
    cairo_status_t status;
1124
1125
1.48M
    status = _cairo_gstate_clip (cr->gstate, cr->path);
1126
1.48M
    if (unlikely (status))
1127
0
  return status;
1128
1129
1.48M
    return _cairo_default_context_new_path (cr);
1130
1.48M
}
1131
1132
static cairo_status_t
1133
_cairo_default_context_in_clip (void *abstract_cr,
1134
        double x, double y,
1135
        cairo_bool_t *inside)
1136
0
{
1137
0
    cairo_default_context_t *cr = abstract_cr;
1138
1139
0
    *inside = _cairo_gstate_in_clip (cr->gstate, x, y);
1140
0
    return CAIRO_STATUS_SUCCESS;
1141
0
}
1142
1143
static cairo_status_t
1144
_cairo_default_context_reset_clip (void *abstract_cr)
1145
1
{
1146
1
    cairo_default_context_t *cr = abstract_cr;
1147
1148
1
    return _cairo_gstate_reset_clip (cr->gstate);
1149
1
}
1150
1151
static cairo_status_t
1152
_cairo_default_context_clip_extents (void *abstract_cr,
1153
             double *x1, double *y1, double *x2, double *y2)
1154
12.5M
{
1155
12.5M
    cairo_default_context_t *cr = abstract_cr;
1156
1157
12.5M
    if (! _cairo_gstate_clip_extents (cr->gstate, x1, y1, x2, y2)) {
1158
0
  *x1 = -INFINITY;
1159
0
  *y1 = -INFINITY;
1160
0
  *x2 = +INFINITY;
1161
0
  *y2 = +INFINITY;
1162
0
    }
1163
1164
12.5M
    return CAIRO_STATUS_SUCCESS;
1165
12.5M
}
1166
1167
static cairo_rectangle_list_t *
1168
_cairo_default_context_copy_clip_rectangle_list (void *abstract_cr)
1169
0
{
1170
0
    cairo_default_context_t *cr = abstract_cr;
1171
1172
0
    return _cairo_gstate_copy_clip_rectangle_list (cr->gstate);
1173
0
}
1174
1175
static cairo_status_t
1176
_cairo_default_context_copy_page (void *abstract_cr)
1177
0
{
1178
0
    cairo_default_context_t *cr = abstract_cr;
1179
1180
0
    return _cairo_gstate_copy_page (cr->gstate);
1181
0
}
1182
1183
static cairo_status_t
1184
_cairo_default_context_tag_begin (void *abstract_cr,
1185
          const char *tag_name, const char *attributes)
1186
0
{
1187
0
    cairo_default_context_t *cr = abstract_cr;
1188
1189
0
    return _cairo_gstate_tag_begin (cr->gstate, tag_name, attributes);
1190
0
}
1191
1192
static cairo_status_t
1193
_cairo_default_context_tag_end (void *abstract_cr,
1194
        const char *tag_name)
1195
0
{
1196
0
    cairo_default_context_t *cr = abstract_cr;
1197
1198
0
    return _cairo_gstate_tag_end (cr->gstate, tag_name);
1199
0
}
1200
1201
static cairo_status_t
1202
_cairo_default_context_show_page (void *abstract_cr)
1203
0
{
1204
0
    cairo_default_context_t *cr = abstract_cr;
1205
1206
0
    return _cairo_gstate_show_page (cr->gstate);
1207
0
}
1208
1209
static cairo_status_t
1210
_cairo_default_context_set_font_face (void *abstract_cr,
1211
              cairo_font_face_t *font_face)
1212
2.22M
{
1213
2.22M
    cairo_default_context_t *cr = abstract_cr;
1214
1215
2.22M
    return _cairo_gstate_set_font_face (cr->gstate, font_face);
1216
2.22M
}
1217
1218
static cairo_font_face_t *
1219
_cairo_default_context_get_font_face (void *abstract_cr)
1220
0
{
1221
0
    cairo_default_context_t *cr = abstract_cr;
1222
0
    cairo_font_face_t *font_face;
1223
0
    cairo_status_t status;
1224
1225
0
    status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
1226
0
    if (unlikely (status)) {
1227
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1228
0
  return (cairo_font_face_t *) &_cairo_font_face_nil;
1229
0
    }
1230
1231
0
    return font_face;
1232
0
}
1233
1234
static cairo_status_t
1235
_cairo_default_context_font_extents (void *abstract_cr,
1236
             cairo_font_extents_t *extents)
1237
0
{
1238
0
    cairo_default_context_t *cr = abstract_cr;
1239
1240
0
    return _cairo_gstate_get_font_extents (cr->gstate, extents);
1241
0
}
1242
1243
static cairo_status_t
1244
_cairo_default_context_set_font_size (void *abstract_cr,
1245
              double size)
1246
2.22M
{
1247
2.22M
    cairo_default_context_t *cr = abstract_cr;
1248
1249
2.22M
    return _cairo_gstate_set_font_size (cr->gstate, size);
1250
2.22M
}
1251
1252
static cairo_status_t
1253
_cairo_default_context_set_font_matrix (void *abstract_cr,
1254
          const cairo_matrix_t *matrix)
1255
2.22M
{
1256
2.22M
    cairo_default_context_t *cr = abstract_cr;
1257
1258
2.22M
    return _cairo_gstate_set_font_matrix (cr->gstate, matrix);
1259
2.22M
}
1260
1261
static void
1262
_cairo_default_context_get_font_matrix (void *abstract_cr,
1263
          cairo_matrix_t *matrix)
1264
0
{
1265
0
    cairo_default_context_t *cr = abstract_cr;
1266
1267
0
    _cairo_gstate_get_font_matrix (cr->gstate, matrix);
1268
0
}
1269
1270
static cairo_status_t
1271
_cairo_default_context_set_font_options (void *abstract_cr,
1272
           const cairo_font_options_t *options)
1273
21.7k
{
1274
21.7k
    cairo_default_context_t *cr = abstract_cr;
1275
1276
21.7k
    _cairo_gstate_set_font_options (cr->gstate, options);
1277
21.7k
    return CAIRO_STATUS_SUCCESS;
1278
21.7k
}
1279
1280
static void
1281
_cairo_default_context_get_font_options (void *abstract_cr,
1282
           cairo_font_options_t *options)
1283
0
{
1284
0
    cairo_default_context_t *cr = abstract_cr;
1285
1286
0
    _cairo_gstate_get_font_options (cr->gstate, options);
1287
0
}
1288
1289
static cairo_status_t
1290
_cairo_default_context_set_scaled_font (void *abstract_cr,
1291
          cairo_scaled_font_t *scaled_font)
1292
0
{
1293
0
    cairo_default_context_t *cr = abstract_cr;
1294
0
    cairo_bool_t was_previous;
1295
0
    cairo_status_t status;
1296
1297
0
    if (scaled_font == cr->gstate->scaled_font)
1298
0
  return CAIRO_STATUS_SUCCESS;
1299
1300
0
    was_previous = scaled_font == cr->gstate->previous_scaled_font;
1301
1302
0
    status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face);
1303
0
    if (unlikely (status))
1304
0
  return status;
1305
1306
0
    status = _cairo_gstate_set_font_matrix (cr->gstate, &scaled_font->font_matrix);
1307
0
    if (unlikely (status))
1308
0
  return status;
1309
1310
0
    _cairo_gstate_set_font_options (cr->gstate, &scaled_font->options);
1311
1312
0
    if (was_previous)
1313
0
  cr->gstate->scaled_font = cairo_scaled_font_reference (scaled_font);
1314
1315
0
    return CAIRO_STATUS_SUCCESS;
1316
0
}
1317
1318
static cairo_scaled_font_t *
1319
_cairo_default_context_get_scaled_font (void *abstract_cr)
1320
0
{
1321
0
    cairo_default_context_t *cr = abstract_cr;
1322
0
    cairo_scaled_font_t *scaled_font;
1323
0
    cairo_status_t status;
1324
1325
0
    status = _cairo_gstate_get_scaled_font (cr->gstate, &scaled_font);
1326
0
    if (unlikely (status))
1327
0
  return _cairo_scaled_font_create_in_error (status);
1328
1329
0
    return scaled_font;
1330
0
}
1331
1332
static cairo_status_t
1333
_cairo_default_context_glyphs (void *abstract_cr,
1334
             const cairo_glyph_t *glyphs,
1335
             int num_glyphs,
1336
             cairo_glyph_text_info_t *info)
1337
2.22M
{
1338
2.22M
    cairo_default_context_t *cr = abstract_cr;
1339
1340
2.22M
    return _cairo_gstate_show_text_glyphs (cr->gstate, glyphs, num_glyphs, info);
1341
2.22M
}
1342
1343
static cairo_status_t
1344
_cairo_default_context_glyph_path (void *abstract_cr,
1345
           const cairo_glyph_t *glyphs,
1346
           int num_glyphs)
1347
0
{
1348
0
    cairo_default_context_t *cr = abstract_cr;
1349
1350
0
    return _cairo_gstate_glyph_path (cr->gstate,
1351
0
             glyphs, num_glyphs,
1352
0
             cr->path);
1353
0
}
1354
1355
static cairo_status_t
1356
_cairo_default_context_glyph_extents (void                *abstract_cr,
1357
              const cairo_glyph_t    *glyphs,
1358
              int                    num_glyphs,
1359
              cairo_text_extents_t   *extents)
1360
0
{
1361
0
    cairo_default_context_t *cr = abstract_cr;
1362
1363
0
    return _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents);
1364
0
}
1365
1366
static const cairo_backend_t _cairo_default_context_backend = {
1367
    CAIRO_TYPE_DEFAULT,
1368
    _cairo_default_context_destroy,
1369
1370
    _cairo_default_context_get_original_target,
1371
    _cairo_default_context_get_current_target,
1372
1373
    _cairo_default_context_save,
1374
    _cairo_default_context_restore,
1375
1376
    _cairo_default_context_push_group,
1377
    _cairo_default_context_pop_group,
1378
1379
    _cairo_default_context_set_source_rgba,
1380
    _cairo_default_context_set_source_surface,
1381
    _cairo_default_context_set_source,
1382
    _cairo_default_context_get_source,
1383
1384
    _cairo_default_context_set_antialias,
1385
    _cairo_default_context_set_dash,
1386
    _cairo_default_context_set_fill_rule,
1387
    _cairo_default_context_set_line_cap,
1388
    _cairo_default_context_set_line_join,
1389
    _cairo_default_context_set_line_width,
1390
    _cairo_default_context_set_hairline,
1391
    _cairo_default_context_set_miter_limit,
1392
    _cairo_default_context_set_opacity,
1393
    _cairo_default_context_set_operator,
1394
    _cairo_default_context_set_tolerance,
1395
    _cairo_default_context_get_antialias,
1396
    _cairo_default_context_get_dash,
1397
    _cairo_default_context_get_fill_rule,
1398
    _cairo_default_context_get_line_cap,
1399
    _cairo_default_context_get_line_join,
1400
    _cairo_default_context_get_line_width,
1401
    _cairo_default_context_get_hairline,
1402
    _cairo_default_context_get_miter_limit,
1403
    _cairo_default_context_get_opacity,
1404
    _cairo_default_context_get_operator,
1405
    _cairo_default_context_get_tolerance,
1406
1407
    _cairo_default_context_translate,
1408
    _cairo_default_context_scale,
1409
    _cairo_default_context_rotate,
1410
    _cairo_default_context_transform,
1411
    _cairo_default_context_set_matrix,
1412
    _cairo_default_context_set_identity_matrix,
1413
    _cairo_default_context_get_matrix,
1414
1415
    _cairo_default_context_user_to_device,
1416
    _cairo_default_context_user_to_device_distance,
1417
    _cairo_default_context_device_to_user,
1418
    _cairo_default_context_device_to_user_distance,
1419
1420
    _cairo_default_context_user_to_backend,
1421
    _cairo_default_context_user_to_backend_distance,
1422
    _cairo_default_context_backend_to_user,
1423
    _cairo_default_context_backend_to_user_distance,
1424
1425
    _cairo_default_context_new_path,
1426
    _cairo_default_context_new_sub_path,
1427
    _cairo_default_context_move_to,
1428
    _cairo_default_context_rel_move_to,
1429
    _cairo_default_context_line_to,
1430
    _cairo_default_context_rel_line_to,
1431
    _cairo_default_context_curve_to,
1432
    _cairo_default_context_rel_curve_to,
1433
    NULL, /* arc-to */
1434
    NULL, /* rel-arc-to */
1435
    _cairo_default_context_close_path,
1436
    _cairo_default_context_arc,
1437
    _cairo_default_context_rectangle,
1438
    _cairo_default_context_path_extents,
1439
    _cairo_default_context_has_current_point,
1440
    _cairo_default_context_get_current_point,
1441
    _cairo_default_context_copy_path,
1442
    _cairo_default_context_copy_path_flat,
1443
    _cairo_default_context_append_path,
1444
1445
    NULL, /* stroke-to-path */
1446
1447
    _cairo_default_context_clip,
1448
    _cairo_default_context_clip_preserve,
1449
    _cairo_default_context_in_clip,
1450
    _cairo_default_context_clip_extents,
1451
    _cairo_default_context_reset_clip,
1452
    _cairo_default_context_copy_clip_rectangle_list,
1453
1454
    _cairo_default_context_paint,
1455
    _cairo_default_context_paint_with_alpha,
1456
    _cairo_default_context_mask,
1457
1458
    _cairo_default_context_stroke,
1459
    _cairo_default_context_stroke_preserve,
1460
    _cairo_default_context_in_stroke,
1461
    _cairo_default_context_stroke_extents,
1462
1463
    _cairo_default_context_fill,
1464
    _cairo_default_context_fill_preserve,
1465
    _cairo_default_context_in_fill,
1466
    _cairo_default_context_fill_extents,
1467
1468
    _cairo_default_context_set_font_face,
1469
    _cairo_default_context_get_font_face,
1470
    _cairo_default_context_set_font_size,
1471
    _cairo_default_context_set_font_matrix,
1472
    _cairo_default_context_get_font_matrix,
1473
    _cairo_default_context_set_font_options,
1474
    _cairo_default_context_get_font_options,
1475
    _cairo_default_context_set_scaled_font,
1476
    _cairo_default_context_get_scaled_font,
1477
    _cairo_default_context_font_extents,
1478
1479
    _cairo_default_context_glyphs,
1480
    _cairo_default_context_glyph_path,
1481
    _cairo_default_context_glyph_extents,
1482
1483
    _cairo_default_context_copy_page,
1484
    _cairo_default_context_show_page,
1485
1486
    _cairo_default_context_tag_begin,
1487
    _cairo_default_context_tag_end,
1488
};
1489
1490
cairo_status_t
1491
_cairo_default_context_init (cairo_default_context_t *cr, void *target)
1492
14.5M
{
1493
14.5M
    _cairo_init (&cr->base, &_cairo_default_context_backend);
1494
14.5M
    _cairo_path_fixed_init (cr->path);
1495
1496
14.5M
    cr->gstate = &cr->gstate_tail[0];
1497
14.5M
    cr->gstate_freelist = &cr->gstate_tail[1];
1498
14.5M
    cr->gstate_tail[1].next = NULL;
1499
1500
14.5M
    return _cairo_gstate_init (cr->gstate, target);
1501
14.5M
}
1502
1503
cairo_t *
1504
_cairo_default_context_create (void *target)
1505
14.5M
{
1506
14.5M
    cairo_default_context_t *cr;
1507
14.5M
    cairo_status_t status;
1508
1509
14.5M
    cr = _freed_pool_get (&context_pool);
1510
14.5M
    if (unlikely (cr == NULL)) {
1511
93
  cr = _cairo_calloc (sizeof (cairo_default_context_t));
1512
93
  if (unlikely (cr == NULL))
1513
0
      return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1514
93
    }
1515
1516
14.5M
    status = _cairo_default_context_init (cr, target);
1517
14.5M
    if (unlikely (status)) {
1518
0
  _freed_pool_put (&context_pool, cr);
1519
0
  return _cairo_create_in_error (status);
1520
0
    }
1521
1522
14.5M
    return &cr->base;
1523
14.5M
}