diff --git a/build.sh b/build.sh index 326dbba..b890724 100755 --- a/build.sh +++ b/build.sh @@ -9,10 +9,11 @@ pushd "$(dirname $0)" compiler=${CC:-g++} src_files=( - src/main.cxx + src/main.cxx src/util/random.cxx src/layout/layout_tree.cxx src/rendering.cxx + src/rendering_context.cxx ) rapidxml_version="1.13" @@ -44,8 +45,8 @@ gl_flags=$(pkg-config --cflags --libs gl) misc_lib_flags=$(pkg-config --cflags --libs libwebp libwebpmux libwebpdemux libpng libjpeg fontconfig) -common_opts="$rapidxml_flags $skia_flags $glfw_flags $gl_flags -I$root/src -Wall --std=c++20 -v -L$root/vendor/skia/out/Static -lskia -lz $misc_lib_flags" -debug_opts="--debug --optimize -DDEBUG $common_opts" +common_opts="$rapidxml_flags $skia_flags $glfw_flags $gl_flags -I$root/src -Wall --std=c++20 -L$root/vendor/skia/out/Static -lskia -lz $misc_lib_flags" +debug_opts="--debug -g --optimize -DDEBUG $common_opts" mkdir -p build pushd build >> /dev/null diff --git a/src/layout/layout_bound.hxx b/src/layout/layout_bound.hxx new file mode 100644 index 0000000..9f284db --- /dev/null +++ b/src/layout/layout_bound.hxx @@ -0,0 +1,15 @@ +#ifndef __CLEF_LAYOUT_LAYOUT_BOUND_HXX_ +#define __CLEF_LAYOUT_LAYOUT_BOUND_HXX_ + +namespace Clef { + +struct LayoutBound { + float x; + float y; + float width; + float height; +}; + +} // namespace Clef + +#endif diff --git a/src/layout/layout_tree.cxx b/src/layout/layout_tree.cxx index fbd5244..f2e4ec0 100644 --- a/src/layout/layout_tree.cxx +++ b/src/layout/layout_tree.cxx @@ -6,6 +6,7 @@ #include "include/core/SkRefCnt.h" #include "include/core/SkTypeface.h" #include "rapidxml.hpp" +#include "rendering.hxx" #include #include #include @@ -32,8 +33,6 @@ Clef::LayoutBound Clef::ContainerNode::measure() { float total_height = 0; for (const auto &child : children) { const auto bound = child->measure(); - std::cout << "bound width" << bound.width << " height " << bound.height - << std::endl; if (bound.width > max_child_width) { max_child_width = bound.width; } @@ -60,8 +59,8 @@ Clef::LayoutBound Clef::TextNode::measure() { Clef::LayoutTree::LayoutTree(Clef::LayoutTree::Node *root) : root(root) {} Clef::LayoutTree::Node * -Clef::LayoutTree::Node::from_xml_node(rapidxml::xml_node *node, - const SkFontMgr &font_mgr) { +Clef::LayoutTree::Node::from_xml_node(const RenderingContext &ctx, + rapidxml::xml_node *node) { std::cout << "encountered node:" << node->name() << std::endl; if (std::strncmp("box", node->name(), 3) == 0) { @@ -70,10 +69,10 @@ Clef::LayoutTree::Node::from_xml_node(rapidxml::xml_node *node, std::cout << "assigned id " << container_node->id << std::endl; auto current_node = node->first_node(); - Node *last_node; + Node *last_node = nullptr; while (current_node) { - auto n = Node::from_xml_node(current_node, font_mgr); + auto n = Node::from_xml_node(ctx, current_node); if (!n) { return nullptr; } @@ -102,7 +101,7 @@ Clef::LayoutTree::Node::from_xml_node(rapidxml::xml_node *node, } auto typeface = - font_mgr.matchFamilyStyle("Inter", SkFontStyle::Normal()); + ctx.font_mgr->matchFamilyStyle("Inter", SkFontStyle::Normal()); SkFont f(typeface, 20); auto n = new TextNode(content, f); @@ -116,8 +115,9 @@ Clef::LayoutTree::Node::from_xml_node(rapidxml::xml_node *node, return nullptr; } -Clef::LayoutTree Clef::LayoutTree::from_xml(const rapidxml::xml_document<> &doc, - const SkFontMgr &font_mgr) { +Clef::LayoutTree +Clef::LayoutTree::from_xml(const RenderingContext &ctx, + const rapidxml::xml_document<> &doc) { Clef::LayoutTree::Node *root; auto xml_root = doc.first_node("box"); @@ -126,7 +126,7 @@ Clef::LayoutTree Clef::LayoutTree::from_xml(const rapidxml::xml_document<> &doc, "cml layout must start with a container node."); } - root = Node::from_xml_node(xml_root, font_mgr); + root = Node::from_xml_node(ctx, xml_root); if (!root) { throw std::runtime_error("failed to parse cml"); } diff --git a/src/layout/layout_tree.hxx b/src/layout/layout_tree.hxx index 879195e..6de1117 100644 --- a/src/layout/layout_tree.hxx +++ b/src/layout/layout_tree.hxx @@ -1,23 +1,17 @@ #ifndef __CLEF_LAYOUT_LAYOUT_TREE_HXX__ #define __CLEF_LAYOUT_LAYOUT_TREE_HXX__ +#include "include/core/SkColorSpace.h" #include "include/core/SkFont.h" -#include "include/core/SkRefCnt.h" -#include "include/core/SkTypeface.h" +#include "layout_bound.hxx" #include "rapidxml.hpp" +#include "rendering_context.hxx" #include #include #include namespace Clef { -struct LayoutBound { - float x; - float y; - float width; - float height; -}; - struct LayoutTree { enum class NodeType { Text, Container }; @@ -28,16 +22,16 @@ struct LayoutTree { Node *next_sibiling; NodeType type; - static Node *from_xml_node(rapidxml::xml_node *node, - const SkFontMgr &font_mgr); + static Node *from_xml_node(const RenderingContext &ctx, + rapidxml::xml_node *node); virtual Clef::LayoutBound measure() = 0; }; Node *root; - static LayoutTree from_xml(const rapidxml::xml_document<> &doc, - const SkFontMgr &font_mgr); + static LayoutTree from_xml(const RenderingContext &ctx, + const rapidxml::xml_document<> &doc); private: LayoutTree(Node *root); diff --git a/src/main.cxx b/src/main.cxx index 4ef80eb..3a6eee7 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -1,20 +1,12 @@ #include "GL/gl.h" #include "GLFW/glfw3.h" -#include "include/core/SkCanvas.h" -#include "include/core/SkColor.h" -#include "include/core/SkColorType.h" -#include "include/core/SkFontStyle.h" -#include "include/core/SkPaint.h" -#include "include/core/SkTypeface.h" #include "include/gpu/ganesh/GrDirectContext.h" -#include "include/gpu/ganesh/GrTypes.h" -#include "include/gpu/ganesh/gl/GrGLTypes.h" #include "layout/layout_tree.hxx" #include "rapidxml.hpp" #include "rendering.hxx" +#include "rendering_context.hxx" #include #include -#include #include #include #include @@ -30,11 +22,19 @@ #include #include +const auto INITIAL_WINDOW_WIDTH = 800; +const auto INITIAL_WINDOW_HEIGHT = 600; + void framebuffer_size_callback(GLFWwindow *window, int width, int height) { + auto ctx = + static_cast(glfwGetWindowUserPointer(window)); + GLFWmonitor *mon = glfwGetPrimaryMonitor(); float xscale, yscale; glfwGetMonitorContentScale(mon, &xscale, &yscale); glViewport(0, 0, width, height); + + Clef::update_skia_surface(*ctx, width, height); } int main(int argc, char *argv[]) { @@ -50,7 +50,8 @@ int main(int argc, char *argv[]) { return -1; } - window = glfwCreateWindow(200, 200, "Clef", nullptr, nullptr); + window = glfwCreateWindow(INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT, + "Clef", nullptr, nullptr); if (!window) { std::cout << "window cannot be created" << std::endl; glfwTerminate(); @@ -58,85 +59,30 @@ int main(int argc, char *argv[]) { } glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE); + glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE); - glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); - + glfwSwapInterval(1); glfwMakeContextCurrent(window); - auto interface = GrGLMakeNativeInterface(); - if (!interface) { - interface = GrGLMakeAssembledInterface( - nullptr, (GrGLGetProc) * [](void *, const char *p) -> void * { - return (void *)glfwGetProcAddress(p); - }); - if (!interface) { - std::cout << "failed to make native interface" << std::endl; - exit(EXIT_FAILURE); - } - } + float xscale, yscale; + GLFWmonitor *mon = glfwGetPrimaryMonitor(); + glfwGetMonitorContentScale(mon, &xscale, &yscale); - auto context = GrDirectContexts::MakeGL(interface); - if (!context) { - std::cout << "failed to make DirectContext" << std::endl; - exit(EXIT_FAILURE); - } + Clef::RenderingContext rendering_ctx = Clef::new_rendering_context( + INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT); - std::cout << "gl direct context created" << std::endl; - - GrGLFramebufferInfo framebufferInfo; - framebufferInfo.fFBOID = 0; - framebufferInfo.fFormat = GL_RGBA8; - - std::cout << "frame buffer info created" << std::endl; - - SkColorType colorType = kRGBA_8888_SkColorType; - auto target = - GrBackendRenderTargets::MakeGL(400, 400, 0, 0, framebufferInfo); - - auto skSurface = SkSurfaces::WrapBackendRenderTarget( - context.get(), target, kBottomLeft_GrSurfaceOrigin, colorType, nullptr, - nullptr); - if (!skSurface) { - std::cout << "failed to create skia surface" << std::endl; - exit(EXIT_FAILURE); - } - - std::cout << "skia surface created" << std::endl; - - SkCanvas *canvas = skSurface->getCanvas(); - if (!canvas) { - std::cout << "failed to obtain skia canvas" << std::endl; - exit(EXIT_FAILURE); - } - - glfwSwapInterval(1); - - std::cout << "canvas obtained. entering run loop..." << std::endl; - - auto fontMgr = SkFontMgr_New_Custom_Directory("../resources/font/Inter"); - std::cout << "fonts found: " << fontMgr->countFamilies() << std::endl; - - auto interRegular = - fontMgr->matchFamilyStyle("Inter", SkFontStyle::Normal()); - if (!interRegular) { - std::cout << "WARNING: inter regular not found" << std::endl; - } + glfwSetWindowUserPointer(window, (void *)&rendering_ctx); + glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); rapidxml::file<> input_file(argv[1]); rapidxml::xml_document<> doc; doc.parse(input_file.data()); - - Clef::RenderingContext ctx{ - .canvas = canvas, - .font_mgr = fontMgr, - }; - - Clef::LayoutTree tree = Clef::LayoutTree::from_xml(doc, *fontMgr.get()); + Clef::LayoutTree tree = Clef::LayoutTree::from_xml(rendering_ctx, doc); while (!glfwWindowShouldClose(window)) { - Clef::render_tree(ctx, tree); + Clef::render_tree(rendering_ctx, tree); - context->flush(); + rendering_ctx.gr_direct_context->flush(); glfwSwapBuffers(window); glfwPollEvents(); diff --git a/src/rendering.cxx b/src/rendering.cxx index b5824f6..7efe4f5 100644 --- a/src/rendering.cxx +++ b/src/rendering.cxx @@ -4,26 +4,15 @@ #include "include/core/SkFont.h" #include "include/core/SkPaint.h" #include "include/core/SkRect.h" -#include "include/core/SkSurfaceProps.h" +#include "include/core/SkRefCnt.h" +#include "include/ports/SkFontMgr_directory.h" #include "layout/layout_tree.hxx" -#include #include -#include #include inline const auto NODE_TYPE_BOX = "box"; inline const auto NODE_TYPE_TEXT = "text"; -Clef::RenderingContext new_rendering_context(SkCanvas *canvas, - sk_sp font_mgr) { - return { - .canvas = canvas, - .layout_map{}, - .font_mgr = font_mgr, - .random_id{0, std::numeric_limits::max()}, - }; -} - Clef::LayoutBound __calculate_node_position(Clef::RenderingContext &ctx, Clef::LayoutTree::Node *node) { auto bounds = node->measure(); @@ -60,8 +49,6 @@ void clef_render_node(Clef::RenderingContext &ctx, auto tn = static_cast(node); SkPaint paint; paint.setColor(SK_ColorBLACK); - std::cout << "rendering text: " << tn->content << " at x = " << pos.x - << " y = " << pos.y << std::endl; ctx.canvas->drawString(tn->content.c_str(), pos.x, pos.y + pos.height, tn->font, paint); ctx.layout_map.insert({node->id, pos}); diff --git a/src/rendering.hxx b/src/rendering.hxx index 8a010c3..45ecdd9 100644 --- a/src/rendering.hxx +++ b/src/rendering.hxx @@ -1,29 +1,11 @@ #ifndef __CLEF__RENDERING_HXX__ #define __CLEF__RENDERING_HXX__ -#include "include/core/SkCanvas.h" -#include "include/core/SkFontMgr.h" -#include "include/core/SkFontStyle.h" -#include "include/core/SkRefCnt.h" -#include "include/core/SkScalar.h" #include "layout/layout_tree.hxx" #include "rapidxml.hpp" -#include -#include -#include namespace Clef { -struct RenderingContext { - SkCanvas *canvas; - std::unordered_map layout_map; - sk_sp font_mgr; - std::uniform_int_distribution random_id; -}; - -RenderingContext new_rendering_context(SkCanvas *canvas, - sk_sp font_mgr); - void render_document(RenderingContext &ctx, const rapidxml::xml_document<> &doc); diff --git a/src/rendering_context.cxx b/src/rendering_context.cxx new file mode 100644 index 0000000..4d644e3 --- /dev/null +++ b/src/rendering_context.cxx @@ -0,0 +1,48 @@ +#include "rendering_context.hxx" +#include "GLFW/glfw3.h" +#include "include/gpu/ganesh/SkSurfaceGanesh.h" +#include "include/gpu/ganesh/gl/GrGLAssembleInterface.h" +#include "include/gpu/ganesh/gl/GrGLBackendSurface.h" +#include "include/gpu/ganesh/gl/GrGLDirectContext.h" +#include "include/ports/SkFontMgr_directory.h" +#include + +Clef::RenderingContext Clef::new_rendering_context(int width, int height) { + Clef::RenderingContext ctx{ + .framebuffer_info{0, GL_RGBA8}, + .font_mgr = SkFontMgr_New_Custom_Directory("../resources/font/Inter"), + }; + + sk_sp interface = GrGLMakeNativeInterface(); + if (!interface) { + interface = GrGLMakeAssembledInterface( + nullptr, (GrGLGetProc) * [](void *, const char *p) -> void * { + return (void *)glfwGetProcAddress(p); + }); + if (!interface) { + std::cout << "failed to make native interface" << std::endl; + exit(EXIT_FAILURE); + } + } + + ctx.gl_interface = interface; + ctx.gr_direct_context = GrDirectContexts::MakeGL(interface); + + Clef::update_skia_surface(ctx, width, height); + + return ctx; +} + +void Clef::update_skia_surface(Clef::RenderingContext &ctx, int width, + int height) { + ctx.render_target = GrBackendRenderTargets::MakeGL(width, height, 0, 0, + ctx.framebuffer_info); + ctx.sk_surface = SkSurfaces::WrapBackendRenderTarget( + ctx.gr_direct_context.get(), ctx.render_target, + kBottomLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, + SkColorSpace::MakeSRGB(), nullptr); + std::cout << "sk surface" << ctx.sk_surface << std::endl; + ctx.canvas = ctx.sk_surface->getCanvas(); + std::cout << " kasdjkjsak" << ctx.sk_surface->getCanvas() << std::endl; + std::cout << "new canvas address " << ctx.canvas << std::endl; +} diff --git a/src/rendering_context.hxx b/src/rendering_context.hxx new file mode 100644 index 0000000..7b593be --- /dev/null +++ b/src/rendering_context.hxx @@ -0,0 +1,34 @@ +#ifndef __CLEF_RENDERING_CONTEXT_HXX__ +#define __CLEF_RENDERING_CONTEXT_HXX__ + +#include "include/core/SkCanvas.h" +#include "include/core/SkColorSpace.h" +#include "include/core/SkFontMgr.h" +#include "include/gpu/ganesh/GrBackendSurface.h" +#include "include/gpu/ganesh/GrDirectContext.h" +#include "include/gpu/ganesh/gl/GrGLInterface.h" +#include "include/gpu/ganesh/gl/GrGLTypes.h" +#include "layout/layout_bound.hxx" +#include + +namespace Clef { + +struct RenderingContext { + GrGLFramebufferInfo framebuffer_info; + GrBackendRenderTarget render_target; + sk_sp gl_interface; + sk_sp gr_direct_context; + sk_sp sk_surface; + SkCanvas *canvas; + std::unordered_map layout_map; + sk_sp font_mgr; + std::uniform_int_distribution random_id; +}; + +RenderingContext new_rendering_context(int width, int height); + +void update_skia_surface(RenderingContext &ctx, int width, int height); + +} // namespace Clef + +#endif