mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 07:35:38 +00:00
Merge commit '3acd894f373efcdc18f682a826f78f6722f32c59' into new-svg-renderer
This commit is contained in:
commit
261f699bb6
|
@ -13,7 +13,7 @@ static SW_FT_Outline* sw_ft_outline_create(int points, int contours)
|
|||
SW_FT_Outline* ft = malloc(sizeof(SW_FT_Outline));
|
||||
ft->points = malloc((size_t)(points + contours) * sizeof(SW_FT_Vector));
|
||||
ft->tags = malloc((size_t)(points + contours) * sizeof(char));
|
||||
ft->contours = malloc((size_t)contours * sizeof(short));
|
||||
ft->contours = malloc((size_t)contours * sizeof(int));
|
||||
ft->contours_flag = malloc((size_t)contours * sizeof(char));
|
||||
ft->n_points = ft->n_contours = 0;
|
||||
ft->flags = 0x0;
|
||||
|
|
|
@ -114,12 +114,12 @@
|
|||
/* */
|
||||
typedef struct SW_FT_Outline_
|
||||
{
|
||||
short n_contours; /* number of contours in glyph */
|
||||
short n_points; /* number of points in the glyph */
|
||||
int n_contours; /* number of contours in glyph */
|
||||
int n_points; /* number of points in the glyph */
|
||||
|
||||
SW_FT_Vector* points; /* the outline's points */
|
||||
char* tags; /* the points flags */
|
||||
short* contours; /* the contour end points */
|
||||
int* contours; /* the contour end points */
|
||||
char* contours_flag; /* the contour open flags */
|
||||
|
||||
int flags; /* outline masks */
|
||||
|
|
|
@ -650,8 +650,8 @@ static void ft_stroke_border_export(SW_FT_StrokeBorder border,
|
|||
{
|
||||
SW_FT_UInt count = border->num_points;
|
||||
SW_FT_Byte* tags = border->tags;
|
||||
SW_FT_Short* write = outline->contours + outline->n_contours;
|
||||
SW_FT_Short idx = (SW_FT_Short)outline->n_points;
|
||||
SW_FT_Int* write = outline->contours + outline->n_contours;
|
||||
SW_FT_Int idx = (SW_FT_Int)outline->n_points;
|
||||
|
||||
for (; count > 0; count--, tags++, idx++) {
|
||||
if (*tags & SW_FT_STROKE_TAG_END) {
|
||||
|
@ -661,7 +661,7 @@ static void ft_stroke_border_export(SW_FT_StrokeBorder border,
|
|||
}
|
||||
}
|
||||
|
||||
outline->n_points = (short)(outline->n_points + border->num_points);
|
||||
outline->n_points = (int)(outline->n_points + border->num_points);
|
||||
|
||||
assert(SW_FT_Outline_Check(outline) == 0);
|
||||
}
|
||||
|
|
2
external/lunasvg/CMakeLists.txt
vendored
2
external/lunasvg/CMakeLists.txt
vendored
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.3)
|
|||
|
||||
project(lunasvg VERSION 2.3.2 LANGUAGES CXX C)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
option(BUILD_SHARED_LIBS "Builds as shared library" OFF)
|
||||
|
|
63
external/lunasvg/include/lunasvg.h
vendored
63
external/lunasvg/include/lunasvg.h
vendored
|
@ -39,6 +39,7 @@
|
|||
namespace lunasvg {
|
||||
|
||||
class Rect;
|
||||
class Matrix;
|
||||
|
||||
class LUNASVG_API Box
|
||||
{
|
||||
|
@ -47,6 +48,9 @@ public:
|
|||
Box(double x, double y, double w, double h);
|
||||
Box(const Rect& rect);
|
||||
|
||||
Box& transform(const Matrix& matrix);
|
||||
Box transformed(const Matrix& matrix) const;
|
||||
|
||||
public:
|
||||
double x{0};
|
||||
double y{0};
|
||||
|
@ -78,7 +82,6 @@ public:
|
|||
|
||||
Matrix inverted() const;
|
||||
Matrix operator*(const Matrix& matrix) const;
|
||||
Box map(const Box& box) const;
|
||||
|
||||
static Matrix rotated(double angle);
|
||||
static Matrix rotated(double angle, double cx, double cy);
|
||||
|
@ -159,63 +162,9 @@ public:
|
|||
static std::unique_ptr<Document> loadFromData(const char* data);
|
||||
|
||||
/**
|
||||
* @brief Pre-Rotates the document matrix clockwise around the current origin
|
||||
* @param angle - rotation angle, in degrees
|
||||
* @return this
|
||||
* @brief Sets the current transformation matrix of the document
|
||||
* @param matrix - current transformation matrix
|
||||
*/
|
||||
Document* rotate(double angle);
|
||||
|
||||
/**
|
||||
* @brief Pre-Rotates the document matrix clockwise around the given point
|
||||
* @param angle - rotation angle, in degrees
|
||||
* @param cx - horizontal translation
|
||||
* @param cy - vertical translation
|
||||
* @return this
|
||||
*/
|
||||
Document* rotate(double angle, double cx, double cy);
|
||||
|
||||
/**
|
||||
* @brief Pre-Scales the document matrix by sx horizontally and sy vertically
|
||||
* @param sx - horizontal scale factor
|
||||
* @param sy - vertical scale factor
|
||||
* @return this
|
||||
*/
|
||||
Document* scale(double sx, double sy);
|
||||
|
||||
/**
|
||||
* @brief Pre-Shears the document matrix by shx horizontally and shy vertically
|
||||
* @param shx - horizontal skew factor, in degree
|
||||
* @param shy - vertical skew factor, in degree
|
||||
* @return this
|
||||
*/
|
||||
Document* shear(double shx, double shy);
|
||||
|
||||
/**
|
||||
* @brief Pre-Translates the document matrix by tx horizontally and ty vertically
|
||||
* @param tx - horizontal translation
|
||||
* @param ty - vertical translation
|
||||
* @return this
|
||||
*/
|
||||
Document* translate(double tx, double ty);
|
||||
|
||||
/**
|
||||
* @brief Pre-Multiplies the document matrix by Matrix(a, b, c, d, e, f)
|
||||
* @param a - horizontal scale factor
|
||||
* @param b - horizontal skew factor
|
||||
* @param c - vertical skew factor
|
||||
* @param d - vertical scale factor
|
||||
* @param e - horizontal translation
|
||||
* @param f - vertical translation
|
||||
* @return this
|
||||
*/
|
||||
Document* transform(double a, double b, double c, double d, double e, double f);
|
||||
|
||||
/**
|
||||
* @brief Resets the document matrix to identity
|
||||
* @return this
|
||||
*/
|
||||
Document* identity();
|
||||
|
||||
void setMatrix(const Matrix& matrix);
|
||||
|
||||
/**
|
||||
|
|
2
external/lunasvg/source/CMakeLists.txt
vendored
2
external/lunasvg/source/CMakeLists.txt
vendored
|
@ -20,6 +20,8 @@ PRIVATE
|
|||
"${CMAKE_CURRENT_LIST_DIR}/svgelement.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/symbolelement.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/useelement.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/cssparser.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/cssstylesheet.cpp"
|
||||
)
|
||||
|
||||
target_include_directories(lunasvg
|
||||
|
|
8
external/lunasvg/source/canvas.cpp
vendored
8
external/lunasvg/source/canvas.cpp
vendored
|
@ -9,7 +9,7 @@ static plutovg_fill_rule_t to_plutovg_fill_rule(WindRule winding);
|
|||
static plutovg_operator_t to_plutovg_operator(BlendMode mode);
|
||||
static plutovg_line_cap_t to_plutovg_line_cap(LineCap cap);
|
||||
static plutovg_line_join_t to_plutovg_line_join(LineJoin join);
|
||||
static plutovg_spread_method_t to_plutovg_spread_methood(SpreadMethod spread);
|
||||
static plutovg_spread_method_t to_plutovg_spread_method(SpreadMethod spread);
|
||||
static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops& stops);
|
||||
static void to_plutovg_path(plutovg_t* pluto, const Path& path);
|
||||
|
||||
|
@ -67,7 +67,7 @@ void Canvas::setLinearGradient(double x1, double y1, double x2, double y2, const
|
|||
auto gradient = plutovg_gradient_create_linear(x1, y1, x2, y2);
|
||||
auto matrix = to_plutovg_matrix(transform);
|
||||
to_plutovg_stops(gradient, stops);
|
||||
plutovg_gradient_set_spread(gradient, to_plutovg_spread_methood(spread));
|
||||
plutovg_gradient_set_spread(gradient, to_plutovg_spread_method(spread));
|
||||
plutovg_gradient_set_matrix(gradient, &matrix);
|
||||
plutovg_set_source_gradient(pluto, gradient);
|
||||
plutovg_gradient_destroy(gradient);
|
||||
|
@ -78,7 +78,7 @@ void Canvas::setRadialGradient(double cx, double cy, double r, double fx, double
|
|||
auto gradient = plutovg_gradient_create_radial(cx, cy, r, fx, fy, 0);
|
||||
auto matrix = to_plutovg_matrix(transform);
|
||||
to_plutovg_stops(gradient, stops);
|
||||
plutovg_gradient_set_spread(gradient, to_plutovg_spread_methood(spread));
|
||||
plutovg_gradient_set_spread(gradient, to_plutovg_spread_method(spread));
|
||||
plutovg_gradient_set_matrix(gradient, &matrix);
|
||||
plutovg_set_source_gradient(pluto, gradient);
|
||||
plutovg_gradient_destroy(gradient);
|
||||
|
@ -227,7 +227,7 @@ plutovg_line_join_t to_plutovg_line_join(LineJoin join)
|
|||
return join == LineJoin::Miter ? plutovg_line_join_miter : join == LineJoin::Round ? plutovg_line_join_round : plutovg_line_join_bevel;
|
||||
}
|
||||
|
||||
static plutovg_spread_method_t to_plutovg_spread_methood(SpreadMethod spread)
|
||||
static plutovg_spread_method_t to_plutovg_spread_method(SpreadMethod spread)
|
||||
{
|
||||
return spread == SpreadMethod::Pad ? plutovg_spread_method_pad : spread == SpreadMethod::Reflect ? plutovg_spread_method_reflect : plutovg_spread_method_repeat;
|
||||
}
|
||||
|
|
4
external/lunasvg/source/clippathelement.cpp
vendored
4
external/lunasvg/source/clippathelement.cpp
vendored
|
@ -5,13 +5,13 @@
|
|||
namespace lunasvg {
|
||||
|
||||
ClipPathElement::ClipPathElement()
|
||||
: GraphicsElement(ElementId::ClipPath)
|
||||
: GraphicsElement(ElementID::ClipPath)
|
||||
{
|
||||
}
|
||||
|
||||
Units ClipPathElement::clipPathUnits() const
|
||||
{
|
||||
auto& value = get(PropertyId::ClipPathUnits);
|
||||
auto& value = get(PropertyID::ClipPathUnits);
|
||||
return Parser::parseUnits(value, Units::UserSpaceOnUse);
|
||||
}
|
||||
|
||||
|
|
1816
external/lunasvg/source/cssparser.cpp
vendored
Normal file
1816
external/lunasvg/source/cssparser.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
305
external/lunasvg/source/cssparser.h
vendored
Normal file
305
external/lunasvg/source/cssparser.h
vendored
Normal file
|
@ -0,0 +1,305 @@
|
|||
#ifndef CSSPARSER_H
|
||||
#define CSSPARSER_H
|
||||
|
||||
#include "parserutils.h"
|
||||
#include "cssstylesheet.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace lunasvg {
|
||||
|
||||
class CSSToken {
|
||||
public:
|
||||
enum class Type : uint8_t {
|
||||
Unknown,
|
||||
Ident,
|
||||
Function,
|
||||
AtKeyword,
|
||||
Hash,
|
||||
String,
|
||||
BadString,
|
||||
Url,
|
||||
BadUrl,
|
||||
Delim,
|
||||
Number,
|
||||
Percentage,
|
||||
Dimension,
|
||||
Whitespace,
|
||||
Comment,
|
||||
CDO,
|
||||
CDC,
|
||||
Colon,
|
||||
Semicolon,
|
||||
Comma,
|
||||
LeftParenthesis,
|
||||
RightParenthesis,
|
||||
LeftSquareBracket,
|
||||
RightSquareBracket,
|
||||
LeftCurlyBracket,
|
||||
RightCurlyBracket,
|
||||
EndOfFile
|
||||
};
|
||||
|
||||
enum class HashType : uint8_t {
|
||||
Identifier,
|
||||
Unrestricted
|
||||
};
|
||||
|
||||
enum class NumberType : uint8_t {
|
||||
Integer,
|
||||
Number
|
||||
};
|
||||
|
||||
enum class NumberSign : uint8_t {
|
||||
None,
|
||||
Plus,
|
||||
Minus
|
||||
};
|
||||
|
||||
CSSToken() = default;
|
||||
explicit CSSToken(Type type) : m_type(type) {}
|
||||
CSSToken(Type type, uint32_t delim) : m_type(type), m_delim(delim) {}
|
||||
CSSToken(Type type, std::string_view data) : m_type(type), m_data(data) {}
|
||||
CSSToken(Type type, HashType hashType, std::string_view data) : m_type(type), m_hashType(hashType), m_data(data) {}
|
||||
|
||||
CSSToken(Type type, NumberType numberType, NumberSign numberSign, double number)
|
||||
: m_type(type), m_numberType(numberType), m_numberSign(numberSign), m_number(number)
|
||||
{}
|
||||
|
||||
CSSToken(Type type, NumberType numberType, NumberSign numberSign, double number, std::string_view unit)
|
||||
: m_type(type), m_numberType(numberType), m_numberSign(numberSign), m_number(number), m_data(unit)
|
||||
{}
|
||||
|
||||
Type type() const { return m_type; }
|
||||
HashType hashType() const { return m_hashType; }
|
||||
NumberType numberType() const { return m_numberType; }
|
||||
NumberSign numberSign() const { return m_numberSign; }
|
||||
uint32_t delim() const { return m_delim; }
|
||||
double number() const { return m_number; }
|
||||
int integer() const { return static_cast<int>(m_number); }
|
||||
const std::string_view& data() const { return m_data; }
|
||||
|
||||
static Type closeType(Type type) {
|
||||
switch(type) {
|
||||
case Type::Function:
|
||||
case Type::LeftParenthesis:
|
||||
return Type::RightParenthesis;
|
||||
case Type::LeftSquareBracket:
|
||||
return Type::RightSquareBracket;
|
||||
case Type::LeftCurlyBracket:
|
||||
return Type::RightCurlyBracket;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Type m_type{Type::Unknown};
|
||||
HashType m_hashType{HashType::Identifier};
|
||||
NumberType m_numberType{NumberType::Integer};
|
||||
NumberSign m_numberSign{NumberSign::None};
|
||||
uint32_t m_delim{0};
|
||||
double m_number{0};
|
||||
std::string_view m_data;
|
||||
};
|
||||
|
||||
using CSSTokenList = std::vector<CSSToken>;
|
||||
|
||||
class CSSTokenStream {
|
||||
public:
|
||||
CSSTokenStream(const CSSToken* begin, const CSSToken* end)
|
||||
: m_begin(begin), m_end(end)
|
||||
{}
|
||||
|
||||
const CSSToken& peek() const {
|
||||
static const CSSToken EndOfFileToken(CSSToken::Type::EndOfFile);
|
||||
if(m_begin == m_end)
|
||||
return EndOfFileToken;
|
||||
return *m_begin;
|
||||
}
|
||||
|
||||
void consume() {
|
||||
assert(m_begin < m_end);
|
||||
m_begin += 1;
|
||||
}
|
||||
|
||||
void consumeWhitespace() {
|
||||
while(m_begin < m_end && m_begin->type() == CSSToken::Type::Whitespace) {
|
||||
m_begin += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void consumeIncludingWhitespace() {
|
||||
assert(m_begin < m_end);
|
||||
do {
|
||||
m_begin += 1;
|
||||
} while(m_begin < m_end && m_begin->type() == CSSToken::Type::Whitespace);
|
||||
}
|
||||
|
||||
void consumeComponent() {
|
||||
assert(m_begin < m_end);
|
||||
switch(m_begin->type()) {
|
||||
case CSSToken::Type::Function:
|
||||
case CSSToken::Type::LeftParenthesis:
|
||||
case CSSToken::Type::LeftSquareBracket:
|
||||
case CSSToken::Type::LeftCurlyBracket: {
|
||||
auto closeType = CSSToken::closeType(m_begin->type());
|
||||
m_begin += 1;
|
||||
while(m_begin < m_end && m_begin->type() != closeType)
|
||||
consumeComponent();
|
||||
if(m_begin < m_end)
|
||||
m_begin += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
m_begin += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CSSTokenStream consumeBlock() {
|
||||
assert(m_begin < m_end);
|
||||
auto closeType = CSSToken::closeType(m_begin->type());
|
||||
m_begin += 1;
|
||||
auto blockBegin = m_begin;
|
||||
while(m_begin < m_end && m_begin->type() != closeType)
|
||||
consumeComponent();
|
||||
auto blockEnd = m_begin;
|
||||
if(m_begin < m_end)
|
||||
m_begin += 1;
|
||||
return CSSTokenStream(blockBegin, blockEnd);
|
||||
}
|
||||
|
||||
bool empty() const { return m_begin == m_end; }
|
||||
|
||||
const CSSToken& operator*() const { return peek(); }
|
||||
const CSSToken* operator->() const { return &peek(); }
|
||||
|
||||
const CSSToken* begin() const { return m_begin; }
|
||||
const CSSToken* end() const { return m_end; }
|
||||
|
||||
private:
|
||||
const CSSToken* m_begin;
|
||||
const CSSToken* m_end;
|
||||
};
|
||||
|
||||
class CSSTokenStreamGuard {
|
||||
public:
|
||||
CSSTokenStreamGuard(CSSTokenStream& input)
|
||||
: m_input(input), m_state(input)
|
||||
{}
|
||||
|
||||
void release() { m_state = m_input; }
|
||||
|
||||
~CSSTokenStreamGuard() { m_input = m_state; }
|
||||
|
||||
private:
|
||||
CSSTokenStream& m_input;
|
||||
CSSTokenStream m_state;
|
||||
};
|
||||
|
||||
class CSSTokenizer {
|
||||
public:
|
||||
CSSTokenizer(const std::string_view& input)
|
||||
: m_input(input)
|
||||
{}
|
||||
|
||||
CSSTokenStream tokenize();
|
||||
|
||||
private:
|
||||
static bool isEscapeSequence(char first, char second);
|
||||
static bool isIdentSequence(char first, char second, char third);
|
||||
static bool isNumberSequence(char first, char second, char third);
|
||||
|
||||
bool isEscapeSequence() const;
|
||||
bool isIdentSequence() const;
|
||||
bool isNumberSequence() const;
|
||||
bool isExponentSequence() const;
|
||||
|
||||
std::string_view substring(size_t offset, size_t count);
|
||||
std::string_view addstring(std::string&& value);
|
||||
|
||||
std::string_view consumeName();
|
||||
uint32_t consumeEscape();
|
||||
|
||||
CSSToken consumeStringToken();
|
||||
CSSToken consumeNumericToken();
|
||||
CSSToken consumeIdentLikeToken();
|
||||
CSSToken consumeUrlToken();
|
||||
CSSToken consumeBadUrlRemnants();
|
||||
CSSToken consumeWhitespaceToken();
|
||||
CSSToken consumeCommentToken();
|
||||
CSSToken consumeSolidusToken();
|
||||
CSSToken consumeHashToken();
|
||||
CSSToken consumePlusSignToken();
|
||||
CSSToken consumeHyphenMinusToken();
|
||||
CSSToken consumeFullStopToken();
|
||||
CSSToken consumeLessThanSignToken();
|
||||
CSSToken consumeCommercialAtToken();
|
||||
CSSToken consumeReverseSolidusToken();
|
||||
|
||||
CSSToken nextToken();
|
||||
|
||||
private:
|
||||
using StringList = std::vector<std::string>;
|
||||
ParserString m_input;
|
||||
CSSTokenList m_tokenList;
|
||||
StringList m_stringList;
|
||||
};
|
||||
|
||||
class CSSParser {
|
||||
public:
|
||||
static void parseSheet(CSSRuleList& rules, const std::string_view& content);
|
||||
static void parseStyle(CSSPropertyList& properties, const std::string_view& content);
|
||||
|
||||
private:
|
||||
static bool consumeRule(CSSTokenStream& input, CSSRuleList& rules);
|
||||
static bool consumeStyleRule(CSSTokenStream& input, CSSRuleList& rules);
|
||||
static bool consumeAtRule(CSSTokenStream& input, CSSRuleList& rules);
|
||||
static bool consumeImportRule(CSSTokenStream& input, CSSRuleList& rules);
|
||||
|
||||
static bool consumeSelectorList(CSSTokenStream& input, CSSSelectorList& selectors);
|
||||
static bool consumeSelector(CSSTokenStream& input, CSSSelector& selector);
|
||||
static bool consumeSimpleSelector(CSSTokenStream& input, CSSSimpleSelector& selector);
|
||||
static bool consumeTagSelector(CSSTokenStream& input, CSSSimpleSelector& selector);
|
||||
static bool consumeIdSelector(CSSTokenStream& input, CSSSimpleSelector& selector);
|
||||
static bool consumeClassSelector(CSSTokenStream& input, CSSSimpleSelector& selector);
|
||||
static bool consumeAttributeSelector(CSSTokenStream& input, CSSSimpleSelector& selector);
|
||||
static bool consumePseudoSelector(CSSTokenStream& input, CSSSimpleSelector& selector);
|
||||
|
||||
static bool consumeCombinator(CSSTokenStream& input, CSSSimpleSelector::Combinator& combinator);
|
||||
static bool consumeMatchPattern(CSSTokenStream& input, CSSSimpleSelector::Pseudo::MatchPattern& pattern);
|
||||
|
||||
static void consumeDeclaractionList(CSSTokenStream& input, CSSPropertyList& properties);
|
||||
static bool consumeDeclaraction(CSSTokenStream& input, CSSPropertyList& properties);
|
||||
static bool consumeDeclaractionValue(CSSTokenStream& input, CSSPropertyList& properties, CSSPropertyID id, bool important);
|
||||
|
||||
static RefPtr<CSSValue> consumeNone(CSSTokenStream& input);
|
||||
static RefPtr<CSSValue> consumeNormal(CSSTokenStream& input);
|
||||
|
||||
static RefPtr<CSSValue> consumePercent(CSSTokenStream& input, bool negative);
|
||||
static RefPtr<CSSValue> consumeNumber(CSSTokenStream& input, bool negative);
|
||||
static RefPtr<CSSValue> consumeLength(CSSTokenStream& input, bool negative, bool unitless);
|
||||
static RefPtr<CSSValue> consumeLengthOrNormal(CSSTokenStream& input, bool negative, bool unitless);
|
||||
static RefPtr<CSSValue> consumeLengthOrPercent(CSSTokenStream& input, bool negative, bool unitless);
|
||||
static RefPtr<CSSValue> consumeNumberOrPercent(CSSTokenStream& input, bool negative);
|
||||
|
||||
static RefPtr<CSSValue> consumeUrl(CSSTokenStream& input);
|
||||
static RefPtr<CSSValue> consumeUrlOrNone(CSSTokenStream& input);
|
||||
static RefPtr<CSSValue> consumeColor(CSSTokenStream& input);
|
||||
static RefPtr<CSSValue> consumeRgb(CSSTokenStream& input);
|
||||
static RefPtr<CSSValue> consumeFillOrStroke(CSSTokenStream& input);
|
||||
static RefPtr<CSSValue> consumeDashList(CSSTokenStream& input);
|
||||
|
||||
static RefPtr<CSSValue> consumeFontWeight(CSSTokenStream& input);
|
||||
static RefPtr<CSSValue> consumeFontSize(CSSTokenStream& input, bool unitless);
|
||||
static RefPtr<CSSValue> consumeFontFamilyValue(CSSTokenStream& input);
|
||||
static RefPtr<CSSValue> consumeFontFamily(CSSTokenStream& input);
|
||||
|
||||
static RefPtr<CSSValue> consumeValue(CSSTokenStream& input, CSSPropertyID id);
|
||||
};
|
||||
|
||||
} // namespace lunasvg
|
||||
|
||||
#endif // CSSPARSER_H
|
378
external/lunasvg/source/cssstylesheet.cpp
vendored
Normal file
378
external/lunasvg/source/cssstylesheet.cpp
vendored
Normal file
|
@ -0,0 +1,378 @@
|
|||
#include "cssstylesheet.h"
|
||||
#include "cssparser.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace lunasvg {
|
||||
|
||||
RefPtr<CSSInitialValue> CSSInitialValue::create()
|
||||
{
|
||||
static auto value = adoptPtr(new CSSInitialValue);
|
||||
return value;
|
||||
}
|
||||
|
||||
RefPtr<CSSInheritValue> CSSInheritValue::create()
|
||||
{
|
||||
static auto value = adoptPtr(new CSSInheritValue);
|
||||
return value;
|
||||
}
|
||||
|
||||
RefPtr<CSSIdentValue> CSSIdentValue::create(CSSValueID value)
|
||||
{
|
||||
static std::map<CSSValueID, RefPtr<CSSIdentValue>> table;
|
||||
auto it = table.find(value);
|
||||
if(it == table.end()) {
|
||||
auto item = adoptPtr(new CSSIdentValue(value));
|
||||
table.emplace(value, item);
|
||||
return item;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
RefPtr<CSSIntegerValue> CSSIntegerValue::create(int value)
|
||||
{
|
||||
return adoptPtr(new CSSIntegerValue(value));
|
||||
}
|
||||
|
||||
RefPtr<CSSNumberValue> CSSNumberValue::create(double value)
|
||||
{
|
||||
return adoptPtr(new CSSNumberValue(value));
|
||||
}
|
||||
|
||||
RefPtr<CSSPercentValue> CSSPercentValue::create(double value)
|
||||
{
|
||||
return adoptPtr(new CSSPercentValue(value));
|
||||
}
|
||||
|
||||
RefPtr<CSSLengthValue> CSSLengthValue::create(double value, Unit unit)
|
||||
{
|
||||
return adoptPtr(new CSSLengthValue(value, unit));
|
||||
}
|
||||
|
||||
RefPtr<CSSStringValue> CSSStringValue::create(std::string value)
|
||||
{
|
||||
return adoptPtr(new CSSStringValue(std::move(value)));
|
||||
}
|
||||
|
||||
RefPtr<CSSUrlValue> CSSUrlValue::create(std::string value)
|
||||
{
|
||||
return adoptPtr(new CSSUrlValue(std::move(value)));
|
||||
}
|
||||
|
||||
RefPtr<CSSColorValue> CSSColorValue::create(uint32_t value)
|
||||
{
|
||||
return adoptPtr(new CSSColorValue(value));
|
||||
}
|
||||
|
||||
RefPtr<CSSColorValue> CSSColorValue::create(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
return adoptPtr(new CSSColorValue(a << 24 | r << 16 | g << 8 | b));
|
||||
}
|
||||
|
||||
RefPtr<CSSPairValue> CSSPairValue::create(RefPtr<CSSValue> first, RefPtr<CSSValue> second)
|
||||
{
|
||||
return adoptPtr(new CSSPairValue(std::move(first), std::move(second)));
|
||||
}
|
||||
|
||||
RefPtr<CSSListValue> CSSListValue::create(CSSValueList values)
|
||||
{
|
||||
return adoptPtr(new CSSListValue(std::move(values)));
|
||||
}
|
||||
|
||||
CSSPropertyID csspropertyid(const std::string_view& name)
|
||||
{
|
||||
static const struct {
|
||||
std::string_view name;
|
||||
CSSPropertyID value;
|
||||
} table[] = {
|
||||
{"clip-path", CSSPropertyID::Clip_Path},
|
||||
{"clip-rule", CSSPropertyID::Clip_Rule},
|
||||
{"color", CSSPropertyID::Color},
|
||||
{"display", CSSPropertyID::Display},
|
||||
{"fill", CSSPropertyID::Fill},
|
||||
{"fill-opacity", CSSPropertyID::Fill_Opacity},
|
||||
{"fill-rule", CSSPropertyID::Fill_Rule},
|
||||
{"font-family", CSSPropertyID::Font_Family},
|
||||
{"font-size", CSSPropertyID::Font_Size},
|
||||
{"font-style", CSSPropertyID::Font_Style},
|
||||
{"font-variant", CSSPropertyID::Font_Variant},
|
||||
{"font-weight", CSSPropertyID::Font_Weight},
|
||||
{"letter-spacing", CSSPropertyID::Letter_Spacing},
|
||||
{"marker-end", CSSPropertyID::Marker_End},
|
||||
{"marker-mid", CSSPropertyID::Marker_Mid},
|
||||
{"marker-start", CSSPropertyID::Marker_Start},
|
||||
{"mask", CSSPropertyID::Mask},
|
||||
{"opacity", CSSPropertyID::Opacity},
|
||||
{"overflow", CSSPropertyID::Overflow},
|
||||
{"solid-color", CSSPropertyID::Solid_Color},
|
||||
{"solid-opacity", CSSPropertyID::Solid_Opacity},
|
||||
{"stop-color", CSSPropertyID::Stop_Color},
|
||||
{"stop-opacity", CSSPropertyID::Stop_Opacity},
|
||||
{"stroke", CSSPropertyID::Stroke},
|
||||
{"stroke-dasharray", CSSPropertyID::Stroke_Dasharray},
|
||||
{"stroke-dashoffset", CSSPropertyID::Stroke_Dashoffset},
|
||||
{"stroke-linecap", CSSPropertyID::Stroke_Linecap},
|
||||
{"stroke-linejoin", CSSPropertyID::Stroke_Linejoin},
|
||||
{"stroke-miterlimit", CSSPropertyID::Stroke_Miterlimit},
|
||||
{"stroke-opacity", CSSPropertyID::Stroke_Opacity},
|
||||
{"stroke-width", CSSPropertyID::Stroke_Width},
|
||||
{"text-anchor", CSSPropertyID::Text_Anchor},
|
||||
{"text-decoration", CSSPropertyID::Text_Decoration},
|
||||
{"visibility", CSSPropertyID::Visibility},
|
||||
{"word-spacing", CSSPropertyID::Word_Spacing},
|
||||
};
|
||||
|
||||
auto it = std::lower_bound(table, std::end(table), name, [](auto& item, auto& name) { return item.name < name; });
|
||||
if(it != std::end(table) && it->name == name)
|
||||
return it->value;
|
||||
return CSSPropertyID::Unknown;
|
||||
}
|
||||
|
||||
bool CSSSimpleSelector::Pseudo::matchnth(size_t count) const
|
||||
{
|
||||
auto [a, b] = pattern;
|
||||
if(a == 0)
|
||||
return count == b;
|
||||
if(a > 0) {
|
||||
if(count < b)
|
||||
return false;
|
||||
return (count - b) % a == 0;
|
||||
}
|
||||
|
||||
if(count > b)
|
||||
return false;
|
||||
return (b - count) % -a == 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<CSSRule> CSSRule::create(CSSSelectorList selectors, CSSPropertyList properties)
|
||||
{
|
||||
return std::unique_ptr<CSSRule>(new CSSRule(std::move(selectors), std::move(properties)));
|
||||
}
|
||||
|
||||
bool CSSRuleData::match(const Element* element) const
|
||||
{
|
||||
if(m_selector.empty())
|
||||
return false;
|
||||
|
||||
if(m_selector.size() == 1)
|
||||
return matchSimpleSelector(m_selector.front(), element);
|
||||
|
||||
auto it = m_selector.rbegin();
|
||||
auto end = m_selector.rend();
|
||||
if(!matchSimpleSelector(*it, element))
|
||||
return false;
|
||||
++it;
|
||||
|
||||
while(it != end) {
|
||||
switch(it->combinator) {
|
||||
case CSSSimpleSelector::Combinator::Child:
|
||||
case CSSSimpleSelector::Combinator::Descendant:
|
||||
element = element->parent;
|
||||
break;
|
||||
case CSSSimpleSelector::Combinator::DirectAdjacent:
|
||||
case CSSSimpleSelector::Combinator::InDirectAdjacent:
|
||||
element = element->previousElement();
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if(element == nullptr)
|
||||
return false;
|
||||
|
||||
auto match = matchSimpleSelector(*it, element);
|
||||
if(!match && (it->combinator != CSSSimpleSelector::Combinator::Descendant && it->combinator != CSSSimpleSelector::Combinator::InDirectAdjacent))
|
||||
return false;
|
||||
|
||||
if(match || (it->combinator != CSSSimpleSelector::Combinator::Descendant && it->combinator != CSSSimpleSelector::Combinator::InDirectAdjacent))
|
||||
++it;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSSRuleData::matchSimpleSelector(const CSSSimpleSelector& selector, const Element* element)
|
||||
{
|
||||
if(selector.id != ElementID::Star && selector.id != element->id)
|
||||
return false;
|
||||
|
||||
for(auto& attribute : selector.attributes)
|
||||
if(!matchAttributeSelector(attribute, element))
|
||||
return false;
|
||||
|
||||
for(auto& pseudo : selector.pseudos)
|
||||
if(!matchPseudoClassSelector(pseudo, element))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSSRuleData::matchAttributeSelector(const CSSSimpleSelector::Attribute& attribute, const Element* element)
|
||||
{
|
||||
auto& value = element->get(attribute.id);
|
||||
switch(attribute.type) {
|
||||
case CSSSimpleSelector::Attribute::Type::None:
|
||||
return !value.empty();
|
||||
case CSSSimpleSelector::Attribute::Type::Equals:
|
||||
return equals(value, attribute.value, false);
|
||||
case CSSSimpleSelector::Attribute::Type::Contains:
|
||||
return contains(value, attribute.value, false);
|
||||
case CSSSimpleSelector::Attribute::Type::Includes:
|
||||
return includes(value, attribute.value, false);
|
||||
case CSSSimpleSelector::Attribute::Type::StartsWith:
|
||||
return startswith(value, attribute.value, false);
|
||||
case CSSSimpleSelector::Attribute::Type::EndsWith:
|
||||
return endswith(value, attribute.value, false);
|
||||
case CSSSimpleSelector::Attribute::Type::DashEquals:
|
||||
return dashequals(value, attribute.value, false);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CSSRuleData::matchPseudoClassSelector(const CSSSimpleSelector::Pseudo& pseudo, const Element* element)
|
||||
{
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::Empty)
|
||||
return element->children.empty();
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::Root)
|
||||
return element->parent == nullptr;
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::Is) {
|
||||
for(auto& selector : pseudo.selectors) {
|
||||
for(auto& sel : selector) {
|
||||
if(!matchSimpleSelector(sel, element)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::Not) {
|
||||
for(auto& selector : pseudo.selectors) {
|
||||
for(auto& sel : selector) {
|
||||
if(matchSimpleSelector(sel, element)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::FirstChild)
|
||||
return !element->previousElement();
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::LastChild)
|
||||
return !element->nextElement();
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::OnlyChild)
|
||||
return !(element->previousElement() || element->nextElement());
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::FirstOfType) {
|
||||
auto child = element->nextElement();
|
||||
while(child) {
|
||||
if(child->id == element->id)
|
||||
return false;
|
||||
child = element->nextElement();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::LastOfType) {
|
||||
auto child = element->nextElement();
|
||||
while(child) {
|
||||
if(child->id == element->id)
|
||||
return false;
|
||||
child = element->nextElement();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::OnlyOfType) {
|
||||
auto child = element->nextElement();
|
||||
while(child) {
|
||||
if(child->id == element->id)
|
||||
return false;
|
||||
child = element->nextElement();
|
||||
}
|
||||
|
||||
child = element->nextElement();
|
||||
while(child) {
|
||||
if(child->id == element->id)
|
||||
return false;
|
||||
child = element->nextElement();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::NthChild) {
|
||||
int count = 1;
|
||||
auto child = element->previousElement();
|
||||
while(child) {
|
||||
count += 1;
|
||||
child = element->previousElement();
|
||||
}
|
||||
|
||||
return pseudo.matchnth(count);
|
||||
}
|
||||
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::NthLastChild) {
|
||||
int count = 1;
|
||||
auto child = element->nextElement();
|
||||
while(child) {
|
||||
count += 1;
|
||||
child = element->nextElement();
|
||||
}
|
||||
|
||||
return pseudo.matchnth(count);
|
||||
}
|
||||
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::NthOfType) {
|
||||
int count = 1;
|
||||
auto child = element->previousElement();
|
||||
while(child && child->id == element->id) {
|
||||
count += 1;
|
||||
child = element->previousElement();
|
||||
}
|
||||
|
||||
return pseudo.matchnth(count);
|
||||
}
|
||||
|
||||
if(pseudo.type == CSSSimpleSelector::Pseudo::Type::NthLastOfType) {
|
||||
int count = 1;
|
||||
auto child = element->nextElement();
|
||||
while(child && child->id == element->id) {
|
||||
count += 1;
|
||||
child = element->nextElement();
|
||||
}
|
||||
|
||||
return pseudo.matchnth(count);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CSSStyleSheet::parse(const std::string_view& content)
|
||||
{
|
||||
auto position = m_ruleList.size();
|
||||
CSSParser::parseSheet(m_ruleList, content);
|
||||
for(; position < m_ruleList.size(); ++position) {
|
||||
auto& rule = m_ruleList[position];
|
||||
auto& properties = rule->properties();
|
||||
for(auto& selector : rule->selectors()) {
|
||||
uint32_t specificity = 0;
|
||||
for(auto& sel : selector) {
|
||||
specificity += (sel.id == ElementID::Star) ? 0x0 : 0x1;
|
||||
for(auto& attribute : sel.attributes) {
|
||||
specificity += (attribute.id == PropertyID::Id) ? 0x10000 : 0x100;
|
||||
}
|
||||
}
|
||||
|
||||
m_ruleSet.emplace(selector, properties, specificity, position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace lunasvg
|
495
external/lunasvg/source/cssstylesheet.h
vendored
Normal file
495
external/lunasvg/source/cssstylesheet.h
vendored
Normal file
|
@ -0,0 +1,495 @@
|
|||
#ifndef CSSSTYLESHEET_H
|
||||
#define CSSSTYLESHEET_H
|
||||
|
||||
#include "element.h"
|
||||
#include "pointer.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace lunasvg {
|
||||
|
||||
class CSSValue : public RefCounted<CSSValue> {
|
||||
public:
|
||||
virtual ~CSSValue() = default;
|
||||
virtual bool isInitialValue() const { return false; }
|
||||
virtual bool isInheritValue() const { return false; }
|
||||
virtual bool isIdentValue() const { return false; }
|
||||
virtual bool isIntegerValue() const { return false; }
|
||||
virtual bool isNumberValue() const { return false; }
|
||||
virtual bool isPercentValue() const { return false; }
|
||||
virtual bool isLengthValue() const { return false; }
|
||||
virtual bool isStringValue() const { return false; }
|
||||
virtual bool isUrlValue() const { return false; }
|
||||
virtual bool isColorValue() const { return false; }
|
||||
virtual bool isPairValue() const { return false; }
|
||||
virtual bool isListValue() const { return false; }
|
||||
|
||||
protected:
|
||||
CSSValue() = default;
|
||||
};
|
||||
|
||||
using CSSValueList = std::vector<RefPtr<CSSValue>>;
|
||||
|
||||
class CSSInitialValue final : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSInitialValue> create();
|
||||
|
||||
bool isInitialValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSInitialValue() = default;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSInitialValue> {
|
||||
static bool check(const CSSValue& value) { return value.isInitialValue(); }
|
||||
};
|
||||
|
||||
class CSSInheritValue final : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSInheritValue> create();
|
||||
|
||||
bool isInheritValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSInheritValue() = default;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSInheritValue> {
|
||||
static bool check(const CSSValue& value) { return value.isInheritValue(); }
|
||||
};
|
||||
|
||||
enum class CSSValueID {
|
||||
Unknown,
|
||||
Auto,
|
||||
Bevel,
|
||||
Bold,
|
||||
Bolder,
|
||||
Butt,
|
||||
Clip,
|
||||
Collapse,
|
||||
Color,
|
||||
CurrentColor,
|
||||
End,
|
||||
Evenodd,
|
||||
Hidden,
|
||||
Inherit,
|
||||
Initial,
|
||||
Inline,
|
||||
Italic,
|
||||
Large,
|
||||
Larger,
|
||||
Lighter,
|
||||
Medium,
|
||||
Middle,
|
||||
Miter,
|
||||
None,
|
||||
Nonzero,
|
||||
Normal,
|
||||
Oblique,
|
||||
Round,
|
||||
Small,
|
||||
SmallCaps,
|
||||
Smaller,
|
||||
Square,
|
||||
Start,
|
||||
Stroke,
|
||||
Visible,
|
||||
XLarge,
|
||||
XSmall,
|
||||
XxLarge,
|
||||
XxSmall,
|
||||
XxxLarge
|
||||
};
|
||||
|
||||
class CSSIdentValue final : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSIdentValue> create(CSSValueID value);
|
||||
|
||||
CSSValueID value() const { return m_value; }
|
||||
bool isIdentValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSIdentValue(CSSValueID value) : m_value(value) {}
|
||||
CSSValueID m_value;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSIdentValue> {
|
||||
static bool check(const CSSValue& value) { return value.isIdentValue(); }
|
||||
};
|
||||
|
||||
class CSSIntegerValue final : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSIntegerValue> create(int value);
|
||||
|
||||
int value() const { return m_value; }
|
||||
bool isIntegerValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSIntegerValue(int value) : m_value(value) {}
|
||||
int m_value;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSIntegerValue> {
|
||||
static bool check(const CSSValue& value) { return value.isIntegerValue(); }
|
||||
};
|
||||
|
||||
class CSSNumberValue final : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSNumberValue> create(double value);
|
||||
|
||||
double value() const { return m_value; }
|
||||
bool isNumberValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSNumberValue(double value) : m_value(value) {}
|
||||
double m_value;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSNumberValue> {
|
||||
static bool check(const CSSValue& value) { return value.isNumberValue(); }
|
||||
};
|
||||
|
||||
class CSSPercentValue final : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSPercentValue> create(double value);
|
||||
|
||||
double value() const { return m_value; }
|
||||
bool isPercentValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSPercentValue(double value) : m_value(value) {}
|
||||
double m_value;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSPercentValue> {
|
||||
static bool check(const CSSValue& value) { return value.isPercentValue(); }
|
||||
};
|
||||
|
||||
class CSSLengthValue final : public CSSValue {
|
||||
public:
|
||||
enum class Unit {
|
||||
None,
|
||||
Ems,
|
||||
Exs,
|
||||
Pixels,
|
||||
Centimeters,
|
||||
Millimeters,
|
||||
Inches,
|
||||
Points,
|
||||
Picas,
|
||||
ViewportWidth,
|
||||
ViewportHeight,
|
||||
ViewportMin,
|
||||
ViewportMax,
|
||||
Rems,
|
||||
Chs
|
||||
};
|
||||
|
||||
static RefPtr<CSSLengthValue> create(double value, Unit unit);
|
||||
|
||||
double value() const { return m_value; }
|
||||
Unit unit() const { return m_unit; }
|
||||
bool isLengthValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSLengthValue(double value, Unit unit)
|
||||
: m_value(value), m_unit(unit)
|
||||
{}
|
||||
|
||||
double m_value;
|
||||
Unit m_unit;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSLengthValue> {
|
||||
static bool check(const CSSValue& value) { return value.isLengthValue(); }
|
||||
};
|
||||
|
||||
class CSSStringValue final : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSStringValue> create(std::string value);
|
||||
|
||||
const std::string& value() const { return m_value; }
|
||||
bool isStringValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSStringValue(std::string value) : m_value(std::move(value)) {}
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSStringValue> {
|
||||
static bool check(const CSSValue& value) { return value.isStringValue(); }
|
||||
};
|
||||
|
||||
class CSSUrlValue final : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSUrlValue> create(std::string value);
|
||||
|
||||
const std::string& value() const { return m_value; }
|
||||
bool isUrlValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSUrlValue(std::string value) : m_value(std::move(value)) {}
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSUrlValue> {
|
||||
static bool check(const CSSValue& value) { return value.isUrlValue(); }
|
||||
};
|
||||
|
||||
class CSSColorValue final : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSColorValue> create(uint32_t value);
|
||||
static RefPtr<CSSColorValue> create(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
|
||||
uint32_t value() const { return m_value; }
|
||||
bool isColorValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSColorValue(uint32_t value) : m_value(value) {}
|
||||
uint32_t m_value;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSColorValue> {
|
||||
static bool check(const CSSValue& value) { return value.isColorValue(); }
|
||||
};
|
||||
|
||||
class CSSPairValue final : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSPairValue> create(RefPtr<CSSValue> first, RefPtr<CSSValue> second);
|
||||
|
||||
const RefPtr<CSSValue>& first() const { return m_first; }
|
||||
const RefPtr<CSSValue>& second() const { return m_second; }
|
||||
bool isPairValue() const final { return true; }
|
||||
|
||||
private:
|
||||
CSSPairValue(RefPtr<CSSValue> first, RefPtr<CSSValue> second)
|
||||
: m_first(first), m_second(second)
|
||||
{}
|
||||
|
||||
RefPtr<CSSValue> m_first;
|
||||
RefPtr<CSSValue> m_second;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is<CSSPairValue> {
|
||||
static bool check(const CSSValue& value) { return value.isPairValue(); }
|
||||
};
|
||||
|
||||
class CSSListValue : public CSSValue {
|
||||
public:
|
||||
static RefPtr<CSSListValue> create(CSSValueList values);
|
||||
|
||||
size_t length() const { return m_values.size(); }
|
||||
const RefPtr<CSSValue>& front() const { return m_values.front(); }
|
||||
const RefPtr<CSSValue>& back() const { return m_values.back(); }
|
||||
const RefPtr<CSSValue>& at(size_t index) const { return m_values.at(index); }
|
||||
const CSSValueList& values() const { return m_values; }
|
||||
bool isListValue() const final { return true; }
|
||||
|
||||
protected:
|
||||
CSSListValue(CSSValueList values) : m_values(std::move(values)) {}
|
||||
CSSValueList m_values;
|
||||
};
|
||||
|
||||
enum class CSSPropertyID {
|
||||
Unknown = 0,
|
||||
Clip_Path,
|
||||
Clip_Rule,
|
||||
Color,
|
||||
Display,
|
||||
Fill,
|
||||
Fill_Opacity,
|
||||
Fill_Rule,
|
||||
Font_Family,
|
||||
Font_Size,
|
||||
Font_Style,
|
||||
Font_Variant,
|
||||
Font_Weight,
|
||||
Letter_Spacing,
|
||||
Marker_End,
|
||||
Marker_Mid,
|
||||
Marker_Start,
|
||||
Mask,
|
||||
Opacity,
|
||||
Overflow,
|
||||
Solid_Color,
|
||||
Solid_Opacity,
|
||||
Stop_Color,
|
||||
Stop_Opacity,
|
||||
Stroke,
|
||||
Stroke_Dasharray,
|
||||
Stroke_Dashoffset,
|
||||
Stroke_Linecap,
|
||||
Stroke_Linejoin,
|
||||
Stroke_Miterlimit,
|
||||
Stroke_Opacity,
|
||||
Stroke_Width,
|
||||
Text_Anchor,
|
||||
Text_Decoration,
|
||||
Visibility,
|
||||
Word_Spacing
|
||||
};
|
||||
|
||||
CSSPropertyID csspropertyid(const std::string_view& name);
|
||||
|
||||
class CSSProperty {
|
||||
public:
|
||||
CSSProperty(CSSPropertyID id, bool important, RefPtr<CSSValue> value)
|
||||
: m_id(id), m_important(important), m_value(value)
|
||||
{}
|
||||
|
||||
CSSPropertyID id() const { return m_id; }
|
||||
bool important() const { return m_important; }
|
||||
const RefPtr<CSSValue>& value() const { return m_value; }
|
||||
|
||||
private:
|
||||
CSSPropertyID m_id;
|
||||
bool m_important;
|
||||
RefPtr<CSSValue> m_value;
|
||||
};
|
||||
|
||||
using CSSPropertyList = std::vector<CSSProperty>;
|
||||
using CSSPropertyMap = std::map<CSSPropertyID, CSSProperty>;
|
||||
|
||||
struct CSSSimpleSelector;
|
||||
|
||||
using CSSSelector = std::vector<CSSSimpleSelector>;
|
||||
using CSSSelectorList = std::vector<CSSSelector>;
|
||||
|
||||
struct CSSSimpleSelector {
|
||||
struct Attribute {
|
||||
enum class Type {
|
||||
None,
|
||||
Equals,
|
||||
Contains,
|
||||
Includes,
|
||||
StartsWith,
|
||||
EndsWith,
|
||||
DashEquals
|
||||
};
|
||||
|
||||
Type type{Type::None};
|
||||
PropertyID id{PropertyID::Unknown};
|
||||
std::string value;
|
||||
};
|
||||
|
||||
struct Pseudo {
|
||||
enum class Type {
|
||||
Unknown,
|
||||
Empty,
|
||||
Root,
|
||||
Is,
|
||||
Not,
|
||||
FirstChild,
|
||||
LastChild,
|
||||
OnlyChild,
|
||||
FirstOfType,
|
||||
LastOfType,
|
||||
OnlyOfType,
|
||||
NthChild,
|
||||
NthLastChild,
|
||||
NthOfType,
|
||||
NthLastOfType
|
||||
};
|
||||
|
||||
using MatchPattern = std::pair<int16_t, int16_t>;
|
||||
|
||||
bool matchnth(size_t count) const;
|
||||
|
||||
Type type{Type::Unknown};
|
||||
MatchPattern pattern;
|
||||
CSSSelectorList selectors;
|
||||
};
|
||||
|
||||
enum class Combinator {
|
||||
None,
|
||||
Descendant,
|
||||
Child,
|
||||
DirectAdjacent,
|
||||
InDirectAdjacent
|
||||
};
|
||||
|
||||
Combinator combinator{Combinator::Descendant};
|
||||
ElementID id{ElementID::Star};
|
||||
std::vector<Attribute> attributes;
|
||||
std::vector<Pseudo> pseudos;
|
||||
};
|
||||
|
||||
class CSSRule {
|
||||
public:
|
||||
static std::unique_ptr<CSSRule> create(CSSSelectorList selectors, CSSPropertyList properties);
|
||||
|
||||
const CSSSelectorList& selectors() const { return m_selectors; }
|
||||
const CSSPropertyList& properties() const { return m_properties; }
|
||||
|
||||
private:
|
||||
CSSRule(CSSSelectorList selectors, CSSPropertyList properties)
|
||||
: m_selectors(std::move(selectors)), m_properties(std::move(properties))
|
||||
{}
|
||||
|
||||
CSSSelectorList m_selectors;
|
||||
CSSPropertyList m_properties;
|
||||
};
|
||||
|
||||
using CSSRuleList = std::vector<std::unique_ptr<CSSRule>>;
|
||||
|
||||
class CSSRuleData {
|
||||
public:
|
||||
CSSRuleData(const CSSSelector& selector, const CSSPropertyList& properties, uint32_t specificity, uint32_t position)
|
||||
: m_selector(selector), m_properties(properties), m_specificity(specificity), m_position(position)
|
||||
{}
|
||||
|
||||
const CSSSelector& selector() const { return m_selector; }
|
||||
const CSSPropertyList& properties() const { return m_properties; }
|
||||
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 CSSSimpleSelector& selector, const Element* element);
|
||||
static bool matchAttributeSelector(const CSSSimpleSelector::Attribute& attribute, const Element* element);
|
||||
static bool matchPseudoClassSelector(const CSSSimpleSelector::Pseudo& pseudo, const Element* element);
|
||||
|
||||
private:
|
||||
const CSSSelector& m_selector;
|
||||
const CSSPropertyList& m_properties;
|
||||
uint32_t m_specificity;
|
||||
uint32_t m_position;
|
||||
};
|
||||
|
||||
inline bool operator<(const CSSRuleData& a, const CSSRuleData& b) { return std::tie(a.specificity(), a.position()) < std::tie(b.specificity(), b.position()); }
|
||||
inline bool operator>(const CSSRuleData& a, const CSSRuleData& b) { return std::tie(a.specificity(), a.position()) > std::tie(b.specificity(), b.position()); }
|
||||
|
||||
using CSSRuleSet = std::multiset<CSSRuleData>;
|
||||
|
||||
class ComputedStyle;
|
||||
|
||||
class CSSStyleSheet {
|
||||
public:
|
||||
CSSStyleSheet() = default;
|
||||
|
||||
void parse(const std::string_view& content);
|
||||
bool empty() const { return m_ruleList.empty(); }
|
||||
|
||||
RefPtr<ComputedStyle> styleForElement(const Element* element, const RefPtr<ComputedStyle>& parentStyle) const;
|
||||
|
||||
private:
|
||||
CSSRuleList m_ruleList;
|
||||
CSSRuleSet m_ruleSet;
|
||||
};
|
||||
|
||||
} // namespace lunasvg
|
||||
|
||||
#endif // CSSSTYLESHEET_H
|
2
external/lunasvg/source/defselement.cpp
vendored
2
external/lunasvg/source/defselement.cpp
vendored
|
@ -3,7 +3,7 @@
|
|||
namespace lunasvg {
|
||||
|
||||
DefsElement::DefsElement()
|
||||
: GraphicsElement(ElementId::Defs)
|
||||
: GraphicsElement(ElementID::Defs)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
161
external/lunasvg/source/element.cpp
vendored
161
external/lunasvg/source/element.cpp
vendored
|
@ -2,9 +2,146 @@
|
|||
#include "parser.h"
|
||||
#include "svgelement.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace lunasvg {
|
||||
|
||||
void PropertyList::set(PropertyId id, const std::string& value, int specificity)
|
||||
ElementID elementid(const std::string_view& name)
|
||||
{
|
||||
static const struct {
|
||||
std::string_view name;
|
||||
ElementID value;
|
||||
} table[] = {
|
||||
{"a", ElementID::A},
|
||||
{"circle", ElementID::Circle},
|
||||
{"clipPath", ElementID::ClipPath},
|
||||
{"defs", ElementID::Defs},
|
||||
{"ellipse", ElementID::Ellipse},
|
||||
{"g", ElementID::G},
|
||||
{"image", ElementID::Image},
|
||||
{"line", ElementID::Line},
|
||||
{"linearGradient", ElementID::LinearGradient},
|
||||
{"marker", ElementID::Marker},
|
||||
{"mask", ElementID::Mask},
|
||||
{"path", ElementID::Path},
|
||||
{"pattern", ElementID::Pattern},
|
||||
{"polygon", ElementID::Polygon},
|
||||
{"polyline", ElementID::Polyline},
|
||||
{"radialGradient", ElementID::RadialGradient},
|
||||
{"rect", ElementID::Rect},
|
||||
{"solidColor", ElementID::SolidColor},
|
||||
{"stop", ElementID::Stop},
|
||||
{"style", ElementID::Style},
|
||||
{"svg", ElementID::Svg},
|
||||
{"switch", ElementID::Switch},
|
||||
{"symbol", ElementID::Symbol},
|
||||
{"text", ElementID::Text},
|
||||
{"textPath", ElementID::TextPath},
|
||||
{"tref", ElementID::Tref},
|
||||
{"tspan", ElementID::Tspan},
|
||||
{"use", ElementID::Use}
|
||||
};
|
||||
|
||||
auto it = std::lower_bound(table, std::end(table), name, [](auto& item, auto& name) { return item.name < name; });
|
||||
if(it != std::end(table) && it->name == name)
|
||||
return it->value;
|
||||
return ElementID::Unknown;
|
||||
}
|
||||
|
||||
PropertyID propertyid(const std::string_view& name)
|
||||
{
|
||||
static const struct {
|
||||
std::string_view name;
|
||||
PropertyID value;
|
||||
} table[] = {
|
||||
{"class", PropertyID::Class},
|
||||
{"clip-path", PropertyID::Clip_Path},
|
||||
{"clip-rule", PropertyID::Clip_Rule},
|
||||
{"clipPathUnits", PropertyID::ClipPathUnits},
|
||||
{"color", PropertyID::Color},
|
||||
{"cx", PropertyID::Cx},
|
||||
{"cy", PropertyID::Cy},
|
||||
{"d", PropertyID::D},
|
||||
{"dx", PropertyID::Dx},
|
||||
{"dy", PropertyID::Dy},
|
||||
{"display", PropertyID::Display},
|
||||
{"fill", PropertyID::Fill},
|
||||
{"fill-opacity", PropertyID::Fill_Opacity},
|
||||
{"fill-rule", PropertyID::Fill_Rule},
|
||||
{"font-family", PropertyID::Font_Family},
|
||||
{"font-size", PropertyID::Font_Size},
|
||||
{"font-style", PropertyID::Font_Style},
|
||||
{"font-variant", PropertyID::Font_Variant},
|
||||
{"font-weight", PropertyID::Font_Weight},
|
||||
{"fx", PropertyID::Fx},
|
||||
{"fy", PropertyID::Fy},
|
||||
{"gradientTransform", PropertyID::GradientTransform},
|
||||
{"gradientUnits", PropertyID::GradientUnits},
|
||||
{"height", PropertyID::Height},
|
||||
{"href", PropertyID::Href},
|
||||
{"id", PropertyID::Id},
|
||||
{"letter-spacing", PropertyID::Letter_Spacing},
|
||||
{"marker-end", PropertyID::Marker_End},
|
||||
{"marker-mid", PropertyID::Marker_Mid},
|
||||
{"marker-start", PropertyID::Marker_Start},
|
||||
{"markerHeight", PropertyID::MarkerHeight},
|
||||
{"markerUnits", PropertyID::MarkerUnits},
|
||||
{"markerWidth", PropertyID::MarkerWidth},
|
||||
{"mask", PropertyID::Mask},
|
||||
{"maskContentUnits", PropertyID::MaskContentUnits},
|
||||
{"maskUnits", PropertyID::MaskUnits},
|
||||
{"offset", PropertyID::Offset},
|
||||
{"opacity", PropertyID::Opacity},
|
||||
{"orient", PropertyID::Orient},
|
||||
{"overflow", PropertyID::Overflow},
|
||||
{"patternContentUnits", PropertyID::PatternContentUnits},
|
||||
{"patternTransform", PropertyID::PatternTransform},
|
||||
{"patternUnits", PropertyID::PatternUnits},
|
||||
{"points", PropertyID::Points},
|
||||
{"preserveAspectRatio", PropertyID::PreserveAspectRatio},
|
||||
{"r", PropertyID::R},
|
||||
{"refX", PropertyID::RefX},
|
||||
{"refY", PropertyID::RefY},
|
||||
{"rotate", PropertyID::Rotate},
|
||||
{"rx", PropertyID::Rx},
|
||||
{"ry", PropertyID::Ry},
|
||||
{"solid-color", PropertyID::Solid_Color},
|
||||
{"solid-opacity", PropertyID::Solid_Opacity},
|
||||
{"spreadMethod", PropertyID::SpreadMethod},
|
||||
{"startOffset", PropertyID::StartOffset},
|
||||
{"stop-color", PropertyID::Stop_Color},
|
||||
{"stop-opacity", PropertyID::Stop_Opacity},
|
||||
{"stroke", PropertyID::Stroke},
|
||||
{"stroke-dasharray", PropertyID::Stroke_Dasharray},
|
||||
{"stroke-dashoffset", PropertyID::Stroke_Dashoffset},
|
||||
{"stroke-linecap", PropertyID::Stroke_Linecap},
|
||||
{"stroke-linejoin", PropertyID::Stroke_Linejoin},
|
||||
{"stroke-miterlimit", PropertyID::Stroke_Miterlimit},
|
||||
{"stroke-opacity", PropertyID::Stroke_Opacity},
|
||||
{"stroke-width", PropertyID::Stroke_Width},
|
||||
{"style", PropertyID::Style},
|
||||
{"text-anchor", PropertyID::Text_Anchor},
|
||||
{"text-decoration", PropertyID::Text_Decoration},
|
||||
{"transform", PropertyID::Transform},
|
||||
{"viewBox", PropertyID::ViewBox},
|
||||
{"visibility", PropertyID::Visibility},
|
||||
{"width", PropertyID::Width},
|
||||
{"word-spacing", PropertyID::Word_Spacing},
|
||||
{"x", PropertyID::X},
|
||||
{"x1", PropertyID::X1},
|
||||
{"x2", PropertyID::X2},
|
||||
{"y", PropertyID::Y},
|
||||
{"y1", PropertyID::Y1},
|
||||
{"y2", PropertyID::Y2}
|
||||
};
|
||||
|
||||
auto it = std::lower_bound(table, std::end(table), name, [](auto& item, auto& name) { return item.name < name; });
|
||||
if(it != std::end(table) && it->name == name)
|
||||
return it->value;
|
||||
return PropertyID::Unknown;
|
||||
}
|
||||
|
||||
void PropertyList::set(PropertyID id, const std::string& value, int specificity)
|
||||
{
|
||||
auto property = get(id);
|
||||
if(property == nullptr)
|
||||
|
@ -21,7 +158,7 @@ void PropertyList::set(PropertyId id, const std::string& value, int specificity)
|
|||
property->value = value;
|
||||
}
|
||||
|
||||
Property* PropertyList::get(PropertyId id) const
|
||||
Property* PropertyList::get(PropertyID id) const
|
||||
{
|
||||
auto data = m_properties.data();
|
||||
auto end = data + m_properties.size();
|
||||
|
@ -59,19 +196,19 @@ std::unique_ptr<Node> TextNode::clone() const
|
|||
return std::move(node);
|
||||
}
|
||||
|
||||
Element::Element(ElementId id)
|
||||
Element::Element(ElementID id)
|
||||
: id(id)
|
||||
{
|
||||
}
|
||||
|
||||
void Element::set(PropertyId id, const std::string& value, int specificity)
|
||||
void Element::set(PropertyID id, const std::string& value, int specificity)
|
||||
{
|
||||
properties.set(id, value, specificity);
|
||||
}
|
||||
|
||||
static const std::string EmptyString;
|
||||
|
||||
const std::string& Element::get(PropertyId id) const
|
||||
const std::string& Element::get(PropertyID id) const
|
||||
{
|
||||
auto property = properties.get(id);
|
||||
if(property == nullptr)
|
||||
|
@ -82,7 +219,7 @@ const std::string& Element::get(PropertyId id) const
|
|||
|
||||
static const std::string InheritString{"inherit"};
|
||||
|
||||
const std::string& Element::find(PropertyId id) const
|
||||
const std::string& Element::find(PropertyID id) const
|
||||
{
|
||||
auto element = this;
|
||||
do {
|
||||
|
@ -95,12 +232,12 @@ const std::string& Element::find(PropertyId id) const
|
|||
return EmptyString;
|
||||
}
|
||||
|
||||
bool Element::has(PropertyId id) const
|
||||
bool Element::has(PropertyID id) const
|
||||
{
|
||||
return properties.get(id);
|
||||
}
|
||||
|
||||
Element* Element::previousSibling() const
|
||||
Element* Element::previousElement() const
|
||||
{
|
||||
if(parent == nullptr)
|
||||
return nullptr;
|
||||
|
@ -122,7 +259,7 @@ Element* Element::previousSibling() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Element* Element::nextSibling() const
|
||||
Element* Element::nextElement() const
|
||||
{
|
||||
if(parent == nullptr)
|
||||
return nullptr;
|
||||
|
@ -162,15 +299,15 @@ Rect Element::currentViewport() const
|
|||
if(parent == nullptr)
|
||||
{
|
||||
auto element = static_cast<const SVGElement*>(this);
|
||||
if(element->has(PropertyId::ViewBox))
|
||||
if(element->has(PropertyID::ViewBox))
|
||||
return element->viewBox();
|
||||
return Rect{0, 0, 300, 150};
|
||||
}
|
||||
|
||||
if(parent->id == ElementId::Svg)
|
||||
if(parent->id == ElementID::Svg)
|
||||
{
|
||||
auto element = static_cast<SVGElement*>(parent);
|
||||
if(element->has(PropertyId::ViewBox))
|
||||
if(element->has(PropertyID::ViewBox))
|
||||
return element->viewBox();
|
||||
|
||||
LengthContext lengthContext(element);
|
||||
|
|
54
external/lunasvg/source/element.h
vendored
54
external/lunasvg/source/element.h
vendored
|
@ -8,15 +8,16 @@
|
|||
|
||||
namespace lunasvg {
|
||||
|
||||
enum class ElementId
|
||||
{
|
||||
enum class ElementID {
|
||||
Unknown = 0,
|
||||
Star,
|
||||
A,
|
||||
Circle,
|
||||
ClipPath,
|
||||
Defs,
|
||||
Ellipse,
|
||||
G,
|
||||
Image,
|
||||
Line,
|
||||
LinearGradient,
|
||||
Marker,
|
||||
|
@ -31,12 +32,16 @@ enum class ElementId
|
|||
Stop,
|
||||
Style,
|
||||
Svg,
|
||||
Switch,
|
||||
Symbol,
|
||||
Text,
|
||||
TextPath,
|
||||
Tref,
|
||||
Tspan,
|
||||
Use
|
||||
};
|
||||
|
||||
enum class PropertyId
|
||||
{
|
||||
enum class PropertyID {
|
||||
Unknown = 0,
|
||||
Class,
|
||||
Clip_Path,
|
||||
|
@ -46,10 +51,17 @@ enum class PropertyId
|
|||
Cx,
|
||||
Cy,
|
||||
D,
|
||||
Dx,
|
||||
Dy,
|
||||
Display,
|
||||
Fill,
|
||||
Fill_Opacity,
|
||||
Fill_Rule,
|
||||
Font_Family,
|
||||
Font_Size,
|
||||
Font_Style,
|
||||
Font_Variant,
|
||||
Font_Weight,
|
||||
Fx,
|
||||
Fy,
|
||||
GradientTransform,
|
||||
|
@ -57,6 +69,7 @@ enum class PropertyId
|
|||
Height,
|
||||
Href,
|
||||
Id,
|
||||
Letter_Spacing,
|
||||
Marker_End,
|
||||
Marker_Mid,
|
||||
Marker_Start,
|
||||
|
@ -78,11 +91,13 @@ enum class PropertyId
|
|||
R,
|
||||
RefX,
|
||||
RefY,
|
||||
Rotate,
|
||||
Rx,
|
||||
Ry,
|
||||
Solid_Color,
|
||||
Solid_Opacity,
|
||||
SpreadMethod,
|
||||
StartOffset,
|
||||
Stop_Color,
|
||||
Stop_Opacity,
|
||||
Stroke,
|
||||
|
@ -94,10 +109,13 @@ enum class PropertyId
|
|||
Stroke_Opacity,
|
||||
Stroke_Width,
|
||||
Style,
|
||||
Text_Anchor,
|
||||
Text_Decoration,
|
||||
Transform,
|
||||
ViewBox,
|
||||
Visibility,
|
||||
Width,
|
||||
Word_Spacing,
|
||||
X,
|
||||
X1,
|
||||
X2,
|
||||
|
@ -106,9 +124,12 @@ enum class PropertyId
|
|||
Y2
|
||||
};
|
||||
|
||||
ElementID elementid(const std::string_view& name);
|
||||
PropertyID propertyid(const std::string_view& name);
|
||||
|
||||
struct Property
|
||||
{
|
||||
PropertyId id;
|
||||
PropertyID id;
|
||||
std::string value;
|
||||
int specificity;
|
||||
};
|
||||
|
@ -118,10 +139,11 @@ class PropertyList
|
|||
public:
|
||||
PropertyList() = default;
|
||||
|
||||
void set(PropertyId id, const std::string& value, int specificity);
|
||||
Property* get(PropertyId id) const;
|
||||
void set(PropertyID id, const std::string& value, int specificity);
|
||||
Property* get(PropertyID id) const;
|
||||
void add(const Property& property);
|
||||
void add(const PropertyList& properties);
|
||||
void clear() { m_properties.clear(); }
|
||||
|
||||
private:
|
||||
std::vector<Property> m_properties;
|
||||
|
@ -159,20 +181,22 @@ public:
|
|||
std::string text;
|
||||
};
|
||||
|
||||
using Attribute = std::pair<PropertyID, std::string>;
|
||||
using AttributeList = std::vector<Attribute>;
|
||||
using NodeList = std::list<std::unique_ptr<Node>>;
|
||||
|
||||
class Element : public Node
|
||||
{
|
||||
public:
|
||||
Element(ElementId id);
|
||||
Element(ElementID id);
|
||||
|
||||
void set(PropertyId id, const std::string& value, int specificity);
|
||||
const std::string& get(PropertyId id) const;
|
||||
const std::string& find(PropertyId id) const;
|
||||
bool has(PropertyId id) const;
|
||||
void set(PropertyID id, const std::string& value, int specificity);
|
||||
const std::string& get(PropertyID id) const;
|
||||
const std::string& find(PropertyID id) const;
|
||||
bool has(PropertyID id) const;
|
||||
|
||||
Element* previousSibling() const;
|
||||
Element* nextSibling() const;
|
||||
Element* previousElement() const;
|
||||
Element* nextElement() const;
|
||||
Node* addChild(std::unique_ptr<Node> child);
|
||||
void layoutChildren(LayoutContext* context, LayoutContainer* current) const;
|
||||
Rect currentViewport() const;
|
||||
|
@ -208,7 +232,7 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
ElementId id;
|
||||
ElementID id;
|
||||
NodeList children;
|
||||
PropertyList properties;
|
||||
};
|
||||
|
|
2
external/lunasvg/source/gelement.cpp
vendored
2
external/lunasvg/source/gelement.cpp
vendored
|
@ -4,7 +4,7 @@
|
|||
namespace lunasvg {
|
||||
|
||||
GElement::GElement()
|
||||
: GraphicsElement(ElementId::G)
|
||||
: GraphicsElement(ElementID::G)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
56
external/lunasvg/source/geometryelement.cpp
vendored
56
external/lunasvg/source/geometryelement.cpp
vendored
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace lunasvg {
|
||||
|
||||
GeometryElement::GeometryElement(ElementId id)
|
||||
GeometryElement::GeometryElement(ElementID id)
|
||||
: GraphicsElement(id)
|
||||
{
|
||||
}
|
||||
|
@ -35,13 +35,13 @@ void GeometryElement::layout(LayoutContext* context, LayoutContainer* current) c
|
|||
}
|
||||
|
||||
PathElement::PathElement()
|
||||
: GeometryElement(ElementId::Path)
|
||||
: GeometryElement(ElementID::Path)
|
||||
{
|
||||
}
|
||||
|
||||
Path PathElement::d() const
|
||||
{
|
||||
auto& value = get(PropertyId::D);
|
||||
auto& value = get(PropertyID::D);
|
||||
return Parser::parsePath(value);
|
||||
}
|
||||
|
||||
|
@ -55,19 +55,19 @@ std::unique_ptr<Node> PathElement::clone() const
|
|||
return cloneElement<PathElement>();
|
||||
}
|
||||
|
||||
PolyElement::PolyElement(ElementId id)
|
||||
PolyElement::PolyElement(ElementID id)
|
||||
: GeometryElement(id)
|
||||
{
|
||||
}
|
||||
|
||||
PointList PolyElement::points() const
|
||||
{
|
||||
auto& value = get(PropertyId::Points);
|
||||
auto& value = get(PropertyID::Points);
|
||||
return Parser::parsePointList(value);
|
||||
}
|
||||
|
||||
PolygonElement::PolygonElement()
|
||||
: PolyElement(ElementId::Polygon)
|
||||
: PolyElement(ElementID::Polygon)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ std::unique_ptr<Node> PolygonElement::clone() const
|
|||
}
|
||||
|
||||
PolylineElement::PolylineElement()
|
||||
: PolyElement(ElementId::Polyline)
|
||||
: PolyElement(ElementID::Polyline)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -116,25 +116,25 @@ std::unique_ptr<Node> PolylineElement::clone() const
|
|||
}
|
||||
|
||||
CircleElement::CircleElement()
|
||||
: GeometryElement(ElementId::Circle)
|
||||
: GeometryElement(ElementID::Circle)
|
||||
{
|
||||
}
|
||||
|
||||
Length CircleElement::cx() const
|
||||
{
|
||||
auto& value = get(PropertyId::Cx);
|
||||
auto& value = get(PropertyID::Cx);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length CircleElement::cy() const
|
||||
{
|
||||
auto& value = get(PropertyId::Cy);
|
||||
auto& value = get(PropertyID::Cy);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length CircleElement::r() const
|
||||
{
|
||||
auto& value = get(PropertyId::R);
|
||||
auto& value = get(PropertyID::R);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
|
@ -160,31 +160,31 @@ std::unique_ptr<Node> CircleElement::clone() const
|
|||
}
|
||||
|
||||
EllipseElement::EllipseElement()
|
||||
: GeometryElement(ElementId::Ellipse)
|
||||
: GeometryElement(ElementID::Ellipse)
|
||||
{
|
||||
}
|
||||
|
||||
Length EllipseElement::cx() const
|
||||
{
|
||||
auto& value = get(PropertyId::Cx);
|
||||
auto& value = get(PropertyID::Cx);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length EllipseElement::cy() const
|
||||
{
|
||||
auto& value = get(PropertyId::Cy);
|
||||
auto& value = get(PropertyID::Cy);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length EllipseElement::rx() const
|
||||
{
|
||||
auto& value = get(PropertyId::Rx);
|
||||
auto& value = get(PropertyID::Rx);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length EllipseElement::ry() const
|
||||
{
|
||||
auto& value = get(PropertyId::Ry);
|
||||
auto& value = get(PropertyID::Ry);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
|
@ -212,31 +212,31 @@ std::unique_ptr<Node> EllipseElement::clone() const
|
|||
}
|
||||
|
||||
LineElement::LineElement()
|
||||
: GeometryElement(ElementId::Line)
|
||||
: GeometryElement(ElementID::Line)
|
||||
{
|
||||
}
|
||||
|
||||
Length LineElement::x1() const
|
||||
{
|
||||
auto& value = get(PropertyId::X1);
|
||||
auto& value = get(PropertyID::X1);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length LineElement::y1() const
|
||||
{
|
||||
auto& value = get(PropertyId::Y1);
|
||||
auto& value = get(PropertyID::Y1);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length LineElement::x2() const
|
||||
{
|
||||
auto& value = get(PropertyId::X2);
|
||||
auto& value = get(PropertyID::X2);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length LineElement::y2() const
|
||||
{
|
||||
auto& value = get(PropertyId::Y2);
|
||||
auto& value = get(PropertyID::Y2);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
|
@ -260,43 +260,43 @@ std::unique_ptr<Node> LineElement::clone() const
|
|||
}
|
||||
|
||||
RectElement::RectElement()
|
||||
: GeometryElement(ElementId::Rect)
|
||||
: GeometryElement(ElementID::Rect)
|
||||
{
|
||||
}
|
||||
|
||||
Length RectElement::x() const
|
||||
{
|
||||
auto& value = get(PropertyId::X);
|
||||
auto& value = get(PropertyID::X);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length RectElement::y() const
|
||||
{
|
||||
auto& value = get(PropertyId::Y);
|
||||
auto& value = get(PropertyID::Y);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length RectElement::rx() const
|
||||
{
|
||||
auto& value = get(PropertyId::Rx);
|
||||
auto& value = get(PropertyID::Rx);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown);
|
||||
}
|
||||
|
||||
Length RectElement::ry() const
|
||||
{
|
||||
auto& value = get(PropertyId::Ry);
|
||||
auto& value = get(PropertyID::Ry);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown);
|
||||
}
|
||||
|
||||
Length RectElement::width() const
|
||||
{
|
||||
auto& value = get(PropertyId::Width);
|
||||
auto& value = get(PropertyID::Width);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length RectElement::height() const
|
||||
{
|
||||
auto& value = get(PropertyId::Height);
|
||||
auto& value = get(PropertyID::Height);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
|
|
4
external/lunasvg/source/geometryelement.h
vendored
4
external/lunasvg/source/geometryelement.h
vendored
|
@ -10,7 +10,7 @@ class LayoutShape;
|
|||
class GeometryElement : public GraphicsElement
|
||||
{
|
||||
public:
|
||||
GeometryElement(ElementId id);
|
||||
GeometryElement(ElementID id);
|
||||
|
||||
bool isGeometry() const { return true; }
|
||||
virtual void layout(LayoutContext* context, LayoutContainer* current) const;
|
||||
|
@ -31,7 +31,7 @@ public:
|
|||
class PolyElement : public GeometryElement
|
||||
{
|
||||
public:
|
||||
PolyElement(ElementId id);
|
||||
PolyElement(ElementID id);
|
||||
|
||||
PointList points() const;
|
||||
};
|
||||
|
|
4
external/lunasvg/source/graphicselement.cpp
vendored
4
external/lunasvg/source/graphicselement.cpp
vendored
|
@ -3,14 +3,14 @@
|
|||
|
||||
namespace lunasvg {
|
||||
|
||||
GraphicsElement::GraphicsElement(ElementId id)
|
||||
GraphicsElement::GraphicsElement(ElementID id)
|
||||
: StyledElement(id)
|
||||
{
|
||||
}
|
||||
|
||||
Transform GraphicsElement::transform() const
|
||||
{
|
||||
auto& value = get(PropertyId::Transform);
|
||||
auto& value = get(PropertyID::Transform);
|
||||
return Parser::parseTransform(value);
|
||||
}
|
||||
|
||||
|
|
2
external/lunasvg/source/graphicselement.h
vendored
2
external/lunasvg/source/graphicselement.h
vendored
|
@ -8,7 +8,7 @@ namespace lunasvg {
|
|||
class GraphicsElement : public StyledElement
|
||||
{
|
||||
public:
|
||||
GraphicsElement(ElementId id);
|
||||
GraphicsElement(ElementID id);
|
||||
|
||||
Transform transform() const;
|
||||
};
|
||||
|
|
12
external/lunasvg/source/layoutcontext.cpp
vendored
12
external/lunasvg/source/layoutcontext.cpp
vendored
|
@ -479,14 +479,14 @@ void RenderState::endGroup(RenderState& state, const BlendInfo& info)
|
|||
state.canvas->blend(canvas.get(), BlendMode::Src_Over, m_mode == RenderMode::Display ? info.opacity : 1.0);
|
||||
}
|
||||
|
||||
LayoutContext::LayoutContext(const ParseDocument* document, LayoutSymbol* root)
|
||||
: m_document(document), m_root(root)
|
||||
LayoutContext::LayoutContext(const TreeBuilder* builder, LayoutSymbol* root)
|
||||
: m_builder(builder), m_root(root)
|
||||
{
|
||||
}
|
||||
|
||||
Element* LayoutContext::getElementById(const std::string& id) const
|
||||
{
|
||||
return m_document->getElementById(id);
|
||||
return m_builder->getElementById(id);
|
||||
}
|
||||
|
||||
LayoutObject* LayoutContext::getResourcesById(const std::string& id) const
|
||||
|
@ -517,7 +517,7 @@ LayoutMask* LayoutContext::getMasker(const std::string& id)
|
|||
return static_cast<LayoutMask*>(ref);
|
||||
|
||||
auto element = getElementById(id);
|
||||
if(element == nullptr || element->id != ElementId::Mask)
|
||||
if(element == nullptr || element->id != ElementID::Mask)
|
||||
return nullptr;
|
||||
|
||||
auto masker = static_cast<MaskElement*>(element)->getMasker(this);
|
||||
|
@ -534,7 +534,7 @@ LayoutClipPath* LayoutContext::getClipper(const std::string& id)
|
|||
return static_cast<LayoutClipPath*>(ref);
|
||||
|
||||
auto element = getElementById(id);
|
||||
if(element == nullptr || element->id != ElementId::ClipPath)
|
||||
if(element == nullptr || element->id != ElementID::ClipPath)
|
||||
return nullptr;
|
||||
|
||||
auto clipper = static_cast<ClipPathElement*>(element)->getClipper(this);
|
||||
|
@ -551,7 +551,7 @@ LayoutMarker* LayoutContext::getMarker(const std::string& id)
|
|||
return static_cast<LayoutMarker*>(ref);
|
||||
|
||||
auto element = getElementById(id);
|
||||
if(element == nullptr || element->id != ElementId::Marker)
|
||||
if(element == nullptr || element->id != ElementID::Marker)
|
||||
return nullptr;
|
||||
|
||||
auto marker = static_cast<MarkerElement*>(element)->getMarker(this);
|
||||
|
|
9
external/lunasvg/source/layoutcontext.h
vendored
9
external/lunasvg/source/layoutcontext.h
vendored
|
@ -346,14 +346,13 @@ private:
|
|||
RenderMode m_mode;
|
||||
};
|
||||
|
||||
class ParseDocument;
|
||||
class TreeBuilder;
|
||||
class StyledElement;
|
||||
class GeometryElement;
|
||||
|
||||
class LayoutContext
|
||||
{
|
||||
class LayoutContext {
|
||||
public:
|
||||
LayoutContext(const ParseDocument* document, LayoutSymbol* root);
|
||||
LayoutContext(const TreeBuilder* builder, LayoutSymbol* root);
|
||||
|
||||
Element* getElementById(const std::string& id) const;
|
||||
LayoutObject* getResourcesById(const std::string& id) const;
|
||||
|
@ -373,7 +372,7 @@ public:
|
|||
bool hasReference(const Element* element) const;
|
||||
|
||||
private:
|
||||
const ParseDocument* m_document;
|
||||
const TreeBuilder* m_builder;
|
||||
LayoutSymbol* m_root;
|
||||
std::map<std::string, LayoutObject*> m_resourcesCache;
|
||||
std::set<const Element*> m_references;
|
||||
|
|
73
external/lunasvg/source/lunasvg.cpp
vendored
73
external/lunasvg/source/lunasvg.cpp
vendored
|
@ -141,15 +141,29 @@ void Bitmap::convert(int ri, int gi, int bi, int ai, bool unpremultiply)
|
|||
|
||||
Box::Box(double x, double y, double w, double h)
|
||||
: x(x), y(y), w(w), h(h)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
Box::Box(const Rect& rect)
|
||||
: x(rect.x), y(rect.y), w(rect.w), h(rect.h)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
Box& Box::transform(const Matrix &matrix)
|
||||
{
|
||||
*this = transformed(matrix);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Box Box::transformed(const Matrix& matrix) const
|
||||
{
|
||||
return Transform(matrix).map(*this);
|
||||
}
|
||||
|
||||
Matrix::Matrix(double a, double b, double c, double d, double e, double f)
|
||||
: a(a), b(b), c(c), d(d), e(e), f(f)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
Matrix::Matrix(const Transform& transform)
|
||||
: a(transform.m00), b(transform.m10), c(transform.m01), d(transform.m11), e(transform.m02), f(transform.m12)
|
||||
|
@ -232,11 +246,6 @@ Matrix Matrix::operator*(const Matrix& matrix) const
|
|||
return Transform(*this) * Transform(matrix);
|
||||
}
|
||||
|
||||
Box Matrix::map(const Box& box) const
|
||||
{
|
||||
return Transform(*this).map(box);
|
||||
}
|
||||
|
||||
Matrix Matrix::rotated(double angle)
|
||||
{
|
||||
return Transform::rotated(angle);
|
||||
|
@ -283,11 +292,11 @@ std::unique_ptr<Document> Document::loadFromData(const std::string& string)
|
|||
|
||||
std::unique_ptr<Document> Document::loadFromData(const char* data, std::size_t size)
|
||||
{
|
||||
ParseDocument parser;
|
||||
if(!parser.parse(data, size))
|
||||
TreeBuilder builder;
|
||||
if(!builder.parse(data, size))
|
||||
return nullptr;
|
||||
|
||||
auto root = parser.layout();
|
||||
auto root = builder.build();
|
||||
if(!root || root->children.empty())
|
||||
return nullptr;
|
||||
|
||||
|
@ -301,48 +310,6 @@ std::unique_ptr<Document> Document::loadFromData(const char* data)
|
|||
return loadFromData(data, std::strlen(data));
|
||||
}
|
||||
|
||||
Document* Document::rotate(double angle)
|
||||
{
|
||||
root->transform.rotate(angle);
|
||||
return this;
|
||||
}
|
||||
|
||||
Document* Document::rotate(double angle, double cx, double cy)
|
||||
{
|
||||
root->transform.rotate(angle, cx, cy);
|
||||
return this;
|
||||
}
|
||||
|
||||
Document* Document::scale(double sx, double sy)
|
||||
{
|
||||
root->transform.scale(sx, sy);
|
||||
return this;
|
||||
}
|
||||
|
||||
Document* Document::shear(double shx, double shy)
|
||||
{
|
||||
root->transform.shear(shx, shy);
|
||||
return this;
|
||||
}
|
||||
|
||||
Document* Document::translate(double tx, double ty)
|
||||
{
|
||||
root->transform.translate(tx, ty);
|
||||
return this;
|
||||
}
|
||||
|
||||
Document* Document::transform(double a, double b, double c, double d, double e, double f)
|
||||
{
|
||||
root->transform.transform(a, b, c, d, e, f);
|
||||
return this;
|
||||
}
|
||||
|
||||
Document* Document::identity()
|
||||
{
|
||||
root->transform.identity();
|
||||
return this;
|
||||
}
|
||||
|
||||
void Document::setMatrix(const Matrix& matrix)
|
||||
{
|
||||
root->transform = Transform(matrix);
|
||||
|
|
18
external/lunasvg/source/markerelement.cpp
vendored
18
external/lunasvg/source/markerelement.cpp
vendored
|
@ -5,55 +5,55 @@
|
|||
namespace lunasvg {
|
||||
|
||||
MarkerElement::MarkerElement()
|
||||
: StyledElement(ElementId::Marker)
|
||||
: StyledElement(ElementID::Marker)
|
||||
{
|
||||
}
|
||||
|
||||
Length MarkerElement::refX() const
|
||||
{
|
||||
auto& value = get(PropertyId::RefX);
|
||||
auto& value = get(PropertyID::RefX);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length MarkerElement::refY() const
|
||||
{
|
||||
auto& value = get(PropertyId::RefY);
|
||||
auto& value = get(PropertyID::RefY);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length MarkerElement::markerWidth() const
|
||||
{
|
||||
auto& value = get(PropertyId::MarkerWidth);
|
||||
auto& value = get(PropertyID::MarkerWidth);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::ThreePercent);
|
||||
}
|
||||
|
||||
Length MarkerElement::markerHeight() const
|
||||
{
|
||||
auto& value = get(PropertyId::MarkerHeight);
|
||||
auto& value = get(PropertyID::MarkerHeight);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::ThreePercent);
|
||||
}
|
||||
|
||||
Angle MarkerElement::orient() const
|
||||
{
|
||||
auto& value = get(PropertyId::Orient);
|
||||
auto& value = get(PropertyID::Orient);
|
||||
return Parser::parseAngle(value);
|
||||
}
|
||||
|
||||
MarkerUnits MarkerElement::markerUnits() const
|
||||
{
|
||||
auto& value = get(PropertyId::MarkerUnits);
|
||||
auto& value = get(PropertyID::MarkerUnits);
|
||||
return Parser::parseMarkerUnits(value);
|
||||
}
|
||||
|
||||
Rect MarkerElement::viewBox() const
|
||||
{
|
||||
auto& value = get(PropertyId::ViewBox);
|
||||
auto& value = get(PropertyID::ViewBox);
|
||||
return Parser::parseViewBox(value);
|
||||
}
|
||||
|
||||
PreserveAspectRatio MarkerElement::preserveAspectRatio() const
|
||||
{
|
||||
auto& value = get(PropertyId::PreserveAspectRatio);
|
||||
auto& value = get(PropertyID::PreserveAspectRatio);
|
||||
return Parser::parsePreserveAspectRatio(value);
|
||||
}
|
||||
|
||||
|
|
14
external/lunasvg/source/maskelement.cpp
vendored
14
external/lunasvg/source/maskelement.cpp
vendored
|
@ -5,43 +5,43 @@
|
|||
namespace lunasvg {
|
||||
|
||||
MaskElement::MaskElement()
|
||||
: StyledElement(ElementId::Mask)
|
||||
: StyledElement(ElementID::Mask)
|
||||
{
|
||||
}
|
||||
|
||||
Length MaskElement::x() const
|
||||
{
|
||||
auto& value = get(PropertyId::X);
|
||||
auto& value = get(PropertyID::X);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::MinusTenPercent);
|
||||
}
|
||||
|
||||
Length MaskElement::y() const
|
||||
{
|
||||
auto& value = get(PropertyId::Y);
|
||||
auto& value = get(PropertyID::Y);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::MinusTenPercent);
|
||||
}
|
||||
|
||||
Length MaskElement::width() const
|
||||
{
|
||||
auto& value = get(PropertyId::Width);
|
||||
auto& value = get(PropertyID::Width);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::OneTwentyPercent);
|
||||
}
|
||||
|
||||
Length MaskElement::height() const
|
||||
{
|
||||
auto& value = get(PropertyId::Height);
|
||||
auto& value = get(PropertyID::Height);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::OneTwentyPercent);
|
||||
}
|
||||
|
||||
Units MaskElement::maskUnits() const
|
||||
{
|
||||
auto& value = get(PropertyId::MaskUnits);
|
||||
auto& value = get(PropertyID::MaskUnits);
|
||||
return Parser::parseUnits(value, Units::ObjectBoundingBox);
|
||||
}
|
||||
|
||||
Units MaskElement::maskContentUnits() const
|
||||
{
|
||||
auto& value = get(PropertyId::MaskContentUnits);
|
||||
auto& value = get(PropertyID::MaskContentUnits);
|
||||
return Parser::parseUnits(value, Units::UserSpaceOnUse);
|
||||
}
|
||||
|
||||
|
|
118
external/lunasvg/source/paintelement.cpp
vendored
118
external/lunasvg/source/paintelement.cpp
vendored
|
@ -7,37 +7,37 @@
|
|||
|
||||
namespace lunasvg {
|
||||
|
||||
PaintElement::PaintElement(ElementId id)
|
||||
PaintElement::PaintElement(ElementID id)
|
||||
: StyledElement(id)
|
||||
{
|
||||
}
|
||||
|
||||
GradientElement::GradientElement(ElementId id)
|
||||
GradientElement::GradientElement(ElementID id)
|
||||
: PaintElement(id)
|
||||
{
|
||||
}
|
||||
|
||||
Transform GradientElement::gradientTransform() const
|
||||
{
|
||||
auto& value = get(PropertyId::GradientTransform);
|
||||
auto& value = get(PropertyID::GradientTransform);
|
||||
return Parser::parseTransform(value);
|
||||
}
|
||||
|
||||
SpreadMethod GradientElement::spreadMethod() const
|
||||
{
|
||||
auto& value = get(PropertyId::SpreadMethod);
|
||||
auto& value = get(PropertyID::SpreadMethod);
|
||||
return Parser::parseSpreadMethod(value);
|
||||
}
|
||||
|
||||
Units GradientElement::gradientUnits() const
|
||||
{
|
||||
auto& value = get(PropertyId::GradientUnits);
|
||||
auto& value = get(PropertyID::GradientUnits);
|
||||
return Parser::parseUnits(value, Units::ObjectBoundingBox);
|
||||
}
|
||||
|
||||
std::string GradientElement::href() const
|
||||
{
|
||||
auto& value = get(PropertyId::Href);
|
||||
auto& value = get(PropertyID::Href);
|
||||
return Parser::parseHref(value);
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ GradientStops GradientElement::buildGradientStops() const
|
|||
if(child->isText())
|
||||
continue;
|
||||
auto element = static_cast<Element*>(child.get());
|
||||
if(element->id != ElementId::Stop)
|
||||
if(element->id != ElementID::Stop)
|
||||
continue;
|
||||
auto stop = static_cast<StopElement*>(element);
|
||||
auto offset = std::max(prevOffset, stop->offset());
|
||||
|
@ -62,31 +62,31 @@ GradientStops GradientElement::buildGradientStops() const
|
|||
}
|
||||
|
||||
LinearGradientElement::LinearGradientElement()
|
||||
: GradientElement(ElementId::LinearGradient)
|
||||
: GradientElement(ElementID::LinearGradient)
|
||||
{
|
||||
}
|
||||
|
||||
Length LinearGradientElement::x1() const
|
||||
{
|
||||
auto& value = get(PropertyId::X1);
|
||||
auto& value = get(PropertyID::X1);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length LinearGradientElement::y1() const
|
||||
{
|
||||
auto& value = get(PropertyId::Y1);
|
||||
auto& value = get(PropertyID::Y1);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length LinearGradientElement::x2() const
|
||||
{
|
||||
auto& value = get(PropertyId::X2);
|
||||
auto& value = get(PropertyID::X2);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::HundredPercent);
|
||||
}
|
||||
|
||||
Length LinearGradientElement::y2() const
|
||||
{
|
||||
auto& value = get(PropertyId::Y2);
|
||||
auto& value = get(PropertyID::Y2);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
|
@ -98,30 +98,30 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
|
|||
|
||||
while(true)
|
||||
{
|
||||
if(!attributes.hasGradientTransform() && current->has(PropertyId::GradientTransform))
|
||||
if(!attributes.hasGradientTransform() && current->has(PropertyID::GradientTransform))
|
||||
attributes.setGradientTransform(current->gradientTransform());
|
||||
if(!attributes.hasSpreadMethod() && current->has(PropertyId::SpreadMethod))
|
||||
if(!attributes.hasSpreadMethod() && current->has(PropertyID::SpreadMethod))
|
||||
attributes.setSpreadMethod(current->spreadMethod());
|
||||
if(!attributes.hasGradientUnits() && current->has(PropertyId::GradientUnits))
|
||||
if(!attributes.hasGradientUnits() && current->has(PropertyID::GradientUnits))
|
||||
attributes.setGradientUnits(current->gradientUnits());
|
||||
if(!attributes.hasGradientStops())
|
||||
attributes.setGradientStops(current->buildGradientStops());
|
||||
|
||||
if(current->id == ElementId::LinearGradient)
|
||||
if(current->id == ElementID::LinearGradient)
|
||||
{
|
||||
auto element = static_cast<const LinearGradientElement*>(current);
|
||||
if(!attributes.hasX1() && element->has(PropertyId::X1))
|
||||
if(!attributes.hasX1() && element->has(PropertyID::X1))
|
||||
attributes.setX1(element->x1());
|
||||
if(!attributes.hasY1() && element->has(PropertyId::Y1))
|
||||
if(!attributes.hasY1() && element->has(PropertyID::Y1))
|
||||
attributes.setY1(element->y1());
|
||||
if(!attributes.hasX2() && element->has(PropertyId::X2))
|
||||
if(!attributes.hasX2() && element->has(PropertyID::X2))
|
||||
attributes.setX2(element->x2());
|
||||
if(!attributes.hasY2() && element->has(PropertyId::Y2))
|
||||
if(!attributes.hasY2() && element->has(PropertyID::Y2))
|
||||
attributes.setY2(element->y2());
|
||||
}
|
||||
|
||||
auto ref = context->getElementById(current->href());
|
||||
if(!ref || !(ref->id == ElementId::LinearGradient || ref->id == ElementId::RadialGradient))
|
||||
if(!ref || !(ref->id == ElementID::LinearGradient || ref->id == ElementID::RadialGradient))
|
||||
break;
|
||||
|
||||
processedGradients.insert(current);
|
||||
|
@ -164,37 +164,37 @@ std::unique_ptr<Node> LinearGradientElement::clone() const
|
|||
}
|
||||
|
||||
RadialGradientElement::RadialGradientElement()
|
||||
: GradientElement(ElementId::RadialGradient)
|
||||
: GradientElement(ElementID::RadialGradient)
|
||||
{
|
||||
}
|
||||
|
||||
Length RadialGradientElement::cx() const
|
||||
{
|
||||
auto& value = get(PropertyId::Cx);
|
||||
auto& value = get(PropertyID::Cx);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::FiftyPercent);
|
||||
}
|
||||
|
||||
Length RadialGradientElement::cy() const
|
||||
{
|
||||
auto& value = get(PropertyId::Cy);
|
||||
auto& value = get(PropertyID::Cy);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::FiftyPercent);
|
||||
}
|
||||
|
||||
Length RadialGradientElement::r() const
|
||||
{
|
||||
auto& value = get(PropertyId::R);
|
||||
auto& value = get(PropertyID::R);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::FiftyPercent);
|
||||
}
|
||||
|
||||
Length RadialGradientElement::fx() const
|
||||
{
|
||||
auto& value = get(PropertyId::Fx);
|
||||
auto& value = get(PropertyID::Fx);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length RadialGradientElement::fy() const
|
||||
{
|
||||
auto& value = get(PropertyId::Fy);
|
||||
auto& value = get(PropertyID::Fy);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
|
@ -206,32 +206,32 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
|
|||
|
||||
while(true)
|
||||
{
|
||||
if(!attributes.hasGradientTransform() && current->has(PropertyId::GradientTransform))
|
||||
if(!attributes.hasGradientTransform() && current->has(PropertyID::GradientTransform))
|
||||
attributes.setGradientTransform(current->gradientTransform());
|
||||
if(!attributes.hasSpreadMethod() && current->has(PropertyId::SpreadMethod))
|
||||
if(!attributes.hasSpreadMethod() && current->has(PropertyID::SpreadMethod))
|
||||
attributes.setSpreadMethod(current->spreadMethod());
|
||||
if(!attributes.hasGradientUnits() && current->has(PropertyId::GradientUnits))
|
||||
if(!attributes.hasGradientUnits() && current->has(PropertyID::GradientUnits))
|
||||
attributes.setGradientUnits(current->gradientUnits());
|
||||
if(!attributes.hasGradientStops())
|
||||
attributes.setGradientStops(current->buildGradientStops());
|
||||
|
||||
if(current->id == ElementId::RadialGradient)
|
||||
if(current->id == ElementID::RadialGradient)
|
||||
{
|
||||
auto element = static_cast<const RadialGradientElement*>(current);
|
||||
if(!attributes.hasCx() && element->has(PropertyId::Cx))
|
||||
if(!attributes.hasCx() && element->has(PropertyID::Cx))
|
||||
attributes.setCx(element->cx());
|
||||
if(!attributes.hasCy() && element->has(PropertyId::Cy))
|
||||
if(!attributes.hasCy() && element->has(PropertyID::Cy))
|
||||
attributes.setCy(element->cy());
|
||||
if(!attributes.hasR() && element->has(PropertyId::R))
|
||||
if(!attributes.hasR() && element->has(PropertyID::R))
|
||||
attributes.setR(element->r());
|
||||
if(!attributes.hasFx() && element->has(PropertyId::Fx))
|
||||
if(!attributes.hasFx() && element->has(PropertyID::Fx))
|
||||
attributes.setFx(element->fx());
|
||||
if(!attributes.hasFy() && element->has(PropertyId::Fy))
|
||||
if(!attributes.hasFy() && element->has(PropertyID::Fy))
|
||||
attributes.setFy(element->fy());
|
||||
}
|
||||
|
||||
auto ref = context->getElementById(current->href());
|
||||
if(!ref || !(ref->id == ElementId::LinearGradient || ref->id == ElementId::RadialGradient))
|
||||
if(!ref || !(ref->id == ElementID::LinearGradient || ref->id == ElementID::RadialGradient))
|
||||
break;
|
||||
|
||||
processedGradients.insert(current);
|
||||
|
@ -278,67 +278,67 @@ std::unique_ptr<Node> RadialGradientElement::clone() const
|
|||
}
|
||||
|
||||
PatternElement::PatternElement()
|
||||
: PaintElement(ElementId::Pattern)
|
||||
: PaintElement(ElementID::Pattern)
|
||||
{
|
||||
}
|
||||
|
||||
Length PatternElement::x() const
|
||||
{
|
||||
auto& value = get(PropertyId::X);
|
||||
auto& value = get(PropertyID::X);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length PatternElement::y() const
|
||||
{
|
||||
auto& value = get(PropertyId::Y);
|
||||
auto& value = get(PropertyID::Y);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length PatternElement::width() const
|
||||
{
|
||||
auto& value = get(PropertyId::Width);
|
||||
auto& value = get(PropertyID::Width);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length PatternElement::height() const
|
||||
{
|
||||
auto& value = get(PropertyId::Height);
|
||||
auto& value = get(PropertyID::Height);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Transform PatternElement::patternTransform() const
|
||||
{
|
||||
auto& value = get(PropertyId::PatternTransform);
|
||||
auto& value = get(PropertyID::PatternTransform);
|
||||
return Parser::parseTransform(value);
|
||||
}
|
||||
|
||||
Units PatternElement::patternUnits() const
|
||||
{
|
||||
auto& value = get(PropertyId::PatternUnits);
|
||||
auto& value = get(PropertyID::PatternUnits);
|
||||
return Parser::parseUnits(value, Units::ObjectBoundingBox);
|
||||
}
|
||||
|
||||
Units PatternElement::patternContentUnits() const
|
||||
{
|
||||
auto& value = get(PropertyId::PatternContentUnits);
|
||||
auto& value = get(PropertyID::PatternContentUnits);
|
||||
return Parser::parseUnits(value, Units::UserSpaceOnUse);
|
||||
}
|
||||
|
||||
Rect PatternElement::viewBox() const
|
||||
{
|
||||
auto& value = get(PropertyId::ViewBox);
|
||||
auto& value = get(PropertyID::ViewBox);
|
||||
return Parser::parseViewBox(value);
|
||||
}
|
||||
|
||||
PreserveAspectRatio PatternElement::preserveAspectRatio() const
|
||||
{
|
||||
auto& value = get(PropertyId::PreserveAspectRatio);
|
||||
auto& value = get(PropertyID::PreserveAspectRatio);
|
||||
return Parser::parsePreserveAspectRatio(value);
|
||||
}
|
||||
|
||||
std::string PatternElement::href() const
|
||||
{
|
||||
auto& value = get(PropertyId::Href);
|
||||
auto& value = get(PropertyID::Href);
|
||||
return Parser::parseHref(value);
|
||||
}
|
||||
|
||||
|
@ -353,29 +353,29 @@ std::unique_ptr<LayoutObject> PatternElement::getPainter(LayoutContext* context)
|
|||
|
||||
while(true)
|
||||
{
|
||||
if(!attributes.hasX() && current->has(PropertyId::X))
|
||||
if(!attributes.hasX() && current->has(PropertyID::X))
|
||||
attributes.setX(current->x());
|
||||
if(!attributes.hasY() && current->has(PropertyId::Y))
|
||||
if(!attributes.hasY() && current->has(PropertyID::Y))
|
||||
attributes.setY(current->y());
|
||||
if(!attributes.hasWidth() && current->has(PropertyId::Width))
|
||||
if(!attributes.hasWidth() && current->has(PropertyID::Width))
|
||||
attributes.setWidth(current->width());
|
||||
if(!attributes.hasHeight() && current->has(PropertyId::Height))
|
||||
if(!attributes.hasHeight() && current->has(PropertyID::Height))
|
||||
attributes.setHeight(current->height());
|
||||
if(!attributes.hasPatternTransform() && current->has(PropertyId::PatternTransform))
|
||||
if(!attributes.hasPatternTransform() && current->has(PropertyID::PatternTransform))
|
||||
attributes.setPatternTransform(current->patternTransform());
|
||||
if(!attributes.hasPatternUnits() && current->has(PropertyId::PatternUnits))
|
||||
if(!attributes.hasPatternUnits() && current->has(PropertyID::PatternUnits))
|
||||
attributes.setPatternUnits(current->patternUnits());
|
||||
if(!attributes.hasPatternContentUnits() && current->has(PropertyId::PatternContentUnits))
|
||||
if(!attributes.hasPatternContentUnits() && current->has(PropertyID::PatternContentUnits))
|
||||
attributes.setPatternContentUnits(current->patternContentUnits());
|
||||
if(!attributes.hasViewBox() && current->has(PropertyId::ViewBox))
|
||||
if(!attributes.hasViewBox() && current->has(PropertyID::ViewBox))
|
||||
attributes.setViewBox(current->viewBox());
|
||||
if(!attributes.hasPreserveAspectRatio() && current->has(PropertyId::PreserveAspectRatio))
|
||||
if(!attributes.hasPreserveAspectRatio() && current->has(PropertyID::PreserveAspectRatio))
|
||||
attributes.setPreserveAspectRatio(current->preserveAspectRatio());
|
||||
if(!attributes.hasPatternContentElement() && current->children.size())
|
||||
attributes.setPatternContentElement(current);
|
||||
|
||||
auto ref = context->getElementById(current->href());
|
||||
if(!ref || ref->id != ElementId::Pattern)
|
||||
if(!ref || ref->id != ElementID::Pattern)
|
||||
break;
|
||||
|
||||
processedPatterns.insert(current);
|
||||
|
@ -413,7 +413,7 @@ std::unique_ptr<Node> PatternElement::clone() const
|
|||
}
|
||||
|
||||
SolidColorElement::SolidColorElement()
|
||||
: PaintElement(ElementId::SolidColor)
|
||||
: PaintElement(ElementID::SolidColor)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
4
external/lunasvg/source/paintelement.h
vendored
4
external/lunasvg/source/paintelement.h
vendored
|
@ -11,7 +11,7 @@ class LayoutObject;
|
|||
class PaintElement : public StyledElement
|
||||
{
|
||||
public:
|
||||
PaintElement(ElementId id);
|
||||
PaintElement(ElementID id);
|
||||
|
||||
bool isPaint() const { return true; }
|
||||
virtual std::unique_ptr<LayoutObject> getPainter(LayoutContext* context) const = 0;
|
||||
|
@ -20,7 +20,7 @@ public:
|
|||
class GradientElement : public PaintElement
|
||||
{
|
||||
public:
|
||||
GradientElement(ElementId id);
|
||||
GradientElement(ElementID id);
|
||||
|
||||
Transform gradientTransform() const;
|
||||
SpreadMethod spreadMethod() const;
|
||||
|
|
1024
external/lunasvg/source/parser.cpp
vendored
1024
external/lunasvg/source/parser.cpp
vendored
File diff suppressed because it is too large
Load diff
105
external/lunasvg/source/parser.h
vendored
105
external/lunasvg/source/parser.h
vendored
|
@ -2,6 +2,7 @@
|
|||
#define PARSER_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "property.h"
|
||||
#include "element.h"
|
||||
|
@ -63,7 +64,10 @@ private:
|
|||
static bool parseTransform(const char*& ptr, const char* end, TransformType& type, double* values, int& count);
|
||||
};
|
||||
|
||||
struct Selector;
|
||||
struct SimpleSelector;
|
||||
|
||||
using Selector = std::vector<SimpleSelector>;
|
||||
using SelectorList = std::vector<Selector>;
|
||||
|
||||
struct AttributeSelector
|
||||
{
|
||||
|
@ -78,20 +82,19 @@ struct AttributeSelector
|
|||
Contains
|
||||
};
|
||||
|
||||
PropertyId id{PropertyId::Unknown};
|
||||
std::string value;
|
||||
MatchType matchType{MatchType::None};
|
||||
PropertyID id{PropertyID::Unknown};
|
||||
std::string value;
|
||||
};
|
||||
|
||||
using SelectorList = std::vector<Selector>;
|
||||
|
||||
struct PseudoClass
|
||||
struct PseudoClassSelector
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
Unknown,
|
||||
Empty,
|
||||
Root,
|
||||
Is,
|
||||
Not,
|
||||
FirstChild,
|
||||
LastChild,
|
||||
|
@ -102,7 +105,9 @@ struct PseudoClass
|
|||
};
|
||||
|
||||
Type type{Type::Unknown};
|
||||
SelectorList notSelectors;
|
||||
int16_t a{0};
|
||||
int16_t b{0};
|
||||
SelectorList subSelectors;
|
||||
};
|
||||
|
||||
struct SimpleSelector
|
||||
|
@ -115,16 +120,10 @@ struct SimpleSelector
|
|||
InDirectAdjacent
|
||||
};
|
||||
|
||||
ElementId id{ElementId::Star};
|
||||
std::vector<AttributeSelector> attributeSelectors;
|
||||
std::vector<PseudoClass> pseudoClasses;
|
||||
Combinator combinator{Combinator::Descendant};
|
||||
};
|
||||
|
||||
struct Selector
|
||||
{
|
||||
std::vector<SimpleSelector> simpleSelectors;
|
||||
int specificity{0};
|
||||
ElementID id{ElementID::Star};
|
||||
std::vector<AttributeSelector> attributeSelectors;
|
||||
std::vector<PseudoClassSelector> pseudoClassSelectors;
|
||||
};
|
||||
|
||||
struct Rule
|
||||
|
@ -133,21 +132,47 @@ struct Rule
|
|||
PropertyList declarations;
|
||||
};
|
||||
|
||||
class RuleMatchContext
|
||||
{
|
||||
class RuleData {
|
||||
public:
|
||||
RuleMatchContext(const std::vector<Rule>& rules);
|
||||
RuleData(const Selector& selector, const PropertyList& properties, uint32_t specificity, uint32_t position)
|
||||
: m_selector(selector), m_properties(properties), m_specificity(specificity), m_position(position)
|
||||
{}
|
||||
|
||||
const Selector& selector() const { return m_selector; }
|
||||
const PropertyList& properties() const { return m_properties; }
|
||||
const uint32_t& specificity() const { return m_specificity; }
|
||||
const uint32_t& position() const { return m_position; }
|
||||
|
||||
bool match(const Element* element) const;
|
||||
|
||||
private:
|
||||
bool matchSimpleSelector(const SimpleSelector& selector, const Element* element) const;
|
||||
bool matchAttributeSelector(const AttributeSelector& selector, const Element* element) const;
|
||||
bool matchPseudoClassSelector(const PseudoClassSelector& selector, const Element* element) const;
|
||||
|
||||
private:
|
||||
Selector m_selector;
|
||||
PropertyList m_properties;
|
||||
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;
|
||||
|
||||
void parse(const std::string& content);
|
||||
void add(const Rule& rule);
|
||||
bool empty() const { return m_position == 0; }
|
||||
|
||||
std::vector<const PropertyList*> match(const Element* element) const;
|
||||
|
||||
private:
|
||||
bool selectorMatch(const Selector* selector, const Element* element) const;
|
||||
bool simpleSelectorMatch(const SimpleSelector& selector, const Element* element) const;
|
||||
bool attributeSelectorMatch(const AttributeSelector& selector, const Element* element) const;
|
||||
bool pseudoClassMatch(const PseudoClass& pseudo, const Element* element) const;
|
||||
|
||||
private:
|
||||
std::multimap<int, std::pair<const Selector*, const PropertyList*>, std::less<int>> m_selectors;
|
||||
std::multiset<RuleData> m_rules;
|
||||
uint32_t m_position{0};
|
||||
};
|
||||
|
||||
class CSSParser
|
||||
|
@ -155,35 +180,29 @@ class CSSParser
|
|||
public:
|
||||
CSSParser() = default;
|
||||
|
||||
bool parseMore(const std::string& value);
|
||||
|
||||
const std::vector<Rule>& rules() const { return m_rules; }
|
||||
static bool parseSheet(StyleSheet* sheet, const std::string& value);
|
||||
|
||||
private:
|
||||
bool parseAtRule(const char*& ptr, const char* end) const;
|
||||
bool parseRule(const char*& ptr, const char* end, Rule& rule) const;
|
||||
bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors) const;
|
||||
bool parseDeclarations(const char*& ptr, const char* end, PropertyList& declarations) const;
|
||||
bool parseSelector(const char*& ptr, const char* end, Selector& selector) const;
|
||||
bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector) const;
|
||||
|
||||
private:
|
||||
std::vector<Rule> m_rules;
|
||||
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, PropertyList& declarations);
|
||||
static bool parseSelector(const char*& ptr, const char* end, Selector& selector);
|
||||
static bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector);
|
||||
};
|
||||
|
||||
class LayoutSymbol;
|
||||
|
||||
class ParseDocument
|
||||
{
|
||||
class TreeBuilder {
|
||||
public:
|
||||
ParseDocument();
|
||||
~ParseDocument();
|
||||
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> layout() const;
|
||||
std::unique_ptr<LayoutSymbol> build() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<SVGElement> m_rootElement;
|
||||
|
|
237
external/lunasvg/source/parserutils.h
vendored
237
external/lunasvg/source/parserutils.h
vendored
|
@ -6,6 +6,8 @@
|
|||
#include <limits>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
#include <cassert>
|
||||
|
||||
namespace lunasvg {
|
||||
|
||||
|
@ -262,6 +264,241 @@ inline bool parseNumber(const char*& ptr, const char* end, T& number)
|
|||
|
||||
} // namespace Utils
|
||||
|
||||
class ParserString {
|
||||
public:
|
||||
explicit ParserString(const std::string_view& value)
|
||||
: ParserString(value.data(), value.length())
|
||||
{}
|
||||
|
||||
ParserString(const char* begin, size_t length)
|
||||
: ParserString(begin, begin + length)
|
||||
{}
|
||||
|
||||
ParserString(const char* begin, const char* end)
|
||||
: ParserString(begin, begin, end)
|
||||
{}
|
||||
|
||||
ParserString(const char* current, const char* begin, const char* end)
|
||||
: m_current(current), m_begin(begin), m_end(end)
|
||||
{}
|
||||
|
||||
ParserString operator+(size_t count) const {
|
||||
auto current = m_current + count;
|
||||
assert(m_end >= current);
|
||||
return ParserString(current, m_begin, m_end);
|
||||
}
|
||||
|
||||
ParserString operator-(size_t count) const {
|
||||
auto current = m_current - count;
|
||||
assert(current >= m_begin);
|
||||
return ParserString(current, m_begin, m_end);
|
||||
}
|
||||
|
||||
ParserString& operator+=(size_t count) {
|
||||
*this = *this + count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ParserString& operator-=(size_t count) {
|
||||
*this = *this - count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const char& operator*() const {
|
||||
assert(m_current < m_end);
|
||||
return *m_current;
|
||||
}
|
||||
|
||||
char peek(size_t count = 0) const {
|
||||
auto current = m_current + count;
|
||||
assert(m_end >= current);
|
||||
if(current == m_end)
|
||||
return 0;
|
||||
return *current;
|
||||
}
|
||||
|
||||
char advance(size_t count = 1) {
|
||||
m_current += count;
|
||||
assert(m_end >= m_current);
|
||||
if(m_current == m_end)
|
||||
return 0;
|
||||
return *m_current;
|
||||
}
|
||||
|
||||
char get() const {
|
||||
assert(m_end >= m_current);
|
||||
if(m_current == m_end)
|
||||
return 0;
|
||||
return *m_current;
|
||||
}
|
||||
|
||||
std::string_view string(size_t offset, size_t count) const { return string().substr(offset, count); }
|
||||
std::string_view substring(size_t offset, size_t count) const { return substring().substr(offset, count); }
|
||||
|
||||
std::string_view string() const { return std::string_view(m_begin, length()); }
|
||||
std::string_view substring() const { return std::string_view(m_current, sublength()); }
|
||||
|
||||
size_t offset() const { return m_current - m_begin; }
|
||||
size_t length() const { return m_end - m_begin; }
|
||||
size_t sublength() const { return m_end - m_current; }
|
||||
|
||||
const char* current() const { return m_current; }
|
||||
const char* begin() const { return m_begin; }
|
||||
const char* end() const { return m_end; }
|
||||
|
||||
bool empty() const { return m_current == m_end; }
|
||||
|
||||
private:
|
||||
const char* m_current;
|
||||
const char* m_begin;
|
||||
const char* m_end;
|
||||
};
|
||||
|
||||
constexpr bool isspace(int cc) { return (cc == ' ' || cc == '\n' || cc == '\t' || cc == '\r' || cc == '\f'); }
|
||||
constexpr bool isdigit(int cc) { return (cc >= '0' && cc <= '9'); }
|
||||
constexpr bool isupper(int cc) { return (cc >= 'A' && cc <= 'Z'); }
|
||||
constexpr bool islower(int cc) { return (cc >= 'a' && cc <= 'z'); }
|
||||
constexpr bool isalpha(int cc) { return isupper(cc) || islower(cc); }
|
||||
|
||||
constexpr bool isxupper(int cc) { return (cc >= 'A' && cc <= 'F'); }
|
||||
constexpr bool isxlower(int cc) { return (cc >= 'a' && cc <= 'f'); }
|
||||
constexpr bool isxdigit(int cc) { return isdigit(cc) || isxupper(cc) || isxlower(cc); }
|
||||
|
||||
constexpr int xdigit(int cc) {
|
||||
if(isdigit(cc))
|
||||
return cc - '0';
|
||||
if(isxupper(cc))
|
||||
return 10 + cc - 'A';
|
||||
if(isxlower(cc))
|
||||
return 10 + cc - 'a';
|
||||
return 0;
|
||||
}
|
||||
|
||||
constexpr char tolower(int cc) {
|
||||
if(isupper(cc))
|
||||
return cc + 0x20;
|
||||
return cc;
|
||||
}
|
||||
|
||||
constexpr bool equals(int a, int b, bool caseSensitive) {
|
||||
if(caseSensitive)
|
||||
return a == b;
|
||||
return tolower(a) == tolower(b);
|
||||
}
|
||||
|
||||
constexpr bool equals(const char* aData, size_t aLength, const char* bData, size_t bLength, bool caseSensitive) {
|
||||
if(aLength != bLength)
|
||||
return false;
|
||||
|
||||
auto aEnd = aData + aLength;
|
||||
while(aData != aEnd) {
|
||||
if(!equals(*aData, *bData, caseSensitive))
|
||||
return false;
|
||||
++aData;
|
||||
++bData;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr bool equals(const std::string_view& a, const std::string_view& b, bool caseSensitive) {
|
||||
return equals(a.data(), a.length(), b.data(), b.length(), caseSensitive);
|
||||
}
|
||||
|
||||
constexpr bool contains(const std::string_view& value, const std::string_view& subvalue, bool caseSensitive) {
|
||||
if(subvalue.empty() || subvalue.length() > value.length())
|
||||
return false;
|
||||
auto it = value.data();
|
||||
auto end = it + value.length();
|
||||
while(it < end) {
|
||||
size_t count = 0;
|
||||
do {
|
||||
if(!equals(*it, subvalue[count], caseSensitive))
|
||||
break;
|
||||
++count;
|
||||
++it;
|
||||
} while(it < end && count < subvalue.length());
|
||||
if(count == subvalue.length())
|
||||
return true;
|
||||
++it;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr bool includes(const std::string_view& value, const std::string_view& subvalue, bool caseSensitive) {
|
||||
if(subvalue.empty() || subvalue.length() > value.length())
|
||||
return false;
|
||||
auto it = value.data();
|
||||
auto end = it + value.length();
|
||||
while(true) {
|
||||
while(it < end && isspace(*it))
|
||||
++it;
|
||||
if(it >= end)
|
||||
return false;
|
||||
size_t count = 0;
|
||||
auto begin = it;
|
||||
do {
|
||||
++count;
|
||||
++it;
|
||||
} while(it < end && !isspace(*it));
|
||||
if(equals(begin, count, subvalue.data(), subvalue.length(), caseSensitive))
|
||||
return true;
|
||||
++it;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr bool startswith(const std::string_view& value, const std::string_view& subvalue, bool caseSensitive) {
|
||||
if(subvalue.empty() || subvalue.length() > value.length())
|
||||
return false;
|
||||
return equals(value.substr(0, subvalue.size()), subvalue, caseSensitive);
|
||||
}
|
||||
|
||||
constexpr bool endswith(const std::string_view& value, const std::string_view& subvalue, bool caseSensitive) {
|
||||
if(subvalue.empty() || subvalue.length() > value.length())
|
||||
return false;
|
||||
return equals(value.substr(value.size() - subvalue.size(), subvalue.size()), subvalue, caseSensitive);
|
||||
}
|
||||
|
||||
constexpr bool dashequals(const std::string_view& value, const std::string_view& subvalue, bool caseSensitive) {
|
||||
if(!startswith(value, subvalue, caseSensitive))
|
||||
return false;
|
||||
return (value.length() == subvalue.length() || value.at(subvalue.length()) == '-');
|
||||
}
|
||||
|
||||
inline void appendCodepoint(std::string& output, uint32_t cp) {
|
||||
char c[5] = {0, 0, 0, 0, 0};
|
||||
if(cp < 0x80) {
|
||||
c[1] = 0;
|
||||
c[0] = cp;
|
||||
} else if(cp < 0x800) {
|
||||
c[2] = 0;
|
||||
c[1] = (cp & 0x3F) | 0x80;
|
||||
cp >>= 6;
|
||||
c[0] = cp | 0xC0;
|
||||
} else if(cp < 0x10000) {
|
||||
c[3] = 0;
|
||||
c[2] = (cp & 0x3F) | 0x80;
|
||||
cp >>= 6;
|
||||
c[1] = (cp & 0x3F) | 0x80;
|
||||
cp >>= 6;
|
||||
c[0] = cp | 0xE0;
|
||||
} else if(cp < 0x110000) {
|
||||
c[4] = 0;
|
||||
c[3] = (cp & 0x3F) | 0x80;
|
||||
cp >>= 6;
|
||||
c[2] = (cp & 0x3F) | 0x80;
|
||||
cp >>= 6;
|
||||
c[1] = (cp & 0x3F) | 0x80;
|
||||
cp >>= 6;
|
||||
c[0] = cp | 0xF0;
|
||||
}
|
||||
|
||||
output.append(c);
|
||||
}
|
||||
|
||||
} // namespace lunasvg
|
||||
|
||||
#endif // PARSERUTILS_H
|
||||
|
|
254
external/lunasvg/source/pointer.h
vendored
Normal file
254
external/lunasvg/source/pointer.h
vendored
Normal file
|
@ -0,0 +1,254 @@
|
|||
#ifndef POINTER_H
|
||||
#define POINTER_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
namespace lunasvg {
|
||||
|
||||
template<typename T>
|
||||
class RefCounted {
|
||||
public:
|
||||
RefCounted() = default;
|
||||
|
||||
void ref() { ++m_refCount; }
|
||||
void deref() {
|
||||
if(--m_refCount == 0) {
|
||||
delete static_cast<T*>(this);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t refCount() const { return m_refCount; }
|
||||
bool hasOneRefCount() const { return m_refCount == 1; }
|
||||
|
||||
private:
|
||||
uint32_t m_refCount{1};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline void refIfNotNull(T* ptr)
|
||||
{
|
||||
if(ptr)
|
||||
ptr->ref();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void derefIfNotNull(T* ptr)
|
||||
{
|
||||
if(ptr)
|
||||
ptr->deref();
|
||||
}
|
||||
|
||||
template<typename T> class RefPtr;
|
||||
template<typename T> RefPtr<T> adoptPtr(T*);
|
||||
|
||||
template<typename T>
|
||||
class RefPtr {
|
||||
public:
|
||||
RefPtr() = default;
|
||||
RefPtr(std::nullptr_t) : m_ptr(nullptr) {}
|
||||
RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(m_ptr); }
|
||||
RefPtr(T& ref) : m_ptr(&ref) { m_ptr->ref(); }
|
||||
RefPtr(const RefPtr<T>& p) : m_ptr(p.get()) { refIfNotNull(m_ptr); }
|
||||
RefPtr(RefPtr<T>&& p) : m_ptr(p.release()) {}
|
||||
|
||||
template<typename U>
|
||||
RefPtr(const RefPtr<U>& p) : m_ptr(p.get()) { refIfNotNull(m_ptr); }
|
||||
|
||||
template<typename U>
|
||||
RefPtr(RefPtr<U>&& p) : m_ptr(p.release()) {}
|
||||
|
||||
~RefPtr() { derefIfNotNull(m_ptr); }
|
||||
|
||||
T* get() const { return m_ptr; }
|
||||
T& operator*() const { return *m_ptr; }
|
||||
T* operator->() const { return m_ptr; }
|
||||
|
||||
bool empty() const { return !m_ptr; }
|
||||
bool operator!() const { return !m_ptr; }
|
||||
operator bool() const { return !!m_ptr; }
|
||||
|
||||
RefPtr<T>& operator=(std::nullptr_t)
|
||||
{
|
||||
clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefPtr<T>& operator=(T* o)
|
||||
{
|
||||
RefPtr<T> p = o;
|
||||
swap(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefPtr<T>& operator=(T& o)
|
||||
{
|
||||
RefPtr<T> p = o;
|
||||
swap(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefPtr<T>& operator=(const RefPtr<T>& o)
|
||||
{
|
||||
RefPtr<T> p = o;
|
||||
swap(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefPtr<T>& operator=(RefPtr<T>&& o)
|
||||
{
|
||||
RefPtr<T> p = std::move(o);
|
||||
swap(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
RefPtr<T>& operator=(const RefPtr<U>& o)
|
||||
{
|
||||
RefPtr<T> p = o;
|
||||
swap(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
RefPtr<T>& operator=(RefPtr<U>&& o)
|
||||
{
|
||||
RefPtr<T> p = std::move(o);
|
||||
swap(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(RefPtr<T>& o)
|
||||
{
|
||||
std::swap(m_ptr, o.m_ptr);
|
||||
}
|
||||
|
||||
T* release()
|
||||
{
|
||||
T* ptr = m_ptr;
|
||||
m_ptr = nullptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
derefIfNotNull(m_ptr);
|
||||
m_ptr = nullptr;
|
||||
}
|
||||
|
||||
friend RefPtr<T> adoptPtr<T>(T*);
|
||||
|
||||
private:
|
||||
RefPtr(T* ptr, std::nullptr_t) : m_ptr(ptr) {}
|
||||
T* m_ptr{nullptr};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline RefPtr<T> adoptPtr(T* ptr)
|
||||
{
|
||||
return RefPtr<T>(ptr, nullptr);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void swap(RefPtr<T>& a, RefPtr<T>& b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator==(const RefPtr<T>& a, const U* b)
|
||||
{
|
||||
return a.get() == b;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator==(const T* a, const RefPtr<U>& b)
|
||||
{
|
||||
return a == b.get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool operator==(const RefPtr<T>& a, std::nullptr_t)
|
||||
{
|
||||
return a.get() == nullptr;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator!=(const RefPtr<T>& a, const U* b)
|
||||
{
|
||||
return a.get() != b;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator!=(const T* a, const RefPtr<U>& b)
|
||||
{
|
||||
return a != b.get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool operator!=(const RefPtr<T>& a, std::nullptr_t)
|
||||
{
|
||||
return a.get() != nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct is {
|
||||
template<typename U>
|
||||
static bool check(const U& value);
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr bool is_a(U& value) {
|
||||
return is<T>::check(value);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr bool is_a(const U& value) {
|
||||
return is<T>::check(value);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr bool is_a(U* value) {
|
||||
return value && is<T>::check(*value);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr bool is_a(const U* value) {
|
||||
return value && is<T>::check(*value);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr T* to(U& value) {
|
||||
return is_a<T>(value) ? static_cast<T*>(&value) : nullptr;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr const T* to(const U& value) {
|
||||
return is_a<T>(value) ? static_cast<const T*>(&value) : nullptr;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr T* to(U* value) {
|
||||
return is_a<T>(value) ? static_cast<T*>(value) : nullptr;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr const T* to(const U* value) {
|
||||
return is_a<T>(value) ? static_cast<const T*>(value) : nullptr;
|
||||
}
|
||||
|
||||
} // namespace lunasvg
|
||||
|
||||
#endif // POINTER_H
|
4
external/lunasvg/source/stopelement.cpp
vendored
4
external/lunasvg/source/stopelement.cpp
vendored
|
@ -4,13 +4,13 @@
|
|||
namespace lunasvg {
|
||||
|
||||
StopElement::StopElement()
|
||||
: StyledElement(ElementId::Stop)
|
||||
: StyledElement(ElementID::Stop)
|
||||
{
|
||||
}
|
||||
|
||||
double StopElement::offset() const
|
||||
{
|
||||
auto& value = get(PropertyId::Offset);
|
||||
auto& value = get(PropertyID::Offset);
|
||||
return Parser::parseNumberPercentage(value, 0.0);
|
||||
}
|
||||
|
||||
|
|
54
external/lunasvg/source/styledelement.cpp
vendored
54
external/lunasvg/source/styledelement.cpp
vendored
|
@ -3,164 +3,164 @@
|
|||
|
||||
namespace lunasvg {
|
||||
|
||||
StyledElement::StyledElement(ElementId id)
|
||||
StyledElement::StyledElement(ElementID id)
|
||||
: Element(id)
|
||||
{
|
||||
}
|
||||
|
||||
Paint StyledElement::fill() const
|
||||
{
|
||||
auto& value = find(PropertyId::Fill);
|
||||
auto& value = find(PropertyID::Fill);
|
||||
return Parser::parsePaint(value, this, Color::Black);
|
||||
}
|
||||
|
||||
Paint StyledElement::stroke() const
|
||||
{
|
||||
auto& value = find(PropertyId::Stroke);
|
||||
auto& value = find(PropertyID::Stroke);
|
||||
return Parser::parsePaint(value, this, Color::Transparent);
|
||||
}
|
||||
|
||||
Color StyledElement::color() const
|
||||
{
|
||||
auto& value = find(PropertyId::Color);
|
||||
auto& value = find(PropertyID::Color);
|
||||
return Parser::parseColor(value, this, Color::Black);
|
||||
}
|
||||
|
||||
Color StyledElement::stop_color() const
|
||||
{
|
||||
auto& value = find(PropertyId::Stop_Color);
|
||||
auto& value = find(PropertyID::Stop_Color);
|
||||
return Parser::parseColor(value, this, Color::Black);
|
||||
}
|
||||
|
||||
Color StyledElement::solid_color() const
|
||||
{
|
||||
auto& value = find(PropertyId::Solid_Color);
|
||||
auto& value = find(PropertyID::Solid_Color);
|
||||
return Parser::parseColor(value, this, Color::Black);
|
||||
}
|
||||
|
||||
double StyledElement::opacity() const
|
||||
{
|
||||
auto& value = get(PropertyId::Opacity);
|
||||
auto& value = get(PropertyID::Opacity);
|
||||
return Parser::parseNumberPercentage(value, 1.0);
|
||||
}
|
||||
|
||||
double StyledElement::fill_opacity() const
|
||||
{
|
||||
auto& value = find(PropertyId::Fill_Opacity);
|
||||
auto& value = find(PropertyID::Fill_Opacity);
|
||||
return Parser::parseNumberPercentage(value, 1.0);
|
||||
}
|
||||
|
||||
double StyledElement::stroke_opacity() const
|
||||
{
|
||||
auto& value = find(PropertyId::Stroke_Opacity);
|
||||
auto& value = find(PropertyID::Stroke_Opacity);
|
||||
return Parser::parseNumberPercentage(value, 1.0);
|
||||
}
|
||||
|
||||
double StyledElement::stop_opacity() const
|
||||
{
|
||||
auto& value = find(PropertyId::Stop_Opacity);
|
||||
auto& value = find(PropertyID::Stop_Opacity);
|
||||
return Parser::parseNumberPercentage(value, 1.0);
|
||||
}
|
||||
|
||||
double StyledElement::solid_opacity() const
|
||||
{
|
||||
auto& value = find(PropertyId::Solid_Opacity);
|
||||
auto& value = find(PropertyID::Solid_Opacity);
|
||||
return Parser::parseNumberPercentage(value, 1.0);
|
||||
}
|
||||
|
||||
double StyledElement::stroke_miterlimit() const
|
||||
{
|
||||
auto& value = find(PropertyId::Stroke_Miterlimit);
|
||||
auto& value = find(PropertyID::Stroke_Miterlimit);
|
||||
return Parser::parseNumber(value, 4.0);
|
||||
}
|
||||
|
||||
Length StyledElement::stroke_width() const
|
||||
{
|
||||
auto& value = find(PropertyId::Stroke_Width);
|
||||
auto& value = find(PropertyID::Stroke_Width);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::One);
|
||||
}
|
||||
|
||||
Length StyledElement::stroke_dashoffset() const
|
||||
{
|
||||
auto& value = find(PropertyId::Stroke_Dashoffset);
|
||||
auto& value = find(PropertyID::Stroke_Dashoffset);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
LengthList StyledElement::stroke_dasharray() const
|
||||
{
|
||||
auto& value = find(PropertyId::Stroke_Dasharray);
|
||||
auto& value = find(PropertyID::Stroke_Dasharray);
|
||||
return Parser::parseLengthList(value, ForbidNegativeLengths);
|
||||
}
|
||||
|
||||
WindRule StyledElement::fill_rule() const
|
||||
{
|
||||
auto& value = find(PropertyId::Fill_Rule);
|
||||
auto& value = find(PropertyID::Fill_Rule);
|
||||
return Parser::parseWindRule(value);
|
||||
}
|
||||
|
||||
WindRule StyledElement::clip_rule() const
|
||||
{
|
||||
auto& value = find(PropertyId::Clip_Rule);
|
||||
auto& value = find(PropertyID::Clip_Rule);
|
||||
return Parser::parseWindRule(value);
|
||||
}
|
||||
|
||||
LineCap StyledElement::stroke_linecap() const
|
||||
{
|
||||
auto& value = find(PropertyId::Stroke_Linecap);
|
||||
auto& value = find(PropertyID::Stroke_Linecap);
|
||||
return Parser::parseLineCap(value);
|
||||
}
|
||||
|
||||
LineJoin StyledElement::stroke_linejoin() const
|
||||
{
|
||||
auto& value = find(PropertyId::Stroke_Linejoin);
|
||||
auto& value = find(PropertyID::Stroke_Linejoin);
|
||||
return Parser::parseLineJoin(value);
|
||||
}
|
||||
|
||||
Display StyledElement::display() const
|
||||
{
|
||||
auto& value = get(PropertyId::Display);
|
||||
auto& value = get(PropertyID::Display);
|
||||
return Parser::parseDisplay(value);
|
||||
}
|
||||
|
||||
Visibility StyledElement::visibility() const
|
||||
{
|
||||
auto& value = find(PropertyId::Visibility);
|
||||
auto& value = find(PropertyID::Visibility);
|
||||
return Parser::parseVisibility(value);
|
||||
}
|
||||
|
||||
Overflow StyledElement::overflow() const
|
||||
{
|
||||
auto& value = get(PropertyId::Overflow);
|
||||
auto& value = get(PropertyID::Overflow);
|
||||
return Parser::parseOverflow(value, parent == nullptr ? Overflow::Visible : Overflow::Hidden);
|
||||
}
|
||||
|
||||
std::string StyledElement::clip_path() const
|
||||
{
|
||||
auto& value = get(PropertyId::Clip_Path);
|
||||
auto& value = get(PropertyID::Clip_Path);
|
||||
return Parser::parseUrl(value);
|
||||
}
|
||||
|
||||
std::string StyledElement::mask() const
|
||||
{
|
||||
auto& value = get(PropertyId::Mask);
|
||||
auto& value = get(PropertyID::Mask);
|
||||
return Parser::parseUrl(value);
|
||||
}
|
||||
|
||||
std::string StyledElement::marker_start() const
|
||||
{
|
||||
auto& value = find(PropertyId::Marker_Start);
|
||||
auto& value = find(PropertyID::Marker_Start);
|
||||
return Parser::parseUrl(value);
|
||||
}
|
||||
|
||||
std::string StyledElement::marker_mid() const
|
||||
{
|
||||
auto& value = find(PropertyId::Marker_Mid);
|
||||
auto& value = find(PropertyID::Marker_Mid);
|
||||
return Parser::parseUrl(value);
|
||||
}
|
||||
|
||||
std::string StyledElement::marker_end() const
|
||||
{
|
||||
auto& value = find(PropertyId::Marker_End);
|
||||
auto& value = find(PropertyID::Marker_End);
|
||||
return Parser::parseUrl(value);
|
||||
}
|
||||
|
||||
|
|
2
external/lunasvg/source/styledelement.h
vendored
2
external/lunasvg/source/styledelement.h
vendored
|
@ -8,7 +8,7 @@ namespace lunasvg {
|
|||
class StyledElement : public Element
|
||||
{
|
||||
public:
|
||||
StyledElement(ElementId id);
|
||||
StyledElement(ElementID id);
|
||||
|
||||
Paint fill() const;
|
||||
Paint stroke() const;
|
||||
|
|
2
external/lunasvg/source/styleelement.cpp
vendored
2
external/lunasvg/source/styleelement.cpp
vendored
|
@ -3,7 +3,7 @@
|
|||
namespace lunasvg {
|
||||
|
||||
StyleElement::StyleElement()
|
||||
: Element(ElementId::Style)
|
||||
: Element(ElementID::Style)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
18
external/lunasvg/source/svgelement.cpp
vendored
18
external/lunasvg/source/svgelement.cpp
vendored
|
@ -5,47 +5,47 @@
|
|||
namespace lunasvg {
|
||||
|
||||
SVGElement::SVGElement()
|
||||
: GraphicsElement(ElementId::Svg)
|
||||
: GraphicsElement(ElementID::Svg)
|
||||
{
|
||||
}
|
||||
|
||||
Length SVGElement::x() const
|
||||
{
|
||||
auto& value = get(PropertyId::X);
|
||||
auto& value = get(PropertyID::X);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length SVGElement::y() const
|
||||
{
|
||||
auto& value = get(PropertyId::Y);
|
||||
auto& value = get(PropertyID::Y);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length SVGElement::width() const
|
||||
{
|
||||
auto& value = get(PropertyId::Width);
|
||||
auto& value = get(PropertyID::Width);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||
}
|
||||
|
||||
Length SVGElement::height() const
|
||||
{
|
||||
auto& value = get(PropertyId::Height);
|
||||
auto& value = get(PropertyID::Height);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||
}
|
||||
|
||||
Rect SVGElement::viewBox() const
|
||||
{
|
||||
auto& value = get(PropertyId::ViewBox);
|
||||
auto& value = get(PropertyID::ViewBox);
|
||||
return Parser::parseViewBox(value);
|
||||
}
|
||||
|
||||
PreserveAspectRatio SVGElement::preserveAspectRatio() const
|
||||
{
|
||||
auto& value = get(PropertyId::PreserveAspectRatio);
|
||||
auto& value = get(PropertyID::PreserveAspectRatio);
|
||||
return Parser::parsePreserveAspectRatio(value);
|
||||
}
|
||||
|
||||
std::unique_ptr<LayoutSymbol> SVGElement::layoutDocument(const ParseDocument* document) const
|
||||
std::unique_ptr<LayoutSymbol> SVGElement::build(const TreeBuilder* builder) const
|
||||
{
|
||||
if(isDisplayNone())
|
||||
return nullptr;
|
||||
|
@ -73,7 +73,7 @@ std::unique_ptr<LayoutSymbol> SVGElement::layoutDocument(const ParseDocument* do
|
|||
root->clip = isOverflowHidden() ? preserveAspectRatio.getClip(_w, _h, viewBox) : Rect::Invalid;
|
||||
root->opacity = opacity();
|
||||
|
||||
LayoutContext context(document, root.get());
|
||||
LayoutContext context(builder, root.get());
|
||||
root->masker = context.getMasker(mask());
|
||||
root->clipper = context.getClipper(clip_path());
|
||||
layoutChildren(&context, root.get());
|
||||
|
|
4
external/lunasvg/source/svgelement.h
vendored
4
external/lunasvg/source/svgelement.h
vendored
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace lunasvg {
|
||||
|
||||
class ParseDocument;
|
||||
class TreeBuilder;
|
||||
class LayoutSymbol;
|
||||
|
||||
class SVGElement : public GraphicsElement
|
||||
|
@ -20,7 +20,7 @@ public:
|
|||
|
||||
Rect viewBox() const;
|
||||
PreserveAspectRatio preserveAspectRatio() const;
|
||||
std::unique_ptr<LayoutSymbol> layoutDocument(const ParseDocument* document) const;
|
||||
std::unique_ptr<LayoutSymbol> build(const TreeBuilder* builder) const;
|
||||
|
||||
void layout(LayoutContext* context, LayoutContainer* current) const;
|
||||
std::unique_ptr<Node> clone() const;
|
||||
|
|
14
external/lunasvg/source/symbolelement.cpp
vendored
14
external/lunasvg/source/symbolelement.cpp
vendored
|
@ -4,43 +4,43 @@
|
|||
namespace lunasvg {
|
||||
|
||||
SymbolElement::SymbolElement()
|
||||
: StyledElement(ElementId::Symbol)
|
||||
: StyledElement(ElementID::Symbol)
|
||||
{
|
||||
}
|
||||
|
||||
Length SymbolElement::x() const
|
||||
{
|
||||
auto& value = get(PropertyId::X);
|
||||
auto& value = get(PropertyID::X);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length SymbolElement::y() const
|
||||
{
|
||||
auto& value = get(PropertyId::Y);
|
||||
auto& value = get(PropertyID::Y);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length SymbolElement::width() const
|
||||
{
|
||||
auto& value = get(PropertyId::Width);
|
||||
auto& value = get(PropertyID::Width);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||
}
|
||||
|
||||
Length SymbolElement::height() const
|
||||
{
|
||||
auto& value = get(PropertyId::Height);
|
||||
auto& value = get(PropertyID::Height);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||
}
|
||||
|
||||
Rect SymbolElement::viewBox() const
|
||||
{
|
||||
auto& value = get(PropertyId::ViewBox);
|
||||
auto& value = get(PropertyID::ViewBox);
|
||||
return Parser::parseViewBox(value);
|
||||
}
|
||||
|
||||
PreserveAspectRatio SymbolElement::preserveAspectRatio() const
|
||||
{
|
||||
auto& value = get(PropertyId::PreserveAspectRatio);
|
||||
auto& value = get(PropertyID::PreserveAspectRatio);
|
||||
return Parser::parsePreserveAspectRatio(value);
|
||||
}
|
||||
|
||||
|
|
26
external/lunasvg/source/useelement.cpp
vendored
26
external/lunasvg/source/useelement.cpp
vendored
|
@ -8,47 +8,47 @@
|
|||
namespace lunasvg {
|
||||
|
||||
UseElement::UseElement()
|
||||
: GraphicsElement(ElementId::Use)
|
||||
: GraphicsElement(ElementID::Use)
|
||||
{
|
||||
}
|
||||
|
||||
Length UseElement::x() const
|
||||
{
|
||||
auto& value = get(PropertyId::X);
|
||||
auto& value = get(PropertyID::X);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length UseElement::y() const
|
||||
{
|
||||
auto& value = get(PropertyId::Y);
|
||||
auto& value = get(PropertyID::Y);
|
||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||
}
|
||||
|
||||
Length UseElement::width() const
|
||||
{
|
||||
auto& value = get(PropertyId::Width);
|
||||
auto& value = get(PropertyID::Width);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||
}
|
||||
|
||||
Length UseElement::height() const
|
||||
{
|
||||
auto& value = get(PropertyId::Height);
|
||||
auto& value = get(PropertyID::Height);
|
||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||
}
|
||||
|
||||
std::string UseElement::href() const
|
||||
{
|
||||
auto& value = get(PropertyId::Href);
|
||||
auto& value = get(PropertyID::Href);
|
||||
return Parser::parseHref(value);
|
||||
}
|
||||
|
||||
void UseElement::transferWidthAndHeight(Element* element) const
|
||||
{
|
||||
auto& width = get(PropertyId::Width);
|
||||
auto& height = get(PropertyId::Height);
|
||||
auto& width = get(PropertyID::Width);
|
||||
auto& height = get(PropertyID::Height);
|
||||
|
||||
element->set(PropertyId::Width, width, 0x0);
|
||||
element->set(PropertyId::Height, height, 0x0);
|
||||
element->set(PropertyID::Width, width, 0x0);
|
||||
element->set(PropertyID::Height, height, 0x0);
|
||||
}
|
||||
|
||||
void UseElement::layout(LayoutContext* context, LayoutContainer* current) const
|
||||
|
@ -69,15 +69,15 @@ void UseElement::layout(LayoutContext* context, LayoutContainer* current) const
|
|||
auto _x = lengthContext.valueForLength(x(), LengthMode::Width);
|
||||
auto _y = lengthContext.valueForLength(y(), LengthMode::Height);
|
||||
|
||||
auto transform = get(PropertyId::Transform);
|
||||
auto transform = get(PropertyID::Transform);
|
||||
transform += "translate(";
|
||||
transform += std::to_string(_x);
|
||||
transform += ' ';
|
||||
transform += std::to_string(_y);
|
||||
transform += ')';
|
||||
group->set(PropertyId::Transform, transform, 0x10);
|
||||
group->set(PropertyID::Transform, transform, 0x10);
|
||||
|
||||
if(ref->id == ElementId::Svg || ref->id == ElementId::Symbol)
|
||||
if(ref->id == ElementID::Svg || ref->id == ElementID::Symbol)
|
||||
{
|
||||
auto element = ref->cloneElement<SVGElement>();
|
||||
transferWidthAndHeight(element.get());
|
||||
|
|
Loading…
Reference in a new issue