From bca29c537cfdf818577f79cc5a279d1412b9dcda Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Sun, 15 Dec 2024 22:29:07 +0100 Subject: [PATCH] scissor command --- src/main.c3 | 13 ++++++------ src/ugui_cmd.c3 | 22 ++++++++++++++++++++- src/ugui_data.c3 | 12 ++++++------ src/ugui_font.c3 | 49 ++++++++++++++++++++++++++++++++++++++++++++++ src/ugui_layout.c3 | 2 +- src/ugui_text.c3 | 48 --------------------------------------------- 6 files changed, 83 insertions(+), 63 deletions(-) diff --git a/src/main.c3 b/src/main.c3 index 2a9b439..5acebe9 100644 --- a/src/main.c3 +++ b/src/main.c3 @@ -162,7 +162,6 @@ fn int main(String[] args) rl::unload_texture(font_texture); } font_texture = rl::load_texture_from_image(font_atlas); - //rl::draw_texture(font_texture, 0, 0, rl::WHITE); case ugui::CmdType.CMD_SPRITE: rl::Rectangle source = { .x = cmd.sprite.texture_rect.x, @@ -176,12 +175,12 @@ fn int main(String[] args) }; rl::draw_texture_rec(font_texture, source, position, rl::WHITE); - //rl::draw_rectangle(cmd.sprite.rect.x, - // cmd.sprite.rect.y, - // cmd.sprite.rect.w, - // cmd.sprite.rect.h, - // rl::WHITE - //); + case ugui::CmdType.CMD_SCISSOR: + if (cmd.scissor.rect.w == 0 && cmd.scissor.rect.h == 0) { + rl::end_scissor_mode(); + } else { + rl::begin_scissor_mode(cmd.scissor.rect.x, cmd.scissor.rect.y, cmd.scissor.rect.w, cmd.scissor.rect.h); + } default: io::printfn("Unknown cmd type: %s", cmd.type); } diff --git a/src/ugui_cmd.c3 b/src/ugui_cmd.c3 index e021ad1..16b49e5 100644 --- a/src/ugui_cmd.c3 +++ b/src/ugui_cmd.c3 @@ -7,6 +7,7 @@ enum CmdType { CMD_RECT, CMD_UPDATE_ATLAS, CMD_SPRITE, + CMD_SCISSOR, } // command to draw a rect @@ -16,7 +17,6 @@ struct CmdRect { Color color; } -// FIXME: For now only support black and white atlas, so PIXELFORMAT_UNCOMPRESSED_GRAYSCALE struct CmdUpdateAtlas { Id id; char* raw_buffer; @@ -31,6 +31,11 @@ struct CmdSprite { Rect texture_rect; } +// if rect is zero Rect{0} then reset the scissor +struct CmdScissor { + Rect rect; +} + // command structure struct Cmd { CmdType type; @@ -38,6 +43,7 @@ struct Cmd { CmdRect rect; CmdUpdateAtlas update_atlas; CmdSprite sprite; + CmdScissor scissor; } } @@ -96,6 +102,8 @@ fn void! Ctx.push_string(&ctx, Rect bounds, String text) return; } + ctx.push_scissor(bounds)!; + short baseline = (short)ctx.font.ascender; short line_height = (short)ctx.font.ascender - (short)ctx.font.descender; short line_gap = (short)ctx.font.linegap; @@ -135,6 +143,9 @@ fn void! Ctx.push_string(&ctx, Rect bounds, String text) continue; } } + + // FIXME: we never get here if an error was thrown before + ctx.push_scissor(Rect{})!; } fn void! Ctx.push_update_atlas(&ctx, Atlas* atlas) @@ -150,4 +161,13 @@ fn void! Ctx.push_update_atlas(&ctx, Atlas* atlas) }, }; ctx.cmd_queue.enqueue(&up)!; +} + +fn void! Ctx.push_scissor(&ctx, Rect rect) +{ + Cmd sc = { + .type = CMD_SCISSOR, + .scissor.rect = rect, + }; + ctx.cmd_queue.enqueue(&sc)!; } \ No newline at end of file diff --git a/src/ugui_data.c3 b/src/ugui_data.c3 index 1ec0539..7cd39da 100644 --- a/src/ugui_data.c3 +++ b/src/ugui_data.c3 @@ -54,7 +54,7 @@ enum DivLayout { } // div element -struct Div { +struct ElemDiv { DivLayout layout; struct scroll { bool can_x; @@ -70,12 +70,12 @@ struct Div { } // slider element -struct Slider { +struct ElemSlider { float value; Rect handle; } -struct Text { +struct ElemText { char* str; } @@ -87,9 +87,9 @@ struct Elem { Rect bounds; ElemType type; union { - Div div; - Slider slider; - Text text; + ElemDiv div; + ElemSlider slider; + ElemText text; } } diff --git a/src/ugui_font.c3 b/src/ugui_font.c3 index 68d1be8..f465650 100644 --- a/src/ugui_font.c3 +++ b/src/ugui_font.c3 @@ -1,9 +1,12 @@ module ugui; import schrift; +import grapheme; import std::collections::map; import std::core::mem; import std::io; +import std::ascii; + // unicode code point, different type for a different hash def Codepoint = uint; @@ -161,4 +164,50 @@ fn void Font.free(&font) fn void! Ctx.load_font(&ctx, String name, String path, uint height, float scale = 1.0) { return ctx.font.load(name, path, height, scale); +} + +<* +@require off != null +*> +fn Codepoint str_to_codepoint(char[] str, usz* off) +{ + Codepoint cp; + isz b = grapheme::decode_utf8(str, str.len, &cp); + if (b == 0 || b > str.len) { + return 0; + } + *off = b; + return cp; +} + +fn Rect! Ctx.get_text_bounds(&ctx, String text) +{ + Rect text_bounds; + short line_height = (short)ctx.font.ascender - (short)ctx.font.descender; + short line_gap = (short)ctx.font.linegap; + text_bounds.h = line_height; + Glyph* gp; + + // TODO: account for unicode codepoints + short line_len; + Codepoint cp; + usz off, x; + while ((cp = str_to_codepoint(text[off..], &x)) != 0) { + off += x; + bool n; + if (!ascii::is_cntrl((char)cp)) { + gp = ctx.font.get_glyph(cp)!; + line_len += gp.adv; + } else if (cp == '\n'){ + text_bounds.h += line_height + line_gap; + line_len = 0; + } else { + continue; + } + if (line_len > text_bounds.w) { + text_bounds.w = line_len; + } + } + + return text_bounds; } \ No newline at end of file diff --git a/src/ugui_layout.c3 b/src/ugui_layout.c3 index 5b56913..dcf63f4 100644 --- a/src/ugui_layout.c3 +++ b/src/ugui_layout.c3 @@ -86,7 +86,7 @@ fn Rect Ctx.position_element(&ctx, Elem *parent, Rect rect, bool style = false) { Rect placement; Point origin; - Div* div = &parent.div; + ElemDiv* div = &parent.div; // 1. Select the right origin switch (div.layout) { diff --git a/src/ugui_text.c3 b/src/ugui_text.c3 index 4b25ad8..88fb581 100644 --- a/src/ugui_text.c3 +++ b/src/ugui_text.c3 @@ -1,54 +1,6 @@ module ugui; import std::io; -import std::ascii; -import grapheme; - -<* -@require off != null -*> -fn Codepoint str_to_codepoint(char[] str, usz* off) -{ - Codepoint cp; - isz b = grapheme::decode_utf8(str, str.len, &cp); - if (b == 0 || b > str.len) { - return 0; - } - *off = b; - return cp; -} - -fn Rect! Ctx.get_text_bounds(&ctx, String text) -{ - Rect text_bounds; - short line_height = (short)ctx.font.ascender - (short)ctx.font.descender; - short line_gap = (short)ctx.font.linegap; - text_bounds.h = line_height; - Glyph* gp; - - // TODO: account for unicode codepoints - short line_len; - Codepoint cp; - usz off, x; - while ((cp = str_to_codepoint(text[off..], &x)) != 0) { - off += x; - bool n; - if (!ascii::is_cntrl((char)cp)) { - gp = ctx.font.get_glyph(cp)!; - line_len += gp.adv; - } else if (cp == '\n'){ - text_bounds.h += line_height + line_gap; - line_len = 0; - } else { - continue; - } - if (line_len > text_bounds.w) { - text_bounds.w = line_len; - } - } - - return text_bounds; -} fn void! Ctx.text_unbounded(&ctx, String label, String text) {