1 /*
2  * Copyright 2016 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 
8 #include "SkRandom.h"
9 #include "random_parse_path.h"
10 
11 const struct Legal {
12     char fSymbol;
13     int fScalars;
14 } gLegal[] = {
15     { 'M', 2 },
16     { 'H', 1 },
17     { 'V', 1 },
18     { 'L', 2 },
19     { 'Q', 4 },
20     { 'T', 2 },
21     { 'C', 6 },
22     { 'S', 4 },
23     { 'A', 4 },
24     { 'Z', 0 },
25 };
26 
27 bool gEasy = false;  // set to true while debugging to suppress unusual whitespace
28 
29 // mostly do nothing, then bias towards spaces
30 const char gWhiteSpace[] = { 0, 0, 0, 0, 0, 0, 0, 0, ' ', ' ', ' ', ' ', 0x09, 0x0D, 0x0A };
31 
add_white(SkRandom * rand,SkString * atom)32 static void add_white(SkRandom* rand, SkString* atom) {
33     if (gEasy) {
34         atom->append(" ");
35         return;
36     }
37     int reps = rand->nextRangeU(0, 2);
38     for (int rep = 0; rep < reps; ++rep) {
39         int index = rand->nextRangeU(0, (int) SK_ARRAY_COUNT(gWhiteSpace) - 1);
40         if (gWhiteSpace[index]) {
41             atom->append(&gWhiteSpace[index], 1);
42         }
43     }
44 }
45 
add_comma(SkRandom * rand,SkString * atom)46 static void add_comma(SkRandom* rand, SkString* atom) {
47     if (gEasy) {
48         atom->append(",");
49         return;
50     }
51     size_t count = atom->size();
52     add_white(rand, atom);
53     if (rand->nextBool()) {
54         atom->append(",");
55     }
56     do {
57         add_white(rand, atom);
58     } while (count == atom->size());
59 }
60 
add_some_white(SkRandom * rand,SkString * atom)61 static void add_some_white(SkRandom* rand, SkString* atom) {
62     size_t count = atom->size();
63     do {
64         add_white(rand, atom);
65     } while (count == atom->size());
66 }
67 
MakeRandomParsePathPiece(SkRandom * rand)68 SkString MakeRandomParsePathPiece(SkRandom* rand) {
69     SkString atom;
70     int index = rand->nextRangeU(0, (int) SK_ARRAY_COUNT(gLegal) - 1);
71     const Legal& legal = gLegal[index];
72     gEasy ? atom.append("\n") : add_white(rand, &atom);
73     char symbol = legal.fSymbol | (rand->nextBool() ? 0x20 : 0);
74     atom.append(&symbol, 1);
75     int reps = rand->nextRangeU(1, 3);
76     for (int rep = 0; rep < reps; ++rep) {
77         for (int index = 0; index < legal.fScalars; ++index) {
78             SkScalar coord = rand->nextRangeF(0, 100);
79             add_white(rand, &atom);
80             atom.appendScalar(coord);
81             if (rep < reps - 1 && index < legal.fScalars - 1) {
82                 add_comma(rand, &atom);
83             } else {
84                 add_some_white(rand, &atom);
85             }
86             if ('A' == legal.fSymbol && 1 == index) {
87                 atom.appendScalar(rand->nextRangeF(-720, 720));
88                 add_comma(rand, &atom);
89                 atom.appendU32(rand->nextRangeU(0, 1));
90                 add_comma(rand, &atom);
91                 atom.appendU32(rand->nextRangeU(0, 1));
92                 add_comma(rand, &atom);
93             }
94         }
95     }
96     return atom;
97 }
98