ES-DE/external/lunasvg/source/parser.h

203 lines
6.5 KiB
C
Raw Permalink Normal View History

#ifndef PARSER_H
#define PARSER_H
#include <map>
#include <set>
#include "property.h"
#include "element.h"
namespace lunasvg {
class SVGElement;
class StyledElement;
enum LengthNegativeValuesMode {
AllowNegativeLengths,
ForbidNegativeLengths
};
enum class TransformType {
Matrix,
Rotate,
Scale,
SkewX,
SkewY,
Translate
};
class Parser {
public:
static Length parseLength(const std::string& string, LengthNegativeValuesMode mode, const Length& defaultValue);
static LengthList parseLengthList(const std::string& string, LengthNegativeValuesMode mode);
static double parseNumber(const std::string& string, double defaultValue);
static double parseNumberPercentage(const std::string& string, double defaultValue);
static PointList parsePointList(const std::string& string);
static Transform parseTransform(const std::string& string);
static Path parsePath(const std::string& string);
static std::string parseUrl(const std::string& string);
static std::string parseHref(const std::string& string);
static Rect parseViewBox(const std::string& string);
static PreserveAspectRatio parsePreserveAspectRatio(const std::string& string);
static Angle parseAngle(const std::string& string);
static MarkerUnits parseMarkerUnits(const std::string& string);
static SpreadMethod parseSpreadMethod(const std::string& string);
static Units parseUnits(const std::string& string, Units defaultValue);
static Color parseColor(const std::string& string, const StyledElement* element, const Color& defaultValue);
static Paint parsePaint(const std::string& string, const StyledElement* element, const Color& defaultValue);
static WindRule parseWindRule(const std::string& string);
static LineCap parseLineCap(const std::string& string);
static LineJoin parseLineJoin(const std::string& string);
static Display parseDisplay(const std::string& string);
static Visibility parseVisibility(const std::string& string);
static Overflow parseOverflow(const std::string& string, Overflow defaultValue);
private:
static bool parseLength(const char*& ptr, const char* end, double& value, LengthUnits& units, LengthNegativeValuesMode mode);
static bool parseNumberList(const char*& ptr, const char* end, double* values, int count);
static bool parseArcFlag(const char*& ptr, const char* end, bool& flag);
static bool parseColorComponent(const char*& ptr, const char* end, int& component);
static bool parseUrlFragment(const char*& ptr, const char* end, std::string& ref);
static bool parseTransform(const char*& ptr, const char* end, TransformType& type, double* values, int& count);
};
struct SimpleSelector;
using Selector = std::vector<SimpleSelector>;
using SelectorList = std::vector<Selector>;
struct AttributeSelector {
enum class MatchType {
None,
Equal,
Includes,
DashMatch,
StartsWith,
EndsWith,
Contains
};
MatchType matchType{MatchType::None};
PropertyID id{PropertyID::Unknown};
std::string value;
};
struct PseudoClassSelector {
enum class Type {
Unknown,
Empty,
Root,
Is,
Not,
FirstChild,
LastChild,
OnlyChild,
FirstOfType,
LastOfType,
OnlyOfType
};
Type type{Type::Unknown};
SelectorList subSelectors;
};
struct SimpleSelector {
enum class Combinator {
Descendant,
Child,
DirectAdjacent,
InDirectAdjacent
};
Combinator combinator{Combinator::Descendant};
ElementID id{ElementID::Star};
std::vector<AttributeSelector> attributeSelectors;
std::vector<PseudoClassSelector> pseudoClassSelectors;
};
struct Declaration {
int specificity;
PropertyID id;
std::string value;
};
using DeclarationList = std::vector<Declaration>;
struct Rule {
SelectorList selectors;
DeclarationList declarations;
};
class RuleData {
public:
RuleData(const Selector& selector, const DeclarationList& declarations, uint32_t specificity, uint32_t position)
: m_selector(selector), m_declarations(declarations), m_specificity(specificity), m_position(position)
{}
const Selector& selector() const { return m_selector; }
const DeclarationList& declarations() const { return m_declarations; }
const uint32_t& specificity() const { return m_specificity; }
const uint32_t& position() const { return m_position; }
bool match(const Element* element) const;
private:
static bool matchSimpleSelector(const SimpleSelector& selector, const Element* element);
static bool matchAttributeSelector(const AttributeSelector& selector, const Element* element);
static bool matchPseudoClassSelector(const PseudoClassSelector& selector, const Element* element);
private:
Selector m_selector;
DeclarationList m_declarations;
uint32_t m_specificity;
uint32_t m_position;
};
inline bool operator<(const RuleData& a, const RuleData& b) { return std::tie(a.specificity(), a.position()) < std::tie(b.specificity(), b.position()); }
inline bool operator>(const RuleData& a, const RuleData& b) { return std::tie(a.specificity(), a.position()) > std::tie(b.specificity(), b.position()); }
class StyleSheet {
public:
StyleSheet() = default;
bool parse(const std::string& content);
void add(const Rule& rule);
bool empty() const { return m_rules.empty(); }
const std::multiset<RuleData>& rules() const { return m_rules; }
private:
static bool parseAtRule(const char*& ptr, const char* end);
static bool parseRule(const char*& ptr, const char* end, Rule& rule);
static bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors);
static bool parseDeclarations(const char*& ptr, const char* end, DeclarationList& declarations);
static bool parseSelector(const char*& ptr, const char* end, Selector& selector);
static bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector);
private:
std::multiset<RuleData> m_rules;
uint32_t m_position{0};
};
class LayoutSymbol;
class TreeBuilder {
public:
TreeBuilder();
~TreeBuilder();
bool parse(const char* data, std::size_t size);
SVGElement* rootElement() const { return m_rootElement.get(); }
Element* getElementById(const std::string& id) const;
std::unique_ptr<LayoutSymbol> build() const;
private:
std::unique_ptr<SVGElement> m_rootElement;
std::map<std::string, Element*> m_idCache;
};
} // namespace lunasvg
#endif // PARSER_H