diff options
-rw-r--r-- | include/cru/platform/graphics/Geometry.h | 46 | ||||
-rw-r--r-- | include/cru/platform/graphics/SvgGeometry.h | 10 | ||||
-rw-r--r-- | include/cru/platform/graphics/web_canvas/WebCanvasGeometry.h | 27 | ||||
-rw-r--r-- | include/cru/platform/graphics/web_canvas/WebCanvasPainter.h | 8 | ||||
-rw-r--r-- | include/cru/platform/web/Js.h | 17 | ||||
-rw-r--r-- | include/cru/platform/web/JsUtility.h | 9 | ||||
-rw-r--r-- | src/platform/graphics/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/platform/graphics/Geometry.cpp | 31 | ||||
-rw-r--r-- | src/platform/graphics/SvgGeometry.cpp | 1 | ||||
-rw-r--r-- | src/platform/graphics/web_canvas/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/platform/graphics/web_canvas/Geometry.cpp | 12 | ||||
-rw-r--r-- | src/platform/graphics/web_canvas/Painter.cpp | 23 | ||||
-rw-r--r-- | src/platform/graphics/web_canvas/WebCanvasRef.cpp | 4 | ||||
-rw-r--r-- | src/platform/web/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/platform/web/Js.cpp | 13 | ||||
-rw-r--r-- | src/platform/web/JsUtility.cpp | 11 |
16 files changed, 168 insertions, 48 deletions
diff --git a/include/cru/platform/graphics/Geometry.h b/include/cru/platform/graphics/Geometry.h index d1045b59..112c95e6 100644 --- a/include/cru/platform/graphics/Geometry.h +++ b/include/cru/platform/graphics/Geometry.h @@ -17,49 +17,45 @@ struct CRU_PLATFORM_GRAPHICS_API IGeometry : virtual IGraphicsResource { virtual std::unique_ptr<IGeometry> CreateStrokeGeometry(float width) = 0; }; +/** + * \remarks We always run into platform porting problems. When I designed this + * interface, I thought every platform would support GetCurrentPosition. + * However, this is not actually true. + * For web canvas, it turns out that it can't get current position. So I have to + * not implement or use it, which disables every relative actions because they + * depend on it. But luckily, the web canvas path can be constructed from svg + * path (see https://developer.mozilla.org/en-US/docs/Web/API/Path2D/Path2D). So + * I come up with a new idea that first create a geometry describe itself in + * svg, and then construct path from it. And all relative methods should become + * virtual so it can override them. + */ struct CRU_PLATFORM_GRAPHICS_API IGeometryBuilder : virtual IGraphicsResource { virtual Point GetCurrentPosition() = 0; virtual void MoveTo(const Point& point) = 0; - void RelativeMoveTo(const Point& offset) { - MoveTo(GetCurrentPosition() + offset); - } + virtual void RelativeMoveTo(const Point& offset); virtual void LineTo(const Point& point) = 0; void LineTo(float x, float y) { LineTo(Point(x, y)); } - void RelativeLineTo(const Point& offset) { - LineTo(GetCurrentPosition() + offset); - } + virtual void RelativeLineTo(const Point& offset); void RelativeLineTo(float x, float y) { RelativeLineTo(Point(x, y)); } virtual void CubicBezierTo(const Point& start_control_point, const Point& end_control_point, const Point& end_point) = 0; - void RelativeCubicBezierTo(const Point& start_control_offset, - const Point& end_control_offset, - const Point& end_offset) { - auto current_position = GetCurrentPosition(); - CubicBezierTo(current_position + start_control_offset, - current_position + end_control_offset, - current_position + end_offset); - } + virtual void RelativeCubicBezierTo(const Point& start_control_offset, + const Point& end_control_offset, + const Point& end_offset); virtual void QuadraticBezierTo(const Point& control_point, const Point& end_point) = 0; - void RelativeQuadraticBezierTo(const Point& control_offset, - const Point& end_offset) { - auto current_position = GetCurrentPosition(); - QuadraticBezierTo(current_position + control_offset, - current_position + end_offset); - } + virtual void RelativeQuadraticBezierTo(const Point& control_offset, + const Point& end_offset); virtual void ArcTo(const Point& radius, float angle, bool is_large_arc, bool is_clockwise, const Point& end_point); - void RelativeArcTo(const Point& radius, float angle, bool is_large_arc, - bool is_clockwise, const Point& end_offset) { - ArcTo(radius, angle, is_large_arc, is_clockwise, - GetCurrentPosition() + 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/SvgGeometry.h new file mode 100644 index 00000000..281158f0 --- /dev/null +++ b/include/cru/platform/graphics/SvgGeometry.h @@ -0,0 +1,10 @@ +#pragma once + +#include "Geometry.h" + +namespace cru::platform::graphics { +class CRU_PLATFORM_GRAPHICS_API SvgGeometryBuilder : public virtual IGeometryBuilder { + +}; +} + diff --git a/include/cru/platform/graphics/web_canvas/WebCanvasGeometry.h b/include/cru/platform/graphics/web_canvas/WebCanvasGeometry.h new file mode 100644 index 00000000..af4cee91 --- /dev/null +++ b/include/cru/platform/graphics/web_canvas/WebCanvasGeometry.h @@ -0,0 +1,27 @@ +#pragma once + +#include "../Geometry.h" +#include "WebCanvasResource.h" + +#include <emscripten/val.h> + +namespace cru::platform::graphics::web_canvas { +/** + * \remarks See IGeometryBuilder for platform limitation. + */ +class WebCanvasGeometryBuilder : public WebCanvasResource, + public virtual IGeometryBuilder { + public: + WebCanvasGeometryBuilder(WebCanvasGraphicsFactory* factory); + + ~WebCanvasGeometryBuilder() override; + + Point GetCurrentPosition() override; + + void MoveTo(const Point& point) override; + + private: + Point current_postion_; + emscripten::val path2d_; +}; +} // namespace cru::platform::graphics::web_canvas diff --git a/include/cru/platform/graphics/web_canvas/WebCanvasPainter.h b/include/cru/platform/graphics/web_canvas/WebCanvasPainter.h index 0832831c..bb092f2f 100644 --- a/include/cru/platform/graphics/web_canvas/WebCanvasPainter.h +++ b/include/cru/platform/graphics/web_canvas/WebCanvasPainter.h @@ -35,6 +35,14 @@ class WebCanvasPainter : public WebCanvasResource, public virtual IPainter { void DrawLine(const Point& start, const Point& end, IBrush* brush, float width) override; + void StrokeRectangle(const Rect& rectangle, IBrush* brush, + float width) override; + + void FillRectangle(const Rect& rectangle, IBrush* brush) override; + void StrokeEllipse(const Rect& outline_rect, IBrush* brush, + float width) override; + void FillEllipse(const Rect& outline_rect, IBrush* brush) override; + emscripten::val GetCanvas2DContext() const { return context_; } WebCanvasRef GetCanvas(); diff --git a/include/cru/platform/web/Js.h b/include/cru/platform/web/Js.h new file mode 100644 index 00000000..b4c91702 --- /dev/null +++ b/include/cru/platform/web/Js.h @@ -0,0 +1,17 @@ +#pragma once + +#include <emscripten/val.h> +#include <utility> + +namespace cru::platform::web::js { +bool IsNotNullAndInstanceOf(const emscripten::val& value, + const emscripten::val& type); +bool IsNotNullAndInstanceOf(const emscripten::val& value, + const char* global_type); + +template <typename... Args> +emscripten::val Construct(const char* class_name, Args&&... args) { + emscripten::val constructor = emscripten::val::global(class_name); + return constructor.new_(std::forward<Args>(args)...); +} +} // namespace cru::platform::web diff --git a/include/cru/platform/web/JsUtility.h b/include/cru/platform/web/JsUtility.h deleted file mode 100644 index 37c2735d..00000000 --- a/include/cru/platform/web/JsUtility.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include <emscripten/val.h> - -namespace cru::platform::web { - bool IsNotNullAndInstanceOf(const emscripten::val& value, const emscripten::val& type); - bool IsNotNullAndInstanceOf(const emscripten::val& value, const char* global_type); -} - diff --git a/src/platform/graphics/CMakeLists.txt b/src/platform/graphics/CMakeLists.txt index b6362961..1b24c22b 100644 --- a/src/platform/graphics/CMakeLists.txt +++ b/src/platform/graphics/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(CruPlatformGraphics Geometry.cpp Image.cpp NullPainter.cpp + SvgGeometry.cpp ) target_compile_definitions(CruPlatformGraphics PRIVATE CRU_PLATFORM_GRAPHICS_EXPORT_API) target_link_libraries(CruPlatformGraphics PUBLIC CruPlatformBase) diff --git a/src/platform/graphics/Geometry.cpp b/src/platform/graphics/Geometry.cpp index 20197153..b6f2a724 100644 --- a/src/platform/graphics/Geometry.cpp +++ b/src/platform/graphics/Geometry.cpp @@ -12,6 +12,37 @@ bool IGeometry::StrokeContains(float width, const Point& point) { return geometry->FillContains(point); } +void IGeometryBuilder::RelativeMoveTo(const Point& offset) { + MoveTo(GetCurrentPosition() + offset); +} + +void IGeometryBuilder::RelativeLineTo(const Point& offset) { + LineTo(GetCurrentPosition() + offset); +} + +void IGeometryBuilder::RelativeCubicBezierTo(const Point& start_control_offset, + const Point& end_control_offset, + const Point& end_offset) { + auto current_position = GetCurrentPosition(); + CubicBezierTo(current_position + start_control_offset, + current_position + end_control_offset, + current_position + end_offset); +} + +void IGeometryBuilder::RelativeQuadraticBezierTo(const Point& control_offset, + const Point& end_offset) { + auto current_position = GetCurrentPosition(); + QuadraticBezierTo(current_position + control_offset, + current_position + end_offset); +} + +void IGeometryBuilder::RelativeArcTo(const Point& radius, float angle, + bool is_large_arc, bool is_clockwise, + const Point& end_offset) { + ArcTo(radius, angle, is_large_arc, is_clockwise, + GetCurrentPosition() + end_offset); +} + constexpr float PI = 3.14159265358979323846f; using std::abs; diff --git a/src/platform/graphics/SvgGeometry.cpp b/src/platform/graphics/SvgGeometry.cpp new file mode 100644 index 00000000..149c4bb6 --- /dev/null +++ b/src/platform/graphics/SvgGeometry.cpp @@ -0,0 +1 @@ +#include "cru/platform/graphics/SvgGeometry.h" diff --git a/src/platform/graphics/web_canvas/CMakeLists.txt b/src/platform/graphics/web_canvas/CMakeLists.txt index bbf736e0..d0a1a7d9 100644 --- a/src/platform/graphics/web_canvas/CMakeLists.txt +++ b/src/platform/graphics/web_canvas/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(CruPlatformGraphicsWebCanvas Brush.cpp Factory.cpp + Geometry.cpp Painter.cpp Resource.cpp WebCanvasRef.cpp diff --git a/src/platform/graphics/web_canvas/Geometry.cpp b/src/platform/graphics/web_canvas/Geometry.cpp new file mode 100644 index 00000000..eb4ce84e --- /dev/null +++ b/src/platform/graphics/web_canvas/Geometry.cpp @@ -0,0 +1,12 @@ +#include "cru/platform/graphics/web_canvas/WebCanvasGeometry.h" +#include "cru/platform/graphics/web_canvas/WebCanvasGraphicsFactory.h" +#include "cru/platform/graphics/web_canvas/WebCanvasResource.h" +#include "cru/platform/web/Js.h" + +namespace cru::platform::graphics::web_canvas { +WebCanvasGeometryBuilder::WebCanvasGeometryBuilder( + WebCanvasGraphicsFactory* factory) + : WebCanvasResource(factory) { + path2d_ = web::js::Construct("Path2D"); +} +} // namespace cru::platform::graphics::web_canvas diff --git a/src/platform/graphics/web_canvas/Painter.cpp b/src/platform/graphics/web_canvas/Painter.cpp index a78ab9f1..c9184165 100644 --- a/src/platform/graphics/web_canvas/Painter.cpp +++ b/src/platform/graphics/web_canvas/Painter.cpp @@ -59,6 +59,29 @@ void WebCanvasPainter::DrawLine(const Point& start, const Point& end, context_.call<void>("stroke"); } +void WebCanvasPainter::StrokeRectangle(const Rect& rectangle, IBrush* brush, + float width) { + SetStrokeStyle(brush, width); + context_.call<void>("strokeRect", rectangle.left, rectangle.top, + rectangle.width, rectangle.height); +} + +void WebCanvasPainter::FillRectangle(const Rect& rectangle, IBrush* brush) { + SetFillStyle(brush); + context_.call<void>("fillRect", rectangle.left, rectangle.top, + rectangle.width, rectangle.height); +} + +void WebCanvasPainter::StrokeEllipse(const Rect& outline_rect, IBrush* brush, + float width) { + SetStrokeStyle(brush); + // TODO: Need to use path. +} +void WebCanvasPainter::FillEllipse(const Rect& outline_rect, IBrush* brush) { + SetFillStyle(brush); + // TODO: Need to use path. +} + void WebCanvasPainter::SetStrokeStyle(IBrush* brush, float width) { context_.set("strokeStyle", ConvertBrush(brush)->GetStyle()); if (width > 0) { diff --git a/src/platform/graphics/web_canvas/WebCanvasRef.cpp b/src/platform/graphics/web_canvas/WebCanvasRef.cpp index c4f75626..886131f6 100644 --- a/src/platform/graphics/web_canvas/WebCanvasRef.cpp +++ b/src/platform/graphics/web_canvas/WebCanvasRef.cpp @@ -1,5 +1,5 @@ #include "cru/platform/graphics/web_canvas/WebCanvasRef.h" -#include "cru/platform/web/JsUtility.h" +#include "cru/platform/web/Js.h" #include <cassert> #include <utility> @@ -7,7 +7,7 @@ namespace cru::platform::graphics::web_canvas { WebCanvasRef::WebCanvasRef(emscripten::val canvas_val) : val_(std::move(canvas_val)) { - assert(web::IsNotNullAndInstanceOf(val_, "HTMLCanvasElement")); + assert(web::js::IsNotNullAndInstanceOf(val_, "HTMLCanvasElement")); } int WebCanvasRef::GetWidth() const { return val_["width"].as<int>(); } diff --git a/src/platform/web/CMakeLists.txt b/src/platform/web/CMakeLists.txt index 0a9bd6dd..3d11e428 100644 --- a/src/platform/web/CMakeLists.txt +++ b/src/platform/web/CMakeLists.txt @@ -1,5 +1,5 @@ add_library(CruPlatformBaseWeb - JsUtility.cpp + Js.cpp Resource.cpp ) diff --git a/src/platform/web/Js.cpp b/src/platform/web/Js.cpp new file mode 100644 index 00000000..ea8a0d68 --- /dev/null +++ b/src/platform/web/Js.cpp @@ -0,0 +1,13 @@ +#include "cru/platform/web/Js.h" + +namespace cru::platform::web { +bool IsNotNullAndInstanceOf(const emscripten::val& value, + const emscripten::val& type) { + return !value.isNull() && !type.isNull() && value.instanceof (type); +} + +bool IsNotNullAndInstanceOf(const emscripten::val& value, + const char* global_type) { + return IsNotNullAndInstanceOf(value, emscripten::val::global(global_type)); +} +} // namespace cru::platform::web diff --git a/src/platform/web/JsUtility.cpp b/src/platform/web/JsUtility.cpp deleted file mode 100644 index b426bbda..00000000 --- a/src/platform/web/JsUtility.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "cru/platform/web/JsUtility.h" - -namespace cru::platform::web { -bool IsNotNullAndInstanceOf(const emscripten::val& value, const emscripten::val& type) { - return !value.isNull() && !type.isNull() && value.instanceof(type); -} - -bool IsNotNullAndInstanceOf(const emscripten::val& value, const char* global_type) { - return IsNotNullAndInstanceOf(value, emscripten::val::global(global_type)); -} -} |