intermediate

This commit is contained in:
Vicente Ferrari Smith 2025-07-17 07:27:27 +02:00
parent 68096796dc
commit 3520906f28
12 changed files with 309 additions and 15 deletions

View File

@ -6,7 +6,7 @@
NAME :: "mexplore";
VERSION :: "0.1";
JAI_VERSION :: "beta 0.2.014, built on 24 May 2025";
RELEASE_DATE :: "13 July 2025, 19:51:19";
RELEASE_DATE :: "16 July 2025, 20:47:28";
GIT_BRANCH :: "main";
GIT_REVISION :: "ad439a550931e9088715ccfbe161757bcead4a9a";
GIT_REVISION :: "68096796dc50c0bfe4e9d687ce4e9563e0bbf4bb";
DEBUG :: true;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -283,7 +283,7 @@ STB_TEXTEDIT_STRINGLEN :: (obj: *STB_TEXTEDIT_STRING) -> s32 {
}
STB_TEXTEDIT_KEYTOTEXT :: (k: STB_TEXTEDIT_KEYTYPE) -> s32 #expand {
return ifx k >= 32 && k < 127 then k else -1;
return ifx k >= 32 then k else -1;
}
STB_TEXTEDIT_DELETECHARS :: (obj: *STB_TEXTEDIT_STRING, i: s32, n: s32) {
@ -339,11 +339,24 @@ STB_TEXTEDIT_LAYOUTROW :: (row: *StbTexteditRow, obj: *STB_TEXTEDIT_STRING, n: s
//size, max_descent, read := SegmentText(obj.font, text_utf32.data, xx text_utf32.count);
idx : s32;
while idx < obj.text.count && row.x1 < obj.max_size.x {
size, max_descent, read := next_word_size(obj.font, .{obj.text.count, obj.text.data}, n + idx, obj.max_size.x);
while word := n + idx < obj.text.count && row.x1 < obj.max_size.x {
size, max_descent, read := next_word_size(obj.font, obj.text, n + idx, obj.max_size.x);
if row.x1 + size.x > obj.max_size.x {
break;
while grapheme := idx < obj.text.count {
size, max_descent, read := next_grapheme_size(obj.font, obj.text, n + idx, obj.max_size.x);
if row.x1 + size.x > obj.max_size.x {
break word;
}
row.x1 += size.x;
row.baseline_y_delta = max(row.baseline_y_delta, size.y);
row.ymin = max(row.ymin, max_descent);
row.ymax = max(row.ymax, size.y - row.ymin);
row.num_chars += read;
idx += read;
}
}
row.x1 += size.x;

View File

@ -81,8 +81,11 @@ init_font :: (using font: *Font, filename: string, size: s32) {
charcode : FT_ULong;
gindex : FT_UInt;
i : int;
charcode = FT_Get_First_Char(face, *gindex);
while gindex != 0 {
log("Reading index: % - Charcode: %", gindex, charcode);
error = FT_Load_Glyph(face, gindex, FT_LOAD_RENDER);
if error
log("%", to_string(FT_Error_String(error)));
@ -108,6 +111,7 @@ init_font :: (using font: *Font, filename: string, size: s32) {
table_set(*font.glyphs, glyph.index, glyph);
charcode = FT_Get_Next_Char(face, charcode, *gindex);
i += 1;
}
// for 0..face.num_glyphs {
@ -275,6 +279,12 @@ render_text :: (font: *Font, text: []u32, pos: Vector2, size: Vector2, window_sp
glyph : *Glyph = table_find_pointer(*font.glyphs, kglyph.Id);
if !glyph {
log("[Error] Panic! Didn't find the glyph!");
for font.glyphs
log("%", it);
}
v0 : Vector2;
v1 : Vector2;
if count_descent {
@ -633,6 +643,250 @@ SegmentText :: (font: *Font, Codepoints: *u32, CodepointCount: u64) -> Vector2,
// return 0;
// }
next_grapheme_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0) -> Vector2, float, s32 {
textp : *u32 = text.data;
Codepoints : *u32 = textp + n;
CodepointCount : u64 = xx (text.count - (Codepoints - textp));
// text_utf32 : [..]u32;
// defer array_free(text_utf32);
// StringAt : u64;
// while StringAt < xx len {
// Decode : kbts_decode = kbts_DecodeUtf8(line_start + StringAt, xx len - StringAt);
// StringAt += Decode.SourceCharactersConsumed;
// if Decode.Valid {
// array_add(*text_utf32, Decode.Codepoint);
// }
// }
//size, max_descent, read := SegmentText(font, line_start, len);
//return size, max_descent, read;
Cursor : kbts_cursor;
Direction : kbts_direction = .NONE;
Script : kbts_script = .DONT_KNOW;
RunStart : u64 = 0;
BreakState : kbts_break_state;
kbts_BeginBreak(*BreakState, .NONE, .NORMAL);
// size : Vector2;
// max_descent : float;
CodepointIndex : u64;
while CodepointIndex < xx CodepointCount {
kbts_BreakAddCodepoint(*BreakState, Codepoints[CodepointIndex], 1, xx ((CodepointIndex + 1) == xx CodepointCount));
Break : kbts_break;
while kbts_Break(*BreakState, *Break) {
// if (Break.Position > RunStart) && (Break.Flags & (.DIRECTION | .SCRIPT | .LINE_HARD)) {
// RunLength : u64 = Break.Position - RunStart;
// size, max_descent := ShapeText(font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script);
// return size, max_descent, Break.Position;
// }
// if (Break.Position > RunStart) && (Break.Flags & (.DIRECTION | .SCRIPT | .LINE_HARD)) {
// RunLength : u64 = Break.Position - RunStart;
// size, max_descent := ShapeText(font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script);
// return size, max_descent, xx CodepointIndex;
// }
if Break.Flags & .DIRECTION {
Direction = Break.Direction;
if(!Cursor.Direction) Cursor = kbts_Cursor(BreakState.MainDirection);
}
if Break.Flags & .SCRIPT {
Script = Break.Script;
}
if (Break.Position > RunStart) && (Break.Flags & .GRAPHEME) {
RunLength : u64 = Break.Position - RunStart;
size, max_descent := ShapeText(font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script);
//if max_width > 0.0 && size.x + word_size.x > max_width {
return size, max_descent, xx Break.Position;
//}
// size.x += word_size.x;
// size.y = max(word_size.y);
// max_descent = max(max_descent, word_max_descent);
}
// if (Break.Position > RunStart) && Break.Flags & .LINE_HARD {
// RunLength : u64 = Break.Position - RunStart;
// word_size, word_max_descent := ShapeText(font, *Cursor, Codepoints + RunStart, RunLength, BreakState.MainDirection, Direction, Script);
// return size, max_descent, Break.Position;
// }
}
CodepointIndex += 1;
}
return .{}, 0, 0;
// words := split(text, " ");
// for *word : words {
// if word.* != "" && word.data - text.data + word.count < text.count {
// if text[word.data - text.data + word.count] == " " {
// word.count += 1;
// }
// }
// }
//total_size : Vector2;
// lines : [..]Line;
// if !text {
// return .{}, 0.0, 0.0, lines;
// }
// if words.count == 0 {
// return .{}, 0.0, 0.0, lines;
// }
// text_utf32 : [..]u32;
// defer array_free(text_utf32);
// StringAt : u64;
// while StringAt < text.count {
// Decode : kbts_decode = kbts_DecodeUtf8(text.data, text.count - StringAt);
// StringAt += Decode.SourceCharactersConsumed;
// if Decode.Valid {
// array_add(*text_utf32, Decode.Codepoint);
// }
// }
// String : *u8 = text_utf32.data;
// Length : u64 = text_utf32.count;
// // Make some glyphs
// kbts_glyph *Glyphs = cast(*kbts_glyph, alloc(size_of(kbts_glyph) * Length));
// GlyphCount : u32 = 0;
// Script : kbts_script = KBTS_SCRIPT_DONT_KNOW;
// Direction : kbts_direction = KBTS_DIRECTION_NONE;
// StringAt : u64;
// while StringAt < Length {
// Decode : kbts_decode = kbts_DecodeUtf8(String, Length - StringAt);
// StringAt += Decode.SourceCharactersConsumed;
// if(Decode.Valid) {
// Glyph : kbts_glyph = kbts_CodepointToGlyph(*Font, Decode.Codepoint);
// // Easy script inference for simple cases. (This is similar to hb_buffer_guess_segment_properties.)
// // If you have already segmented String with our API, you already have a script!
// // So no need to pass it in that case.
// // Only use this as a shorthand, when you are pretty sure String is a single
// // script.
// kbts_InferScript(*Direction, *Script, Glyph.Script);
// Glyphs[GlyphCount] = Glyph;
// GlyphCount += 1;
// }
// }
// void SegmentText(uint32_t *Codepoints, size_t CodepointCount)
// line : Line;
// for word : words {
// started_a_line : bool;
// if line.text.count == 0 {
// line.text.data = word.data;
// line.text.count = word.count;
// started_a_line = true;
// }
// buf : *hb_buffer_t = hb_buffer_create();
// hb_buffer_add_utf8(buf, word.data, xx word.count, 0, -1);
// hb_buffer_set_direction(buf, hb_direction_t.LTR);
// hb_buffer_set_script(buf, hb_script_t.HB_SCRIPT_LATIN);
// hb_buffer_set_language(buf, hb_language_from_string("en", -1));
// features : [1]hb_feature_t;
// features[0].tag = HB_TAG(#char "c", #char "a", #char "l", #char "t");
// features[0].value = 1;
// features[0].start = HB_FEATURE_GLOBAL_START;
// features[0].end = HB_FEATURE_GLOBAL_END;
// hb_shape(font.hb, buf, features.data, features.count);
// glyph_count_u : u32;
// glyph_info : *hb_glyph_info_t = hb_buffer_get_glyph_infos(buf, *glyph_count_u);
// glyph_pos : *hb_glyph_position_t = hb_buffer_get_glyph_positions(buf, *glyph_count_u);
// glyph_count : s32 = xx glyph_count_u;
// word_size : Vector2;
// for i : 0..glyph_count - 1 {
// glyphid : hb_codepoint_t = glyph_info[i].codepoint;
// x_offset : hb_position_t = glyph_pos[i].x_offset;
// y_offset : hb_position_t = glyph_pos[i].y_offset;
// x_advance : hb_position_t = glyph_pos[i].x_advance;
// y_advance : hb_position_t = glyph_pos[i].y_advance;
// glyph : *Glyph = table_find_pointer(*font.glyphs, glyphid);
// if glyph {
// word_size.y = max(word_size.y, xx (glyph.height + glyph.descent));
// word_size.x += x_advance / 64.0;
// line.max_descent = max(line.max_descent, cast(float) glyph.descent);
// line.max_ascent = max(line.max_ascent, cast(float) glyph.ascent);
// }
// }
// if !started_a_line {
// line.text.count += word.count;
// }
// if max_width > 0.0 {
// if line.size.x + word_size.x > max_width {
// line.size.x = max_width;
// line.size.y = max(line.size.y, word_size.y);
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// array_add(*lines, line);
// line = .{};
// } else {
// line.size.y = max(total_size.y, word_size.y);
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// line.size.x += word_size.x;
// // } else {
// // line.text.data = word.data;
// // line.text.count = word.count;
// // }
// }
// } else if max_width == 0.0 {
// line.size.y = max(total_size.y, word_size.y);
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// line.size.x += word_size.x;
// // if include_descent
// // size.y = max_ascent + max_descent;
// }
// hb_buffer_destroy(buf);
// }
// if line.text.count > 0 {
// line.size.y = max(line.size.y, line.max_ascent + line.max_descent);
// array_add(*lines, line);
// line = .{};
// }
// for line : lines {
// total_size.x = max(total_size.x, line.size.x);
// total_size.y += line.size.y;
// }
//return total_size, 0, 0;
}
next_word_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0) -> Vector2, float, s32 {
textp : *u32 = text.data;

View File

@ -984,19 +984,19 @@ ui_draw_text_input :: (using text_input: *TextInput) {
if text_input.text.count > 0 {
//midline : Vector2 = pos + Vector2.{cast(float, margin + border_size + padding), xx (size.y / 2.0)};
row : StbTexteditRow;
draw_pos : Vector2 = pos + v2(margin);
i : s32;
while i < text_input.text.count {
row : StbTexteditRow;
STB_TEXTEDIT_LAYOUTROW(*row, text_input, i);
render_text(font, .{row.num_chars, text_input.text.data + i},
.{draw_pos.x, draw_pos.y + row.ymin /*+ line.max_descent*/}, text_input.size,
colour = font_colour);
draw_pos.y -= row.baseline_y_delta;
draw_pos.y -= font.face.size.metrics.height >> 6;
i += xx row.num_chars;
}
@ -1363,6 +1363,7 @@ ui_grow_roots :: () {
if bottom_left.sizing_x == .GROW {
bottom_left.size.x = xx window_width;
bottom_left.max_size.x = bottom_left.size.x;
}
}
@ -1376,6 +1377,7 @@ ui_grow_roots :: () {
if top_left.sizing_x == .GROW {
top_left.size.x = xx window_width;
top_left.max_size.x = top_left.size.x;
}
ui_grow_containers(top_left);
@ -1583,13 +1585,21 @@ ui_max_sizes :: () {
if next.type == .CONTAINER
ui_max_size_containers(next);
if next.type == .TEXTINPUT {
text_input := cast(*TextInput, next);
text_input.max_size.x = top_left.max_size.x;
return;
}
next = next.next;
}
}
}
ui_max_size_containers :: (rect: *Rect) {
if rect.type != .CONTAINER return;
if rect.type != .CONTAINER
return;
container := cast(*Container, rect);

29
ui.rad
View File

@ -1,15 +1,15 @@
// raddbg 0.9.20 project file
recent_file: path: "src/main.jai"
recent_file: path: "src/text.jai"
recent_file: path: "src/ui.jai"
recent_file: path: "src/stb_textedit.jai"
recent_file: path: "../../../../jai/modules/runtime_support.jai"
recent_file: path: "modules/kb_text_shape/kb_text_shape.h"
recent_file: path: "src/main.jai"
recent_file: path: "../../../../jai/modules/math/module.jai"
recent_file: path: "../../../../jai/modules/basic/array.jai"
recent_file: path: "src/stb_textedit.jai"
recent_file: path: "src/text.jai"
recent_file: path: "modules/kb_text_shape/kb_text_shape.h"
recent_file: path: "../../../../jai/modules/basic/module.jai"
recent_file: path: "../../../../jai/modules/default_allocator/module.jai"
recent_file: path: "../../../../jai/modules/runtime_support.jai"
target:
{
executable: "bin/mexplore-debug.exe"
@ -18,7 +18,24 @@ target:
}
breakpoint:
{
source_location: "src/stb_textedit.jai:990:1"
source_location: "src/ui.jai:1588:1"
hit_count: 0
enabled: 0
}
breakpoint:
{
source_location: "src/ui.jai:262:1"
hit_count: 0
enabled: 0
}
breakpoint:
{
source_location: "src/stb_textedit.jai:346:1"
hit_count: 0
enabled: 0
}
breakpoint:
{
source_location: "src/text.jai:282:1"
hit_count: 8
}