Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/cairo/src/cairo-clip-polygon.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2011 Intel Corporation
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it either under the terms of the GNU Lesser General Public
8
 * License version 2.1 as published by the Free Software Foundation
9
 * (the "LGPL") or, at your option, under the terms of the Mozilla
10
 * Public License Version 1.1 (the "MPL"). If you do not alter this
11
 * notice, a recipient may use your version of this file under either
12
 * the MPL or the LGPL.
13
 *
14
 * You should have received a copy of the LGPL along with this library
15
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17
 * You should have received a copy of the MPL along with this library
18
 * in the file COPYING-MPL-1.1
19
 *
20
 * The contents of this file are subject to the Mozilla Public License
21
 * Version 1.1 (the "License"); you may not use this file except in
22
 * compliance with the License. You may obtain a copy of the License at
23
 * http://www.mozilla.org/MPL/
24
 *
25
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27
 * the specific language governing rights and limitations.
28
 *
29
 * The Original Code is the cairo graphics library.
30
 *
31
 * The Initial Developer of the Original Code is University of Southern
32
 * California.
33
 *
34
 * Contributor(s):
35
 *  Chris Wilson <chris@chris-wilson.co.uk>
36
 */
37
38
#include "cairoint.h"
39
#include "cairo-clip-inline.h"
40
#include "cairo-clip-private.h"
41
#include "cairo-error-private.h"
42
#include "cairo-freed-pool-private.h"
43
#include "cairo-gstate-private.h"
44
#include "cairo-path-fixed-private.h"
45
#include "cairo-pattern-private.h"
46
#include "cairo-composite-rectangles-private.h"
47
#include "cairo-region-private.h"
48
49
static cairo_bool_t
50
can_convert_to_polygon (const cairo_clip_t *clip)
51
0
{
52
0
    cairo_clip_path_t *clip_path = clip->path;
53
0
    cairo_antialias_t antialias = clip_path->antialias;
54
55
0
    while ((clip_path = clip_path->prev) != NULL) {
56
0
  if (clip_path->antialias != antialias)
57
0
      return FALSE;
58
0
    }
59
60
0
    return TRUE;
61
0
}
62
63
cairo_int_status_t
64
_cairo_clip_get_polygon (const cairo_clip_t *clip,
65
       cairo_polygon_t *polygon,
66
       cairo_fill_rule_t *fill_rule,
67
       cairo_antialias_t *antialias)
68
0
{
69
0
    cairo_status_t status;
70
0
    cairo_clip_path_t *clip_path;
71
72
0
    if (_cairo_clip_is_all_clipped (clip)) {
73
0
  _cairo_polygon_init (polygon, NULL, 0);
74
0
  return CAIRO_INT_STATUS_SUCCESS;
75
0
    }
76
77
    /* If there is no clip, we need an infinite polygon */
78
0
    assert (clip && (clip->path || clip->num_boxes));
79
80
0
    if (clip->path == NULL) {
81
0
  *fill_rule = CAIRO_FILL_RULE_WINDING;
82
0
  *antialias = CAIRO_ANTIALIAS_DEFAULT;
83
0
  return _cairo_polygon_init_box_array (polygon,
84
0
                clip->boxes,
85
0
                clip->num_boxes);
86
0
    }
87
88
    /* check that residual is all of the same type/tolerance */
89
0
    if (! can_convert_to_polygon (clip))
90
0
  return CAIRO_INT_STATUS_UNSUPPORTED;
91
92
0
    if (clip->num_boxes < 2)
93
0
  _cairo_polygon_init_with_clip (polygon, clip);
94
0
    else
95
0
  _cairo_polygon_init_with_clip (polygon, NULL);
96
97
0
    clip_path = clip->path;
98
0
    *fill_rule = clip_path->fill_rule;
99
0
    *antialias = clip_path->antialias;
100
101
0
    status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
102
0
            clip_path->tolerance,
103
0
            polygon);
104
0
    if (unlikely (status))
105
0
  goto err;
106
107
0
    if (clip->num_boxes > 1) {
108
0
  status = _cairo_polygon_intersect_with_boxes (polygon, fill_rule,
109
0
                  clip->boxes, clip->num_boxes);
110
0
  if (unlikely (status))
111
0
      goto err;
112
0
    }
113
114
0
    polygon->limits = NULL;
115
0
    polygon->num_limits = 0;
116
117
0
    while ((clip_path = clip_path->prev) != NULL) {
118
0
  cairo_polygon_t next;
119
120
0
  _cairo_polygon_init (&next, NULL, 0);
121
0
  status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
122
0
                clip_path->tolerance,
123
0
                &next);
124
0
  if (likely (status == CAIRO_STATUS_SUCCESS))
125
0
    status = _cairo_polygon_intersect (polygon, *fill_rule,
126
0
               &next, clip_path->fill_rule);
127
0
  _cairo_polygon_fini (&next);
128
0
  if (unlikely (status))
129
0
      goto err;
130
131
0
  *fill_rule = CAIRO_FILL_RULE_WINDING;
132
0
    }
133
134
0
    return CAIRO_STATUS_SUCCESS;
135
136
0
err:
137
0
    _cairo_polygon_fini (polygon);
138
0
    return status;
139
0
}
140
141
cairo_bool_t
142
_cairo_clip_is_polygon (const cairo_clip_t *clip)
143
0
{
144
0
    if (_cairo_clip_is_all_clipped (clip))
145
0
  return TRUE;
146
147
    /* If there is no clip, we need an infinite polygon */
148
0
    if (clip == NULL)
149
0
  return FALSE;
150
151
0
    if (clip->path == NULL)
152
0
  return TRUE;
153
154
    /* check that residual is all of the same type/tolerance */
155
0
    return can_convert_to_polygon (clip);
156
0
}