fix: window resizing

This commit is contained in:
2024-10-13 00:13:14 +01:00
parent 030e8d51af
commit dda194a5dd
9 changed files with 143 additions and 136 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -6,6 +6,7 @@
#include "include/core/SkRefCnt.h"
#include "include/core/SkTypeface.h"
#include "rapidxml.hpp"
#include "rendering.hxx"
#include <cstdint>
#include <cstring>
#include <iostream>
@@ -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<char> *node,
const SkFontMgr &font_mgr) {
Clef::LayoutTree::Node::from_xml_node(const RenderingContext &ctx,
rapidxml::xml_node<char> *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<char> *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<char> *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<char> *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");
}

View File

@@ -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 <cstdint>
#include <string>
#include <vector>
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<char> *node,
const SkFontMgr &font_mgr);
static Node *from_xml_node(const RenderingContext &ctx,
rapidxml::xml_node<char> *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);

View File

@@ -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 <GLFW/glfw3.h>
#include <cstdlib>
#include <fstream>
#include <include/core/SkColorSpace.h>
#include <include/core/SkFont.h>
#include <include/core/SkFontMgr.h>
@@ -30,11 +22,19 @@
#include <iostream>
#include <rapidxml_utils.hpp>
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<Clef::RenderingContext *>(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<rapidxml::parse_default>(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();

View File

@@ -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 <cstdint>
#include <iostream>
#include <limits>
#include <utility>
inline const auto NODE_TYPE_BOX = "box";
inline const auto NODE_TYPE_TEXT = "text";
Clef::RenderingContext new_rendering_context(SkCanvas *canvas,
sk_sp<SkFontMgr> font_mgr) {
return {
.canvas = canvas,
.layout_map{},
.font_mgr = font_mgr,
.random_id{0, std::numeric_limits<uint64_t>::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<Clef::TextNode *>(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});

View File

@@ -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 <cstdint>
#include <random>
#include <unordered_map>
namespace Clef {
struct RenderingContext {
SkCanvas *canvas;
std::unordered_map<uint64_t, LayoutBound> layout_map;
sk_sp<SkFontMgr> font_mgr;
std::uniform_int_distribution<std::mt19937::result_type> random_id;
};
RenderingContext new_rendering_context(SkCanvas *canvas,
sk_sp<SkFontMgr> font_mgr);
void render_document(RenderingContext &ctx,
const rapidxml::xml_document<> &doc);

48
src/rendering_context.cxx Normal file
View File

@@ -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 <iostream>
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<const GrGLInterface> 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;
}

34
src/rendering_context.hxx Normal file
View File

@@ -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 <random>
namespace Clef {
struct RenderingContext {
GrGLFramebufferInfo framebuffer_info;
GrBackendRenderTarget render_target;
sk_sp<const GrGLInterface> gl_interface;
sk_sp<GrDirectContext> gr_direct_context;
sk_sp<SkSurface> sk_surface;
SkCanvas *canvas;
std::unordered_map<uint64_t, LayoutBound> layout_map;
sk_sp<SkFontMgr> font_mgr;
std::uniform_int_distribution<std::mt19937::result_type> random_id;
};
RenderingContext new_rendering_context(int width, int height);
void update_skia_surface(RenderingContext &ctx, int width, int height);
} // namespace Clef
#endif