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
4
* Copyright © 2007 Mozilla Corporation
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
* You should have received a copy of the MPL along with this library
18
* in the file COPYING-MPL-1.1
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/
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.
29
* The Original Code is the cairo graphics library.
31
* The Initial Developer of the Original Code is Mozilla Corporation
34
* Vladimir Vukicevic <vladimir@pobox.com>
37
#ifndef CAIRO_FIXED_PRIVATE_H
38
#define CAIRO_FIXED_PRIVATE_H
40
#include "cairo-wideint-private.h"
43
* Fixed-point configuration
46
typedef int32_t cairo_fixed_16_16_t;
47
typedef cairo_int64_t cairo_fixed_32_32_t;
48
typedef cairo_int64_t cairo_fixed_48_16_t;
49
typedef cairo_int128_t cairo_fixed_64_64_t;
50
typedef cairo_int128_t cairo_fixed_96_32_t;
52
/* Eventually, we should allow changing this, but I think
53
* there are some assumptions in the tesselator about the
54
* size of a fixed type. For now, it must be 32.
56
#define CAIRO_FIXED_BITS 32
58
/* The number of fractional bits. Changing this involves
59
* making sure that you compute a double-to-fixed magic number.
62
#define CAIRO_FIXED_FRAC_BITS 8
64
/* A signed type CAIRO_FIXED_BITS in size; the main fixed point type */
65
typedef int32_t cairo_fixed_t;
67
/* An unsigned type of the same size as cairo_fixed_t */
68
typedef uint32_t cairo_fixed_unsigned_t;
71
* No configurable bits below this.
74
#if (CAIRO_FIXED_BITS != 32)
75
# error CAIRO_FIXED_BITS must be 32, and the type must be a 32-bit type.
76
# error To remove this limitation, you will have to fix the tesselator.
79
#define CAIRO_FIXED_ONE ((cairo_fixed_t)(1 << CAIRO_FIXED_FRAC_BITS))
80
#define CAIRO_FIXED_ONE_DOUBLE ((double)(1 << CAIRO_FIXED_FRAC_BITS))
81
#define CAIRO_FIXED_EPSILON ((cairo_fixed_t)(1))
83
#define CAIRO_FIXED_FRAC_MASK (((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS))
84
#define CAIRO_FIXED_WHOLE_MASK (~CAIRO_FIXED_FRAC_MASK)
86
static inline cairo_fixed_t
87
_cairo_fixed_from_int (int i)
89
return i << CAIRO_FIXED_FRAC_BITS;
92
/* This is the "magic number" approach to converting a double into fixed
93
* point as described here:
95
* http://www.stereopsis.com/sree/fpu2006.html (an overview)
96
* http://www.d6.com/users/checker/pdfs/gdmfp.pdf (in detail)
98
* The basic idea is to add a large enough number to the double that the
99
* literal floating point is moved up to the extent that it forces the
100
* double's value to be shifted down to the bottom of the mantissa (to make
101
* room for the large number being added in). Since the mantissa is, at a
102
* given moment in time, a fixed point integer itself, one can convert a
103
* float to various fixed point representations by moving around the point
104
* of a floating point number through arithmetic operations. This behavior
105
* is reliable on most modern platforms as it is mandated by the IEEE-754
106
* standard for floating point arithmetic.
108
* For our purposes, a "magic number" must be carefully selected that is
109
* both large enough to produce the desired point-shifting effect, and also
110
* has no lower bits in its representation that would interfere with our
111
* value at the bottom of the mantissa. The magic number is calculated as
114
* (2 ^ (MANTISSA_SIZE - FRACTIONAL_SIZE)) * 1.5
117
* - MANTISSA_SIZE for 64-bit doubles is 52
118
* - FRACTIONAL_SIZE for 16.16 fixed point is 16
120
* Although this approach provides a very large speedup of this function
121
* on a wide-array of systems, it does come with two caveats:
123
* 1) It uses banker's rounding as opposed to arithmetic rounding.
124
* 2) It doesn't function properly if the FPU is in single-precision
128
/* The 16.16 number must always be available */
129
#define CAIRO_MAGIC_NUMBER_FIXED_16_16 (103079215104.0)
131
#if CAIRO_FIXED_BITS <= 32
132
#define CAIRO_MAGIC_NUMBER_FIXED ((1LL << (52 - CAIRO_FIXED_FRAC_BITS)) * 1.5)
134
/* For 32-bit fixed point numbers */
135
static inline cairo_fixed_t
136
_cairo_fixed_from_double (double d)
143
u.d = d + CAIRO_MAGIC_NUMBER_FIXED;
144
#ifdef FLOAT_WORDS_BIGENDIAN
152
# error Please define a magic number for your fixed point type!
153
# error See cairo-fixed-private.h for details.
156
static inline cairo_fixed_t
157
_cairo_fixed_from_26_6 (uint32_t i)
159
#if CAIRO_FIXED_FRAC_BITS > 6
160
return i << (CAIRO_FIXED_FRAC_BITS - 6);
162
return i >> (6 - CAIRO_FIXED_FRAC_BITS);
167
_cairo_fixed_to_double (cairo_fixed_t f)
169
return ((double) f) / CAIRO_FIXED_ONE_DOUBLE;
173
_cairo_fixed_is_integer (cairo_fixed_t f)
175
return (f & CAIRO_FIXED_FRAC_MASK) == 0;
179
_cairo_fixed_integer_part (cairo_fixed_t f)
181
return f >> CAIRO_FIXED_FRAC_BITS;
185
_cairo_fixed_integer_floor (cairo_fixed_t f)
188
return f >> CAIRO_FIXED_FRAC_BITS;
190
return -((-f - 1) >> CAIRO_FIXED_FRAC_BITS) - 1;
194
_cairo_fixed_integer_ceil (cairo_fixed_t f)
197
return ((f - 1)>>CAIRO_FIXED_FRAC_BITS) + 1;
199
return - (-f >> CAIRO_FIXED_FRAC_BITS);
202
/* A bunch of explicit 16.16 operators; we need these
203
* to interface with pixman and other backends that require
204
* 16.16 fixed point types.
206
static inline cairo_fixed_16_16_t
207
_cairo_fixed_to_16_16 (cairo_fixed_t f)
209
#if (CAIRO_FIXED_FRAC_BITS == 16) && (CAIRO_FIXED_BITS == 32)
211
#elif CAIRO_FIXED_FRAC_BITS > 16
212
/* We're just dropping the low bits, so we won't ever got over/underflow here */
213
return f >> (CAIRO_FIXED_FRAC_BITS - 16);
215
cairo_fixed_16_16_t x;
217
/* Handle overflow/underflow by claping to the lowest/highest
218
* value representable as 16.16
220
if ((f >> CAIRO_FIXED_FRAC_BITS) < INT16_MIN) {
222
} else if ((f >> CAIRO_FIXED_FRAC_BITS) > INT16_MAX) {
225
x = f << (16 - CAIRO_FIXED_FRAC_BITS);
232
static inline cairo_fixed_16_16_t
233
_cairo_fixed_16_16_from_double (double d)
240
u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16;
241
#ifdef FLOAT_WORDS_BIGENDIAN
248
#if CAIRO_FIXED_BITS == 32
250
static inline cairo_fixed_t
251
_cairo_fixed_mul (cairo_fixed_t a, cairo_fixed_t b)
253
cairo_int64_t temp = _cairo_int32x32_64_mul (a, b);
254
return _cairo_int64_to_int32(_cairo_int64_rsl (temp, CAIRO_FIXED_FRAC_BITS));
258
# error Please define multiplication and other operands for your fixed-point type size
261
#endif /* CAIRO_FIXED_PRIVATE_H */