From eddca849e6e29a3c668e25903ac95efed39d9d63 Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Sat, 16 Mar 2024 22:11:59 +0800 Subject: [PATCH] MCVE example --- examples/host/linux/skia_app.cpp | 165 ++++++---------- examples/shapes.cpp | 312 ------------------------------- 2 files changed, 52 insertions(+), 425 deletions(-) diff --git a/examples/host/linux/skia_app.cpp b/examples/host/linux/skia_app.cpp index c057b46a..abbbaffd 100644 --- a/examples/host/linux/skia_app.cpp +++ b/examples/host/linux/skia_app.cpp @@ -3,7 +3,6 @@ Distributed under the MIT License [ https://opensource.org/licenses/MIT ] =============================================================================*/ -#include "../../app.hpp" #include #include #include @@ -14,32 +13,12 @@ #include "SkColorSpace.h" #include "SkCanvas.h" #include "SkSurface.h" -#include - -using namespace cycfi::artist; -float elapsed_ = 0; // rendering elapsed time namespace { - struct view_state - { - extent _size = {}; - float _scale = 1.0; - bool _animate = false; - color _bkd = colors::white; - guint _timer_id = 0; - - sk_sp _xface; - sk_sp _ctx; - sk_sp _surface; - }; - - void close_window(GtkWidget*, gpointer user_data) - { - view_state& state = *reinterpret_cast(user_data); - if (state._timer_id) - g_source_remove(state._timer_id); - } + sk_sp gl_interface; + sk_sp gr_context; + sk_sp skia_surface; void realize(GtkGLArea* area, gpointer user_data) { @@ -47,61 +26,42 @@ namespace if (gtk_gl_area_get_error (area) != NULL) return; - view_state& state = *reinterpret_cast(user_data); - glClearColor(state._bkd.red, state._bkd.green, state._bkd.blue, state._bkd.alpha); + glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); - state._xface = GrGLMakeNativeInterface(); - state._ctx = GrDirectContext::MakeGL(state._xface); + gl_interface = GrGLMakeNativeInterface(); + gr_context = GrDirectContext::MakeGL(gl_interface); } gboolean render(GtkGLArea* area, GdkGLContext* context, gpointer user_data) { - view_state& state = *reinterpret_cast(user_data); - auto error = [](char const* msg) { throw std::runtime_error(msg); }; - - auto draw_f = - [&]() - { - if (!state._surface) - { - GrGLint buffer; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer); - GrGLFramebufferInfo info; - info.fFBOID = (GrGLuint) buffer; - SkColorType colorType = kRGBA_8888_SkColorType; - - info.fFormat = GL_RGBA8; - GrBackendRenderTarget target( - state._size.x*state._scale - , state._size.y*state._scale - , 0, 8, info - ); - - state._surface = - SkSurface::MakeFromBackendRenderTarget( - state._ctx.get(), target, - kBottomLeft_GrSurfaceOrigin, colorType, nullptr, nullptr - ); - - if (!state._surface) - error("Error: SkSurface::MakeRenderTarget returned null"); - } - - SkCanvas* gpu_canvas = state._surface->getCanvas(); - gpu_canvas->save(); - gpu_canvas->scale(state._scale, state._scale); - auto cnv = canvas{gpu_canvas}; - - draw(cnv); - - gpu_canvas->restore(); - state._surface->flush(); - }; - - auto start = std::chrono::steady_clock::now(); - draw_f(); - auto stop = std::chrono::steady_clock::now(); - elapsed_ = std::chrono::duration{stop - start}.count(); + if (!skia_surface) + { + GrGLint buffer; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer); + GrGLFramebufferInfo info; + info.fFBOID = (GrGLuint) buffer; + SkColorType colorType = kRGBA_8888_SkColorType; + + info.fFormat = GL_RGBA8; + GrBackendRenderTarget target(640, 480, 0, 8, info); + + skia_surface = + SkSurface::MakeFromBackendRenderTarget( + gr_context.get(), target, + kBottomLeft_GrSurfaceOrigin, colorType, nullptr, nullptr + ); + + if (!skia_surface) + throw std::runtime_error("Error: SkSurface::MakeRenderTarget returned null"); + } + + SkCanvas* gpu_canvas = skia_surface->getCanvas(); + gpu_canvas->save(); + + // Drawing here... + + gpu_canvas->restore(); + skia_surface->flush(); return true; } @@ -113,20 +73,11 @@ namespace return true; } - static auto proc = &glXGetProcAddress; - void activate(GtkApplication* app, gpointer user_data) { - auto error = [](char const* msg) { throw std::runtime_error(msg); }; - if (!proc) - error("Error: glXGetProcAddress is null"); - - view_state& state = *reinterpret_cast(user_data); auto* window = gtk_application_window_new(app); gtk_window_set_title(GTK_WINDOW(window), "Drawing Area"); - g_signal_connect(window, "destroy", G_CALLBACK(close_window), user_data); - // create a GtkGLArea instance auto* gl_area = gtk_gl_area_new(); gtk_container_add(GTK_CONTAINER(window), gl_area); @@ -134,17 +85,29 @@ namespace g_signal_connect(gl_area, "render", G_CALLBACK(render), user_data); g_signal_connect(gl_area, "realize", G_CALLBACK(realize), user_data); - gtk_window_resize(GTK_WINDOW(window), state._size.x, state._size.y); + gtk_window_resize(GTK_WINDOW(window), 640, 480); gtk_widget_show_all(window); auto w = gtk_widget_get_window(GTK_WIDGET(window)); - state._scale = gdk_window_get_scale_factor(w); - - if (state._animate) - state._timer_id = g_timeout_add(1000 / 60, animate, gl_area); } } +int main(int argc, char const* argv[]) +{ + auto* app = gtk_application_new("org.gtk-skia.example", G_APPLICATION_FLAGS_NONE); + g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); + int status = g_application_run(G_APPLICATION(app), argc, const_cast(argv)); + g_object_unref(app); + + return status; +} + +#include +#include +namespace fs = std::filesystem; + +float elapsed_ = 0; // rendering elapsed time + namespace cycfi::artist { void init_paths() @@ -159,28 +122,4 @@ namespace cycfi::artist { return fs::path(fs::current_path() / "resources/fonts"); } -} - -int run_app( - int argc - , char const* argv[] - , extent window_size - , color background_color - , bool animate -) -{ - view_state state; - state._size = window_size; - state._animate = animate; - state._bkd = background_color; - - auto* app = gtk_application_new("org.gtk-skia.example", G_APPLICATION_FLAGS_NONE); - g_signal_connect(app, "activate", G_CALLBACK(activate), &state); - int status = g_application_run(G_APPLICATION(app), argc, const_cast(argv)); - g_object_unref(app); - - return status; -} - - - +} \ No newline at end of file diff --git a/examples/shapes.cpp b/examples/shapes.cpp index 7fcf0ea7..f3efb3a3 100644 --- a/examples/shapes.cpp +++ b/examples/shapes.cpp @@ -5,315 +5,3 @@ =============================================================================*/ #include "app.hpp" -using namespace cycfi::artist; -using cycfi::pi; -auto constexpr window_size = point{640.0f, 480.0f}; -auto constexpr bkd_color = rgb(44, 42, 45); - -void background(canvas& cnv) -{ - cnv.add_rect({{0, 0}, window_size}); - cnv.fill_style(bkd_color); - cnv.fill(); -} - -void rectangles(canvas& cnv) -{ - constexpr auto x = 40; - constexpr auto y = 40; - cnv.line_width(2); - - cnv.add_rect(x, y, 150, 100); - cnv.fill_style(colors::red); - cnv.fill(); - - cnv.add_rect(x, y, 150, 100); - cnv.stroke_style(colors::navajo_white.opacity(0.5)); - cnv.stroke(); - - cnv.add_round_rect(x + 30, y + 30, 150, 100, 10); - cnv.fill_style(colors::blue.opacity(0.5)); - cnv.fill(); - - cnv.add_round_rect(x + 30, y + 30, 150, 100, 10); - cnv.stroke_style(colors::honeydew.opacity(0.5)); - cnv.stroke(); -} - -void circles_and_arcs(canvas& cnv) -{ - constexpr auto x = 300; - constexpr auto y = 100; - - for (int i = 0; i != 7; ++i) - { - auto cx = x+(i*45); - auto cy = y; - auto ri = 7-i; - auto radius = 20+(ri*5); - - cnv.add_circle(cx, cy, radius); - cnv.fill_style(hsl(360/7 * i, 0.8, 0.5).opacity(0.7)); - cnv.fill(); - - cnv.line_width((ri+1)/2); - cnv.stroke_style(colors::light_sky_blue.opacity(0.8)); - cnv.arc(cx, cy, radius, 0.0f, pi + (pi * ((i+1)/7.0f)), false); - cnv.stroke(); - } -} - -void arc_to(canvas& cnv) -{ - constexpr auto x = 40; - constexpr auto y = 200; - constexpr auto r = 40; - - auto make_arc = - [=](canvas& cnv) - { - cnv.begin_path(); - cnv.move_to(x, y); - cnv.line_to(x+(80-r), y); - cnv.arc_to(x+80, y, x+80, y+20, r); - cnv.line_to(x+80, y+80); - }; - - cnv.stroke_style(colors::dodger_blue.opacity(0.6)); - cnv.line_width(10); - make_arc(cnv); - cnv.stroke(); - - cnv.fill_style(colors::dodger_blue.opacity(0.2)); - make_arc(cnv); - cnv.line_to(x, y+80); - cnv.close_path(); - cnv.fill(); - - cnv.stroke_style(colors::white); - cnv.line_width(1); - cnv.begin_path(); - cnv.move_to(x, y); - cnv.line_to(x+80, y); - cnv.line_to(x+80, y+80); - cnv.stroke(); -} - -void line_caps(canvas& cnv) -{ - auto where = point{160, 215}; - auto spacing = 25; - cnv.line_width(10); - - cnv.stroke_style(colors::gold); - cnv.begin_path(); - cnv.line_width(10); - cnv.line_cap(cnv.butt); - cnv.move_to(where.x, where.y); - cnv.line_to(where.x+100, where.y); - cnv.stroke(); - - cnv.stroke_style(colors::sky_blue); - cnv.begin_path(); - cnv.line_cap(cnv.round); - cnv.move_to(where.x, where.y+spacing); - cnv.line_to(where.x+100, where.y+spacing); - cnv.stroke(); - - cnv.stroke_style(colors::light_sea_green); - cnv.begin_path(); - cnv.line_cap(cnv.square); - cnv.move_to(where.x, where.y+spacing*2); - cnv.line_to(where.x+100, where.y+spacing*2); - cnv.stroke(); - - cnv.stroke_style(colors::white); - cnv.line_width(1); - - cnv.begin_path(); - cnv.move_to(where.x, where.y); - cnv.line_to(where.x+100, where.y); - cnv.stroke(); - - cnv.begin_path(); - cnv.move_to(where.x, where.y+spacing); - cnv.line_to(where.x+100, where.y+spacing); - cnv.stroke(); - - cnv.begin_path(); - cnv.move_to(where.x, where.y+spacing*2); - cnv.line_to(where.x+100, where.y+spacing*2); - cnv.stroke(); -} - -void line_joins(canvas& cnv) -{ - auto where = point{290, 100}; - cnv.line_width(10); - cnv.line_cap(cnv.butt); - - cnv.stroke_style(colors::gold); - cnv.begin_path(); - cnv.line_join(cnv.bevel_join); - cnv.move_to(where.x, where.y+100); - cnv.line_to(where.x+60, where.y+140); - cnv.line_to(where.x, where.y+180); - cnv.stroke(); - - cnv.stroke_style(colors::sky_blue); - cnv.begin_path(); - cnv.line_join(cnv.round_join); - cnv.move_to(where.x+40, where.y+100); - cnv.line_to(where.x+100, where.y+140); - cnv.line_to(where.x+40, where.y+180); - cnv.stroke(); - - cnv.stroke_style(colors::light_sea_green); - cnv.begin_path(); - cnv.line_join(cnv.miter_join); - cnv.move_to(where.x+80, where.y+100); - cnv.line_to(where.x+140, where.y+140); - cnv.line_to(where.x+80, where.y+180); - cnv.stroke(); - - cnv.stroke_style(colors::white); - cnv.line_width(1); - - cnv.begin_path(); - cnv.move_to(where.x, where.y+100); - cnv.line_to(where.x+60, where.y+140); - cnv.line_to(where.x, where.y+180); - cnv.stroke(); - - cnv.begin_path(); - cnv.move_to(where.x+40, where.y+100); - cnv.line_to(where.x+100, where.y+140); - cnv.line_to(where.x+40, where.y+180); - cnv.stroke(); - - cnv.begin_path(); - cnv.move_to(where.x+80, where.y+100); - cnv.line_to(where.x+140, where.y+140); - cnv.line_to(where.x+80, where.y+180); - cnv.stroke(); -} - -void bezier(canvas& cnv) -{ - auto where = point{450, 280}; - auto height = 100; - auto width = 120; - auto xmove = 20; - auto start = point{where.x, where.y}; - auto cp1 = point{where.x+xmove, where.y-height}; - auto cp2 = point{where.x+width-xmove, where.y-height}; - auto end = point{where.x+width, where.y}; - - cnv.line_width(10); - cnv.stroke_style(colors::dodger_blue.opacity(0.6)); - cnv.line_cap(cnv.round); - - cnv.begin_path(); - cnv.move_to(start); - cnv.bezier_curve_to(cp1, cp2, end); - cnv.stroke(); - - cnv.fill_style(colors::pink.opacity(0.8)); - cnv.add_circle(cp1.x, cp1.y, 3); - cnv.add_circle(cp2.x, cp2.y, 3); - cnv.fill(); - - cnv.stroke_style(colors::white); - cnv.line_width(1); - cnv.move_to(start); - cnv.line_to(cp1); - cnv.move_to(cp2); - cnv.line_to(end); - cnv.stroke(); -} - -void quad(canvas& cnv) -{ - auto where = point{40, 420}; - auto height = 100; - auto width = 120; - auto start = point{where.x, where.y}; - auto cp = point{where.x+(width/2), where.y-height}; - auto end = point{where.x+width, where.y}; - - cnv.line_width(10); - cnv.stroke_style(colors::dodger_blue.opacity(0.6)); - cnv.line_cap(cnv.round); - - cnv.begin_path(); - cnv.move_to(start); - cnv.quadratic_curve_to(cp, end); - cnv.stroke(); - - cnv.fill_style(colors::pink.opacity(0.8)); - cnv.add_circle(cp.x, cp.y, 3); - cnv.fill(); - - cnv.stroke_style(colors::white); - cnv.line_width(1); - cnv.move_to(start); - cnv.line_to(cp); - cnv.line_to(end); - cnv.stroke(); -} - -void rainbow(canvas::gradient& gr) -{ - gr.add_color_stop(0.0/6, colors::red); - gr.add_color_stop(1.0/6, colors::orange); - gr.add_color_stop(2.0/6, colors::yellow); - gr.add_color_stop(3.0/6, colors::green); - gr.add_color_stop(4.0/6, colors::blue); - gr.add_color_stop(5.0/6, rgb(0x4B, 0x00, 0x82)); - gr.add_color_stop(6.0/6, colors::violet); -} - -void linear_gradient(canvas& cnv) -{ - auto x = 300.0f; - auto y = 330.0f; - auto gr = canvas::linear_gradient{x, y, x+300, y}; - rainbow(gr); - - cnv.add_round_rect(x, y, 300, 80, 5); - cnv.fill_style(gr); - cnv.fill(); -} - -void radial_gradient(canvas& cnv) -{ - auto center = point{208, 360}; - auto radius = 65.0f; - auto gr = canvas::radial_gradient{center, 5, center.move(15, 10), radius}; - gr.add_color_stop(0.0, colors::red); - gr.add_color_stop(1.0, colors::black); - - cnv.add_circle({center.move(15, 10), radius - 10}); - cnv.fill_style(gr); - cnv.fill(); -} - -void draw(canvas& cnv) -{ - background(cnv); - rectangles(cnv); - circles_and_arcs(cnv); - arc_to(cnv); - line_caps(cnv); - line_joins(cnv); - bezier(cnv); - quad(cnv); - linear_gradient(cnv); - radial_gradient(cnv); -} - -int main(int argc, char const* argv[]) -{ - return run_app(argc, argv, window_size, bkd_color); -} -