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
11const 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
27bool gEasy = false;  // set to true while debugging to suppress unusual whitespace
28
29// mostly do nothing, then bias towards spaces
30const char gWhiteSpace[] = { 0, 0, 0, 0, 0, 0, 0, 0, ' ', ' ', ' ', ' ', 0x09, 0x0D, 0x0A };
31
32static 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
46static 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
61static 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
68SkString 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