mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45: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));
|
SW_FT_Outline* ft = malloc(sizeof(SW_FT_Outline));
|
||||||
ft->points = malloc((size_t)(points + contours) * sizeof(SW_FT_Vector));
|
ft->points = malloc((size_t)(points + contours) * sizeof(SW_FT_Vector));
|
||||||
ft->tags = malloc((size_t)(points + contours) * sizeof(char));
|
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->contours_flag = malloc((size_t)contours * sizeof(char));
|
||||||
ft->n_points = ft->n_contours = 0;
|
ft->n_points = ft->n_contours = 0;
|
||||||
ft->flags = 0x0;
|
ft->flags = 0x0;
|
||||||
|
|
|
@ -114,12 +114,12 @@
|
||||||
/* */
|
/* */
|
||||||
typedef struct SW_FT_Outline_
|
typedef struct SW_FT_Outline_
|
||||||
{
|
{
|
||||||
short n_contours; /* number of contours in glyph */
|
int n_contours; /* number of contours in glyph */
|
||||||
short n_points; /* number of points in the glyph */
|
int n_points; /* number of points in the glyph */
|
||||||
|
|
||||||
SW_FT_Vector* points; /* the outline's points */
|
SW_FT_Vector* points; /* the outline's points */
|
||||||
char* tags; /* the points flags */
|
char* tags; /* the points flags */
|
||||||
short* contours; /* the contour end points */
|
int* contours; /* the contour end points */
|
||||||
char* contours_flag; /* the contour open flags */
|
char* contours_flag; /* the contour open flags */
|
||||||
|
|
||||||
int flags; /* outline masks */
|
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_UInt count = border->num_points;
|
||||||
SW_FT_Byte* tags = border->tags;
|
SW_FT_Byte* tags = border->tags;
|
||||||
SW_FT_Short* write = outline->contours + outline->n_contours;
|
SW_FT_Int* write = outline->contours + outline->n_contours;
|
||||||
SW_FT_Short idx = (SW_FT_Short)outline->n_points;
|
SW_FT_Int idx = (SW_FT_Int)outline->n_points;
|
||||||
|
|
||||||
for (; count > 0; count--, tags++, idx++) {
|
for (; count > 0; count--, tags++, idx++) {
|
||||||
if (*tags & SW_FT_STROKE_TAG_END) {
|
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);
|
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)
|
project(lunasvg VERSION 2.3.2 LANGUAGES CXX C)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
|
||||||
option(BUILD_SHARED_LIBS "Builds as shared library" OFF)
|
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 {
|
namespace lunasvg {
|
||||||
|
|
||||||
class Rect;
|
class Rect;
|
||||||
|
class Matrix;
|
||||||
|
|
||||||
class LUNASVG_API Box
|
class LUNASVG_API Box
|
||||||
{
|
{
|
||||||
|
@ -47,6 +48,9 @@ public:
|
||||||
Box(double x, double y, double w, double h);
|
Box(double x, double y, double w, double h);
|
||||||
Box(const Rect& rect);
|
Box(const Rect& rect);
|
||||||
|
|
||||||
|
Box& transform(const Matrix& matrix);
|
||||||
|
Box transformed(const Matrix& matrix) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
double x{0};
|
double x{0};
|
||||||
double y{0};
|
double y{0};
|
||||||
|
@ -78,7 +82,6 @@ public:
|
||||||
|
|
||||||
Matrix inverted() const;
|
Matrix inverted() const;
|
||||||
Matrix operator*(const Matrix& matrix) const;
|
Matrix operator*(const Matrix& matrix) const;
|
||||||
Box map(const Box& box) const;
|
|
||||||
|
|
||||||
static Matrix rotated(double angle);
|
static Matrix rotated(double angle);
|
||||||
static Matrix rotated(double angle, double cx, double cy);
|
static Matrix rotated(double angle, double cx, double cy);
|
||||||
|
@ -159,63 +162,9 @@ public:
|
||||||
static std::unique_ptr<Document> loadFromData(const char* data);
|
static std::unique_ptr<Document> loadFromData(const char* data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pre-Rotates the document matrix clockwise around the current origin
|
* @brief Sets the current transformation matrix of the document
|
||||||
* @param angle - rotation angle, in degrees
|
* @param matrix - current transformation matrix
|
||||||
* @return this
|
|
||||||
*/
|
*/
|
||||||
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);
|
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}/svgelement.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/symbolelement.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/symbolelement.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/useelement.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/useelement.cpp"
|
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/cssparser.cpp"
|
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/cssstylesheet.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(lunasvg
|
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_operator_t to_plutovg_operator(BlendMode mode);
|
||||||
static plutovg_line_cap_t to_plutovg_line_cap(LineCap cap);
|
static plutovg_line_cap_t to_plutovg_line_cap(LineCap cap);
|
||||||
static plutovg_line_join_t to_plutovg_line_join(LineJoin join);
|
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_stops(plutovg_gradient_t* gradient, const GradientStops& stops);
|
||||||
static void to_plutovg_path(plutovg_t* pluto, const Path& path);
|
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 gradient = plutovg_gradient_create_linear(x1, y1, x2, y2);
|
||||||
auto matrix = to_plutovg_matrix(transform);
|
auto matrix = to_plutovg_matrix(transform);
|
||||||
to_plutovg_stops(gradient, stops);
|
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_gradient_set_matrix(gradient, &matrix);
|
||||||
plutovg_set_source_gradient(pluto, gradient);
|
plutovg_set_source_gradient(pluto, gradient);
|
||||||
plutovg_gradient_destroy(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 gradient = plutovg_gradient_create_radial(cx, cy, r, fx, fy, 0);
|
||||||
auto matrix = to_plutovg_matrix(transform);
|
auto matrix = to_plutovg_matrix(transform);
|
||||||
to_plutovg_stops(gradient, stops);
|
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_gradient_set_matrix(gradient, &matrix);
|
||||||
plutovg_set_source_gradient(pluto, gradient);
|
plutovg_set_source_gradient(pluto, gradient);
|
||||||
plutovg_gradient_destroy(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;
|
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;
|
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 {
|
namespace lunasvg {
|
||||||
|
|
||||||
ClipPathElement::ClipPathElement()
|
ClipPathElement::ClipPathElement()
|
||||||
: GraphicsElement(ElementId::ClipPath)
|
: GraphicsElement(ElementID::ClipPath)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Units ClipPathElement::clipPathUnits() const
|
Units ClipPathElement::clipPathUnits() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::ClipPathUnits);
|
auto& value = get(PropertyID::ClipPathUnits);
|
||||||
return Parser::parseUnits(value, Units::UserSpaceOnUse);
|
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 {
|
namespace lunasvg {
|
||||||
|
|
||||||
DefsElement::DefsElement()
|
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 "parser.h"
|
||||||
#include "svgelement.h"
|
#include "svgelement.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace lunasvg {
|
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);
|
auto property = get(id);
|
||||||
if(property == nullptr)
|
if(property == nullptr)
|
||||||
|
@ -21,7 +158,7 @@ void PropertyList::set(PropertyId id, const std::string& value, int specificity)
|
||||||
property->value = value;
|
property->value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Property* PropertyList::get(PropertyId id) const
|
Property* PropertyList::get(PropertyID id) const
|
||||||
{
|
{
|
||||||
auto data = m_properties.data();
|
auto data = m_properties.data();
|
||||||
auto end = data + m_properties.size();
|
auto end = data + m_properties.size();
|
||||||
|
@ -59,19 +196,19 @@ std::unique_ptr<Node> TextNode::clone() const
|
||||||
return std::move(node);
|
return std::move(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
Element::Element(ElementId id)
|
Element::Element(ElementID id)
|
||||||
: id(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);
|
properties.set(id, value, specificity);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::string EmptyString;
|
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);
|
auto property = properties.get(id);
|
||||||
if(property == nullptr)
|
if(property == nullptr)
|
||||||
|
@ -82,7 +219,7 @@ const std::string& Element::get(PropertyId id) const
|
||||||
|
|
||||||
static const std::string InheritString{"inherit"};
|
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;
|
auto element = this;
|
||||||
do {
|
do {
|
||||||
|
@ -95,12 +232,12 @@ const std::string& Element::find(PropertyId id) const
|
||||||
return EmptyString;
|
return EmptyString;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Element::has(PropertyId id) const
|
bool Element::has(PropertyID id) const
|
||||||
{
|
{
|
||||||
return properties.get(id);
|
return properties.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Element* Element::previousSibling() const
|
Element* Element::previousElement() const
|
||||||
{
|
{
|
||||||
if(parent == nullptr)
|
if(parent == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -122,7 +259,7 @@ Element* Element::previousSibling() const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Element* Element::nextSibling() const
|
Element* Element::nextElement() const
|
||||||
{
|
{
|
||||||
if(parent == nullptr)
|
if(parent == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -162,15 +299,15 @@ Rect Element::currentViewport() const
|
||||||
if(parent == nullptr)
|
if(parent == nullptr)
|
||||||
{
|
{
|
||||||
auto element = static_cast<const SVGElement*>(this);
|
auto element = static_cast<const SVGElement*>(this);
|
||||||
if(element->has(PropertyId::ViewBox))
|
if(element->has(PropertyID::ViewBox))
|
||||||
return element->viewBox();
|
return element->viewBox();
|
||||||
return Rect{0, 0, 300, 150};
|
return Rect{0, 0, 300, 150};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parent->id == ElementId::Svg)
|
if(parent->id == ElementID::Svg)
|
||||||
{
|
{
|
||||||
auto element = static_cast<SVGElement*>(parent);
|
auto element = static_cast<SVGElement*>(parent);
|
||||||
if(element->has(PropertyId::ViewBox))
|
if(element->has(PropertyID::ViewBox))
|
||||||
return element->viewBox();
|
return element->viewBox();
|
||||||
|
|
||||||
LengthContext lengthContext(element);
|
LengthContext lengthContext(element);
|
||||||
|
|
54
external/lunasvg/source/element.h
vendored
54
external/lunasvg/source/element.h
vendored
|
@ -8,15 +8,16 @@
|
||||||
|
|
||||||
namespace lunasvg {
|
namespace lunasvg {
|
||||||
|
|
||||||
enum class ElementId
|
enum class ElementID {
|
||||||
{
|
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
Star,
|
Star,
|
||||||
|
A,
|
||||||
Circle,
|
Circle,
|
||||||
ClipPath,
|
ClipPath,
|
||||||
Defs,
|
Defs,
|
||||||
Ellipse,
|
Ellipse,
|
||||||
G,
|
G,
|
||||||
|
Image,
|
||||||
Line,
|
Line,
|
||||||
LinearGradient,
|
LinearGradient,
|
||||||
Marker,
|
Marker,
|
||||||
|
@ -31,12 +32,16 @@ enum class ElementId
|
||||||
Stop,
|
Stop,
|
||||||
Style,
|
Style,
|
||||||
Svg,
|
Svg,
|
||||||
|
Switch,
|
||||||
Symbol,
|
Symbol,
|
||||||
|
Text,
|
||||||
|
TextPath,
|
||||||
|
Tref,
|
||||||
|
Tspan,
|
||||||
Use
|
Use
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PropertyId
|
enum class PropertyID {
|
||||||
{
|
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
Class,
|
Class,
|
||||||
Clip_Path,
|
Clip_Path,
|
||||||
|
@ -46,10 +51,17 @@ enum class PropertyId
|
||||||
Cx,
|
Cx,
|
||||||
Cy,
|
Cy,
|
||||||
D,
|
D,
|
||||||
|
Dx,
|
||||||
|
Dy,
|
||||||
Display,
|
Display,
|
||||||
Fill,
|
Fill,
|
||||||
Fill_Opacity,
|
Fill_Opacity,
|
||||||
Fill_Rule,
|
Fill_Rule,
|
||||||
|
Font_Family,
|
||||||
|
Font_Size,
|
||||||
|
Font_Style,
|
||||||
|
Font_Variant,
|
||||||
|
Font_Weight,
|
||||||
Fx,
|
Fx,
|
||||||
Fy,
|
Fy,
|
||||||
GradientTransform,
|
GradientTransform,
|
||||||
|
@ -57,6 +69,7 @@ enum class PropertyId
|
||||||
Height,
|
Height,
|
||||||
Href,
|
Href,
|
||||||
Id,
|
Id,
|
||||||
|
Letter_Spacing,
|
||||||
Marker_End,
|
Marker_End,
|
||||||
Marker_Mid,
|
Marker_Mid,
|
||||||
Marker_Start,
|
Marker_Start,
|
||||||
|
@ -78,11 +91,13 @@ enum class PropertyId
|
||||||
R,
|
R,
|
||||||
RefX,
|
RefX,
|
||||||
RefY,
|
RefY,
|
||||||
|
Rotate,
|
||||||
Rx,
|
Rx,
|
||||||
Ry,
|
Ry,
|
||||||
Solid_Color,
|
Solid_Color,
|
||||||
Solid_Opacity,
|
Solid_Opacity,
|
||||||
SpreadMethod,
|
SpreadMethod,
|
||||||
|
StartOffset,
|
||||||
Stop_Color,
|
Stop_Color,
|
||||||
Stop_Opacity,
|
Stop_Opacity,
|
||||||
Stroke,
|
Stroke,
|
||||||
|
@ -94,10 +109,13 @@ enum class PropertyId
|
||||||
Stroke_Opacity,
|
Stroke_Opacity,
|
||||||
Stroke_Width,
|
Stroke_Width,
|
||||||
Style,
|
Style,
|
||||||
|
Text_Anchor,
|
||||||
|
Text_Decoration,
|
||||||
Transform,
|
Transform,
|
||||||
ViewBox,
|
ViewBox,
|
||||||
Visibility,
|
Visibility,
|
||||||
Width,
|
Width,
|
||||||
|
Word_Spacing,
|
||||||
X,
|
X,
|
||||||
X1,
|
X1,
|
||||||
X2,
|
X2,
|
||||||
|
@ -106,9 +124,12 @@ enum class PropertyId
|
||||||
Y2
|
Y2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ElementID elementid(const std::string_view& name);
|
||||||
|
PropertyID propertyid(const std::string_view& name);
|
||||||
|
|
||||||
struct Property
|
struct Property
|
||||||
{
|
{
|
||||||
PropertyId id;
|
PropertyID id;
|
||||||
std::string value;
|
std::string value;
|
||||||
int specificity;
|
int specificity;
|
||||||
};
|
};
|
||||||
|
@ -118,10 +139,11 @@ class PropertyList
|
||||||
public:
|
public:
|
||||||
PropertyList() = default;
|
PropertyList() = default;
|
||||||
|
|
||||||
void set(PropertyId id, const std::string& value, int specificity);
|
void set(PropertyID id, const std::string& value, int specificity);
|
||||||
Property* get(PropertyId id) const;
|
Property* get(PropertyID id) const;
|
||||||
void add(const Property& property);
|
void add(const Property& property);
|
||||||
void add(const PropertyList& properties);
|
void add(const PropertyList& properties);
|
||||||
|
void clear() { m_properties.clear(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Property> m_properties;
|
std::vector<Property> m_properties;
|
||||||
|
@ -159,20 +181,22 @@ public:
|
||||||
std::string text;
|
std::string text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using Attribute = std::pair<PropertyID, std::string>;
|
||||||
|
using AttributeList = std::vector<Attribute>;
|
||||||
using NodeList = std::list<std::unique_ptr<Node>>;
|
using NodeList = std::list<std::unique_ptr<Node>>;
|
||||||
|
|
||||||
class Element : public Node
|
class Element : public Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Element(ElementId id);
|
Element(ElementID id);
|
||||||
|
|
||||||
void set(PropertyId id, const std::string& value, int specificity);
|
void set(PropertyID id, const std::string& value, int specificity);
|
||||||
const std::string& get(PropertyId id) const;
|
const std::string& get(PropertyID id) const;
|
||||||
const std::string& find(PropertyId id) const;
|
const std::string& find(PropertyID id) const;
|
||||||
bool has(PropertyId id) const;
|
bool has(PropertyID id) const;
|
||||||
|
|
||||||
Element* previousSibling() const;
|
Element* previousElement() const;
|
||||||
Element* nextSibling() const;
|
Element* nextElement() const;
|
||||||
Node* addChild(std::unique_ptr<Node> child);
|
Node* addChild(std::unique_ptr<Node> child);
|
||||||
void layoutChildren(LayoutContext* context, LayoutContainer* current) const;
|
void layoutChildren(LayoutContext* context, LayoutContainer* current) const;
|
||||||
Rect currentViewport() const;
|
Rect currentViewport() const;
|
||||||
|
@ -208,7 +232,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ElementId id;
|
ElementID id;
|
||||||
NodeList children;
|
NodeList children;
|
||||||
PropertyList properties;
|
PropertyList properties;
|
||||||
};
|
};
|
||||||
|
|
2
external/lunasvg/source/gelement.cpp
vendored
2
external/lunasvg/source/gelement.cpp
vendored
|
@ -4,7 +4,7 @@
|
||||||
namespace lunasvg {
|
namespace lunasvg {
|
||||||
|
|
||||||
GElement::GElement()
|
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 {
|
namespace lunasvg {
|
||||||
|
|
||||||
GeometryElement::GeometryElement(ElementId id)
|
GeometryElement::GeometryElement(ElementID id)
|
||||||
: GraphicsElement(id)
|
: GraphicsElement(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -35,13 +35,13 @@ void GeometryElement::layout(LayoutContext* context, LayoutContainer* current) c
|
||||||
}
|
}
|
||||||
|
|
||||||
PathElement::PathElement()
|
PathElement::PathElement()
|
||||||
: GeometryElement(ElementId::Path)
|
: GeometryElement(ElementID::Path)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Path PathElement::d() const
|
Path PathElement::d() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::D);
|
auto& value = get(PropertyID::D);
|
||||||
return Parser::parsePath(value);
|
return Parser::parsePath(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,19 +55,19 @@ std::unique_ptr<Node> PathElement::clone() const
|
||||||
return cloneElement<PathElement>();
|
return cloneElement<PathElement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
PolyElement::PolyElement(ElementId id)
|
PolyElement::PolyElement(ElementID id)
|
||||||
: GeometryElement(id)
|
: GeometryElement(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PointList PolyElement::points() const
|
PointList PolyElement::points() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Points);
|
auto& value = get(PropertyID::Points);
|
||||||
return Parser::parsePointList(value);
|
return Parser::parsePointList(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
PolygonElement::PolygonElement()
|
PolygonElement::PolygonElement()
|
||||||
: PolyElement(ElementId::Polygon)
|
: PolyElement(ElementID::Polygon)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ std::unique_ptr<Node> PolygonElement::clone() const
|
||||||
}
|
}
|
||||||
|
|
||||||
PolylineElement::PolylineElement()
|
PolylineElement::PolylineElement()
|
||||||
: PolyElement(ElementId::Polyline)
|
: PolyElement(ElementID::Polyline)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,25 +116,25 @@ std::unique_ptr<Node> PolylineElement::clone() const
|
||||||
}
|
}
|
||||||
|
|
||||||
CircleElement::CircleElement()
|
CircleElement::CircleElement()
|
||||||
: GeometryElement(ElementId::Circle)
|
: GeometryElement(ElementID::Circle)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length CircleElement::cx() const
|
Length CircleElement::cx() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Cx);
|
auto& value = get(PropertyID::Cx);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length CircleElement::cy() const
|
Length CircleElement::cy() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Cy);
|
auto& value = get(PropertyID::Cy);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length CircleElement::r() const
|
Length CircleElement::r() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::R);
|
auto& value = get(PropertyID::R);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,31 +160,31 @@ std::unique_ptr<Node> CircleElement::clone() const
|
||||||
}
|
}
|
||||||
|
|
||||||
EllipseElement::EllipseElement()
|
EllipseElement::EllipseElement()
|
||||||
: GeometryElement(ElementId::Ellipse)
|
: GeometryElement(ElementID::Ellipse)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length EllipseElement::cx() const
|
Length EllipseElement::cx() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Cx);
|
auto& value = get(PropertyID::Cx);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length EllipseElement::cy() const
|
Length EllipseElement::cy() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Cy);
|
auto& value = get(PropertyID::Cy);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length EllipseElement::rx() const
|
Length EllipseElement::rx() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Rx);
|
auto& value = get(PropertyID::Rx);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length EllipseElement::ry() const
|
Length EllipseElement::ry() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Ry);
|
auto& value = get(PropertyID::Ry);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,31 +212,31 @@ std::unique_ptr<Node> EllipseElement::clone() const
|
||||||
}
|
}
|
||||||
|
|
||||||
LineElement::LineElement()
|
LineElement::LineElement()
|
||||||
: GeometryElement(ElementId::Line)
|
: GeometryElement(ElementID::Line)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length LineElement::x1() const
|
Length LineElement::x1() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::X1);
|
auto& value = get(PropertyID::X1);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length LineElement::y1() const
|
Length LineElement::y1() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Y1);
|
auto& value = get(PropertyID::Y1);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length LineElement::x2() const
|
Length LineElement::x2() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::X2);
|
auto& value = get(PropertyID::X2);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length LineElement::y2() const
|
Length LineElement::y2() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Y2);
|
auto& value = get(PropertyID::Y2);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,43 +260,43 @@ std::unique_ptr<Node> LineElement::clone() const
|
||||||
}
|
}
|
||||||
|
|
||||||
RectElement::RectElement()
|
RectElement::RectElement()
|
||||||
: GeometryElement(ElementId::Rect)
|
: GeometryElement(ElementID::Rect)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RectElement::x() const
|
Length RectElement::x() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::X);
|
auto& value = get(PropertyID::X);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RectElement::y() const
|
Length RectElement::y() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Y);
|
auto& value = get(PropertyID::Y);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RectElement::rx() const
|
Length RectElement::rx() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Rx);
|
auto& value = get(PropertyID::Rx);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RectElement::ry() const
|
Length RectElement::ry() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Ry);
|
auto& value = get(PropertyID::Ry);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RectElement::width() const
|
Length RectElement::width() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Width);
|
auto& value = get(PropertyID::Width);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RectElement::height() const
|
Length RectElement::height() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Height);
|
auto& value = get(PropertyID::Height);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
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
|
class GeometryElement : public GraphicsElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GeometryElement(ElementId id);
|
GeometryElement(ElementID id);
|
||||||
|
|
||||||
bool isGeometry() const { return true; }
|
bool isGeometry() const { return true; }
|
||||||
virtual void layout(LayoutContext* context, LayoutContainer* current) const;
|
virtual void layout(LayoutContext* context, LayoutContainer* current) const;
|
||||||
|
@ -31,7 +31,7 @@ public:
|
||||||
class PolyElement : public GeometryElement
|
class PolyElement : public GeometryElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PolyElement(ElementId id);
|
PolyElement(ElementID id);
|
||||||
|
|
||||||
PointList points() const;
|
PointList points() const;
|
||||||
};
|
};
|
||||||
|
|
4
external/lunasvg/source/graphicselement.cpp
vendored
4
external/lunasvg/source/graphicselement.cpp
vendored
|
@ -3,14 +3,14 @@
|
||||||
|
|
||||||
namespace lunasvg {
|
namespace lunasvg {
|
||||||
|
|
||||||
GraphicsElement::GraphicsElement(ElementId id)
|
GraphicsElement::GraphicsElement(ElementID id)
|
||||||
: StyledElement(id)
|
: StyledElement(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform GraphicsElement::transform() const
|
Transform GraphicsElement::transform() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Transform);
|
auto& value = get(PropertyID::Transform);
|
||||||
return Parser::parseTransform(value);
|
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
|
class GraphicsElement : public StyledElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GraphicsElement(ElementId id);
|
GraphicsElement(ElementID id);
|
||||||
|
|
||||||
Transform transform() const;
|
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);
|
state.canvas->blend(canvas.get(), BlendMode::Src_Over, m_mode == RenderMode::Display ? info.opacity : 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutContext::LayoutContext(const ParseDocument* document, LayoutSymbol* root)
|
LayoutContext::LayoutContext(const TreeBuilder* builder, LayoutSymbol* root)
|
||||||
: m_document(document), m_root(root)
|
: m_builder(builder), m_root(root)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Element* LayoutContext::getElementById(const std::string& id) const
|
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
|
LayoutObject* LayoutContext::getResourcesById(const std::string& id) const
|
||||||
|
@ -517,7 +517,7 @@ LayoutMask* LayoutContext::getMasker(const std::string& id)
|
||||||
return static_cast<LayoutMask*>(ref);
|
return static_cast<LayoutMask*>(ref);
|
||||||
|
|
||||||
auto element = getElementById(id);
|
auto element = getElementById(id);
|
||||||
if(element == nullptr || element->id != ElementId::Mask)
|
if(element == nullptr || element->id != ElementID::Mask)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto masker = static_cast<MaskElement*>(element)->getMasker(this);
|
auto masker = static_cast<MaskElement*>(element)->getMasker(this);
|
||||||
|
@ -534,7 +534,7 @@ LayoutClipPath* LayoutContext::getClipper(const std::string& id)
|
||||||
return static_cast<LayoutClipPath*>(ref);
|
return static_cast<LayoutClipPath*>(ref);
|
||||||
|
|
||||||
auto element = getElementById(id);
|
auto element = getElementById(id);
|
||||||
if(element == nullptr || element->id != ElementId::ClipPath)
|
if(element == nullptr || element->id != ElementID::ClipPath)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto clipper = static_cast<ClipPathElement*>(element)->getClipper(this);
|
auto clipper = static_cast<ClipPathElement*>(element)->getClipper(this);
|
||||||
|
@ -551,7 +551,7 @@ LayoutMarker* LayoutContext::getMarker(const std::string& id)
|
||||||
return static_cast<LayoutMarker*>(ref);
|
return static_cast<LayoutMarker*>(ref);
|
||||||
|
|
||||||
auto element = getElementById(id);
|
auto element = getElementById(id);
|
||||||
if(element == nullptr || element->id != ElementId::Marker)
|
if(element == nullptr || element->id != ElementID::Marker)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto marker = static_cast<MarkerElement*>(element)->getMarker(this);
|
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;
|
RenderMode m_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParseDocument;
|
class TreeBuilder;
|
||||||
class StyledElement;
|
class StyledElement;
|
||||||
class GeometryElement;
|
class GeometryElement;
|
||||||
|
|
||||||
class LayoutContext
|
class LayoutContext {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
LayoutContext(const ParseDocument* document, LayoutSymbol* root);
|
LayoutContext(const TreeBuilder* builder, LayoutSymbol* root);
|
||||||
|
|
||||||
Element* getElementById(const std::string& id) const;
|
Element* getElementById(const std::string& id) const;
|
||||||
LayoutObject* getResourcesById(const std::string& id) const;
|
LayoutObject* getResourcesById(const std::string& id) const;
|
||||||
|
@ -373,7 +372,7 @@ public:
|
||||||
bool hasReference(const Element* element) const;
|
bool hasReference(const Element* element) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ParseDocument* m_document;
|
const TreeBuilder* m_builder;
|
||||||
LayoutSymbol* m_root;
|
LayoutSymbol* m_root;
|
||||||
std::map<std::string, LayoutObject*> m_resourcesCache;
|
std::map<std::string, LayoutObject*> m_resourcesCache;
|
||||||
std::set<const Element*> m_references;
|
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)
|
Box::Box(double x, double y, double w, double h)
|
||||||
: x(x), y(y), w(w), h(h)
|
: x(x), y(y), w(w), h(h)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Box::Box(const Rect& rect)
|
Box::Box(const Rect& rect)
|
||||||
: x(rect.x), y(rect.y), w(rect.w), h(rect.h)
|
: 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)
|
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)
|
: a(a), b(b), c(c), d(d), e(e), f(f)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Matrix::Matrix(const Transform& transform)
|
Matrix::Matrix(const Transform& transform)
|
||||||
: a(transform.m00), b(transform.m10), c(transform.m01), d(transform.m11), e(transform.m02), f(transform.m12)
|
: 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);
|
return Transform(*this) * Transform(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
Box Matrix::map(const Box& box) const
|
|
||||||
{
|
|
||||||
return Transform(*this).map(box);
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix Matrix::rotated(double angle)
|
Matrix Matrix::rotated(double angle)
|
||||||
{
|
{
|
||||||
return Transform::rotated(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)
|
std::unique_ptr<Document> Document::loadFromData(const char* data, std::size_t size)
|
||||||
{
|
{
|
||||||
ParseDocument parser;
|
TreeBuilder builder;
|
||||||
if(!parser.parse(data, size))
|
if(!builder.parse(data, size))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto root = parser.layout();
|
auto root = builder.build();
|
||||||
if(!root || root->children.empty())
|
if(!root || root->children.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -301,48 +310,6 @@ std::unique_ptr<Document> Document::loadFromData(const char* data)
|
||||||
return loadFromData(data, std::strlen(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)
|
void Document::setMatrix(const Matrix& matrix)
|
||||||
{
|
{
|
||||||
root->transform = Transform(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 {
|
namespace lunasvg {
|
||||||
|
|
||||||
MarkerElement::MarkerElement()
|
MarkerElement::MarkerElement()
|
||||||
: StyledElement(ElementId::Marker)
|
: StyledElement(ElementID::Marker)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length MarkerElement::refX() const
|
Length MarkerElement::refX() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::RefX);
|
auto& value = get(PropertyID::RefX);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length MarkerElement::refY() const
|
Length MarkerElement::refY() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::RefY);
|
auto& value = get(PropertyID::RefY);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length MarkerElement::markerWidth() const
|
Length MarkerElement::markerWidth() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::MarkerWidth);
|
auto& value = get(PropertyID::MarkerWidth);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::ThreePercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::ThreePercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length MarkerElement::markerHeight() const
|
Length MarkerElement::markerHeight() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::MarkerHeight);
|
auto& value = get(PropertyID::MarkerHeight);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::ThreePercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::ThreePercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Angle MarkerElement::orient() const
|
Angle MarkerElement::orient() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Orient);
|
auto& value = get(PropertyID::Orient);
|
||||||
return Parser::parseAngle(value);
|
return Parser::parseAngle(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkerUnits MarkerElement::markerUnits() const
|
MarkerUnits MarkerElement::markerUnits() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::MarkerUnits);
|
auto& value = get(PropertyID::MarkerUnits);
|
||||||
return Parser::parseMarkerUnits(value);
|
return Parser::parseMarkerUnits(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect MarkerElement::viewBox() const
|
Rect MarkerElement::viewBox() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::ViewBox);
|
auto& value = get(PropertyID::ViewBox);
|
||||||
return Parser::parseViewBox(value);
|
return Parser::parseViewBox(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
PreserveAspectRatio MarkerElement::preserveAspectRatio() const
|
PreserveAspectRatio MarkerElement::preserveAspectRatio() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::PreserveAspectRatio);
|
auto& value = get(PropertyID::PreserveAspectRatio);
|
||||||
return Parser::parsePreserveAspectRatio(value);
|
return Parser::parsePreserveAspectRatio(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
external/lunasvg/source/maskelement.cpp
vendored
14
external/lunasvg/source/maskelement.cpp
vendored
|
@ -5,43 +5,43 @@
|
||||||
namespace lunasvg {
|
namespace lunasvg {
|
||||||
|
|
||||||
MaskElement::MaskElement()
|
MaskElement::MaskElement()
|
||||||
: StyledElement(ElementId::Mask)
|
: StyledElement(ElementID::Mask)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length MaskElement::x() const
|
Length MaskElement::x() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::X);
|
auto& value = get(PropertyID::X);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::MinusTenPercent);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::MinusTenPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length MaskElement::y() const
|
Length MaskElement::y() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Y);
|
auto& value = get(PropertyID::Y);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::MinusTenPercent);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::MinusTenPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length MaskElement::width() const
|
Length MaskElement::width() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Width);
|
auto& value = get(PropertyID::Width);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::OneTwentyPercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::OneTwentyPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length MaskElement::height() const
|
Length MaskElement::height() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Height);
|
auto& value = get(PropertyID::Height);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::OneTwentyPercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::OneTwentyPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Units MaskElement::maskUnits() const
|
Units MaskElement::maskUnits() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::MaskUnits);
|
auto& value = get(PropertyID::MaskUnits);
|
||||||
return Parser::parseUnits(value, Units::ObjectBoundingBox);
|
return Parser::parseUnits(value, Units::ObjectBoundingBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
Units MaskElement::maskContentUnits() const
|
Units MaskElement::maskContentUnits() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::MaskContentUnits);
|
auto& value = get(PropertyID::MaskContentUnits);
|
||||||
return Parser::parseUnits(value, Units::UserSpaceOnUse);
|
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 {
|
namespace lunasvg {
|
||||||
|
|
||||||
PaintElement::PaintElement(ElementId id)
|
PaintElement::PaintElement(ElementID id)
|
||||||
: StyledElement(id)
|
: StyledElement(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GradientElement::GradientElement(ElementId id)
|
GradientElement::GradientElement(ElementID id)
|
||||||
: PaintElement(id)
|
: PaintElement(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform GradientElement::gradientTransform() const
|
Transform GradientElement::gradientTransform() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::GradientTransform);
|
auto& value = get(PropertyID::GradientTransform);
|
||||||
return Parser::parseTransform(value);
|
return Parser::parseTransform(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpreadMethod GradientElement::spreadMethod() const
|
SpreadMethod GradientElement::spreadMethod() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::SpreadMethod);
|
auto& value = get(PropertyID::SpreadMethod);
|
||||||
return Parser::parseSpreadMethod(value);
|
return Parser::parseSpreadMethod(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Units GradientElement::gradientUnits() const
|
Units GradientElement::gradientUnits() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::GradientUnits);
|
auto& value = get(PropertyID::GradientUnits);
|
||||||
return Parser::parseUnits(value, Units::ObjectBoundingBox);
|
return Parser::parseUnits(value, Units::ObjectBoundingBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GradientElement::href() const
|
std::string GradientElement::href() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Href);
|
auto& value = get(PropertyID::Href);
|
||||||
return Parser::parseHref(value);
|
return Parser::parseHref(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ GradientStops GradientElement::buildGradientStops() const
|
||||||
if(child->isText())
|
if(child->isText())
|
||||||
continue;
|
continue;
|
||||||
auto element = static_cast<Element*>(child.get());
|
auto element = static_cast<Element*>(child.get());
|
||||||
if(element->id != ElementId::Stop)
|
if(element->id != ElementID::Stop)
|
||||||
continue;
|
continue;
|
||||||
auto stop = static_cast<StopElement*>(element);
|
auto stop = static_cast<StopElement*>(element);
|
||||||
auto offset = std::max(prevOffset, stop->offset());
|
auto offset = std::max(prevOffset, stop->offset());
|
||||||
|
@ -62,31 +62,31 @@ GradientStops GradientElement::buildGradientStops() const
|
||||||
}
|
}
|
||||||
|
|
||||||
LinearGradientElement::LinearGradientElement()
|
LinearGradientElement::LinearGradientElement()
|
||||||
: GradientElement(ElementId::LinearGradient)
|
: GradientElement(ElementID::LinearGradient)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length LinearGradientElement::x1() const
|
Length LinearGradientElement::x1() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::X1);
|
auto& value = get(PropertyID::X1);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length LinearGradientElement::y1() const
|
Length LinearGradientElement::y1() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Y1);
|
auto& value = get(PropertyID::Y1);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length LinearGradientElement::x2() const
|
Length LinearGradientElement::x2() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::X2);
|
auto& value = get(PropertyID::X2);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::HundredPercent);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::HundredPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length LinearGradientElement::y2() const
|
Length LinearGradientElement::y2() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Y2);
|
auto& value = get(PropertyID::Y2);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,30 +98,30 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
if(!attributes.hasGradientTransform() && current->has(PropertyId::GradientTransform))
|
if(!attributes.hasGradientTransform() && current->has(PropertyID::GradientTransform))
|
||||||
attributes.setGradientTransform(current->gradientTransform());
|
attributes.setGradientTransform(current->gradientTransform());
|
||||||
if(!attributes.hasSpreadMethod() && current->has(PropertyId::SpreadMethod))
|
if(!attributes.hasSpreadMethod() && current->has(PropertyID::SpreadMethod))
|
||||||
attributes.setSpreadMethod(current->spreadMethod());
|
attributes.setSpreadMethod(current->spreadMethod());
|
||||||
if(!attributes.hasGradientUnits() && current->has(PropertyId::GradientUnits))
|
if(!attributes.hasGradientUnits() && current->has(PropertyID::GradientUnits))
|
||||||
attributes.setGradientUnits(current->gradientUnits());
|
attributes.setGradientUnits(current->gradientUnits());
|
||||||
if(!attributes.hasGradientStops())
|
if(!attributes.hasGradientStops())
|
||||||
attributes.setGradientStops(current->buildGradientStops());
|
attributes.setGradientStops(current->buildGradientStops());
|
||||||
|
|
||||||
if(current->id == ElementId::LinearGradient)
|
if(current->id == ElementID::LinearGradient)
|
||||||
{
|
{
|
||||||
auto element = static_cast<const LinearGradientElement*>(current);
|
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());
|
attributes.setX1(element->x1());
|
||||||
if(!attributes.hasY1() && element->has(PropertyId::Y1))
|
if(!attributes.hasY1() && element->has(PropertyID::Y1))
|
||||||
attributes.setY1(element->y1());
|
attributes.setY1(element->y1());
|
||||||
if(!attributes.hasX2() && element->has(PropertyId::X2))
|
if(!attributes.hasX2() && element->has(PropertyID::X2))
|
||||||
attributes.setX2(element->x2());
|
attributes.setX2(element->x2());
|
||||||
if(!attributes.hasY2() && element->has(PropertyId::Y2))
|
if(!attributes.hasY2() && element->has(PropertyID::Y2))
|
||||||
attributes.setY2(element->y2());
|
attributes.setY2(element->y2());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ref = context->getElementById(current->href());
|
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;
|
break;
|
||||||
|
|
||||||
processedGradients.insert(current);
|
processedGradients.insert(current);
|
||||||
|
@ -164,37 +164,37 @@ std::unique_ptr<Node> LinearGradientElement::clone() const
|
||||||
}
|
}
|
||||||
|
|
||||||
RadialGradientElement::RadialGradientElement()
|
RadialGradientElement::RadialGradientElement()
|
||||||
: GradientElement(ElementId::RadialGradient)
|
: GradientElement(ElementID::RadialGradient)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RadialGradientElement::cx() const
|
Length RadialGradientElement::cx() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Cx);
|
auto& value = get(PropertyID::Cx);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::FiftyPercent);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::FiftyPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RadialGradientElement::cy() const
|
Length RadialGradientElement::cy() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Cy);
|
auto& value = get(PropertyID::Cy);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::FiftyPercent);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::FiftyPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RadialGradientElement::r() const
|
Length RadialGradientElement::r() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::R);
|
auto& value = get(PropertyID::R);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::FiftyPercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::FiftyPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RadialGradientElement::fx() const
|
Length RadialGradientElement::fx() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Fx);
|
auto& value = get(PropertyID::Fx);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length RadialGradientElement::fy() const
|
Length RadialGradientElement::fy() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Fy);
|
auto& value = get(PropertyID::Fy);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,32 +206,32 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
if(!attributes.hasGradientTransform() && current->has(PropertyId::GradientTransform))
|
if(!attributes.hasGradientTransform() && current->has(PropertyID::GradientTransform))
|
||||||
attributes.setGradientTransform(current->gradientTransform());
|
attributes.setGradientTransform(current->gradientTransform());
|
||||||
if(!attributes.hasSpreadMethod() && current->has(PropertyId::SpreadMethod))
|
if(!attributes.hasSpreadMethod() && current->has(PropertyID::SpreadMethod))
|
||||||
attributes.setSpreadMethod(current->spreadMethod());
|
attributes.setSpreadMethod(current->spreadMethod());
|
||||||
if(!attributes.hasGradientUnits() && current->has(PropertyId::GradientUnits))
|
if(!attributes.hasGradientUnits() && current->has(PropertyID::GradientUnits))
|
||||||
attributes.setGradientUnits(current->gradientUnits());
|
attributes.setGradientUnits(current->gradientUnits());
|
||||||
if(!attributes.hasGradientStops())
|
if(!attributes.hasGradientStops())
|
||||||
attributes.setGradientStops(current->buildGradientStops());
|
attributes.setGradientStops(current->buildGradientStops());
|
||||||
|
|
||||||
if(current->id == ElementId::RadialGradient)
|
if(current->id == ElementID::RadialGradient)
|
||||||
{
|
{
|
||||||
auto element = static_cast<const RadialGradientElement*>(current);
|
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());
|
attributes.setCx(element->cx());
|
||||||
if(!attributes.hasCy() && element->has(PropertyId::Cy))
|
if(!attributes.hasCy() && element->has(PropertyID::Cy))
|
||||||
attributes.setCy(element->cy());
|
attributes.setCy(element->cy());
|
||||||
if(!attributes.hasR() && element->has(PropertyId::R))
|
if(!attributes.hasR() && element->has(PropertyID::R))
|
||||||
attributes.setR(element->r());
|
attributes.setR(element->r());
|
||||||
if(!attributes.hasFx() && element->has(PropertyId::Fx))
|
if(!attributes.hasFx() && element->has(PropertyID::Fx))
|
||||||
attributes.setFx(element->fx());
|
attributes.setFx(element->fx());
|
||||||
if(!attributes.hasFy() && element->has(PropertyId::Fy))
|
if(!attributes.hasFy() && element->has(PropertyID::Fy))
|
||||||
attributes.setFy(element->fy());
|
attributes.setFy(element->fy());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ref = context->getElementById(current->href());
|
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;
|
break;
|
||||||
|
|
||||||
processedGradients.insert(current);
|
processedGradients.insert(current);
|
||||||
|
@ -278,67 +278,67 @@ std::unique_ptr<Node> RadialGradientElement::clone() const
|
||||||
}
|
}
|
||||||
|
|
||||||
PatternElement::PatternElement()
|
PatternElement::PatternElement()
|
||||||
: PaintElement(ElementId::Pattern)
|
: PaintElement(ElementID::Pattern)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length PatternElement::x() const
|
Length PatternElement::x() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::X);
|
auto& value = get(PropertyID::X);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length PatternElement::y() const
|
Length PatternElement::y() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Y);
|
auto& value = get(PropertyID::Y);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length PatternElement::width() const
|
Length PatternElement::width() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Width);
|
auto& value = get(PropertyID::Width);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length PatternElement::height() const
|
Length PatternElement::height() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Height);
|
auto& value = get(PropertyID::Height);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform PatternElement::patternTransform() const
|
Transform PatternElement::patternTransform() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::PatternTransform);
|
auto& value = get(PropertyID::PatternTransform);
|
||||||
return Parser::parseTransform(value);
|
return Parser::parseTransform(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Units PatternElement::patternUnits() const
|
Units PatternElement::patternUnits() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::PatternUnits);
|
auto& value = get(PropertyID::PatternUnits);
|
||||||
return Parser::parseUnits(value, Units::ObjectBoundingBox);
|
return Parser::parseUnits(value, Units::ObjectBoundingBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
Units PatternElement::patternContentUnits() const
|
Units PatternElement::patternContentUnits() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::PatternContentUnits);
|
auto& value = get(PropertyID::PatternContentUnits);
|
||||||
return Parser::parseUnits(value, Units::UserSpaceOnUse);
|
return Parser::parseUnits(value, Units::UserSpaceOnUse);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect PatternElement::viewBox() const
|
Rect PatternElement::viewBox() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::ViewBox);
|
auto& value = get(PropertyID::ViewBox);
|
||||||
return Parser::parseViewBox(value);
|
return Parser::parseViewBox(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
PreserveAspectRatio PatternElement::preserveAspectRatio() const
|
PreserveAspectRatio PatternElement::preserveAspectRatio() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::PreserveAspectRatio);
|
auto& value = get(PropertyID::PreserveAspectRatio);
|
||||||
return Parser::parsePreserveAspectRatio(value);
|
return Parser::parsePreserveAspectRatio(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PatternElement::href() const
|
std::string PatternElement::href() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Href);
|
auto& value = get(PropertyID::Href);
|
||||||
return Parser::parseHref(value);
|
return Parser::parseHref(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,29 +353,29 @@ std::unique_ptr<LayoutObject> PatternElement::getPainter(LayoutContext* context)
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
if(!attributes.hasX() && current->has(PropertyId::X))
|
if(!attributes.hasX() && current->has(PropertyID::X))
|
||||||
attributes.setX(current->x());
|
attributes.setX(current->x());
|
||||||
if(!attributes.hasY() && current->has(PropertyId::Y))
|
if(!attributes.hasY() && current->has(PropertyID::Y))
|
||||||
attributes.setY(current->y());
|
attributes.setY(current->y());
|
||||||
if(!attributes.hasWidth() && current->has(PropertyId::Width))
|
if(!attributes.hasWidth() && current->has(PropertyID::Width))
|
||||||
attributes.setWidth(current->width());
|
attributes.setWidth(current->width());
|
||||||
if(!attributes.hasHeight() && current->has(PropertyId::Height))
|
if(!attributes.hasHeight() && current->has(PropertyID::Height))
|
||||||
attributes.setHeight(current->height());
|
attributes.setHeight(current->height());
|
||||||
if(!attributes.hasPatternTransform() && current->has(PropertyId::PatternTransform))
|
if(!attributes.hasPatternTransform() && current->has(PropertyID::PatternTransform))
|
||||||
attributes.setPatternTransform(current->patternTransform());
|
attributes.setPatternTransform(current->patternTransform());
|
||||||
if(!attributes.hasPatternUnits() && current->has(PropertyId::PatternUnits))
|
if(!attributes.hasPatternUnits() && current->has(PropertyID::PatternUnits))
|
||||||
attributes.setPatternUnits(current->patternUnits());
|
attributes.setPatternUnits(current->patternUnits());
|
||||||
if(!attributes.hasPatternContentUnits() && current->has(PropertyId::PatternContentUnits))
|
if(!attributes.hasPatternContentUnits() && current->has(PropertyID::PatternContentUnits))
|
||||||
attributes.setPatternContentUnits(current->patternContentUnits());
|
attributes.setPatternContentUnits(current->patternContentUnits());
|
||||||
if(!attributes.hasViewBox() && current->has(PropertyId::ViewBox))
|
if(!attributes.hasViewBox() && current->has(PropertyID::ViewBox))
|
||||||
attributes.setViewBox(current->viewBox());
|
attributes.setViewBox(current->viewBox());
|
||||||
if(!attributes.hasPreserveAspectRatio() && current->has(PropertyId::PreserveAspectRatio))
|
if(!attributes.hasPreserveAspectRatio() && current->has(PropertyID::PreserveAspectRatio))
|
||||||
attributes.setPreserveAspectRatio(current->preserveAspectRatio());
|
attributes.setPreserveAspectRatio(current->preserveAspectRatio());
|
||||||
if(!attributes.hasPatternContentElement() && current->children.size())
|
if(!attributes.hasPatternContentElement() && current->children.size())
|
||||||
attributes.setPatternContentElement(current);
|
attributes.setPatternContentElement(current);
|
||||||
|
|
||||||
auto ref = context->getElementById(current->href());
|
auto ref = context->getElementById(current->href());
|
||||||
if(!ref || ref->id != ElementId::Pattern)
|
if(!ref || ref->id != ElementID::Pattern)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
processedPatterns.insert(current);
|
processedPatterns.insert(current);
|
||||||
|
@ -413,7 +413,7 @@ std::unique_ptr<Node> PatternElement::clone() const
|
||||||
}
|
}
|
||||||
|
|
||||||
SolidColorElement::SolidColorElement()
|
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
|
class PaintElement : public StyledElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PaintElement(ElementId id);
|
PaintElement(ElementID id);
|
||||||
|
|
||||||
bool isPaint() const { return true; }
|
bool isPaint() const { return true; }
|
||||||
virtual std::unique_ptr<LayoutObject> getPainter(LayoutContext* context) const = 0;
|
virtual std::unique_ptr<LayoutObject> getPainter(LayoutContext* context) const = 0;
|
||||||
|
@ -20,7 +20,7 @@ public:
|
||||||
class GradientElement : public PaintElement
|
class GradientElement : public PaintElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GradientElement(ElementId id);
|
GradientElement(ElementID id);
|
||||||
|
|
||||||
Transform gradientTransform() const;
|
Transform gradientTransform() const;
|
||||||
SpreadMethod spreadMethod() const;
|
SpreadMethod spreadMethod() const;
|
||||||
|
|
1010
external/lunasvg/source/parser.cpp
vendored
1010
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
|
#define PARSER_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "property.h"
|
#include "property.h"
|
||||||
#include "element.h"
|
#include "element.h"
|
||||||
|
@ -63,7 +64,10 @@ private:
|
||||||
static bool parseTransform(const char*& ptr, const char* end, TransformType& type, double* values, int& count);
|
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
|
struct AttributeSelector
|
||||||
{
|
{
|
||||||
|
@ -78,20 +82,19 @@ struct AttributeSelector
|
||||||
Contains
|
Contains
|
||||||
};
|
};
|
||||||
|
|
||||||
PropertyId id{PropertyId::Unknown};
|
|
||||||
std::string value;
|
|
||||||
MatchType matchType{MatchType::None};
|
MatchType matchType{MatchType::None};
|
||||||
|
PropertyID id{PropertyID::Unknown};
|
||||||
|
std::string value;
|
||||||
};
|
};
|
||||||
|
|
||||||
using SelectorList = std::vector<Selector>;
|
struct PseudoClassSelector
|
||||||
|
|
||||||
struct PseudoClass
|
|
||||||
{
|
{
|
||||||
enum class Type
|
enum class Type
|
||||||
{
|
{
|
||||||
Unknown,
|
Unknown,
|
||||||
Empty,
|
Empty,
|
||||||
Root,
|
Root,
|
||||||
|
Is,
|
||||||
Not,
|
Not,
|
||||||
FirstChild,
|
FirstChild,
|
||||||
LastChild,
|
LastChild,
|
||||||
|
@ -102,7 +105,9 @@ struct PseudoClass
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type{Type::Unknown};
|
Type type{Type::Unknown};
|
||||||
SelectorList notSelectors;
|
int16_t a{0};
|
||||||
|
int16_t b{0};
|
||||||
|
SelectorList subSelectors;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SimpleSelector
|
struct SimpleSelector
|
||||||
|
@ -115,16 +120,10 @@ struct SimpleSelector
|
||||||
InDirectAdjacent
|
InDirectAdjacent
|
||||||
};
|
};
|
||||||
|
|
||||||
ElementId id{ElementId::Star};
|
|
||||||
std::vector<AttributeSelector> attributeSelectors;
|
|
||||||
std::vector<PseudoClass> pseudoClasses;
|
|
||||||
Combinator combinator{Combinator::Descendant};
|
Combinator combinator{Combinator::Descendant};
|
||||||
};
|
ElementID id{ElementID::Star};
|
||||||
|
std::vector<AttributeSelector> attributeSelectors;
|
||||||
struct Selector
|
std::vector<PseudoClassSelector> pseudoClassSelectors;
|
||||||
{
|
|
||||||
std::vector<SimpleSelector> simpleSelectors;
|
|
||||||
int specificity{0};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Rule
|
struct Rule
|
||||||
|
@ -133,21 +132,47 @@ struct Rule
|
||||||
PropertyList declarations;
|
PropertyList declarations;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RuleMatchContext
|
class RuleData {
|
||||||
{
|
|
||||||
public:
|
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;
|
std::vector<const PropertyList*> match(const Element* element) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool selectorMatch(const Selector* selector, const Element* element) const;
|
std::multiset<RuleData> m_rules;
|
||||||
bool simpleSelectorMatch(const SimpleSelector& selector, const Element* element) const;
|
uint32_t m_position{0};
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CSSParser
|
class CSSParser
|
||||||
|
@ -155,35 +180,29 @@ class CSSParser
|
||||||
public:
|
public:
|
||||||
CSSParser() = default;
|
CSSParser() = default;
|
||||||
|
|
||||||
bool parseMore(const std::string& value);
|
static bool parseSheet(StyleSheet* sheet, const std::string& value);
|
||||||
|
|
||||||
const std::vector<Rule>& rules() const { return m_rules; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool parseAtRule(const char*& ptr, const char* end) const;
|
static bool parseAtRule(const char*& ptr, const char* end);
|
||||||
bool parseRule(const char*& ptr, const char* end, Rule& rule) const;
|
static bool parseRule(const char*& ptr, const char* end, Rule& rule);
|
||||||
bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors) const;
|
static bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors);
|
||||||
bool parseDeclarations(const char*& ptr, const char* end, PropertyList& declarations) const;
|
static bool parseDeclarations(const char*& ptr, const char* end, PropertyList& declarations);
|
||||||
bool parseSelector(const char*& ptr, const char* end, Selector& selector) const;
|
static bool parseSelector(const char*& ptr, const char* end, Selector& selector);
|
||||||
bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector) const;
|
static bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector);
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<Rule> m_rules;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LayoutSymbol;
|
class LayoutSymbol;
|
||||||
|
|
||||||
class ParseDocument
|
class TreeBuilder {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
ParseDocument();
|
TreeBuilder();
|
||||||
~ParseDocument();
|
~TreeBuilder();
|
||||||
|
|
||||||
bool parse(const char* data, std::size_t size);
|
bool parse(const char* data, std::size_t size);
|
||||||
|
|
||||||
SVGElement* rootElement() const { return m_rootElement.get(); }
|
SVGElement* rootElement() const { return m_rootElement.get(); }
|
||||||
Element* getElementById(const std::string& id) const;
|
Element* getElementById(const std::string& id) const;
|
||||||
std::unique_ptr<LayoutSymbol> layout() const;
|
std::unique_ptr<LayoutSymbol> build() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<SVGElement> m_rootElement;
|
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 <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <string_view>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace lunasvg {
|
namespace lunasvg {
|
||||||
|
|
||||||
|
@ -262,6 +264,241 @@ inline bool parseNumber(const char*& ptr, const char* end, T& number)
|
||||||
|
|
||||||
} // namespace Utils
|
} // 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
|
} // namespace lunasvg
|
||||||
|
|
||||||
#endif // PARSERUTILS_H
|
#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 {
|
namespace lunasvg {
|
||||||
|
|
||||||
StopElement::StopElement()
|
StopElement::StopElement()
|
||||||
: StyledElement(ElementId::Stop)
|
: StyledElement(ElementID::Stop)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
double StopElement::offset() const
|
double StopElement::offset() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Offset);
|
auto& value = get(PropertyID::Offset);
|
||||||
return Parser::parseNumberPercentage(value, 0.0);
|
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 {
|
namespace lunasvg {
|
||||||
|
|
||||||
StyledElement::StyledElement(ElementId id)
|
StyledElement::StyledElement(ElementID id)
|
||||||
: Element(id)
|
: Element(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Paint StyledElement::fill() const
|
Paint StyledElement::fill() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Fill);
|
auto& value = find(PropertyID::Fill);
|
||||||
return Parser::parsePaint(value, this, Color::Black);
|
return Parser::parsePaint(value, this, Color::Black);
|
||||||
}
|
}
|
||||||
|
|
||||||
Paint StyledElement::stroke() const
|
Paint StyledElement::stroke() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Stroke);
|
auto& value = find(PropertyID::Stroke);
|
||||||
return Parser::parsePaint(value, this, Color::Transparent);
|
return Parser::parsePaint(value, this, Color::Transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color StyledElement::color() const
|
Color StyledElement::color() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Color);
|
auto& value = find(PropertyID::Color);
|
||||||
return Parser::parseColor(value, this, Color::Black);
|
return Parser::parseColor(value, this, Color::Black);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color StyledElement::stop_color() const
|
Color StyledElement::stop_color() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Stop_Color);
|
auto& value = find(PropertyID::Stop_Color);
|
||||||
return Parser::parseColor(value, this, Color::Black);
|
return Parser::parseColor(value, this, Color::Black);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color StyledElement::solid_color() const
|
Color StyledElement::solid_color() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Solid_Color);
|
auto& value = find(PropertyID::Solid_Color);
|
||||||
return Parser::parseColor(value, this, Color::Black);
|
return Parser::parseColor(value, this, Color::Black);
|
||||||
}
|
}
|
||||||
|
|
||||||
double StyledElement::opacity() const
|
double StyledElement::opacity() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Opacity);
|
auto& value = get(PropertyID::Opacity);
|
||||||
return Parser::parseNumberPercentage(value, 1.0);
|
return Parser::parseNumberPercentage(value, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double StyledElement::fill_opacity() const
|
double StyledElement::fill_opacity() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Fill_Opacity);
|
auto& value = find(PropertyID::Fill_Opacity);
|
||||||
return Parser::parseNumberPercentage(value, 1.0);
|
return Parser::parseNumberPercentage(value, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double StyledElement::stroke_opacity() const
|
double StyledElement::stroke_opacity() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Stroke_Opacity);
|
auto& value = find(PropertyID::Stroke_Opacity);
|
||||||
return Parser::parseNumberPercentage(value, 1.0);
|
return Parser::parseNumberPercentage(value, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double StyledElement::stop_opacity() const
|
double StyledElement::stop_opacity() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Stop_Opacity);
|
auto& value = find(PropertyID::Stop_Opacity);
|
||||||
return Parser::parseNumberPercentage(value, 1.0);
|
return Parser::parseNumberPercentage(value, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double StyledElement::solid_opacity() const
|
double StyledElement::solid_opacity() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Solid_Opacity);
|
auto& value = find(PropertyID::Solid_Opacity);
|
||||||
return Parser::parseNumberPercentage(value, 1.0);
|
return Parser::parseNumberPercentage(value, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double StyledElement::stroke_miterlimit() const
|
double StyledElement::stroke_miterlimit() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Stroke_Miterlimit);
|
auto& value = find(PropertyID::Stroke_Miterlimit);
|
||||||
return Parser::parseNumber(value, 4.0);
|
return Parser::parseNumber(value, 4.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length StyledElement::stroke_width() const
|
Length StyledElement::stroke_width() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Stroke_Width);
|
auto& value = find(PropertyID::Stroke_Width);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::One);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::One);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length StyledElement::stroke_dashoffset() const
|
Length StyledElement::stroke_dashoffset() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Stroke_Dashoffset);
|
auto& value = find(PropertyID::Stroke_Dashoffset);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
LengthList StyledElement::stroke_dasharray() const
|
LengthList StyledElement::stroke_dasharray() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Stroke_Dasharray);
|
auto& value = find(PropertyID::Stroke_Dasharray);
|
||||||
return Parser::parseLengthList(value, ForbidNegativeLengths);
|
return Parser::parseLengthList(value, ForbidNegativeLengths);
|
||||||
}
|
}
|
||||||
|
|
||||||
WindRule StyledElement::fill_rule() const
|
WindRule StyledElement::fill_rule() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Fill_Rule);
|
auto& value = find(PropertyID::Fill_Rule);
|
||||||
return Parser::parseWindRule(value);
|
return Parser::parseWindRule(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
WindRule StyledElement::clip_rule() const
|
WindRule StyledElement::clip_rule() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Clip_Rule);
|
auto& value = find(PropertyID::Clip_Rule);
|
||||||
return Parser::parseWindRule(value);
|
return Parser::parseWindRule(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
LineCap StyledElement::stroke_linecap() const
|
LineCap StyledElement::stroke_linecap() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Stroke_Linecap);
|
auto& value = find(PropertyID::Stroke_Linecap);
|
||||||
return Parser::parseLineCap(value);
|
return Parser::parseLineCap(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
LineJoin StyledElement::stroke_linejoin() const
|
LineJoin StyledElement::stroke_linejoin() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Stroke_Linejoin);
|
auto& value = find(PropertyID::Stroke_Linejoin);
|
||||||
return Parser::parseLineJoin(value);
|
return Parser::parseLineJoin(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Display StyledElement::display() const
|
Display StyledElement::display() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Display);
|
auto& value = get(PropertyID::Display);
|
||||||
return Parser::parseDisplay(value);
|
return Parser::parseDisplay(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Visibility StyledElement::visibility() const
|
Visibility StyledElement::visibility() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Visibility);
|
auto& value = find(PropertyID::Visibility);
|
||||||
return Parser::parseVisibility(value);
|
return Parser::parseVisibility(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Overflow StyledElement::overflow() const
|
Overflow StyledElement::overflow() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Overflow);
|
auto& value = get(PropertyID::Overflow);
|
||||||
return Parser::parseOverflow(value, parent == nullptr ? Overflow::Visible : Overflow::Hidden);
|
return Parser::parseOverflow(value, parent == nullptr ? Overflow::Visible : Overflow::Hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StyledElement::clip_path() const
|
std::string StyledElement::clip_path() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Clip_Path);
|
auto& value = get(PropertyID::Clip_Path);
|
||||||
return Parser::parseUrl(value);
|
return Parser::parseUrl(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StyledElement::mask() const
|
std::string StyledElement::mask() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Mask);
|
auto& value = get(PropertyID::Mask);
|
||||||
return Parser::parseUrl(value);
|
return Parser::parseUrl(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StyledElement::marker_start() const
|
std::string StyledElement::marker_start() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Marker_Start);
|
auto& value = find(PropertyID::Marker_Start);
|
||||||
return Parser::parseUrl(value);
|
return Parser::parseUrl(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StyledElement::marker_mid() const
|
std::string StyledElement::marker_mid() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Marker_Mid);
|
auto& value = find(PropertyID::Marker_Mid);
|
||||||
return Parser::parseUrl(value);
|
return Parser::parseUrl(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StyledElement::marker_end() const
|
std::string StyledElement::marker_end() const
|
||||||
{
|
{
|
||||||
auto& value = find(PropertyId::Marker_End);
|
auto& value = find(PropertyID::Marker_End);
|
||||||
return Parser::parseUrl(value);
|
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
|
class StyledElement : public Element
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StyledElement(ElementId id);
|
StyledElement(ElementID id);
|
||||||
|
|
||||||
Paint fill() const;
|
Paint fill() const;
|
||||||
Paint stroke() const;
|
Paint stroke() const;
|
||||||
|
|
2
external/lunasvg/source/styleelement.cpp
vendored
2
external/lunasvg/source/styleelement.cpp
vendored
|
@ -3,7 +3,7 @@
|
||||||
namespace lunasvg {
|
namespace lunasvg {
|
||||||
|
|
||||||
StyleElement::StyleElement()
|
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 {
|
namespace lunasvg {
|
||||||
|
|
||||||
SVGElement::SVGElement()
|
SVGElement::SVGElement()
|
||||||
: GraphicsElement(ElementId::Svg)
|
: GraphicsElement(ElementID::Svg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length SVGElement::x() const
|
Length SVGElement::x() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::X);
|
auto& value = get(PropertyID::X);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length SVGElement::y() const
|
Length SVGElement::y() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Y);
|
auto& value = get(PropertyID::Y);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length SVGElement::width() const
|
Length SVGElement::width() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Width);
|
auto& value = get(PropertyID::Width);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length SVGElement::height() const
|
Length SVGElement::height() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Height);
|
auto& value = get(PropertyID::Height);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect SVGElement::viewBox() const
|
Rect SVGElement::viewBox() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::ViewBox);
|
auto& value = get(PropertyID::ViewBox);
|
||||||
return Parser::parseViewBox(value);
|
return Parser::parseViewBox(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
PreserveAspectRatio SVGElement::preserveAspectRatio() const
|
PreserveAspectRatio SVGElement::preserveAspectRatio() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::PreserveAspectRatio);
|
auto& value = get(PropertyID::PreserveAspectRatio);
|
||||||
return Parser::parsePreserveAspectRatio(value);
|
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())
|
if(isDisplayNone())
|
||||||
return nullptr;
|
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->clip = isOverflowHidden() ? preserveAspectRatio.getClip(_w, _h, viewBox) : Rect::Invalid;
|
||||||
root->opacity = opacity();
|
root->opacity = opacity();
|
||||||
|
|
||||||
LayoutContext context(document, root.get());
|
LayoutContext context(builder, root.get());
|
||||||
root->masker = context.getMasker(mask());
|
root->masker = context.getMasker(mask());
|
||||||
root->clipper = context.getClipper(clip_path());
|
root->clipper = context.getClipper(clip_path());
|
||||||
layoutChildren(&context, root.get());
|
layoutChildren(&context, root.get());
|
||||||
|
|
4
external/lunasvg/source/svgelement.h
vendored
4
external/lunasvg/source/svgelement.h
vendored
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
namespace lunasvg {
|
namespace lunasvg {
|
||||||
|
|
||||||
class ParseDocument;
|
class TreeBuilder;
|
||||||
class LayoutSymbol;
|
class LayoutSymbol;
|
||||||
|
|
||||||
class SVGElement : public GraphicsElement
|
class SVGElement : public GraphicsElement
|
||||||
|
@ -20,7 +20,7 @@ public:
|
||||||
|
|
||||||
Rect viewBox() const;
|
Rect viewBox() const;
|
||||||
PreserveAspectRatio preserveAspectRatio() 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;
|
void layout(LayoutContext* context, LayoutContainer* current) const;
|
||||||
std::unique_ptr<Node> clone() 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 {
|
namespace lunasvg {
|
||||||
|
|
||||||
SymbolElement::SymbolElement()
|
SymbolElement::SymbolElement()
|
||||||
: StyledElement(ElementId::Symbol)
|
: StyledElement(ElementID::Symbol)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length SymbolElement::x() const
|
Length SymbolElement::x() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::X);
|
auto& value = get(PropertyID::X);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length SymbolElement::y() const
|
Length SymbolElement::y() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Y);
|
auto& value = get(PropertyID::Y);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length SymbolElement::width() const
|
Length SymbolElement::width() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Width);
|
auto& value = get(PropertyID::Width);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length SymbolElement::height() const
|
Length SymbolElement::height() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Height);
|
auto& value = get(PropertyID::Height);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect SymbolElement::viewBox() const
|
Rect SymbolElement::viewBox() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::ViewBox);
|
auto& value = get(PropertyID::ViewBox);
|
||||||
return Parser::parseViewBox(value);
|
return Parser::parseViewBox(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
PreserveAspectRatio SymbolElement::preserveAspectRatio() const
|
PreserveAspectRatio SymbolElement::preserveAspectRatio() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::PreserveAspectRatio);
|
auto& value = get(PropertyID::PreserveAspectRatio);
|
||||||
return Parser::parsePreserveAspectRatio(value);
|
return Parser::parsePreserveAspectRatio(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
external/lunasvg/source/useelement.cpp
vendored
26
external/lunasvg/source/useelement.cpp
vendored
|
@ -8,47 +8,47 @@
|
||||||
namespace lunasvg {
|
namespace lunasvg {
|
||||||
|
|
||||||
UseElement::UseElement()
|
UseElement::UseElement()
|
||||||
: GraphicsElement(ElementId::Use)
|
: GraphicsElement(ElementID::Use)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Length UseElement::x() const
|
Length UseElement::x() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::X);
|
auto& value = get(PropertyID::X);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length UseElement::y() const
|
Length UseElement::y() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Y);
|
auto& value = get(PropertyID::Y);
|
||||||
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
return Parser::parseLength(value, AllowNegativeLengths, Length::Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length UseElement::width() const
|
Length UseElement::width() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Width);
|
auto& value = get(PropertyID::Width);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Length UseElement::height() const
|
Length UseElement::height() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Height);
|
auto& value = get(PropertyID::Height);
|
||||||
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
return Parser::parseLength(value, ForbidNegativeLengths, Length::HundredPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string UseElement::href() const
|
std::string UseElement::href() const
|
||||||
{
|
{
|
||||||
auto& value = get(PropertyId::Href);
|
auto& value = get(PropertyID::Href);
|
||||||
return Parser::parseHref(value);
|
return Parser::parseHref(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UseElement::transferWidthAndHeight(Element* element) const
|
void UseElement::transferWidthAndHeight(Element* element) const
|
||||||
{
|
{
|
||||||
auto& width = get(PropertyId::Width);
|
auto& width = get(PropertyID::Width);
|
||||||
auto& height = get(PropertyId::Height);
|
auto& height = get(PropertyID::Height);
|
||||||
|
|
||||||
element->set(PropertyId::Width, width, 0x0);
|
element->set(PropertyID::Width, width, 0x0);
|
||||||
element->set(PropertyId::Height, height, 0x0);
|
element->set(PropertyID::Height, height, 0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UseElement::layout(LayoutContext* context, LayoutContainer* current) const
|
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 _x = lengthContext.valueForLength(x(), LengthMode::Width);
|
||||||
auto _y = lengthContext.valueForLength(y(), LengthMode::Height);
|
auto _y = lengthContext.valueForLength(y(), LengthMode::Height);
|
||||||
|
|
||||||
auto transform = get(PropertyId::Transform);
|
auto transform = get(PropertyID::Transform);
|
||||||
transform += "translate(";
|
transform += "translate(";
|
||||||
transform += std::to_string(_x);
|
transform += std::to_string(_x);
|
||||||
transform += ' ';
|
transform += ' ';
|
||||||
transform += std::to_string(_y);
|
transform += std::to_string(_y);
|
||||||
transform += ')';
|
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>();
|
auto element = ref->cloneElement<SVGElement>();
|
||||||
transferWidthAndHeight(element.get());
|
transferWidthAndHeight(element.get());
|
||||||
|
|
Loading…
Reference in a new issue