1544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin/************************************************************************** 2544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 3544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * Copyright 2009 VMware, Inc. All Rights Reserved. 4544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 5544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * Permission is hereby granted, free of charge, to any person obtaining a 6544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * copy of this software and associated documentation files (the 7544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * "Software"), to deal in the Software without restriction, including 8544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * without limitation the rights to use, copy, modify, merge, publish, 9544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * distribute, sub license, and/or sell copies of the Software, and to 10544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * permit persons to whom the Software is furnished to do so, subject to 11544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * the following conditions: 12544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 13544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * The above copyright notice and this permission notice (including the 14544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * next paragraph) shall be included in all copies or substantial portions 15544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * of the Software. 16544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 17544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 25544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin **************************************************************************/ 26544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 27544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "arc.h" 28544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 29544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "matrix.h" 30544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "bezier.h" 31544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "polygon.h" 32544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "stroker.h" 33544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "path.h" 34544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 35544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "util/u_debug.h" 36e5b5d84e8a87a5603a84f8c4625592a278bcf9afChia-I Wu#include "util/u_math.h" 37544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 38544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#ifndef M_PI 39544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#define M_PI 3.14159265358979323846 40544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 41544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 42544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#define DEBUG_ARCS 0 43544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 44544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic const VGfloat two_pi = M_PI * 2; 45544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 46544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 47544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic const double coeffs3Low[2][4][4] = { 48544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 49544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 3.85268, -21.229, -0.330434, 0.0127842 }, 50544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { -1.61486, 0.706564, 0.225945, 0.263682 }, 51544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { -0.910164, 0.388383, 0.00551445, 0.00671814 }, 52544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { -0.630184, 0.192402, 0.0098871, 0.0102527 } 53544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin }, 54544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 55544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { -0.162211, 9.94329, 0.13723, 0.0124084 }, 56544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { -0.253135, 0.00187735, 0.0230286, 0.01264 }, 57544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { -0.0695069, -0.0437594, 0.0120636, 0.0163087 }, 58544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { -0.0328856, -0.00926032, -0.00173573, 0.00527385 } 59544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 60544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin}; 61544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 62544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin/* coefficients for error estimation 63544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin while using cubic Bézier curves for approximation 64544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1/4 <= b/a <= 1 */ 65544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic const double coeffs3High[2][4][4] = { 66544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 67544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 0.0899116, -19.2349, -4.11711, 0.183362 }, 68544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 0.138148, -1.45804, 1.32044, 1.38474 }, 69544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 0.230903, -0.450262, 0.219963, 0.414038 }, 70544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 0.0590565, -0.101062, 0.0430592, 0.0204699 } 71544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin }, 72544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 73544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 0.0164649, 9.89394, 0.0919496, 0.00760802 }, 74544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 0.0191603, -0.0322058, 0.0134667, -0.0825018 }, 75544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 0.0156192, -0.017535, 0.00326508, -0.228157 }, 76544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { -0.0236752, 0.0405821, -0.0173086, 0.176187 } 77544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 78544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin}; 79544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 80544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin/* safety factor to convert the "best" error approximation 81544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin into a "max bound" error */ 82544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic const double safety3[] = { 83544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 0.001, 4.98, 0.207, 0.0067 84544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin}; 85544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 86544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin/* The code below is from the OpenVG 1.1 Spec 87544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * Section 18.4 */ 88544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 89544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin/* Given: Points (x0, y0) and (x1, y1) 90544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * Return: TRUE if a solution exists, FALSE otherwise 91544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * Circle centers are written to (cx0, cy0) and (cx1, cy1) 92544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin */ 93544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGboolean 94544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinfind_unit_circles(double x0, double y0, double x1, double y1, 95544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double *cx0, double *cy0, 96544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double *cx1, double *cy1) 97544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 98544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* Compute differences and averages */ 99544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double dx = x0 - x1; 100544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double dy = y0 - y1; 101544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double xm = (x0 + x1)/2; 102544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double ym = (y0 + y1)/2; 103544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double dsq, disc, s, sdx, sdy; 104544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 105544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* Solve for intersecting unit circles */ 106544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dsq = dx*dx + dy*dy; 107544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (dsq == 0.0) return VG_FALSE; /* Points are coincident */ 108544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin disc = 1.0/dsq - 1.0/4.0; 109544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 110544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* the precision we care about here is around float so if we're 111544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * around the float defined zero then make it official to avoid 112544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * precision problems later on */ 113544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatIsZero(disc)) 114544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin disc = 0.0; 115544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 116544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (disc < 0.0) return VG_FALSE; /* Points are too far apart */ 117544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin s = sqrt(disc); 118544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sdx = s*dx; 119544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sdy = s*dy; 120544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *cx0 = xm + sdy; 121544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *cy0 = ym - sdx; 122544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *cx1 = xm - sdy; 123544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *cy1 = ym + sdx; 124544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 125544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 126544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 127544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 128544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin/* Given: Ellipse parameters rh, rv, rot (in degrees), 129544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * endpoints (x0, y0) and (x1, y1) 130544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * Return: TRUE if a solution exists, FALSE otherwise 131544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * Ellipse centers are written to (cx0, cy0) and (cx1, cy1) 132544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin */ 133544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGboolean 134544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinfind_ellipses(double rh, double rv, double rot, 135544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double x0, double y0, double x1, double y1, 136544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double *cx0, double *cy0, double *cx1, double *cy1) 137544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 138544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double COS, SIN, x0p, y0p, x1p, y1p, pcx0, pcy0, pcx1, pcy1; 139544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* Convert rotation angle from degrees to radians */ 140544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rot *= M_PI/180.0; 141544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* Pre-compute rotation matrix entries */ 142544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin COS = cos(rot); SIN = sin(rot); 143544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* Transform (x0, y0) and (x1, y1) into unit space */ 144544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* using (inverse) rotate, followed by (inverse) scale */ 145544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0p = (x0*COS + y0*SIN)/rh; 146544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0p = (-x0*SIN + y0*COS)/rv; 147544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1p = (x1*COS + y1*SIN)/rh; 148544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1p = (-x1*SIN + y1*COS)/rv; 149544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!find_unit_circles(x0p, y0p, x1p, y1p, 150544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin &pcx0, &pcy0, &pcx1, &pcy1)) { 151544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_FALSE; 152544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 153544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* Transform back to original coordinate space */ 154544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* using (forward) scale followed by (forward) rotate */ 155544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pcx0 *= rh; pcy0 *= rv; 156544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pcx1 *= rh; pcy1 *= rv; 157544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *cx0 = pcx0*COS - pcy0*SIN; 158544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *cy0 = pcx0*SIN + pcy0*COS; 159544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *cx1 = pcx1*COS - pcy1*SIN; 160544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *cy1 = pcx1*SIN + pcy1*COS; 161544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 162544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 163544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 164544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGboolean 165544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusintry_to_fix_radii(struct arc *arc) 166544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 167544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double COS, SIN, rot, x0p, y0p, x1p, y1p; 168544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double dx, dy, dsq, scale; 169544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 170544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* Convert rotation angle from degrees to radians */ 171544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rot = DEGREES_TO_RADIANS(arc->theta); 172544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 173544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* Pre-compute rotation matrix entries */ 174544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin COS = cos(rot); SIN = sin(rot); 175544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 176544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* Transform (x0, y0) and (x1, y1) into unit space */ 177544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* using (inverse) rotate, followed by (inverse) scale */ 178544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0p = (arc->x1*COS + arc->y1*SIN)/arc->a; 179544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0p = (-arc->x1*SIN + arc->y1*COS)/arc->b; 180544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1p = (arc->x2*COS + arc->y2*SIN)/arc->a; 181544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1p = (-arc->x2*SIN + arc->y2*COS)/arc->b; 182544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* Compute differences and averages */ 183544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dx = x0p - x1p; 184544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dy = y0p - y1p; 185544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 186544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dsq = dx*dx + dy*dy; 187544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if 0 188544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (dsq <= 0.001) { 189544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaaa\n"); 190544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 191544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 192544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin scale = 1/(2/sqrt(dsq)); 193544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->a *= scale; 194544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->b *= scale; 195544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 196544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 197544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 198544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE double vector_normalize(double *v) 199544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 200544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double sq = v[0] * v[0] + v[1] * v[1]; 201544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return sqrt(sq); 202544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 203544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE double vector_orientation(double *v) 204544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 205544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double norm = vector_normalize(v); 206544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double cosa = v[0] / norm; 207544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double sina = v[1] / norm; 208544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return (sina>=0 ? acos(cosa) : 2*M_PI - acos(cosa)); 209544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 210544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE double vector_dot(double *v0, 211544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double *v1) 212544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 213544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return v0[0] * v1[0] + v0[1] * v1[1]; 214544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 215544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 216544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE double vector_angles(double *v0, 217544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double *v1) 218544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 219544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double dot = vector_dot(v0, v1); 220544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double norm0 = vector_normalize(v0); 221544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double norm1 = vector_normalize(v1); 222544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 223544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return acos(dot / (norm0 * norm1)); 224544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 225544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 226544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGboolean find_angles(struct arc *arc) 227544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 228544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double vec0[2], vec1[2]; 229544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double lambda1, lambda2; 230544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double angle; 231544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix matrix; 232544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 233544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatIsZero(arc->a) || floatIsZero(arc->b)) { 234544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_FALSE; 235544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 236544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* map the points to an identity circle */ 237544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_load_identity(&matrix); 238544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_scale(&matrix, 1.f, arc->a/arc->b); 239544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_rotate(&matrix, -arc->theta); 240544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(&matrix, 241544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->x1, arc->y1, 242544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin &arc->x1, &arc->y1); 243544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(&matrix, 244544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->x2, arc->y2, 245544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin &arc->x2, &arc->y2); 246544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(&matrix, 247544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->cx, arc->cy, 248544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin &arc->cx, &arc->cy); 249544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 250544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if DEBUG_ARCS 251544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("Matrix 3 [%f, %f, %f| %f, %f, %f| %f, %f, %f]\n", 252544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix.m[0], matrix.m[1], matrix.m[2], 253544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix.m[3], matrix.m[4], matrix.m[5], 254544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix.m[6], matrix.m[7], matrix.m[8]); 255544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("Endpoints [%f, %f], [%f, %f]\n", 256544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->x1, arc->y1, arc->x2, arc->y2); 257544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 258544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 259544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vec0[0] = arc->x1 - arc->cx; 260544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vec0[1] = arc->y1 - arc->cy; 261544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vec1[0] = arc->x2 - arc->cx; 262544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vec1[1] = arc->y2 - arc->cy; 263544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 264544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if DEBUG_ARCS 265544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("Vec is [%f, %f], [%f, %f], [%f, %f]\n", 266544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vec0[0], vec0[1], vec1[0], vec1[1], arc->cx, arc->cy); 267544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 268544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 269544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin lambda1 = vector_orientation(vec0); 270544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 271544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (isnan(lambda1)) 272544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin lambda1 = 0.f; 273544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 274544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (arc->type == VG_SCWARC_TO || 275544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->type == VG_SCCWARC_TO) 276544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin angle = vector_angles(vec0, vec1); 277544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else if (arc->type == VG_LCWARC_TO || 278544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->type == VG_LCCWARC_TO) { 279544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin angle = 2*M_PI - vector_angles(vec0, vec1); 280544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else 281544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin abort(); 282544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 283544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (isnan(angle)) 284544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin angle = M_PI; 285544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 286544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 287544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (arc->type == VG_SCWARC_TO || 288544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->type == VG_LCWARC_TO) 289544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin lambda2 = lambda1 - angle; 290544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else 291544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin lambda2 = lambda1 + angle; 292544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 293544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if DEBUG_ARCS 294544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("Angle is %f and (%f, %f)\n", angle, lambda1, lambda2); 295544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 296544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 297544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if 0 298544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->eta1 = atan2(sin(lambda1) / arc->b, 299544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cos(lambda1) / arc->a); 300544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->eta2 = atan2(sin(lambda2) / arc->b, 301544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cos(lambda2) / arc->a); 302544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 303544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* make sure we have eta1 <= eta2 <= eta1 + 2 PI */ 304544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->eta2 -= two_pi * floor((arc->eta2 - arc->eta1) / two_pi); 305544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 306544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* the preceding correction fails if we have exactly et2 - eta1 = 2 PI 307544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin it reduces the interval to zero length */ 308544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if ((lambda2 - lambda1 > M_PI) && (arc->eta2 - arc->eta1 < M_PI)) { 309544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->eta2 += 2 * M_PI; 310544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 311544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#else 312544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->eta1 = lambda1; 313544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->eta2 = lambda2; 314544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 315544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 316544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 317544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 318544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 319544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if DEBUG_ARCS 320544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void check_endpoints(struct arc *arc) 321544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 322544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double x1, y1, x2, y2; 323544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 324544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double a_cos_eta1 = arc->a * cos(arc->eta1); 325544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double b_sin_eta1 = arc->b * sin(arc->eta1); 326544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = arc->cx + a_cos_eta1 * arc->cos_theta - 327544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_sin_eta1 * arc->sin_theta; 328544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = arc->cy + a_cos_eta1 * arc->sin_theta + 329544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_sin_eta1 * arc->cos_theta; 330544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 331544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double a_cos_eta2 = arc->a * cos(arc->eta2); 332544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double b_sin_eta2 = arc->b * sin(arc->eta2); 333544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = arc->cx + a_cos_eta2 * arc->cos_theta - 334544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_sin_eta2 * arc->sin_theta; 335544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = arc->cy + a_cos_eta2 * arc->sin_theta + 336544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_sin_eta2 * arc->cos_theta; 337544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 338544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("Computed (%f, %f), (%f, %f)\n", 339544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1, y1, x2, y2); 340544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("Real (%f, %f), (%f, %f)\n", 341544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->x1, arc->y1, 342544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->x2, arc->y2); 343544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 344544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 345544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 346544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid arc_init(struct arc *arc, 347544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathSegment type, 348544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x1, VGfloat y1, 349544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x2, VGfloat y2, 350544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat rh, VGfloat rv, 351544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat rot) 352544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 353544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(type == VG_SCCWARC_TO || 354544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin type == VG_SCWARC_TO || 355544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin type == VG_LCCWARC_TO || 356544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin type == VG_LCWARC_TO); 357544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->type = type; 358544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->x1 = x1; 359544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->y1 = y1; 360544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->x2 = x2; 361544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->y2 = y2; 362544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->a = rh; 363544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->b = rv; 364544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->theta = rot; 365544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->cos_theta = cos(arc->theta); 366544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->sin_theta = sin(arc->theta); 367544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 368544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double cx0, cy0, cx1, cy1; 369544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double cx, cy; 370544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->is_valid = find_ellipses(rh, rv, rot, x1, y1, x2, y2, 371544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin &cx0, &cy0, &cx1, &cy1); 372544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 373544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!arc->is_valid && try_to_fix_radii(arc)) { 374544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rh = arc->a; 375544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rv = arc->b; 376544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->is_valid = 377544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin find_ellipses(rh, rv, rot, x1, y1, x2, y2, 378544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin &cx0, &cy0, &cx1, &cy1); 379544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 380544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 381544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (type == VG_SCWARC_TO || 382544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin type == VG_LCCWARC_TO) { 383544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cx = cx1; 384544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cy = cy1; 385544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 386544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cx = cx0; 387544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cy = cy0; 388544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 389544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if DEBUG_ARCS 390544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("Centers are : (%f, %f) , (%f, %f). Real (%f, %f)\n", 391544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cx0, cy0, cx1, cy1, cx, cy); 392544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 393544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->cx = cx; 394544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->cy = cy; 395544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (arc->is_valid) { 396544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->is_valid = find_angles(arc); 397544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if DEBUG_ARCS 398544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin check_endpoints(arc); 399544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 400544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* remap a few points. find_angles requires 401544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * rot in angles, the rest of the code 402544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * will need them in radians. and find_angles 403544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * modifies the center to match an identity 404544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * circle so lets reset it */ 405544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->theta = DEGREES_TO_RADIANS(rot); 406544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->cos_theta = cos(arc->theta); 407544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->sin_theta = sin(arc->theta); 408544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->cx = cx; 409544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc->cy = cy; 410544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 411544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 412544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 413544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 414544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE double rational_function(double x, const double *c) 415544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 416544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return (x * (x * c[0] + c[1]) + c[2]) / (x + c[3]); 417544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 418544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 419544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic double estimate_error(struct arc *arc, 420544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double etaA, double etaB) 421544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 422544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double eta = 0.5 * (etaA + etaB); 423544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 424544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double x = arc->b / arc->a; 425544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double dEta = etaB - etaA; 426544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double cos2 = cos(2 * eta); 427544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double cos4 = cos(4 * eta); 428544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double cos6 = cos(6 * eta); 429544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double c0, c1; 430544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 431544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* select the right coeficients set according to degree and b/a */ 432544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const double (*coeffs)[4][4]; 433544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const double *safety; 434544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coeffs = (x < 0.25) ? coeffs3Low : coeffs3High; 435544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin safety = safety3; 436544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 437544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin c0 = rational_function(x, coeffs[0][0]) 438544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin + cos2 * rational_function(x, coeffs[0][1]) 439544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin + cos4 * rational_function(x, coeffs[0][2]) 440544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin + cos6 * rational_function(x, coeffs[0][3]); 441544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 442544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin c1 = rational_function(x, coeffs[1][0]) 443544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin + cos2 * rational_function(x, coeffs[1][1]) 444544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin + cos4 * rational_function(x, coeffs[1][2]) 445544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin + cos6 * rational_function(x, coeffs[1][3]); 446544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 447544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return rational_function(x, safety) * arc->a * exp(c0 + c1 * dEta); 448544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 449544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 450544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstruct arc_cb { 451544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void (*move)(struct arc_cb *cb, VGfloat x, VGfloat y); 452544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void (*point)(struct arc_cb *cb, VGfloat x, VGfloat y); 453544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void (*bezier)(struct arc_cb *cb, struct bezier *bezier); 454544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 455544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *user_data; 456544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin}; 457544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 458544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void cb_null_move(struct arc_cb *cb, VGfloat x, VGfloat y) 459544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 460544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 461544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 462544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void polygon_point(struct arc_cb *cb, VGfloat x, VGfloat y) 463544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 464544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct polygon *poly = (struct polygon*)cb->user_data; 465544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_vertex_append(poly, x, y); 466544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 467544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 468544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void polygon_bezier(struct arc_cb *cb, struct bezier *bezier) 469544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 470544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct polygon *poly = (struct polygon*)cb->user_data; 471544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_add_to_polygon(bezier, poly); 472544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 473544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 474544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_point(struct arc_cb *cb, VGfloat x, VGfloat y) 475544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 476544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroker *stroker = (struct stroker*)cb->user_data; 477544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to(stroker, x, y); 478544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 479544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 480544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_curve(struct arc_cb *cb, struct bezier *bezier) 481544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 482544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroker *stroker = (struct stroker*)cb->user_data; 483544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_curve_to(stroker, 484544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier->x2, bezier->y2, 485544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier->x3, bezier->y3, 486544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier->x4, bezier->y4); 487544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 488544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 489544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_emit_point(struct arc_cb *cb, VGfloat x, VGfloat y) 490544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 491544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroker *stroker = (struct stroker*)cb->user_data; 492544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, x, y); 493544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 494544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 495544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_emit_curve(struct arc_cb *cb, struct bezier *bezier) 496544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 497544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroker *stroker = (struct stroker*)cb->user_data; 498544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_curve_to(stroker, 499544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier->x2, bezier->y2, 500544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier->x3, bezier->y3, 501544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier->x4, bezier->y4); 502544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 503544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 504544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void arc_path_move(struct arc_cb *cb, VGfloat x, VGfloat y) 505544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 506544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path = (struct path*)cb->user_data; 507544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_move_to(path, x, y); 508544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 509544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 510544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void arc_path_point(struct arc_cb *cb, VGfloat x, VGfloat y) 511544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 512544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path = (struct path*)cb->user_data; 513544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_line_to(path, x, y); 514544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 515544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 516544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void arc_path_bezier(struct arc_cb *cb, struct bezier *bezier) 517544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 518544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path = (struct path*)cb->user_data; 519544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_cubic_to(path, 520544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier->x2, bezier->y2, 521544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier->x3, bezier->y3, 522544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier->x4, bezier->y4); 523544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 524544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 525544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE int num_beziers_needed(struct arc *arc) 526544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 527544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double threshold = 0.05; 528544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean found = VG_FALSE; 529544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin int n = 1; 530544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double min_eta, max_eta; 531544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 532544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin min_eta = MIN2(arc->eta1, arc->eta2); 533544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin max_eta = MAX2(arc->eta1, arc->eta2); 534544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 535544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin while ((! found) && (n < 1024)) { 536544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double d_eta = (max_eta - min_eta) / n; 537544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (d_eta <= 0.5 * M_PI) { 538544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double eta_b = min_eta; 53915ecd0337e4e4d9d33449bdff014a634e368c7d6Vinson Lee int i; 540544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin found = VG_TRUE; 541910b58039a3980d9857380cf367bdbe2395d791fAlan Hourihane for (i = 0; found && (i < n); ++i) { 542544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double etaA = eta_b; 543544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin eta_b += d_eta; 544544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin found = (estimate_error(arc, etaA, eta_b) <= threshold); 545544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 546544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 547544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin n = n << 1; 548544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 549544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 550544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return n; 551544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 552544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 553544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void arc_to_beziers(struct arc *arc, 554544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc_cb cb, 555544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix *matrix) 556544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 557910b58039a3980d9857380cf367bdbe2395d791fAlan Hourihane int i; 558544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin int n = 1; 559544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double d_eta, eta_b, cos_eta_b, 560544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sin_eta_b, a_cos_eta_b, b_sin_eta_b, a_sin_eta_b, 561544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_cos_eta_b, x_b, y_b, x_b_dot, y_b_dot, lx, ly; 562544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double t, alpha; 563544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 564544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { /* always move to the start of the arc */ 565544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x = arc->x1; 566544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat y = arc->y1; 567544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x, y, &x, &y); 568544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.move(&cb, x, y); 569544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 570544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 571544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!arc->is_valid) { 572544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x = arc->x2; 573544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat y = arc->y2; 574544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x, y, &x, &y); 575544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.point(&cb, x, y); 576544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 577544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 578544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 579544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* find the number of Bézier curves needed */ 580544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin n = num_beziers_needed(arc); 581544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 582544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin d_eta = (arc->eta2 - arc->eta1) / n; 583544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin eta_b = arc->eta1; 584544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 585544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cos_eta_b = cos(eta_b); 586544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sin_eta_b = sin(eta_b); 587544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin a_cos_eta_b = arc->a * cos_eta_b; 588544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_sin_eta_b = arc->b * sin_eta_b; 589544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin a_sin_eta_b = arc->a * sin_eta_b; 590544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_cos_eta_b = arc->b * cos_eta_b; 591544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x_b = arc->cx + a_cos_eta_b * arc->cos_theta - 592544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_sin_eta_b * arc->sin_theta; 593544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y_b = arc->cy + a_cos_eta_b * arc->sin_theta + 594544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_sin_eta_b * arc->cos_theta; 595544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x_b_dot = -a_sin_eta_b * arc->cos_theta - 596544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_cos_eta_b * arc->sin_theta; 597544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y_b_dot = -a_sin_eta_b * arc->sin_theta + 598544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_cos_eta_b * arc->cos_theta; 599544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 600544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 601544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x = x_b, y = y_b; 602544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x, y, &x, &y); 603544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.point(&cb, x, y); 604544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 605544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin lx = x_b; 606544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ly = y_b; 607544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 608544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin t = tan(0.5 * d_eta); 609544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin alpha = sin(d_eta) * (sqrt(4 + 3 * t * t) - 1) / 3; 610544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 611910b58039a3980d9857380cf367bdbe2395d791fAlan Hourihane for (i = 0; i < n; ++i) { 612544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 613544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double xA = x_b; 614544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double yA = y_b; 615544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double xADot = x_b_dot; 616544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin double yADot = y_b_dot; 617544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 618544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin eta_b += d_eta; 619544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cos_eta_b = cos(eta_b); 620544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sin_eta_b = sin(eta_b); 621544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin a_cos_eta_b = arc->a * cos_eta_b; 622544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_sin_eta_b = arc->b * sin_eta_b; 623544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin a_sin_eta_b = arc->a * sin_eta_b; 624544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_cos_eta_b = arc->b * cos_eta_b; 625544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x_b = arc->cx + a_cos_eta_b * arc->cos_theta - 626544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_sin_eta_b * arc->sin_theta; 627544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y_b = arc->cy + a_cos_eta_b * arc->sin_theta + 628544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_sin_eta_b * arc->cos_theta; 629544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x_b_dot = -a_sin_eta_b * arc->cos_theta - 630544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_cos_eta_b * arc->sin_theta; 631544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y_b_dot = -a_sin_eta_b * arc->sin_theta + 632544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b_cos_eta_b * arc->cos_theta; 633544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 634544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, 635544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin lx, ly, 636544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (float) (xA + alpha * xADot), (float) (yA + alpha * yADot), 637544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (float) (x_b - alpha * x_b_dot), (float) (y_b - alpha * y_b_dot), 638544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (float) x_b, (float) y_b); 639544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if 0 640544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("%d) Bezier (%f, %f), (%f, %f), (%f, %f), (%f, %f)\n", 641544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin i, 642544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier.x1, bezier.y1, 643544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier.x2, bezier.y2, 644544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier.x3, bezier.y3, 645544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier.x4, bezier.y4); 646544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 647544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_transform(&bezier, matrix); 648544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.bezier(&cb, &bezier); 649544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin lx = x_b; 650544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ly = y_b; 651544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 652544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 653544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 654544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 655544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid arc_add_to_polygon(struct arc *arc, 656544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct polygon *poly, 657544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix *matrix) 658544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 659544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc_cb cb; 660544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 661544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.move = cb_null_move; 662544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.point = polygon_point; 663544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.bezier = polygon_bezier; 664544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.user_data = poly; 665544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 666544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_to_beziers(arc, cb, matrix); 667544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 668544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 669544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid arc_stroke_cb(struct arc *arc, 670544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroker *stroke, 671544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix *matrix) 672544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 673544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc_cb cb; 674544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 675544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.move = cb_null_move; 676544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.point = stroke_point; 677544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.bezier = stroke_curve; 678544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.user_data = stroke; 679544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 680544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_to_beziers(arc, cb, matrix); 681544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 682544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 683544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid arc_stroker_emit(struct arc *arc, 684544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroker *stroker, 685544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix *matrix) 686544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 687544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc_cb cb; 688544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 689544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.move = cb_null_move; 690544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.point = stroke_emit_point; 691544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.bezier = stroke_emit_curve; 692544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.user_data = stroker; 693544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 694544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_to_beziers(arc, cb, matrix); 695544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 696544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 697544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid arc_to_path(struct arc *arc, 698544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path, 699544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix *matrix) 700544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 701544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc_cb cb; 702544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 703544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.move = arc_path_move; 704544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.point = arc_path_point; 705544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.bezier = arc_path_bezier; 706544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb.user_data = path; 707544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 708544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_to_beziers(arc, cb, matrix); 709544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 710