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_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(LUNASVG_BUILD_EXAMPLES "Builds examples" OFF)
@ -19,61 +14,25 @@ add_subdirectory(include)
add_subdirectory(source)
add_subdirectory(3rdparty/plutovg)
set_target_properties(lunasvg
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
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)
if(BUILD_SHARED_LIBS)
target_compile_definitions(lunasvg PUBLIC LUNASVG_SHARED)
target_compile_definitions(lunasvg PRIVATE LUNASVG_EXPORT)
endif()
if(LUNASVG_BUILD_EXAMPLES)
add_subdirectory(example)
endif()
#
# Installation
#
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
)
set(LUNASVG_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib)
set(LUNASVG_INCDIR ${CMAKE_INSTALL_PREFIX}/include)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/lunasvgConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/lunasvgConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lunasvg
include/lunasvg.h
DESTINATION ${LUNASVG_INCDIR}
)
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)
[![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)

View file

@ -1,16 +1,4 @@
# Generate a standard header with export macros
include(GenerateExportHeader)
generate_export_header(lunasvg)
target_include_directories(lunasvg
# When building a project that uses the lunasvg library,
# we need to look in the installed include directory
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}>
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}"
)

View file

@ -27,16 +27,22 @@
#include <string>
#include <cstdint>
#include <lunasvg_export.h>
#define LUNASVG_API LUNASVG_EXPORT
#if defined(_MSC_VER) && defined(LUNASVG_SHARED)
#ifdef LUNASVG_EXPORT
#define LUNASVG_API __declspec(dllexport)
#else
#define LUNASVG_API __declspec(dllimport)
#endif
#else
#define LUNASVG_API
#endif
namespace lunasvg {
class Rect;
class Matrix;
class LUNASVG_API Box
{
class LUNASVG_API Box {
public:
Box() = default;
Box(double x, double y, double w, double h);
@ -54,8 +60,7 @@ public:
class Transform;
class LUNASVG_API Matrix
{
class LUNASVG_API Matrix {
public:
Matrix() = default;
Matrix(double a, double b, double c, double d, double e, double f);
@ -92,8 +97,7 @@ public:
double f{0};
};
class LUNASVG_API Bitmap
{
class LUNASVG_API Bitmap {
public:
/**
* @note Bitmap format is ARGB Premultiplied.
@ -123,8 +127,7 @@ private:
class LayoutSymbol;
class LUNASVG_API Document
{
class LUNASVG_API Document {
public:
/**
* @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;
~Document();
private:
Document();

View file

@ -149,11 +149,9 @@ void Canvas::luminance()
auto height = plutovg_surface_get_height(surface);
auto stride = plutovg_surface_get_stride(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);
for(int x = 0;x < width;x++)
{
for(int x = 0; x < width; x++) {
auto pixel = pixels[x];
auto r = (pixel >> 16) & 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)
{
for(const auto& stop : stops)
{
for(const auto& stop : stops) {
auto offset = std::get<0>(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);
@ -241,8 +238,7 @@ void to_plutovg_path(plutovg_t* pluto, const Path& path)
{
PathIterator it(path);
std::array<Point, 3> p;
while(!it.isDone())
{
while(!it.isDone()) {
switch(it.currentSegment(p)) {
case PathCommand::MoveTo:
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>;
struct DashData
{
struct DashData {
DashArray array;
double offset{0.0};
};
enum class TextureType
{
enum class TextureType {
Plain,
Tiled
};
enum class BlendMode
{
enum class BlendMode {
Src,
Src_Over,
Dst_In,
@ -35,8 +32,7 @@ enum class BlendMode
class CanvasImpl;
class Canvas
{
class Canvas {
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(double x, double y, double width, double height);
@ -61,6 +57,7 @@ public:
Rect box() const;
~Canvas();
private:
Canvas(unsigned char* data, int width, int height, int stride);
Canvas(int x, int y, int width, int height);

View file

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

View file

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

View file

@ -1,53 +1,8 @@
#include "element.h"
#include "parser.h"
#include "svgelement.h"
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
{
}
@ -66,18 +21,32 @@ Element::Element(ElementID id)
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;
const std::string& Element::get(PropertyID id) const
{
auto property = properties.get(id);
if(property == nullptr)
return EmptyString;
for(auto& property : properties) {
if(property.id == id) {
return property.value;
}
}
return property->value;
return EmptyString;
}
static const std::string InheritString{"inherit"};
@ -97,7 +66,13 @@ const std::string& Element::find(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
@ -108,12 +83,10 @@ Element* Element::previousElement() const
Element* element = nullptr;
auto it = parent->children.begin();
auto end = parent->children.end();
for(;it != end;++it)
{
for(; it != end; ++it) {
auto node = it->get();
if(node->isText())
continue;
if(node == this)
return element;
element = static_cast<Element*>(node);
@ -130,8 +103,7 @@ Element* Element::nextElement() const
Element* element = nullptr;
auto it = parent->children.rbegin();
auto end = parent->children.rend();
for(;it != end;++it)
{
for(; it != end; ++it) {
auto node = it->get();
if(node->isText())
continue;
@ -153,22 +125,21 @@ Node* Element::addChild(std::unique_ptr<Node> child)
void Element::layoutChildren(LayoutContext* context, LayoutContainer* current) const
{
for(auto& child : children)
for(auto& child : children) {
child->layout(context, current);
}
}
Rect Element::currentViewport() const
{
if(parent == nullptr)
{
if(parent == nullptr) {
auto element = static_cast<const SVGElement*>(this);
if(element->has(PropertyID::ViewBox))
return element->viewBox();
return Rect{0, 0, 300, 150};
}
if(parent->id == ElementID::Svg)
{
if(parent->id == ElementID::Svg) {
auto element = static_cast<SVGElement*>(parent);
if(element->has(PropertyID::ViewBox))
return element->viewBox();

View file

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

View file

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

View file

@ -79,7 +79,7 @@ Path PolygonElement::path() const
Path path;
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.close();
@ -104,7 +104,7 @@ Path PolylineElement::path() const
Path path;
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);
return path;

View file

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

View file

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

View file

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

View file

@ -8,8 +8,7 @@
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::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
{
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
@ -90,17 +93,16 @@ void Bitmap::clear(std::uint32_t color)
auto stride = this->stride();
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;
for(std::uint32_t x = 0;x < width;x++)
{
for(std::uint32_t x = 0; x < width; x++) {
data[0] = pb;
data[1] = pg;
data[2] = pr;
data[3] = a;
data += 4;
}
rowData += stride;
}
}
@ -112,18 +114,15 @@ void Bitmap::convert(int ri, int gi, int bi, int ai, bool unpremultiply)
auto stride = this->stride();
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;
for(std::uint32_t x = 0;x < width;x++)
{
for(std::uint32_t x = 0; x < width; x++) {
auto b = data[0];
auto g = data[1];
auto r = data[2];
auto a = data[3];
if(unpremultiply && a != 0)
{
if(unpremultiply && a != 0) {
r = (r * 255) / a;
g = (g * 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 += 4;
}
rowData += stride;
}
}
@ -258,7 +258,7 @@ Matrix Matrix::rotated(double angle, double cx, double cy)
Matrix Matrix::scaled(double sx, double sy)
{
return Transform::scaled(sx, sy);;
return Transform::scaled(sx, sy);
}
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)
return Bitmap{};
if(width == 0 && height == 0)
{
if(width == 0 && height == 0) {
width = static_cast<std::uint32_t>(std::ceil(root->width));
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));
}
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));
}
@ -369,12 +364,8 @@ Bitmap Document::renderToBitmap(std::uint32_t width, std::uint32_t height, std::
return bitmap;
}
Document::Document()
{
}
Document::Document() = default;
Document::~Document()
{
}
Document::~Document() = default;
} // namespace lunasvg

View file

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

View file

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

View file

@ -45,8 +45,7 @@ GradientStops GradientElement::buildGradientStops() const
{
GradientStops gradientStops;
double prevOffset = 0.0;
for(auto& child : children)
{
for(auto& child : children) {
if(child->isText())
continue;
auto element = static_cast<Element*>(child.get());
@ -96,8 +95,7 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
std::set<const GradientElement*> processedGradients;
const GradientElement* current = this;
while(true)
{
while(true) {
if(!attributes.hasGradientTransform() && current->has(PropertyID::GradientTransform))
attributes.setGradientTransform(current->gradientTransform());
if(!attributes.hasSpreadMethod() && current->has(PropertyID::SpreadMethod))
@ -107,8 +105,7 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
if(!attributes.hasGradientStops())
attributes.setGradientStops(current->buildGradientStops());
if(current->id == ElementID::LinearGradient)
{
if(current->id == ElementID::LinearGradient) {
auto element = static_cast<const LinearGradientElement*>(current);
if(!attributes.hasX1() && element->has(PropertyID::X1))
attributes.setX1(element->x1());
@ -126,9 +123,10 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
processedGradients.insert(current);
current = static_cast<const GradientElement*>(ref);
if(processedGradients.find(current) != processedGradients.end())
if(processedGradients.find(current) != processedGradients.end()) {
break;
}
}
auto& stops = attributes.gradientStops();
if(stops.empty())
@ -139,8 +137,7 @@ std::unique_ptr<LayoutObject> LinearGradientElement::getPainter(LayoutContext* c
auto y1 = lengthContext.valueForLength(attributes.y1(), LengthMode::Height);
auto x2 = lengthContext.valueForLength(attributes.x2(), LengthMode::Width);
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>();
solid->color = std::get<1>(stops.back());
return std::move(solid);
@ -204,8 +201,7 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
std::set<const GradientElement*> processedGradients;
const GradientElement* current = this;
while(true)
{
while(true) {
if(!attributes.hasGradientTransform() && current->has(PropertyID::GradientTransform))
attributes.setGradientTransform(current->gradientTransform());
if(!attributes.hasSpreadMethod() && current->has(PropertyID::SpreadMethod))
@ -215,8 +211,7 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
if(!attributes.hasGradientStops())
attributes.setGradientStops(current->buildGradientStops());
if(current->id == ElementID::RadialGradient)
{
if(current->id == ElementID::RadialGradient) {
auto element = static_cast<const RadialGradientElement*>(current);
if(!attributes.hasCx() && element->has(PropertyID::Cx))
attributes.setCx(element->cx());
@ -236,9 +231,10 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
processedGradients.insert(current);
current = static_cast<const GradientElement*>(ref);
if(processedGradients.find(current) != processedGradients.end())
if(processedGradients.find(current) != processedGradients.end()) {
break;
}
}
if(!attributes.hasFx())
attributes.setFx(attributes.cx());
@ -250,8 +246,7 @@ std::unique_ptr<LayoutObject> RadialGradientElement::getPainter(LayoutContext* c
return nullptr;
auto& r = attributes.r();
if(r.isZero() || stops.size() == 1)
{
if(r.isZero() || stops.size() == 1) {
auto solid = std::make_unique<LayoutSolidColor>();
solid->color = std::get<1>(stops.back());
return std::move(solid);
@ -351,8 +346,7 @@ std::unique_ptr<LayoutObject> PatternElement::getPainter(LayoutContext* context)
std::set<const PatternElement*> processedPatterns;
const PatternElement* current = this;
while(true)
{
while(true) {
if(!attributes.hasX() && current->has(PropertyID::X))
attributes.setX(current->x());
if(!attributes.hasY() && current->has(PropertyID::Y))
@ -380,9 +374,10 @@ std::unique_ptr<LayoutObject> PatternElement::getPainter(LayoutContext* context)
processedPatterns.insert(current);
current = static_cast<const PatternElement*>(ref);
if(processedPatterns.find(current) != processedPatterns.end())
if(processedPatterns.find(current) != processedPatterns.end()) {
break;
}
}
auto& width = attributes.width();
auto& height = attributes.height();

View file

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

File diff suppressed because it is too large Load diff

View file

@ -12,14 +12,12 @@ namespace lunasvg {
class SVGElement;
class StyledElement;
enum LengthNegativeValuesMode
{
enum LengthNegativeValuesMode {
AllowNegativeLengths,
ForbidNegativeLengths
};
enum class TransformType
{
enum class TransformType {
Matrix,
Rotate,
Scale,
@ -28,8 +26,7 @@ enum class TransformType
Translate
};
class Parser
{
class Parser {
public:
static Length parseLength(const std::string& string, LengthNegativeValuesMode mode, const Length& defaultValue);
static LengthList parseLengthList(const std::string& string, LengthNegativeValuesMode mode);
@ -69,10 +66,8 @@ struct SimpleSelector;
using Selector = std::vector<SimpleSelector>;
using SelectorList = std::vector<Selector>;
struct AttributeSelector
{
enum class MatchType
{
struct AttributeSelector {
enum class MatchType {
None,
Equal,
Includes,
@ -87,10 +82,8 @@ struct AttributeSelector
std::string value;
};
struct PseudoClassSelector
{
enum class Type
{
struct PseudoClassSelector {
enum class Type {
Unknown,
Empty,
Root,
@ -105,15 +98,11 @@ struct PseudoClassSelector
};
Type type{Type::Unknown};
int16_t a{0};
int16_t b{0};
SelectorList subSelectors;
};
struct SimpleSelector
{
enum class Combinator
{
struct SimpleSelector {
enum class Combinator {
Descendant,
Child,
DirectAdjacent,
@ -126,33 +115,40 @@ struct SimpleSelector
std::vector<PseudoClassSelector> pseudoClassSelectors;
};
struct Rule
{
struct Declaration {
int specificity;
PropertyID id;
std::string value;
};
using DeclarationList = std::vector<Declaration>;
struct Rule {
SelectorList selectors;
PropertyList declarations;
DeclarationList declarations;
};
class RuleData {
public:
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)
RuleData(const Selector& selector, const DeclarationList& declarations, uint32_t specificity, uint32_t position)
: m_selector(selector), m_declarations(declarations), m_specificity(specificity), m_position(position)
{}
const Selector& selector() const { return m_selector; }
const PropertyList& properties() const { return m_properties; }
const DeclarationList& declarations() const { return m_declarations; }
const uint32_t& specificity() const { return m_specificity; }
const uint32_t& position() const { return m_position; }
bool match(const Element* element) const;
private:
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;
static bool matchSimpleSelector(const SimpleSelector& selector, const Element* element);
static bool matchAttributeSelector(const AttributeSelector& selector, const Element* element);
static bool matchPseudoClassSelector(const PseudoClassSelector& selector, const Element* element);
private:
Selector m_selector;
PropertyList m_properties;
DeclarationList m_declarations;
uint32_t m_specificity;
uint32_t m_position;
};
@ -164,31 +160,23 @@ class StyleSheet {
public:
StyleSheet() = default;
void parse(const std::string& content);
bool parse(const std::string& content);
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;
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);
const std::multiset<RuleData>& rules() const { return m_rules; }
private:
static bool parseAtRule(const char*& ptr, const char* end);
static bool parseRule(const char*& ptr, const char* end, Rule& rule);
static bool parseSelectors(const char*& ptr, const char* end, SelectorList& selectors);
static bool parseDeclarations(const char*& ptr, const char* end, 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 parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector);
private:
std::multiset<RuleData> m_rules;
uint32_t m_position{0};
};
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)
{
int read = 0;
while(data[read])
{
if(ptr >= end || *ptr != data[read])
{
while(data[read]) {
if(ptr >= end || *ptr != data[read]) {
ptr -= read;
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)
{
while(ptr < end)
{
while(ptr < end) {
auto start = ptr;
if(skipDesc(start, end, data))
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)
return false;
if(skipWs(ptr, end))
{
if(ptr < end && *ptr == delimiter)
{
if(skipWs(ptr, end)) {
if(ptr < end && *ptr == delimiter) {
++ptr;
skipWs(ptr, end);
}
@ -153,8 +148,7 @@ inline bool parseInteger(const char*& ptr, const char* end, T& integer, int base
if(ptr < end && *ptr == '+')
++ptr;
else if(ptr < end && isSigned && *ptr == '-')
{
else if(ptr < end && isSigned && *ptr == '-') {
++ptr;
isNegative = true;
}
@ -200,8 +194,7 @@ inline bool parseNumber(const char*& ptr, const char* end, T& number)
if(ptr < end && *ptr == '+')
++ptr;
else if(ptr < end && *ptr == '-')
{
else if(ptr < end && *ptr == '-') {
++ptr;
sign = -1;
}
@ -209,16 +202,14 @@ inline bool parseNumber(const char*& ptr, const char* end, T& number)
if(ptr >= end || !(IS_NUM(*ptr) || *ptr == '.'))
return false;
if(*ptr != '.')
{
if(*ptr != '.') {
do {
integer = static_cast<T>(10) * integer + (*ptr - '0');
++ptr;
} while(ptr < end && IS_NUM(*ptr));
}
if(ptr < end && *ptr == '.')
{
if(ptr < end && *ptr == '.') {
++ptr;
if(ptr >= end || !IS_NUM(*ptr))
return false;
@ -238,8 +229,7 @@ inline bool parseNumber(const char*& ptr, const char* end, T& number)
++ptr;
if(ptr < end && *ptr == '+')
++ptr;
else if(ptr < end && *ptr == '-')
{
else if(ptr < end && *ptr == '-') {
++ptr;
expsign = -1;
}

View file

@ -238,8 +238,7 @@ Rect Transform::map(const Rect& rect) const
auto r = p[0].x;
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 > r) r = p[i].x;
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 Py = dy1 * dy1;
auto check = Px / Pr1 + Py / Pr2;
if(check > 1)
{
if(check > 1) {
rx = rx * 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;
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 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 bottom = y + h;
if(rx == 0.0 && ry == 0.0)
{
if(rx == 0.0 && ry == 0.0) {
moveTo(x, y);
lineTo(right, y);
lineTo(right, bottom);
lineTo(x, bottom);
lineTo(x, y);
close();
}
else
{
} else {
double cpx = rx * kappa;
double cpy = ry * kappa;
moveTo(x, y+ry);
@ -481,8 +475,7 @@ Rect Path::box() const
auto r = m_points[0].x;
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 > r) r = m_points[i].x;
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
{
if(m_units == LengthUnits::Percent)
{
if(m_units == LengthUnits::Percent) {
auto viewport = element->currentViewport();
auto w = viewport.w;
auto h = viewport.h;
@ -635,8 +627,7 @@ Transform PreserveAspectRatio::getMatrix(double width, double height, const Rect
auto xscale = width / viewBox.w;
auto yscale = height / viewBox.h;
if(m_align == Align::None)
{
if(m_align == Align::None) {
auto xoffset = -viewBox.x * xscale;
auto yoffset = -viewBox.y * yscale;
return Transform{xscale, 0, 0, yscale, xoffset, yoffset};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -77,14 +77,11 @@ void UseElement::layout(LayoutContext* context, LayoutContainer* current) const
transform += ')';
group->set(PropertyID::Transform, transform, 0x10);
if(ref->id == ElementID::Svg || ref->id == ElementID::Symbol)
{
if(ref->id == ElementID::Svg || ref->id == ElementID::Symbol) {
auto element = ref->cloneElement<SVGElement>();
transferWidthAndHeight(element.get());
group->addChild(std::move(element));
}
else
{
} else {
group->addChild(ref->clone());
}

View file

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