LCOV - code coverage report
Current view: directory - gfx/cairo/cairo/src - cairo-fixed-private.h (source / functions) Found Hit Coverage
Test: app.info Lines: 68 14 20.6 %
Date: 2012-06-02 Functions: 19 6 31.6 %

       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                 : 
      44                 : /* Implementation */
      45                 : 
      46                 : #if (CAIRO_FIXED_BITS != 32)
      47                 : # error CAIRO_FIXED_BITS must be 32, and the type must be a 32-bit type.
      48                 : # error To remove this limitation, you will have to fix the tesselator.
      49                 : #endif
      50                 : 
      51                 : #define CAIRO_FIXED_ONE        ((cairo_fixed_t)(1 << CAIRO_FIXED_FRAC_BITS))
      52                 : #define CAIRO_FIXED_ONE_DOUBLE ((double)(1 << CAIRO_FIXED_FRAC_BITS))
      53                 : #define CAIRO_FIXED_ONE_FLOAT  ((float)(1 << CAIRO_FIXED_FRAC_BITS))
      54                 : #define CAIRO_FIXED_EPSILON    ((cairo_fixed_t)(1))
      55                 : 
      56                 : #define CAIRO_FIXED_FRAC_MASK  ((cairo_fixed_t)(((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS)))
      57                 : #define CAIRO_FIXED_WHOLE_MASK (~CAIRO_FIXED_FRAC_MASK)
      58                 : 
      59                 : static inline cairo_fixed_t
      60             340 : _cairo_fixed_from_int (int i)
      61                 : {
      62             340 :     return i << CAIRO_FIXED_FRAC_BITS;
      63                 : }
      64                 : 
      65                 : /* This is the "magic number" approach to converting a double into fixed
      66                 :  * point as described here:
      67                 :  *
      68                 :  * http://www.stereopsis.com/sree/fpu2006.html (an overview)
      69                 :  * http://www.d6.com/users/checker/pdfs/gdmfp.pdf (in detail)
      70                 :  *
      71                 :  * The basic idea is to add a large enough number to the double that the
      72                 :  * literal floating point is moved up to the extent that it forces the
      73                 :  * double's value to be shifted down to the bottom of the mantissa (to make
      74                 :  * room for the large number being added in). Since the mantissa is, at a
      75                 :  * given moment in time, a fixed point integer itself, one can convert a
      76                 :  * float to various fixed point representations by moving around the point
      77                 :  * of a floating point number through arithmetic operations. This behavior
      78                 :  * is reliable on most modern platforms as it is mandated by the IEEE-754
      79                 :  * standard for floating point arithmetic.
      80                 :  *
      81                 :  * For our purposes, a "magic number" must be carefully selected that is
      82                 :  * both large enough to produce the desired point-shifting effect, and also
      83                 :  * has no lower bits in its representation that would interfere with our
      84                 :  * value at the bottom of the mantissa. The magic number is calculated as
      85                 :  * follows:
      86                 :  *
      87                 :  *          (2 ^ (MANTISSA_SIZE - FRACTIONAL_SIZE)) * 1.5
      88                 :  *
      89                 :  * where in our case:
      90                 :  *  - MANTISSA_SIZE for 64-bit doubles is 52
      91                 :  *  - FRACTIONAL_SIZE for 16.16 fixed point is 16
      92                 :  *
      93                 :  * Although this approach provides a very large speedup of this function
      94                 :  * on a wide-array of systems, it does come with two caveats:
      95                 :  *
      96                 :  * 1) It uses banker's rounding as opposed to arithmetic rounding.
      97                 :  * 2) It doesn't function properly if the FPU is in single-precision
      98                 :  *    mode.
      99                 :  */
     100                 : 
     101                 : /* The 16.16 number must always be available */
     102                 : #define CAIRO_MAGIC_NUMBER_FIXED_16_16 (103079215104.0)
     103                 : 
     104                 : #if CAIRO_FIXED_BITS <= 32
     105                 : #define CAIRO_MAGIC_NUMBER_FIXED ((1LL << (52 - CAIRO_FIXED_FRAC_BITS)) * 1.5)
     106                 : 
     107                 : /* For 32-bit fixed point numbers */
     108                 : static inline cairo_fixed_t
     109             316 : _cairo_fixed_from_double (double d)
     110                 : {
     111                 :     union {
     112                 :         double d;
     113                 :         int32_t i[2];
     114                 :     } u;
     115                 : 
     116             316 :     u.d = d + CAIRO_MAGIC_NUMBER_FIXED;
     117                 : #ifdef FLOAT_WORDS_BIGENDIAN
     118                 :     return u.i[1];
     119                 : #else
     120             316 :     return u.i[0];
     121                 : #endif
     122                 : }
     123                 : 
     124                 : #else
     125                 : # error Please define a magic number for your fixed point type!
     126                 : # error See cairo-fixed-private.h for details.
     127                 : #endif
     128                 : 
     129                 : static inline cairo_fixed_t
     130               0 : _cairo_fixed_from_26_6 (uint32_t i)
     131                 : {
     132                 : #if CAIRO_FIXED_FRAC_BITS > 6
     133               0 :     return i << (CAIRO_FIXED_FRAC_BITS - 6);
     134                 : #else
     135                 :     return i >> (6 - CAIRO_FIXED_FRAC_BITS);
     136                 : #endif
     137                 : }
     138                 : 
     139                 : static inline cairo_fixed_t
     140                 : _cairo_fixed_from_16_16 (uint32_t i)
     141                 : {
     142                 : #if CAIRO_FIXED_FRAC_BITS > 16
     143                 :     return i << (CAIRO_FIXED_FRAC_BITS - 16);
     144                 : #else
     145                 :     return i >> (16 - CAIRO_FIXED_FRAC_BITS);
     146                 : #endif
     147                 : }
     148                 : 
     149                 : static inline double
     150               0 : _cairo_fixed_to_double (cairo_fixed_t f)
     151                 : {
     152               0 :     return ((double) f) / CAIRO_FIXED_ONE_DOUBLE;
     153                 : }
     154                 : 
     155                 : static inline float
     156                 : _cairo_fixed_to_float (cairo_fixed_t f)
     157                 : {
     158                 :     return ((float) f) / CAIRO_FIXED_ONE_FLOAT;
     159                 : }
     160                 : 
     161                 : static inline int
     162             614 : _cairo_fixed_is_integer (cairo_fixed_t f)
     163                 : {
     164             614 :     return (f & CAIRO_FIXED_FRAC_MASK) == 0;
     165                 : }
     166                 : 
     167                 : static inline cairo_fixed_t
     168               0 : _cairo_fixed_floor (cairo_fixed_t f)
     169                 : {
     170               0 :     return f & ~CAIRO_FIXED_FRAC_MASK;
     171                 : }
     172                 : 
     173                 : static inline cairo_fixed_t
     174                 : _cairo_fixed_round (cairo_fixed_t f)
     175                 : {
     176                 :     return _cairo_fixed_floor (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
     177                 : }
     178                 : 
     179                 : static inline cairo_fixed_t
     180               0 : _cairo_fixed_round_down (cairo_fixed_t f)
     181                 : {
     182               0 :     return _cairo_fixed_floor (f + CAIRO_FIXED_FRAC_MASK/2);
     183                 : }
     184                 : 
     185                 : static inline int
     186             256 : _cairo_fixed_integer_part (cairo_fixed_t f)
     187                 : {
     188             256 :     return f >> CAIRO_FIXED_FRAC_BITS;
     189                 : }
     190                 : 
     191                 : static inline int
     192                 : _cairo_fixed_integer_round (cairo_fixed_t f)
     193                 : {
     194                 :     return _cairo_fixed_integer_part (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
     195                 : }
     196                 : 
     197                 : static inline int
     198             256 : _cairo_fixed_integer_round_down (cairo_fixed_t f)
     199                 : {
     200             256 :     return _cairo_fixed_integer_part (f + CAIRO_FIXED_FRAC_MASK/2);
     201                 : }
     202                 : 
     203                 : static inline int
     204               0 : _cairo_fixed_fractional_part (cairo_fixed_t f)
     205                 : {
     206               0 :     return f & CAIRO_FIXED_FRAC_MASK;
     207                 : }
     208                 : 
     209                 : static inline int
     210               0 : _cairo_fixed_integer_floor (cairo_fixed_t f)
     211                 : {
     212               0 :     if (f >= 0)
     213               0 :         return f >> CAIRO_FIXED_FRAC_BITS;
     214                 :     else
     215               0 :         return -((-f - 1) >> CAIRO_FIXED_FRAC_BITS) - 1;
     216                 : }
     217                 : 
     218                 : static inline int
     219               0 : _cairo_fixed_integer_ceil (cairo_fixed_t f)
     220                 : {
     221               0 :     if (f > 0)
     222               0 :         return ((f - 1)>>CAIRO_FIXED_FRAC_BITS) + 1;
     223                 :     else
     224               0 :         return - (-f >> CAIRO_FIXED_FRAC_BITS);
     225                 : }
     226                 : 
     227                 : /* A bunch of explicit 16.16 operators; we need these
     228                 :  * to interface with pixman and other backends that require
     229                 :  * 16.16 fixed point types.
     230                 :  */
     231                 : static inline cairo_fixed_16_16_t
     232               0 : _cairo_fixed_to_16_16 (cairo_fixed_t f)
     233                 : {
     234                 : #if (CAIRO_FIXED_FRAC_BITS == 16) && (CAIRO_FIXED_BITS == 32)
     235                 :     return f;
     236                 : #elif CAIRO_FIXED_FRAC_BITS > 16
     237                 :     /* We're just dropping the low bits, so we won't ever got over/underflow here */
     238                 :     return f >> (CAIRO_FIXED_FRAC_BITS - 16);
     239                 : #else
     240                 :     cairo_fixed_16_16_t x;
     241                 : 
     242                 :     /* Handle overflow/underflow by clamping to the lowest/highest
     243                 :      * value representable as 16.16
     244                 :      */
     245               0 :     if ((f >> CAIRO_FIXED_FRAC_BITS) < INT16_MIN) {
     246               0 :         x = INT32_MIN;
     247               0 :     } else if ((f >> CAIRO_FIXED_FRAC_BITS) > INT16_MAX) {
     248               0 :         x = INT32_MAX;
     249                 :     } else {
     250               0 :         x = f << (16 - CAIRO_FIXED_FRAC_BITS);
     251                 :     }
     252                 : 
     253               0 :     return x;
     254                 : #endif
     255                 : }
     256                 : 
     257                 : static inline cairo_fixed_16_16_t
     258             100 : _cairo_fixed_16_16_from_double (double d)
     259                 : {
     260                 :     union {
     261                 :         double d;
     262                 :         int32_t i[2];
     263                 :     } u;
     264                 : 
     265             100 :     u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16;
     266                 : #ifdef FLOAT_WORDS_BIGENDIAN
     267                 :     return u.i[1];
     268                 : #else
     269             100 :     return u.i[0];
     270                 : #endif
     271                 : }
     272                 : 
     273                 : static inline int
     274               0 : _cairo_fixed_16_16_floor (cairo_fixed_16_16_t f)
     275                 : {
     276               0 :     if (f >= 0)
     277               0 :         return f >> 16;
     278                 :     else
     279               0 :         return -((-f - 1) >> 16) - 1;
     280                 : }
     281                 : 
     282                 : static inline double
     283                 : _cairo_fixed_16_16_to_double (cairo_fixed_16_16_t f)
     284                 : {
     285                 :     return ((double) f) / (double) (1 << 16);
     286                 : }
     287                 : 
     288                 : #if CAIRO_FIXED_BITS == 32
     289                 : 
     290                 : static inline cairo_fixed_t
     291               0 : _cairo_fixed_mul (cairo_fixed_t a, cairo_fixed_t b)
     292                 : {
     293               0 :     cairo_int64_t temp = _cairo_int32x32_64_mul (a, b);
     294               0 :     return _cairo_int64_to_int32(_cairo_int64_rsl (temp, CAIRO_FIXED_FRAC_BITS));
     295                 : }
     296                 : 
     297                 : /* computes round (a * b / c) */
     298                 : static inline cairo_fixed_t
     299                 : _cairo_fixed_mul_div (cairo_fixed_t a, cairo_fixed_t b, cairo_fixed_t c)
     300                 : {
     301                 :     cairo_int64_t ab  = _cairo_int32x32_64_mul (a, b);
     302                 :     cairo_int64_t c64 = _cairo_int32_to_int64 (c);
     303                 :     return _cairo_int64_to_int32 (_cairo_int64_divrem (ab, c64).quo);
     304                 : }
     305                 : 
     306                 : /* computes floor (a * b / c) */
     307                 : static inline cairo_fixed_t
     308               0 : _cairo_fixed_mul_div_floor (cairo_fixed_t a, cairo_fixed_t b, cairo_fixed_t c)
     309                 : {
     310               0 :     return _cairo_int64_32_div (_cairo_int32x32_64_mul (a, b), c);
     311                 : }
     312                 : 
     313                 : 
     314                 : static inline cairo_fixed_t
     315               0 : _cairo_edge_compute_intersection_y_for_x (const cairo_point_t *p1,
     316                 :                                           const cairo_point_t *p2,
     317                 :                                           cairo_fixed_t x)
     318                 : {
     319                 :     cairo_fixed_t y, dx;
     320                 : 
     321               0 :     if (x == p1->x)
     322               0 :         return p1->y;
     323               0 :     if (x == p2->x)
     324               0 :         return p2->y;
     325                 : 
     326               0 :     y = p1->y;
     327               0 :     dx = p2->x - p1->x;
     328               0 :     if (dx != 0)
     329               0 :         y += _cairo_fixed_mul_div_floor (x - p1->x, p2->y - p1->y, dx);
     330                 : 
     331               0 :     return y;
     332                 : }
     333                 : 
     334                 : static inline cairo_fixed_t
     335               0 : _cairo_edge_compute_intersection_x_for_y (const cairo_point_t *p1,
     336                 :                                           const cairo_point_t *p2,
     337                 :                                           cairo_fixed_t y)
     338                 : {
     339                 :     cairo_fixed_t x, dy;
     340                 : 
     341               0 :     if (y == p1->y)
     342               0 :         return p1->x;
     343               0 :     if (y == p2->y)
     344               0 :         return p2->x;
     345                 : 
     346               0 :     x = p1->x;
     347               0 :     dy = p2->y - p1->y;
     348               0 :     if (dy != 0)
     349               0 :         x += _cairo_fixed_mul_div_floor (y - p1->y, p2->x - p1->x, dy);
     350                 : 
     351               0 :     return x;
     352                 : }
     353                 : 
     354                 : #else
     355                 : # error Please define multiplication and other operands for your fixed-point type size
     356                 : #endif
     357                 : 
     358                 : #endif /* CAIRO_FIXED_PRIVATE_H */

Generated by: LCOV version 1.7