diff --git a/external/lunasvg/.gitignore b/external/lunasvg/.gitignore deleted file mode 100644 index 6cb22275e..000000000 --- a/external/lunasvg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.vscode -build/* diff --git a/external/lunasvg/CMakeLists.txt b/external/lunasvg/CMakeLists.txt index 0903cc528..ea4b2d20c 100755 --- a/external/lunasvg/CMakeLists.txt +++ b/external/lunasvg/CMakeLists.txt @@ -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} +) diff --git a/external/lunasvg/README.md b/external/lunasvg/README.md index 3aef84fd0..1cff72721 100644 --- a/external/lunasvg/README.md +++ b/external/lunasvg/README.md @@ -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) diff --git a/external/lunasvg/cmake/lunasvgConfig.cmake.in b/external/lunasvg/cmake/lunasvgConfig.cmake.in deleted file mode 100644 index 850098f24..000000000 --- a/external/lunasvg/cmake/lunasvgConfig.cmake.in +++ /dev/null @@ -1,3 +0,0 @@ -@PACKAGE_INIT@ - -include("${CMAKE_CURRENT_LIST_DIR}/lunasvgTargets.cmake") diff --git a/external/lunasvg/example/CMakeLists.txt b/external/lunasvg/example/CMakeLists.txt index de18b31d1..53ec5ef46 100644 --- a/external/lunasvg/example/CMakeLists.txt +++ b/external/lunasvg/example/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.3) set(CMAKE_CXX_STANDARD 14) diff --git a/external/lunasvg/include/CMakeLists.txt b/external/lunasvg/include/CMakeLists.txt index 70d896f55..de589546c 100755 --- a/external/lunasvg/include/CMakeLists.txt +++ b/external/lunasvg/include/CMakeLists.txt @@ -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 - $ - - # 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 - $ - $ +PUBLIC + "${CMAKE_CURRENT_LIST_DIR}" ) diff --git a/external/lunasvg/include/lunasvg.h b/external/lunasvg/include/lunasvg.h index 687b5723a..23fbbbf31 100644 --- a/external/lunasvg/include/lunasvg.h +++ b/external/lunasvg/include/lunasvg.h @@ -27,16 +27,22 @@ #include #include -#include -#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(); diff --git a/external/lunasvg/source/canvas.cpp b/external/lunasvg/source/canvas.cpp index 80e05a38f..f5d650115 100644 --- a/external/lunasvg/source/canvas.cpp +++ b/external/lunasvg/source/canvas.cpp @@ -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(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 p; - while(!it.isDone()) - { + while(!it.isDone()) { switch(it.currentSegment(p)) { case PathCommand::MoveTo: plutovg_move_to(pluto, p[0].x, p[0].y); diff --git a/external/lunasvg/source/canvas.h b/external/lunasvg/source/canvas.h index a7d743300..31f4307b6 100644 --- a/external/lunasvg/source/canvas.h +++ b/external/lunasvg/source/canvas.h @@ -13,20 +13,17 @@ using GradientStops = std::vector; using DashArray = std::vector; -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 create(unsigned char* data, unsigned int width, unsigned int height, unsigned int stride); static std::shared_ptr 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); diff --git a/external/lunasvg/source/clippathelement.h b/external/lunasvg/source/clippathelement.h index 5a7c393ee..82a5bf698 100644 --- a/external/lunasvg/source/clippathelement.h +++ b/external/lunasvg/source/clippathelement.h @@ -7,8 +7,7 @@ namespace lunasvg { class LayoutClipPath; -class ClipPathElement : public GraphicsElement -{ +class ClipPathElement : public GraphicsElement { public: ClipPathElement(); diff --git a/external/lunasvg/source/defselement.h b/external/lunasvg/source/defselement.h index 4f986539e..9d5311545 100644 --- a/external/lunasvg/source/defselement.h +++ b/external/lunasvg/source/defselement.h @@ -5,8 +5,7 @@ namespace lunasvg { -class DefsElement : public GraphicsElement -{ +class DefsElement : public GraphicsElement { public: DefsElement(); diff --git a/external/lunasvg/source/element.cpp b/external/lunasvg/source/element.cpp index 518556fdb..f3c9eab2d 100644 --- a/external/lunasvg/source/element.cpp +++ b/external/lunasvg/source/element.cpp @@ -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(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(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 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(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(parent); if(element->has(PropertyID::ViewBox)) return element->viewBox(); diff --git a/external/lunasvg/source/element.h b/external/lunasvg/source/element.h index e6c668975..90979dcda 100644 --- a/external/lunasvg/source/element.h +++ b/external/lunasvg/source/element.h @@ -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 m_properties; -}; +using PropertyList = std::vector; 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>; -class Element : public Node -{ +class Element : public Node { public: Element(ElementID id); @@ -179,16 +160,13 @@ public: Rect currentViewport() const; template - 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 - std::unique_ptr cloneElement() const - { + std::unique_ptr cloneElement() const { auto element = std::make_unique(); element->properties = properties; for(auto& child : children) diff --git a/external/lunasvg/source/gelement.h b/external/lunasvg/source/gelement.h index be6a20b54..b9934d00b 100644 --- a/external/lunasvg/source/gelement.h +++ b/external/lunasvg/source/gelement.h @@ -5,8 +5,7 @@ namespace lunasvg { -class GElement : public GraphicsElement -{ +class GElement : public GraphicsElement { public: GElement(); diff --git a/external/lunasvg/source/geometryelement.cpp b/external/lunasvg/source/geometryelement.cpp index 6f848ac72..a7922908f 100644 --- a/external/lunasvg/source/geometryelement.cpp +++ b/external/lunasvg/source/geometryelement.cpp @@ -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; diff --git a/external/lunasvg/source/geometryelement.h b/external/lunasvg/source/geometryelement.h index e2f0bb462..3ed529965 100644 --- a/external/lunasvg/source/geometryelement.h +++ b/external/lunasvg/source/geometryelement.h @@ -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 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 clone() const; }; -class PolylineElement : public PolyElement -{ +class PolylineElement : public PolyElement { public: PolylineElement(); @@ -56,8 +51,7 @@ public: std::unique_ptr clone() const; }; -class CircleElement : public GeometryElement -{ +class CircleElement : public GeometryElement { public: CircleElement(); @@ -70,8 +64,7 @@ public: std::unique_ptr clone() const; }; -class EllipseElement : public GeometryElement -{ +class EllipseElement : public GeometryElement { public: EllipseElement(); @@ -85,8 +78,7 @@ public: std::unique_ptr clone() const; }; -class LineElement : public GeometryElement -{ +class LineElement : public GeometryElement { public: LineElement(); @@ -100,8 +92,7 @@ public: std::unique_ptr clone() const; }; -class RectElement : public GeometryElement -{ +class RectElement : public GeometryElement { public: RectElement(); diff --git a/external/lunasvg/source/layoutcontext.cpp b/external/lunasvg/source/layoutcontext.cpp index 24f4d0f1e..526f5d1d7 100644 --- a/external/lunasvg/source/layoutcontext.cpp +++ b/external/lunasvg/source/layoutcontext.cpp @@ -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_ptrchildren.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 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; diff --git a/external/lunasvg/source/layoutcontext.h b/external/lunasvg/source/layoutcontext.h index e81be5ad6..4c0e1ce3e 100644 --- a/external/lunasvg/source/layoutcontext.h +++ b/external/lunasvg/source/layoutcontext.h @@ -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>; -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; -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 m_references; }; -class LayoutBreaker -{ +class LayoutBreaker { public: LayoutBreaker(LayoutContext* context, const Element* element); ~LayoutBreaker(); diff --git a/external/lunasvg/source/lunasvg.cpp b/external/lunasvg/source/lunasvg.cpp index 4da130422..95186f046 100644 --- a/external/lunasvg/source/lunasvg.cpp +++ b/external/lunasvg/source/lunasvg.cpp @@ -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::ceil(root->width)); height = static_cast(std::ceil(root->height)); - } - else if(width != 0 && height == 0) - { + } else if(width != 0 && height == 0) { height = static_cast(std::ceil(width * root->height / root->width)); - } - else if(height != 0 && width == 0) - { + } else if(height != 0 && width == 0) { width = static_cast(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 diff --git a/external/lunasvg/source/markerelement.h b/external/lunasvg/source/markerelement.h index 1b519f190..1daf6c8c3 100644 --- a/external/lunasvg/source/markerelement.h +++ b/external/lunasvg/source/markerelement.h @@ -7,8 +7,7 @@ namespace lunasvg { class LayoutMarker; -class MarkerElement : public StyledElement -{ +class MarkerElement : public StyledElement { public: MarkerElement(); diff --git a/external/lunasvg/source/maskelement.h b/external/lunasvg/source/maskelement.h index 44df229fb..7018cd41b 100644 --- a/external/lunasvg/source/maskelement.h +++ b/external/lunasvg/source/maskelement.h @@ -7,8 +7,7 @@ namespace lunasvg { class LayoutMask; -class MaskElement : public StyledElement -{ +class MaskElement : public StyledElement { public: MaskElement(); diff --git a/external/lunasvg/source/paintelement.cpp b/external/lunasvg/source/paintelement.cpp index 7cc77a6f3..f8cebeb2c 100644 --- a/external/lunasvg/source/paintelement.cpp +++ b/external/lunasvg/source/paintelement.cpp @@ -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(child.get()); @@ -96,8 +95,7 @@ std::unique_ptr LinearGradientElement::getPainter(LayoutContext* c std::set 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 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(current); if(!attributes.hasX1() && element->has(PropertyID::X1)) attributes.setX1(element->x1()); @@ -126,8 +123,9 @@ std::unique_ptr LinearGradientElement::getPainter(LayoutContext* c processedGradients.insert(current); current = static_cast(ref); - if(processedGradients.find(current) != processedGradients.end()) + if(processedGradients.find(current) != processedGradients.end()) { break; + } } auto& stops = attributes.gradientStops(); @@ -139,8 +137,7 @@ std::unique_ptr 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(); solid->color = std::get<1>(stops.back()); return std::move(solid); @@ -204,8 +201,7 @@ std::unique_ptr RadialGradientElement::getPainter(LayoutContext* c std::set 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 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(current); if(!attributes.hasCx() && element->has(PropertyID::Cx)) attributes.setCx(element->cx()); @@ -236,8 +231,9 @@ std::unique_ptr RadialGradientElement::getPainter(LayoutContext* c processedGradients.insert(current); current = static_cast(ref); - if(processedGradients.find(current) != processedGradients.end()) + if(processedGradients.find(current) != processedGradients.end()) { break; + } } if(!attributes.hasFx()) @@ -250,8 +246,7 @@ std::unique_ptr 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(); solid->color = std::get<1>(stops.back()); return std::move(solid); @@ -351,8 +346,7 @@ std::unique_ptr PatternElement::getPainter(LayoutContext* context) std::set 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,8 +374,9 @@ std::unique_ptr PatternElement::getPainter(LayoutContext* context) processedPatterns.insert(current); current = static_cast(ref); - if(processedPatterns.find(current) != processedPatterns.end()) + if(processedPatterns.find(current) != processedPatterns.end()) { break; + } } auto& width = attributes.width(); diff --git a/external/lunasvg/source/paintelement.h b/external/lunasvg/source/paintelement.h index b2d152a63..5c7041933 100644 --- a/external/lunasvg/source/paintelement.h +++ b/external/lunasvg/source/paintelement.h @@ -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 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 clone() const; }; -class RadialGradientElement : public GradientElement -{ +class RadialGradientElement : public GradientElement { public: RadialGradientElement(); @@ -58,8 +54,7 @@ public: std::unique_ptr clone() const; }; -class PatternElement : public PaintElement -{ +class PatternElement : public PaintElement { public: PatternElement(); @@ -79,8 +74,7 @@ public: std::unique_ptr clone() const; }; -class SolidColorElement : public PaintElement -{ +class SolidColorElement : public PaintElement { public: SolidColorElement(); @@ -88,8 +82,7 @@ public: std::unique_ptr 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; } diff --git a/external/lunasvg/source/parser.cpp b/external/lunasvg/source/parser.cpp index a5d09c5ef..420f870d7 100644 --- a/external/lunasvg/source/parser.cpp +++ b/external/lunasvg/source/parser.cpp @@ -45,8 +45,7 @@ LengthList Parser::parseLengthList(const std::string& string, LengthNegativeValu LengthUnits units; LengthList values; - while(ptr < end) - { + while(ptr < end) { if(!parseLength(ptr, end, value, units, mode)) break; values.emplace_back(value, units); @@ -100,12 +99,13 @@ PointList Parser::parsePointList(const std::string& string) double y; PointList values; - while(ptr < end) - { + while(ptr < end) { if(!Utils::parseNumber(ptr, end, x) - || !Utils::skipWsComma(ptr, end) - || !Utils::parseNumber(ptr, end, y)) + || !Utils::skipWsComma(ptr, end) + || !Utils::parseNumber(ptr, end, y)) { break; + } + values.emplace_back(x, y); Utils::skipWsComma(ptr, end); } @@ -126,8 +126,7 @@ Transform Parser::parseTransform(const std::string& string) int count; Transform transform; - while(ptr < end) - { + while(ptr < end) { if(!parseTransform(ptr, end, type, values, count)) break; Utils::skipWsComma(ptr, end); @@ -182,15 +181,13 @@ Path Parser::parsePath(const std::string& string) Point controlPoint; Path path; - while(true) - { + while(true) { Utils::skipWs(ptr, end); if(command == 'M' || command == 'm') { if(!parseNumberList(ptr, end, c, 2)) return path; - if(command == 'm') - { + if(command == 'm') { c[0] += currentPoint.x; c[1] += currentPoint.y; } @@ -203,8 +200,7 @@ Path Parser::parsePath(const std::string& string) if(!parseNumberList(ptr, end, c, 2)) return path; - if(command == 'l') - { + if(command == 'l') { c[0] += currentPoint.x; c[1] += currentPoint.y; } @@ -234,8 +230,7 @@ Path Parser::parsePath(const std::string& string) if(!parseNumberList(ptr, end, c, 4)) return path; - if(command == 'q') - { + if(command == 'q') { c[0] += currentPoint.x; c[1] += currentPoint.y; c[2] += currentPoint.x; @@ -251,8 +246,7 @@ Path Parser::parsePath(const std::string& string) if(!parseNumberList(ptr, end, c, 6)) return path; - if(command == 'c') - { + if(command == 'c') { c[0] += currentPoint.x; c[1] += currentPoint.y; c[2] += currentPoint.x; @@ -278,8 +272,7 @@ Path Parser::parsePath(const std::string& string) if(!parseNumberList(ptr, end, c + 2, 2)) return path; - if(command == 't') - { + if(command == 't') { c[2] += currentPoint.x; c[3] += currentPoint.y; } @@ -301,8 +294,7 @@ Path Parser::parsePath(const std::string& string) if(!parseNumberList(ptr, end, c + 2, 4)) return path; - if(command == 's') - { + if(command == 's') { c[2] += currentPoint.x; c[3] += currentPoint.y; c[4] += currentPoint.x; @@ -316,13 +308,13 @@ Path Parser::parsePath(const std::string& string) currentPoint.y = c[5]; } else if(command == 'A' || command == 'a') { if(!parseNumberList(ptr, end, c, 3) - || !parseArcFlag(ptr, end, f[0]) - || !parseArcFlag(ptr, end, f[1]) - || !parseNumberList(ptr, end, c + 3, 2)) + || !parseArcFlag(ptr, end, f[0]) + || !parseArcFlag(ptr, end, f[1]) + || !parseNumberList(ptr, end, c + 3, 2)) { return path; + } - if(command == 'a') - { + if(command == 'a') { c[3] += currentPoint.x; c[4] += currentPoint.y; } @@ -343,8 +335,9 @@ Path Parser::parsePath(const std::string& string) break; lastCommand = command; - if(IS_ALPHA(*ptr)) + if(IS_ALPHA(*ptr)) { command = *ptr++; + } } return path; @@ -367,7 +360,6 @@ std::string Parser::parseHref(const std::string& string) { if(string.size() > 1 && string.front() == '#') return string.substr(1); - return std::string{}; } @@ -384,17 +376,17 @@ Rect Parser::parseViewBox(const std::string& string) double w; double h; if(!Utils::parseNumber(ptr, end, x) - || !Utils::skipWsComma(ptr, end) - || !Utils::parseNumber(ptr, end, y) - || !Utils::skipWsComma(ptr, end) - || !Utils::parseNumber(ptr, end, w) - || !Utils::skipWsComma(ptr, end) - || !Utils::parseNumber(ptr, end, h)) + || !Utils::skipWsComma(ptr, end) + || !Utils::parseNumber(ptr, end, y) + || !Utils::skipWsComma(ptr, end) + || !Utils::parseNumber(ptr, end, w) + || !Utils::skipWsComma(ptr, end) + || !Utils::parseNumber(ptr, end, h)) { return Rect::Invalid; + } if(w < 0.0 || h < 0.0) return Rect::Invalid; - return Rect{x, y, w, h}; } @@ -499,157 +491,6 @@ Units Parser::parseUnits(const std::string& string, Units defaultValue) return defaultValue; } -static const std::map colormap = { - {"aliceblue", 0xF0F8FF}, - {"antiquewhite", 0xFAEBD7}, - {"aqua", 0x00FFFF}, - {"aquamarine", 0x7FFFD4}, - {"azure", 0xF0FFFF}, - {"beige", 0xF5F5DC}, - {"bisque", 0xFFE4C4}, - {"black", 0x000000}, - {"blanchedalmond", 0xFFEBCD}, - {"blue", 0x0000FF}, - {"blueviolet", 0x8A2BE2}, - {"brown", 0xA52A2A}, - {"burlywood", 0xDEB887}, - {"cadetblue", 0x5F9EA0}, - {"chartreuse", 0x7FFF00}, - {"chocolate", 0xD2691E}, - {"coral", 0xFF7F50}, - {"cornflowerblue", 0x6495ED}, - {"cornsilk", 0xFFF8DC}, - {"crimson", 0xDC143C}, - {"cyan", 0x00FFFF}, - {"darkblue", 0x00008B}, - {"darkcyan", 0x008B8B}, - {"darkgoldenrod", 0xB8860B}, - {"darkgray", 0xA9A9A9}, - {"darkgreen", 0x006400}, - {"darkgrey", 0xA9A9A9}, - {"darkkhaki", 0xBDB76B}, - {"darkmagenta", 0x8B008B}, - {"darkolivegreen", 0x556B2F}, - {"darkorange", 0xFF8C00}, - {"darkorchid", 0x9932CC}, - {"darkred", 0x8B0000}, - {"darksalmon", 0xE9967A}, - {"darkseagreen", 0x8FBC8F}, - {"darkslateblue", 0x483D8B}, - {"darkslategray", 0x2F4F4F}, - {"darkslategrey", 0x2F4F4F}, - {"darkturquoise", 0x00CED1}, - {"darkviolet", 0x9400D3}, - {"deeppink", 0xFF1493}, - {"deepskyblue", 0x00BFFF}, - {"dimgray", 0x696969}, - {"dimgrey", 0x696969}, - {"dodgerblue", 0x1E90FF}, - {"firebrick", 0xB22222}, - {"floralwhite", 0xFFFAF0}, - {"forestgreen", 0x228B22}, - {"fuchsia", 0xFF00FF}, - {"gainsboro", 0xDCDCDC}, - {"ghostwhite", 0xF8F8FF}, - {"gold", 0xFFD700}, - {"goldenrod", 0xDAA520}, - {"gray", 0x808080}, - {"green", 0x008000}, - {"greenyellow", 0xADFF2F}, - {"grey", 0x808080}, - {"honeydew", 0xF0FFF0}, - {"hotpink", 0xFF69B4}, - {"indianred", 0xCD5C5C}, - {"indigo", 0x4B0082}, - {"ivory", 0xFFFFF0}, - {"khaki", 0xF0E68C}, - {"lavender", 0xE6E6FA}, - {"lavenderblush", 0xFFF0F5}, - {"lawngreen", 0x7CFC00}, - {"lemonchiffon", 0xFFFACD}, - {"lightblue", 0xADD8E6}, - {"lightcoral", 0xF08080}, - {"lightcyan", 0xE0FFFF}, - {"lightgoldenrodyellow", 0xFAFAD2}, - {"lightgray", 0xD3D3D3}, - {"lightgreen", 0x90EE90}, - {"lightgrey", 0xD3D3D3}, - {"lightpink", 0xFFB6C1}, - {"lightsalmon", 0xFFA07A}, - {"lightseagreen", 0x20B2AA}, - {"lightskyblue", 0x87CEFA}, - {"lightslategray", 0x778899}, - {"lightslategrey", 0x778899}, - {"lightsteelblue", 0xB0C4DE}, - {"lightyellow", 0xFFFFE0}, - {"lime", 0x00FF00}, - {"limegreen", 0x32CD32}, - {"linen", 0xFAF0E6}, - {"magenta", 0xFF00FF}, - {"maroon", 0x800000}, - {"mediumaquamarine", 0x66CDAA}, - {"mediumblue", 0x0000CD}, - {"mediumorchid", 0xBA55D3}, - {"mediumpurple", 0x9370DB}, - {"mediumseagreen", 0x3CB371}, - {"mediumslateblue", 0x7B68EE}, - {"mediumspringgreen", 0x00FA9A}, - {"mediumturquoise", 0x48D1CC}, - {"mediumvioletred", 0xC71585}, - {"midnightblue", 0x191970}, - {"mintcream", 0xF5FFFA}, - {"mistyrose", 0xFFE4E1}, - {"moccasin", 0xFFE4B5}, - {"navajowhite", 0xFFDEAD}, - {"navy", 0x000080}, - {"oldlace", 0xFDF5E6}, - {"olive", 0x808000}, - {"olivedrab", 0x6B8E23}, - {"orange", 0xFFA500}, - {"orangered", 0xFF4500}, - {"orchid", 0xDA70D6}, - {"palegoldenrod", 0xEEE8AA}, - {"palegreen", 0x98FB98}, - {"paleturquoise", 0xAFEEEE}, - {"palevioletred", 0xDB7093}, - {"papayawhip", 0xFFEFD5}, - {"peachpuff", 0xFFDAB9}, - {"peru", 0xCD853F}, - {"pink", 0xFFC0CB}, - {"plum", 0xDDA0DD}, - {"powderblue", 0xB0E0E6}, - {"purple", 0x800080}, - {"rebeccapurple", 0x663399}, - {"red", 0xFF0000}, - {"rosybrown", 0xBC8F8F}, - {"royalblue", 0x4169E1}, - {"saddlebrown", 0x8B4513}, - {"salmon", 0xFA8072}, - {"sandybrown", 0xF4A460}, - {"seagreen", 0x2E8B57}, - {"seashell", 0xFFF5EE}, - {"sienna", 0xA0522D}, - {"silver", 0xC0C0C0}, - {"skyblue", 0x87CEEB}, - {"slateblue", 0x6A5ACD}, - {"slategray", 0x708090}, - {"slategrey", 0x708090}, - {"snow", 0xFFFAFA}, - {"springgreen", 0x00FF7F}, - {"steelblue", 0x4682B4}, - {"tan", 0xD2B48C}, - {"teal", 0x008080}, - {"thistle", 0xD8BFD8}, - {"tomato", 0xFF6347}, - {"turquoise", 0x40E0D0}, - {"violet", 0xEE82EE}, - {"wheat", 0xF5DEB3}, - {"white", 0xFFFFFF}, - {"whitesmoke", 0xF5F5F5}, - {"yellow", 0xFFFF00}, - {"yellowgreen", 0x9ACD32} -}; - Color Parser::parseColor(const std::string& string, const StyledElement* element, const Color& defaultValue) { if(string.empty()) @@ -658,8 +499,7 @@ Color Parser::parseColor(const std::string& string, const StyledElement* element auto ptr = string.data(); auto end = ptr + string.size(); - if(Utils::skipDesc(ptr, end, '#')) - { + if(Utils::skipDesc(ptr, end, '#')) { auto start = ptr; unsigned int value; if(!Utils::parseInteger(ptr, end, value, 16)) @@ -669,8 +509,7 @@ Color Parser::parseColor(const std::string& string, const StyledElement* element if(n != 3 && n != 6) return defaultValue; - if(n == 3) - { + if(n == 3) { value = ((value&0xf00) << 8) | ((value&0x0f0) << 4) | (value&0x00f); value |= value << 4; } @@ -678,8 +517,7 @@ Color Parser::parseColor(const std::string& string, const StyledElement* element return Color(value | 0xFF000000); } - if(Utils::skipDesc(ptr, end, "rgb(")) - { + if(Utils::skipDesc(ptr, end, "rgb(")) { int r, g, b; if(!Utils::skipWs(ptr, end) || !parseColorComponent(ptr, end, r) @@ -688,8 +526,9 @@ Color Parser::parseColor(const std::string& string, const StyledElement* element || !Utils::skipWsComma(ptr, end) || !parseColorComponent(ptr, end, b) || !Utils::skipWs(ptr, end) - || !Utils::skipDesc(ptr, end, ')')) + || !Utils::skipDesc(ptr, end, ')')) { return defaultValue; + } return Color(r, g, b, 255); } @@ -700,6 +539,157 @@ Color Parser::parseColor(const std::string& string, const StyledElement* element if(Utils::skipDesc(ptr, end, "currentColor")) return element->color(); + static const std::map colormap = { + {"aliceblue", 0xF0F8FF}, + {"antiquewhite", 0xFAEBD7}, + {"aqua", 0x00FFFF}, + {"aquamarine", 0x7FFFD4}, + {"azure", 0xF0FFFF}, + {"beige", 0xF5F5DC}, + {"bisque", 0xFFE4C4}, + {"black", 0x000000}, + {"blanchedalmond", 0xFFEBCD}, + {"blue", 0x0000FF}, + {"blueviolet", 0x8A2BE2}, + {"brown", 0xA52A2A}, + {"burlywood", 0xDEB887}, + {"cadetblue", 0x5F9EA0}, + {"chartreuse", 0x7FFF00}, + {"chocolate", 0xD2691E}, + {"coral", 0xFF7F50}, + {"cornflowerblue", 0x6495ED}, + {"cornsilk", 0xFFF8DC}, + {"crimson", 0xDC143C}, + {"cyan", 0x00FFFF}, + {"darkblue", 0x00008B}, + {"darkcyan", 0x008B8B}, + {"darkgoldenrod", 0xB8860B}, + {"darkgray", 0xA9A9A9}, + {"darkgreen", 0x006400}, + {"darkgrey", 0xA9A9A9}, + {"darkkhaki", 0xBDB76B}, + {"darkmagenta", 0x8B008B}, + {"darkolivegreen", 0x556B2F}, + {"darkorange", 0xFF8C00}, + {"darkorchid", 0x9932CC}, + {"darkred", 0x8B0000}, + {"darksalmon", 0xE9967A}, + {"darkseagreen", 0x8FBC8F}, + {"darkslateblue", 0x483D8B}, + {"darkslategray", 0x2F4F4F}, + {"darkslategrey", 0x2F4F4F}, + {"darkturquoise", 0x00CED1}, + {"darkviolet", 0x9400D3}, + {"deeppink", 0xFF1493}, + {"deepskyblue", 0x00BFFF}, + {"dimgray", 0x696969}, + {"dimgrey", 0x696969}, + {"dodgerblue", 0x1E90FF}, + {"firebrick", 0xB22222}, + {"floralwhite", 0xFFFAF0}, + {"forestgreen", 0x228B22}, + {"fuchsia", 0xFF00FF}, + {"gainsboro", 0xDCDCDC}, + {"ghostwhite", 0xF8F8FF}, + {"gold", 0xFFD700}, + {"goldenrod", 0xDAA520}, + {"gray", 0x808080}, + {"green", 0x008000}, + {"greenyellow", 0xADFF2F}, + {"grey", 0x808080}, + {"honeydew", 0xF0FFF0}, + {"hotpink", 0xFF69B4}, + {"indianred", 0xCD5C5C}, + {"indigo", 0x4B0082}, + {"ivory", 0xFFFFF0}, + {"khaki", 0xF0E68C}, + {"lavender", 0xE6E6FA}, + {"lavenderblush", 0xFFF0F5}, + {"lawngreen", 0x7CFC00}, + {"lemonchiffon", 0xFFFACD}, + {"lightblue", 0xADD8E6}, + {"lightcoral", 0xF08080}, + {"lightcyan", 0xE0FFFF}, + {"lightgoldenrodyellow", 0xFAFAD2}, + {"lightgray", 0xD3D3D3}, + {"lightgreen", 0x90EE90}, + {"lightgrey", 0xD3D3D3}, + {"lightpink", 0xFFB6C1}, + {"lightsalmon", 0xFFA07A}, + {"lightseagreen", 0x20B2AA}, + {"lightskyblue", 0x87CEFA}, + {"lightslategray", 0x778899}, + {"lightslategrey", 0x778899}, + {"lightsteelblue", 0xB0C4DE}, + {"lightyellow", 0xFFFFE0}, + {"lime", 0x00FF00}, + {"limegreen", 0x32CD32}, + {"linen", 0xFAF0E6}, + {"magenta", 0xFF00FF}, + {"maroon", 0x800000}, + {"mediumaquamarine", 0x66CDAA}, + {"mediumblue", 0x0000CD}, + {"mediumorchid", 0xBA55D3}, + {"mediumpurple", 0x9370DB}, + {"mediumseagreen", 0x3CB371}, + {"mediumslateblue", 0x7B68EE}, + {"mediumspringgreen", 0x00FA9A}, + {"mediumturquoise", 0x48D1CC}, + {"mediumvioletred", 0xC71585}, + {"midnightblue", 0x191970}, + {"mintcream", 0xF5FFFA}, + {"mistyrose", 0xFFE4E1}, + {"moccasin", 0xFFE4B5}, + {"navajowhite", 0xFFDEAD}, + {"navy", 0x000080}, + {"oldlace", 0xFDF5E6}, + {"olive", 0x808000}, + {"olivedrab", 0x6B8E23}, + {"orange", 0xFFA500}, + {"orangered", 0xFF4500}, + {"orchid", 0xDA70D6}, + {"palegoldenrod", 0xEEE8AA}, + {"palegreen", 0x98FB98}, + {"paleturquoise", 0xAFEEEE}, + {"palevioletred", 0xDB7093}, + {"papayawhip", 0xFFEFD5}, + {"peachpuff", 0xFFDAB9}, + {"peru", 0xCD853F}, + {"pink", 0xFFC0CB}, + {"plum", 0xDDA0DD}, + {"powderblue", 0xB0E0E6}, + {"purple", 0x800080}, + {"rebeccapurple", 0x663399}, + {"red", 0xFF0000}, + {"rosybrown", 0xBC8F8F}, + {"royalblue", 0x4169E1}, + {"saddlebrown", 0x8B4513}, + {"salmon", 0xFA8072}, + {"sandybrown", 0xF4A460}, + {"seagreen", 0x2E8B57}, + {"seashell", 0xFFF5EE}, + {"sienna", 0xA0522D}, + {"silver", 0xC0C0C0}, + {"skyblue", 0x87CEEB}, + {"slateblue", 0x6A5ACD}, + {"slategray", 0x708090}, + {"slategrey", 0x708090}, + {"snow", 0xFFFAFA}, + {"springgreen", 0x00FF7F}, + {"steelblue", 0x4682B4}, + {"tan", 0xD2B48C}, + {"teal", 0x008080}, + {"thistle", 0xD8BFD8}, + {"tomato", 0xFF6347}, + {"turquoise", 0x40E0D0}, + {"violet", 0xEE82EE}, + {"wheat", 0xF5DEB3}, + {"white", 0xFFFFFF}, + {"whitesmoke", 0xF5F5F5}, + {"yellow", 0xFFFF00}, + {"yellowgreen", 0x9ACD32} + }; + auto it = colormap.find(string); if(it == colormap.end()) return defaultValue; @@ -858,8 +848,7 @@ bool Parser::parseLength(const char*& ptr, const char* end, double& value, Lengt bool Parser::parseNumberList(const char*& ptr, const char* end, double* values, int count) { - for(int i = 0;i < count;i++) - { + for(int i = 0; i < count; i++) { if(!Utils::parseNumber(ptr, end, values[i])) return false; Utils::skipWsComma(ptr, end); @@ -908,7 +897,8 @@ bool Parser::parseUrlFragment(const char*& ptr, const char* end, std::string& re case '"': { auto delim = *ptr; ++ptr; // delim - if(!Utils::skipWs(ptr, end) || *ptr != '#') + Utils::skipWs(ptr, end); + if(ptr >= end || *ptr != '#') return false; ++ptr; // # if(!Utils::readUntil(ptr, end, delim, ref)) @@ -937,44 +927,31 @@ bool Parser::parseTransform(const char*& ptr, const char* end, TransformType& ty { int required = 0; int optional = 0; - if(Utils::skipDesc(ptr, end, "matrix")) - { + if(Utils::skipDesc(ptr, end, "matrix")) { type = TransformType::Matrix; required = 6; optional = 0; - } - else if(Utils::skipDesc(ptr, end, "rotate")) - { + } else if(Utils::skipDesc(ptr, end, "rotate")) { type = TransformType::Rotate; required = 1; optional = 2; - } - else if(Utils::skipDesc(ptr, end, "scale")) - { + } else if(Utils::skipDesc(ptr, end, "scale")) { type = TransformType::Scale; required = 1; optional = 1; - } - else if(Utils::skipDesc(ptr, end, "skewX")) - { + } else if(Utils::skipDesc(ptr, end, "skewX")) { type = TransformType::SkewX; required = 1; optional = 0; - } - else if(Utils::skipDesc(ptr, end, "skewY")) - { + } else if(Utils::skipDesc(ptr, end, "skewY")) { type = TransformType::SkewY; required = 1; optional = 0; - } - else if(Utils::skipDesc(ptr, end, "translate")) - { + } else if(Utils::skipDesc(ptr, end, "translate")) { type = TransformType::Translate; required = 1; optional = 1; - } - else - { + } else { return false; } @@ -986,8 +963,7 @@ bool Parser::parseTransform(const char*& ptr, const char* end, TransformType& ty int maxCount = required + optional; count = 0; Utils::skipWs(ptr, end); - while(count < maxCount) - { + while(count < maxCount) { if(!Utils::parseNumber(ptr, end, values[count])) break; ++count; @@ -1001,127 +977,124 @@ bool Parser::parseTransform(const char*& ptr, const char* end, TransformType& ty return true; } -static const std::map elementmap = { - {"circle", ElementID::Circle}, - {"clipPath", ElementID::ClipPath}, - {"defs", ElementID::Defs}, - {"ellipse", ElementID::Ellipse}, - {"g", ElementID::G}, - {"line", ElementID::Line}, - {"linearGradient", ElementID::LinearGradient}, - {"marker", ElementID::Marker}, - {"mask", ElementID::Mask}, - {"path", ElementID::Path}, - {"pattern", ElementID::Pattern}, - {"polygon", ElementID::Polygon}, - {"polyline", ElementID::Polyline}, - {"radialGradient", ElementID::RadialGradient}, - {"rect", ElementID::Rect}, - {"stop", ElementID::Stop}, - {"style", ElementID::Style}, - {"solidColor", ElementID::SolidColor}, - {"svg", ElementID::Svg}, - {"symbol", ElementID::Symbol}, - {"use", ElementID::Use} -}; - -static const std::map propertymap = { - {"class", PropertyID::Class}, - {"clipPathUnits", PropertyID::ClipPathUnits}, - {"cx", PropertyID::Cx}, - {"cy", PropertyID::Cy}, - {"d", PropertyID::D}, - {"fx", PropertyID::Fx}, - {"fy", PropertyID::Fy}, - {"gradientTransform", PropertyID::GradientTransform}, - {"gradientUnits", PropertyID::GradientUnits}, - {"height", PropertyID::Height}, - {"href", PropertyID::Href}, - {"id", PropertyID::Id}, - {"markerHeight", PropertyID::MarkerHeight}, - {"markerUnits", PropertyID::MarkerUnits}, - {"markerWidth", PropertyID::MarkerWidth}, - {"maskContentUnits", PropertyID::MaskContentUnits}, - {"maskUnits", PropertyID::MaskUnits}, - {"offset", PropertyID::Offset}, - {"orient", PropertyID::Orient}, - {"patternContentUnits", PropertyID::PatternContentUnits}, - {"patternTransform", PropertyID::PatternTransform}, - {"patternUnits", PropertyID::PatternUnits}, - {"points", PropertyID::Points}, - {"preserveAspectRatio", PropertyID::PreserveAspectRatio}, - {"r", PropertyID::R}, - {"refX", PropertyID::RefX}, - {"refY", PropertyID::RefY}, - {"rx", PropertyID::Rx}, - {"ry", PropertyID::Ry}, - {"spreadMethod", PropertyID::SpreadMethod}, - {"style", PropertyID::Style}, - {"transform", PropertyID::Transform}, - {"viewBox", PropertyID::ViewBox}, - {"width", PropertyID::Width}, - {"x", PropertyID::X}, - {"x1", PropertyID::X1}, - {"x2", PropertyID::X2}, - {"xlink:href", PropertyID::Href}, - {"y", PropertyID::Y}, - {"y1", PropertyID::Y1}, - {"y2", PropertyID::Y2} -}; - -static const std::map csspropertymap = { - {"clip-path", PropertyID::Clip_Path}, - {"clip-rule", PropertyID::Clip_Rule}, - {"color", PropertyID::Color}, - {"display", PropertyID::Display}, - {"fill", PropertyID::Fill}, - {"fill-opacity", PropertyID::Fill_Opacity}, - {"fill-rule", PropertyID::Fill_Rule}, - {"marker-end", PropertyID::Marker_End}, - {"marker-mid", PropertyID::Marker_Mid}, - {"marker-start", PropertyID::Marker_Start}, - {"mask", PropertyID::Mask}, - {"opacity", PropertyID::Opacity}, - {"overflow", PropertyID::Overflow}, - {"solid-color", PropertyID::Solid_Color}, - {"solid-opacity", PropertyID::Solid_Opacity}, - {"stop-color", PropertyID::Stop_Color}, - {"stop-opacity", PropertyID::Stop_Opacity}, - {"stroke", PropertyID::Stroke}, - {"stroke-dasharray", PropertyID::Stroke_Dasharray}, - {"stroke-dashoffset", PropertyID::Stroke_Dashoffset}, - {"stroke-linecap", PropertyID::Stroke_Linecap}, - {"stroke-linejoin", PropertyID::Stroke_Linejoin}, - {"stroke-miterlimit", PropertyID::Stroke_Miterlimit}, - {"stroke-opacity", PropertyID::Stroke_Opacity}, - {"stroke-width", PropertyID::Stroke_Width}, - {"visibility", PropertyID::Visibility} -}; - -static inline ElementID elementId(const std::string& name) +static inline ElementID elementid(const std::string& name) { + static const std::map elementmap = { + {"circle", ElementID::Circle}, + {"clipPath", ElementID::ClipPath}, + {"defs", ElementID::Defs}, + {"ellipse", ElementID::Ellipse}, + {"g", ElementID::G}, + {"line", ElementID::Line}, + {"linearGradient", ElementID::LinearGradient}, + {"marker", ElementID::Marker}, + {"mask", ElementID::Mask}, + {"path", ElementID::Path}, + {"pattern", ElementID::Pattern}, + {"polygon", ElementID::Polygon}, + {"polyline", ElementID::Polyline}, + {"radialGradient", ElementID::RadialGradient}, + {"rect", ElementID::Rect}, + {"stop", ElementID::Stop}, + {"style", ElementID::Style}, + {"solidColor", ElementID::SolidColor}, + {"svg", ElementID::Svg}, + {"symbol", ElementID::Symbol}, + {"use", ElementID::Use} + }; + auto it = elementmap.find(name); if(it == elementmap.end()) return ElementID::Unknown; - return it->second; } -static inline PropertyID cssPropertyId(const std::string& name) +static inline PropertyID csspropertyid(const std::string& name) { + static const std::map csspropertymap = { + {"clip-path", PropertyID::Clip_Path}, + {"clip-rule", PropertyID::Clip_Rule}, + {"color", PropertyID::Color}, + {"display", PropertyID::Display}, + {"fill", PropertyID::Fill}, + {"fill-opacity", PropertyID::Fill_Opacity}, + {"fill-rule", PropertyID::Fill_Rule}, + {"marker-end", PropertyID::Marker_End}, + {"marker-mid", PropertyID::Marker_Mid}, + {"marker-start", PropertyID::Marker_Start}, + {"mask", PropertyID::Mask}, + {"opacity", PropertyID::Opacity}, + {"overflow", PropertyID::Overflow}, + {"solid-color", PropertyID::Solid_Color}, + {"solid-opacity", PropertyID::Solid_Opacity}, + {"stop-color", PropertyID::Stop_Color}, + {"stop-opacity", PropertyID::Stop_Opacity}, + {"stroke", PropertyID::Stroke}, + {"stroke-dasharray", PropertyID::Stroke_Dasharray}, + {"stroke-dashoffset", PropertyID::Stroke_Dashoffset}, + {"stroke-linecap", PropertyID::Stroke_Linecap}, + {"stroke-linejoin", PropertyID::Stroke_Linejoin}, + {"stroke-miterlimit", PropertyID::Stroke_Miterlimit}, + {"stroke-opacity", PropertyID::Stroke_Opacity}, + {"stroke-width", PropertyID::Stroke_Width}, + {"visibility", PropertyID::Visibility} + }; + auto it = csspropertymap.find(name); if(it == csspropertymap.end()) return PropertyID::Unknown; - return it->second; } -static inline PropertyID propertyId(const std::string& name) +static inline PropertyID propertyid(const std::string& name) { + static const std::map propertymap = { + {"class", PropertyID::Class}, + {"clipPathUnits", PropertyID::ClipPathUnits}, + {"cx", PropertyID::Cx}, + {"cy", PropertyID::Cy}, + {"d", PropertyID::D}, + {"fx", PropertyID::Fx}, + {"fy", PropertyID::Fy}, + {"gradientTransform", PropertyID::GradientTransform}, + {"gradientUnits", PropertyID::GradientUnits}, + {"height", PropertyID::Height}, + {"href", PropertyID::Href}, + {"id", PropertyID::Id}, + {"markerHeight", PropertyID::MarkerHeight}, + {"markerUnits", PropertyID::MarkerUnits}, + {"markerWidth", PropertyID::MarkerWidth}, + {"maskContentUnits", PropertyID::MaskContentUnits}, + {"maskUnits", PropertyID::MaskUnits}, + {"offset", PropertyID::Offset}, + {"orient", PropertyID::Orient}, + {"patternContentUnits", PropertyID::PatternContentUnits}, + {"patternTransform", PropertyID::PatternTransform}, + {"patternUnits", PropertyID::PatternUnits}, + {"points", PropertyID::Points}, + {"preserveAspectRatio", PropertyID::PreserveAspectRatio}, + {"r", PropertyID::R}, + {"refX", PropertyID::RefX}, + {"refY", PropertyID::RefY}, + {"rx", PropertyID::Rx}, + {"ry", PropertyID::Ry}, + {"spreadMethod", PropertyID::SpreadMethod}, + {"style", PropertyID::Style}, + {"transform", PropertyID::Transform}, + {"viewBox", PropertyID::ViewBox}, + {"width", PropertyID::Width}, + {"x", PropertyID::X}, + {"x1", PropertyID::X1}, + {"x2", PropertyID::X2}, + {"xlink:href", PropertyID::Href}, + {"y", PropertyID::Y}, + {"y1", PropertyID::Y1}, + {"y2", PropertyID::Y2} + }; + auto it = propertymap.find(name); if(it == propertymap.end()) - return cssPropertyId(name); - + return csspropertyid(name); return it->second; } @@ -1139,8 +1112,7 @@ bool RuleData::match(const Element* element) const return false; ++it; - while(it != end) - { + while(it != end) { switch(it->combinator) { case SimpleSelector::Combinator::Child: case SimpleSelector::Combinator::Descendant: @@ -1155,34 +1127,38 @@ bool RuleData::match(const Element* element) const if(element == nullptr) return false; - auto match = matchSimpleSelector(*it, element); - if(!match && (it->combinator != SimpleSelector::Combinator::Descendant && it->combinator != SimpleSelector::Combinator::InDirectAdjacent)) - return false; - - if(match || (it->combinator != SimpleSelector::Combinator::Descendant && it->combinator != SimpleSelector::Combinator::InDirectAdjacent)) + if(matchSimpleSelector(*it, element)) { ++it; + } else if(it->combinator != SimpleSelector::Combinator::Descendant + && it->combinator != SimpleSelector::Combinator::InDirectAdjacent) { + return false; + } } return true; } -bool RuleData::matchSimpleSelector(const SimpleSelector& selector, const Element* element) const +bool RuleData::matchSimpleSelector(const SimpleSelector& selector, const Element* element) { if(selector.id != ElementID::Star && selector.id != element->id) return false; - for(auto& sel : selector.attributeSelectors) - if(!matchAttributeSelector(sel, element)) + for(auto& sel : selector.attributeSelectors) { + if(!matchAttributeSelector(sel, element)) { return false; + } + } - for(auto& sel : selector.pseudoClassSelectors) - if(!matchPseudoClassSelector(sel, element)) + for(auto& sel : selector.pseudoClassSelectors) { + if(!matchPseudoClassSelector(sel, element)) { return false; + } + } return true; } -bool RuleData::matchAttributeSelector(const AttributeSelector& selector, const Element* element) const +bool RuleData::matchAttributeSelector(const AttributeSelector& selector, const Element* element) { auto& value = element->get(selector.id); if(value.empty()) @@ -1194,16 +1170,13 @@ bool RuleData::matchAttributeSelector(const AttributeSelector& selector, const E if(selector.matchType == AttributeSelector::MatchType::Equal) return selector.value == value; - if(selector.matchType == AttributeSelector::MatchType::Includes) - { + if(selector.matchType == AttributeSelector::MatchType::Includes) { auto ptr = value.data(); auto end = ptr + value.size(); - while(ptr < end) - { + while(ptr < end) { auto start = ptr; while(ptr < end && !IS_WS(*ptr)) ++ptr; - if(selector.value == std::string(start, ptr)) return true; Utils::skipWs(ptr, end); @@ -1215,22 +1188,18 @@ bool RuleData::matchAttributeSelector(const AttributeSelector& selector, const E auto starts_with = [](const std::string& string, const std::string& prefix) { if(prefix.empty() || prefix.size() > string.size()) return false; - return string.compare(0, prefix.size(), prefix) == 0; }; auto ends_with = [](const std::string& string, const std::string& suffix) { if(suffix.empty() || suffix.size() > string.size()) return false; - return string.compare(string.size() - suffix.size(), suffix.size(), suffix) == 0; }; - if(selector.matchType == AttributeSelector::MatchType::DashMatch) - { + if(selector.matchType == AttributeSelector::MatchType::DashMatch) { if(selector.value == value) return true; - return starts_with(value, selector.value + '-'); } @@ -1246,7 +1215,7 @@ bool RuleData::matchAttributeSelector(const AttributeSelector& selector, const E return false; } -bool RuleData::matchPseudoClassSelector(const PseudoClassSelector& selector, const Element* element) const +bool RuleData::matchPseudoClassSelector(const PseudoClassSelector& selector, const Element* element) { if(selector.type == PseudoClassSelector::Type::Empty) return element->children.empty(); @@ -1254,8 +1223,7 @@ bool RuleData::matchPseudoClassSelector(const PseudoClassSelector& selector, con if(selector.type == PseudoClassSelector::Type::Root) return element->parent == nullptr; - if(selector.type == PseudoClassSelector::Type::Is) - { + if(selector.type == PseudoClassSelector::Type::Is) { for(auto& selector : selector.subSelectors) { for(auto& sel : selector) { if(!matchSimpleSelector(sel, element)) { @@ -1267,8 +1235,7 @@ bool RuleData::matchPseudoClassSelector(const PseudoClassSelector& selector, con return true; } - if(selector.type == PseudoClassSelector::Type::Not) - { + if(selector.type == PseudoClassSelector::Type::Not) { for(auto& selector : selector.subSelectors) { for(auto& sel : selector) { if(matchSimpleSelector(sel, element)) { @@ -1289,11 +1256,9 @@ bool RuleData::matchPseudoClassSelector(const PseudoClassSelector& selector, con if(selector.type == PseudoClassSelector::Type::OnlyChild) return !(element->previousElement() || element->nextElement()); - if(selector.type == PseudoClassSelector::Type::FirstOfType) - { + if(selector.type == PseudoClassSelector::Type::FirstOfType) { auto sibling = element->previousElement(); - while(sibling) - { + while(sibling) { if(sibling->id == element->id) return false; sibling = element->previousElement(); @@ -1302,11 +1267,9 @@ bool RuleData::matchPseudoClassSelector(const PseudoClassSelector& selector, con return true; } - if(selector.type == PseudoClassSelector::Type::LastOfType) - { + if(selector.type == PseudoClassSelector::Type::LastOfType) { auto sibling = element->nextElement(); - while(sibling) - { + while(sibling) { if(sibling->id == element->id) return false; sibling = element->nextElement(); @@ -1318,40 +1281,6 @@ bool RuleData::matchPseudoClassSelector(const PseudoClassSelector& selector, con return false; } -void StyleSheet::parse(const std::string& content) -{ - CSSParser::parseSheet(this, content); -} - -void StyleSheet::add(const Rule& rule) -{ - for(auto& selector : rule.selectors) { - uint32_t specificity = 0; - for(auto& simpleSelector : selector) { - specificity += (simpleSelector.id == ElementID::Star) ? 0x0 : 0x1; - for(auto& attributeSelector : simpleSelector.attributeSelectors) { - specificity += (attributeSelector.id == PropertyID::Id) ? 0x10000 : 0x100; - } - } - - m_rules.emplace(selector, rule.declarations, specificity, m_position); - } - - m_position += 1; -} - -std::vector StyleSheet::match(const Element *element) const -{ - std::vector declarations; - for(auto& rule : m_rules) { - if(!rule.match(element)) - continue; - declarations.push_back(&rule.properties()); - } - - return declarations; -} - #define IS_STARTNAMECHAR(c) (IS_ALPHA(c) || (c) == '_' || (c) == ':') #define IS_NAMECHAR(c) (IS_STARTNAMECHAR(c) || IS_NUM(c) || (c) == '-' || (c) == '.') static inline bool readIdentifier(const char*& ptr, const char* end, std::string& value) @@ -1384,42 +1313,55 @@ static inline bool readCSSIdentifier(const char*& ptr, const char* end, std::str return true; } -bool CSSParser::parseSheet(StyleSheet* sheet, const std::string& value) +bool StyleSheet::parse(const std::string& value) { auto ptr = value.data(); auto end = ptr + value.size(); - Rule rule; - while(ptr < end) - { + while(ptr < end) { Utils::skipWs(ptr, end); - if(Utils::skipDesc(ptr, end, '@')) - { + if(Utils::skipDesc(ptr, end, '@')) { if(!parseAtRule(ptr, end)) return false; continue; } + Rule rule; if(!parseRule(ptr, end, rule)) return false; - sheet->add(rule); + add(rule); } return true; } -bool CSSParser::parseAtRule(const char*& ptr, const char* end) +void StyleSheet::add(const Rule& rule) +{ + for(auto& selector : rule.selectors) { + uint32_t specificity = 0; + for(auto& simpleSelector : selector) { + specificity += (simpleSelector.id == ElementID::Star) ? 0x0 : 0x1; + for(auto& attributeSelector : simpleSelector.attributeSelectors) { + specificity += (attributeSelector.id == PropertyID::Id) ? 0x10000 : 0x100; + } + } + + m_rules.emplace(selector, rule.declarations, specificity, m_position); + } + + m_position += 1; +} + +bool StyleSheet::parseAtRule(const char*& ptr, const char* end) { int depth = 0; - while(ptr < end) - { + while(ptr < end) { auto ch = *ptr; ++ptr; if(ch == ';' && depth == 0) break; if(ch == '{') ++depth; - else if(ch == '}' && depth > 0) - { + else if(ch == '}' && depth > 0) { if(depth == 1) break; --depth; @@ -1429,7 +1371,7 @@ bool CSSParser::parseAtRule(const char*& ptr, const char* end) return true; } -bool CSSParser::parseRule(const char*& ptr, const char* end, Rule& rule) +bool StyleSheet::parseRule(const char*& ptr, const char* end, Rule& rule) { if(!parseSelectors(ptr, end, rule.selectors)) return false; @@ -1440,36 +1382,32 @@ bool CSSParser::parseRule(const char*& ptr, const char* end, Rule& rule) return true; } -bool CSSParser::parseSelectors(const char*& ptr, const char* end, SelectorList& selectors) +bool StyleSheet::parseSelectors(const char*& ptr, const char* end, SelectorList& selectors) { - selectors.clear(); Selector selector; if(!parseSelector(ptr, end, selector)) return false; - selectors.push_back(selector); + selectors.push_back(std::move(selector)); - while(Utils::skipDesc(ptr, end, ',')) - { + while(Utils::skipDesc(ptr, end, ',')) { Utils::skipWs(ptr, end); Selector selector; if(!parseSelector(ptr, end, selector)) return false; - selectors.push_back(selector); + selectors.push_back(std::move(selector)); } return true; } -bool CSSParser::parseDeclarations(const char*& ptr, const char* end, PropertyList& declarations) +bool StyleSheet::parseDeclarations(const char*& ptr, const char* end, DeclarationList& declarations) { - declarations.clear(); if(!Utils::skipDesc(ptr, end, '{')) return false; - std::string name; - std::string value; Utils::skipWs(ptr, end); do { + std::string name; if(!readCSSIdentifier(ptr, end, name)) return false; Utils::skipWs(ptr, end); @@ -1479,18 +1417,19 @@ bool CSSParser::parseDeclarations(const char*& ptr, const char* end, PropertyLis auto start = ptr; while(ptr < end && !(*ptr == '!' || *ptr == ';' || *ptr == '}')) ++ptr; - value.assign(start, Utils::rtrim(start, ptr)); - int specificity = 0x10; - if(Utils::skipDesc(ptr, end, '!')) - { + + Declaration declaration; + declaration.specificity = 0x10; + declaration.id = csspropertyid(name); + declaration.value.assign(start, Utils::rtrim(start, ptr)); + if(Utils::skipDesc(ptr, end, '!')) { if(!Utils::skipDesc(ptr, end, "important")) return false; - specificity = 0x1000; + declaration.specificity = 0x1000; } - auto id = cssPropertyId(name); - if(id != PropertyID::Unknown) - declarations.set(id, value, specificity); + if(declaration.id != PropertyID::Unknown) + declarations.push_back(std::move(declaration)); Utils::skipWsDelimiter(ptr, end, ';'); } while(ptr < end && *ptr != '}'); @@ -1498,58 +1437,54 @@ bool CSSParser::parseDeclarations(const char*& ptr, const char* end, PropertyLis } #define IS_SELECTOR_STARTNAMECHAR(c) (IS_CSS_STARTNAMECHAR(c) || (c) == '*' || (c) == '#' || (c) == '.' || (c) == '[' || (c) == ':') -bool CSSParser::parseSelector(const char*& ptr, const char* end, Selector& selector) +bool StyleSheet::parseSelector(const char*& ptr, const char* end, Selector& selector) { do { SimpleSelector simpleSelector; if(!parseSimpleSelector(ptr, end, simpleSelector)) return false; - selector.push_back(simpleSelector); + selector.push_back(std::move(simpleSelector)); Utils::skipWs(ptr, end); } while(ptr < end && IS_SELECTOR_STARTNAMECHAR(*ptr)); return true; } -bool CSSParser::parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector) +bool StyleSheet::parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector) { std::string name; if(Utils::skipDesc(ptr, end, '*')) simpleSelector.id = ElementID::Star; else if(readCSSIdentifier(ptr, end, name)) - simpleSelector.id = elementId(name); + simpleSelector.id = elementid(name); - while(ptr < end) - { - if(Utils::skipDesc(ptr, end, '#')) - { + while(ptr < end) { + if(Utils::skipDesc(ptr, end, '#')) { AttributeSelector a; a.id = PropertyID::Id; a.matchType = AttributeSelector::MatchType::Equal; if(!readCSSIdentifier(ptr, end, a.value)) return false; - simpleSelector.attributeSelectors.push_back(a); + simpleSelector.attributeSelectors.push_back(std::move(a)); continue; } - if(Utils::skipDesc(ptr, end, '.')) - { + if(Utils::skipDesc(ptr, end, '.')) { AttributeSelector a; a.id = PropertyID::Class; a.matchType = AttributeSelector::MatchType::Includes; if(!readCSSIdentifier(ptr, end, a.value)) return false; - simpleSelector.attributeSelectors.push_back(a); + simpleSelector.attributeSelectors.push_back(std::move(a)); continue; } - if(Utils::skipDesc(ptr, end, '[')) - { + if(Utils::skipDesc(ptr, end, '[')) { Utils::skipWs(ptr, end); if(!readCSSIdentifier(ptr, end, name)) return false; AttributeSelector a; - a.id = propertyId(name); + a.id = propertyid(name); if(Utils::skipDesc(ptr, end, '=')) a.matchType = AttributeSelector::MatchType::Equal; else if(Utils::skipDesc(ptr, end, "~=")) @@ -1562,11 +1497,9 @@ bool CSSParser::parseSimpleSelector(const char*& ptr, const char* end, SimpleSel a.matchType = AttributeSelector::MatchType::EndsWith; else if(Utils::skipDesc(ptr, end, "*=")) a.matchType = AttributeSelector::MatchType::Contains; - if(a.matchType != AttributeSelector::MatchType::None) - { + if(a.matchType != AttributeSelector::MatchType::None) { Utils::skipWs(ptr, end); - if(!readCSSIdentifier(ptr, end, a.value)) - { + if(!readCSSIdentifier(ptr, end, a.value)) { if(ptr >= end || !(*ptr == '\"' || *ptr == '\'')) return false; @@ -1581,12 +1514,11 @@ bool CSSParser::parseSimpleSelector(const char*& ptr, const char* end, SimpleSel Utils::skipWs(ptr, end); if(!Utils::skipDesc(ptr, end, ']')) return false; - simpleSelector.attributeSelectors.push_back(a); + simpleSelector.attributeSelectors.push_back(std::move(a)); continue; } - if(Utils::skipDesc(ptr, end, ':')) - { + if(Utils::skipDesc(ptr, end, ':')) { if(!readCSSIdentifier(ptr, end, name)) return false; PseudoClassSelector selector; @@ -1608,8 +1540,7 @@ bool CSSParser::parseSimpleSelector(const char*& ptr, const char* end, SimpleSel selector.type = PseudoClassSelector::Type::LastOfType; else if(name.compare("only-of-type") == 0) selector.type = PseudoClassSelector::Type::OnlyOfType; - if(selector.type == PseudoClassSelector::Type::Is || selector.type == PseudoClassSelector::Type::Not) - { + if(selector.type == PseudoClassSelector::Type::Is || selector.type == PseudoClassSelector::Type::Not) { if(!Utils::skipDesc(ptr, end, '(')) return false; @@ -1618,11 +1549,12 @@ bool CSSParser::parseSimpleSelector(const char*& ptr, const char* end, SimpleSel return false; Utils::skipWs(ptr, end); - if(!Utils::skipDesc(ptr, end, ')')) + if(!Utils::skipDesc(ptr, end, ')')) { return false; + } } - simpleSelector.pseudoClassSelectors.push_back(selector); + simpleSelector.pseudoClassSelectors.push_back(std::move(selector)); continue; } @@ -1695,18 +1627,15 @@ static inline std::unique_ptr createElement(ElementID id) static inline bool decodeText(const char* ptr, const char* end, std::string& value) { value.clear(); - while(ptr < end) - { + while(ptr < end) { auto ch = *ptr; ++ptr; - if(ch != '&') - { + if(ch != '&') { value.push_back(ch); continue; } - if(Utils::skipDesc(ptr, end, '#')) - { + if(Utils::skipDesc(ptr, end, '#')) { int base = 10; if(Utils::skipDesc(ptr, end, 'x')) base = 16; @@ -1716,29 +1645,22 @@ static inline bool decodeText(const char* ptr, const char* end, std::string& val return false; char c[5] = {0, 0, 0, 0, 0}; - if(cp < 0x80) - { + if(cp < 0x80) { c[1] = 0; c[0] = cp; - } - else if(cp < 0x800) - { + } else if(cp < 0x800) { c[2] = 0; c[1] = (cp & 0x3F) | 0x80; cp >>= 6; c[0] = cp | 0xC0; - } - else if(cp < 0x10000) - { + } else if(cp < 0x10000) { c[3] = 0; c[2] = (cp & 0x3F) | 0x80; cp >>= 6; c[1] = (cp & 0x3F) | 0x80; cp >>= 6; c[0] = cp | 0xE0; - } - else if(cp < 0x200000) - { + } else if(cp < 0x200000) { c[4] = 0; c[3] = (cp & 0x3F) | 0x80; cp >>= 6; @@ -1750,9 +1672,7 @@ static inline bool decodeText(const char* ptr, const char* end, std::string& val } value.append(c); - } - else - { + } else { if(Utils::skipDesc(ptr, end, "amp")) value.push_back('&'); else if(Utils::skipDesc(ptr, end, "lt")) @@ -1763,12 +1683,14 @@ static inline bool decodeText(const char* ptr, const char* end, std::string& val value.push_back('\"'); else if(Utils::skipDesc(ptr, end, "apos")) value.push_back('\''); - else + else { return false; + } } - if(!Utils::skipDesc(ptr, end, ';')) + if(!Utils::skipDesc(ptr, end, ';')) { return false; + } } return true; @@ -1782,8 +1704,7 @@ static inline void parseStyle(const std::string& string, Element* element) std::string name; std::string value; Utils::skipWs(ptr, end); - while(ptr < end && readCSSIdentifier(ptr, end, name)) - { + while(ptr < end && readCSSIdentifier(ptr, end, name)) { Utils::skipWs(ptr, end); if(!Utils::skipDesc(ptr, end, ':')) return; @@ -1792,13 +1713,23 @@ static inline void parseStyle(const std::string& string, Element* element) while(ptr < end && *ptr != ';') ++ptr; value.assign(start, Utils::rtrim(start, ptr)); - auto id = cssPropertyId(name); + auto id = csspropertyid(name); if(id != PropertyID::Unknown) element->set(id, value, 0x100); Utils::skipWsDelimiter(ptr, end, ';'); } } +static inline void removeComments(std::string& value) +{ + auto start = value.find("/*"); + while(start != std::string::npos) { + auto end = value.find("*/", start + 2); + value.erase(start, end - start + 2); + start = value.find("/*"); + } +} + TreeBuilder::TreeBuilder() = default; TreeBuilder::~TreeBuilder() = default; @@ -1813,17 +1744,7 @@ bool TreeBuilder::parse(const char* data, std::size_t size) std::string name; std::string value; int ignoring = 0; - - auto remove_comments = [](std::string& value) { - auto start = value.find("/*"); - while(start != std::string::npos) { - auto end = value.find("*/", start + 2); - value.erase(start, end - start + 2); - start = value.find("/*"); - } - }; - - auto handle_text = [&](const char* start, const char* end, bool in_cdata) { + auto handleText = [&](const char* start, const char* end, bool in_cdata) { if(ignoring > 0 || current == nullptr || current->id != ElementID::Style) return; @@ -1832,21 +1753,19 @@ bool TreeBuilder::parse(const char* data, std::size_t size) else decodeText(start, end, value); - remove_comments(value); + removeComments(value); styleSheet.parse(value); }; - while(ptr < end) - { + while(ptr < end) { auto start = ptr; if(!Utils::skipUntil(ptr, end, '<')) break; - handle_text(start, ptr, false); + handleText(start, ptr, false); ptr += 1; - if(ptr < end && *ptr == '/') - { + if(ptr < end && *ptr == '/') { if(current == nullptr && ignoring == 0) return false; @@ -1867,8 +1786,7 @@ bool TreeBuilder::parse(const char* data, std::size_t size) continue; } - if(ptr < end && *ptr == '?') - { + if(ptr < end && *ptr == '?') { ++ptr; if(!readIdentifier(ptr, end, name)) return false; @@ -1880,48 +1798,39 @@ bool TreeBuilder::parse(const char* data, std::size_t size) continue; } - if(ptr < end && *ptr == '!') - { + if(ptr < end && *ptr == '!') { ++ptr; - if(Utils::skipDesc(ptr, end, "--")) - { + if(Utils::skipDesc(ptr, end, "--")) { start = ptr; if(!Utils::skipUntil(ptr, end, "-->")) return false; - handle_text(start, ptr, false); + handleText(start, ptr, false); ptr += 3; continue; } - if(Utils::skipDesc(ptr, end, "[CDATA[")) - { + if(Utils::skipDesc(ptr, end, "[CDATA[")) { start = ptr; if(!Utils::skipUntil(ptr, end, "]]>")) return false; - handle_text(start, ptr, true); + handleText(start, ptr, true); ptr += 3; continue; } - if(Utils::skipDesc(ptr, end, "DOCTYPE")) - { - while(ptr < end && *ptr != '>') - { - if(*ptr == '[') - { + if(Utils::skipDesc(ptr, end, "DOCTYPE")) { + while(ptr < end && *ptr != '>') { + if(*ptr == '[') { ++ptr; int depth = 1; - while(ptr < end && depth > 0) - { + while(ptr < end && depth > 0) { if(*ptr == '[') ++depth; else if(*ptr == ']') --depth; ++ptr; } - } - else - { + } else { ++ptr; } } @@ -1939,26 +1848,23 @@ bool TreeBuilder::parse(const char* data, std::size_t size) if(!readIdentifier(ptr, end, name)) return false; - auto id = ignoring == 0 ? elementId(name) : ElementID::Unknown; + auto id = ElementID::Unknown; + if(ignoring == 0) + id = elementid(name); if(id == ElementID::Unknown) ++ignoring; Element* element = nullptr; - if(ignoring == 0) - { + if(ignoring == 0) { if(m_rootElement && current == nullptr) return false; - if(m_rootElement == nullptr) - { + if(m_rootElement == nullptr) { if(id != ElementID::Svg) return false; - m_rootElement = std::make_unique(); element = m_rootElement.get(); - } - else - { + } else { auto child = createElement(id); element = child.get(); current->addChild(std::move(child)); @@ -1966,8 +1872,7 @@ bool TreeBuilder::parse(const char* data, std::size_t size) } Utils::skipWs(ptr, end); - while(ptr < end && readIdentifier(ptr, end, name)) - { + while(ptr < end && readIdentifier(ptr, end, name)) { Utils::skipWs(ptr, end); if(ptr >= end || *ptr != '=') return false; @@ -1987,17 +1892,15 @@ bool TreeBuilder::parse(const char* data, std::size_t size) if(ptr >= end || *ptr != quote) return false; - auto id = element ? propertyId(name) : PropertyID::Unknown; - if(id != PropertyID::Unknown) - { + auto id = PropertyID::Unknown; + if(element != nullptr) + id = propertyid(name); + if(id != PropertyID::Unknown) { decodeText(start, Utils::rtrim(start, ptr), value); - if(id == PropertyID::Style) - { - remove_comments(value); + if(id == PropertyID::Style) { + removeComments(value); parseStyle(value, element); - } - else - { + } else { if(id == PropertyID::Id) m_idCache.emplace(value, element); element->set(id, value, 0x1); @@ -2008,8 +1911,7 @@ bool TreeBuilder::parse(const char* data, std::size_t size) Utils::skipWs(ptr, end); } - if(ptr < end && *ptr == '>') - { + if(ptr < end && *ptr == '>') { if(element != nullptr) current = element; @@ -2017,8 +1919,7 @@ bool TreeBuilder::parse(const char* data, std::size_t size) continue; } - if(ptr < end && *ptr == '/') - { + if(ptr < end && *ptr == '/') { ++ptr; if(ptr >= end || *ptr != '>') return false; @@ -2036,17 +1937,21 @@ bool TreeBuilder::parse(const char* data, std::size_t size) if(!m_rootElement || ptr < end || ignoring > 0) return false; - if(!styleSheet.empty()) - { + if(!styleSheet.empty()) { m_rootElement->transverse([&styleSheet](Node* node) { if(node->isText()) - return false; + return true; auto element = static_cast(node); - auto declarations = styleSheet.match(element); - for(auto& declaration : declarations) - element->properties.add(*declaration); - return false; + for(auto& rule : styleSheet.rules()) { + if(rule.match(element)) { + for(auto& declaration : rule.declarations()) { + element->set(declaration.id, declaration.value, declaration.specificity); + } + } + } + + return true; }); } @@ -2058,7 +1963,6 @@ Element* TreeBuilder::getElementById(const std::string& id) const auto it = m_idCache.find(id); if(it == m_idCache.end()) return nullptr; - return it->second; } diff --git a/external/lunasvg/source/parser.h b/external/lunasvg/source/parser.h index 76864d3ee..1df9cdb69 100644 --- a/external/lunasvg/source/parser.h +++ b/external/lunasvg/source/parser.h @@ -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; using SelectorList = std::vector; -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 pseudoClassSelectors; }; -struct Rule -{ +struct Declaration { + int specificity; + PropertyID id; + std::string value; +}; + +using DeclarationList = std::vector; + +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 match(const Element* element) const; - -private: - std::multiset m_rules; - uint32_t m_position{0}; -}; - -class CSSParser -{ -public: - CSSParser() = default; - - static bool parseSheet(StyleSheet* sheet, const std::string& value); + const std::multiset& 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 m_rules; + uint32_t m_position{0}; }; class LayoutSymbol; diff --git a/external/lunasvg/source/parserutils.h b/external/lunasvg/source/parserutils.h index e83746d6d..d7d00e59c 100644 --- a/external/lunasvg/source/parserutils.h +++ b/external/lunasvg/source/parserutils.h @@ -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(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; } diff --git a/external/lunasvg/source/property.cpp b/external/lunasvg/source/property.cpp index 6dd4e2c32..fcffa82be 100644 --- a/external/lunasvg/source/property.cpp +++ b/external/lunasvg/source/property.cpp @@ -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(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}; diff --git a/external/lunasvg/source/property.h b/external/lunasvg/source/property.h index b08724704..3b7afd7ab 100644 --- a/external/lunasvg/source/property.h +++ b/external/lunasvg/source/property.h @@ -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; 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 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; -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); diff --git a/external/lunasvg/source/stopelement.h b/external/lunasvg/source/stopelement.h index ee97f2830..161b76194 100644 --- a/external/lunasvg/source/stopelement.h +++ b/external/lunasvg/source/stopelement.h @@ -5,8 +5,7 @@ namespace lunasvg { -class StopElement : public StyledElement -{ +class StopElement : public StyledElement { public: StopElement(); diff --git a/external/lunasvg/source/styledelement.h b/external/lunasvg/source/styledelement.h index 4d0ceb0a0..eb1888dc8 100644 --- a/external/lunasvg/source/styledelement.h +++ b/external/lunasvg/source/styledelement.h @@ -5,8 +5,7 @@ namespace lunasvg { -class StyledElement : public Element -{ +class StyledElement : public Element { public: StyledElement(ElementID id); diff --git a/external/lunasvg/source/styleelement.h b/external/lunasvg/source/styleelement.h index 7c46af155..fbebbb179 100644 --- a/external/lunasvg/source/styleelement.h +++ b/external/lunasvg/source/styleelement.h @@ -5,8 +5,7 @@ namespace lunasvg { -class StyleElement : public Element -{ +class StyleElement : public Element { public: StyleElement(); diff --git a/external/lunasvg/source/svgelement.h b/external/lunasvg/source/svgelement.h index 789a7cad4..210aaffe3 100644 --- a/external/lunasvg/source/svgelement.h +++ b/external/lunasvg/source/svgelement.h @@ -8,8 +8,7 @@ namespace lunasvg { class TreeBuilder; class LayoutSymbol; -class SVGElement : public GraphicsElement -{ +class SVGElement : public GraphicsElement { public: SVGElement(); diff --git a/external/lunasvg/source/symbolelement.h b/external/lunasvg/source/symbolelement.h index e2345f7ad..29ed27987 100644 --- a/external/lunasvg/source/symbolelement.h +++ b/external/lunasvg/source/symbolelement.h @@ -5,8 +5,7 @@ namespace lunasvg { -class SymbolElement : public StyledElement -{ +class SymbolElement : public StyledElement { public: SymbolElement(); diff --git a/external/lunasvg/source/useelement.cpp b/external/lunasvg/source/useelement.cpp index ced0ec004..348cb727b 100644 --- a/external/lunasvg/source/useelement.cpp +++ b/external/lunasvg/source/useelement.cpp @@ -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(); transferWidthAndHeight(element.get()); group->addChild(std::move(element)); - } - else - { + } else { group->addChild(ref->clone()); } diff --git a/external/lunasvg/source/useelement.h b/external/lunasvg/source/useelement.h index ea898f232..46747dc10 100644 --- a/external/lunasvg/source/useelement.h +++ b/external/lunasvg/source/useelement.h @@ -5,8 +5,7 @@ namespace lunasvg { -class UseElement : public GraphicsElement -{ +class UseElement : public GraphicsElement { public: UseElement();