LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/utils - SkParsePath.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 168 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : #include "SkParse.h"
       8             : #include "SkParsePath.h"
       9             : 
      10           0 : static inline bool is_between(int c, int min, int max) {
      11           0 :     return (unsigned)(c - min) <= (unsigned)(max - min);
      12             : }
      13             : 
      14           0 : static inline bool is_ws(int c) {
      15           0 :     return is_between(c, 1, 32);
      16             : }
      17             : 
      18           0 : static inline bool is_digit(int c) {
      19           0 :     return is_between(c, '0', '9');
      20             : }
      21             : 
      22           0 : static inline bool is_sep(int c) {
      23           0 :     return is_ws(c) || c == ',';
      24             : }
      25             : 
      26           0 : static inline bool is_lower(int c) {
      27           0 :     return is_between(c, 'a', 'z');
      28             : }
      29             : 
      30           0 : static inline int to_upper(int c) {
      31           0 :     return c - 'a' + 'A';
      32             : }
      33             : 
      34           0 : static const char* skip_ws(const char str[]) {
      35           0 :     SkASSERT(str);
      36           0 :     while (is_ws(*str))
      37           0 :         str++;
      38           0 :     return str;
      39             : }
      40             : 
      41           0 : static const char* skip_sep(const char str[]) {
      42           0 :     if (!str) {
      43           0 :         return nullptr;
      44             :     }
      45           0 :     while (is_sep(*str))
      46           0 :         str++;
      47           0 :     return str;
      48             : }
      49             : 
      50           0 : static const char* find_points(const char str[], SkPoint value[], int count,
      51             :                                bool isRelative, SkPoint* relative) {
      52           0 :     str = SkParse::FindScalars(str, &value[0].fX, count * 2);
      53           0 :     if (isRelative) {
      54           0 :         for (int index = 0; index < count; index++) {
      55           0 :             value[index].fX += relative->fX;
      56           0 :             value[index].fY += relative->fY;
      57             :         }
      58             :     }
      59           0 :     return str;
      60             : }
      61             : 
      62           0 : static const char* find_scalar(const char str[], SkScalar* value,
      63             :                                bool isRelative, SkScalar relative) {
      64           0 :     str = SkParse::FindScalar(str, value);
      65           0 :     if (!str) {
      66           0 :         return nullptr;
      67             :     }
      68           0 :     if (isRelative) {
      69           0 :         *value += relative;
      70             :     }
      71           0 :     str = skip_sep(str);
      72           0 :     return str;
      73             : }
      74             : 
      75           0 : bool SkParsePath::FromSVGString(const char data[], SkPath* result) {
      76           0 :     SkPath path;
      77           0 :     SkPoint first = {0, 0};
      78           0 :     SkPoint c = {0, 0};
      79           0 :     SkPoint lastc = {0, 0};
      80             :     SkPoint points[3];
      81           0 :     char op = '\0';
      82           0 :     char previousOp = '\0';
      83           0 :     bool relative = false;
      84             :     for (;;) {
      85           0 :         if (!data) {
      86             :             // Truncated data
      87           0 :             return false;
      88             :         }
      89           0 :         data = skip_ws(data);
      90           0 :         if (data[0] == '\0') {
      91           0 :             break;
      92             :         }
      93           0 :         char ch = data[0];
      94           0 :         if (is_digit(ch) || ch == '-' || ch == '+' || ch == '.') {
      95           0 :             if (op == '\0') {
      96           0 :                 return false;
      97             :             }
      98           0 :         } else if (is_sep(ch)) {
      99           0 :             data = skip_sep(data);
     100             :         } else {
     101           0 :             op = ch;
     102           0 :             relative = false;
     103           0 :             if (is_lower(op)) {
     104           0 :                 op = (char) to_upper(op);
     105           0 :                 relative = true;
     106             :             }
     107           0 :             data++;
     108           0 :             data = skip_sep(data);
     109             :         }
     110           0 :         switch (op) {
     111             :             case 'M':
     112           0 :                 data = find_points(data, points, 1, relative, &c);
     113           0 :                 path.moveTo(points[0]);
     114           0 :                 previousOp = '\0';
     115           0 :                 op = 'L';
     116           0 :                 c = points[0];
     117           0 :                 break;
     118             :             case 'L':
     119           0 :                 data = find_points(data, points, 1, relative, &c);
     120           0 :                 path.lineTo(points[0]);
     121           0 :                 c = points[0];
     122           0 :                 break;
     123             :             case 'H': {
     124             :                 SkScalar x;
     125           0 :                 data = find_scalar(data, &x, relative, c.fX);
     126           0 :                 path.lineTo(x, c.fY);
     127           0 :                 c.fX = x;
     128           0 :             } break;
     129             :             case 'V': {
     130             :                 SkScalar y;
     131           0 :                 data = find_scalar(data, &y, relative, c.fY);
     132           0 :                 path.lineTo(c.fX, y);
     133           0 :                 c.fY = y;
     134           0 :             } break;
     135             :             case 'C':
     136           0 :                 data = find_points(data, points, 3, relative, &c);
     137           0 :                 goto cubicCommon;
     138             :             case 'S':
     139           0 :                 data = find_points(data, &points[1], 2, relative, &c);
     140           0 :                 points[0] = c;
     141           0 :                 if (previousOp == 'C' || previousOp == 'S') {
     142           0 :                     points[0].fX -= lastc.fX - c.fX;
     143           0 :                     points[0].fY -= lastc.fY - c.fY;
     144             :                 }
     145             :             cubicCommon:
     146           0 :                 path.cubicTo(points[0], points[1], points[2]);
     147           0 :                 lastc = points[1];
     148           0 :                 c = points[2];
     149           0 :                 break;
     150             :             case 'Q':  // Quadratic Bezier Curve
     151           0 :                 data = find_points(data, points, 2, relative, &c);
     152           0 :                 goto quadraticCommon;
     153             :             case 'T':
     154           0 :                 data = find_points(data, &points[1], 1, relative, &c);
     155           0 :                 points[0] = c;
     156           0 :                 if (previousOp == 'Q' || previousOp == 'T') {
     157           0 :                     points[0].fX -= lastc.fX - c.fX;
     158           0 :                     points[0].fY -= lastc.fY - c.fY;
     159             :                 }
     160             :             quadraticCommon:
     161           0 :                 path.quadTo(points[0], points[1]);
     162           0 :                 lastc = points[0];
     163           0 :                 c = points[1];
     164           0 :                 break;
     165             :             case 'A': {
     166             :                 SkPoint radii;
     167             :                 SkScalar angle, largeArc, sweep;
     168           0 :                 if ((data = find_points(data, &radii, 1, false, nullptr))
     169           0 :                         && (data = skip_sep(data))
     170           0 :                         && (data = find_scalar(data, &angle, false, 0))
     171           0 :                         && (data = skip_sep(data))
     172           0 :                         && (data = find_scalar(data, &largeArc, false, 0))
     173           0 :                         && (data = skip_sep(data))
     174           0 :                         && (data = find_scalar(data, &sweep, false, 0))
     175           0 :                         && (data = skip_sep(data))
     176           0 :                         && (data = find_points(data, &points[0], 1, relative, &c))) {
     177           0 :                     path.arcTo(radii, angle, (SkPath::ArcSize) SkToBool(largeArc),
     178           0 :                             (SkPath::Direction) !SkToBool(sweep), points[0]);
     179           0 :                     path.getLastPt(&c);
     180             :                 }
     181           0 :                 } break;
     182             :             case 'Z':
     183           0 :                 path.close();
     184           0 :                 c = first;
     185           0 :                 break;
     186             :             case '~': {
     187             :                 SkPoint args[2];
     188           0 :                 data = find_points(data, args, 2, false, nullptr);
     189           0 :                 path.moveTo(args[0].fX, args[0].fY);
     190           0 :                 path.lineTo(args[1].fX, args[1].fY);
     191           0 :             } break;
     192             :             default:
     193           0 :                 return false;
     194             :         }
     195           0 :         if (previousOp == 0) {
     196           0 :             first = c;
     197             :         }
     198           0 :         previousOp = op;
     199           0 :     }
     200             :     // we're good, go ahead and swap in the result
     201           0 :     result->swap(path);
     202           0 :     return true;
     203             : }
     204             : 
     205             : ///////////////////////////////////////////////////////////////////////////////
     206             : 
     207             : #include "SkGeometry.h"
     208             : #include "SkString.h"
     209             : #include "SkStream.h"
     210             : 
     211           0 : static void write_scalar(SkWStream* stream, SkScalar value) {
     212             :     char buffer[64];
     213             : #ifdef SK_BUILD_FOR_WIN32
     214             :     int len = _snprintf(buffer, sizeof(buffer), "%g", value);
     215             : #else
     216           0 :     int len = snprintf(buffer, sizeof(buffer), "%g", value);
     217             : #endif
     218           0 :     char* stop = buffer + len;
     219           0 :     stream->write(buffer, stop - buffer);
     220           0 : }
     221             : 
     222           0 : static void append_scalars(SkWStream* stream, char verb, const SkScalar data[],
     223             :                            int count) {
     224           0 :     stream->write(&verb, 1);
     225           0 :     write_scalar(stream, data[0]);
     226           0 :     for (int i = 1; i < count; i++) {
     227           0 :         stream->write(" ", 1);
     228           0 :         write_scalar(stream, data[i]);
     229             :     }
     230           0 : }
     231             : 
     232           0 : void SkParsePath::ToSVGString(const SkPath& path, SkString* str) {
     233           0 :     SkDynamicMemoryWStream  stream;
     234             : 
     235           0 :     SkPath::Iter    iter(path, false);
     236             :     SkPoint         pts[4];
     237             : 
     238             :     for (;;) {
     239           0 :         switch (iter.next(pts, false)) {
     240             :             case SkPath::kConic_Verb: {
     241           0 :                 const SkScalar tol = SK_Scalar1 / 1024; // how close to a quad
     242           0 :                 SkAutoConicToQuads quadder;
     243           0 :                 const SkPoint* quadPts = quadder.computeQuads(pts, iter.conicWeight(), tol);
     244           0 :                 for (int i = 0; i < quadder.countQuads(); ++i) {
     245           0 :                     append_scalars(&stream, 'Q', &quadPts[i*2 + 1].fX, 4);
     246             :                 }
     247           0 :             } break;
     248             :            case SkPath::kMove_Verb:
     249           0 :                 append_scalars(&stream, 'M', &pts[0].fX, 2);
     250           0 :                 break;
     251             :             case SkPath::kLine_Verb:
     252           0 :                 append_scalars(&stream, 'L', &pts[1].fX, 2);
     253           0 :                 break;
     254             :             case SkPath::kQuad_Verb:
     255           0 :                 append_scalars(&stream, 'Q', &pts[1].fX, 4);
     256           0 :                 break;
     257             :             case SkPath::kCubic_Verb:
     258           0 :                 append_scalars(&stream, 'C', &pts[1].fX, 6);
     259           0 :                 break;
     260             :             case SkPath::kClose_Verb:
     261           0 :                 stream.write("Z", 1);
     262           0 :                 break;
     263             :             case SkPath::kDone_Verb:
     264           0 :                 str->resize(stream.bytesWritten());
     265           0 :                 stream.copyTo(str->writable_str());
     266           0 :             return;
     267             :         }
     268           0 :     }
     269             : }

Generated by: LCOV version 1.13