diff --git a/Crafter.Web-Canvas.cpp b/Crafter.Web-Canvas.cpp new file mode 100644 index 0000000..4985b8b --- /dev/null +++ b/Crafter.Web-Canvas.cpp @@ -0,0 +1,42 @@ +/* +Crafter.Web +Copyright (C) 2024 Catcrafts +Catcrafts.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +module; +#include +#include +#include +#include +#include +#include +module Crafter.Web; +using namespace Crafter::Web; + +Canvas::Canvas(std::uint32_t width, std::uint32_t height, std::string value, std::unordered_map style, std::vector children , std::unordered_map attributes) : HtmlElement("canvas", value, style, children, attributes), width(width), height(height) { + this->attributes.insert({"width",std::to_string(width)}); + this->attributes.insert({"height",std::to_string(height)}); +} + +void Canvas::DrawRect(std::uint32_t x, std::uint32_t y, std::uint32_t width, std::uint32_t height, std::string color) { + Crafter::Web::Bindings::StrokeRect(id, x, y, width, height, color.c_str(), color.size()); +} + +void Canvas::SetBuffer(Pixel* buffer) { + Crafter::Web::Bindings::PutImageData(id, buffer, width, height); +} diff --git a/Crafter.Web-Canvas.cppm b/Crafter.Web-Canvas.cppm new file mode 100644 index 0000000..71773e2 --- /dev/null +++ b/Crafter.Web-Canvas.cppm @@ -0,0 +1,47 @@ +/* +Crafter.Web +Copyright (C) 2024 Catcrafts +Catcrafts.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +module; +#include +#include +#include +#include +export module Crafter.Web:Canvas; +import :HtmlElement; + +export namespace Crafter::Web { + + struct Pixel { + std::uint8_t r; + std::uint8_t g; + std::uint8_t b; + std::uint8_t a; + }; + + class Canvas : public Crafter::Web::HtmlElement { + public: + std::uint32_t width; + std::uint32_t height; + Canvas(std::uint32_t width, std::uint32_t height, std::string value = "", std::unordered_map style = {}, std::vector children = {}, std::unordered_map attributes = {}); + void DrawRect(std::uint32_t x, std::uint32_t y, std::uint32_t width, std::uint32_t height, std::string color); + void SetBuffer(Pixel* buffer); + }; +} + diff --git a/Crafter.Web-HtmlElement.cpp b/Crafter.Web-HtmlElement.cpp index 6b69f09..a2ba2e9 100644 --- a/Crafter.Web-HtmlElement.cpp +++ b/Crafter.Web-HtmlElement.cpp @@ -1,5 +1,5 @@ /* -Crafter.Build +Crafter.Web Copyright (C) 2024 Catcrafts Catcrafts.net @@ -28,15 +28,15 @@ module; module Crafter.Web; using namespace Crafter::Web; -HtmlElement::HtmlElement(std::string tag, std::string value, std::unordered_map style, std::vector children, std::unordered_map attributes) : id(idCounter++), tag(tag), children(children), style(style), value(value), attributes(attributes) { +HtmlElement::HtmlElement(std::string tag, std::string value, std::unordered_map style, std::vector children, std::unordered_map attributes) : id(idCounter++), tag(tag), children(children), style(style), value(value), attributes(attributes) { } std::string HtmlElement::Render() const { std::string childrenRendered; - for(const HtmlElement& child : children){ - childrenRendered+=child.Render(); + for(HtmlElement* child : children){ + childrenRendered+=child->Render(); } std::string styleRender; for(const auto& [key, value] : style){ @@ -46,7 +46,7 @@ std::string HtmlElement::Render() const { for(const auto& [key, value] : attributes){ attributesRender+=std::format("{}=\"{}\"",key,value); } - return std::format("<{} style=\"{}\" {}>{}{}",tag, styleRender, attributesRender, value, childrenRendered, tag); + return std::format("<{} id=\"{}\" style=\"{}\" {}>{}{}",tag, id, styleRender, attributesRender, value, childrenRendered, tag); } void HtmlElement::RenderAsRoot() const { diff --git a/Crafter.Web-HtmlElement.cppm b/Crafter.Web-HtmlElement.cppm index 87a5dca..62c16c1 100644 --- a/Crafter.Web-HtmlElement.cppm +++ b/Crafter.Web-HtmlElement.cppm @@ -1,5 +1,5 @@ /* -Crafter.Build +Crafter.Web Copyright (C) 2024 Catcrafts Catcrafts.net @@ -33,9 +33,9 @@ export namespace Crafter::Web { std::string tag; std::string value; std::unordered_map style; - std::vector children; + std::vector children; std::unordered_map attributes; - HtmlElement(std::string tag, std::string value = "", std::unordered_map style = {}, std::vector children = {}, std::unordered_map attributes = {}); + HtmlElement(std::string tag, std::string value = "", std::unordered_map style = {}, std::vector children = {}, std::unordered_map attributes = {}); std::string Render() const; void RenderAsRoot() const; }; diff --git a/Crafter.Web.cppm b/Crafter.Web.cppm index 15f63fc..1c30dc6 100644 --- a/Crafter.Web.cppm +++ b/Crafter.Web.cppm @@ -1,5 +1,5 @@ /* -Crafter.Build +Crafter.Web Copyright (C) 2024 Catcrafts Catcrafts.net @@ -20,8 +20,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA module; #include +#include +#include export module Crafter.Web; export import :HtmlElement; +export import :Canvas; extern "C" { void __cxa_allocate_exception() { @@ -33,8 +36,15 @@ extern "C" { } } + + export namespace Crafter::Web::Bindings { __attribute__((import_module("env"), import_name("setInnerHTML"))) void SetInnerHTML(const char* id, std::size_t idLenght, const char* html, std::size_t htmlLenght); + __attribute__((import_module("env"), import_name("strokeRect"))) void StrokeRect(std::uint64_t id, std::uint32_t x, std::uint32_t y, std::uint32_t width, std::uint32_t height, const char* color, std::size_t colorLenght); + __attribute__((import_module("env"), import_name("putImageData"))) void PutImageData(std::uint64_t id, Crafter::Web::Pixel* buffer, std::uint32_t width, std::uint32_t height); + __attribute__((import_module("env"), import_name("fetch"))) void Fetch(void* obj, const char* url, std::size_t urlCallback, char* buffer, void (*listener)(void* obj, std::uint32_t, char*)); + __attribute__((import_module("env"), import_name("setTimeout"))) void SetTimeout(void* obj, std::uint32_t time, void (*listener)(void* obj)); + __attribute__((import_module("env"), import_name("draw"))) void Draw(std::uint64_t id, std::uint32_t x, std::uint32_t y, const char* text, std::uint32_t textLenght); //__attribute__((import_module("env"), import_name("addEventListener"))) void AddEventListener(std::string id, std::string eventId, void (*listener)(void)); } diff --git a/Crafter.Web.js b/Crafter.Web.js index 202f646..b92d837 100644 --- a/Crafter.Web.js +++ b/Crafter.Web.js @@ -23,15 +23,81 @@ function setInnerHTML(id, idLenght, html, htmlLenght) { document.getElementById(decoder.decode(new Int8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, id, idLenght))).innerHTML = decoder.decode(new Int8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, html, htmlLenght)); } +function strokeRect(id, x, y, width, height, color, colorLenght) { + const decoder = new TextDecoder(); + const canvas = document.getElementById(id.toString()); + const ctx = canvas.getContext("2d"); + ctx.strokeStyle = decoder.decode(new Int8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, color, colorLenght)); + ctx.strokeRect(x, y, width, height); +} + +function putImageData(id, buffer, width, height) { + const decoder = new TextDecoder(); + const canvas = document.getElementById(id.toString()); + const ctx = canvas.getContext("2d"); + const view = new Uint8ClampedArray(window.crafter_webbuild_wasi.instance.exports.memory.buffer, buffer, 640*360*4); + const imageData = new ImageData(view, 640, 360); + ctx.putImageData(imageData, 0, 0); +} + +function draw(id, x, y, text, textLenght){ + const decoder = new TextDecoder(); + const canvas = document.getElementById("1"); + let ctx = canvas.getContext("2d") + + ctx.fillStyle = "red"; + ctx.font = '20px sans-serif'; + + var textString = decoder.decode(new Int8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, text, textLenght)) + let textWidth = ctx.measureText(textString).width; + + ctx.fillText(textString , x - (textWidth / 2), y); +} + +function setTimeoutt(obj, time, callback) { + setTimeout(() => { + window.crafter_webbuild_wasi.instance.exports.__indirect_function_table.get(callback)(obj); + }, time); +} function addEventListener(id, eventId, listener) { } +function fetchh(obj, url, urlLenght, buffer, callback) { + const decoder = new TextDecoder(); + const view = new Uint8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, buffer); + fetch(decoder.decode(new Int8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, url, urlLenght)), { + // Adding Get request + method: "GET", + + // Setting headers + headers: { + 'Content-Type': 'application/octet-stream', + }, + // Setting response type to arraybuffer + responseType: "arraybuffer" + }).then(x => x.arrayBuffer()).then( + y => { + const outputBytes = new Uint8Array(y); + for(let i = 0; i < outputBytes.length; i++) { + view[i] = outputBytes[i] + } + window.crafter_webbuild_wasi.instance.exports.__indirect_function_table.get(callback)(obj, outputBytes.length, buffer); + } + ); + return 1; +} + let env = { setInnerHTML:setInnerHTML, - addEventListener:addEventListener + addEventListener:addEventListener, + strokeRect:strokeRect, + fetch:fetchh, + putImageData:putImageData, + setTimeout:setTimeoutt, + draw:draw } if(window.crafter_webbuild_env){ diff --git a/project.json b/project.json index 35cbe0f..84afc9a 100644 --- a/project.json +++ b/project.json @@ -4,8 +4,8 @@ { "name": "base", "standard": "c++26", - "source_files": ["Crafter.Web-HtmlElement"], - "module_files": ["Crafter.Web-HtmlElement", "Crafter.Web"], + "source_files": ["Crafter.Web-HtmlElement", "Crafter.Web-Canvas"], + "module_files": ["Crafter.Web-Canvas", "Crafter.Web-HtmlElement", "Crafter.Web"], "additional_files": ["Crafter.Web.js"], "build_dir": "./build", "output_dir": "./bin",