text editing
This commit is contained in:
parent
3520906f28
commit
89727b9bc1
@ -6,7 +6,7 @@
|
||||
NAME :: "mexplore";
|
||||
VERSION :: "0.1";
|
||||
JAI_VERSION :: "beta 0.2.014, built on 24 May 2025";
|
||||
RELEASE_DATE :: "16 July 2025, 20:47:28";
|
||||
RELEASE_DATE :: "19 July 2025, 16:47:42";
|
||||
GIT_BRANCH :: "main";
|
||||
GIT_REVISION :: "68096796dc50c0bfe4e9d687ce4e9563e0bbf4bb";
|
||||
GIT_REVISION :: "3520906f2803cf5baf5d52dcb05daf94d8edadd1";
|
||||
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.
Binary file not shown.
10
src/main.jai
10
src/main.jai
@ -77,9 +77,15 @@ main :: () {
|
||||
running = false;
|
||||
|
||||
case SDL_EVENT_KEY_DOWN;
|
||||
if event.key.key == SDLK_ESCAPE
|
||||
if event.key.key == {
|
||||
case SDLK_ESCAPE;
|
||||
running = false;
|
||||
|
||||
case SDLK_RETURN;
|
||||
log("pressing enter");
|
||||
input_state.last_char = STB_TEXTEDIT_NEWLINE;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_MOTION;
|
||||
transition.motion_delta = .{event.motion.xrel, event.motion.yrel};
|
||||
|
||||
@ -152,7 +158,7 @@ main :: () {
|
||||
ui_context.sizing_x = .FIT;
|
||||
ui_context.sizing_y = .FIT;
|
||||
//ui_label("Hello, World! How's it going?");
|
||||
ui_label("Hello, World!");
|
||||
//ui_label("Hello, World!");
|
||||
ui_text_input("Name");
|
||||
// ui_begin_container("Picture-Name-Settings");
|
||||
// {
|
||||
|
||||
@ -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 then k else -1;
|
||||
return ifx k >= 0 then k else -1;
|
||||
}
|
||||
|
||||
STB_TEXTEDIT_DELETECHARS :: (obj: *STB_TEXTEDIT_STRING, i: s32, n: s32) {
|
||||
@ -321,33 +321,31 @@ STB_TEXTEDIT_INSERTCHARS :: (obj: *STB_TEXTEDIT_STRING, i: s32, c: *STB_TEXTEDIT
|
||||
}
|
||||
|
||||
STB_TEXTEDIT_LAYOUTROW :: (row: *StbTexteditRow, obj: *STB_TEXTEDIT_STRING, n: s32) {
|
||||
// text : *u8 = obj.text.data;
|
||||
// line_start : *u8 = text + n;
|
||||
// len := obj.text.count - (line_start - text);
|
||||
|
||||
// text_utf32 : [..]u32;
|
||||
// defer array_free(text_utf32);
|
||||
|
||||
// StringAt : u64;
|
||||
// while StringAt < xx len {
|
||||
// Decode : kbts_decode = kbts_DecodeUtf8(line_start, xx len - StringAt);
|
||||
// StringAt += Decode.SourceCharactersConsumed;
|
||||
// if Decode.Valid {
|
||||
// array_add(*text_utf32, Decode.Codepoint);
|
||||
// }
|
||||
// }
|
||||
|
||||
//size, max_descent, read := SegmentText(obj.font, text_utf32.data, xx text_utf32.count);
|
||||
idx : s32;
|
||||
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 n + idx < obj.text.count && row.x1 < obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding) {
|
||||
size, max_descent, read := next_line_size(obj.font, obj.text, n + idx, obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding));
|
||||
|
||||
if row.x1 + size.x > obj.max_size.x {
|
||||
if row.x1 + size.x > obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding) {
|
||||
|
||||
while word := n + idx < obj.text.count && row.x1 < obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding) {
|
||||
size, max_descent, read := next_word_size(obj.font, obj.text, n + idx, obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding));
|
||||
|
||||
if row.x1 + size.x > obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding) {
|
||||
while grapheme := idx < obj.text.count {
|
||||
size, max_descent, read := next_grapheme_size(obj.font, obj.text, n + idx, obj.max_size.x);
|
||||
size, max_descent, read := next_grapheme_size(obj.font, obj.text, n + idx, obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding));
|
||||
|
||||
if row.x1 + size.x > obj.max_size.x {
|
||||
break word;
|
||||
if row.x1 + size.x > obj.max_size.x - (2 * obj.margin + 2 * obj.border_size + 2 * obj.padding) {
|
||||
//break word;
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
@ -368,153 +366,6 @@ STB_TEXTEDIT_LAYOUTROW :: (row: *StbTexteditRow, obj: *STB_TEXTEDIT_STRING, n: s
|
||||
}
|
||||
|
||||
row.x0 = 0.0;
|
||||
|
||||
// words := split(.{len, line_start}, " ");
|
||||
|
||||
// for *word : words {
|
||||
// if word.* != "" && word.data - line_start + word.count < len {
|
||||
// if text[word.data - line_start + len] == " " {
|
||||
// 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;
|
||||
// }
|
||||
|
||||
//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(obj.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(*obj.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 obj.max_size.x > 0.0 {
|
||||
// if line.size.x + word_size.x > obj.max_size.x {
|
||||
// line.size.x = obj.max_size.x;
|
||||
// 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 obj.max_size.x == 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;
|
||||
// }
|
||||
|
||||
// // determine how many characters to shape (until newline or wrap)
|
||||
// // for simplicity, shape a chunk of ~256 characters or to newline
|
||||
// p := line_start;
|
||||
// len : s32 = 0;
|
||||
// while p.* && p.* != #char "\n" && len < 256 {
|
||||
// p += 1;
|
||||
// len += 1;
|
||||
// }
|
||||
|
||||
// // shape the text
|
||||
// buf : *hb_buffer_t = hb_buffer_create();
|
||||
// hb_buffer_add_utf8(buf, line_start, len, 0, len);
|
||||
// hb_buffer_guess_segment_properties(buf);
|
||||
// hb_shape(hb_font, buf, NULL, 0);
|
||||
|
||||
// glyph_count : u32;
|
||||
// glyph_info : *hb_glyph_info_t = hb_buffer_get_glyph_infos(buf, *glyph_count);
|
||||
// pos : *hb_glyph_position_t = hb_buffer_get_glyph_positions(buf, *glyph_count);
|
||||
|
||||
// // iterate through glyphs, accumulate width
|
||||
// x : float = 0.0;
|
||||
// num_chars : s32 = 0;
|
||||
// for i : 0..glyph_count - 1 {
|
||||
// x += pos[i].x_advance / 64.0; // HarfBuzz uses 26.6 fixed-point
|
||||
// num_chars += 1;
|
||||
// // optional: if you have a max line width, break here
|
||||
// }
|
||||
|
||||
// 4. Use FreeType or your line layout logic for line height
|
||||
// line_height : float = obj->font->height; // or extract from FT_Size_Metrics
|
||||
// ymin : float = -obj->font->ascent;
|
||||
// ymax : float = obj->font->descent;
|
||||
|
||||
//hb_buffer_destroy(buf);
|
||||
}
|
||||
|
||||
STB_TEXTEDIT_GETWIDTH :: (obj: *STB_TEXTEDIT_STRING, n: s32, i: s32) -> float {
|
||||
|
||||
253
src/text.jai
253
src/text.jai
@ -85,7 +85,6 @@ init_font :: (using font: *Font, filename: string, size: s32) {
|
||||
|
||||
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)));
|
||||
@ -280,9 +279,9 @@ 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);
|
||||
//log("[Error] Panic! Didn't find the glyph!");
|
||||
GlyphIndex += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
v0 : Vector2;
|
||||
@ -649,23 +648,6 @@ next_grapheme_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0)
|
||||
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;
|
||||
@ -673,29 +655,12 @@ next_grapheme_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.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);
|
||||
@ -709,182 +674,14 @@ next_grapheme_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0)
|
||||
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 {
|
||||
@ -1065,6 +862,48 @@ next_word_size :: (font: *Font, text: []u32, n: s32, max_width: float = 0.0) ->
|
||||
//return total_size, 0, 0;
|
||||
}
|
||||
|
||||
next_line_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));
|
||||
|
||||
Cursor : kbts_cursor;
|
||||
Direction : kbts_direction = .NONE;
|
||||
Script : kbts_script = .DONT_KNOW;
|
||||
RunStart : u64 = 0;
|
||||
BreakState : kbts_break_state;
|
||||
kbts_BeginBreak(*BreakState, .NONE, .NORMAL);
|
||||
|
||||
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.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 & .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 Break.Position;
|
||||
}
|
||||
}
|
||||
|
||||
CodepointIndex += 1;
|
||||
}
|
||||
|
||||
return .{}, 0, 0;
|
||||
}
|
||||
|
||||
make_texture_from_data :: (data: *u8, width: s32, height: s32) -> Texture {
|
||||
if !data {
|
||||
log("[Error] Could not load the texture.");
|
||||
@ -1102,7 +941,7 @@ PRIMITIVE_TYPE :: enum u8 {
|
||||
render_batch :: (primitive_type: PRIMITIVE_TYPE, vertices: []$T, shader: *_Shader, texture: *Texture, view: Matrix4, proj: Matrix4) {
|
||||
|
||||
if !vertices {
|
||||
log("[Error] The batch has no vertices.");
|
||||
//log("[Error] The batch has no vertices.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
35
src/ui.jai
35
src/ui.jai
@ -899,39 +899,50 @@ ui_text_input :: (s: string, font_colour := Vector4.{1, 1, 1, 1}) {
|
||||
//text_input.frame = get_texture("panel-border-000");
|
||||
|
||||
text_input.font = ui_context.font;
|
||||
stb_textedit_initialize_state(*text_input.textedit_state, 1);
|
||||
stb_textedit_initialize_state(*text_input.textedit_state, 0);
|
||||
}
|
||||
|
||||
ui_append_to_parent(text_input);
|
||||
|
||||
if text_input.active && input_state.last_char > 0 {
|
||||
stb_textedit_key(text_input, *text_input.textedit_state, input_state.last_char);
|
||||
log("adding char %", input_state.last_char);
|
||||
// log("Adding % to builder.", to_string(*input_state.last_char, 1));
|
||||
// append(*text_input.input_buffer, input_state.last_char);
|
||||
}
|
||||
|
||||
text_size : Vector2;
|
||||
text_size.y = xx text_input.font.face.size.metrics.height >> 6;
|
||||
//text_size.y = xx text_input.font.face.size.metrics.height >> 6;
|
||||
//str := builder_to_string(*text_input.input_buffer, 0, false);
|
||||
// if str.count > 0 {
|
||||
// defer free(str);
|
||||
// textsize = Vector2.{xx Simp.prepare_text(text_input.font, str), xx text_input.font.character_height};
|
||||
// }
|
||||
max_descent : float;
|
||||
idx : s32;
|
||||
while idx < text_input.text.count {
|
||||
word_size, word_descent, read := next_word_size(text_input.font, text_input.text, idx, 0.0);
|
||||
// idx : s32;
|
||||
// while idx < text_input.text.count {
|
||||
// word_size, word_descent, read := next_word_size(text_input.font, text_input.text, idx, 0.0);
|
||||
|
||||
text_size.x += word_size.x;
|
||||
text_size.y = max(text_size.y, word_size.y);
|
||||
max_descent = max(max_descent, word_descent);
|
||||
// text_size.x += word_size.x;
|
||||
// text_size.y = max(text_size.y, word_size.y);
|
||||
// max_descent = max(max_descent, word_descent);
|
||||
|
||||
idx += read;
|
||||
// idx += read;
|
||||
// }
|
||||
|
||||
i : s32;
|
||||
while i < text_input.text.count {
|
||||
row : StbTexteditRow;
|
||||
STB_TEXTEDIT_LAYOUTROW(*row, text_input, i);
|
||||
|
||||
text_size.x = max(text_size.x, row.x1);
|
||||
text_size.y += text_input.font.face.size.metrics.height >> 6;
|
||||
|
||||
i += xx row.num_chars;
|
||||
}
|
||||
|
||||
text_input.min_size = v2(2 * text_input.margin + 2 * text_input.border_size + 2 * text_input.padding) + text_size;
|
||||
text_input.min_size = v2(2 * text_input.margin + 2 * text_input.border_size + 2 * text_input.padding) + max(text_size, .{xx text_input.font.face.size.metrics.max_advance >> 6, xx text_input.font.face.size.metrics.height >> 6});
|
||||
text_input.size = text_input.min_size;
|
||||
text_input.size = max(text_input.size, .{40.0, 20.0});
|
||||
text_input.max_size = text_input.size;
|
||||
text_input.anchor = ui_context.anchor;
|
||||
|
||||
@ -984,7 +995,7 @@ 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)};
|
||||
|
||||
draw_pos : Vector2 = pos + v2(margin);
|
||||
draw_pos : Vector2 = pos + .{0.0, size.y - font.face.size.metrics.height >> 6 - (margin + border_size + padding)} + v2(margin) + v2(border_size) + v2(padding);
|
||||
|
||||
i : s32;
|
||||
|
||||
|
||||
60
ui.rad
60
ui.rad
@ -1,41 +1,51 @@
|
||||
// raddbg 0.9.20 project file
|
||||
|
||||
recent_file: path: "src/text.jai"
|
||||
recent_file: path: "../jai_test/j.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/text.jai"
|
||||
recent_file: path: "modules/SDL3/src/SDL-release-3.2.16/src/events/sdl_keyboard.c"
|
||||
recent_file: path: "modules/SDL3/src/SDL-release-3.2.16/src/video/windows/SDL_windowsevents.c"
|
||||
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: "../../../../jai/modules/math/module.jai"
|
||||
recent_file: path: "src/math/math.jai"
|
||||
recent_file: path: "../../../../jai/modules/runtime_support.jai"
|
||||
recent_file: path: "../../../../jai/modules/basic/module.jai"
|
||||
recent_file: path: "../../../../jai/modules/default_allocator/module.jai"
|
||||
breakpoint:
|
||||
{
|
||||
source_location: "src/text.jai:516:1"
|
||||
hit_count: 0
|
||||
enabled: 0
|
||||
}
|
||||
breakpoint:
|
||||
{
|
||||
source_location: "src/ui.jai:935:1"
|
||||
hit_count: 0
|
||||
enabled: 0
|
||||
}
|
||||
breakpoint:
|
||||
{
|
||||
source_location: "src/text.jai:944:1"
|
||||
hit_count: 0
|
||||
enabled: 0
|
||||
}
|
||||
breakpoint:
|
||||
{
|
||||
source_location: "src/ui.jai:908:1"
|
||||
hit_count: 0
|
||||
enabled: 0
|
||||
}
|
||||
target:
|
||||
{
|
||||
executable: "bin/mexplore-debug.exe"
|
||||
working_directory: bin
|
||||
executable: "../jai_test/j.exe"
|
||||
working_directory: "../jai_test/"
|
||||
enabled: 1
|
||||
}
|
||||
breakpoint:
|
||||
{
|
||||
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
|
||||
source_location: "../jai_test/j.jai:44:1"
|
||||
hit_count: 1
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user