Coverage Report

Created: 2026-09-28 10:59

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