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 #ifndef SkSVGAttributeParser_DEFINED
9 #define SkSVGAttributeParser_DEFINED
10 
11 #include <vector>
12 
13 #include "include/private/SkNoncopyable.h"
14 #include "modules/svg/include/SkSVGTypes.h"
15 #include "src/core/SkTLazy.h"
16 
17 class SkSVGAttributeParser : public SkNoncopyable {
18 public:
19     SkSVGAttributeParser(const char[]);
20 
21     bool parseInteger(SkSVGIntegerType*);
22     bool parseViewBox(SkSVGViewBoxType*);
23     bool parsePreserveAspectRatio(SkSVGPreserveAspectRatio*);
24 
25     // TODO: Migrate all parse*() functions to this style (and delete the old version)
26     //      so they can be used by parse<T>():
parse(SkSVGIntegerType * v)27     bool parse(SkSVGIntegerType* v) { return parseInteger(v); }
28 
29     template <typename T> using ParseResult = SkTLazy<T>;
30 
parse(const char * value)31     template <typename T> static ParseResult<T> parse(const char* value) {
32         ParseResult<T> result;
33         T parsedValue;
34         if (SkSVGAttributeParser(value).parse(&parsedValue)) {
35             result.set(std::move(parsedValue));
36         }
37         return result;
38     }
39 
40     template <typename T>
parse(const char * expectedName,const char * name,const char * value)41     static ParseResult<T> parse(const char* expectedName,
42                                 const char* name,
43                                 const char* value) {
44         if (!strcmp(name, expectedName)) {
45             return parse<T>(value);
46         }
47 
48         return ParseResult<T>();
49     }
50 
51     template <typename PropertyT>
parseProperty(const char * expectedName,const char * name,const char * value)52     static ParseResult<PropertyT> parseProperty(const char* expectedName,
53                                                 const char* name,
54                                                 const char* value) {
55         if (strcmp(name, expectedName) != 0) {
56             return ParseResult<PropertyT>();
57         }
58 
59         if (!strcmp(value, "inherit")) {
60             PropertyT result(SkSVGPropertyState::kInherit);
61             return ParseResult<PropertyT>(&result);
62         }
63 
64         auto pr = parse<typename PropertyT::ValueT>(value);
65         if (pr.isValid()) {
66             PropertyT result(*pr);
67             return ParseResult<PropertyT>(&result);
68         }
69 
70         return ParseResult<PropertyT>();
71     }
72 
73 private:
74     // Stack-only
75     void* operator new(size_t) = delete;
76     void* operator new(size_t, void*) = delete;
77 
78     template <typename T>
79     bool parse(T*);
80 
81     template <typename F>
82     bool advanceWhile(F func);
83 
84     bool matchStringToken(const char* token, const char** newPos = nullptr) const;
85 
86     bool parseWSToken();
87     bool parseEOSToken();
88     bool parseSepToken();
89     bool parseCommaWspToken();
90     bool parseExpectedStringToken(const char*);
91     bool parseScalarToken(SkScalar*);
92     bool parseInt32Token(int32_t*);
93     bool parseHexToken(uint32_t*);
94     bool parseLengthUnitToken(SkSVGLength::Unit*);
95     bool parseNamedColorToken(SkColor*);
96     bool parseHexColorToken(SkColor*);
97     bool parseColorComponentToken(int32_t*);
98     bool parseRGBColorToken(SkColor*);
99     bool parseFuncIRI(SkSVGFuncIRI*);
100 
101     // Transform helpers
102     bool parseMatrixToken(SkMatrix*);
103     bool parseTranslateToken(SkMatrix*);
104     bool parseScaleToken(SkMatrix*);
105     bool parseRotateToken(SkMatrix*);
106     bool parseSkewXToken(SkMatrix*);
107     bool parseSkewYToken(SkMatrix*);
108 
109     // Parses a sequence of 'WS* <prefix> WS* (<nested>)', where the nested sequence
110     // is handled by the passed functor.
111     template <typename Func, typename T>
112     bool parseParenthesized(const char* prefix, Func, T* result);
113 
114     template <typename T>
115     bool parseList(std::vector<T>*);
116 
117     template <typename T, typename TArray>
parseEnumMap(const TArray & arr,T * result)118     bool parseEnumMap(const TArray& arr, T* result) {
119         for (size_t i = 0; i < SK_ARRAY_COUNT(arr); ++i) {
120             if (this->parseExpectedStringToken(std::get<0>(arr[i]))) {
121                 *result = std::get<1>(arr[i]);
122                 return true;
123             }
124         }
125         return false;
126     }
127 
128     // The current position in the input string.
129     const char* fCurPos;
130 
131     using INHERITED = SkNoncopyable;
132 };
133 
134 #endif // SkSVGAttributeParser_DEFINED
135