180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <ctype.h> 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkDrawPath.h" 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkParse.h" 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPoint.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkUtils.h" 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define QUADRATIC_APPROXIMATION 1 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if QUADRATIC_APPROXIMATION 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////////////////////////////////////////////////////////////////////////////// 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//functions to approximate a cubic using two quadratics 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// midPt sets the first argument to be the midpoint of the other two 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// it is used by quadApprox 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void midPt(SkPoint& dest,const SkPoint& a,const SkPoint& b) 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dest.set(SkScalarAve(a.fX, b.fX),SkScalarAve(a.fY, b.fY)); 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// quadApprox - makes an approximation, which we hope is faster 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void quadApprox(SkPath &fPath, const SkPoint &p0, const SkPoint &p1, const SkPoint &p2) 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //divide the cubic up into two cubics, then convert them into quadratics 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //define our points 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint c,j,k,l,m,n,o,p,q, mid; 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.getLastPt(&c); 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru midPt(j, p0, c); 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru midPt(k, p0, p1); 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru midPt(l, p1, p2); 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru midPt(o, j, k); 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru midPt(p, k, l); 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru midPt(q, o, p); 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //compute the first half 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru m.set(SkScalarHalf(3*j.fX - c.fX), SkScalarHalf(3*j.fY - c.fY)); 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n.set(SkScalarHalf(3*o.fX -q.fX), SkScalarHalf(3*o.fY - q.fY)); 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru midPt(mid,m,n); 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.quadTo(mid,q); 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c = q; 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //compute the second half 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru m.set(SkScalarHalf(3*p.fX - c.fX), SkScalarHalf(3*p.fY - c.fY)); 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n.set(SkScalarHalf(3*l.fX -p2.fX),SkScalarHalf(3*l.fY -p2.fY)); 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru midPt(mid,m,n); 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.quadTo(mid,p2); 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_between(int c, int min, int max) 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (unsigned)(c - min) <= (unsigned)(max - min); 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_ws(int c) 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return is_between(c, 1, 32); 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_digit(int c) 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return is_between(c, '0', '9'); 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_sep(int c) 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return is_ws(c) || c == ','; 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const char* skip_ws(const char str[]) 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(str); 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (is_ws(*str)) 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str++; 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return str; 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const char* skip_sep(const char str[]) 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(str); 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (is_sep(*str)) 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str++; 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return str; 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const char* find_points(const char str[], SkPoint value[], int count, 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isRelative, SkPoint* relative) 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str = SkParse::FindScalars(str, &value[0].fX, count * 2); 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (isRelative) { 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int index = 0; index < count; index++) { 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru value[index].fX += relative->fX; 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru value[index].fY += relative->fY; 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return str; 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const char* find_scalar(const char str[], SkScalar* value, 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool isRelative, SkScalar relative) 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str = SkParse::FindScalar(str, value); 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (isRelative) 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *value += relative; 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return str; 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkDrawPath::parseSVG() { 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.reset(); 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const char* data = d.c_str(); 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint f = {0, 0}; 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint c = {0, 0}; 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint lastc = {0, 0}; 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint points[3]; 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru char op = '\0'; 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru char previousOp = '\0'; 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool relative = false; 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru do { 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = skip_ws(data); 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (data[0] == '\0') 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru char ch = data[0]; 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (is_digit(ch) || ch == '-' || ch == '+') { 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (op == '\0') 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return; 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru else { 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru op = ch; 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru relative = false; 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (islower(op)) { 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru op = (char) toupper(op); 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru relative = true; 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data++; 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = skip_sep(data); 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru switch (op) { 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 'M': 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = find_points(data, points, 1, relative, &c); 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.moveTo(points[0]); 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru op = 'L'; 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c = points[0]; 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 'L': 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = find_points(data, points, 1, relative, &c); 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.lineTo(points[0]); 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c = points[0]; 15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 'H': { 15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar x; 15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = find_scalar(data, &x, relative, c.fX); 15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.lineTo(x, c.fY); 15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c.fX = x; 15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 'V': { 16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScalar y; 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = find_scalar(data, &y, relative, c.fY); 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.lineTo(c.fX, y); 16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c.fY = y; 16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 'C': 16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = find_points(data, points, 3, relative, &c); 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru goto cubicCommon; 17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 'S': 17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = find_points(data, &points[1], 2, relative, &c); 17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru points[0] = c; 17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (previousOp == 'C' || previousOp == 'S') { 17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru points[0].fX -= lastc.fX - c.fX; 17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru points[0].fY -= lastc.fY - c.fY; 17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cubicCommon: 17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // if (data[0] == '\0') 18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // return; 18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if QUADRATIC_APPROXIMATION 18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru quadApprox(fPath, points[0], points[1], points[2]); 18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else //this way just does a boring, slow old cubic 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.cubicTo(points[0], points[1], points[2]); 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //if we are using the quadApprox, lastc is what it would have been if we had used 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //cubicTo 18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru lastc = points[1]; 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c = points[2]; 19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 'Q': // Quadratic Bezier Curve 19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = find_points(data, points, 2, relative, &c); 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru goto quadraticCommon; 19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 'T': 19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = find_points(data, &points[1], 1, relative, &c); 19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru points[0] = points[1]; 19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (previousOp == 'Q' || previousOp == 'T') { 19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru points[0].fX = c.fX * 2 - lastc.fX; 19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru points[0].fY = c.fY * 2 - lastc.fY; 20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru quadraticCommon: 20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.quadTo(points[0], points[1]); 20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru lastc = points[0]; 20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c = points[1]; 20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 'Z': 20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.close(); 20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0 // !!! still a bug? 20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fPath.isEmpty() && (f.fX != 0 || f.fY != 0)) { 21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c.fX -= SkScalar.Epsilon; // !!! enough? 21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.moveTo(c); 21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.lineTo(f); 21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.close(); 21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c = f; 21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru op = '\0'; 21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case '~': { 22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPoint args[2]; 22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru data = find_points(data, args, 2, false, NULL); 22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.moveTo(args[0].fX, args[0].fY); 22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fPath.lineTo(args[1].fX, args[1].fY); 22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru default: 22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(0); 22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return; 22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (previousOp == 0) 23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru f = c; 23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru previousOp = op; 23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } while (data[0] > 0); 23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 235