gfx/skia/trunk/src/utils/SkParsePath.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial