| Index: skia/animator/SkSVGPath.cpp
|
| ===================================================================
|
| --- skia/animator/SkSVGPath.cpp (revision 16859)
|
| +++ skia/animator/SkSVGPath.cpp (working copy)
|
| @@ -1,243 +0,0 @@
|
| -/* libs/graphics/animator/SkSVGPath.cpp
|
| -**
|
| -** Copyright 2006, The Android Open Source Project
|
| -**
|
| -** Licensed under the Apache License, Version 2.0 (the "License");
|
| -** you may not use this file except in compliance with the License.
|
| -** You may obtain a copy of the License at
|
| -**
|
| -** http://www.apache.org/licenses/LICENSE-2.0
|
| -**
|
| -** Unless required by applicable law or agreed to in writing, software
|
| -** distributed under the License is distributed on an "AS IS" BASIS,
|
| -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -** See the License for the specific language governing permissions and
|
| -** limitations under the License.
|
| -*/
|
| -
|
| -#include <ctype.h>
|
| -#include "SkDrawPath.h"
|
| -#include "SkParse.h"
|
| -#include "SkPoint.h"
|
| -#include "SkUtils.h"
|
| -#define QUADRATIC_APPROXIMATION 1
|
| -
|
| -#if QUADRATIC_APPROXIMATION
|
| -////////////////////////////////////////////////////////////////////////////////////
|
| -//functions to approximate a cubic using two quadratics
|
| -
|
| -// midPt sets the first argument to be the midpoint of the other two
|
| -// it is used by quadApprox
|
| -static inline void midPt(SkPoint& dest,const SkPoint& a,const SkPoint& b)
|
| -{
|
| - dest.set(SkScalarAve(a.fX, b.fX),SkScalarAve(a.fY, b.fY));
|
| -}
|
| -// quadApprox - makes an approximation, which we hope is faster
|
| -static void quadApprox(SkPath &fPath, const SkPoint &p0, const SkPoint &p1, const SkPoint &p2)
|
| -{
|
| - //divide the cubic up into two cubics, then convert them into quadratics
|
| - //define our points
|
| - SkPoint c,j,k,l,m,n,o,p,q, mid;
|
| - fPath.getLastPt(&c);
|
| - midPt(j, p0, c);
|
| - midPt(k, p0, p1);
|
| - midPt(l, p1, p2);
|
| - midPt(o, j, k);
|
| - midPt(p, k, l);
|
| - midPt(q, o, p);
|
| - //compute the first half
|
| - m.set(SkScalarHalf(3*j.fX - c.fX), SkScalarHalf(3*j.fY - c.fY));
|
| - n.set(SkScalarHalf(3*o.fX -q.fX), SkScalarHalf(3*o.fY - q.fY));
|
| - midPt(mid,m,n);
|
| - fPath.quadTo(mid,q);
|
| - c = q;
|
| - //compute the second half
|
| - m.set(SkScalarHalf(3*p.fX - c.fX), SkScalarHalf(3*p.fY - c.fY));
|
| - n.set(SkScalarHalf(3*l.fX -p2.fX),SkScalarHalf(3*l.fY -p2.fY));
|
| - midPt(mid,m,n);
|
| - fPath.quadTo(mid,p2);
|
| -}
|
| -#endif
|
| -
|
| -
|
| -static inline bool is_between(int c, int min, int max)
|
| -{
|
| - return (unsigned)(c - min) <= (unsigned)(max - min);
|
| -}
|
| -
|
| -static inline bool is_ws(int c)
|
| -{
|
| - return is_between(c, 1, 32);
|
| -}
|
| -
|
| -static inline bool is_digit(int c)
|
| -{
|
| - return is_between(c, '0', '9');
|
| -}
|
| -
|
| -static inline bool is_sep(int c)
|
| -{
|
| - return is_ws(c) || c == ',';
|
| -}
|
| -
|
| -static const char* skip_ws(const char str[])
|
| -{
|
| - SkASSERT(str);
|
| - while (is_ws(*str))
|
| - str++;
|
| - return str;
|
| -}
|
| -
|
| -static const char* skip_sep(const char str[])
|
| -{
|
| - SkASSERT(str);
|
| - while (is_sep(*str))
|
| - str++;
|
| - return str;
|
| -}
|
| -
|
| -static const char* find_points(const char str[], SkPoint value[], int count,
|
| - bool isRelative, SkPoint* relative)
|
| -{
|
| - str = SkParse::FindScalars(str, &value[0].fX, count * 2);
|
| - if (isRelative) {
|
| - for (int index = 0; index < count; index++) {
|
| - value[index].fX += relative->fX;
|
| - value[index].fY += relative->fY;
|
| - }
|
| - }
|
| - return str;
|
| -}
|
| -
|
| -static const char* find_scalar(const char str[], SkScalar* value,
|
| - bool isRelative, SkScalar relative)
|
| -{
|
| - str = SkParse::FindScalar(str, value);
|
| - if (isRelative)
|
| - *value += relative;
|
| - return str;
|
| -}
|
| -
|
| -void SkDrawPath::parseSVG() {
|
| - fPath.reset();
|
| - const char* data = d.c_str();
|
| - SkPoint f = {0, 0};
|
| - SkPoint c = {0, 0};
|
| - SkPoint lastc = {0, 0};
|
| - SkPoint points[3];
|
| - char op = '\0';
|
| - char previousOp = '\0';
|
| - bool relative = false;
|
| - do {
|
| - data = skip_ws(data);
|
| - if (data[0] == '\0')
|
| - break;
|
| - char ch = data[0];
|
| - if (is_digit(ch) || ch == '-' || ch == '+') {
|
| - if (op == '\0')
|
| - return;
|
| - }
|
| - else {
|
| - op = ch;
|
| - relative = false;
|
| - if (islower(op)) {
|
| - op = (char) toupper(op);
|
| - relative = true;
|
| - }
|
| - data++;
|
| - data = skip_sep(data);
|
| - }
|
| - switch (op) {
|
| - case 'M':
|
| - data = find_points(data, points, 1, relative, &c);
|
| - fPath.moveTo(points[0]);
|
| - op = 'L';
|
| - c = points[0];
|
| - break;
|
| - case 'L':
|
| - data = find_points(data, points, 1, relative, &c);
|
| - fPath.lineTo(points[0]);
|
| - c = points[0];
|
| - break;
|
| - case 'H': {
|
| - SkScalar x;
|
| - data = find_scalar(data, &x, relative, c.fX);
|
| - fPath.lineTo(x, c.fY);
|
| - c.fX = x;
|
| - }
|
| - break;
|
| - case 'V': {
|
| - SkScalar y;
|
| - data = find_scalar(data, &y, relative, c.fY);
|
| - fPath.lineTo(c.fX, y);
|
| - c.fY = y;
|
| - }
|
| - break;
|
| - case 'C':
|
| - data = find_points(data, points, 3, relative, &c);
|
| - goto cubicCommon;
|
| - case 'S':
|
| - data = find_points(data, &points[1], 2, relative, &c);
|
| - points[0] = c;
|
| - if (previousOp == 'C' || previousOp == 'S') {
|
| - points[0].fX -= lastc.fX - c.fX;
|
| - points[0].fY -= lastc.fY - c.fY;
|
| - }
|
| - cubicCommon:
|
| - // if (data[0] == '\0')
|
| - // return;
|
| -#if QUADRATIC_APPROXIMATION
|
| - quadApprox(fPath, points[0], points[1], points[2]);
|
| -#else //this way just does a boring, slow old cubic
|
| - fPath.cubicTo(points[0], points[1], points[2]);
|
| -#endif
|
| - //if we are using the quadApprox, lastc is what it would have been if we had used
|
| - //cubicTo
|
| - lastc = points[1];
|
| - c = points[2];
|
| - break;
|
| - case 'Q': // Quadratic Bezier Curve
|
| - data = find_points(data, points, 2, relative, &c);
|
| - goto quadraticCommon;
|
| - case 'T':
|
| - data = find_points(data, &points[1], 1, relative, &c);
|
| - points[0] = points[1];
|
| - if (previousOp == 'Q' || previousOp == 'T') {
|
| - points[0].fX = c.fX * 2 - lastc.fX;
|
| - points[0].fY = c.fY * 2 - lastc.fY;
|
| - }
|
| - quadraticCommon:
|
| - fPath.quadTo(points[0], points[1]);
|
| - lastc = points[0];
|
| - c = points[1];
|
| - break;
|
| - case 'Z':
|
| - fPath.close();
|
| -#if 0 // !!! still a bug?
|
| - if (fPath.isEmpty() && (f.fX != 0 || f.fY != 0)) {
|
| - c.fX -= SkScalar.Epsilon; // !!! enough?
|
| - fPath.moveTo(c);
|
| - fPath.lineTo(f);
|
| - fPath.close();
|
| - }
|
| -#endif
|
| - c = f;
|
| - op = '\0';
|
| - break;
|
| - case '~': {
|
| - SkPoint args[2];
|
| - data = find_points(data, args, 2, false, NULL);
|
| - fPath.moveTo(args[0].fX, args[0].fY);
|
| - fPath.lineTo(args[1].fX, args[1].fY);
|
| - }
|
| - break;
|
| - default:
|
| - SkASSERT(0);
|
| - return;
|
| - }
|
| - if (previousOp == 0)
|
| - f = c;
|
| - previousOp = op;
|
| - } while (data[0] > 0);
|
| -}
|
| -
|
|
|