mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 13:57: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
|
@ -170,7 +170,7 @@ private:
|
||||||
|
|
||||||
if (m_show_percent) {
|
if (m_show_percent) {
|
||||||
auto volume_text = m_audio_muted ? "mute" : DeprecatedString::formatted("{}%", m_audio_volume);
|
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();
|
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_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
|
// Vertical ruler
|
||||||
|
@ -234,7 +234,7 @@ void ImageEditor::paint_event(GUI::PaintEvent& event)
|
||||||
|
|
||||||
int const editor_y = content_to_frame_position({ 0, y }).y();
|
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_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
|
// 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_bitmap = text_bitmap_result.release_value();
|
||||||
auto text_painter = GUI::Painter(text_bitmap);
|
auto text_painter = GUI::Painter(text_bitmap);
|
||||||
text_painter.set_font(*m_selected_font);
|
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();
|
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();
|
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);
|
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();
|
return color.to_grayscale();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ void WelcomeWidget::paint_event(GUI::PaintEvent& event)
|
||||||
painter.add_clip_rect(event.rect());
|
painter.add_clip_rect(event.rect());
|
||||||
|
|
||||||
static auto font = Gfx::BitmapFont::load_from_file("/res/fonts/MarietaRegular24.font"sv);
|
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(Gfx::IntRect { 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(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({ 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 + 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({ 20, 260, 480, 320 }, Color::DarkGray);
|
||||||
|
|
||||||
painter.draw_rect({ 520, 260, 240, 80 }, 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(Gfx::IntRect { 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(Gfx::IntRect { 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(Gfx::IntRect { 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(Gfx::IntRect { 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(Gfx::IntRect { 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(Gfx::IntRect { 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 }, "BottomRight"sv, Gfx::TextAlignment::BottomRight, Color::White);
|
||||||
|
|
||||||
painter.draw_rect({ 520, 360, 240, 30 }, Color::DarkGray);
|
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_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(Gfx::IntRect { 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(Gfx::IntRect { 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(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({ 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, 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);
|
auto font = Gfx::BitmapFont::load_from_file("/res/fonts/PebbletonBold14.font"sv);
|
||||||
painter.draw_rect({ 520, 510, 240, 30 }, Color::DarkGray);
|
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({ 520, 560, 10, 20 }, Color::White);
|
||||||
painter.fill_rect({ 530, 560, 10, 20 }, Color::WarmGray);
|
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 };
|
Gfx::Painter painter { bitmap };
|
||||||
painter.clear_rect(bitmap.rect(), Gfx::Color::Transparent);
|
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();
|
return color.inverted();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -727,10 +727,10 @@ void AbstractView::draw_item_text(Gfx::Painter& painter, ModelIndex const& index
|
||||||
|
|
||||||
// Highlight the text background first
|
// Highlight the text background first
|
||||||
auto background_searching_length = searching_length;
|
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) {
|
if (background_searching_length > 0) {
|
||||||
background_searching_length--;
|
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);
|
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 text_searching_length = searching_length;
|
||||||
auto highlight_text_color = palette().highlight_searching_text();
|
auto highlight_text_color = palette().highlight_searching_text();
|
||||||
searching_length = searching_text.length();
|
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) {
|
if (text_searching_length > 0) {
|
||||||
text_searching_length--;
|
text_searching_length--;
|
||||||
painter.draw_glyph_or_emoji(rect.location(), it, font, highlight_text_color);
|
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
|
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
|
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);
|
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 glyph = font.glyph(code_point);
|
||||||
auto top_left = point + IntPoint(glyph.left_bearing(), 0);
|
auto top_left = point + IntPoint(glyph.left_bearing(), 0);
|
||||||
|
|
||||||
if (glyph.is_glyph_bitmap()) {
|
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 {
|
} 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);
|
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());
|
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;
|
StringBuilder builder;
|
||||||
builder.append_code_point(code_point);
|
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);
|
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.
|
// FIXME: These should live somewhere else.
|
||||||
constexpr u32 text_variation_selector = 0xFE0E;
|
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 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)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1469,8 +1469,28 @@ void Painter::draw_glyph_or_emoji(IntPoint point, Utf8CodePointIterator& it, Fon
|
||||||
draw_glyph(point, 0xFFFD, font, color);
|
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>
|
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;
|
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)) {
|
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);
|
rect.translate_by(0, distance_from_baseline_to_bottom / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto point = rect.location();
|
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) {
|
if (direction == TextDirection::RTL) {
|
||||||
point.translate_by(rect.width(), 0); // Start drawing from the end
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kerning = round_to<int>(font.glyphs_horizontal_kerning(last_code_point, code_point));
|
auto kerning = font.glyphs_horizontal_kerning(last_code_point, code_point);
|
||||||
if (kerning != 0.f)
|
if (kerning != 0.0f)
|
||||||
point.translate_by(direction == TextDirection::LTR ? kerning : -kerning, 0);
|
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)
|
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
|
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);
|
draw_glyph({ point, glyph_size }, it);
|
||||||
|
@ -1698,14 +1718,14 @@ bool Painter::text_contains_bidirectional_text(Utf8View const& text, TextDirecti
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename DrawGlyphFunction>
|
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)
|
if (draw_text_get_length(text) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TextLayout layout(&font, text, rect);
|
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 lines = layout.lines(elision, wrapping, LINE_SPACING);
|
||||||
auto bounding_rect = layout.bounding_rect(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() });
|
bounding_rect.set_location({ (rect.right() + 1) - bounding_rect.width(), rect.y() });
|
||||||
break;
|
break;
|
||||||
case TextAlignment::CenterLeft:
|
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;
|
break;
|
||||||
case TextAlignment::CenterRight:
|
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;
|
break;
|
||||||
case TextAlignment::Center:
|
case TextAlignment::Center:
|
||||||
bounding_rect.center_within(rect);
|
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) {
|
for (size_t i = 0; i < lines.size(); ++i) {
|
||||||
auto line = Utf8View { lines[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);
|
line_rect.intersect(rect);
|
||||||
|
|
||||||
TextDirection line_direction = get_text_direction(line);
|
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);
|
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)
|
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)
|
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 };
|
draw_text(rect.to_type<float>(), raw_text, font, alignment, color, elision, wrapping);
|
||||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](IntRect const& r, Utf8CodePointIterator& it) {
|
|
||||||
draw_glyph_or_emoji(r.location(), it, font, color);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Painter::draw_text(IntRect const& rect, Utf32View const& raw_text, Font const& font, TextAlignment alignment, Color color, TextElision elision, TextWrapping 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
|
return draw_text(rect.to_type<float>(), raw_text, font, alignment, color, elision, wrapping);
|
||||||
// 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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
return draw_text(move(draw_one_glyph), rect.to_type<float>(), text, font, alignment, elision, wrapping);
|
||||||
|
|
||||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](IntRect const& r, Utf8CodePointIterator& it) {
|
|
||||||
draw_one_glyph(r, it);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
return draw_text(move(draw_one_glyph), rect.to_type<float>(), raw_text, font, alignment, elision, wrapping);
|
||||||
|
|
||||||
Utf8View text { raw_text };
|
|
||||||
do_draw_text(rect, text, font, alignment, elision, wrapping, [&](IntRect const& r, Utf8CodePointIterator& it) {
|
|
||||||
draw_one_glyph(r, it);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
return draw_text(move(draw_one_glyph), rect.to_type<float>(), raw_text, font, alignment, elision, 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_one_glyph(r, it);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Painter::set_pixel(IntPoint p, Color color, bool blend)
|
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();
|
auto pixel_metrics = font.pixel_metrics();
|
||||||
float x = baseline_start.x();
|
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(' ');
|
float space_width = font.glyph_or_emoji_width(' ');
|
||||||
|
|
||||||
u32 last_code_point = 0;
|
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
|
// FIXME: this is probably not the real space taken for complex emojis
|
||||||
x += font.glyphs_horizontal_kerning(last_code_point, code_point);
|
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();
|
x += font.glyph_or_emoji_width(code_point) + font.glyph_spacing();
|
||||||
last_code_point = code_point;
|
last_code_point = code_point;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,19 +81,30 @@ public:
|
||||||
void blit_offset(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, IntPoint);
|
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_disabled(IntPoint, Gfx::Bitmap const&, IntRect const&, Palette const&);
|
||||||
void blit_tiled(IntRect const&, Gfx::Bitmap const&, IntRect const& src_rect);
|
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, 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&, 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&, 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(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(FloatRect 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(FloatRect 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&, 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_ui_text(Gfx::IntRect const&, StringView, Gfx::Font const&, TextAlignment, Gfx::Color);
|
||||||
void draw_glyph(IntPoint, u32, Color);
|
void draw_glyph(IntPoint, u32, Color);
|
||||||
void draw_glyph(IntPoint, u32, Font const&, Color);
|
void draw_glyph(IntPoint, u32, Font const&, Color);
|
||||||
void draw_emoji(IntPoint, Gfx::Bitmap const&, Font const&);
|
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, u32, Font const&, Color);
|
||||||
void draw_glyph_or_emoji(IntPoint, Utf8CodePointIterator&, 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);
|
void draw_circle_arc_intersecting(IntRect const&, IntPoint, int radius, Color, int thickness);
|
||||||
|
|
||||||
// Streamlined text drawing routine that does no wrapping/elision/alignment.
|
// 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);
|
Vector<DirectionalRun> split_text_into_directional_runs(Utf8View const&, TextDirection initial_direction);
|
||||||
bool text_contains_bidirectional_text(Utf8View const&, TextDirection);
|
bool text_contains_bidirectional_text(Utf8View const&, TextDirection);
|
||||||
template<typename DrawGlyphFunction>
|
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 {
|
class PainterStateSaver {
|
||||||
|
|
|
@ -20,15 +20,15 @@ struct Block {
|
||||||
Utf8View characters;
|
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);
|
auto lines = wrap_lines(TextElision::None, wrapping, line_spacing, FitWithinRect::No);
|
||||||
if (!lines.size()) {
|
if (!lines.size()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
IntRect bounding_rect = {
|
FloatRect bounding_rect = {
|
||||||
0, 0, 0, static_cast<int>((lines.size() * (m_font->pixel_size() + line_spacing)) - line_spacing)
|
0, 0, 0, (lines.size() * (m_font->pixel_size() + line_spacing)) - line_spacing
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto& line : lines) {
|
for (auto& line : lines) {
|
||||||
|
@ -119,7 +119,7 @@ Vector<DeprecatedString, 32> TextLayout::wrap_lines(TextElision elision, TextWra
|
||||||
|
|
||||||
Vector<DeprecatedString> lines;
|
Vector<DeprecatedString> lines;
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
size_t line_width = 0;
|
float line_width = 0;
|
||||||
size_t current_block = 0;
|
size_t current_block = 0;
|
||||||
bool did_not_finish = false;
|
bool did_not_finish = false;
|
||||||
for (Block& block : blocks) {
|
for (Block& block : blocks) {
|
||||||
|
@ -139,14 +139,14 @@ Vector<DeprecatedString, 32> TextLayout::wrap_lines(TextElision elision, TextWra
|
||||||
}
|
}
|
||||||
case BlockType::Whitespace:
|
case BlockType::Whitespace:
|
||||||
case BlockType::Word: {
|
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
|
// FIXME: This should look at the specific advance amount of the
|
||||||
// last character, but we don't support that yet.
|
// last character, but we don't support that yet.
|
||||||
if (current_block != blocks.size() - 1) {
|
if (current_block != blocks.size() - 1) {
|
||||||
block_width += font().glyph_spacing();
|
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());
|
lines.append(builder.to_deprecated_string());
|
||||||
builder.clear();
|
builder.clear();
|
||||||
line_width = 0;
|
line_width = 0;
|
||||||
|
@ -185,10 +185,10 @@ blocks_processed:
|
||||||
|
|
||||||
DeprecatedString TextLayout::elide_text_from_right(Utf8View text, bool force_elision) const
|
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())) {
|
if (force_elision || text_width > static_cast<unsigned>(m_rect.width())) {
|
||||||
size_t ellipsis_width = m_font->width("..."sv);
|
float ellipsis_width = m_font->width("..."sv);
|
||||||
size_t current_width = ellipsis_width;
|
float current_width = ellipsis_width;
|
||||||
size_t glyph_spacing = m_font->glyph_spacing();
|
size_t glyph_spacing = m_font->glyph_spacing();
|
||||||
|
|
||||||
// FIXME: This code will break when the font has glyphs with advance
|
// 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;
|
size_t offset = 0;
|
||||||
for (auto it = text.begin(); !it.done(); ++it) {
|
for (auto it = text.begin(); !it.done(); ++it) {
|
||||||
auto code_point = *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,
|
// 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,
|
// but since we are here because the last glyph does not actually fit on the line,
|
||||||
// we don't have to worry about spacing.
|
// 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())
|
if (width_with_this_glyph_included > m_rect.width())
|
||||||
break;
|
break;
|
||||||
current_width += glyph_width + glyph_spacing;
|
current_width += glyph_width + glyph_spacing;
|
||||||
|
|
|
@ -44,7 +44,7 @@ enum class FitWithinRect {
|
||||||
// b) Taking the Lines from TextLayout and painting each glyph.
|
// b) Taking the Lines from TextLayout and painting each glyph.
|
||||||
class TextLayout {
|
class TextLayout {
|
||||||
public:
|
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_font(font)
|
||||||
, m_text(text)
|
, m_text(text)
|
||||||
, m_rect(rect)
|
, m_rect(rect)
|
||||||
|
@ -57,15 +57,15 @@ public:
|
||||||
Utf8View const& text() const { return m_text; }
|
Utf8View const& text() const { return m_text; }
|
||||||
void set_text(Utf8View const& text) { m_text = text; }
|
void set_text(Utf8View const& text) { m_text = text; }
|
||||||
|
|
||||||
IntRect const& rect() const { return m_rect; }
|
FloatRect const& rect() const { return m_rect; }
|
||||||
void set_rect(IntRect const& rect) { m_rect = rect; }
|
void set_rect(FloatRect const& rect) { m_rect = rect; }
|
||||||
|
|
||||||
Vector<DeprecatedString, 32> lines(TextElision elision, TextWrapping wrapping, int line_spacing) const
|
Vector<DeprecatedString, 32> lines(TextElision elision, TextWrapping wrapping, int line_spacing) const
|
||||||
{
|
{
|
||||||
return wrap_lines(elision, wrapping, line_spacing, FitWithinRect::Yes);
|
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:
|
private:
|
||||||
Vector<DeprecatedString, 32> wrap_lines(TextElision, TextWrapping, int line_spacing, FitWithinRect) const;
|
Vector<DeprecatedString, 32> wrap_lines(TextElision, TextWrapping, int line_spacing, FitWithinRect) const;
|
||||||
|
@ -73,7 +73,7 @@ private:
|
||||||
|
|
||||||
Font const* m_font;
|
Font const* m_font;
|
||||||
Utf8View m_text;
|
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)
|
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)
|
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)
|
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()
|
void WindowGeometryOverlay::window_rect_changed()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue