13a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org/************************************************************************** 23a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * 33a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * Copyright 2009 VMware, Inc. All Rights Reserved. 43a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * 53a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a 63a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * copy of this software and associated documentation files (the 73a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * "Software"), to deal in the Software without restriction, including 83a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * without limitation the rights to use, copy, modify, merge, publish, 93a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * distribute, sub license, and/or sell copies of the Software, and to 103a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * permit persons to whom the Software is furnished to do so, subject to 113a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * the following conditions: 123a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * 133a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * The above copyright notice and this permission notice (including the 143a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * next paragraph) shall be included in all copies or substantial portions 153a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * of the Software. 163a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * 173a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 183a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 193a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 203a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 213a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 223a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 233a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 243a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * 253a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org **************************************************************************/ 263a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 273a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#include "arc.h" 283a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 293a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#include "matrix.h" 303a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#include "bezier.h" 313a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#include "polygon.h" 323a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#include "stroker.h" 333a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#include "path.h" 343a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 353a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#include "util/u_debug.h" 36760fd893ba809a7a5daa25c2749ff502f7186e83kbr@chromium.org#include "util/u_math.h" 373a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 383a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#ifndef M_PI 393a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#define M_PI 3.14159265358979323846 403a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#endif 413a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 423a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#define DEBUG_ARCS 0 433a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 443a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic const VGfloat two_pi = M_PI * 2; 453a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 463a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 473a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic const double coeffs3Low[2][4][4] = { 483a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 493a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 3.85268, -21.229, -0.330434, 0.0127842 }, 503a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { -1.61486, 0.706564, 0.225945, 0.263682 }, 513a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { -0.910164, 0.388383, 0.00551445, 0.00671814 }, 523a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { -0.630184, 0.192402, 0.0098871, 0.0102527 } 533a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org }, 543a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 553a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { -0.162211, 9.94329, 0.13723, 0.0124084 }, 563a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { -0.253135, 0.00187735, 0.0230286, 0.01264 }, 573a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { -0.0695069, -0.0437594, 0.0120636, 0.0163087 }, 583a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { -0.0328856, -0.00926032, -0.00173573, 0.00527385 } 593a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 603a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org}; 613a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 623a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org/* coefficients for error estimation 633a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org while using cubic Bézier curves for approximation 643a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1/4 <= b/a <= 1 */ 653a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic const double coeffs3High[2][4][4] = { 663a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 673a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 0.0899116, -19.2349, -4.11711, 0.183362 }, 683a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 0.138148, -1.45804, 1.32044, 1.38474 }, 693a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 0.230903, -0.450262, 0.219963, 0.414038 }, 703a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 0.0590565, -0.101062, 0.0430592, 0.0204699 } 713a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org }, 723a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 733a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 0.0164649, 9.89394, 0.0919496, 0.00760802 }, 743a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 0.0191603, -0.0322058, 0.0134667, -0.0825018 }, 753a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 0.0156192, -0.017535, 0.00326508, -0.228157 }, 763a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { -0.0236752, 0.0405821, -0.0173086, 0.176187 } 773a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 783a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org}; 793a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 803a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org/* safety factor to convert the "best" error approximation 813a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org into a "max bound" error */ 823a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic const double safety3[] = { 833a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 0.001, 4.98, 0.207, 0.0067 843a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org}; 853a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 863a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org/* The code below is from the OpenVG 1.1 Spec 873a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * Section 18.4 */ 883a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 893a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org/* Given: Points (x0, y0) and (x1, y1) 903a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * Return: TRUE if a solution exists, FALSE otherwise 913a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * Circle centers are written to (cx0, cy0) and (cx1, cy1) 923a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org */ 933a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic VGboolean 943a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgfind_unit_circles(double x0, double y0, double x1, double y1, 953a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double *cx0, double *cy0, 963a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double *cx1, double *cy1) 973a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 983a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* Compute differences and averages */ 993a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double dx = x0 - x1; 1003a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double dy = y0 - y1; 1013a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double xm = (x0 + x1)/2; 1023a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double ym = (y0 + y1)/2; 1033a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double dsq, disc, s, sdx, sdy; 1043a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1053a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* Solve for intersecting unit circles */ 1063a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org dsq = dx*dx + dy*dy; 1073a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (dsq == 0.0) return VG_FALSE; /* Points are coincident */ 1083a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org disc = 1.0/dsq - 1.0/4.0; 1093a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1103a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* the precision we care about here is around float so if we're 1113a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * around the float defined zero then make it official to avoid 1123a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * precision problems later on */ 1133a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (floatIsZero(disc)) 1143a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org disc = 0.0; 1153a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1163a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (disc < 0.0) return VG_FALSE; /* Points are too far apart */ 1173a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org s = sqrt(disc); 1183a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org sdx = s*dx; 1193a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org sdy = s*dy; 1203a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org *cx0 = xm + sdy; 1213a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org *cy0 = ym - sdx; 1223a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org *cx1 = xm - sdy; 1233a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org *cy1 = ym + sdx; 1243a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return VG_TRUE; 1253a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 1263a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1273a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1283a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org/* Given: Ellipse parameters rh, rv, rot (in degrees), 1293a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * endpoints (x0, y0) and (x1, y1) 1303a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * Return: TRUE if a solution exists, FALSE otherwise 1313a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * Ellipse centers are written to (cx0, cy0) and (cx1, cy1) 1323a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org */ 1333a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic VGboolean 1343a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgfind_ellipses(double rh, double rv, double rot, 1353a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double x0, double y0, double x1, double y1, 1363a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double *cx0, double *cy0, double *cx1, double *cy1) 1373a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 1383a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double COS, SIN, x0p, y0p, x1p, y1p, pcx0, pcy0, pcx1, pcy1; 1393a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* Convert rotation angle from degrees to radians */ 1403a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org rot *= M_PI/180.0; 1413a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* Pre-compute rotation matrix entries */ 1423a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org COS = cos(rot); SIN = sin(rot); 1433a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* Transform (x0, y0) and (x1, y1) into unit space */ 1443a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* using (inverse) rotate, followed by (inverse) scale */ 1453a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x0p = (x0*COS + y0*SIN)/rh; 1463a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org y0p = (-x0*SIN + y0*COS)/rv; 1473a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x1p = (x1*COS + y1*SIN)/rh; 1483a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org y1p = (-x1*SIN + y1*COS)/rv; 1493a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (!find_unit_circles(x0p, y0p, x1p, y1p, 1503a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org &pcx0, &pcy0, &pcx1, &pcy1)) { 1513a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return VG_FALSE; 1523a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 1533a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* Transform back to original coordinate space */ 1543a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* using (forward) scale followed by (forward) rotate */ 1553a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org pcx0 *= rh; pcy0 *= rv; 1563a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org pcx1 *= rh; pcy1 *= rv; 1573a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org *cx0 = pcx0*COS - pcy0*SIN; 1583a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org *cy0 = pcx0*SIN + pcy0*COS; 1593a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org *cx1 = pcx1*COS - pcy1*SIN; 1603a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org *cy1 = pcx1*SIN + pcy1*COS; 1613a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return VG_TRUE; 1623a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 1633a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1643a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic INLINE VGboolean 1653a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgtry_to_fix_radii(struct arc *arc) 1663a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 1673a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double COS, SIN, rot, x0p, y0p, x1p, y1p; 1683a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double dx, dy, dsq, scale; 1693a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1703a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* Convert rotation angle from degrees to radians */ 1713a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org rot = DEGREES_TO_RADIANS(arc->theta); 1723a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1733a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* Pre-compute rotation matrix entries */ 1743a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org COS = cos(rot); SIN = sin(rot); 1753a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1763a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* Transform (x0, y0) and (x1, y1) into unit space */ 1773a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* using (inverse) rotate, followed by (inverse) scale */ 1783a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x0p = (arc->x1*COS + arc->y1*SIN)/arc->a; 1793a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org y0p = (-arc->x1*SIN + arc->y1*COS)/arc->b; 1803a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x1p = (arc->x2*COS + arc->y2*SIN)/arc->a; 1813a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org y1p = (-arc->x2*SIN + arc->y2*COS)/arc->b; 1823a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* Compute differences and averages */ 1833a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org dx = x0p - x1p; 1843a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org dy = y0p - y1p; 1853a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1863a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org dsq = dx*dx + dy*dy; 1873a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#if 0 1883a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (dsq <= 0.001) { 1893a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org debug_printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaaa\n"); 1903a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 1913a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#endif 1923a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org scale = 1/(2/sqrt(dsq)); 1933a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->a *= scale; 1943a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->b *= scale; 1953a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return VG_TRUE; 1963a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 1973a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 1983a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic INLINE double vector_normalize(double *v) 1993a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 2003a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double sq = v[0] * v[0] + v[1] * v[1]; 2013a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return sqrt(sq); 2023a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 2033a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic INLINE double vector_orientation(double *v) 2043a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 2053a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double norm = vector_normalize(v); 2063a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double cosa = v[0] / norm; 2073a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double sina = v[1] / norm; 2083a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return (sina>=0 ? acos(cosa) : 2*M_PI - acos(cosa)); 2093a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 2103a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic INLINE double vector_dot(double *v0, 2113a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double *v1) 2123a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 2133a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return v0[0] * v1[0] + v0[1] * v1[1]; 2143a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 2153a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2163a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic INLINE double vector_angles(double *v0, 2173a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double *v1) 2183a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 2193a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double dot = vector_dot(v0, v1); 2203a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double norm0 = vector_normalize(v0); 2213a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double norm1 = vector_normalize(v1); 2223a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2233a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return acos(dot / (norm0 * norm1)); 2243a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 2253a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2263a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic VGboolean find_angles(struct arc *arc) 2273a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 2283a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double vec0[2], vec1[2]; 2293a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double lambda1, lambda2; 2303a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double angle; 2313a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct matrix matrix; 2323a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2333a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (floatIsZero(arc->a) || floatIsZero(arc->b)) { 2343a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return VG_FALSE; 2353a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 2363a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* map the points to an identity circle */ 2373a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix_load_identity(&matrix); 2383a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix_scale(&matrix, 1.f, arc->a/arc->b); 2393a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix_rotate(&matrix, -arc->theta); 2403a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix_map_point(&matrix, 2413a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->x1, arc->y1, 2423a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org &arc->x1, &arc->y1); 2433a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix_map_point(&matrix, 2443a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->x2, arc->y2, 2453a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org &arc->x2, &arc->y2); 2463a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix_map_point(&matrix, 2473a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->cx, arc->cy, 2483a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org &arc->cx, &arc->cy); 2493a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2503a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#if DEBUG_ARCS 2513a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org debug_printf("Matrix 3 [%f, %f, %f| %f, %f, %f| %f, %f, %f]\n", 2523a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix.m[0], matrix.m[1], matrix.m[2], 2533a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix.m[3], matrix.m[4], matrix.m[5], 2543a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix.m[6], matrix.m[7], matrix.m[8]); 2553a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org debug_printf("Endpoints [%f, %f], [%f, %f]\n", 2563a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->x1, arc->y1, arc->x2, arc->y2); 2573a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#endif 2583a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2593a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org vec0[0] = arc->x1 - arc->cx; 2603a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org vec0[1] = arc->y1 - arc->cy; 2613a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org vec1[0] = arc->x2 - arc->cx; 2623a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org vec1[1] = arc->y2 - arc->cy; 2633a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2643a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#if DEBUG_ARCS 2653a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org debug_printf("Vec is [%f, %f], [%f, %f], [%f, %f]\n", 2663a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org vec0[0], vec0[1], vec1[0], vec1[1], arc->cx, arc->cy); 2673a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#endif 2683a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2693a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org lambda1 = vector_orientation(vec0); 2703a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2713a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (isnan(lambda1)) 2723a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org lambda1 = 0.f; 2733a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2743a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (arc->type == VG_SCWARC_TO || 2753a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->type == VG_SCCWARC_TO) 2763a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org angle = vector_angles(vec0, vec1); 2773a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org else if (arc->type == VG_LCWARC_TO || 2783a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->type == VG_LCCWARC_TO) { 2793a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org angle = 2*M_PI - vector_angles(vec0, vec1); 2803a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } else 2813a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org abort(); 2823a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2833a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (isnan(angle)) 2843a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org angle = M_PI; 2853a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2863a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2873a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (arc->type == VG_SCWARC_TO || 2883a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->type == VG_LCWARC_TO) 2893a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org lambda2 = lambda1 - angle; 2903a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org else 2913a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org lambda2 = lambda1 + angle; 2923a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2933a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#if DEBUG_ARCS 2943a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org debug_printf("Angle is %f and (%f, %f)\n", angle, lambda1, lambda2); 2953a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#endif 2963a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 2973a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#if 0 2983a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->eta1 = atan2(sin(lambda1) / arc->b, 2993a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cos(lambda1) / arc->a); 3003a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->eta2 = atan2(sin(lambda2) / arc->b, 3013a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cos(lambda2) / arc->a); 3023a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 3033a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* make sure we have eta1 <= eta2 <= eta1 + 2 PI */ 3043a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->eta2 -= two_pi * floor((arc->eta2 - arc->eta1) / two_pi); 3053a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 3063a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* the preceding correction fails if we have exactly et2 - eta1 = 2 PI 3073a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org it reduces the interval to zero length */ 3083a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if ((lambda2 - lambda1 > M_PI) && (arc->eta2 - arc->eta1 < M_PI)) { 3093a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->eta2 += 2 * M_PI; 3103a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 3113a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#else 3123a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->eta1 = lambda1; 3133a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->eta2 = lambda2; 3143a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#endif 3153a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 3163a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return VG_TRUE; 3173a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 3183a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 3193a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#if DEBUG_ARCS 3203a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void check_endpoints(struct arc *arc) 3213a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 3223a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double x1, y1, x2, y2; 3233a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 3243a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double a_cos_eta1 = arc->a * cos(arc->eta1); 3253a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double b_sin_eta1 = arc->b * sin(arc->eta1); 3263a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x1 = arc->cx + a_cos_eta1 * arc->cos_theta - 3273a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_sin_eta1 * arc->sin_theta; 3283a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org y1 = arc->cy + a_cos_eta1 * arc->sin_theta + 3293a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_sin_eta1 * arc->cos_theta; 3303a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 3313a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double a_cos_eta2 = arc->a * cos(arc->eta2); 3323a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double b_sin_eta2 = arc->b * sin(arc->eta2); 3333a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x2 = arc->cx + a_cos_eta2 * arc->cos_theta - 3343a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_sin_eta2 * arc->sin_theta; 3353a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org y2 = arc->cy + a_cos_eta2 * arc->sin_theta + 3363a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_sin_eta2 * arc->cos_theta; 3373a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 3383a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org debug_printf("Computed (%f, %f), (%f, %f)\n", 3393a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x1, y1, x2, y2); 3403a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org debug_printf("Real (%f, %f), (%f, %f)\n", 3413a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->x1, arc->y1, 3423a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->x2, arc->y2); 3433a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 3443a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#endif 3453a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 3463a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgvoid arc_init(struct arc *arc, 3473a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGPathSegment type, 3483a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGfloat x1, VGfloat y1, 3493a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGfloat x2, VGfloat y2, 3503a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGfloat rh, VGfloat rv, 3513a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGfloat rot) 3523a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 3533a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org assert(type == VG_SCCWARC_TO || 3543a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org type == VG_SCWARC_TO || 3553a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org type == VG_LCCWARC_TO || 3563a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org type == VG_LCWARC_TO); 3573a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->type = type; 3583a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->x1 = x1; 3593a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->y1 = y1; 3603a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->x2 = x2; 3613a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->y2 = y2; 3623a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->a = rh; 3633a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->b = rv; 3643a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->theta = rot; 3653a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->cos_theta = cos(arc->theta); 3663a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->sin_theta = sin(arc->theta); 3673a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 3683a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double cx0, cy0, cx1, cy1; 3693a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double cx, cy; 3703a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->is_valid = find_ellipses(rh, rv, rot, x1, y1, x2, y2, 3713a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org &cx0, &cy0, &cx1, &cy1); 3723a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 3733a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (!arc->is_valid && try_to_fix_radii(arc)) { 3743a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org rh = arc->a; 3753a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org rv = arc->b; 3763a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->is_valid = 3773a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org find_ellipses(rh, rv, rot, x1, y1, x2, y2, 3783a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org &cx0, &cy0, &cx1, &cy1); 3793a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 3803a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 3813a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (type == VG_SCWARC_TO || 3823a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org type == VG_LCCWARC_TO) { 3833a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cx = cx1; 3843a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cy = cy1; 3853a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } else { 3863a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cx = cx0; 3873a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cy = cy0; 3883a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 3893a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#if DEBUG_ARCS 3903a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org debug_printf("Centers are : (%f, %f) , (%f, %f). Real (%f, %f)\n", 3913a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cx0, cy0, cx1, cy1, cx, cy); 3923a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#endif 3933a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->cx = cx; 3943a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->cy = cy; 3953a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (arc->is_valid) { 3963a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->is_valid = find_angles(arc); 3973a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#if DEBUG_ARCS 3983a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org check_endpoints(arc); 3993a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#endif 4003a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* remap a few points. find_angles requires 4013a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * rot in angles, the rest of the code 4023a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * will need them in radians. and find_angles 4033a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * modifies the center to match an identity 4043a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org * circle so lets reset it */ 4053a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->theta = DEGREES_TO_RADIANS(rot); 4063a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->cos_theta = cos(arc->theta); 4073a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->sin_theta = sin(arc->theta); 4083a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->cx = cx; 4093a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc->cy = cy; 4103a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 4113a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 4123a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 4133a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4143a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic INLINE double rational_function(double x, const double *c) 4153a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 4163a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return (x * (x * c[0] + c[1]) + c[2]) / (x + c[3]); 4173a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 4183a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4193a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic double estimate_error(struct arc *arc, 4203a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double etaA, double etaB) 4213a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 4223a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double eta = 0.5 * (etaA + etaB); 4233a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4243a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double x = arc->b / arc->a; 4253a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double dEta = etaB - etaA; 4263a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double cos2 = cos(2 * eta); 4273a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double cos4 = cos(4 * eta); 4283a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double cos6 = cos(6 * eta); 4293a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double c0, c1; 4303a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4313a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* select the right coeficients set according to degree and b/a */ 4323a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org const double (*coeffs)[4][4]; 4333a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org const double *safety; 4343a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org coeffs = (x < 0.25) ? coeffs3Low : coeffs3High; 4353a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org safety = safety3; 4363a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4373a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org c0 = rational_function(x, coeffs[0][0]) 4383a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org + cos2 * rational_function(x, coeffs[0][1]) 4393a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org + cos4 * rational_function(x, coeffs[0][2]) 4403a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org + cos6 * rational_function(x, coeffs[0][3]); 4413a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4423a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org c1 = rational_function(x, coeffs[1][0]) 4433a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org + cos2 * rational_function(x, coeffs[1][1]) 4443a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org + cos4 * rational_function(x, coeffs[1][2]) 4453a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org + cos6 * rational_function(x, coeffs[1][3]); 4463a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4473a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return rational_function(x, safety) * arc->a * exp(c0 + c1 * dEta); 4483a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 4493a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4503a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstruct arc_cb { 4513a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org void (*move)(struct arc_cb *cb, VGfloat x, VGfloat y); 4523a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org void (*point)(struct arc_cb *cb, VGfloat x, VGfloat y); 4533a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org void (*bezier)(struct arc_cb *cb, struct bezier *bezier); 4543a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4553a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org void *user_data; 4563a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org}; 4573a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4583a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void cb_null_move(struct arc_cb *cb, VGfloat x, VGfloat y) 4593a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 4603a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 4613a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4623a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void polygon_point(struct arc_cb *cb, VGfloat x, VGfloat y) 4633a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 4643a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct polygon *poly = (struct polygon*)cb->user_data; 4653a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org polygon_vertex_append(poly, x, y); 4663a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 4673a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4683a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void polygon_bezier(struct arc_cb *cb, struct bezier *bezier) 4693a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 4703a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct polygon *poly = (struct polygon*)cb->user_data; 4713a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier_add_to_polygon(bezier, poly); 4723a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 4733a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4743a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void stroke_point(struct arc_cb *cb, VGfloat x, VGfloat y) 4753a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 4763a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct stroker *stroker = (struct stroker*)cb->user_data; 4773a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org stroker_line_to(stroker, x, y); 4783a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 4793a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4803a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void stroke_curve(struct arc_cb *cb, struct bezier *bezier) 4813a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 4823a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct stroker *stroker = (struct stroker*)cb->user_data; 4833a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org stroker_curve_to(stroker, 4843a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier->x2, bezier->y2, 4853a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier->x3, bezier->y3, 4863a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier->x4, bezier->y4); 4873a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 4883a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4893a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void stroke_emit_point(struct arc_cb *cb, VGfloat x, VGfloat y) 4903a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 4913a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct stroker *stroker = (struct stroker*)cb->user_data; 4923a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org stroker_emit_line_to(stroker, x, y); 4933a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 4943a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 4953a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void stroke_emit_curve(struct arc_cb *cb, struct bezier *bezier) 4963a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 4973a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct stroker *stroker = (struct stroker*)cb->user_data; 4983a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org stroker_emit_curve_to(stroker, 4993a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier->x2, bezier->y2, 5003a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier->x3, bezier->y3, 5013a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier->x4, bezier->y4); 5023a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 5033a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5043a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void arc_path_move(struct arc_cb *cb, VGfloat x, VGfloat y) 5053a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 5063a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct path *path = (struct path*)cb->user_data; 5073a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org path_move_to(path, x, y); 5083a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 5093a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5103a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void arc_path_point(struct arc_cb *cb, VGfloat x, VGfloat y) 5113a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 5123a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct path *path = (struct path*)cb->user_data; 5133a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org path_line_to(path, x, y); 5143a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 5153a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5163a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void arc_path_bezier(struct arc_cb *cb, struct bezier *bezier) 5173a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 5183a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct path *path = (struct path*)cb->user_data; 5193a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org path_cubic_to(path, 5203a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier->x2, bezier->y2, 5213a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier->x3, bezier->y3, 5223a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier->x4, bezier->y4); 5233a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 5243a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5253a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic INLINE int num_beziers_needed(struct arc *arc) 5263a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 5273a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double threshold = 0.05; 5283a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGboolean found = VG_FALSE; 5293a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org int n = 1; 5303a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double min_eta, max_eta; 5313a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5323a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org min_eta = MIN2(arc->eta1, arc->eta2); 5333a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org max_eta = MAX2(arc->eta1, arc->eta2); 5343a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5353a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org while ((! found) && (n < 1024)) { 5363a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double d_eta = (max_eta - min_eta) / n; 5373a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (d_eta <= 0.5 * M_PI) { 5383a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double eta_b = min_eta; 539760fd893ba809a7a5daa25c2749ff502f7186e83kbr@chromium.org int i; 5403a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org found = VG_TRUE; 5413a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org for (i = 0; found && (i < n); ++i) { 5423a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double etaA = eta_b; 5433a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org eta_b += d_eta; 5443a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org found = (estimate_error(arc, etaA, eta_b) <= threshold); 5453a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 5463a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 5473a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org n = n << 1; 5483a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 5493a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5503a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return n; 5513a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 5523a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5533a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgstatic void arc_to_beziers(struct arc *arc, 5543a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct arc_cb cb, 5553a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct matrix *matrix) 5563a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 5573a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org int i; 5583a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org int n = 1; 5593a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double d_eta, eta_b, cos_eta_b, 5603a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org sin_eta_b, a_cos_eta_b, b_sin_eta_b, a_sin_eta_b, 5613a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_cos_eta_b, x_b, y_b, x_b_dot, y_b_dot, lx, ly; 5623a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double t, alpha; 5633a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5643a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { /* always move to the start of the arc */ 5653a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGfloat x = arc->x1; 5663a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGfloat y = arc->y1; 5673a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix_map_point(matrix, x, y, &x, &y); 5683a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.move(&cb, x, y); 5693a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 5703a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5713a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org if (!arc->is_valid) { 5723a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGfloat x = arc->x2; 5733a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGfloat y = arc->y2; 5743a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix_map_point(matrix, x, y, &x, &y); 5753a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.point(&cb, x, y); 5763a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org return; 5773a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 5783a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5793a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org /* find the number of Bézier curves needed */ 5803a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org n = num_beziers_needed(arc); 5813a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5823a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org d_eta = (arc->eta2 - arc->eta1) / n; 5833a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org eta_b = arc->eta1; 5843a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 5853a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cos_eta_b = cos(eta_b); 5863a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org sin_eta_b = sin(eta_b); 5873a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org a_cos_eta_b = arc->a * cos_eta_b; 5883a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_sin_eta_b = arc->b * sin_eta_b; 5893a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org a_sin_eta_b = arc->a * sin_eta_b; 5903a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_cos_eta_b = arc->b * cos_eta_b; 5913a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x_b = arc->cx + a_cos_eta_b * arc->cos_theta - 5923a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_sin_eta_b * arc->sin_theta; 5933a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org y_b = arc->cy + a_cos_eta_b * arc->sin_theta + 5943a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_sin_eta_b * arc->cos_theta; 5953a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x_b_dot = -a_sin_eta_b * arc->cos_theta - 5963a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_cos_eta_b * arc->sin_theta; 5973a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org y_b_dot = -a_sin_eta_b * arc->sin_theta + 5983a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_cos_eta_b * arc->cos_theta; 5993a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6003a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org { 6013a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org VGfloat x = x_b, y = y_b; 6023a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org matrix_map_point(matrix, x, y, &x, &y); 6033a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.point(&cb, x, y); 6043a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 6053a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org lx = x_b; 6063a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org ly = y_b; 6073a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6083a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org t = tan(0.5 * d_eta); 6093a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org alpha = sin(d_eta) * (sqrt(4 + 3 * t * t) - 1) / 3; 6103a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6113a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org for (i = 0; i < n; ++i) { 6123a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct bezier bezier; 6133a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double xA = x_b; 6143a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double yA = y_b; 6153a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double xADot = x_b_dot; 6163a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org double yADot = y_b_dot; 6173a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6183a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org eta_b += d_eta; 6193a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cos_eta_b = cos(eta_b); 6203a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org sin_eta_b = sin(eta_b); 6213a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org a_cos_eta_b = arc->a * cos_eta_b; 6223a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_sin_eta_b = arc->b * sin_eta_b; 6233a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org a_sin_eta_b = arc->a * sin_eta_b; 6243a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_cos_eta_b = arc->b * cos_eta_b; 6253a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x_b = arc->cx + a_cos_eta_b * arc->cos_theta - 6263a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_sin_eta_b * arc->sin_theta; 6273a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org y_b = arc->cy + a_cos_eta_b * arc->sin_theta + 6283a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_sin_eta_b * arc->cos_theta; 6293a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org x_b_dot = -a_sin_eta_b * arc->cos_theta - 6303a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_cos_eta_b * arc->sin_theta; 6313a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org y_b_dot = -a_sin_eta_b * arc->sin_theta + 6323a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org b_cos_eta_b * arc->cos_theta; 6333a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6343a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier_init(&bezier, 6353a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org lx, ly, 6363a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org (float) (xA + alpha * xADot), (float) (yA + alpha * yADot), 6373a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org (float) (x_b - alpha * x_b_dot), (float) (y_b - alpha * y_b_dot), 6383a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org (float) x_b, (float) y_b); 6393a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#if 0 6403a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org debug_printf("%d) Bezier (%f, %f), (%f, %f), (%f, %f), (%f, %f)\n", 6413a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org i, 6423a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier.x1, bezier.y1, 6433a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier.x2, bezier.y2, 6443a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier.x3, bezier.y3, 6453a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier.x4, bezier.y4); 6463a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org#endif 6473a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org bezier_transform(&bezier, matrix); 6483a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.bezier(&cb, &bezier); 6493a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org lx = x_b; 6503a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org ly = y_b; 6513a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org } 6523a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 6533a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6543a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6553a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgvoid arc_add_to_polygon(struct arc *arc, 6563a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct polygon *poly, 6573a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct matrix *matrix) 6583a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 6593a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct arc_cb cb; 6603a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6613a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.move = cb_null_move; 6623a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.point = polygon_point; 6633a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.bezier = polygon_bezier; 6643a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.user_data = poly; 6653a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6663a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc_to_beziers(arc, cb, matrix); 6673a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 6683a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6693a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgvoid arc_stroke_cb(struct arc *arc, 6703a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct stroker *stroke, 6713a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct matrix *matrix) 6723a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 6733a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct arc_cb cb; 6743a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6753a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.move = cb_null_move; 6763a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.point = stroke_point; 6773a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.bezier = stroke_curve; 6783a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.user_data = stroke; 6793a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6803a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc_to_beziers(arc, cb, matrix); 6813a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 6823a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6833a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgvoid arc_stroker_emit(struct arc *arc, 6843a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct stroker *stroker, 6853a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct matrix *matrix) 6863a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 6873a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct arc_cb cb; 6883a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6893a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.move = cb_null_move; 6903a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.point = stroke_emit_point; 6913a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.bezier = stroke_emit_curve; 6923a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.user_data = stroker; 6933a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6943a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc_to_beziers(arc, cb, matrix); 6953a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 6963a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 6973a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.orgvoid arc_to_path(struct arc *arc, 6983a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct path *path, 6993a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct matrix *matrix) 7003a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org{ 7013a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org struct arc_cb cb; 7023a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 7033a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.move = arc_path_move; 7043a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.point = arc_path_point; 7053a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.bezier = arc_path_bezier; 7063a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org cb.user_data = path; 7073a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org 7083a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org arc_to_beziers(arc, cb, matrix); 7093a0db227ffe90888ad760c61a63226988c974e0apatrick@chromium.org} 710