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