aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2023-10-12 21:21:26 +0800
committercrupest <crupest@outlook.com>2023-10-12 21:21:26 +0800
commit3c5aa6583d7ab2533ff721282d1efd52d07281c7 (patch)
treec545f412e970f96c8314300672dfa3b3217dbd1f /include
parentab484b2f0a8541cc5c5a172e4f5ea2620d91c8ba (diff)
downloadcru-3c5aa6583d7ab2533ff721282d1efd52d07281c7.tar.gz
cru-3c5aa6583d7ab2533ff721282d1efd52d07281c7.tar.bz2
cru-3c5aa6583d7ab2533ff721282d1efd52d07281c7.zip
Make svg geometry builder a mixin. Record a lot of notes for geometry.
Diffstat (limited to 'include')
-rw-r--r--include/cru/platform/graphics/Geometry.h59
-rw-r--r--include/cru/platform/graphics/SvgGeometryBuilderMixin.h (renamed from include/cru/platform/graphics/SvgGeometry.h)26
-rw-r--r--include/cru/platform/graphics/web_canvas/WebCanvasGeometry.h25
3 files changed, 81 insertions, 29 deletions
diff --git a/include/cru/platform/graphics/Geometry.h b/include/cru/platform/graphics/Geometry.h
index 0e0278d2..71d003f6 100644
--- a/include/cru/platform/graphics/Geometry.h
+++ b/include/cru/platform/graphics/Geometry.h
@@ -4,17 +4,65 @@
#include <memory>
namespace cru::platform::graphics {
+/**
+ * \remarks Geometry implementation is a disaster zone of platform problems.
+ * Here are some notes. For geometry object:
+ * 1. Some platforms just lack the concept of geometry, like web canvas. Even if
+ * there is one, it usually has limited capabilities. They only allow you to
+ * create path right on the context and use it directly. The geometry itself
+ * can't be separated from context and stored independently, not to mention run
+ * some functions. You can't even create a geometry from current state of
+ * context. In one word, context -x-> geometry, geometry is weak.
+ * 2. Doing hit test right on the geometry is not supported on some platform.
+ * The geometry needs to be put on the context first.
+ * 3. Transform a geometry to create a new geometry is not supported on some
+ * platforms. You can transform the context, but no for geometry itself
+ * independently.
+ * 4. Create a geometry of a stroke of another geometry is not suppored more
+ * widely.
+ *
+ * Workarounds:
+ * 1. If the platform didn't support path at all, although not a platform does
+ * so far, record the commands and replay it on context when it is used.
+ * 2. If the geometry can't do hit test itself, always attach a canvas with it,
+ * and when do hit test, put it on context first.
+ * 3. If transform a geometry to create a new geometry is not supported, zip the
+ * original geometry and a transform matrix. When it is used on context, restore
+ * geometry and matrix the same time.
+ * 4. There is no good workaround for 4, so don't use it, maybe.
+ *
+ * Also note for 3, even we can workaround like that, but there are cases it
+ * does not work. Like if we add the support for adding an existing path to a
+ * new path, transform can only be performed on context and we can't construct a
+ * geometry from context, then it fails.
+ *
+ * For geometry builder:
+ * It is hard to conclude the common commands of all platforms. Some have this,
+ * others not. Some don't have this, but others do. There are some common
+ * commands that should be used frequently. If some platforms do not support it,
+ * do it yourself to implement it with existing commands and fancy algorithm.
+ *
+ */
struct CRU_PLATFORM_GRAPHICS_API IGeometry : virtual IGraphicsResource {
/**
- * \remarks Because I designed CreateStrokeGeometry first, which might be not
+ * \remarks Because I designed CreateStrokeGeometry first, which might be not
* that rational. So the default implementation calls that method and do the
* test. New implementation should override this.
*/
virtual bool StrokeContains(float width, const Point& point);
virtual bool FillContains(const Point& point) = 0;
virtual Rect GetBounds() = 0;
+
+ /**
+ * \remarks See class doc for platform limitation.
+ */
virtual std::unique_ptr<IGeometry> Transform(const Matrix& matrix) = 0;
- virtual std::unique_ptr<IGeometry> CreateStrokeGeometry(float width) = 0;
+
+ /**
+ * \remarks This method is a little quirky. It is originated from Direct2D,
+ * but many platforms do not support this, I guess. So don't use this anymore.
+ */
+ virtual std::unique_ptr<IGeometry> CreateStrokeGeometry(float width);
};
/**
@@ -50,12 +98,13 @@ struct CRU_PLATFORM_GRAPHICS_API IGeometryBuilder : virtual IGraphicsResource {
virtual void QuadraticBezierTo(const Point& control_point,
const Point& end_point) = 0;
virtual void RelativeQuadraticBezierTo(const Point& control_offset,
- const Point& end_offset);
+ const Point& end_offset);
virtual void ArcTo(const Point& radius, float angle, bool is_large_arc,
bool is_clockwise, const Point& end_point);
- virtual void RelativeArcTo(const Point& radius, float angle, bool is_large_arc,
- bool is_clockwise, const Point& end_offset);
+ virtual void RelativeArcTo(const Point& radius, float angle,
+ bool is_large_arc, bool is_clockwise,
+ const Point& end_offset);
virtual void CloseFigure(bool close) = 0;
diff --git a/include/cru/platform/graphics/SvgGeometry.h b/include/cru/platform/graphics/SvgGeometryBuilderMixin.h
index 65602578..d516ce6c 100644
--- a/include/cru/platform/graphics/SvgGeometry.h
+++ b/include/cru/platform/graphics/SvgGeometryBuilderMixin.h
@@ -1,28 +1,22 @@
#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.
+ * \remarks This class is a helper mixin for some platforms, especially web
+ * canvas. It constructs a svg data by recording commands. Use GetPathData to
+ * get svg path data and use it to build real geometry.
*/
-class CRU_PLATFORM_GRAPHICS_API SvgGeometryBuilder
- : public Object,
- public virtual IGeometryBuilder {
+class CRU_PLATFORM_GRAPHICS_API SvgGeometryBuilderMixin
+ : public virtual IGeometryBuilder {
public:
- SvgGeometryBuilder();
+ SvgGeometryBuilderMixin();
- CRU_DELETE_COPY(SvgGeometryBuilder)
- CRU_DELETE_MOVE(SvgGeometryBuilder)
-
- ~SvgGeometryBuilder() override;
+ ~SvgGeometryBuilderMixin() override;
Point GetCurrentPosition() override;
@@ -51,12 +45,12 @@ class CRU_PLATFORM_GRAPHICS_API SvgGeometryBuilder
void CloseFigure(bool close) override;
- std::unique_ptr<IGeometry> Build() override;
+ void ParseAndApplySvgPathData(StringView path_d) override;
+ protected:
String GetPathData() const { return current_; }
- void ParseAndApplySvgPathData(StringView path_d) override;
-
+ private:
template <typename... Args>
void Append(StringView format, Args&&... args) {
current_ += Format(format, std::forward<Args>(args)...);
diff --git a/include/cru/platform/graphics/web_canvas/WebCanvasGeometry.h b/include/cru/platform/graphics/web_canvas/WebCanvasGeometry.h
index af4cee91..dfb5bbe7 100644
--- a/include/cru/platform/graphics/web_canvas/WebCanvasGeometry.h
+++ b/include/cru/platform/graphics/web_canvas/WebCanvasGeometry.h
@@ -1,27 +1,36 @@
#pragma once
#include "../Geometry.h"
+#include "../SvgGeometryBuilderMixin.h"
#include "WebCanvasResource.h"
#include <emscripten/val.h>
+#include <memory>
namespace cru::platform::graphics::web_canvas {
+class WebCanvasGeometry : public WebCanvasResource, public virtual IGeometry {
+ public:
+ WebCanvasGeometry(WebCanvasGraphicsFactory* factory, emscripten::val path2d);
+ ~WebCanvasGeometry() override;
+
+ bool StrokeContains(float width, const Point& point) override;
+ virtual bool FillContains(const Point& point) = 0;
+ virtual Rect GetBounds() = 0;
+ virtual std::unique_ptr<IGeometry> Transform(const Matrix& matrix) = 0;
+ private:
+ emscripten::val path2d_;
+};
+
/**
* \remarks See IGeometryBuilder for platform limitation.
*/
class WebCanvasGeometryBuilder : public WebCanvasResource,
- public virtual IGeometryBuilder {
+ public SvgGeometryBuilderMixin {
public:
WebCanvasGeometryBuilder(WebCanvasGraphicsFactory* factory);
~WebCanvasGeometryBuilder() override;
- Point GetCurrentPosition() override;
-
- void MoveTo(const Point& point) override;
-
- private:
- Point current_postion_;
- emscripten::val path2d_;
+ std::unique_ptr<IGeometry> Build() override;
};
} // namespace cru::platform::graphics::web_canvas