mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 13:37:43 +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
|
@ -170,7 +170,7 @@ private:
|
|||
|
||||
if (m_show_percent) {
|
||||
auto volume_text = m_audio_muted ? "mute" : DeprecatedString::formatted("{}%", m_audio_volume);
|
||||
painter.draw_text({ 16, 3, 24, 16 }, volume_text, Gfx::FontDatabase::default_fixed_width_font(), Gfx::TextAlignment::TopLeft, palette().window_text());
|
||||
painter.draw_text(Gfx::IntRect { 16, 3, 24, 16 }, volume_text, Gfx::FontDatabase::default_fixed_width_font(), Gfx::TextAlignment::TopLeft, palette().window_text());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ void ImageEditor::paint_event(GUI::PaintEvent& event)
|
|||
|
||||
int const editor_x = content_to_frame_position({ x, 0 }).x();
|
||||
painter.draw_line({ editor_x, 0 }, { editor_x, m_ruler_thickness }, ruler_fg_color);
|
||||
painter.draw_text({ { editor_x + 2, 0 }, { m_ruler_thickness, m_ruler_thickness - 2 } }, DeprecatedString::formatted("{}", x), painter.font(), Gfx::TextAlignment::CenterLeft, ruler_text_color);
|
||||
painter.draw_text(Gfx::IntRect { { editor_x + 2, 0 }, { m_ruler_thickness, m_ruler_thickness - 2 } }, DeprecatedString::formatted("{}", x), painter.font(), Gfx::TextAlignment::CenterLeft, ruler_text_color);
|
||||
}
|
||||
|
||||
// Vertical ruler
|
||||
|
@ -234,7 +234,7 @@ void ImageEditor::paint_event(GUI::PaintEvent& event)
|
|||
|
||||
int const editor_y = content_to_frame_position({ 0, y }).y();
|
||||
painter.draw_line({ 0, editor_y }, { m_ruler_thickness, editor_y }, ruler_fg_color);
|
||||
painter.draw_text({ { 0, editor_y - m_ruler_thickness }, { m_ruler_thickness, m_ruler_thickness } }, DeprecatedString::formatted("{}", y), painter.font(), Gfx::TextAlignment::BottomRight, ruler_text_color);
|
||||
painter.draw_text(Gfx::IntRect { { 0, editor_y - m_ruler_thickness }, { m_ruler_thickness, m_ruler_thickness } }, DeprecatedString::formatted("{}", y), painter.font(), Gfx::TextAlignment::BottomRight, ruler_text_color);
|
||||
}
|
||||
|
||||
// Mouse position indicator
|
||||
|
|
|
@ -142,7 +142,7 @@ void TextTool::on_second_paint(Layer const* layer, GUI::PaintEvent& event)
|
|||
auto text_bitmap = text_bitmap_result.release_value();
|
||||
auto text_painter = GUI::Painter(text_bitmap);
|
||||
text_painter.set_font(*m_selected_font);
|
||||
text_painter.draw_text({ 0, 0, text_width, text_height }, typed_text, Gfx::TextAlignment::TopLeft, m_text_color);
|
||||
text_painter.draw_text(Gfx::IntRect { 0, 0, text_width, text_height }, typed_text, Gfx::TextAlignment::TopLeft, m_text_color);
|
||||
|
||||
m_text_editor->update();
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ NetworkStatisticsWidget::NetworkStatisticsWidget()
|
|||
m_network_link_down_bitmap = Gfx::Bitmap::try_create(m_network_connected_bitmap->format(), m_network_connected_bitmap->size()).release_value_but_fixme_should_propagate_errors();
|
||||
{
|
||||
Gfx::Painter painter(*m_network_link_down_bitmap);
|
||||
painter.blit_filtered({}, *m_network_connected_bitmap, m_network_connected_bitmap->rect(), [](Color color) {
|
||||
painter.blit_filtered(Gfx::IntPoint {}, *m_network_connected_bitmap, m_network_connected_bitmap->rect(), [](Color color) {
|
||||
return color.to_grayscale();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ void WelcomeWidget::paint_event(GUI::PaintEvent& event)
|
|||
painter.add_clip_rect(event.rect());
|
||||
|
||||
static auto font = Gfx::BitmapFont::load_from_file("/res/fonts/MarietaRegular24.font"sv);
|
||||
painter.draw_text({ 12, 4, 1, 30 }, "Welcome to "sv, *font, Gfx::TextAlignment::CenterLeft, palette().base_text());
|
||||
painter.draw_text({ 12 + static_cast<int>(ceilf(font->width("Welcome to "sv))), 4, 1, 30 }, "Serenity"sv, font->bold_variant(), Gfx::TextAlignment::CenterLeft, palette().base_text());
|
||||
painter.draw_text({ 12 + static_cast<int>(ceilf(font->width("Welcome to "sv))) + static_cast<int>(ceilf(font->bold_variant().width("Serenity"sv))), 4, 1, 30 }, "OS"sv, font->bold_variant(), Gfx::TextAlignment::CenterLeft, palette().base() == palette().window() ? palette().base_text() : palette().base());
|
||||
painter.draw_text(Gfx::IntRect { 12, 4, 1, 30 }, "Welcome to "sv, *font, Gfx::TextAlignment::CenterLeft, palette().base_text());
|
||||
painter.draw_text(Gfx::IntRect { 12 + static_cast<int>(ceilf(font->width("Welcome to "sv))), 4, 1, 30 }, "Serenity"sv, font->bold_variant(), Gfx::TextAlignment::CenterLeft, palette().base_text());
|
||||
painter.draw_text(Gfx::IntRect { 12 + static_cast<int>(ceilf(font->width("Welcome to "sv))) + static_cast<int>(ceilf(font->bold_variant().width("Serenity"sv))), 4, 1, 30 }, "OS"sv, font->bold_variant(), Gfx::TextAlignment::CenterLeft, palette().base() == palette().window() ? palette().base_text() : palette().base());
|
||||
}
|
||||
|
|
|
@ -135,26 +135,26 @@ void Canvas::draw()
|
|||
painter.draw_rect({ 20, 260, 480, 320 }, Color::DarkGray);
|
||||
|
||||
painter.draw_rect({ 520, 260, 240, 80 }, Color::DarkGray);
|
||||
painter.draw_text({ 520, 260, 240, 80 }, "CenterLeft"sv, Gfx::TextAlignment::CenterLeft, Color::White);
|
||||
painter.draw_text({ 520, 260, 240, 80 }, "Center"sv, Gfx::TextAlignment::Center, Color::White);
|
||||
painter.draw_text({ 520, 260, 240, 80 }, "CenterRight"sv, Gfx::TextAlignment::CenterRight, Color::White);
|
||||
painter.draw_text({ 520, 260, 240, 80 }, "TopLeft"sv, Gfx::TextAlignment::TopLeft, Color::White);
|
||||
painter.draw_text({ 520, 260, 240, 80 }, "TopRight"sv, Gfx::TextAlignment::TopRight, Color::White);
|
||||
painter.draw_text({ 520, 260, 240, 80 }, "BottomLeft"sv, Gfx::TextAlignment::BottomLeft, Color::White);
|
||||
painter.draw_text({ 520, 260, 240, 80 }, "BottomRight"sv, Gfx::TextAlignment::BottomRight, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { 520, 260, 240, 80 }, "CenterLeft"sv, Gfx::TextAlignment::CenterLeft, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { 520, 260, 240, 80 }, "Center"sv, Gfx::TextAlignment::Center, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { 520, 260, 240, 80 }, "CenterRight"sv, Gfx::TextAlignment::CenterRight, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { 520, 260, 240, 80 }, "TopLeft"sv, Gfx::TextAlignment::TopLeft, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { 520, 260, 240, 80 }, "TopRight"sv, Gfx::TextAlignment::TopRight, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { 520, 260, 240, 80 }, "BottomLeft"sv, Gfx::TextAlignment::BottomLeft, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { 520, 260, 240, 80 }, "BottomRight"sv, Gfx::TextAlignment::BottomRight, Color::White);
|
||||
|
||||
painter.draw_rect({ 520, 360, 240, 30 }, Color::DarkGray);
|
||||
painter.draw_text({ 520, 360, 240, 30 }, "Emojis! 🙂😂🐞🦄"sv, Gfx::TextAlignment::Center, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { 520, 360, 240, 30 }, "Emojis! 🙂😂🐞🦄"sv, Gfx::TextAlignment::Center, Color::White);
|
||||
|
||||
painter.draw_rect({ 520, 410, 240, 80 }, Color::DarkGray);
|
||||
painter.draw_text({ 520, 415, 240, 20 }, "Normal text"sv, Gfx::FontDatabase::default_font(), Gfx::TextAlignment::CenterLeft, Color::Red);
|
||||
painter.draw_text({ 520, 430, 240, 20 }, "Bold text"sv, Gfx::FontDatabase::default_font().bold_variant(), Gfx::TextAlignment::CenterLeft, Color::Green);
|
||||
painter.draw_text({ 520, 450, 240, 20 }, "Normal text (fixed width)"sv, Gfx::FontDatabase::default_fixed_width_font(), Gfx::TextAlignment::CenterLeft, Color::Blue);
|
||||
painter.draw_text({ 520, 465, 240, 20 }, "Bold text (fixed width)"sv, Gfx::FontDatabase::default_fixed_width_font().bold_variant(), Gfx::TextAlignment::CenterLeft, Color::Yellow);
|
||||
painter.draw_text(Gfx::IntRect { 520, 415, 240, 20 }, "Normal text"sv, Gfx::FontDatabase::default_font(), Gfx::TextAlignment::CenterLeft, Color::Red);
|
||||
painter.draw_text(Gfx::IntRect { 520, 430, 240, 20 }, "Bold text"sv, Gfx::FontDatabase::default_font().bold_variant(), Gfx::TextAlignment::CenterLeft, Color::Green);
|
||||
painter.draw_text(Gfx::IntRect { 520, 450, 240, 20 }, "Normal text (fixed width)"sv, Gfx::FontDatabase::default_fixed_width_font(), Gfx::TextAlignment::CenterLeft, Color::Blue);
|
||||
painter.draw_text(Gfx::IntRect { 520, 465, 240, 20 }, "Bold text (fixed width)"sv, Gfx::FontDatabase::default_fixed_width_font().bold_variant(), Gfx::TextAlignment::CenterLeft, Color::Yellow);
|
||||
|
||||
auto font = Gfx::BitmapFont::load_from_file("/res/fonts/PebbletonBold14.font"sv);
|
||||
painter.draw_rect({ 520, 510, 240, 30 }, Color::DarkGray);
|
||||
painter.draw_text({ 520, 510, 240, 30 }, "Hello friends! :^)"sv, *font, Gfx::TextAlignment::Center, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { 520, 510, 240, 30 }, "Hello friends! :^)"sv, *font, Gfx::TextAlignment::Center, Color::White);
|
||||
|
||||
painter.fill_rect({ 520, 560, 10, 20 }, Color::White);
|
||||
painter.fill_rect({ 530, 560, 10, 20 }, Color::WarmGray);
|
||||
|
|
|
@ -207,7 +207,7 @@ void CardPainter::paint_inverted_card(Gfx::Bitmap& bitmap, Gfx::Bitmap const& so
|
|||
{
|
||||
Gfx::Painter painter { bitmap };
|
||||
painter.clear_rect(bitmap.rect(), Gfx::Color::Transparent);
|
||||
painter.blit_filtered({ 0, 0 }, source_to_invert, source_to_invert.rect(), [&](Color color) {
|
||||
painter.blit_filtered(Gfx::IntPoint {}, source_to_invert, source_to_invert.rect(), [&](Color color) {
|
||||
return color.inverted();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -727,10 +727,10 @@ void AbstractView::draw_item_text(Gfx::Painter& painter, ModelIndex const& index
|
|||
|
||||
// Highlight the text background first
|
||||
auto background_searching_length = searching_length;
|
||||
painter.draw_text([&](Gfx::IntRect const& rect, Utf8CodePointIterator&) {
|
||||
painter.draw_text([&](Gfx::FloatRect const& rect, Utf8CodePointIterator&) {
|
||||
if (background_searching_length > 0) {
|
||||
background_searching_length--;
|
||||
painter.fill_rect(rect.inflated(0, 2), palette().highlight_searching());
|
||||
painter.fill_rect(rect.to_type<int>().inflated(0, 2), palette().highlight_searching());
|
||||
}
|
||||
},
|
||||
text_rect, item_text, font, alignment, elision);
|
||||
|
@ -739,7 +739,7 @@ void AbstractView::draw_item_text(Gfx::Painter& painter, ModelIndex const& index
|
|||
auto text_searching_length = searching_length;
|
||||
auto highlight_text_color = palette().highlight_searching_text();
|
||||
searching_length = searching_text.length();
|
||||
painter.draw_text([&](Gfx::IntRect const& rect, Utf8CodePointIterator& it) {
|
||||
painter.draw_text([&](auto const& rect, Utf8CodePointIterator& it) {
|
||||
if (text_searching_length > 0) {
|
||||
text_searching_length--;
|
||||
painter.draw_glyph_or_emoji(rect.location(), it, font, highlight_text_color);
|
||||
|
|
|
@ -117,7 +117,7 @@ void Label::size_to_fit()
|
|||
|
||||
int Label::text_calculated_preferred_height() const
|
||||
{
|
||||
return Gfx::TextLayout(&font(), Utf8View { m_text }, text_rect()).bounding_rect(Gfx::TextWrapping::Wrap, Gfx::Painter::LINE_SPACING).height();
|
||||
return int(AK::ceil(Gfx::TextLayout(&font(), Utf8View { m_text }, text_rect().to_type<float>()).bounding_rect(Gfx::TextWrapping::Wrap, Gfx::Painter::LINE_SPACING).height()));
|
||||
}
|
||||
|
||||
Optional<UISize> Label::calculated_preferred_size() const
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -81,19 +81,30 @@ public:
|
|||
void blit_offset(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, IntPoint);
|
||||
void blit_disabled(IntPoint, Gfx::Bitmap const&, IntRect const&, Palette const&);
|
||||
void blit_tiled(IntRect const&, Gfx::Bitmap const&, IntRect const& src_rect);
|
||||
void draw_text(FloatRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(FloatRect const&, StringView, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(FloatRect const&, Utf32View const&, Font const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(FloatRect const&, Utf32View const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, FloatRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, FloatRect const&, Utf8View const&, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, FloatRect const&, Utf32View const&, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(IntRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(IntRect const&, StringView, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(IntRect const&, Utf32View const&, Font const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(IntRect const&, Utf32View const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(Function<void(IntRect const&, Utf8CodePointIterator&)>, IntRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(Function<void(IntRect const&, Utf8CodePointIterator&)>, IntRect const&, Utf8View const&, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(Function<void(IntRect const&, Utf8CodePointIterator&)>, IntRect const&, Utf32View const&, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, IntRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, IntRect const&, Utf8View const&, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, IntRect const&, Utf32View const&, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
|
||||
void draw_ui_text(Gfx::IntRect const&, StringView, Gfx::Font const&, TextAlignment, Gfx::Color);
|
||||
void draw_glyph(IntPoint, u32, Color);
|
||||
void draw_glyph(IntPoint, u32, Font const&, Color);
|
||||
void draw_emoji(IntPoint, Gfx::Bitmap const&, Font const&);
|
||||
void draw_glyph_or_emoji(IntPoint, u32, Font const&, Color);
|
||||
void draw_glyph_or_emoji(IntPoint, Utf8CodePointIterator&, Font const&, Color);
|
||||
void draw_glyph(FloatPoint, u32, Color);
|
||||
void draw_glyph(FloatPoint, u32, Font const&, Color);
|
||||
void draw_glyph_or_emoji(FloatPoint, u32, Font const&, Color);
|
||||
void draw_glyph_or_emoji(FloatPoint, Utf8CodePointIterator&, Font const&, Color);
|
||||
void draw_circle_arc_intersecting(IntRect const&, IntPoint, int radius, Color, int thickness);
|
||||
|
||||
// Streamlined text drawing routine that does no wrapping/elision/alignment.
|
||||
|
@ -214,7 +225,7 @@ private:
|
|||
Vector<DirectionalRun> split_text_into_directional_runs(Utf8View const&, TextDirection initial_direction);
|
||||
bool text_contains_bidirectional_text(Utf8View const&, TextDirection);
|
||||
template<typename DrawGlyphFunction>
|
||||
void do_draw_text(IntRect const&, Utf8View const& text, Font const&, TextAlignment, TextElision, TextWrapping, DrawGlyphFunction);
|
||||
void do_draw_text(FloatRect const&, Utf8View const& text, Font const&, TextAlignment, TextElision, TextWrapping, DrawGlyphFunction);
|
||||
};
|
||||
|
||||
class PainterStateSaver {
|
||||
|
|
|
@ -20,15 +20,15 @@ struct Block {
|
|||
Utf8View characters;
|
||||
};
|
||||
|
||||
IntRect TextLayout::bounding_rect(TextWrapping wrapping, int line_spacing) const
|
||||
FloatRect TextLayout::bounding_rect(TextWrapping wrapping, int line_spacing) const
|
||||
{
|
||||
auto lines = wrap_lines(TextElision::None, wrapping, line_spacing, FitWithinRect::No);
|
||||
if (!lines.size()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
IntRect bounding_rect = {
|
||||
0, 0, 0, static_cast<int>((lines.size() * (m_font->pixel_size() + line_spacing)) - line_spacing)
|
||||
FloatRect bounding_rect = {
|
||||
0, 0, 0, (lines.size() * (m_font->pixel_size() + line_spacing)) - line_spacing
|
||||
};
|
||||
|
||||
for (auto& line : lines) {
|
||||
|
@ -119,7 +119,7 @@ Vector<DeprecatedString, 32> TextLayout::wrap_lines(TextElision elision, TextWra
|
|||
|
||||
Vector<DeprecatedString> lines;
|
||||
StringBuilder builder;
|
||||
size_t line_width = 0;
|
||||
float line_width = 0;
|
||||
size_t current_block = 0;
|
||||
bool did_not_finish = false;
|
||||
for (Block& block : blocks) {
|
||||
|
@ -139,14 +139,14 @@ Vector<DeprecatedString, 32> TextLayout::wrap_lines(TextElision elision, TextWra
|
|||
}
|
||||
case BlockType::Whitespace:
|
||||
case BlockType::Word: {
|
||||
size_t block_width = font().width(block.characters);
|
||||
float block_width = font().width(block.characters);
|
||||
// FIXME: This should look at the specific advance amount of the
|
||||
// last character, but we don't support that yet.
|
||||
if (current_block != blocks.size() - 1) {
|
||||
block_width += font().glyph_spacing();
|
||||
}
|
||||
|
||||
if (wrapping == TextWrapping::Wrap && line_width + block_width > static_cast<unsigned>(m_rect.width())) {
|
||||
if (wrapping == TextWrapping::Wrap && line_width + block_width > m_rect.width()) {
|
||||
lines.append(builder.to_deprecated_string());
|
||||
builder.clear();
|
||||
line_width = 0;
|
||||
|
@ -185,10 +185,10 @@ blocks_processed:
|
|||
|
||||
DeprecatedString TextLayout::elide_text_from_right(Utf8View text, bool force_elision) const
|
||||
{
|
||||
size_t text_width = m_font->width(text);
|
||||
float text_width = m_font->width(text);
|
||||
if (force_elision || text_width > static_cast<unsigned>(m_rect.width())) {
|
||||
size_t ellipsis_width = m_font->width("..."sv);
|
||||
size_t current_width = ellipsis_width;
|
||||
float ellipsis_width = m_font->width("..."sv);
|
||||
float current_width = ellipsis_width;
|
||||
size_t glyph_spacing = m_font->glyph_spacing();
|
||||
|
||||
// FIXME: This code will break when the font has glyphs with advance
|
||||
|
@ -198,11 +198,11 @@ DeprecatedString TextLayout::elide_text_from_right(Utf8View text, bool force_eli
|
|||
size_t offset = 0;
|
||||
for (auto it = text.begin(); !it.done(); ++it) {
|
||||
auto code_point = *it;
|
||||
int glyph_width = m_font->glyph_or_emoji_width(code_point);
|
||||
auto glyph_width = m_font->glyph_or_emoji_width(code_point);
|
||||
// NOTE: Glyph spacing should not be added after the last glyph on the line,
|
||||
// but since we are here because the last glyph does not actually fit on the line,
|
||||
// we don't have to worry about spacing.
|
||||
int width_with_this_glyph_included = current_width + glyph_width + glyph_spacing;
|
||||
auto width_with_this_glyph_included = current_width + glyph_width + glyph_spacing;
|
||||
if (width_with_this_glyph_included > m_rect.width())
|
||||
break;
|
||||
current_width += glyph_width + glyph_spacing;
|
||||
|
|
|
@ -44,7 +44,7 @@ enum class FitWithinRect {
|
|||
// b) Taking the Lines from TextLayout and painting each glyph.
|
||||
class TextLayout {
|
||||
public:
|
||||
TextLayout(Gfx::Font const* font, Utf8View const& text, IntRect const& rect)
|
||||
TextLayout(Gfx::Font const* font, Utf8View const& text, FloatRect const& rect)
|
||||
: m_font(font)
|
||||
, m_text(text)
|
||||
, m_rect(rect)
|
||||
|
@ -57,15 +57,15 @@ public:
|
|||
Utf8View const& text() const { return m_text; }
|
||||
void set_text(Utf8View const& text) { m_text = text; }
|
||||
|
||||
IntRect const& rect() const { return m_rect; }
|
||||
void set_rect(IntRect const& rect) { m_rect = rect; }
|
||||
FloatRect const& rect() const { return m_rect; }
|
||||
void set_rect(FloatRect const& rect) { m_rect = rect; }
|
||||
|
||||
Vector<DeprecatedString, 32> lines(TextElision elision, TextWrapping wrapping, int line_spacing) const
|
||||
{
|
||||
return wrap_lines(elision, wrapping, line_spacing, FitWithinRect::Yes);
|
||||
}
|
||||
|
||||
IntRect bounding_rect(TextWrapping wrapping, int line_spacing) const;
|
||||
FloatRect bounding_rect(TextWrapping wrapping, int line_spacing) const;
|
||||
|
||||
private:
|
||||
Vector<DeprecatedString, 32> wrap_lines(TextElision, TextWrapping, int line_spacing, FitWithinRect) const;
|
||||
|
@ -73,7 +73,7 @@ private:
|
|||
|
||||
Font const* m_font;
|
||||
Utf8View m_text;
|
||||
IntRect m_rect;
|
||||
FloatRect m_rect;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ Gfx::Font const& ScreenNumberOverlay::font()
|
|||
|
||||
void ScreenNumberOverlay::render_overlay_bitmap(Gfx::Painter& painter)
|
||||
{
|
||||
painter.draw_text({ {}, rect().size() }, DeprecatedString::formatted("{}", m_screen.index() + 1), font(), Gfx::TextAlignment::Center, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { {}, rect().size() }, DeprecatedString::formatted("{}", m_screen.index() + 1), font(), Gfx::TextAlignment::Center, Color::White);
|
||||
}
|
||||
|
||||
Gfx::IntRect ScreenNumberOverlay::calculate_content_rect_for_screen(Screen& screen)
|
||||
|
@ -264,7 +264,7 @@ void WindowGeometryOverlay::update_rect()
|
|||
|
||||
void WindowGeometryOverlay::render_overlay_bitmap(Gfx::Painter& painter)
|
||||
{
|
||||
painter.draw_text({ {}, rect().size() }, m_label, WindowManager::the().font(), Gfx::TextAlignment::Center, Color::White);
|
||||
painter.draw_text(Gfx::IntRect { {}, rect().size() }, m_label, WindowManager::the().font(), Gfx::TextAlignment::Center, Color::White);
|
||||
}
|
||||
|
||||
void WindowGeometryOverlay::window_rect_changed()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue