xref: /aosp_15_r20/external/skia/modules/svg/include/SkSVGAttributeParser.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 "include/core/SkColor.h"
12 #include "include/core/SkScalar.h"
13 #include "include/core/SkTypes.h"
14 #include "include/private/base/SkNoncopyable.h"
15 #include "modules/svg/include/SkSVGTypes.h"
16 
17 #include "src/base/SkTLazy.h"
18 
19 #include <cstdint>
20 #include <cstring>
21 #include <tuple>
22 #include <vector>
23 
24 class SkMatrix;
25 class SkString;
26 
27 class SkSVGAttributeParser : public SkNoncopyable {
28 public:
29     SkSVGAttributeParser(const char[]);
30 
31     bool parseInteger(SkSVGIntegerType*);
32     bool parseViewBox(SkSVGViewBoxType*);
33     bool parsePreserveAspectRatio(SkSVGPreserveAspectRatio*);
34 
35     // TODO: Migrate all parse*() functions to this style (and delete the old version)
36     //      so they can be used by parse<T>():
parse(SkSVGIntegerType * v)37     bool parse(SkSVGIntegerType* v) { return parseInteger(v); }
38 
39     template <typename T> using ParseResult = SkTLazy<T>;
40 
parse(const char * value)41     template <typename T> static ParseResult<T> parse(const char* value) {
42         ParseResult<T> result;
43         T parsedValue;
44         if (SkSVGAttributeParser(value).parse(&parsedValue)) {
45             result.set(std::move(parsedValue));
46         }
47         return result;
48     }
49 
50     template <typename T>
parse(const char * expectedName,const char * name,const char * value)51     static ParseResult<T> parse(const char* expectedName,
52                                 const char* name,
53                                 const char* value) {
54         if (!strcmp(name, expectedName)) {
55             return parse<T>(value);
56         }
57 
58         return ParseResult<T>();
59     }
60 
61     template <typename PropertyT>
parseProperty(const char * expectedName,const char * name,const char * value)62     static ParseResult<PropertyT> parseProperty(const char* expectedName,
63                                                 const char* name,
64                                                 const char* value) {
65         if (strcmp(name, expectedName) != 0) {
66             return ParseResult<PropertyT>();
67         }
68 
69         if (!strcmp(value, "inherit")) {
70             PropertyT result(SkSVGPropertyState::kInherit);
71             return ParseResult<PropertyT>(&result);
72         }
73 
74         auto pr = parse<typename PropertyT::ValueT>(value);
75         if (pr.isValid()) {
76             PropertyT result(*pr);
77             return ParseResult<PropertyT>(&result);
78         }
79 
80         return ParseResult<PropertyT>();
81     }
82 
83 private:
84     class RestoreCurPos {
85     public:
RestoreCurPos(SkSVGAttributeParser * self)86         explicit RestoreCurPos(SkSVGAttributeParser* self)
87             : fSelf(self), fCurPos(self->fCurPos) {}
88 
~RestoreCurPos()89         ~RestoreCurPos() {
90             if (fSelf) {
91                 fSelf->fCurPos = this->fCurPos;
92             }
93         }
94 
clear()95         void clear() { fSelf = nullptr; }
96     private:
97         SkSVGAttributeParser* fSelf;
98         const char* fCurPos;
99 
100         RestoreCurPos(           const RestoreCurPos&) = delete;
101         RestoreCurPos& operator=(const RestoreCurPos&) = delete;
102     };
103 
104     // Stack-only
105     void* operator new(size_t) = delete;
106     void* operator new(size_t, void*) = delete;
107 
108     template <typename T>
109     bool parse(T*);
110 
111     template <typename F>
112     bool advanceWhile(F func);
113 
114     bool matchStringToken(const char* token, const char** newPos = nullptr) const;
115     bool matchHexToken(const char** newPos) const;
116 
117     bool parseWSToken();
118     bool parseEOSToken();
119     bool parseSepToken();
120     bool parseCommaWspToken();
121     bool parseExpectedStringToken(const char*);
122     bool parseScalarToken(SkScalar*);
123     bool parseInt32Token(int32_t*);
124     bool parseEscape(SkUnichar*);
125     bool parseIdentToken(SkString*);
126     bool parseLengthUnitToken(SkSVGLength::Unit*);
127     bool parseNamedColorToken(SkColor*);
128     bool parseHexColorToken(SkColor*);
129     bool parseColorComponentScalarToken(int32_t*);
130     bool parseColorComponentIntegralToken(int32_t*);
131     bool parseColorComponentFractionalToken(int32_t*);
132     bool parseColorComponentToken(int32_t*);
133     bool parseColorToken(SkColor*);
134     bool parseRGBColorToken(SkColor*);
135     bool parseRGBAColorToken(SkColor*);
136     bool parseSVGColor(SkSVGColor*, SkSVGColor::Vars&&);
137     bool parseSVGColorType(SkSVGColorType*);
138     bool parseFuncIRI(SkSVGFuncIRI*);
139 
140     // Transform helpers
141     bool parseMatrixToken(SkMatrix*);
142     bool parseTranslateToken(SkMatrix*);
143     bool parseScaleToken(SkMatrix*);
144     bool parseRotateToken(SkMatrix*);
145     bool parseSkewXToken(SkMatrix*);
146     bool parseSkewYToken(SkMatrix*);
147 
148     // Parses a sequence of 'WS* <prefix> WS* (<nested>)', where the nested sequence
149     // is handled by the passed functor.
150     template <typename Func, typename T>
151     bool parseParenthesized(const char* prefix, Func, T* result);
152 
153     template <typename T>
154     bool parseList(std::vector<T>*);
155 
156     template <typename T, typename TArray>
parseEnumMap(const TArray & arr,T * result)157     bool parseEnumMap(const TArray& arr, T* result) {
158         for (size_t i = 0; i < std::size(arr); ++i) {
159             if (this->parseExpectedStringToken(std::get<0>(arr[i]))) {
160                 *result = std::get<1>(arr[i]);
161                 return true;
162             }
163         }
164         return false;
165     }
166 
167     // The current position in the input string.
168     const char* fCurPos;
169     const char* fEndPos;
170 
171     using INHERITED = SkNoncopyable;
172 };
173 
174 #endif // SkSVGAttributeParser_DEFINED
175