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