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 © 2007 Mozilla 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 Mozilla Foundation
32
 *
33
 * Contributor(s):
34
 *	Vladimir Vukicevic <vladimir@pobox.com>
35
 */
36

            
37
#ifndef CAIRO_FIXED_PRIVATE_H
38
#define CAIRO_FIXED_PRIVATE_H
39

            
40
#include "cairo-fixed-type-private.h"
41

            
42
#include "cairo-wideint-private.h"
43
#include "cairoint.h"
44

            
45
/* Implementation */
46

            
47
#if (CAIRO_FIXED_BITS != 32)
48
# error CAIRO_FIXED_BITS must be 32, and the type must be a 32-bit type.
49
# error To remove this limitation, you will have to fix the tessellator.
50
#endif
51

            
52
#define CAIRO_FIXED_ONE        ((cairo_fixed_t)(1 << CAIRO_FIXED_FRAC_BITS))
53
#define CAIRO_FIXED_ONE_DOUBLE ((double)(1 << CAIRO_FIXED_FRAC_BITS))
54
#define CAIRO_FIXED_EPSILON    ((cairo_fixed_t)(1))
55

            
56
#define CAIRO_FIXED_MAX        INT32_MAX /* Maximum fixed point value */
57
#define CAIRO_FIXED_MIN        INT32_MIN /* Minimum fixed point value */
58
#define CAIRO_FIXED_MAX_DOUBLE (((double) CAIRO_FIXED_MAX) / CAIRO_FIXED_ONE_DOUBLE)
59
#define CAIRO_FIXED_MIN_DOUBLE (((double) CAIRO_FIXED_MIN) / CAIRO_FIXED_ONE_DOUBLE)
60

            
61
#define CAIRO_FIXED_ERROR_DOUBLE (1. / (2 * CAIRO_FIXED_ONE_DOUBLE))
62

            
63
#define CAIRO_FIXED_FRAC_MASK  ((cairo_fixed_t)(((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS)))
64
#define CAIRO_FIXED_WHOLE_MASK (~CAIRO_FIXED_FRAC_MASK)
65

            
66
static inline cairo_fixed_t
67
14387202
_cairo_fixed_from_int (int i)
68
{
69
14387202
    return (cairo_fixed_unsigned_t)i << CAIRO_FIXED_FRAC_BITS;
70
}
71

            
72
/* This is the "magic number" approach to converting a double into fixed
73
 * point as described here:
74
 *
75
 * http://www.stereopsis.com/sree/fpu2006.html (an overview)
76
 * http://www.d6.com/users/checker/pdfs/gdmfp.pdf (in detail)
77
 *
78
 * The basic idea is to add a large enough number to the double that the
79
 * literal floating point is moved up to the extent that it forces the
80
 * double's value to be shifted down to the bottom of the mantissa (to make
81
 * room for the large number being added in). Since the mantissa is, at a
82
 * given moment in time, a fixed point integer itself, one can convert a
83
 * float to various fixed point representations by moving around the point
84
 * of a floating point number through arithmetic operations. This behavior
85
 * is reliable on most modern platforms as it is mandated by the IEEE-754
86
 * standard for floating point arithmetic.
87
 *
88
 * For our purposes, a "magic number" must be carefully selected that is
89
 * both large enough to produce the desired point-shifting effect, and also
90
 * has no lower bits in its representation that would interfere with our
91
 * value at the bottom of the mantissa. The magic number is calculated as
92
 * follows:
93
 *
94
 *          (2 ^ (MANTISSA_SIZE - FRACTIONAL_SIZE)) * 1.5
95
 *
96
 * where in our case:
97
 *  - MANTISSA_SIZE for 64-bit doubles is 52
98
 *  - FRACTIONAL_SIZE for 16.16 fixed point is 16
99
 *
100
 * Although this approach provides a very large speedup of this function
101
 * on a wide-array of systems, it does come with two caveats:
102
 *
103
 * 1) It uses banker's rounding as opposed to arithmetic rounding.
104
 * 2) It doesn't function properly if the FPU is in single-precision
105
 *    mode.
106
 */
