Subversion Repositories Scribus

Rev

Rev 14952 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
14952 fschmid 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 © 2002 University of Southern California
5
 * Copyright © 2005 Red Hat, Inc.
6
 * Copyright © 2006 Red Hat, Inc.
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
18122 mrdocs 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14952 fschmid 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
 */
39
 
40
#include "cairoint.h"
41
 
42
cairo_private void
43
_cairo_box_from_doubles (cairo_box_t *box,
44
                         double *x1, double *y1,
45
                         double *x2, double *y2)
46
{
47
    box->p1.x = _cairo_fixed_from_double (*x1);
48
    box->p1.y = _cairo_fixed_from_double (*y1);
49
    box->p2.x = _cairo_fixed_from_double (*x2);
50
    box->p2.y = _cairo_fixed_from_double (*y2);
51
}
52
 
53
cairo_private void
54
_cairo_box_to_doubles (const cairo_box_t *box,
55
                       double *x1, double *y1,
56
                       double *x2, double *y2)
57
{
58
    *x1 = _cairo_fixed_to_double (box->p1.x);
59
    *y1 = _cairo_fixed_to_double (box->p1.y);
60
    *x2 = _cairo_fixed_to_double (box->p2.x);
61
    *y2 = _cairo_fixed_to_double (box->p2.y);
62
}
63
 
64
void
65
_cairo_box_from_rectangle (cairo_box_t                 *box,
66
                           const cairo_rectangle_int_t *rect)
67
{
68
    box->p1.x = _cairo_fixed_from_int (rect->x);
69
    box->p1.y = _cairo_fixed_from_int (rect->y);
70
    box->p2.x = _cairo_fixed_from_int (rect->x + rect->width);
71
    box->p2.y = _cairo_fixed_from_int (rect->y + rect->height);
72
}
73
 
74
void
75
_cairo_boxes_get_extents (const cairo_box_t *boxes,
76
                          int num_boxes,
77
                          cairo_box_t *extents)
78
{
79
    int n;
80
 
81
    assert (num_boxes > 0);
82
    *extents = *boxes;
83
 
84
    for (n = 1; n < num_boxes; n++) {
85
        if (boxes[n].p1.x < extents->p1.x)
86
            extents->p1.x = boxes[n].p1.x;
87
        if (boxes[n].p2.x > extents->p2.x)
88
            extents->p2.x = boxes[n].p2.x;
89
 
90
        if (boxes[n].p1.y < extents->p1.y)
91
            extents->p1.y = boxes[n].p1.y;
92
        if (boxes[n].p2.y > extents->p2.y)
93
            extents->p2.y = boxes[n].p2.y;
94
    }
95
}
96
 
97
/* XXX We currently have a confusing mix of boxes and rectangles as
98
 * exemplified by this function.  A #cairo_box_t is a rectangular area
99
 * represented by the coordinates of the upper left and lower right
100
 * corners, expressed in fixed point numbers.  A #cairo_rectangle_int_t is
101
 * also a rectangular area, but represented by the upper left corner
102
 * and the width and the height, as integer numbers.
103
 *
104
 * This function converts a #cairo_box_t to a #cairo_rectangle_int_t by
105
 * increasing the area to the nearest integer coordinates.  We should
106
 * standardize on #cairo_rectangle_fixed_t and #cairo_rectangle_int_t, and
107
 * this function could be renamed to the more reasonable
108
 * _cairo_rectangle_fixed_round.
109
 */
110
 
111
void
112
_cairo_box_round_to_rectangle (const cairo_box_t     *box,
113
                               cairo_rectangle_int_t *rectangle)
114
{
115
    rectangle->x = _cairo_fixed_integer_floor (box->p1.x);
116
    rectangle->y = _cairo_fixed_integer_floor (box->p1.y);
117
    rectangle->width = _cairo_fixed_integer_ceil (box->p2.x) - rectangle->x;
118
    rectangle->height = _cairo_fixed_integer_ceil (box->p2.y) - rectangle->y;
119
}
120
 
121
cairo_bool_t
122
_cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
123
                            const cairo_rectangle_int_t *src)
124
{
125
    int x1, y1, x2, y2;
126
 
127
    x1 = MAX (dst->x, src->x);
128
    y1 = MAX (dst->y, src->y);
129
    /* Beware the unsigned promotion, fortunately we have bits to spare
130
     * as (CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN) < UINT_MAX
131
     */
132
    x2 = MIN (dst->x + (int) dst->width,  src->x + (int) src->width);
133
    y2 = MIN (dst->y + (int) dst->height, src->y + (int) src->height);
134
 
135
    if (x1 >= x2 || y1 >= y2) {
136
        dst->x = 0;
137
        dst->y = 0;
138
        dst->width  = 0;
139
        dst->height = 0;
140
 
141
        return FALSE;
142
    } else {
143
        dst->x = x1;
144
        dst->y = y1;
145
        dst->width  = x2 - x1;
146
        dst->height = y2 - y1;
147
 
148
        return TRUE;
149
    }
150
}
151
 
152
#define P1x (line->p1.x)
153
#define P1y (line->p1.y)
154
#define P2x (line->p2.x)
155
#define P2y (line->p2.y)
156
#define B1x (box->p1.x)
157
#define B1y (box->p1.y)
158
#define B2x (box->p2.x)
159
#define B2y (box->p2.y)
160
 
161
/*
162
 * Check whether any part of line intersects box.  This function essentially
163
 * computes whether the ray starting at line->p1 in the direction of line->p2
164
 * intersects the box before it reaches p2.  Normally, this is done
165
 * by dividing by the lengths of the line projected onto each axis.  Because
166
 * we're in fixed point, this function does a bit more work to avoid having to
167
 * do the division -- we don't care about the actual intersection point, so
168
 * it's of no interest to us.
169
 */
170
 
171
cairo_bool_t
172
_cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line)
173
{
174
    cairo_fixed_t t1=0, t2=0, t3=0, t4=0;
175
    cairo_int64_t t1y, t2y, t3x, t4x;
176
 
177
    cairo_fixed_t xlen, ylen;
178
 
179
    if (_cairo_box_contains_point (box, &line->p1) ||
180
        _cairo_box_contains_point (box, &line->p2))
181
        return TRUE;
182
 
183
    xlen = P2x - P1x;
184
    ylen = P2y - P1y;
185
 
186
    if (xlen) {
187
        if (xlen > 0) {
188
            t1 = B1x - P1x;
189
            t2 = B2x - P1x;
190
        } else {
191
            t1 = P1x - B2x;
192
            t2 = P1x - B1x;
193
            xlen = - xlen;
194
        }
195
 
196
        if ((t1 < 0 || t1 > xlen) &&
197
            (t2 < 0 || t2 > xlen))
198
            return FALSE;
199
    } else {
200
        /* Fully vertical line -- check that X is in bounds */
201
        if (P1x < B1x || P1x > B2x)
202
            return FALSE;
203
    }
204
 
205
    if (ylen) {
206
        if (ylen > 0) {
207
            t3 = B1y - P1y;
208
            t4 = B2y - P1y;
209
        } else {
210
            t3 = P1y - B2y;
211
            t4 = P1y - B1y;
212
            ylen = - ylen;
213
        }
214
 
215
        if ((t3 < 0 || t3 > ylen) &&
216
            (t4 < 0 || t4 > ylen))
217
            return FALSE;
218
    } else {
219
        /* Fully horizontal line -- check Y */
220
        if (P1y < B1y || P1y > B2y)
221
            return FALSE;
222
    }
223
 
224
    /* If we had a horizontal or vertical line, then it's already been checked */
225
    if (P1x == P2x || P1y == P2y)
226
        return TRUE;
227
 
228
    /* Check overlap.  Note that t1 < t2 and t3 < t4 here. */
229
    t1y = _cairo_int32x32_64_mul (t1, ylen);
230
    t2y = _cairo_int32x32_64_mul (t2, ylen);
231
    t3x = _cairo_int32x32_64_mul (t3, xlen);
232
    t4x = _cairo_int32x32_64_mul (t4, xlen);
233
 
234
    if (_cairo_int64_lt(t1y, t4x) &&
235
        _cairo_int64_lt(t3x, t2y))
236
        return TRUE;
237
 
238
    return FALSE;
239
}
240
 
241
cairo_bool_t
242
_cairo_box_contains_point (cairo_box_t *box, const cairo_point_t *point)
243
{
244
    if (point->x < box->p1.x || point->x > box->p2.x ||
245
        point->y < box->p1.y || point->y > box->p2.y)
246
        return FALSE;
247
    return TRUE;
248
}
249
 
250
void
251
_cairo_composite_rectangles_init(
252
        cairo_composite_rectangles_t    *rects,
253
        int                              all_x,
254
        int                              all_y,
255
        int                              width,
256
        int                              height)
257
{
258
        rects->src.x = all_x;
259
        rects->src.y = all_y;
260
        rects->mask.x = all_x;
261
        rects->mask.y = all_y;
262
        rects->clip.x = all_x;
263
        rects->clip.y = all_y;
264
        rects->dst.x = all_x;
265
        rects->dst.y = all_y;
266
 
267
        rects->width = width;
268
        rects->height = height;
269
}