text truncation

This commit is contained in:
jacob 2025-11-02 15:29:17 -06:00
parent 04d8039f5c
commit 658527738a
6 changed files with 82 additions and 24 deletions

View File

@ -245,6 +245,7 @@ F_Run F_RunFromString(Arena *arena, F_Font *font, String str)
F_Run result = ZI;
result.rects = PushDry(arena, F_RunRect);
f32 baseline_length = 0;
for (CodepointIter it = InitCodepointIter(str); NextCodepoint(&it);)
{
u32 codepoint = it.codepoint;
@ -263,15 +264,16 @@ F_Run F_RunFromString(Arena *arena, F_Font *font, String str)
rect->atlas_p1 = glyph.atlas_p1;
Vec2I32 size = SubVec2I32(glyph.atlas_p1, glyph.atlas_p0);
rect->baseline_start_offset = glyph.baseline_offset;
rect->baseline_start_offset.x += result.baseline_length;
rect->pos = baseline_length;
rect->offset = glyph.baseline_offset;
rect->advance = glyph.advance;
result.p0.x = MinF32(result.p0.x, rect->baseline_start_offset.x); /* Left run bounds */
result.p1.x = MaxF32(result.p1.x, rect->baseline_start_offset.x + size.x); /* Right run bounds */
result.p0.y = MinF32(result.p0.y, rect->baseline_start_offset.y); /* Top run bounds */
result.p1.y = MaxF32(result.p1.y, rect->baseline_start_offset.y + size.y); /* Bottom run bounds */
result.p0.x = MinF32(result.p0.x, rect->offset.x + rect->pos); /* Left run bounds */
result.p1.x = MaxF32(result.p1.x, rect->offset.x + rect->pos + size.x); /* Right run bounds */
result.p0.y = MinF32(result.p0.y, rect->offset.y); /* Top run bounds */
result.p1.y = MaxF32(result.p1.y, rect->offset.y + size.y); /* Bottom run bounds */
result.baseline_length += glyph.advance;
baseline_length += rect->advance;
}
}

View File

@ -31,7 +31,9 @@ Struct(F_Font)
Struct(F_RunRect)
{
Vec2 baseline_start_offset; /* Vector from start of baseline to top left of rect */
Vec2 offset; /* Vector from baseline offset to top left of glyph rect */
f32 pos; /* Horizontal distance from start of baseline */
f32 advance;
Vec2I32 atlas_p0;
Vec2I32 atlas_p1;
};
@ -40,7 +42,6 @@ Struct(F_Run)
{
Vec2 p0; /* Start of baseline to top-left-most rect */
Vec2 p1; /* Start of baseline to bottom-right-most rect corner */
f32 baseline_length;
u32 count;
F_RunRect *rects;
};

View File

@ -369,7 +369,7 @@ void DrawDebugConsole(b32 minimized)
if (minimized)
{
UI_SetNext(BackgroundColor, 0);
UI_SetNext(Width, UI_PIX(500, 1));
UI_SetNext(Width, UI_PIX(500, 0));
UI_SetNext(Height, UI_FIT(1));
}
else
@ -443,7 +443,7 @@ void DrawDebugConsole(b32 minimized)
u32 color = colors[log->level][log->color_index];
UI_SetNext(BackgroundColor, color);
UI_SetNext(LayoutAxis, Axis_X);
UI_SetNext(Width, UI_FILL(1, 1));
UI_SetNext(Width, UI_FILL(1, 0));
UI_SetNext(Height, UI_FIT(1));
UI_SetNext(BorderColor, Rgba32F(0.25, 0.25, 0.25, 1));
UI_SetNext(Rounding, 0);
@ -456,7 +456,7 @@ void DrawDebugConsole(b32 minimized)
UI_SetNext(Border, 0);
UI_SetNext(TextPadding, 6);
UI_SetNext(Text, text);
UI_SetNext(Width, UI_FILL(1, 1));
UI_SetNext(Width, UI_FILL(1, 0));
UI_SetNext(Height, UI_TXT(1));
UI_Box *log_textbox = UI_BuildBox(UI_BoxFlag_DrawText, UI_NilKey);
}
@ -2116,7 +2116,7 @@ void UpdateUser(void)
UI_SetNext(LayoutAxis, Axis_Y);
UI_SetNext(BackgroundColor, 0);
UI_SetNext(BorderColor, 0);
UI_SetNext(Width, UI_FIT(1));
UI_SetNext(Width, UI_FIT(0));
UI_SetNext(Height, UI_FIT(1));
UI_SetNext(Tint, 0);
UI_Box *dbg_box = UI_BuildBox(0, UI_NilKey);

View File

