mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:32:44 +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
	
	 MacDue
						MacDue