The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

SvgArc.vala in /libsvgbird

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
Circle boundaries heads/master
1 /* 2 * BirdFont code from SVG Salamander 3 * 4 * Copyright (c) 2004, Mark McKay 5 * Copyright (c) 2014, Johan Mattsson 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or 9 * without modification, are permitted provided that the following 10 * conditions are met: 11 * 12 * - Redistributions of source code must retain the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer. 15 * - Redistributions in binary form must reproduce the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer in the documentation and/or other materials 18 * provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 * OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other 34 * projects can be found at http://www.kitfox.com 35 * 36 * Created on January 26, 2004, 8:40 PM 37 * Adapded to BirdFont on Juli 2, 2014, 5:01 PM 38 */ 39 40 using Math; 41 42 namespace SvgBird { 43 44 public static void get_arc_arguments (double x0, double y0, 45 double rx, double ry, double angle, bool largeArcFlag, 46 bool sweepFlag, double x, double y, 47 out double angle_start, out double angle_extent, 48 out double center_x, out double center_y) { 49 50 // 51 // Elliptical arc implementation based on the SVG specification notes 52 // 53 54 double cx, cy; 55 double dx2, dy2, cosAngle, sinAngle; 56 double x1, y1, Prx, Pry, Px1, Py1, radiiCheck; 57 double sign, sq, coef, cx1, cy1; 58 double sx2, sy2; 59 double ux, uy, vx, vy, p, n; 60 double angleStart, angleExtent; 61 62 // Compute the half distance between the current and the final point 63 dx2 = (x0 - x) / 2.0; 64 dy2 = (y0 - y) / 2.0; 65 66 // Convert angle from degrees to radians 67 angle = angle % (2 * Math.PI); 68 69 cosAngle = cos (angle); 70 sinAngle = sin (angle); 71 72 // 73 // Step 1 : Compute (x1, y1) 74 // 75 x1 = cosAngle * dx2 + sinAngle * dy2; 76 y1 = -sinAngle * dx2 + cosAngle * dy2; 77 78 // Ensure radii are large enough 79 rx = fabs(rx); 80 ry = fabs(ry); 81 Prx = rx * rx; 82 Pry = ry * ry; 83 Px1 = x1 * x1; 84 Py1 = y1 * y1; 85 86 // Check that radii are large enough 87 radiiCheck = Px1 / Prx + Py1 / Pry; 88 89 if (radiiCheck > 1) { 90 rx = sqrt (radiiCheck) * rx; 91 ry = sqrt (radiiCheck) * ry; 92 Prx = rx * rx; 93 Pry = ry * ry; 94 } 95 96 // 97 // Step 2 : Compute (cx1, cy1) 98 // 99 sign = (largeArcFlag == sweepFlag) ? -1 : 1; 100 sq = ((Prx * Pry) - (Prx * Py1) - (Pry * Px1)) / ((Prx * Py1) + (Pry * Px1)); 101 sq = (sq < 0) ? 0 : sq; 102 coef = (sign * Math.sqrt(sq)); 103 cx1 = coef * ((rx * y1) / ry); 104 cy1 = coef * -((ry * x1) / rx); 105 106 // 107 // Step 3 : Compute (cx, cy) from (cx1, cy1) 108 // 109 110 sx2 = (x0 + x) / 2.0; 111 sy2 = (y0 + y) / 2.0; 112 cx = sx2 + (cosAngle * cx1 - sinAngle * cy1); 113 cy = sy2 + (sinAngle * cx1 + cosAngle * cy1); 114 115 // 116 // Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle) 117 // 118 119 ux = (x1 - cx1) / rx; 120 uy = (y1 - cy1) / ry; 121 vx = (-x1 - cx1) / rx; 122 vy = (-y1 - cy1) / ry; 123 124 // Compute the angle start 125 n = sqrt((ux * ux) + (uy * uy)); 126 p = ux; // (1 * ux) + (0 * uy) 127 sign = (uy < 0) ? -1d : 1d; 128 angleStart = sign * acos(p / n); 129 130 // Compute the angle extent 131 n = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy)); 132 p = ux * vx + uy * vy; 133 sign = (ux * vy - uy * vx < 0) ? -1d : 1d; 134 angleExtent = sign * Math.acos(p / n); 135 136 if(!sweepFlag && angleExtent > 0) { 137 angleExtent -= 2 * PI; 138 } else if (sweepFlag && angleExtent < 0) { 139 angleExtent += 2 * PI; 140 } 141 142 center_x = cx; 143 center_y = cy; 144 145 angleExtent = -angleExtent; 146 angleStart = -angleStart; 147 148 angle_start = angleStart; 149 angle_extent = angleExtent; 150 } 151 152 153 } 154 155