aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2023-10-12 20:10:07 +0800
committercrupest <crupest@outlook.com>2023-10-12 20:10:07 +0800
commitab484b2f0a8541cc5c5a172e4f5ea2620d91c8ba (patch)
treee69c02dd76350c17fb9645c216ec2bae69da6c21
parent8739c5d1c544015d0a7e998859a78d4ac3afc8b9 (diff)
downloadcru-ab484b2f0a8541cc5c5a172e4f5ea2620d91c8ba.tar.gz
cru-ab484b2f0a8541cc5c5a172e4f5ea2620d91c8ba.tar.bz2
cru-ab484b2f0a8541cc5c5a172e4f5ea2620d91c8ba.zip
SvgGeometryBuilder done!
-rw-r--r--include/cru/platform/Color.h12
-rw-r--r--include/cru/platform/GraphicsBase.h23
-rw-r--r--include/cru/platform/graphics/Geometry.h2
-rw-r--r--include/cru/platform/graphics/SvgGeometry.h57
-rw-r--r--src/platform/graphics/SvgGeometry.cpp120
5 files changed, 196 insertions, 18 deletions
diff --git a/include/cru/platform/Color.h b/include/cru/platform/Color.h
index 2b38138a..0d7bce5b 100644
--- a/include/cru/platform/Color.h
+++ b/include/cru/platform/Color.h
@@ -257,11 +257,6 @@ extern const std::unordered_map<StringView, Color> predefined_name_color_map;
std::optional<Color> GetPredefinedColorByName(StringView name);
-inline String ToString(const Color& color) {
- return cru::Format(u"rgba({}, {}, {}, {})", color.red, color.green,
- color.blue, color.alpha);
-}
-
struct CRU_PLATFORM_API HslColor {
HslColor() = default;
HslColor(float h, float s, float l, float a = 1.0f)
@@ -276,3 +271,10 @@ struct CRU_PLATFORM_API HslColor {
float a;
};
} // namespace cru::platform
+
+namespace cru {
+inline String ToString(const platform::Color& color) {
+ return cru::Format(u"rgba({}, {}, {}, {})", color.red, color.green,
+ color.blue, color.alpha);
+}
+} // namespace cru
diff --git a/include/cru/platform/GraphicsBase.h b/include/cru/platform/GraphicsBase.h
index f134e74d..88dc6ee2 100644
--- a/include/cru/platform/GraphicsBase.h
+++ b/include/cru/platform/GraphicsBase.h
@@ -5,11 +5,7 @@
#include "cru/common/Range.h"
#include "cru/common/String.h"
-#include <cstdint>
#include <limits>
-#include <optional>
-#include <string>
-#include <utility>
namespace cru::platform {
struct Size;
@@ -47,10 +43,6 @@ constexpr bool operator!=(const Point& left, const Point& right) {
return !(left == right);
}
-inline String ToString(const Point& point) {
- return Format(u"(x: {}, y: {})", point.x, point.y);
-}
-
struct CRU_PLATFORM_API Size final {
static const Size kMax;
static const Size kZero;
@@ -88,10 +80,6 @@ constexpr bool operator!=(const Size& left, const Size& right) {
return !(left == right);
}
-inline String ToString(const Size& size) {
- return Format(u"(width: {}, height: {})", size.width, size.height);
-}
-
struct Thickness final {
constexpr Thickness() : Thickness(0) {}
@@ -290,3 +278,14 @@ constexpr bool operator!=(const Ellipse& left, const Ellipse& right) {
using TextRange = Range;
} // namespace cru::platform
+
+namespace cru {
+
+inline String ToString(const platform::Point& point) {
+ return Format(u"(x: {}, y: {})", point.x, point.y);
+}
+inline String ToString(const platform::Size& size) {
+ return Format(u"(width: {}, height: {})", size.width, size.height);
+}
+
+} // namespace cru
diff --git a/include/cru/platform/graphics/Geometry.h b/include/cru/platform/graphics/Geometry.h
index 112c95e6..0e0278d2 100644
--- a/include/cru/platform/graphics/Geometry.h
+++ b/include/cru/platform/graphics/Geometry.h
@@ -61,7 +61,7 @@ struct CRU_PLATFORM_GRAPHICS_API IGeometryBuilder : virtual IGraphicsResource {
virtual std::unique_ptr<IGeometry> Build() = 0;
- void ParseAndApplySvgPathData(StringView path_d);
+ virtual void ParseAndApplySvgPathData(StringView path_d);
};
std::unique_ptr<IGeometry> CRU_PLATFORM_GRAPHICS_API
diff --git a/include/cru/platform/graphics/SvgGeometry.h b/include/cru/platform/graphics/SvgGeometry.h
index 742a68ca..65602578 100644
--- a/include/cru/platform/graphics/SvgGeometry.h
+++ b/include/cru/platform/graphics/SvgGeometry.h
@@ -1,16 +1,73 @@
#pragma once
#include "Geometry.h"
+#include "cru/common/Base.h"
+#include "cru/common/Format.h"
+
+#include <utility>
namespace cru::platform::graphics {
+/**
+ * \remarks This class is purely a helper for some platforms, especially web
+ * canvas. It constructs a path data of svg of a list of commands. It can't
+ * generate a Geometry. Calling Build will throw a PlatformUnsupportedException.
+ * Instead, use GetPathData to get svg path data and use it to do other things.
+ */
class CRU_PLATFORM_GRAPHICS_API SvgGeometryBuilder
: public Object,
public virtual IGeometryBuilder {
public:
SvgGeometryBuilder();
+ CRU_DELETE_COPY(SvgGeometryBuilder)
+ CRU_DELETE_MOVE(SvgGeometryBuilder)
+
~SvgGeometryBuilder() override;
+ Point GetCurrentPosition() override;
+
+ void MoveTo(const Point& point) override;
+ void RelativeMoveTo(const Point& offset) override;
+
+ void LineTo(const Point& point) override;
+ void RelativeLineTo(const Point& offset) override;
+
+ void CubicBezierTo(const Point& start_control_point,
+ const Point& end_control_point,
+ const Point& end_point) override;
+ void RelativeCubicBezierTo(const Point& start_control_offset,
+ const Point& end_control_offset,
+ const Point& end_offset) override;
+
+ void QuadraticBezierTo(const Point& control_point,
+ const Point& end_point) override;
+ void RelativeQuadraticBezierTo(const Point& control_offset,
+ const Point& end_offset) override;
+
+ void ArcTo(const Point& radius, float angle, bool is_large_arc,
+ bool is_clockwise, const Point& end_point) override;
+ void RelativeArcTo(const Point& radius, float angle, bool is_large_arc,
+ bool is_clockwise, const Point& end_offset) override;
+
+ void CloseFigure(bool close) override;
+
+ std::unique_ptr<IGeometry> Build() override;
+
+ String GetPathData() const { return current_; }
+
+ void ParseAndApplySvgPathData(StringView path_d) override;
+
+ template <typename... Args>
+ void Append(StringView format, Args&&... args) {
+ current_ += Format(format, std::forward<Args>(args)...);
+ current_ += u' ';
+ }
+
+ void AppendCommand(StringView command);
+ void Append(bool flag);
+ void Append(float number);
+ void Append(const Point& point);
+
private:
String current_;
};
diff --git a/src/platform/graphics/SvgGeometry.cpp b/src/platform/graphics/SvgGeometry.cpp
index b757c520..20ef1b56 100644
--- a/src/platform/graphics/SvgGeometry.cpp
+++ b/src/platform/graphics/SvgGeometry.cpp
@@ -1,7 +1,127 @@
#include "cru/platform/graphics/SvgGeometry.h"
+#include "cru/platform/Exception.h"
+#include "cru/platform/graphics/Geometry.h"
namespace cru::platform::graphics {
SvgGeometryBuilder::SvgGeometryBuilder() {}
SvgGeometryBuilder::~SvgGeometryBuilder() {}
+
+Point SvgGeometryBuilder::GetCurrentPosition() {
+ throw PlatformUnsupportedException(
+ GetPlatformId(), u"GetCurrentPosition",
+ u"Svg geometry does not support get current position.");
+}
+
+void SvgGeometryBuilder::MoveTo(const Point& point) {
+ AppendCommand(u"M");
+ Append(point);
+}
+
+void SvgGeometryBuilder::RelativeMoveTo(const Point& offset) {
+ AppendCommand(u"m");
+ Append(offset);
+}
+
+void SvgGeometryBuilder::LineTo(const Point& point) {
+ AppendCommand(u"L");
+ Append(point);
+}
+
+void SvgGeometryBuilder::RelativeLineTo(const Point& offset) {
+ AppendCommand(u"l");
+ Append(offset);
+}
+
+void SvgGeometryBuilder::CubicBezierTo(const Point& start_control_point,
+ const Point& end_control_point,
+ const Point& end_point) {
+ AppendCommand(u"C");
+ Append(start_control_point);
+ Append(end_control_point);
+ Append(end_point);
+}
+
+void SvgGeometryBuilder::RelativeCubicBezierTo(
+ const Point& start_control_offset, const Point& end_control_offset,
+ const Point& end_offset) {
+ AppendCommand(u"c");
+ Append(start_control_offset);
+ Append(end_control_offset);
+ Append(end_offset);
+}
+
+void SvgGeometryBuilder::QuadraticBezierTo(const Point& control_point,
+ const Point& end_point) {
+ AppendCommand(u"Q");
+ Append(control_point);
+ Append(end_point);
+}
+
+void SvgGeometryBuilder::RelativeQuadraticBezierTo(const Point& control_offset,
+ const Point& end_offset) {
+ AppendCommand(u"q");
+ Append(control_offset);
+ Append(end_offset);
+}
+
+void SvgGeometryBuilder::ArcTo(const Point& radius, float angle,
+ bool is_large_arc, bool is_clockwise,
+ const Point& end_point) {
+ AppendCommand(u"A");
+ Append(radius.x);
+ Append(radius.y);
+ Append(angle);
+ Append(is_large_arc);
+ Append(is_clockwise);
+ Append(end_point);
+}
+
+void SvgGeometryBuilder::RelativeArcTo(const Point& radius, float angle,
+ bool is_large_arc, bool is_clockwise,
+ const Point& end_offset) {
+ AppendCommand(u"a");
+ Append(radius.x);
+ Append(radius.y);
+ Append(angle);
+ Append(is_large_arc);
+ Append(is_clockwise);
+ Append(end_offset);
+}
+
+void SvgGeometryBuilder::CloseFigure(bool close) {
+ if (close) AppendCommand(u"z");
+}
+
+std::unique_ptr<IGeometry> SvgGeometryBuilder::Build() {
+ throw PlatformUnsupportedException(
+ u"SvgGeometryBuilder", u"Build",
+ u"SvgGeometryBuilder can't build a Geometry. Use GetPathData instead.");
+}
+
+void SvgGeometryBuilder::ParseAndApplySvgPathData(StringView path_d) {
+ AppendCommand(path_d);
+}
+
+void SvgGeometryBuilder::AppendCommand(StringView command) {
+ current_ += command;
+ current_ += u' ';
+}
+
+void SvgGeometryBuilder::Append(bool flag) {
+ current_ += flag ? u'1' : u'0';
+ current_ += u' ';
+}
+
+void SvgGeometryBuilder::Append(float number) {
+ current_ += ToString(number);
+ current_ += u' ';
+}
+
+void SvgGeometryBuilder::Append(const Point& point) {
+ current_ += ToString(point.x);
+ current_ += u',';
+ current_ += ToString(point.y);
+ current_ += u' ';
+}
} // namespace cru::platform::graphics