Merge commit '9a2c8e10777d7b572589657a49f4dbaaa0c72a16' into next

This commit is contained in:
Leon Styhre 2023-07-29 12:37:05 +02:00
commit b72a57c855
35 changed files with 754 additions and 1134 deletions

View file

@ -1,2 +0,0 @@
.vscode
build/*

View file

@ -1,15 +1,10 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.3)
project(lunasvg VERSION 2.3.5 LANGUAGES CXX C) project(lunasvg VERSION 2.3.8 LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
# Default to hidden visibility for symbols
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
option(BUILD_SHARED_LIBS "Builds as shared library" OFF) option(BUILD_SHARED_LIBS "Builds as shared library" OFF)
option(LUNASVG_BUILD_EXAMPLES "Builds examples" OFF) option(LUNASVG_BUILD_EXAMPLES "Builds examples" OFF)
@ -19,61 +14,25 @@ add_subdirectory(include)
add_subdirectory(source) add_subdirectory(source)
add_subdirectory(3rdparty/plutovg) add_subdirectory(3rdparty/plutovg)
set_target_properties(lunasvg if(BUILD_SHARED_LIBS)
PROPERTIES target_compile_definitions(lunasvg PUBLIC LUNASVG_SHARED)
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" target_compile_definitions(lunasvg PRIVATE LUNASVG_EXPORT)
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
add_library(lunasvg::lunasvg ALIAS lunasvg)
if(NOT BUILD_SHARED_LIBS)
target_compile_definitions(lunasvg PUBLIC LUNASVG_STATIC_DEFINE)
endif() endif()
if(LUNASVG_BUILD_EXAMPLES) if(LUNASVG_BUILD_EXAMPLES)
add_subdirectory(example) add_subdirectory(example)
endif() endif()
# set(LUNASVG_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib)
# Installation set(LUNASVG_INCDIR ${CMAKE_INSTALL_PREFIX}/include)
#
include(GNUInstallDirs)
install(
FILES
${CMAKE_CURRENT_SOURCE_DIR}/include/lunasvg.h
${CMAKE_CURRENT_BINARY_DIR}/include/lunasvg_export.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/lunasvg
)
install(
TARGETS lunasvg
EXPORT lunasvg-targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(
EXPORT lunasvg-targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lunasvg NAMESPACE lunasvg:: FILE lunasvgTargets.cmake
)
include(CMakePackageConfigHelpers)
configure_package_config_file(
${CMAKE_CURRENT_SOURCE_DIR}/cmake/lunasvgConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/lunasvgConfig.cmake
INSTALL_DESTINATION
${CMAKE_INSTALL_LIBDIR}/cmake/lunasvg
)
write_basic_package_version_file(lunasvgConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
install(FILES install(FILES
${CMAKE_CURRENT_BINARY_DIR}/lunasvgConfig.cmake include/lunasvg.h
${CMAKE_CURRENT_BINARY_DIR}/lunasvgConfigVersion.cmake DESTINATION ${LUNASVG_INCDIR}
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lunasvg
) )
export(EXPORT lunasvg-targets FILE ${CMAKE_CURRENT_BINARY_DIR}/lunasvgTargets.cmake NAMESPACE lunasvg::) install(TARGETS lunasvg
LIBRARY DESTINATION ${LUNASVG_LIBDIR}
ARCHIVE DESTINATION ${LUNASVG_LIBDIR}
INCLUDES DESTINATION ${LUNASVG_INCDIR}
)

View file

@ -1,4 +1,4 @@
[![Releases](https://img.shields.io/badge/Version-2.3.5-orange.svg)](https://github.com/sammycage/lunasvg/releases) [![Releases](https://img.shields.io/badge/Version-2.3.8-orange.svg)](https://github.com/sammycage/lunasvg/releases)
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/sammycage/lunasvg/blob/master/LICENSE) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/sammycage/lunasvg/blob/master/LICENSE)
[![Build Status](https://github.com/sammycage/lunasvg/actions/workflows/ci.yml/badge.svg)](https://github.com/sammycage/lunasvg/actions) [![Build Status](https://github.com/sammycage/lunasvg/actions/workflows/ci.yml/badge.svg)](https://github.com/sammycage/lunasvg/actions)

View file

@ -1,3 +0,0 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/lunasvgTargets.cmake")

View file

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.3)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 14)

View file

@ -1,16 +1,4 @@
# Generate a standard header with export macros
include(GenerateExportHeader)
generate_export_header(lunasvg)
target_include_directories(lunasvg target_include_directories(lunasvg
# When building a project that uses the lunasvg library, PUBLIC
# we need to look in the installed include directory "${CMAKE_CURRENT_LIST_DIR}"
PUBLIC
$<INSTALL_INTERFACE:include>
# When building the lunasvg library we need to look in the
# build dir for the lunasvg_export.h header and in the source
# dir for other headers
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
) )

View file

@ -27,16 +27,22 @@
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include <lunasvg_export.h> #if defined(_MSC_VER) && defined(LUNASVG_SHARED)
#define LUNASVG_API LUNASVG_EXPORT #ifdef LUNASVG_EXPORT
#define LUNASVG_API __declspec(dllexport)
#else
#define LUNASVG_API __declspec(dllimport)
#endif
#else
#define LUNASVG_API
#endif
namespace lunasvg { namespace lunasvg {
class Rect; class Rect;
class Matrix; class Matrix;
class LUNASVG_API Box class LUNASVG_API Box {
{
public: public:
Box() = default; Box() = default;
Box(double x, double y, double w, double h); Box(double x, double y, double w, double h);
@ -54,8 +60,7 @@ public:
class Transform; class Transform;
class LUNASVG_API Matrix class LUNASVG_API Matrix {
{
public: public:
Matrix() = default; Matrix() = default;
Matrix(double a, double b, double c, double d, double e, double f); Matrix(double a, double b, double c, double d, double e, double f);
@ -92,8 +97,7 @@ public:
double f{0}; double f{0};
}; };
class LUNASVG_API Bitmap class LUNASVG_API Bitmap {
{
public: public:
/** /**
* @note Bitmap format is ARGB Premultiplied. * @note Bitmap format is ARGB Premultiplied.
@ -123,8 +127,7 @@ private:
class LayoutSymbol; class LayoutSymbol;
class LUNASVG_API Document class LUNASVG_API Document {
{
public: public:
/** /**
* @brief Creates a document from a file * @brief Creates a document from a file
@ -202,6 +205,7 @@ public:
Bitmap renderToBitmap(std::uint32_t width = 0, std::uint32_t height = 0, std::uint32_t backgroundColor = 0x00000000) const; Bitmap renderToBitmap(std::uint32_t width = 0, std::uint32_t height = 0, std::uint32_t backgroundColor = 0x00000000) const;
~Document(); ~Document();
private: private:
Document(); Document();

View file

@ -149,11 +149,9 @@ void Canvas::luminance()
auto height = plutovg_surface_get_height(surface); auto height = plutovg_surface_get_height(surface);
auto stride = plutovg_surface_get_stride(surface); auto stride = plutovg_surface_get_stride(surface);
auto data = plutovg_surface_get_data(surface); auto data = plutovg_surface_get_data(surface);
for(int y = 0;y < height;y++) for(int y = 0; y < height; y++) {
{
auto pixels = reinterpret_cast<uint32_t*>(data + stride * y); auto pixels = reinterpret_cast<uint32_t*>(data + stride * y);
for(int x = 0;x < width;x++) for(int x = 0; x < width; x++) {
{
auto pixel = pixels[x]; auto pixel = pixels[x];
auto r = (pixel >> 16) & 0xFF; auto r = (pixel >> 16) & 0xFF;
auto g = (pixel >> 8) & 0xFF; auto g = (pixel >> 8) & 0xFF;
@ -229,8 +227,7 @@ static plutovg_texture_type_t to_plutovg_texture_type(TextureType type)
static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops& stops) static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops& stops)
{ {
for(const auto& stop : stops) for(const auto& stop : stops) {
{
auto offset = std::get<0>(stop); auto offset = std::get<0>(stop);
auto& color = std::get<1>(stop); auto& color = std::get<1>(stop);
plutovg_gradient_add_stop_rgba(gradient, offset, color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0, color.alpha() / 255.0); plutovg_gradient_add_stop_rgba(gradient, offset, color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0, color.alpha() / 255.0);
@ -241,8 +238,7 @@ void to_plutovg_path(plutovg_t* pluto, const Path& path)
{ {
PathIterator it(path); PathIterator it(path);
std::array<Point, 3> p; std::array<Point, 3> p;
while(!it.isDone()) while(!it.isDone()) {
{
switch(it.currentSegment(p)) { switch(it.currentSegment(p)) {
case PathCommand::MoveTo: case PathCommand::MoveTo:
plutovg_move_to(pluto, p[0].x, p[0].y); plutovg_move_to(pluto, p[0].x, p[0].y);

View file

@ -13,20 +13,17 @@ using GradientStops = std::vector<GradientStop>;
using DashArray = std::vector<double>; using DashArray = std::vector<double>;
struct DashData struct DashData {
{
DashArray array; DashArray array;
double offset{0.0}; double offset{0.0};
}; };
enum class TextureType enum class TextureType {
{
Plain, Plain,
Tiled Tiled
}; };
enum class BlendMode enum class BlendMode {
{
Src, Src,
Src_Over, Src_Over,
Dst_In, Dst_In,
@ -35,8 +32,7 @@ enum class BlendMode
class CanvasImpl; class CanvasImpl;
class Canvas class Canvas {
{
public: public:
static std::shared_ptr<Canvas> create(unsigned char* data, unsigned int width, unsigned int height, unsigned int stride); static std::shared_ptr<Canvas> create(unsigned char* data, unsigned int width, unsigned int height, unsigned int stride);
static std::shared_ptr<Canvas> create(double x, double y, double width, double height); static std::shared_ptr<Canvas> create(double x, double y, double width, double height);
@ -61,6 +57,7 @@ public:
Rect box() const; Rect box() const;
~Canvas(); ~Canvas();
private: private:
Canvas(unsigned char* data, int width, int height, int stride); Canvas(unsigned char* data, int width, int height, int stride);
Canvas(int x, int y, int width, int height); Canvas(int x, int y, int width, int height);

View file

@ -7,8 +7,7 @@ namespace lunasvg {
class LayoutClipPath; class LayoutClipPath;
class ClipPathElement : public GraphicsElement class ClipPathElement : public GraphicsElement {
{
public: public:
ClipPathElement(); ClipPathElement();

View file

@ -5,8 +5,7 @@
namespace lunasvg { namespace lunasvg {
class DefsElement : public GraphicsElement class DefsElement : public GraphicsElement {
{
public: public:
DefsElement(); DefsElement();

View file

@ -1,53 +1,8 @@
#include "element.h" #include "element.h"
#include "parser.h"
#include "svgelement.h" #include "svgelement.h"
namespace lunasvg { namespace lunasvg {
void PropertyList::set(PropertyID id, const std::string& value, int specificity)
{
auto property = get(id);
if(property == nullptr)
{
Property property{id, value, specificity};
m_properties.push_back(std::move(property));
return;
}
if(property->specificity > specificity)
return;
property->specificity = specificity;
property->value = value;
}
Property* PropertyList::get(PropertyID id) const
{
auto data = m_properties.data();
auto end = data + m_properties.size();
while(data < end)
{
if(data->id == id)
return const_cast<Property*>(data);
++data;
}
return nullptr;
}
void PropertyList::add(const Property& property)
{
set(property.id, property.value, property.specificity);
}
void PropertyList::add(const PropertyList& properties)
{
auto it = properties.m_properties.begin();
auto end = properties.m_properties.end();
for(;it != end;++it)
add(*it);
}
void Node::layout(LayoutContext*, LayoutContainer*) const void Node::layout(LayoutContext*, LayoutContainer*) const
{ {
} }
@ -66,18 +21,32 @@ Element::Element(ElementID 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); for(auto& property : properties) {
if(property.id == id) {
if(specificity >= property.specificity) {
property.specificity = specificity;
property.value = value;
}
return;
}
}
Property property{specificity, id, value};
properties.push_back(std::move(property));
} }
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); for(auto& property : properties) {
if(property == nullptr) if(property.id == id) {
return EmptyString; return property.value;
}
}
return property->value; return EmptyString;
} }
static const std::string InheritString{"inherit"}; static const std::string InheritString{"inherit"};
@ -97,7 +66,13 @@ const std::string& Element::find(PropertyID id) const
bool Element::has(PropertyID id) const bool Element::has(PropertyID id) const
{ {
return properties.get(id); for(auto& property : properties) {
if(property.id == id) {
return true;
}
}
return false;
} }
Element* Element::previousElement() const Element* Element::previousElement() const
@ -108,12 +83,10 @@ Element* Element::previousElement() const
Element* element = nullptr; Element* element = nullptr;
auto it = parent->children.begin(); auto it = parent->children.begin();
auto end = parent->children.end(); auto end = parent->children.end();
for(;it != end;++it) for(; it != end; ++it) {
{
auto node = it->get(); auto node = it->get();
if(node->isText()) if(node->isText())
continue; continue;
if(node == this) if(node == this)
return element; return element;
element = static_cast<Element*>(node); element = static_cast<Element*>(node);
@ -130,8 +103,7 @@ Element* Element::nextElement() const
Element* element = nullptr; Element* element = nullptr;
auto it = parent->children.rbegin(); auto it = parent->children.rbegin();
auto end = parent->children.rend(); auto end = parent->children.rend();
for(;it != end;++it) for(; it != end; ++it) {
{
auto node = it->get(); auto node = it->get();
if(node->isText()) if(node->isText())
continue; continue;
@ -153,22 +125,21 @@ Node* Element::addChild(std::unique_ptr<Node> child)
void Element::layoutChildren(LayoutContext* context, LayoutContainer* current) const void Element::layoutChildren(LayoutContext* context, LayoutContainer* current) const
{ {
for(auto& child : children) for(auto& child : children) {
child->layout(context, current); child->layout(context, current);
}
} }
Rect Element::currentViewport() const 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();

View file

@ -8,8 +8,7 @@
namespace lunasvg { namespace lunasvg {
enum class ElementID enum class ElementID {
{
Unknown = 0, Unknown = 0,
Star, Star,
Circle, Circle,
@ -35,8 +34,7 @@ enum class ElementID
Use Use
}; };
enum class PropertyID enum class PropertyID {
{
Unknown = 0, Unknown = 0,
Class, Class,
Clip_Path, Clip_Path,
@ -106,34 +104,19 @@ enum class PropertyID
Y2 Y2
}; };
struct Property struct Property {
{ int specificity;
PropertyID id; PropertyID id;
std::string value; std::string value;
int specificity;
}; };
class PropertyList using PropertyList = std::vector<Property>;
{
public:
PropertyList() = default;
void set(PropertyID id, const std::string& value, int specificity);
Property* get(PropertyID id) const;
void add(const Property& property);
void add(const PropertyList& properties);
void clear() { m_properties.clear(); }
private:
std::vector<Property> m_properties;
};
class LayoutContext; class LayoutContext;
class LayoutContainer; class LayoutContainer;
class Element; class Element;
class Node class Node {
{
public: public:
Node() = default; Node() = default;
virtual ~Node() = default; virtual ~Node() = default;
@ -148,8 +131,7 @@ public:
Element* parent = nullptr; Element* parent = nullptr;
}; };
class TextNode : public Node class TextNode : public Node {
{
public: public:
TextNode() = default; TextNode() = default;
@ -162,8 +144,7 @@ public:
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);
@ -179,16 +160,13 @@ public:
Rect currentViewport() const; Rect currentViewport() const;
template<typename T> template<typename T>
void transverse(T callback) void transverse(T callback) {
{ if(!callback(this))
if(callback(this))
return; return;
for(auto& child : children) for(auto& child : children) {
{ if(child->isText()) {
if(child->isText()) if(!callback(child.get()))
{
if(callback(child.get()))
return; return;
continue; continue;
} }
@ -199,8 +177,7 @@ public:
} }
template<typename T> template<typename T>
std::unique_ptr<T> cloneElement() const std::unique_ptr<T> cloneElement() const {
{
auto element = std::make_unique<T>(); auto element = std::make_unique<T>();
element->properties = properties; element->properties = properties;
for(auto& child : children) for(auto& child : children)

View file

@ -5,8 +5,7 @@
namespace lunasvg { namespace lunasvg {
class GElement : public GraphicsElement class GElement : public GraphicsElement {
{
public: public:
GElement(); GElement();

View file

@ -79,7 +79,7 @@ Path PolygonElement::path() const
Path path; Path path;
path.moveTo(points[0].x, points[0].y); path.moveTo(points[0].x, points[0].y);
for(std::size_t i = 1;i < points.size();i++) for(std::size_t i = 1; i < points.size(); i++)
path.lineTo(points[i].x, points[i].y); path.lineTo(points[i].x, points[i].y);
path.close(); path.close();
@ -104,7 +104,7 @@ Path PolylineElement::path() const
Path path; Path path;
path.moveTo(points[0].x, points[0].y); path.moveTo(points[0].x, points[0].y);
for(std::size_t i = 1;i < points.size();i++) for(std::size_t i = 1; i < points.size(); i++)
path.lineTo(points[i].x, points[i].y); path.lineTo(points[i].x, points[i].y);
return path; return path;

View file

@ -7,8 +7,7 @@ namespace lunasvg {
class LayoutShape; class LayoutShape;
class GeometryElement : public GraphicsElement class GeometryElement : public GraphicsElement {
{
public: public:
GeometryElement(ElementID id); GeometryElement(ElementID id);
@ -17,8 +16,7 @@ public:
virtual Path path() const = 0; virtual Path path() const = 0;
}; };
class PathElement : public GeometryElement class PathElement : public GeometryElement {
{
public: public:
PathElement(); PathElement();
@ -28,16 +26,14 @@ public:
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;
}; };
class PolyElement : public GeometryElement class PolyElement : public GeometryElement {
{
public: public:
PolyElement(ElementID id); PolyElement(ElementID id);
PointList points() const; PointList points() const;
}; };
class PolygonElement : public PolyElement class PolygonElement : public PolyElement {
{
public: public:
PolygonElement(); PolygonElement();
@ -46,8 +42,7 @@ public:
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;
}; };
class PolylineElement : public PolyElement class PolylineElement : public PolyElement {
{
public: public:
PolylineElement(); PolylineElement();
@ -56,8 +51,7 @@ public:
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;
}; };
class CircleElement : public GeometryElement class CircleElement : public GeometryElement {
{
public: public:
CircleElement(); CircleElement();
@ -70,8 +64,7 @@ public:
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;
}; };
class EllipseElement : public GeometryElement class EllipseElement : public GeometryElement {
{
public: public:
EllipseElement(); EllipseElement();
@ -85,8 +78,7 @@ public:
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;
}; };
class LineElement : public GeometryElement class LineElement : public GeometryElement {
{
public: public:
LineElement(); LineElement();
@ -100,8 +92,7 @@ public:
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;
}; };
class RectElement : public GeometryElement class RectElement : public GeometryElement {
{
public: public:
RectElement(); RectElement();

View file

@ -43,8 +43,7 @@ const Rect& LayoutContainer::fillBoundingBox() const
if(m_fillBoundingBox.valid()) if(m_fillBoundingBox.valid())
return m_fillBoundingBox; return m_fillBoundingBox;
for(const auto& child : children) for(const auto& child : children) {
{
if(child->isHidden()) if(child->isHidden())
continue; continue;
m_fillBoundingBox.unite(child->map(child->fillBoundingBox())); m_fillBoundingBox.unite(child->map(child->fillBoundingBox()));
@ -58,8 +57,7 @@ const Rect& LayoutContainer::strokeBoundingBox() const
if(m_strokeBoundingBox.valid()) if(m_strokeBoundingBox.valid())
return m_strokeBoundingBox; return m_strokeBoundingBox;
for(const auto& child : children) for(const auto& child : children) {
{
if(child->isHidden()) if(child->isHidden())
continue; continue;
m_strokeBoundingBox.unite(child->map(child->strokeBoundingBox())); m_strokeBoundingBox.unite(child->map(child->strokeBoundingBox()));
@ -78,14 +76,14 @@ LayoutObject* LayoutContainer::addChildIfNotEmpty(std::unique_ptr<LayoutContaine
{ {
if(child->children.empty()) if(child->children.empty())
return nullptr; return nullptr;
return addChild(std::move(child)); return addChild(std::move(child));
} }
void LayoutContainer::renderChildren(RenderState& state) const void LayoutContainer::renderChildren(RenderState& state) const
{ {
for(const auto& child : children) for(const auto& child : children) {
child->render(state); child->render(state);
}
} }
LayoutClipPath::LayoutClipPath() LayoutClipPath::LayoutClipPath()
@ -98,8 +96,7 @@ void LayoutClipPath::apply(RenderState& state) const
RenderState newState(this, RenderMode::Clipping); RenderState newState(this, RenderMode::Clipping);
newState.canvas = Canvas::create(state.canvas->box()); newState.canvas = Canvas::create(state.canvas->box());
newState.transform = transform * state.transform; newState.transform = transform * state.transform;
if(units == Units::ObjectBoundingBox) if(units == Units::ObjectBoundingBox) {
{
const auto& box = state.objectBoundingBox(); const auto& box = state.objectBoundingBox();
newState.transform.translate(box.x, box.y); newState.transform.translate(box.x, box.y);
newState.transform.scale(box.w, box.h); newState.transform.scale(box.w, box.h);
@ -118,8 +115,7 @@ LayoutMask::LayoutMask()
void LayoutMask::apply(RenderState& state) const void LayoutMask::apply(RenderState& state) const
{ {
Rect rect{x, y, width, height}; Rect rect{x, y, width, height};
if(units == Units::ObjectBoundingBox) if(units == Units::ObjectBoundingBox) {
{
const auto& box = state.objectBoundingBox(); const auto& box = state.objectBoundingBox();
rect.x = rect.x * box.w + box.x; rect.x = rect.x * box.w + box.x;
rect.y = rect.y * box.h + box.y; rect.y = rect.y * box.h + box.y;
@ -130,8 +126,7 @@ void LayoutMask::apply(RenderState& state) const
RenderState newState(this, state.mode()); RenderState newState(this, state.mode());
newState.canvas = Canvas::create(state.canvas->box()); newState.canvas = Canvas::create(state.canvas->box());
newState.transform = state.transform; newState.transform = state.transform;
if(contentUnits == Units::ObjectBoundingBox) if(contentUnits == Units::ObjectBoundingBox) {
{
const auto& box = state.objectBoundingBox(); const auto& box = state.objectBoundingBox();
newState.transform.translate(box.x, box.y); newState.transform.translate(box.x, box.y);
newState.transform.scale(box.w, box.h); newState.transform.scale(box.w, box.h);
@ -230,8 +225,7 @@ LayoutPattern::LayoutPattern()
void LayoutPattern::apply(RenderState& state) const void LayoutPattern::apply(RenderState& state) const
{ {
Rect rect{x, y, width, height}; Rect rect{x, y, width, height};
if(units == Units::ObjectBoundingBox) if(units == Units::ObjectBoundingBox) {
{
const auto& box = state.objectBoundingBox(); const auto& box = state.objectBoundingBox();
rect.x = rect.x * box.w + box.x; rect.x = rect.x * box.w + box.x;
rect.y = rect.y * box.h + box.y; rect.y = rect.y * box.h + box.y;
@ -250,13 +244,10 @@ void LayoutPattern::apply(RenderState& state) const
newState.canvas = Canvas::create(0, 0, width, height); newState.canvas = Canvas::create(0, 0, width, height);
newState.transform = Transform::scaled(scalex, scaley); newState.transform = Transform::scaled(scalex, scaley);
if(viewBox.valid()) if(viewBox.valid()) {
{
auto viewTransform = preserveAspectRatio.getMatrix(rect.w, rect.h, viewBox); auto viewTransform = preserveAspectRatio.getMatrix(rect.w, rect.h, viewBox);
newState.transform.premultiply(viewTransform); newState.transform.premultiply(viewTransform);
} } else if(contentUnits == Units::ObjectBoundingBox) {
else if(contentUnits == Units::ObjectBoundingBox)
{
const auto& box = state.objectBoundingBox(); const auto& box = state.objectBoundingBox();
newState.transform.scale(box.w, box.h); newState.transform.scale(box.w, box.h);
} }
@ -282,8 +273,7 @@ LayoutLinearGradient::LayoutLinearGradient()
void LayoutLinearGradient::apply(RenderState& state) const void LayoutLinearGradient::apply(RenderState& state) const
{ {
auto transform = this->transform; auto transform = this->transform;
if(units == Units::ObjectBoundingBox) if(units == Units::ObjectBoundingBox) {
{
const auto& box = state.objectBoundingBox(); const auto& box = state.objectBoundingBox();
transform *= Transform(box.w, 0, 0, box.h, box.x, box.y); transform *= Transform(box.w, 0, 0, box.h, box.x, box.y);
} }
@ -299,8 +289,7 @@ LayoutRadialGradient::LayoutRadialGradient()
void LayoutRadialGradient::apply(RenderState& state) const void LayoutRadialGradient::apply(RenderState& state) const
{ {
auto transform = this->transform; auto transform = this->transform;
if(units == Units::ObjectBoundingBox) if(units == Units::ObjectBoundingBox) {
{
const auto& box = state.objectBoundingBox(); const auto& box = state.objectBoundingBox();
transform *= Transform(box.w, 0, 0, box.h, box.x, box.y); transform *= Transform(box.w, 0, 0, box.h, box.x, box.y);
} }
@ -378,14 +367,16 @@ void MarkerData::add(const LayoutMarker* marker, const Point& origin, double ang
void MarkerData::render(RenderState& state) const void MarkerData::render(RenderState& state) const
{ {
for(const auto& position : positions) for(const auto& position : positions) {
position.marker->renderMarker(state, position.origin, position.angle, strokeWidth); position.marker->renderMarker(state, position.origin, position.angle, strokeWidth);
}
} }
void MarkerData::inflate(Rect& box) const void MarkerData::inflate(Rect& box) const
{ {
for(const auto& position : positions) for(const auto& position : positions) {
box.unite(position.marker->markerBoundingBox(position.origin, position.angle, strokeWidth)); box.unite(position.marker->markerBoundingBox(position.origin, position.angle, strokeWidth));
}
} }
LayoutShape::LayoutShape() LayoutShape::LayoutShape()
@ -403,14 +394,11 @@ void LayoutShape::render(RenderState& state) const
newState.transform = transform * state.transform; newState.transform = transform * state.transform;
newState.beginGroup(state, info); newState.beginGroup(state, info);
if(newState.mode() == RenderMode::Display) if(newState.mode() == RenderMode::Display) {
{
fillData.fill(newState, path); fillData.fill(newState, path);
strokeData.stroke(newState, path); strokeData.stroke(newState, path);
markerData.render(newState); markerData.render(newState);
} } else {
else
{
newState.canvas->setColor(Color::Black); newState.canvas->setColor(Color::Black);
newState.canvas->fill(path, newState.transform, clipRule, BlendMode::Src, 1.0); newState.canvas->fill(path, newState.transform, clipRule, BlendMode::Src, 1.0);
} }
@ -450,8 +438,8 @@ RenderState::RenderState(const LayoutObject* object, RenderMode mode)
void RenderState::beginGroup(RenderState& state, const BlendInfo& info) void RenderState::beginGroup(RenderState& state, const BlendInfo& info)
{ {
if(!info.clipper && !info.clip.valid() && (m_mode == RenderMode::Display && !(info.masker || info.opacity < 1.0))) if(!info.clipper && !info.clip.valid()
{ && (m_mode == RenderMode::Display && !(info.masker || info.opacity < 1.0))) {
canvas = state.canvas; canvas = state.canvas;
return; return;
} }
@ -494,7 +482,6 @@ LayoutObject* LayoutContext::getResourcesById(const std::string& id) const
auto it = m_resourcesCache.find(id); auto it = m_resourcesCache.find(id);
if(it == m_resourcesCache.end()) if(it == m_resourcesCache.end())
return nullptr; return nullptr;
return it->second; return it->second;
} }
@ -597,8 +584,7 @@ DashData LayoutContext::dashData(const StyledElement* element)
LengthContext lengthContex(element); LengthContext lengthContex(element);
DashArray dashes; DashArray dashes;
for(auto& dash : dasharray) for(auto& dash : dasharray) {
{
auto value = lengthContex.valueForLength(dash, LengthMode::Both); auto value = lengthContex.valueForLength(dash, LengthMode::Both);
dashes.push_back(value); dashes.push_back(value);
} }
@ -610,8 +596,7 @@ DashData LayoutContext::dashData(const StyledElement* element)
DashData dashData; DashData dashData;
dashData.array.resize(num_dash); dashData.array.resize(num_dash);
double sum = 0.0; double sum = 0.0;
for(std::size_t i = 0;i < num_dash;i++) for(std::size_t i = 0; i < num_dash; i++) {
{
dashData.array[i] = dashes[i % dashes.size()]; dashData.array[i] = dashes[i % dashes.size()];
sum += dashData.array[i]; sum += dashData.array[i];
} }
@ -623,7 +608,6 @@ DashData LayoutContext::dashData(const StyledElement* element)
dashData.offset = std::fmod(offset, sum); dashData.offset = std::fmod(offset, sum);
if(dashData.offset < 0.0) if(dashData.offset < 0.0)
dashData.offset += sum; dashData.offset += sum;
return dashData; return dashData;
} }
@ -669,8 +653,7 @@ MarkerData LayoutContext::markerData(const GeometryElement* element, const Path&
int index = 0; int index = 0;
std::array<Point, 3> points; std::array<Point, 3> points;
while(!it.isDone()) while(!it.isDone()) {
{
switch(it.currentSegment(points)) { switch(it.currentSegment(points)) {
case PathCommand::MoveTo: case PathCommand::MoveTo:
startPoint = points[0]; startPoint = points[0];
@ -699,22 +682,19 @@ MarkerData LayoutContext::markerData(const GeometryElement* element, const Path&
index += 1; index += 1;
it.next(); it.next();
if(!it.isDone() && (markerStart || markerMid)) if(!it.isDone() && (markerStart || markerMid)) {
{
it.currentSegment(points); it.currentSegment(points);
outslopePoints[0] = origin; outslopePoints[0] = origin;
outslopePoints[1] = points[0]; outslopePoints[1] = points[0];
if(index == 1 && markerStart) if(index == 1 && markerStart) {
{
Point slope{outslopePoints[1].x - outslopePoints[0].x, outslopePoints[1].y - outslopePoints[0].y}; Point slope{outslopePoints[1].x - outslopePoints[0].x, outslopePoints[1].y - outslopePoints[0].y};
auto angle = 180.0 * std::atan2(slope.y, slope.x) / pi; auto angle = 180.0 * std::atan2(slope.y, slope.x) / pi;
markerData.add(markerStart, origin, angle); markerData.add(markerStart, origin, angle);
} }
if(index > 1 && markerMid) if(index > 1 && markerMid) {
{
Point inslope{inslopePoints[1].x - inslopePoints[0].x, inslopePoints[1].y - inslopePoints[0].y}; Point inslope{inslopePoints[1].x - inslopePoints[0].x, inslopePoints[1].y - inslopePoints[0].y};
Point outslope{outslopePoints[1].x - outslopePoints[0].x, outslopePoints[1].y - outslopePoints[0].y}; Point outslope{outslopePoints[1].x - outslopePoints[0].x, outslopePoints[1].y - outslopePoints[0].y};
auto inangle = 180.0 * std::atan2(inslope.y, inslope.x) / pi; auto inangle = 180.0 * std::atan2(inslope.y, inslope.x) / pi;
@ -725,8 +705,7 @@ MarkerData LayoutContext::markerData(const GeometryElement* element, const Path&
} }
} }
if(it.isDone() && markerEnd) if(it.isDone() && markerEnd) {
{
Point slope{inslopePoints[1].x - inslopePoints[0].x, inslopePoints[1].y - inslopePoints[0].y}; Point slope{inslopePoints[1].x - inslopePoints[0].x, inslopePoints[1].y - inslopePoints[0].y};
auto angle = 180.0 * std::atan2(slope.y, slope.x) / pi; auto angle = 180.0 * std::atan2(slope.y, slope.x) / pi;

View file

@ -10,8 +10,7 @@
namespace lunasvg { namespace lunasvg {
enum class LayoutId enum class LayoutId {
{
Symbol, Symbol,
Group, Group,
Shape, Shape,
@ -26,8 +25,7 @@ enum class LayoutId
class RenderState; class RenderState;
class LayoutObject class LayoutObject {
{
public: public:
LayoutObject(LayoutId id); LayoutObject(LayoutId id);
virtual ~LayoutObject(); virtual ~LayoutObject();
@ -47,8 +45,7 @@ public:
using LayoutList = std::list<std::unique_ptr<LayoutObject>>; using LayoutList = std::list<std::unique_ptr<LayoutObject>>;
class LayoutContainer : public LayoutObject class LayoutContainer : public LayoutObject {
{
public: public:
LayoutContainer(LayoutId id); LayoutContainer(LayoutId id);
@ -67,8 +64,7 @@ protected:
mutable Rect m_strokeBoundingBox{Rect::Invalid}; mutable Rect m_strokeBoundingBox{Rect::Invalid};
}; };
class LayoutClipPath : public LayoutContainer class LayoutClipPath : public LayoutContainer {
{
public: public:
LayoutClipPath(); LayoutClipPath();
@ -80,8 +76,7 @@ public:
const LayoutClipPath* clipper; const LayoutClipPath* clipper;
}; };
class LayoutMask : public LayoutContainer class LayoutMask : public LayoutContainer {
{
public: public:
LayoutMask(); LayoutMask();
@ -99,8 +94,7 @@ public:
const LayoutClipPath* clipper; const LayoutClipPath* clipper;
}; };
class LayoutSymbol : public LayoutContainer class LayoutSymbol : public LayoutContainer {
{
public: public:
LayoutSymbol(); LayoutSymbol();
@ -117,8 +111,7 @@ public:
const LayoutClipPath* clipper; const LayoutClipPath* clipper;
}; };
class LayoutGroup : public LayoutContainer class LayoutGroup : public LayoutContainer {
{
public: public:
LayoutGroup(); LayoutGroup();
@ -132,8 +125,7 @@ public:
const LayoutClipPath* clipper; const LayoutClipPath* clipper;
}; };
class LayoutMarker : public LayoutContainer class LayoutMarker : public LayoutContainer {
{
public: public:
LayoutMarker(); LayoutMarker();
@ -153,8 +145,7 @@ public:
const LayoutClipPath* clipper; const LayoutClipPath* clipper;
}; };
class LayoutPattern : public LayoutContainer class LayoutPattern : public LayoutContainer {
{
public: public:
LayoutPattern(); LayoutPattern();
@ -172,8 +163,7 @@ public:
PreserveAspectRatio preserveAspectRatio; PreserveAspectRatio preserveAspectRatio;
}; };
class LayoutGradient : public LayoutObject class LayoutGradient : public LayoutObject {
{
public: public:
LayoutGradient(LayoutId id); LayoutGradient(LayoutId id);
@ -184,8 +174,7 @@ public:
GradientStops stops; GradientStops stops;
}; };
class LayoutLinearGradient : public LayoutGradient class LayoutLinearGradient : public LayoutGradient {
{
public: public:
LayoutLinearGradient(); LayoutLinearGradient();
@ -198,8 +187,7 @@ public:
double y2; double y2;
}; };
class LayoutRadialGradient : public LayoutGradient class LayoutRadialGradient : public LayoutGradient {
{
public: public:
LayoutRadialGradient(); LayoutRadialGradient();
@ -213,8 +201,7 @@ public:
double fy; double fy;
}; };
class LayoutSolidColor : public LayoutObject class LayoutSolidColor : public LayoutObject {
{
public: public:
LayoutSolidColor(); LayoutSolidColor();
@ -224,8 +211,7 @@ public:
Color color; Color color;
}; };
class FillData class FillData {
{
public: public:
FillData() = default; FillData() = default;
@ -238,8 +224,7 @@ public:
WindRule fillRule{WindRule::NonZero}; WindRule fillRule{WindRule::NonZero};
}; };
class StrokeData class StrokeData {
{
public: public:
StrokeData() = default; StrokeData() = default;
@ -257,8 +242,7 @@ public:
DashData dash; DashData dash;
}; };
class MarkerPosition class MarkerPosition {
{
public: public:
MarkerPosition(const LayoutMarker* marker, const Point& origin, double angle); MarkerPosition(const LayoutMarker* marker, const Point& origin, double angle);
@ -270,8 +254,7 @@ public:
using MarkerPositionList = std::vector<MarkerPosition>; using MarkerPositionList = std::vector<MarkerPosition>;
class MarkerData class MarkerData {
{
public: public:
MarkerData() = default; MarkerData() = default;
@ -284,8 +267,7 @@ public:
double strokeWidth{1}; double strokeWidth{1};
}; };
class LayoutShape : public LayoutObject class LayoutShape : public LayoutObject {
{
public: public:
LayoutShape(); LayoutShape();
@ -311,22 +293,19 @@ private:
mutable Rect m_strokeBoundingBox{Rect::Invalid}; mutable Rect m_strokeBoundingBox{Rect::Invalid};
}; };
enum class RenderMode enum class RenderMode {
{
Display, Display,
Clipping Clipping
}; };
struct BlendInfo struct BlendInfo {
{
const LayoutClipPath* clipper; const LayoutClipPath* clipper;
const LayoutMask* masker; const LayoutMask* masker;
double opacity; double opacity;
Rect clip; Rect clip;
}; };
class RenderState class RenderState {
{
public: public:
RenderState(const LayoutObject* object, RenderMode mode); RenderState(const LayoutObject* object, RenderMode mode);
@ -350,8 +329,7 @@ class TreeBuilder;
class StyledElement; class StyledElement;
class GeometryElement; class GeometryElement;
class LayoutContext class LayoutContext {
{
public: public:
LayoutContext(const TreeBuilder* builder, LayoutSymbol* root); LayoutContext(const TreeBuilder* builder, LayoutSymbol* root);
@ -379,8 +357,7 @@ private:
std::set<const Element*> m_references; std::set<const Element*> m_references;
}; };
class LayoutBreaker class LayoutBreaker {
{
public: public:
LayoutBreaker(LayoutContext* context, const Element* element); LayoutBreaker(LayoutContext* context, const Element* element);
~LayoutBreaker(); ~LayoutBreaker();

View file

@ -8,8 +8,7 @@
namespace lunasvg { namespace lunasvg {
struct Bitmap::Impl struct Bitmap::Impl {
{
Impl(std::uint8_t* data, std::uint32_t width, std::uint32_t height, std::uint32_t stride); Impl(std::uint8_t* data, std::uint32_t width, std::uint32_t height, std::uint32_t stride);
Impl(std::uint32_t width, std::uint32_t height); Impl(std::uint32_t width, std::uint32_t height);
@ -56,7 +55,11 @@ void Bitmap::reset(std::uint32_t width, std::uint32_t height)
std::uint8_t* Bitmap::data() const std::uint8_t* Bitmap::data() const
{ {
return m_impl ? m_impl->data ? m_impl->data : m_impl->ownData.get() : nullptr; if(m_impl == nullptr)
return nullptr;
if(m_impl->data == nullptr)
return m_impl->ownData.get();
return m_impl->data;
} }
std::uint32_t Bitmap::width() const std::uint32_t Bitmap::width() const
@ -90,17 +93,16 @@ void Bitmap::clear(std::uint32_t color)
auto stride = this->stride(); auto stride = this->stride();
auto rowData = this->data(); auto rowData = this->data();
for(std::uint32_t y = 0;y < height;y++) for(std::uint32_t y = 0; y < height; y++) {
{
auto data = rowData; auto data = rowData;
for(std::uint32_t x = 0;x < width;x++) for(std::uint32_t x = 0; x < width; x++) {
{
data[0] = pb; data[0] = pb;
data[1] = pg; data[1] = pg;
data[2] = pr; data[2] = pr;
data[3] = a; data[3] = a;
data += 4; data += 4;
} }
rowData += stride; rowData += stride;
} }
} }
@ -112,18 +114,15 @@ void Bitmap::convert(int ri, int gi, int bi, int ai, bool unpremultiply)
auto stride = this->stride(); auto stride = this->stride();
auto rowData = this->data(); auto rowData = this->data();
for(std::uint32_t y = 0;y < height;y++) for(std::uint32_t y = 0; y < height; y++) {
{
auto data = rowData; auto data = rowData;
for(std::uint32_t x = 0;x < width;x++) for(std::uint32_t x = 0; x < width; x++) {
{
auto b = data[0]; auto b = data[0];
auto g = data[1]; auto g = data[1];
auto r = data[2]; auto r = data[2];
auto a = data[3]; auto a = data[3];
if(unpremultiply && a != 0) if(unpremultiply && a != 0) {
{
r = (r * 255) / a; r = (r * 255) / a;
g = (g * 255) / a; g = (g * 255) / a;
b = (b * 255) / a; b = (b * 255) / a;
@ -135,6 +134,7 @@ void Bitmap::convert(int ri, int gi, int bi, int ai, bool unpremultiply)
data[ai] = a; data[ai] = a;
data += 4; data += 4;
} }
rowData += stride; rowData += stride;
} }
} }
@ -258,7 +258,7 @@ Matrix Matrix::rotated(double angle, double cx, double cy)
Matrix Matrix::scaled(double sx, double sy) Matrix Matrix::scaled(double sx, double sy)
{ {
return Transform::scaled(sx, sy);; return Transform::scaled(sx, sy);
} }
Matrix Matrix::sheared(double shx, double shy) Matrix Matrix::sheared(double shx, double shy)
@ -348,17 +348,12 @@ Bitmap Document::renderToBitmap(std::uint32_t width, std::uint32_t height, std::
if(root->width == 0.0 || root->height == 0.0) if(root->width == 0.0 || root->height == 0.0)
return Bitmap{}; return Bitmap{};
if(width == 0 && height == 0) if(width == 0 && height == 0) {
{
width = static_cast<std::uint32_t>(std::ceil(root->width)); width = static_cast<std::uint32_t>(std::ceil(root->width));
height = static_cast<std::uint32_t>(std::ceil(root->height)); height = static_cast<std::uint32_t>(std::ceil(root->height));
} } else if(width != 0 && height == 0) {
else if(width != 0 && height == 0)
{
height = static_cast<std::uint32_t>(std::ceil(width * root->height / root->width)); height = static_cast<std::uint32_t>(std::ceil(width * root->height / root->width));
} } else if(height != 0 && width == 0) {
else if(height != 0 && width == 0)
{
width = static_cast<std::uint32_t>(std::ceil(height * root->width / root->height)); width = static_cast<std::uint32_t>(std::ceil(height * root->width / root->height));
} }
@ -369,12 +364,8 @@ Bitmap Document::renderToBitmap(std::uint32_t width, std::uint32_t height, std::
return bitmap; return bitmap;
} }
Document::Document() Document::Document() = default;
{
}
Document::~Document() Document::~Document() = default;
{
}
} // namespace lunasvg } // namespace lunasvg

View file

@ -7,8 +7,7 @@ namespace lunasvg {
class LayoutMarker; class LayoutMarker;
class MarkerElement : public StyledElement class MarkerElement : public StyledElement {
{
public: public:
MarkerElement(); MarkerElement();

View file

@ -7,8 +7,7 @@ namespace lunasvg {
class LayoutMask; class LayoutMask;
class MaskElement : public StyledElement class MaskElement : public StyledElement {
{
public: public:
MaskElement(); MaskElement();

View file

@ -45,8 +45,7 @@ GradientStops GradientElement::buildGradientStops() const
{ {
GradientStops gradientStops; GradientStops gradientStops;
double prevOffset = 0.0; double prevOffset = 0.0;
for(auto& child : children) for(auto& child : children) {
{
if(child->isText()) if(child->isText())
continue; continue;
auto element = static_cast<Element*>(child.get()); auto element = static_cast<Element*>(child.get());
@ -96,8 +95,7 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
std::set<const GradientElement*> processedGradients; std::set<const GradientElement*> processedGradients;
const GradientElement* current = this; const GradientElement* current = this;
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))
@ -107,8 +105,7 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
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());
@ -126,8 +123,9 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
processedGradients.insert(current); processedGradients.insert(current);
current = static_cast<const GradientElement*>(ref); current = static_cast<const GradientElement*>(ref);
if(processedGradients.find(current) != processedGradients.end()) if(processedGradients.find(current) != processedGradients.end()) {
break; break;
}
} }
auto& stops = attributes.gradientStops(); auto& stops = attributes.gradientStops();
@ -139,8 +137,7 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
auto y1 = lengthContext.valueForLength(attributes.y1(), LengthMode::Height); auto y1 = lengthContext.valueForLength(attributes.y1(), LengthMode::Height);
auto x2 = lengthContext.valueForLength(attributes.x2(), LengthMode::Width); auto x2 = lengthContext.valueForLength(attributes.x2(), LengthMode::Width);
auto y2 = lengthContext.valueForLength(attributes.y2(), LengthMode::Height); auto y2 = lengthContext.valueForLength(attributes.y2(), LengthMode::Height);
if((x1 == x2 && y1 == y2) || stops.size() == 1) if((x1 == x2 && y1 == y2) || stops.size() == 1) {
{
auto solid = std::make_unique<LayoutSolidColor>(); auto solid = std::make_unique<LayoutSolidColor>();
solid->color = std::get<1>(stops.back()); solid->color = std::get<1>(stops.back());
return std::move(solid); return std::move(solid);
@ -204,8 +201,7 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
std::set<const GradientElement*> processedGradients; std::set<const GradientElement*> processedGradients;
const GradientElement* current = this; const GradientElement* current = this;
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))
@ -215,8 +211,7 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
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());
@ -236,8 +231,9 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
processedGradients.insert(current); processedGradients.insert(current);
current = static_cast<const GradientElement*>(ref); current = static_cast<const GradientElement*>(ref);
if(processedGradients.find(current) != processedGradients.end()) if(processedGradients.find(current) != processedGradients.end()) {
break; break;
}
} }
if(!attributes.hasFx()) if(!attributes.hasFx())
@ -250,8 +246,7 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
return nullptr; return nullptr;
auto& r = attributes.r(); auto& r = attributes.r();
if(r.isZero() || stops.size() == 1) if(r.isZero() || stops.size() == 1) {
{
auto solid = std::make_unique<LayoutSolidColor>(); auto solid = std::make_unique<LayoutSolidColor>();
solid->color = std::get<1>(stops.back()); solid->color = std::get<1>(stops.back());
return std::move(solid); return std::move(solid);
@ -351,8 +346,7 @@ std::unique_ptr<LayoutObject> PatternElement::getPainter(LayoutContext* context)
std::set<const PatternElement*> processedPatterns; std::set<const PatternElement*> processedPatterns;
const PatternElement* current = this; const PatternElement* current = this;
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))
@ -380,8 +374,9 @@ std::unique_ptr<LayoutObject> PatternElement::getPainter(LayoutContext* context)
processedPatterns.insert(current); processedPatterns.insert(current);
current = static_cast<const PatternElement*>(ref); current = static_cast<const PatternElement*>(ref);
if(processedPatterns.find(current) != processedPatterns.end()) if(processedPatterns.find(current) != processedPatterns.end()) {
break; break;
}
} }
auto& width = attributes.width(); auto& width = attributes.width();

View file

@ -8,8 +8,7 @@ namespace lunasvg {
class LayoutObject; class LayoutObject;
class PaintElement : public StyledElement class PaintElement : public StyledElement {
{
public: public:
PaintElement(ElementID id); PaintElement(ElementID id);
@ -17,8 +16,7 @@ public:
virtual std::unique_ptr<LayoutObject> getPainter(LayoutContext* context) const = 0; virtual std::unique_ptr<LayoutObject> getPainter(LayoutContext* context) const = 0;
}; };
class GradientElement : public PaintElement class GradientElement : public PaintElement {
{
public: public:
GradientElement(ElementID id); GradientElement(ElementID id);
@ -29,8 +27,7 @@ public:
GradientStops buildGradientStops() const; GradientStops buildGradientStops() const;
}; };
class LinearGradientElement : public GradientElement class LinearGradientElement : public GradientElement {
{
public: public:
LinearGradientElement(); LinearGradientElement();
@ -43,8 +40,7 @@ public:
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;
}; };
class RadialGradientElement : public GradientElement class RadialGradientElement : public GradientElement {
{
public: public:
RadialGradientElement(); RadialGradientElement();
@ -58,8 +54,7 @@ public:
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;
}; };
class PatternElement : public PaintElement class PatternElement : public PaintElement {
{
public: public:
PatternElement(); PatternElement();
@ -79,8 +74,7 @@ public:
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;
}; };
class SolidColorElement : public PaintElement class SolidColorElement : public PaintElement {
{
public: public:
SolidColorElement(); SolidColorElement();
@ -88,8 +82,7 @@ public:
std::unique_ptr<Node> clone() const; std::unique_ptr<Node> clone() const;
}; };
class GradientAttributes class GradientAttributes {
{
public: public:
GradientAttributes() = default; GradientAttributes() = default;
@ -103,26 +96,22 @@ public:
bool hasGradientUnits() const { return m_hasGradientUnits; } bool hasGradientUnits() const { return m_hasGradientUnits; }
bool hasGradientStops() const { return m_hasGradientStops; } bool hasGradientStops() const { return m_hasGradientStops; }
void setGradientTransform(const Transform& gradientTransform) void setGradientTransform(const Transform& gradientTransform) {
{
m_gradientTransform = gradientTransform; m_gradientTransform = gradientTransform;
m_hasGradientTransform = true; m_hasGradientTransform = true;
} }
void setSpreadMethod(SpreadMethod spreadMethod) void setSpreadMethod(SpreadMethod spreadMethod) {
{
m_spreadMethod = spreadMethod; m_spreadMethod = spreadMethod;
m_hasSpreadMethod = true; m_hasSpreadMethod = true;
} }
void setGradientUnits(Units gradientUnits) void setGradientUnits(Units gradientUnits) {
{
m_gradientUnits = gradientUnits; m_gradientUnits = gradientUnits;
m_hasGradientUnits = true; m_hasGradientUnits = true;
} }
void setGradientStops(const GradientStops& gradientStops) void setGradientStops(const GradientStops& gradientStops) {
{
m_gradientStops = gradientStops; m_gradientStops = gradientStops;
m_hasGradientStops = gradientStops.size(); m_hasGradientStops = gradientStops.size();
} }
@ -139,8 +128,7 @@ private:
bool m_hasGradientStops{false}; bool m_hasGradientStops{false};
}; };
class LinearGradientAttributes : public GradientAttributes class LinearGradientAttributes : public GradientAttributes {
{
public: public:
LinearGradientAttributes() = default; LinearGradientAttributes() = default;
@ -154,26 +142,22 @@ public:
bool hasX2() const { return m_hasX2; } bool hasX2() const { return m_hasX2; }
bool hasY2() const { return m_hasY2; } bool hasY2() const { return m_hasY2; }
void setX1(const Length& x1) void setX1(const Length& x1) {
{
m_x1 = x1; m_x1 = x1;
m_hasX1 = true; m_hasX1 = true;
} }
void setY1(const Length& y1) void setY1(const Length& y1) {
{
m_y1 = y1; m_y1 = y1;
m_hasY1 = true; m_hasY1 = true;
} }
void setX2(const Length& x2) void setX2(const Length& x2) {
{
m_x2 = x2; m_x2 = x2;
m_hasX2 = true; m_hasX2 = true;
} }
void setY2(const Length& y2) void setY2(const Length& y2) {
{
m_y2 = y2; m_y2 = y2;
m_hasY2 = true; m_hasY2 = true;
} }
@ -190,8 +174,7 @@ private:
bool m_hasY2{false}; bool m_hasY2{false};
}; };
class RadialGradientAttributes : public GradientAttributes class RadialGradientAttributes : public GradientAttributes {
{
public: public:
RadialGradientAttributes() = default; RadialGradientAttributes() = default;
@ -207,32 +190,27 @@ public:
bool hasFx() const { return m_hasFx; } bool hasFx() const { return m_hasFx; }
bool hasFy() const { return m_hasFy; } bool hasFy() const { return m_hasFy; }
void setCx(const Length& cx) void setCx(const Length& cx) {
{
m_cx = cx; m_cx = cx;
m_hasCx = true; m_hasCx = true;
} }
void setCy(const Length& cy) void setCy(const Length& cy) {
{
m_cy = cy; m_cy = cy;
m_hasCy = true; m_hasCy = true;
} }
void setR(const Length& r) void setR(const Length& r) {
{
m_r = r; m_r = r;
m_hasR = true; m_hasR = true;
} }
void setFx(const Length& fx) void setFx(const Length& fx) {
{
m_fx = fx; m_fx = fx;
m_hasFx = true; m_hasFx = true;
} }
void setFy(const Length& fy) void setFy(const Length& fy) {
{
m_fy = fy; m_fy = fy;
m_hasFy = true; m_hasFy = true;
} }
@ -252,8 +230,7 @@ private:
bool m_hasFy{false}; bool m_hasFy{false};
}; };
class PatternAttributes class PatternAttributes {
{
public: public:
PatternAttributes() = default; PatternAttributes() = default;
@ -279,62 +256,52 @@ public:
bool hasPreserveAspectRatio() const { return m_hasPreserveAspectRatio; } bool hasPreserveAspectRatio() const { return m_hasPreserveAspectRatio; }
bool hasPatternContentElement() const { return m_hasPatternContentElement; } bool hasPatternContentElement() const { return m_hasPatternContentElement; }
void setX(const Length& x) void setX(const Length& x) {
{
m_x = x; m_x = x;
m_hasX = true; m_hasX = true;
} }
void setY(const Length& y) void setY(const Length& y) {
{
m_y = y; m_y = y;
m_hasY = true; m_hasY = true;
} }
void setWidth(const Length& width) void setWidth(const Length& width) {
{
m_width = width; m_width = width;
m_hasWidth = true; m_hasWidth = true;
} }
void setHeight(const Length& height) void setHeight(const Length& height) {
{
m_height = height; m_height = height;
m_hasHeight = true; m_hasHeight = true;
} }
void setPatternTransform(const Transform& patternTransform) void setPatternTransform(const Transform& patternTransform) {
{
m_patternTransform = patternTransform; m_patternTransform = patternTransform;
m_hasPatternTransform = true; m_hasPatternTransform = true;
} }
void setPatternUnits(Units patternUnits) void setPatternUnits(Units patternUnits) {
{
m_patternUnits = patternUnits; m_patternUnits = patternUnits;
m_hasPatternUnits = true; m_hasPatternUnits = true;
} }
void setPatternContentUnits(Units patternContentUnits) void setPatternContentUnits(Units patternContentUnits) {
{
m_patternContentUnits = patternContentUnits; m_patternContentUnits = patternContentUnits;
m_hasPatternContentUnits = true; m_hasPatternContentUnits = true;
} }
void setViewBox(const Rect& viewBox) void setViewBox(const Rect& viewBox) {
{
m_viewBox = viewBox; m_viewBox = viewBox;
m_hasViewBox = true; m_hasViewBox = true;
} }
void setPreserveAspectRatio(const PreserveAspectRatio& preserveAspectRatio) void setPreserveAspectRatio(const PreserveAspectRatio& preserveAspectRatio) {
{
m_preserveAspectRatio = preserveAspectRatio; m_preserveAspectRatio = preserveAspectRatio;
m_hasPreserveAspectRatio = true; m_hasPreserveAspectRatio = true;
} }
void setPatternContentElement(const PatternElement* patternContentElement) void setPatternContentElement(const PatternElement* patternContentElement) {
{
m_patternContentElement = patternContentElement; m_patternContentElement = patternContentElement;
m_hasPatternContentElement = true; m_hasPatternContentElement = true;
} }

File diff suppressed because it is too large Load diff

View file

@ -12,14 +12,12 @@ namespace lunasvg {
class SVGElement; class SVGElement;
class StyledElement; class StyledElement;
enum LengthNegativeValuesMode enum LengthNegativeValuesMode {
{
AllowNegativeLengths, AllowNegativeLengths,
ForbidNegativeLengths ForbidNegativeLengths
}; };
enum class TransformType enum class TransformType {
{
Matrix, Matrix,
Rotate, Rotate,
Scale, Scale,
@ -28,8 +26,7 @@ enum class TransformType
Translate Translate
}; };
class Parser class Parser {
{
public: public:
static Length parseLength(const std::string& string, LengthNegativeValuesMode mode, const Length& defaultValue); static Length parseLength(const std::string& string, LengthNegativeValuesMode mode, const Length& defaultValue);
static LengthList parseLengthList(const std::string& string, LengthNegativeValuesMode mode); static LengthList parseLengthList(const std::string& string, LengthNegativeValuesMode mode);
@ -69,10 +66,8 @@ struct SimpleSelector;
using Selector = std::vector<SimpleSelector>; using Selector = std::vector<SimpleSelector>;
using SelectorList = std::vector<Selector>; using SelectorList = std::vector<Selector>;
struct AttributeSelector struct AttributeSelector {
{ enum class MatchType {
enum class MatchType
{
None, None,
Equal, Equal,
Includes, Includes,
@ -87,10 +82,8 @@ struct AttributeSelector
std::string value; std::string value;
}; };
struct PseudoClassSelector struct PseudoClassSelector {
{ enum class Type {
enum class Type
{
Unknown, Unknown,
Empty, Empty,
Root, Root,
@ -105,15 +98,11 @@ struct PseudoClassSelector
}; };
Type type{Type::Unknown}; Type type{Type::Unknown};
int16_t a{0};
int16_t b{0};
SelectorList subSelectors; SelectorList subSelectors;
}; };
struct SimpleSelector struct SimpleSelector {
{ enum class Combinator {
enum class Combinator
{
Descendant, Descendant,
Child, Child,
DirectAdjacent, DirectAdjacent,
@ -126,33 +115,40 @@ struct SimpleSelector
std::vector<PseudoClassSelector> pseudoClassSelectors; std::vector<PseudoClassSelector> pseudoClassSelectors;
}; };
struct Rule struct Declaration {
{ int specificity;
PropertyID id;
std::string value;
};
using DeclarationList = std::vector<Declaration>;
struct Rule {
SelectorList selectors; SelectorList selectors;
PropertyList declarations; DeclarationList declarations;
}; };
class RuleData { class RuleData {
public: public:
RuleData(const Selector& selector, const PropertyList& properties, uint32_t specificity, uint32_t position) RuleData(const Selector& selector, const DeclarationList& declarations, uint32_t specificity, uint32_t position)
: m_selector(selector), m_properties(properties), m_specificity(specificity), m_position(position) : m_selector(selector), m_declarations(declarations), m_specificity(specificity), m_position(position)
{} {}
const Selector& selector() const { return m_selector; } const Selector& selector() const { return m_selector; }
const PropertyList& properties() const { return m_properties; } const DeclarationList& declarations() const { return m_declarations; }
const uint32_t& specificity() const { return m_specificity; } const uint32_t& specificity() const { return m_specificity; }
const uint32_t& position() const { return m_position; } const uint32_t& position() const { return m_position; }
bool match(const Element* element) const; bool match(const Element* element) const;
private: private:
bool matchSimpleSelector(const SimpleSelector& selector, const Element* element) const; static bool matchSimpleSelector(const SimpleSelector& selector, const Element* element);
bool matchAttributeSelector(const AttributeSelector& selector, const Element* element) const; static bool matchAttributeSelector(const AttributeSelector& selector, const Element* element);
bool matchPseudoClassSelector(const PseudoClassSelector& selector, const Element* element) const; static bool matchPseudoClassSelector(const PseudoClassSelector& selector, const Element* element);
private: private:
Selector m_selector; Selector m_selector;
PropertyList m_properties; DeclarationList m_declarations;
uint32_t m_specificity; uint32_t m_specificity;
uint32_t m_position; uint32_t m_position;
}; };
@ -164,31 +160,23 @@ class StyleSheet {
public: public:
StyleSheet() = default; StyleSheet() = default;
void parse(const std::string& content); bool parse(const std::string& content);
void add(const Rule& rule); void add(const Rule& rule);
bool empty() const { return m_position == 0; } bool empty() const { return m_rules.empty(); }
std::vector<const PropertyList*> match(const Element* element) const; const std::multiset<RuleData>& rules() const { return m_rules; }
private:
std::multiset<RuleData> m_rules;
uint32_t m_position{0};
};
class CSSParser
{
public:
CSSParser() = default;
static bool parseSheet(StyleSheet* sheet, const std::string& value);
private: private:
static bool parseAtRule(const char*& ptr, const char* end); static bool parseAtRule(const char*& ptr, const char* end);
static bool parseRule(const char*& ptr, const char* end, Rule& rule); static bool parseRule(const char*& ptr, const char* end, Rule& rule);
static bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors); static bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors);
static bool parseDeclarations(const char*& ptr, const char* end, PropertyList& declarations); static bool parseDeclarations(const char*& ptr, const char* end, DeclarationList& declarations);
static bool parseSelector(const char*& ptr, const char* end, Selector& selector); static bool parseSelector(const char*& ptr, const char* end, Selector& selector);
static bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector); static bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector);
private:
std::multiset<RuleData> m_rules;
uint32_t m_position{0};
}; };
class LayoutSymbol; class LayoutSymbol;

View file

@ -43,10 +43,8 @@ inline bool skipDesc(const char*& ptr, const char* end, const char ch)
inline bool skipDesc(const char*& ptr, const char* end, const char* data) inline bool skipDesc(const char*& ptr, const char* end, const char* data)
{ {
int read = 0; int read = 0;
while(data[read]) while(data[read]) {
{ if(ptr >= end || *ptr != data[read]) {
if(ptr >= end || *ptr != data[read])
{
ptr -= read; ptr -= read;
return false; return false;
} }
@ -68,8 +66,7 @@ inline bool skipUntil(const char*& ptr, const char* end, const char ch)
inline bool skipUntil(const char*& ptr, const char* end, const char* data) inline bool skipUntil(const char*& ptr, const char* end, const char* data)
{ {
while(ptr < end) while(ptr < end) {
{
auto start = ptr; auto start = ptr;
if(skipDesc(start, end, data)) if(skipDesc(start, end, data))
break; break;
@ -112,10 +109,8 @@ inline bool skipWsDelimiter(const char*& ptr, const char* end, const char delimi
if(ptr < end && !IS_WS(*ptr) && *ptr != delimiter) if(ptr < end && !IS_WS(*ptr) && *ptr != delimiter)
return false; return false;
if(skipWs(ptr, end)) if(skipWs(ptr, end)) {
{ if(ptr < end && *ptr == delimiter) {
if(ptr < end && *ptr == delimiter)
{
++ptr; ++ptr;
skipWs(ptr, end); skipWs(ptr, end);
} }
@ -153,8 +148,7 @@ inline bool parseInteger(const char*& ptr, const char* end, T& integer, int base
if(ptr < end && *ptr == '+') if(ptr < end && *ptr == '+')
++ptr; ++ptr;
else if(ptr < end && isSigned && *ptr == '-') else if(ptr < end && isSigned && *ptr == '-') {
{
++ptr; ++ptr;
isNegative = true; isNegative = true;
} }
@ -200,8 +194,7 @@ inline bool parseNumber(const char*& ptr, const char* end, T& number)
if(ptr < end && *ptr == '+') if(ptr < end && *ptr == '+')
++ptr; ++ptr;
else if(ptr < end && *ptr == '-') else if(ptr < end && *ptr == '-') {
{
++ptr; ++ptr;
sign = -1; sign = -1;
} }
@ -209,16 +202,14 @@ inline bool parseNumber(const char*& ptr, const char* end, T& number)
if(ptr >= end || !(IS_NUM(*ptr) || *ptr == '.')) if(ptr >= end || !(IS_NUM(*ptr) || *ptr == '.'))
return false; return false;
if(*ptr != '.') if(*ptr != '.') {
{
do { do {
integer = static_cast<T>(10) * integer + (*ptr - '0'); integer = static_cast<T>(10) * integer + (*ptr - '0');
++ptr; ++ptr;
} while(ptr < end && IS_NUM(*ptr)); } while(ptr < end && IS_NUM(*ptr));
} }
if(ptr < end && *ptr == '.') if(ptr < end && *ptr == '.') {
{
++ptr; ++ptr;
if(ptr >= end || !IS_NUM(*ptr)) if(ptr >= end || !IS_NUM(*ptr))
return false; return false;
@ -238,8 +229,7 @@ inline bool parseNumber(const char*& ptr, const char* end, T& number)
++ptr; ++ptr;
if(ptr < end && *ptr == '+') if(ptr < end && *ptr == '+')
++ptr; ++ptr;
else if(ptr < end && *ptr == '-') else if(ptr < end && *ptr == '-') {
{
++ptr; ++ptr;
expsign = -1; expsign = -1;
} }

View file

@ -238,8 +238,7 @@ Rect Transform::map(const Rect& rect) const
auto r = p[0].x; auto r = p[0].x;
auto b = p[0].y; auto b = p[0].y;
for(int i = 1;i < 4;i++) for(int i = 1; i < 4; i++) {
{
if(p[i].x < l) l = p[i].x; if(p[i].x < l) l = p[i].x;
if(p[i].x > r) r = p[i].x; if(p[i].x > r) r = p[i].x;
if(p[i].y < t) t = p[i].y; if(p[i].y < t) t = p[i].y;
@ -356,8 +355,7 @@ void Path::arcTo(double cx, double cy, double rx, double ry, double xAxisRotatio
auto Px = dx1 * dx1; auto Px = dx1 * dx1;
auto Py = dy1 * dy1; auto Py = dy1 * dy1;
auto check = Px / Pr1 + Py / Pr2; auto check = Px / Pr1 + Py / Pr2;
if(check > 1) if(check > 1) {
{
rx = rx * std::sqrt(check); rx = rx * std::sqrt(check);
ry = ry * std::sqrt(check); ry = ry * std::sqrt(check);
} }
@ -388,8 +386,7 @@ void Path::arcTo(double cx, double cy, double rx, double ry, double xAxisRotatio
th_arc -= 2.0 * pi; th_arc -= 2.0 * pi;
auto n_segs = static_cast<int>(std::ceil(std::fabs(th_arc / (pi * 0.5 + 0.001)))); auto n_segs = static_cast<int>(std::ceil(std::fabs(th_arc / (pi * 0.5 + 0.001))));
for(int i = 0;i < n_segs;i++) for(int i = 0; i < n_segs; i++) {
{
auto th2 = th0 + i * th_arc / n_segs; auto th2 = th0 + i * th_arc / n_segs;
auto th3 = th0 + (i + 1) * th_arc / n_segs; auto th3 = th0 + (i + 1) * th_arc / n_segs;
@ -445,17 +442,14 @@ void Path::rect(double x, double y, double w, double h, double rx, double ry)
auto right = x + w; auto right = x + w;
auto bottom = y + h; auto bottom = y + h;
if(rx == 0.0 && ry == 0.0) if(rx == 0.0 && ry == 0.0) {
{
moveTo(x, y); moveTo(x, y);
lineTo(right, y); lineTo(right, y);
lineTo(right, bottom); lineTo(right, bottom);
lineTo(x, bottom); lineTo(x, bottom);
lineTo(x, y); lineTo(x, y);
close(); close();
} } else {
else
{
double cpx = rx * kappa; double cpx = rx * kappa;
double cpy = ry * kappa; double cpy = ry * kappa;
moveTo(x, y+ry); moveTo(x, y+ry);
@ -481,8 +475,7 @@ Rect Path::box() const
auto r = m_points[0].x; auto r = m_points[0].x;
auto b = m_points[0].y; auto b = m_points[0].y;
for(std::size_t i = 1;i < m_points.size();i++) for(std::size_t i = 1; i < m_points.size(); i++) {
{
if(m_points[i].x < l) l = m_points[i].x; if(m_points[i].x < l) l = m_points[i].x;
if(m_points[i].x > r) r = m_points[i].x; if(m_points[i].x > r) r = m_points[i].x;
if(m_points[i].y < t) t = m_points[i].y; if(m_points[i].y < t) t = m_points[i].y;
@ -594,8 +587,7 @@ static const double sqrt2 = 1.41421356237309504880;
double Length::value(const Element* element, LengthMode mode) const double Length::value(const Element* element, LengthMode mode) const
{ {
if(m_units == LengthUnits::Percent) if(m_units == LengthUnits::Percent) {
{
auto viewport = element->currentViewport(); auto viewport = element->currentViewport();
auto w = viewport.w; auto w = viewport.w;
auto h = viewport.h; auto h = viewport.h;
@ -635,8 +627,7 @@ Transform PreserveAspectRatio::getMatrix(double width, double height, const Rect
auto xscale = width / viewBox.w; auto xscale = width / viewBox.w;
auto yscale = height / viewBox.h; auto yscale = height / viewBox.h;
if(m_align == Align::None) if(m_align == Align::None) {
{
auto xoffset = -viewBox.x * xscale; auto xoffset = -viewBox.x * xscale;
auto yoffset = -viewBox.y * yscale; auto yoffset = -viewBox.y * yscale;
return Transform{xscale, 0, 0, yscale, xoffset, yoffset}; return Transform{xscale, 0, 0, yscale, xoffset, yoffset};

View file

@ -8,65 +8,55 @@
namespace lunasvg { namespace lunasvg {
enum class Display enum class Display {
{
Inline, Inline,
None None
}; };
enum class Visibility enum class Visibility {
{
Visible, Visible,
Hidden Hidden
}; };
enum class Overflow enum class Overflow {
{
Visible, Visible,
Hidden Hidden
}; };
enum class LineCap enum class LineCap {
{
Butt, Butt,
Round, Round,
Square Square
}; };
enum class LineJoin enum class LineJoin {
{
Miter, Miter,
Round, Round,
Bevel Bevel
}; };
enum class WindRule enum class WindRule {
{
NonZero, NonZero,
EvenOdd EvenOdd
}; };
enum class Units enum class Units {
{
UserSpaceOnUse, UserSpaceOnUse,
ObjectBoundingBox ObjectBoundingBox
}; };
enum class SpreadMethod enum class SpreadMethod {
{
Pad, Pad,
Reflect, Reflect,
Repeat Repeat
}; };
enum class MarkerUnits enum class MarkerUnits {
{
StrokeWidth, StrokeWidth,
UserSpaceOnUse UserSpaceOnUse
}; };
class Color class Color {
{
public: public:
Color() = default; Color() = default;
explicit Color(uint32_t value) : m_value(value) {} explicit Color(uint32_t value) : m_value(value) {}
@ -92,8 +82,7 @@ private:
uint32_t m_value{0}; uint32_t m_value{0};
}; };
class Paint class Paint {
{
public: public:
Paint() = default; Paint() = default;
Paint(const Color& color); Paint(const Color& color);
@ -108,8 +97,7 @@ public:
Color m_color{Color::Transparent}; Color m_color{Color::Transparent};
}; };
class Point class Point {
{
public: public:
Point() = default; Point() = default;
Point(double x, double y); Point(double x, double y);
@ -123,8 +111,7 @@ using PointList = std::vector<Point>;
class Box; class Box;
class Rect class Rect {
{
public: public:
Rect() = default; Rect() = default;
Rect(double x, double y, double w, double h); Rect(double x, double y, double w, double h);
@ -151,8 +138,7 @@ public:
class Matrix; class Matrix;
class Transform class Transform {
{
public: public:
Transform() = default; Transform() = default;
Transform(double m00, double m10, double m01, double m11, double m02, double m12); Transform(double m00, double m10, double m01, double m11, double m02, double m12);
@ -193,16 +179,14 @@ public:
double m12{0}; double m12{0};
}; };
enum class PathCommand enum class PathCommand {
{
MoveTo, MoveTo,
LineTo, LineTo,
CubicTo, CubicTo,
Close Close
}; };
class Path class Path {
{
public: public:
Path() = default; Path() = default;
@ -229,8 +213,7 @@ private:
std::vector<Point> m_points; std::vector<Point> m_points;
}; };
class PathIterator class PathIterator {
{
public: public:
PathIterator(const Path& path); PathIterator(const Path& path);
@ -245,8 +228,7 @@ private:
unsigned int m_index{0}; unsigned int m_index{0};
}; };
enum class LengthUnits enum class LengthUnits {
{
Unknown, Unknown,
Number, Number,
Px, Px,
@ -260,8 +242,7 @@ enum class LengthUnits
Percent Percent
}; };
enum LengthMode enum LengthMode {
{
Width, Width,
Height, Height,
Both Both
@ -269,8 +250,7 @@ enum LengthMode
class Element; class Element;
class Length class Length {
{
public: public:
Length() = default; Length() = default;
Length(double value); Length(double value);
@ -299,8 +279,7 @@ private:
using LengthList = std::vector<Length>; using LengthList = std::vector<Length>;
class LengthContext class LengthContext {
{
public: public:
LengthContext(const Element* element); LengthContext(const Element* element);
LengthContext(const Element* element, Units units); LengthContext(const Element* element, Units units);
@ -312,8 +291,7 @@ private:
Units m_units{Units::UserSpaceOnUse}; Units m_units{Units::UserSpaceOnUse};
}; };
enum class Align enum class Align {
{
None, None,
xMinYMin, xMinYMin,
xMidYMin, xMidYMin,
@ -326,14 +304,12 @@ enum class Align
xMaxYMax xMaxYMax
}; };
enum class MeetOrSlice enum class MeetOrSlice {
{
Meet, Meet,
Slice Slice
}; };
class PreserveAspectRatio class PreserveAspectRatio {
{
public: public:
PreserveAspectRatio() = default; PreserveAspectRatio() = default;
PreserveAspectRatio(Align align, MeetOrSlice scale); PreserveAspectRatio(Align align, MeetOrSlice scale);
@ -349,14 +325,12 @@ private:
MeetOrSlice m_scale{MeetOrSlice::Meet}; MeetOrSlice m_scale{MeetOrSlice::Meet};
}; };
enum class MarkerOrient enum class MarkerOrient {
{
Auto, Auto,
Angle Angle
}; };
class Angle class Angle {
{
public: public:
Angle() = default; Angle() = default;
Angle(MarkerOrient type); Angle(MarkerOrient type);

View file

@ -5,8 +5,7 @@
namespace lunasvg { namespace lunasvg {
class StopElement : public StyledElement class StopElement : public StyledElement {
{
public: public:
StopElement(); StopElement();

View file

@ -5,8 +5,7 @@
namespace lunasvg { namespace lunasvg {
class StyledElement : public Element class StyledElement : public Element {
{
public: public:
StyledElement(ElementID id); StyledElement(ElementID id);

View file

@ -5,8 +5,7 @@
namespace lunasvg { namespace lunasvg {
class StyleElement : public Element class StyleElement : public Element {
{
public: public:
StyleElement(); StyleElement();

View file

@ -8,8 +8,7 @@ namespace lunasvg {
class TreeBuilder; class TreeBuilder;
class LayoutSymbol; class LayoutSymbol;
class SVGElement : public GraphicsElement class SVGElement : public GraphicsElement {
{
public: public:
SVGElement(); SVGElement();

View file

@ -5,8 +5,7 @@
namespace lunasvg { namespace lunasvg {
class SymbolElement : public StyledElement class SymbolElement : public StyledElement {
{
public: public:
SymbolElement(); SymbolElement();

View file

@ -77,14 +77,11 @@ void UseElement::layout(LayoutContext* context, LayoutContainer* current) const
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());
group->addChild(std::move(element)); group->addChild(std::move(element));
} } else {
else
{
group->addChild(ref->clone()); group->addChild(ref->clone());
} }

View file

@ -5,8 +5,7 @@
namespace lunasvg { namespace lunasvg {
class UseElement : public GraphicsElement class UseElement : public GraphicsElement {
{
public: public:
UseElement(); UseElement();