Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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