@ -1096,8 +1096,7 @@ void StepSim(SimStepCtx *ctx)
}
if (flags & ControlFlag_SpawnTest1)
{
// P_LogDebugF("Spawn test 1");
P_LogDebugF("Spawn test 1 ****************************************************************************************************************************************************************");
P_LogDebugF("Spawn test 1");
u32 count = 1;
f32 spread = 0;
for (u32 j = 0; j < count; ++j)

View File

@ -412,9 +412,13 @@ i64 UI_EndBuild(GPU_Resource *render_target)
}
if (axis == Axis_X)
{
f32 baseline_length = box->glyph_run.baseline_length;
if (box->glyph_run.count > 0)
{
F_RunRect rr = box->glyph_run.rects[box->glyph_run.count - 1];
f32 baseline_length = rr.pos + rr.advance;
text_size = baseline_length;
}
}
else
{
text_size = box->font->ascent + box->font->descent;
@ -507,8 +511,16 @@ i64 UI_EndBuild(GPU_Resource *render_target)
f32 size = child->solved_dims[axis];
f32 strictness = child->pref_size[axis].strictness;
f32 flex = size * (1.0 - strictness);
f32 new_size = size;
if (axis == box->layout_axis)
{
f32 chopoff = MinF32(flex, violation * (flex / flex_accum));
f32 new_size = size - chopoff;
new_size = size - chopoff;
}
else
{
new_size = MinF32(flex, box->solved_dims[axis]);
}
child->solved_dims[axis] = new_size;
}
}
@ -555,7 +567,7 @@ i64 UI_EndBuild(GPU_Resource *render_target)
is_visible = is_visible && (box->p1.y > box->p0.y);
if (is_visible || UI_DEBUG)
{
/* Push box rect */
/* Box rect */
{
UI_RectInstance *rect = PushStruct(g->draw_rects_arena, UI_RectInstance);
rect->flags |= UI_RectFlag_DrawTexture * !!(box->background_texture != 0);
@ -575,14 +587,14 @@ i64 UI_EndBuild(GPU_Resource *render_target)
rect->tex_uv1 = box->background_texture_uv1;
}
}
/* Push text rects */
/* Text rects */
if ((box->flags & UI_BoxFlag_DrawText) && box->glyph_run.count > 0 && box->font)
{
Texture2DRid tex_rid = GPU_Texture2DRidFromResource(box->font->texture);
Vec2 inv_font_image_size = VEC2(1.0f / (f32)box->font->image_width, 1.0f / (f32)box->font->image_height);
String text = box->display_text;
F_Run run = box->glyph_run;
f32 ascent = box->font->ascent;
f32 descent = box->font->descent;
@ -591,6 +603,49 @@ i64 UI_EndBuild(GPU_Resource *render_target)
Vec2 baseline = box->p0;
baseline = AddVec2(baseline, VEC2(padding, padding + ascent));
F_Run run = box->glyph_run;
f32 max_baseline = box->p1.x - (padding * 2);
b32 should_truncate = run.count > 0 && (run.rects[run.count - 1].pos + run.rects[run.count - 1].advance) > max_baseline;
/* Truncate run */
if (should_truncate && !(box->flags & UI_BoxFlag_NoTextTruncation))
{
/* Get elipses run */
F_Run trunc_run = F_RunFromString(g->build_arena, box->font, Lit("..."));
if (trunc_run.count > 0)
{
max_baseline -= trunc_run.rects[trunc_run.count - 1].pos + trunc_run.rects[trunc_run.count - 1].advance;
}
/* Subtract glyphs */
while (run.count > 0)
{
F_RunRect rr = run.rects[run.count - 1];
if (rr.pos + rr.advance <= max_baseline)
{
break;
}
--run.count;
}
/* Merge trunc rects */
F_RunRect *new_rects = 0;
{
new_rects = PushStructsNoZero(g->build_arena, F_RunRect, run.count + trunc_run.count);
CopyStructs(new_rects, run.rects, run.count);
f32 trunc_offset = run.count > 0 ? (run.rects[run.count - 1].pos + run.rects[run.count - 1].advance) : 0;
for (u32 i = 0; i < trunc_run.count; ++i)
{
F_RunRect *rr = &new_rects[i + run.count];
*rr = trunc_run.rects[i];
rr->pos += trunc_offset;
}
}
run.count += trunc_run.count;
run.rects = new_rects;
}
/* Push text rects */
for (u64 i = 0; i < run.count; ++i)
{
F_RunRect rr = run.rects[i];
@ -601,12 +656,12 @@ i64 UI_EndBuild(GPU_Resource *render_target)
{
UI_RectInstance *rect = PushStruct(g->draw_rects_arena, UI_RectInstance);
rect->flags |= UI_RectFlag_DrawTexture;
rect->p0 = AddVec2(baseline, rr.baseline_start_offset);
rect->p0 = AddVec2(baseline, VEC2(rr.pos, 0));
rect->p0 = AddVec2(rect->p0, rr.offset);
rect->p1 = AddVec2(rect->p0, glyph_size);
rect->tint_srgb = box->tint;
rect->tex_uv0 = MulVec2Vec2(atlas_p0, inv_font_image_size);
rect->tex_uv1 = MulVec2Vec2(atlas_p1, inv_font_image_size);
rect->tex = tex_rid;
}
}

View File

@ -87,6 +87,7 @@ Enum(UI_BoxFlag)
{
UI_BoxFlag_None = 0,
UI_BoxFlag_DrawText = (1 << 0),
UI_BoxFlag_NoTextTruncation = (1 << 1),
};
Struct(UI_Box)