Fix ui::label underline & strikethrough handling

This commit is contained in:
Nikita Lisitsa 2022-05-21 22:07:55 +03:00
parent 2b228fbd32
commit 3f282356d7

View file

@ -449,17 +449,7 @@ namespace psemek::ui
{ {
float const line_width = 1.f * (*st->text_scale); float const line_width = 1.f * (*st->text_scale);
std::size_t ch_begin = 0; auto get_batch = [&](gfx::color_rgba const & color) -> cached_state::batch & {
std::size_t ch = 0;
for (std::size_t l = 0; l < lines.size(); ++l)
{
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);
std::optional<std::pair<geom::interval<float>, gfx::color_rgba>> current_underline;
std::optional<std::pair<geom::interval<float>, gfx::color_rgba>> current_strikethrough;
auto batch = [&](gfx::color_rgba const & color) -> cached_state::batch & {
auto texture = single_white_pixel_texture().get(); auto texture = single_white_pixel_texture().get();
if (state.batches.empty() || state.batches.back().texture != texture || state.batches.back().color != color) if (state.batches.empty() || state.batches.back().texture != texture || state.batches.back().color != color)
{ {
@ -470,19 +460,15 @@ namespace psemek::ui
return state.batches.back(); return state.batches.back();
}; };
auto flush_underline = [&]{ std::size_t ch_begin = 0;
auto & image = batch(current_underline->second).images.emplace_back(); std::size_t ch = 0;
image.position[0] = current_underline->first; for (std::size_t l = 0; l < lines.size(); ++l)
image.position[1] = {underline_y, underline_y + line_width}; {
current_underline = std::nullopt; 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);
auto flush_strikethrough = [&]{ std::optional<float> last_underline_end;
auto & image = batch(current_strikethrough->second).images.emplace_back(); std::optional<float> last_strikethrough_end;
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};
last_underline_end = image.position[0].max;
} }
else else
current_underline->first |= x_range; last_underline_end = std::nullopt;
}
else if (underline && !current_underline)
{
current_underline = {x_range, chunk.color};
}
else if (!underline && current_underline)
{
flush_underline();
}
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};
last_strikethrough_end = image.position[0].max;
} }
else else
current_strikethrough->first |= x_range; last_strikethrough_end = std::nullopt;
}
else if (strikethrough && !current_strikethrough)
{
current_strikethrough = {x_range, chunk.color};
}
else if (!strikethrough && current_strikethrough)
{
flush_strikethrough();
}
} }
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();
} }
} }