mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-08 09:08:16 +02:00
[fixpt] Make fixed point methods static inline and generic
Move the fixed point methods to static inline versions in cairo-fixed-private.h, and don't hardcode fixed to be 16.16.
This commit is contained in:
parent
76c32f899a
commit
0048a26a44
4 changed files with 259 additions and 136 deletions
256
src/cairo-fixed-private.h
Normal file
256
src/cairo-fixed-private.h
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2007 Mozilla Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_FIXED_PRIVATE_H
|
||||
#define CAIRO_FIXED_PRIVATE_H
|
||||
|
||||
#include "cairo-wideint-private.h"
|
||||
|
||||
/*
|
||||
* Fixed-point configuration
|
||||
*/
|
||||
|
||||
typedef int32_t cairo_fixed_16_16_t;
|
||||
typedef cairo_int64_t cairo_fixed_32_32_t;
|
||||
typedef cairo_int64_t cairo_fixed_48_16_t;
|
||||
typedef cairo_int128_t cairo_fixed_64_64_t;
|
||||
typedef cairo_int128_t cairo_fixed_96_32_t;
|
||||
|
||||
/* Eventually, we should allow changing this, but I think
|
||||
* there are some assumptions in the tesselator about the
|
||||
* size of a fixed type.
|
||||
*/
|
||||
#define CAIRO_FIXED_BITS 32
|
||||
|
||||
/* The number of fractional bits. Changing this involves
|
||||
* making sure that you compute a double-to-fixed magic number.
|
||||
* (see below).
|
||||
*/
|
||||
#define CAIRO_FIXED_FRAC_BITS 16
|
||||
|
||||
/* A signed type CAIRO_FIXED_BITS in size; the main fixed point type */
|
||||
typedef int32_t cairo_fixed_t;
|
||||
|
||||
/* An unsigned type of the same size as cairo_fixed_t */
|
||||
typedef uint32_t cairo_fixed_unsigned_t;
|
||||
|
||||
/*
|
||||
* No configurable bits below this.
|
||||
*/
|
||||
|
||||
|
||||
#if (CAIRO_FIXED_BITS != 32)
|
||||
# error CAIRO_FIXED_BITS must be 32, and the type must be a 32-bit type.
|
||||
# error To remove this limitation, you will have to fix the tesselator.
|
||||
#endif
|
||||
|
||||
#define CAIRO_FIXED_ONE ((cairo_fixed_t)(1 << CAIRO_FIXED_FRAC_BITS))
|
||||
#define CAIRO_FIXED_ONE_DOUBLE ((double)(1 << CAIRO_FIXED_FRAC_BITS))
|
||||
#define CAIRO_FIXED_EPSILON ((cairo_fixed_t)(1))
|
||||
|
||||
#define CAIRO_FIXED_FRAC_MASK (((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS))
|
||||
#define CAIRO_FIXED_WHOLE_MASK (~CAIRO_FIXED_FRAC_MASK)
|
||||
|
||||
static inline cairo_fixed_t
|
||||
_cairo_fixed_from_int (int i)
|
||||
{
|
||||
return i << CAIRO_FIXED_FRAC_BITS;
|
||||
}
|
||||
|
||||
/* This is the "magic number" approach to converting a double into fixed
|
||||
* point as described here:
|
||||
*
|
||||
* http://www.stereopsis.com/sree/fpu2006.html (an overview)
|
||||
* http://www.d6.com/users/checker/pdfs/gdmfp.pdf (in detail)
|
||||
*
|
||||
* The basic idea is to add a large enough number to the double that the
|
||||
* literal floating point is moved up to the extent that it forces the
|
||||
* double's value to be shifted down to the bottom of the mantissa (to make
|
||||
* room for the large number being added in). Since the mantissa is, at a
|
||||
* given moment in time, a fixed point integer itself, one can convert a
|
||||
* float to various fixed point representations by moving around the point
|
||||
* of a floating point number through arithmetic operations. This behavior
|
||||
* is reliable on most modern platforms as it is mandated by the IEEE-754
|
||||
* standard for floating point arithmetic.
|
||||
*
|
||||
* For our purposes, a "magic number" must be carefully selected that is
|
||||
* both large enough to produce the desired point-shifting effect, and also
|
||||
* has no lower bits in its representation that would interfere with our
|
||||
* value at the bottom of the mantissa. The magic number is calculated as
|
||||
* follows:
|
||||
*
|
||||
* (2 ^ (MANTISSA_SIZE - FRACTIONAL_SIZE)) * 1.5
|
||||
*
|
||||
* where in our case:
|
||||
* - MANTISSA_SIZE for 64-bit doubles is 52
|
||||
* - FRACTIONAL_SIZE for 16.16 fixed point is 16
|
||||
*
|
||||
* Although this approach provides a very large speedup of this function
|
||||
* on a wide-array of systems, it does come with two caveats:
|
||||
*
|
||||
* 1) It uses banker's rounding as opposed to arithmetic rounding.
|
||||
* 2) It doesn't function properly if the FPU is in single-precision
|
||||
* mode.
|
||||
*/
|
||||
|
||||
/* The 16.16 number must always be available */
|
||||
#define CAIRO_MAGIC_NUMBER_FIXED_16_16 (103079215104.0)
|
||||
|
||||
#if CAIRO_FIXED_BITS == 32
|
||||
|
||||
# if CAIRO_FIXED_FRAC_BITS == 16
|
||||
# define CAIRO_MAGIC_NUMBER_FIXED CAIRO_MAGIC_NUMBER_FIXED_16_16
|
||||
# elif CAIRO_FIXED_FRAC_BITS == 8
|
||||
# define CAIRO_MAGIC_NUMBER_FIXED (26388279066624.0)
|
||||
# elif CAIRO_FIXED_FRAC_BITS == 6
|
||||
# define CAIRO_MAGIC_NUMBER_FIXED (105553116266496.0)
|
||||
# else
|
||||
# error Please define a magic number for your fixed point type!
|
||||
# error See cairo-fixed-private.h for details.
|
||||
# endif
|
||||
|
||||
/* For 32-bit fixed point numbers */
|
||||
static inline cairo_fixed_t
|
||||
_cairo_fixed_from_double (double d)
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
int32_t i[2];
|
||||
} u;
|
||||
|
||||
u.d = d + CAIRO_MAGIC_NUMBER_FIXED;
|
||||
#ifdef FLOAT_WORDS_BIGENDIAN
|
||||
return u.i[1];
|
||||
#else
|
||||
return u.i[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
# error Please define a magic number for your fixed point type!
|
||||
# error See cairo-fixed-private.h for details.
|
||||
#endif
|
||||
|
||||
static inline cairo_fixed_t
|
||||
_cairo_fixed_from_26_6 (uint32_t i)
|
||||
{
|
||||
#if CAIRO_FIXED_FRAC_BITS > 6
|
||||
return i << (CAIRO_FIXED_FRAC_BITS - 6);
|
||||
#else
|
||||
return i >> (6 - CAIRO_FIXED_FRAC_BITS);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline double
|
||||
_cairo_fixed_to_double (cairo_fixed_t f)
|
||||
{
|
||||
return ((double) f) / CAIRO_FIXED_ONE_DOUBLE;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_cairo_fixed_is_integer (cairo_fixed_t f)
|
||||
{
|
||||
return (f & CAIRO_FIXED_FRAC_MASK) == 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_cairo_fixed_integer_part (cairo_fixed_t f)
|
||||
{
|
||||
return f >> CAIRO_FIXED_FRAC_BITS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_cairo_fixed_integer_floor (cairo_fixed_t f)
|
||||
{
|
||||
if (f >= 0)
|
||||
return f >> CAIRO_FIXED_FRAC_BITS;
|
||||
else
|
||||
return -((-f - 1) >> CAIRO_FIXED_FRAC_BITS) - 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_cairo_fixed_integer_ceil (cairo_fixed_t f)
|
||||
{
|
||||
if (f > 0)
|
||||
return ((f - 1)>>CAIRO_FIXED_FRAC_BITS) + 1;
|
||||
else
|
||||
return - (-f >> CAIRO_FIXED_FRAC_BITS);
|
||||
}
|
||||
|
||||
/* A bunch of explicit 16.16 operators; we need these
|
||||
* to interface with pixman and other backends that require
|
||||
* 16.16 fixed point types.
|
||||
*/
|
||||
static inline cairo_fixed_16_16_t
|
||||
_cairo_fixed_to_16_16 (cairo_fixed_t f)
|
||||
{
|
||||
#if CAIRO_FIXED_FRAC_BITS > 16
|
||||
return f >> (CAIRO_FIXED_FRAC_BITS - 16);
|
||||
#else
|
||||
return f << (16 - CAIRO_FIXED_FRAC_BITS);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline cairo_fixed_16_16_t
|
||||
_cairo_fixed_16_16_from_double (double d)
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
int32_t i[2];
|
||||
} u;
|
||||
|
||||
u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16;
|
||||
#ifdef FLOAT_WORDS_BIGENDIAN
|
||||
return u.i[1];
|
||||
#else
|
||||
return u.i[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CAIRO_FIXED_BITS == 32
|
||||
|
||||
static inline cairo_fixed_t
|
||||
_cairo_fixed_mul (cairo_fixed_t a, cairo_fixed_t b)
|
||||
{
|
||||
cairo_int64_t temp = _cairo_int32x32_64_mul (a, b);
|
||||
return _cairo_int64_to_int32(_cairo_int64_rsl (temp, CAIRO_FIXED_FRAC_BITS));
|
||||
}
|
||||
|
||||
#else
|
||||
# error Please define multiplication and other operands for your fixed-point type size
|
||||
#endif
|
||||
|
||||
#endif /* CAIRO_FIXED_PRIVATE_H */
|
||||
|
|
@ -36,102 +36,4 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
cairo_fixed_t
|
||||
_cairo_fixed_from_int (int i)
|
||||
{
|
||||
return i << 16;
|
||||
}
|
||||
|
||||
/* This is the "magic number" approach to converting a double into fixed
|
||||
* point as described here:
|
||||
*
|
||||
* http://www.stereopsis.com/sree/fpu2006.html (an overview)
|
||||
* http://www.d6.com/users/checker/pdfs/gdmfp.pdf (in detail)
|
||||
*
|
||||
* The basic idea is to add a large enough number to the double that the
|
||||
* literal floating point is moved up to the extent that it forces the
|
||||
* double's value to be shifted down to the bottom of the mantissa (to make
|
||||
* room for the large number being added in). Since the mantissa is, at a
|
||||
* given moment in time, a fixed point integer itself, one can convert a
|
||||
* float to various fixed point representations by moving around the point
|
||||
* of a floating point number through arithmetic operations. This behavior
|
||||
* is reliable on most modern platforms as it is mandated by the IEEE-754
|
||||
* standard for floating point arithmetic.
|
||||
*
|
||||
* For our purposes, a "magic number" must be carefully selected that is
|
||||
* both large enough to produce the desired point-shifting effect, and also
|
||||
* has no lower bits in its representation that would interfere with our
|
||||
* value at the bottom of the mantissa. The magic number is calculated as
|
||||
* follows:
|
||||
*
|
||||
* (2 ^ (MANTISSA_SIZE - FRACTIONAL_SIZE)) * 1.5
|
||||
*
|
||||
* where in our case:
|
||||
* - MANTISSA_SIZE for 64-bit doubles is 52
|
||||
* - FRACTIONAL_SIZE for 16.16 fixed point is 16
|
||||
*
|
||||
* Although this approach provides a very large speedup of this function
|
||||
* on a wide-array of systems, it does come with two caveats:
|
||||
*
|
||||
* 1) It uses banker's rounding as opposed to arithmetic rounding.
|
||||
* 2) It doesn't function properly if the FPU is in single-precision
|
||||
* mode.
|
||||
*/
|
||||
#define CAIRO_MAGIC_NUMBER_FIXED_16_16 (103079215104.0)
|
||||
cairo_fixed_t
|
||||
_cairo_fixed_from_double (double d)
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
int32_t i[2];
|
||||
} u;
|
||||
|
||||
u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16;
|
||||
#ifdef FLOAT_WORDS_BIGENDIAN
|
||||
return u.i[1];
|
||||
#else
|
||||
return u.i[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
cairo_fixed_t
|
||||
_cairo_fixed_from_26_6 (uint32_t i)
|
||||
{
|
||||
return i << 10;
|
||||
}
|
||||
|
||||
double
|
||||
_cairo_fixed_to_double (cairo_fixed_t f)
|
||||
{
|
||||
return ((double) f) / 65536.0;
|
||||
}
|
||||
|
||||
int
|
||||
_cairo_fixed_is_integer (cairo_fixed_t f)
|
||||
{
|
||||
return (f & 0xFFFF) == 0;
|
||||
}
|
||||
|
||||
int
|
||||
_cairo_fixed_integer_part (cairo_fixed_t f)
|
||||
{
|
||||
return f >> 16;
|
||||
}
|
||||
|
||||
int
|
||||
_cairo_fixed_integer_floor (cairo_fixed_t f)
|
||||
{
|
||||
if (f >= 0)
|
||||
return f >> 16;
|
||||
else
|
||||
return -((-f - 1) >> 16) - 1;
|
||||
}
|
||||
|
||||
int
|
||||
_cairo_fixed_integer_ceil (cairo_fixed_t f)
|
||||
{
|
||||
if (f > 0)
|
||||
return ((f - 1)>>16) + 1;
|
||||
else
|
||||
return - (-f >> 16);
|
||||
}
|
||||
#include "cairo-fixed-private.h"
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ static void
|
|||
ComputeGradientValue (void *info, const float *in, float *out)
|
||||
{
|
||||
float fdist = *in; /* 0.0 .. 1.0 */
|
||||
cairo_fixed_16_16_t fdist_fix = _cairo_fixed_from_double(*in);
|
||||
cairo_fixed_t fdist_fix = _cairo_fixed_from_double(*in);
|
||||
cairo_gradient_pattern_t *grad = (cairo_gradient_pattern_t*) info;
|
||||
unsigned int i;
|
||||
|
||||
|
|
|
|||
|
|
@ -182,15 +182,7 @@ do { \
|
|||
#include "cairo-mutex-private.h"
|
||||
#include "cairo-wideint-private.h"
|
||||
#include "cairo-malloc-private.h"
|
||||
|
||||
typedef int32_t cairo_fixed_16_16_t;
|
||||
typedef cairo_int64_t cairo_fixed_32_32_t;
|
||||
typedef cairo_int64_t cairo_fixed_48_16_t;
|
||||
typedef cairo_int128_t cairo_fixed_64_64_t;
|
||||
typedef cairo_int128_t cairo_fixed_96_32_t;
|
||||
|
||||
/* The common 16.16 format gets a shorter name */
|
||||
typedef cairo_fixed_16_16_t cairo_fixed_t;
|
||||
#include "cairo-fixed-private.h"
|
||||
|
||||
#define CAIRO_ALPHA_IS_OPAQUE(alpha) ((alpha) >= ((double)0xff00 / (double)0xffff))
|
||||
#define CAIRO_ALPHA_SHORT_IS_OPAQUE(alpha) ((alpha) >= 0xff00)
|
||||
|
|
@ -1114,33 +1106,6 @@ _cairo_restrict_value (double *value, double min, double max);
|
|||
cairo_private int
|
||||
_cairo_lround (double d);
|
||||
|
||||
/* cairo_fixed.c */
|
||||
cairo_private cairo_fixed_t
|
||||
_cairo_fixed_from_int (int i);
|
||||
|
||||
#define CAIRO_FIXED_ONE _cairo_fixed_from_int (1)
|
||||
|
||||
cairo_private cairo_fixed_t
|
||||
_cairo_fixed_from_double (double d);
|
||||
|
||||
cairo_private cairo_fixed_t
|
||||
_cairo_fixed_from_26_6 (uint32_t i);
|
||||
|
||||
cairo_private double
|
||||
_cairo_fixed_to_double (cairo_fixed_t f);
|
||||
|
||||
cairo_private int
|
||||
_cairo_fixed_is_integer (cairo_fixed_t f);
|
||||
|
||||
cairo_private int
|
||||
_cairo_fixed_integer_part (cairo_fixed_t f);
|
||||
|
||||
cairo_private int
|
||||
_cairo_fixed_integer_floor (cairo_fixed_t f);
|
||||
|
||||
cairo_private int
|
||||
_cairo_fixed_integer_ceil (cairo_fixed_t f);
|
||||
|
||||
/* cairo_gstate.c */
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_init (cairo_gstate_t *gstate,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue