LCOV - code coverage report
Current view: top level - gfx/cairo/cairo/src - cairo-fixed-private.h (source / functions) Hit Total Coverage
Test: output.info Lines: 3 68 4.4 %
Date: 2017-07-14 16:53:18 Functions: 1 19 5.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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           0 : _cairo_fixed_from_int (int i)
      61             : {
      62           0 :     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         528 : _cairo_fixed_from_double (double d)
     110             : {
     111             :     union {
     112             :         double d;
     113             :         int32_t i[2];
     114             :     } u;
     115             : 
     116         528 :     u.d = d + CAIRO_MAGIC_NUMBER_FIXED;
     117             : #ifdef FLOAT_WORDS_BIGENDIAN
     118             :     return u.i[1];
     119             : #else
     120         528 :     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           0 : _cairo_fixed_is_integer (cairo_fixed_t f)
     163             : {
     164           0 :     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           0 : _cairo_fixed_integer_part (cairo_fixed_t f)
     187             : {
     188           0 :     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           0 : _cairo_fixed_integer_round_down (cairo_fixed_t f)
     199             : {
     200           0 :     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           0 : _cairo_fixed_16_16_from_double (double d)
     259             : {
     260             :     union {
     261             :         double d;
     262             :         int32_t i[2];
     263             :     } u;
     264             : 
     265           0 :     u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16;
     266             : #ifdef FLOAT_WORDS_BIGENDIAN
     267             :     return u.i[1];
     268             : #else
     269           0 :     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.13