107

            
108
/* The 16.16 number must always be available */
109
#define CAIRO_MAGIC_NUMBER_FIXED_16_16 (103079215104.0)
110

            
111
#if CAIRO_FIXED_BITS <= 32
112
#define CAIRO_MAGIC_NUMBER_FIXED ((1LL << (52 - CAIRO_FIXED_FRAC_BITS)) * 1.5)
113

            
114
/* For 32-bit fixed point numbers */
115
static inline cairo_fixed_t
116
229439195
_cairo_fixed_from_double (double d)
117
{
118
    union {
119
        double d;
120
        int32_t i[2];
121
    } u;
122

            
123
229439195
    u.d = d + CAIRO_MAGIC_NUMBER_FIXED;
124
#ifdef FLOAT_WORDS_BIGENDIAN
125
    return u.i[1];
126
#else
127
229439195
    return u.i[0];
128
#endif
129
}
130

            
131
#else
132
# error Please define a magic number for your fixed point type!
133
# error See cairo-fixed-private.h for details.
134
#endif
135

            
136
static inline cairo_fixed_t
137
60571114
_cairo_fixed_from_double_clamped (double d, double tolerance)
138
{
139
60571114
    if (d > CAIRO_FIXED_MAX_DOUBLE - tolerance)
140
15
       d = CAIRO_FIXED_MAX_DOUBLE - tolerance;
141
60571099
    else if (d < CAIRO_FIXED_MIN_DOUBLE + tolerance)
142
9
       d = CAIRO_FIXED_MIN_DOUBLE + tolerance;
143

            
144
60571114
    return _cairo_fixed_from_double (d);
145
}
146

            
147
static inline cairo_fixed_t
148
18810
_cairo_fixed_from_26_6 (uint32_t i)
149
{
150
#if CAIRO_FIXED_FRAC_BITS > 6
151
18810
    return i << (CAIRO_FIXED_FRAC_BITS - 6);
152
#else
153
    return i >> (6 - CAIRO_FIXED_FRAC_BITS);
154
#endif
155
}
156

            
157
static inline cairo_fixed_t
158
_cairo_fixed_from_16_16 (uint32_t i)
159
{
160
#if CAIRO_FIXED_FRAC_BITS > 16
161
    return i << (CAIRO_FIXED_FRAC_BITS - 16);
162
#else
163
    return i >> (16 - CAIRO_FIXED_FRAC_BITS);
164
#endif
165
}
166

            
167
static inline double
168
17640436
_cairo_fixed_to_double (cairo_fixed_t f)
169
{
170
17640436
    return ((double) f) / CAIRO_FIXED_ONE_DOUBLE;
171
}
172

            
173
static inline int
174
7651420
_cairo_fixed_is_integer (cairo_fixed_t f)
175
{
176
7651420
    return (f & CAIRO_FIXED_FRAC_MASK) == 0;
177
}
178

            
179
static inline cairo_fixed_t
180
1002960
_cairo_fixed_floor (cairo_fixed_t f)
181
{
182
1002960
    return f & ~CAIRO_FIXED_FRAC_MASK;
183
}
184

            
185
static inline cairo_fixed_t
186
288
_cairo_fixed_ceil (cairo_fixed_t f)
187
{
188
288
    return _cairo_fixed_floor (f + CAIRO_FIXED_FRAC_MASK);
189
}
190

            
191
static inline cairo_fixed_t
192
_cairo_fixed_round (cairo_fixed_t f)
193
{
194
    return _cairo_fixed_floor (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
195
}
196

            
197
static inline cairo_fixed_t
198
1002384
_cairo_fixed_round_down (cairo_fixed_t f)
199
{
200
1002384
    return _cairo_fixed_floor (f + CAIRO_FIXED_FRAC_MASK/2);
201
}
202

            
203
static inline int
204
4328997
_cairo_fixed_integer_part (cairo_fixed_t f)
205
{
206
4328997
    return f >> CAIRO_FIXED_FRAC_BITS;
207
}
208

            
209
static inline int
210
_cairo_fixed_integer_round (cairo_fixed_t f)
211
{
212
    return _cairo_fixed_integer_part (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
213
}
214

            
215
static inline int
216
1035198
_cairo_fixed_integer_round_down (cairo_fixed_t f)
217
{
218
1035198
    return _cairo_fixed_integer_part (f + CAIRO_FIXED_FRAC_MASK/2);
219
}
220

            
221
static inline int
222
251238
_cairo_fixed_fractional_part (cairo_fixed_t f)
223
{
224
251238
    return f & CAIRO_FIXED_FRAC_MASK;
225
}
226

            
227
static inline int
228
78187903
_cairo_fixed_integer_floor (cairo_fixed_t f)
229
{
230
78187903
    if (f >= 0)
231
52423439
        return f >> CAIRO_FIXED_FRAC_BITS;
232
    else
233
25764464
        return -((-f - 1) >> CAIRO_FIXED_FRAC_BITS) - 1;
234
}
235

            
236
static inline int
237
5236706
_cairo_fixed_integer_ceil (cairo_fixed_t f)
238
{
239
5236706
    if (f > 0)
240
4835956
	return ((f - 1)>>CAIRO_FIXED_FRAC_BITS) + 1;
241
    else
242
400750
	return - ((cairo_fixed_t)(-(cairo_fixed_unsigned_t)f) >> CAIRO_FIXED_FRAC_BITS);
243
}
244

            
245
/* A bunch of explicit 16.16 operators; we need these
246
 * to interface with pixman and other backends that require
247
 * 16.16 fixed point types.
248
 */
249
static inline cairo_fixed_16_16_t
250
69540
_cairo_fixed_to_16_16 (cairo_fixed_t f)
251
{
252
#if (CAIRO_FIXED_FRAC_BITS == 16) && (CAIRO_FIXED_BITS == 32)
253
    return f;
254
#elif CAIRO_FIXED_FRAC_BITS > 16
255
    /* We're just dropping the low bits, so we won't ever got over/underflow here */
256
    return f >> (CAIRO_FIXED_FRAC_BITS - 16);
257
#else
258
    cairo_fixed_16_16_t x;
259

            
260
    /* Handle overflow/underflow by clamping to the lowest/highest
261
     * value representable as 16.16
262
     */
263
69540
    if ((f >> CAIRO_FIXED_FRAC_BITS) < INT16_MIN) {
264
	x = INT32_MIN;
265
69540
    } else if ((f >> CAIRO_FIXED_FRAC_BITS) > INT16_MAX) {
266
	x = INT32_MAX;
267
    } else {
268
69540
	x = f << (16 - CAIRO_FIXED_FRAC_BITS);
269
    }
270

            
271
69540
    return x;
272
#endif
273
}
274

            
275
static inline cairo_fixed_16_16_t
276
4262436
_cairo_fixed_16_16_from_double (double d)
277
{
278
    union {
279
        double d;
280
        int32_t i[2];
281
    } u;
282

            
283
4262436
    u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16;
284
#ifdef FLOAT_WORDS_BIGENDIAN
285
    return u.i[1];
286
#else
287
4262436
    return u.i[0];
288
#endif
289
}
290

            
291
static inline int
292
_cairo_fixed_16_16_floor (cairo_fixed_16_16_t f)
293
{
294
    if (f >= 0)
295
	return f >> 16;
296
    else
297
	return -((-f - 1) >> 16) - 1;
298
}
299

            
300
static inline double
301
_cairo_fixed_16_16_to_double (cairo_fixed_16_16_t f)
302
{
303
    return ((double) f) / (double) (1 << 16);
304
}
305

            
306
#if CAIRO_FIXED_BITS == 32
307

            
308
static inline cairo_fixed_t
309
1090092
_cairo_fixed_mul (cairo_fixed_t a, cairo_fixed_t b)
310
{
311
1090092
    cairo_int64_t temp = _cairo_int32x32_64_mul (a, b);
312
1090092
    return _cairo_int64_to_int32(_cairo_int64_rsl (temp, CAIRO_FIXED_FRAC_BITS));
313
}
314

            
315
/* computes round (a * b / c) */
316
static inline cairo_fixed_t
317
_cairo_fixed_mul_div (cairo_fixed_t a, cairo_fixed_t b, cairo_fixed_t c)
318
{
319
    cairo_int64_t ab  = _cairo_int32x32_64_mul (a, b);
320
    cairo_int64_t c64 = _cairo_int32_to_int64 (c);
321
    return _cairo_int64_to_int32 (_cairo_int64_divrem (ab, c64).quo);
322
}
323

            
324
/* computes floor (a * b / c) */
325
static inline cairo_fixed_t
326
716663
_cairo_fixed_mul_div_floor (cairo_fixed_t a, cairo_fixed_t b, cairo_fixed_t c)
327
{
328
716663
    return _cairo_int64_32_div (_cairo_int32x32_64_mul (a, b), c);
329
}
330

            
331
/* compute y from x so that (x,y), p1, and p2 are collinear */
332
static inline cairo_fixed_t
333
233305
_cairo_edge_compute_intersection_y_for_x (const cairo_point_t *p1,
334
					  const cairo_point_t *p2,
335
					  cairo_fixed_t x)
336
{
337
    cairo_fixed_t y, dx;
338

            
339
233305
    if (x == p1->x)
340
	return p1->y;
341
233305
    if (x == p2->x)
342
	return p2->y;
343

            
344
233305
    y = p1->y;
345
233305
    dx = p2->x - p1->x;
346
233305
    if (dx != 0)
347
233305
	y += _cairo_fixed_mul_div_floor (x - p1->x, p2->y - p1->y, dx);
348

            
349
233305
    return y;
350
}
351

            
352
/* compute x from y so that (x,y), p1, and p2 are collinear */
353
static inline cairo_fixed_t
354
418381
_cairo_edge_compute_intersection_x_for_y (const cairo_point_t *p1,
355
					  const cairo_point_t *p2,
356
					  cairo_fixed_t y)
357
{
358
    cairo_fixed_t x, dy;
359

            
360
418381
    if (y == p1->y)
361
46293
	return p1->x;
362
372088
    if (y == p2->y)
363
	return p2->x;
364

            
365
372088
    x = p1->x;
366
372088
    dy = p2->y - p1->y;
367
372088
    if (dy != 0)
368
372088
	x += _cairo_fixed_mul_div_floor (y - p1->y, p2->x - p1->x, dy);
369

            
370
372088
    return x;
371
}
372

            
373
/* Intersect two segments based on the algorithm described at
374
 * http://paulbourke.net/geometry/pointlineplane/. This implementation
375
 * uses floating point math. */
376
static inline cairo_bool_t
377
_slow_segment_intersection (const cairo_point_t *seg1_p1,
378
			    const cairo_point_t *seg1_p2,
379
			    const cairo_point_t *seg2_p1,
380
			    const cairo_point_t *seg2_p2,
381
			    cairo_point_t *intersection)
382
{
383
    double denominator, u_a, u_b;
384
    double seg1_dx, seg1_dy, seg2_dx, seg2_dy, seg_start_dx, seg_start_dy;
385

            
386
    seg1_dx = _cairo_fixed_to_double (seg1_p2->x - seg1_p1->x);
387
    seg1_dy = _cairo_fixed_to_double (seg1_p2->y - seg1_p1->y);
388
    seg2_dx = _cairo_fixed_to_double (seg2_p2->x - seg2_p1->x);
389
    seg2_dy = _cairo_fixed_to_double (seg2_p2->y - seg2_p1->y);
390
    denominator = (seg2_dy * seg1_dx) - (seg2_dx * seg1_dy);
391
    if (denominator == 0)
392
	return FALSE;
393

            
394
    seg_start_dx = _cairo_fixed_to_double (seg1_p1->x - seg2_p1->x);
395
    seg_start_dy = _cairo_fixed_to_double (seg1_p1->y - seg2_p1->y);
396
    u_a = ((seg2_dx * seg_start_dy) - (seg2_dy * seg_start_dx)) / denominator;
397
    u_b = ((seg1_dx * seg_start_dy) - (seg1_dy * seg_start_dx)) / denominator;
398

            
399
    if (u_a <= 0 || u_a >= 1 || u_b <= 0 || u_b >= 1)
400
	return FALSE;
401

            
402
    intersection->x = seg1_p1->x + _cairo_fixed_from_double ((u_a * seg1_dx));
403
    intersection->y = seg1_p1->y + _cairo_fixed_from_double ((u_a * seg1_dy));
404
    return TRUE;
405
}
406

            
407
#else
408
# error Please define multiplication and other operands for your fixed-point type size
409
#endif
410

            
411
#endif /* CAIRO_FIXED_PRIVATE_H */