Fix ui::label underline & strikethrough handling
This commit is contained in:
parent
2b228fbd32
commit
3f282356d7
1 changed files with 31 additions and 65 deletions
|
|
@ -449,6 +449,17 @@ namespace psemek::ui
|
||||||
{
|
{
|
||||||
float const line_width = 1.f * (*st->text_scale);
|
float const line_width = 1.f * (*st->text_scale);
|
||||||
|
|
||||||
|
auto get_batch = [&](gfx::color_rgba const & color) -> cached_state::batch & {
|
||||||
|
auto texture = single_white_pixel_texture().get();
|
||||||
|
if (state.batches.empty() || state.batches.back().texture != texture || state.batches.back().color != color)
|
||||||
|
{
|
||||||
|
auto & b = state.batches.emplace_back();
|
||||||
|
b.texture = texture;
|
||||||
|
b.color = color;
|
||||||
|
}
|
||||||
|
return state.batches.back();
|
||||||
|
};
|
||||||
|
|
||||||
std::size_t ch_begin = 0;
|
std::size_t ch_begin = 0;
|
||||||
std::size_t ch = 0;
|
std::size_t ch = 0;
|
||||||
for (std::size_t l = 0; l < lines.size(); ++l)
|
for (std::size_t l = 0; l < lines.size(); ++l)
|
||||||
|
|
@ -456,33 +467,8 @@ namespace psemek::ui
|
||||||
float underline_y = std::round(line_offset[l][1] + font_height - line_width);
|
float underline_y = std::round(line_offset[l][1] + font_height - line_width);
|
||||||
float strikethrough_y = std::round(line_offset[l][1] + font_height / 2.f - line_width / 2.f);
|
float strikethrough_y = std::round(line_offset[l][1] + font_height / 2.f - line_width / 2.f);
|
||||||
|
|
||||||
std::optional<std::pair<geom::interval<float>, gfx::color_rgba>> current_underline;
|
std::optional<float> last_underline_end;
|
||||||
std::optional<std::pair<geom::interval<float>, gfx::color_rgba>> current_strikethrough;
|
std::optional<float> last_strikethrough_end;
|
||||||
|
|
||||||
auto batch = [&](gfx::color_rgba const & color) -> cached_state::batch & {
|
|
||||||
auto texture = single_white_pixel_texture().get();
|
|
||||||
if (state.batches.empty() || state.batches.back().texture != texture || state.batches.back().color != color)
|
|
||||||
{
|
|
||||||
auto & b = state.batches.emplace_back();
|
|
||||||
b.texture = texture;
|
|
||||||
b.color = color;
|
|
||||||
}
|
|
||||||
return state.batches.back();
|
|
||||||
};
|
|
||||||
|
|
||||||
auto flush_underline = [&]{
|
|
||||||
auto & image = batch(current_underline->second).images.emplace_back();
|
|
||||||
image.position[0] = current_underline->first;
|
|
||||||
image.position[1] = {underline_y, underline_y + line_width};
|
|
||||||
current_underline = std::nullopt;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto flush_strikethrough = [&]{
|
|
||||||
auto & image = batch(current_strikethrough->second).images.emplace_back();
|
|
||||||
image.position[0] = current_strikethrough->first;
|
|
||||||
image.position[1] = {strikethrough_y, strikethrough_y + line_width};
|
|
||||||
current_strikethrough = std::nullopt;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (; ch < glyph_chunks.size(); ++ch)
|
for (; ch < glyph_chunks.size(); ++ch)
|
||||||
{
|
{
|
||||||
|
|
@ -500,43 +486,29 @@ namespace psemek::ui
|
||||||
for (std::size_t i = ibegin; i < iend; ++i)
|
for (std::size_t i = ibegin; i < iend; ++i)
|
||||||
x_range |= glyphs[i].position[0];
|
x_range |= glyphs[i].position[0];
|
||||||
|
|
||||||
if (underline && current_underline)
|
if (underline)
|
||||||
{
|
{
|
||||||
if (current_underline->second != chunk.color)
|
auto & image = get_batch(chunk.color).images.emplace_back();
|
||||||
{
|
image.position[0] = x_range;
|
||||||
flush_underline();
|
if (last_underline_end)
|
||||||
current_underline = {x_range, chunk.color};
|
image.position[0] |= *last_underline_end;
|
||||||
}
|
image.position[1] = {underline_y, underline_y + line_width};
|
||||||
else
|
last_underline_end = image.position[0].max;
|
||||||
current_underline->first |= x_range;
|
|
||||||
}
|
|
||||||
else if (underline && !current_underline)
|
|
||||||
{
|
|
||||||
current_underline = {x_range, chunk.color};
|
|
||||||
}
|
|
||||||
else if (!underline && current_underline)
|
|
||||||
{
|
|
||||||
flush_underline();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
last_underline_end = std::nullopt;
|
||||||
|
|
||||||
if (strikethrough && current_strikethrough)
|
if (strikethrough)
|
||||||
{
|
{
|
||||||
if (current_strikethrough->second != chunk.color)
|
auto & image = get_batch(chunk.color).images.emplace_back();
|
||||||
{
|
image.position[0] = x_range;
|
||||||
flush_strikethrough();
|
if (last_strikethrough_end)
|
||||||
current_strikethrough = {x_range, chunk.color};
|
image.position[0] |= *last_strikethrough_end;
|
||||||
}
|
image.position[1] = {strikethrough_y, strikethrough_y + line_width};
|
||||||
else
|
last_strikethrough_end = image.position[0].max;
|
||||||
current_strikethrough->first |= x_range;
|
|
||||||
}
|
|
||||||
else if (strikethrough && !current_strikethrough)
|
|
||||||
{
|
|
||||||
current_strikethrough = {x_range, chunk.color};
|
|
||||||
}
|
|
||||||
else if (!strikethrough && current_strikethrough)
|
|
||||||
{
|
|
||||||
flush_strikethrough();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
last_strikethrough_end = std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chunk.end > lines[l].end)
|
if (chunk.end > lines[l].end)
|
||||||
|
|
@ -544,12 +516,6 @@ namespace psemek::ui
|
||||||
|
|
||||||
ch_begin = chunk.end;
|
ch_begin = chunk.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_underline)
|
|
||||||
flush_underline();
|
|
||||||
|
|
||||||
if (current_strikethrough)
|
|
||||||
flush_strikethrough();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue