mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:27:35 +00:00
LibGfx: Avoid rounding/truncating glyph positions till blitting
This keeps some overloads that accept ints to avoid adding calls to .to_type<float>() all over the place.
This commit is contained in:
parent
68f678f566
commit
a1726b1ba5
14 changed files with 172 additions and 106 deletions
|
@ -1375,20 +1375,20 @@ void Painter::draw_scaled_bitmap(IntRect const& a_dst_rect, Gfx::Bitmap const& s
|
|||
}
|
||||
}
|
||||
|
||||
FLATTEN void Painter::draw_glyph(IntPoint point, u32 code_point, Color color)
|
||||
FLATTEN void Painter::draw_glyph(FloatPoint point, u32 code_point, Color color)
|
||||
{
|
||||
draw_glyph(point, code_point, font(), color);
|
||||
}
|
||||
|
||||
FLATTEN void Painter::draw_glyph(IntPoint point, u32 code_point, Font const& font, Color color)
|
||||
FLATTEN void Painter::draw_glyph(FloatPoint point, u32 code_point, Font const& font, Color color)
|
||||
{
|
||||
auto glyph = font.glyph(code_point);
|
||||
auto top_left = point + IntPoint(glyph.left_bearing(), 0);
|
||||
|
||||
if (glyph.is_glyph_bitmap()) {
|
||||
draw_bitmap(top_left, glyph.glyph_bitmap(), color);
|
||||
draw_bitmap(top_left.to_type<int>(), glyph.glyph_bitmap(), color);
|
||||
} else {
|
||||
blit_filtered(top_left, *glyph.bitmap(), glyph.bitmap()->rect(), [color](Color pixel) -> Color {
|
||||
blit_filtered(top_left.to_type<int>(), *glyph.bitmap(), glyph.bitmap()->rect(), [color](Color pixel) -> Color {
|
||||
return pixel.multiply(color);
|
||||
});
|
||||
}
|
||||
|
@ -1405,7 +1405,7 @@ void Painter::draw_emoji(IntPoint point, Gfx::Bitmap const& emoji, Font const& f
|
|||
draw_scaled_bitmap(dst_rect, emoji, emoji.rect());
|
||||
}
|
||||
|
||||
void Painter::draw_glyph_or_emoji(IntPoint point, u32 code_point, Font const& font, Color color)
|
||||
void Painter::draw_glyph_or_emoji(FloatPoint point, u32 code_point, Font const& font, Color color)
|
||||
{
|
||||
StringBuilder builder;
|
||||
builder.append_code_point(code_point);
|
||||
|
@ -1413,7 +1413,7 @@ void Painter::draw_glyph_or_emoji(IntPoint point, u32 code_point, Font const& fo
|
|||
return draw_glyph_or_emoji(point, it, font, color);
|
||||
}
|
||||
|
||||
void Painter::draw_glyph_or_emoji(IntPoint point, Utf8CodePointIterator& it, Font const& font, Color color)
|
||||
void Painter::draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font, Color color)
|
||||
{
|
||||
// FIXME: These should live somewhere else.
|
||||
constexpr u32 text_variation_selector = 0xFE0E;
|
||||
|
@ -1454,7 +1454,7 @@ void Painter::draw_glyph_or_emoji(IntPoint point, Utf8CodePointIterator& it, Fon
|
|||
|
||||
// If we didn't find a text glyph, or have an emoji variation selector or regional indicator, try to draw an emoji glyph.
|
||||
if (auto const* emoji = Emoji::emoji_for_code_point_iterator(it)) {
|
||||
draw_emoji(point, *emoji, font);
|
||||
draw_emoji(point.to_type<int>(), *emoji, font);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1469,8 +1469,28 @@ void Painter::draw_glyph_or_emoji(IntPoint point, Utf8CodePointIterator& it, Fon
|
|||
draw_glyph(point, 0xFFFD, font, color);
|
||||
}
|
||||
|
||||
void Painter::draw_glyph(IntPoint point, u32 code_point, Color color)
|
||||
{
|
||||
draw_glyph(point.to_type<float>(), code_point, font(), color);
|
||||
}
|
||||
|
||||
void Painter::draw_glyph(IntPoint point, u32 code_point, Font const& font, Color color)
|
||||
{
|
||||
draw_glyph(point.to_type<float>(), code_point, font, color);
|
||||
}
|
||||
|
||||
void Painter::draw_glyph_or_emoji(IntPoint point, u32 code_point, Font const& font, Color color)
|
||||
{
|
||||
draw_glyph_or_emoji(point.to_type<float>(), code_point, font, color);
|
||||
}
|
||||
|
||||
void Painter::draw_glyph_or_emoji(IntPoint point, Utf8CodePointIterator& it, Font const& font, Color color)
|
||||
{
|
||||
draw_glyph_or_emoji(point.to_type<float>(), it, font, color);
|
||||
}
|
||||
|
||||
template<typename DrawGlyphFunction>
|
||||
void draw_text_line(IntRect const& a_rect, Utf8View const& text, Font const& font, TextAlignment alignment, TextDirection direction, DrawGlyphFunction draw_glyph)
|
||||
void draw_text_line(FloatRect const& a_rect, Utf8View const& text, Font const& font, TextAlignment alignment, TextDirection direction, DrawGlyphFunction draw_glyph)
|
||||
{
|
||||
auto rect = a_rect;
|
||||
|
||||
|
@ -1498,12 +1518,12 @@ void draw_text_line(IntRect const& a_rect, Utf8View const& text, Font const& fon
|
|||
}
|
||||
|
||||
if (is_vertically_centered_text_alignment(alignment)) {
|
||||
int distance_from_baseline_to_bottom = (font.pixel_size() - 1) - font.baseline();
|
||||
auto distance_from_baseline_to_bottom = (font.pixel_size() - 1) - font.baseline();
|
||||
rect.translate_by(0, distance_from_baseline_to_bottom / 2);
|
||||
}
|
||||
|
||||
auto point = rect.location();
|
||||
int space_width = font.glyph_width(' ') + font.glyph_spacing();
|
||||
auto space_width = font.glyph_width(' ') + font.glyph_spacing();
|
||||
|
||||
if (direction == TextDirection::RTL) {
|
||||
point.translate_by(rect.width(), 0); // Start drawing from the end
|
||||
|
@ -1519,11 +1539,11 @@ void draw_text_line(IntRect const& a_rect, Utf8View const& text, Font const& fon
|
|||
continue;
|
||||
}
|
||||
|
||||
int kerning = round_to<int>(font.glyphs_horizontal_kerning(last_code_point, code_point));
|
||||
if (kerning != 0.f)
|
||||
auto kerning = font.glyphs_horizontal_kerning(last_code_point, code_point);
|
||||
if (kerning != 0.0f)
|
||||
point.translate_by(direction == TextDirection::LTR ? kerning : -kerning, 0);
|
||||
|
||||
IntSize glyph_size(font.glyph_or_emoji_width(code_point) + font.glyph_spacing(), font.pixel_size());
|
||||
FloatSize glyph_size(font.glyph_or_emoji_width(code_point) + font.glyph_spacing(), font.pixel_size());
|
||||
if (direction == TextDirection::RTL)
|
||||
point.translate_by(-glyph_size.width(), 0); // If we are drawing right to left, we have to move backwards before drawing the glyph
|
||||
draw_glyph({ point, glyph_size }, it);
|
||||
|
@ -1698,14 +1718,14 @@ bool Painter::text_contains_bidirectional_text(Utf8View const& text, TextDirecti
|
|||
}
|
||||
|
||||
template<typename DrawGlyphFunction>
|
||||
void Painter::do_draw_text(IntRect const& rect, Utf8View const& text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping, DrawGlyphFunction draw_glyph)
|
||||
void Painter::do_draw_text(FloatRect const& rect, Utf8View const& text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping, DrawGlyphFunction draw_glyph)
|
||||
{
|
||||
if (draw_text_get_length(text) == 0)
|
||||
return;
|
||||
|
||||
TextLayout layout(&font, text, rect);
|
||||
|
||||
int line_height = font.pixel_size() + LINE_SPACING;
|
||||
auto line_height = font.pixel_size() + LINE_SPACING;
|
||||
|
||||
auto lines = layout.lines(elision, wrapping, LINE_SPACING);
|
||||
auto bounding_rect = layout.bounding_rect(wrapping, LINE_SPACING);
|
||||
|
@ -1722,10 +1742,10 @@ void Painter::do_draw_text(IntRect const& rect, Utf8View const& text, Font const
|
|||
bounding_rect.set_location({ (rect.right() + 1) - bounding_rect.width(), rect.y() });
|
||||
break;
|
||||
case TextAlignment::CenterLeft:
|
||||
bounding_rect.set_location({ rect.x(), rect.center().y() - (bounding_rect.height() / 2) });
|
||||
bounding_rect.set_location({ rect.x(), rect.center().y() - int(bounding_rect.height() / 2) });
|
||||
break;
|
||||
case TextAlignment::CenterRight:
|
||||
bounding_rect.set_location({ (rect.right() + 1) - bounding_rect.width(), rect.center().y() - (bounding_rect.height() / 2) });
|
||||
bounding_rect.set_location({ (rect.right() + 1) - bounding_rect.width(), rect.center().y() - int(bounding_rect.height() / 2) });
|
||||
break;
|
||||
case TextAlignment::Center:
|
||||
bounding_rect.center_within(rect);
|
||||
|
@ -1749,7 +1769,7 @@ void Painter::do_draw_text(IntRect const& rect, Utf8View const& text, Font const
|
|||
for (size_t i = 0; i < lines.size(); ++i) {
|
||||
auto line = Utf8View { lines[i] };
|
||||
|
||||
IntRect line_rect { bounding_rect.x(), bounding_rect.y() + static_cast<int>(i) * line_height, bounding_rect.width(), line_height };
|
||||
FloatRect line_rect { bounding_rect.x(), bounding_rect.y() + i * line_height, bounding_rect.width(), line_height };
|
||||
line_rect.intersect(rect);
|
||||
|
||||
TextDirection line_direction = get_text_direction(line);
|
||||
|
@ -1779,67 +1799,102 @@ void Painter::do_draw_text(IntRect const& rect, Utf8View const& text, Font const
|
|||
}
|
||||
}
|
||||
|
||||
void Painter::draw_text(IntRect const& rect, StringView text, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
|
||||
void Painter::draw_text(FloatRect const& rect, StringView text, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
draw_text(rect, text, font(), alignment, color, elision, wrapping);
|
||||
}
|
||||
|
||||
void Painter::draw_text(FloatRect const& rect, Utf32View const& text, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
draw_text(rect, text, font(), alignment, color, elision, wrapping);
|
||||
}
|
||||
|
||||
void Painter::draw_text(FloatRect const& rect, StringView raw_text, Font const& font, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
Utf8View text { raw_text };
|
||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](FloatRect const& r, Utf8CodePointIterator& it) {
|
||||
draw_glyph_or_emoji(r.location(), it, font, color);
|
||||
});
|
||||
}
|
||||
|
||||
void Painter::draw_text(FloatRect const& rect, Utf32View const& raw_text, Font const& font, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
// FIXME: UTF-32 should eventually be completely removed, but for the time
|
||||
// being some places might depend on it, so we do some internal conversion.
|
||||
StringBuilder builder;
|
||||
builder.append(raw_text);
|
||||
auto text = Utf8View { builder.string_view() };
|
||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](FloatRect const& r, Utf8CodePointIterator& it) {
|
||||
draw_glyph_or_emoji(r.location(), it, font, color);
|
||||
});
|
||||
}
|
||||
|
||||
void Painter::draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)> draw_one_glyph, FloatRect const& rect, Utf8View const& text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
VERIFY(scale() == 1); // FIXME: Add scaling support.
|
||||
|
||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](FloatRect const& r, Utf8CodePointIterator& it) {
|
||||
draw_one_glyph(r, it);
|
||||
});
|
||||
}
|
||||
|
||||
void Painter::draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)> draw_one_glyph, FloatRect const& rect, StringView raw_text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
VERIFY(scale() == 1); // FIXME: Add scaling support.
|
||||
|
||||
Utf8View text { raw_text };
|
||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](FloatRect const& r, Utf8CodePointIterator& it) {
|
||||
draw_one_glyph(r, it);
|
||||
});
|
||||
}
|
||||
|
||||
void Painter::draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)> draw_one_glyph, FloatRect const& rect, Utf32View const& raw_text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
VERIFY(scale() == 1); // FIXME: Add scaling support.
|
||||
|
||||
// FIXME: UTF-32 should eventually be completely removed, but for the time
|
||||
// being some places might depend on it, so we do some internal conversion.
|
||||
StringBuilder builder;
|
||||
builder.append(raw_text);
|
||||
auto text = Utf8View { builder.string_view() };
|
||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](FloatRect const& r, Utf8CodePointIterator& it) {
|
||||
draw_one_glyph(r, it);
|
||||
});
|
||||
}
|
||||
|
||||
void Painter::draw_text(IntRect const& rect, StringView text, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
draw_text(rect.to_type<float>(), text, font(), alignment, color, elision, wrapping);
|
||||
}
|
||||
|
||||
void Painter::draw_text(IntRect const& rect, Utf32View const& text, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
draw_text(rect, text, font(), alignment, color, elision, wrapping);
|
||||
draw_text(rect.to_type<float>(), text, font(), alignment, color, elision, wrapping);
|
||||
}
|
||||
|
||||
void Painter::draw_text(IntRect const& rect, StringView raw_text, Font const& font, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
Utf8View text { raw_text };
|
||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](IntRect const& r, Utf8CodePointIterator& it) {
|
||||
draw_glyph_or_emoji(r.location(), it, font, color);
|
||||
});
|
||||
draw_text(rect.to_type<float>(), raw_text, font, alignment, color, elision, wrapping);
|
||||
}
|
||||
|
||||
void Painter::draw_text(IntRect const& rect, Utf32View const& raw_text, Font const& font, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
// FIXME: UTF-32 should eventually be completely removed, but for the time
|
||||
// being some places might depend on it, so we do some internal conversion.
|
||||
StringBuilder builder;
|
||||
builder.append(raw_text);
|
||||
auto text = Utf8View { builder.string_view() };
|
||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](IntRect const& r, Utf8CodePointIterator& it) {
|
||||
draw_glyph_or_emoji(r.location(), it, font, color);
|
||||
});
|
||||
return draw_text(rect.to_type<float>(), raw_text, font, alignment, color, elision, wrapping);
|
||||
}
|
||||
|
||||
void Painter::draw_text(Function<void(IntRect const&, Utf8CodePointIterator&)> draw_one_glyph, IntRect const& rect, Utf8View const& text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping)
|
||||
void Painter::draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)> draw_one_glyph, IntRect const& rect, Utf8View const& text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
VERIFY(scale() == 1); // FIXME: Add scaling support.
|
||||
|
||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](IntRect const& r, Utf8CodePointIterator& it) {
|
||||
draw_one_glyph(r, it);
|
||||
});
|
||||
return draw_text(move(draw_one_glyph), rect.to_type<float>(), text, font, alignment, elision, wrapping);
|
||||
}
|
||||
|
||||
void Painter::draw_text(Function<void(IntRect const&, Utf8CodePointIterator&)> draw_one_glyph, IntRect const& rect, StringView raw_text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping)
|
||||
void Painter::draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)> draw_one_glyph, IntRect const& rect, StringView raw_text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
VERIFY(scale() == 1); // FIXME: Add scaling support.
|
||||
|
||||
Utf8View text { raw_text };
|
||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](IntRect const& r, Utf8CodePointIterator& it) {
|
||||
draw_one_glyph(r, it);
|
||||
});
|
||||
return draw_text(move(draw_one_glyph), rect.to_type<float>(), raw_text, font, alignment, elision, wrapping);
|
||||
}
|
||||
|
||||
void Painter::draw_text(Function<void(IntRect const&, Utf8CodePointIterator&)> draw_one_glyph, IntRect const& rect, Utf32View const& raw_text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping)
|
||||
void Painter::draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)> draw_one_glyph, IntRect const& rect, Utf32View const& raw_text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping)
|
||||
{
|
||||
VERIFY(scale() == 1); // FIXME: Add scaling support.
|
||||
|
||||
// FIXME: UTF-32 should eventually be completely removed, but for the time
|
||||
// being some places might depend on it, so we do some internal conversion.
|
||||
StringBuilder builder;
|
||||
builder.append(raw_text);
|
||||
auto text = Utf8View { builder.string_view() };
|
||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](IntRect const& r, Utf8CodePointIterator& it) {
|
||||
draw_one_glyph(r, it);
|
||||
});
|
||||
return draw_text(move(draw_one_glyph), rect.to_type<float>(), raw_text, font, alignment, elision, wrapping);
|
||||
}
|
||||
|
||||
void Painter::set_pixel(IntPoint p, Color color, bool blend)
|
||||
|
@ -2481,7 +2536,7 @@ void Painter::draw_text_run(FloatPoint baseline_start, Utf8View const& string, F
|
|||
{
|
||||
auto pixel_metrics = font.pixel_metrics();
|
||||
float x = baseline_start.x();
|
||||
int y = baseline_start.y() - pixel_metrics.ascent;
|
||||
float y = baseline_start.y() - pixel_metrics.ascent;
|
||||
float space_width = font.glyph_or_emoji_width(' ');
|
||||
|
||||
u32 last_code_point = 0;
|
||||
|
@ -2496,7 +2551,7 @@ void Painter::draw_text_run(FloatPoint baseline_start, Utf8View const& string, F
|
|||
|
||||
// FIXME: this is probably not the real space taken for complex emojis
|
||||
x += font.glyphs_horizontal_kerning(last_code_point, code_point);
|
||||
draw_glyph_or_emoji({ static_cast<int>(x), y }, code_point_iterator, font, color);
|
||||
draw_glyph_or_emoji(FloatPoint { x, y }, code_point_iterator, font, color);
|
||||
x += font.glyph_or_emoji_width(code_point) + font.glyph_spacing();
|
||||
last_code_point = code_point;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue