diff --git a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h index 01e75c707e8..309ed10e12f 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h +++ b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h @@ -53,6 +53,7 @@ public: bool is_atomic_inline() const; RefPtr glyph_run() const { return m_glyph_run; } + CSS::WritingMode writing_mode() const { return m_writing_mode; } void append_glyph_run(RefPtr const&, CSSPixels run_width); private: diff --git a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp index 341f30dc286..ba129b19bdd 100644 --- a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -31,7 +31,7 @@ static RefPtr compute_text_clip_paths(PaintContext& context, Painta DevicePixelPoint baseline_start { fragment_absolute_device_rect.x(), fragment_absolute_device_rect.y() + context.rounded_device_pixels(fragment.baseline()) }; auto scale = context.device_pixels_per_css_pixel(); - display_list_recorder.draw_text_run(baseline_start.to_type(), *glyph_run, Gfx::Color::Black, fragment_absolute_device_rect.to_type(), scale); + display_list_recorder.draw_text_run(baseline_start.to_type(), *glyph_run, Gfx::Color::Black, fragment_absolute_device_rect.to_type(), scale, fragment.orientation()); }; paintable.for_each_in_inclusive_subtree([&](auto& paintable) { diff --git a/Userland/Libraries/LibWeb/Painting/Command.h b/Userland/Libraries/LibWeb/Painting/Command.h index ac61071246a..48262a73506 100644 --- a/Userland/Libraries/LibWeb/Painting/Command.h +++ b/Userland/Libraries/LibWeb/Painting/Command.h @@ -42,6 +42,7 @@ struct DrawGlyphRun { Gfx::IntRect rect; Gfx::FloatPoint translation; double scale { 1 }; + Gfx::Orientation orientation { Gfx::Orientation::Horizontal }; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp index 33f2bd616b3..d72ce363604 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp @@ -474,7 +474,20 @@ void DisplayListPlayerSkia::draw_glyph_run(DrawGlyphRun const& command) SkPaint paint; paint.setColor(to_skia_color(command.color)); - surface().canvas().drawGlyphs(glyphs.size(), glyphs.data(), positions.data(), to_skia_point(command.translation), sk_font, paint); + + auto& canvas = surface().canvas(); + switch (command.orientation) { + case Gfx::Orientation::Horizontal: + canvas.drawGlyphs(glyphs.size(), glyphs.data(), positions.data(), to_skia_point(command.translation), sk_font, paint); + break; + case Gfx::Orientation::Vertical: + canvas.save(); + canvas.translate(command.rect.width(), 0); + canvas.rotate(90, command.rect.top_left().x(), command.rect.top_left().y()); + canvas.drawGlyphs(glyphs.size(), glyphs.data(), positions.data(), to_skia_point(command.translation), sk_font, paint); + canvas.restore(); + break; + } } void DisplayListPlayerSkia::fill_rect(FillRect const& command) diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp index 21c4a63d5c0..8967649a809 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp @@ -234,10 +234,10 @@ void DisplayListRecorder::draw_text(Gfx::IntRect const& rect, String raw_text, G } auto metrics = font.pixel_metrics(); float baseline_y = static_cast(rect.y()) + metrics.ascent + (static_cast(rect.height()) - (metrics.ascent + metrics.descent)) / 2.0f; - draw_text_run(Gfx::IntPoint(roundf(baseline_x), roundf(baseline_y)), *glyph_run, color, rect, 1.0); + draw_text_run(Gfx::IntPoint(roundf(baseline_x), roundf(baseline_y)), *glyph_run, color, rect, 1.0, Orientation::Horizontal); } -void DisplayListRecorder::draw_text_run(Gfx::IntPoint baseline_start, Gfx::GlyphRun const& glyph_run, Color color, Gfx::IntRect const& rect, double scale) +void DisplayListRecorder::draw_text_run(Gfx::IntPoint baseline_start, Gfx::GlyphRun const& glyph_run, Color color, Gfx::IntRect const& rect, double scale, Orientation orientation) { if (rect.is_empty()) return; @@ -247,6 +247,7 @@ void DisplayListRecorder::draw_text_run(Gfx::IntPoint baseline_start, Gfx::Glyph .rect = rect, .translation = baseline_start.to_type(), .scale = scale, + .orientation = orientation, }); } diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h index 1ee81221235..f5c363433d4 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h +++ b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h @@ -97,7 +97,7 @@ public: void draw_text(Gfx::IntRect const&, String, Gfx::Font const&, Gfx::TextAlignment, Color); // Streamlined text drawing routine that does no wrapping/elision/alignment. - void draw_text_run(Gfx::IntPoint baseline_start, Gfx::GlyphRun const& glyph_run, Color color, Gfx::IntRect const& rect, double scale); + void draw_text_run(Gfx::IntPoint baseline_start, Gfx::GlyphRun const& glyph_run, Color color, Gfx::IntRect const& rect, double scale, Gfx::Orientation); void add_clip_rect(Gfx::IntRect const& rect); diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index 2bdcdd11dfa..5e7337fb8a1 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -670,14 +670,14 @@ void paint_text_fragment(PaintContext& context, TextPaintable const& paintable, DevicePixelPoint baseline_start { fragment_absolute_device_rect.x(), fragment_absolute_device_rect.y() + context.rounded_device_pixels(fragment.baseline()) }; auto scale = context.device_pixels_per_css_pixel(); - painter.draw_text_run(baseline_start.to_type(), *glyph_run, paintable.computed_values().webkit_text_fill_color(), fragment_absolute_device_rect.to_type(), scale); + painter.draw_text_run(baseline_start.to_type(), *glyph_run, paintable.computed_values().webkit_text_fill_color(), fragment_absolute_device_rect.to_type(), scale, fragment.orientation()); auto selection_rect = context.enclosing_device_rect(fragment.selection_rect(paintable.layout_node().first_available_font())).to_type(); if (!selection_rect.is_empty()) { painter.fill_rect(selection_rect, CSS::SystemColor::highlight()); DisplayListRecorderStateSaver saver(painter); painter.add_clip_rect(selection_rect); - painter.draw_text_run(baseline_start.to_type(), *glyph_run, CSS::SystemColor::highlight_text(), fragment_absolute_device_rect.to_type(), scale); + painter.draw_text_run(baseline_start.to_type(), *glyph_run, CSS::SystemColor::highlight_text(), fragment_absolute_device_rect.to_type(), scale, fragment.orientation()); } paint_text_decoration(context, paintable, fragment); diff --git a/Userland/Libraries/LibWeb/Painting/PaintableFragment.cpp b/Userland/Libraries/LibWeb/Painting/PaintableFragment.cpp index 7f42b1299b8..ebb914c9750 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableFragment.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableFragment.cpp @@ -22,6 +22,7 @@ PaintableFragment::PaintableFragment(Layout::LineBoxFragment const& fragment) , m_start(fragment.start()) , m_length(fragment.length()) , m_glyph_run(fragment.glyph_run()) + , m_writing_mode(fragment.writing_mode()) { } @@ -129,6 +130,21 @@ CSSPixelRect PaintableFragment::range_rect(Gfx::Font const& font, size_t start_o return {}; } +Gfx::Orientation PaintableFragment::orientation() const +{ + switch (m_writing_mode) { + case CSS::WritingMode::HorizontalTb: + return Gfx::Orientation::Horizontal; + case CSS::WritingMode::VerticalRl: + case CSS::WritingMode::VerticalLr: + case CSS::WritingMode::SidewaysRl: + case CSS::WritingMode::SidewaysLr: + return Gfx::Orientation::Vertical; + default: + VERIFY_NOT_REACHED(); + } +} + CSSPixelRect PaintableFragment::selection_rect(Gfx::Font const& font) const { if (!paintable().is_selected()) diff --git a/Userland/Libraries/LibWeb/Painting/PaintableFragment.h b/Userland/Libraries/LibWeb/Painting/PaintableFragment.h index 80e2a60784f..7f5d31723cf 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableFragment.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableFragment.h @@ -44,6 +44,7 @@ public: CSSPixelRect const absolute_rect() const; RefPtr glyph_run() const { return m_glyph_run; } + Gfx::Orientation orientation() const; CSSPixelRect selection_rect(Gfx::Font const&) const; CSSPixelRect range_rect(Gfx::Font const&, size_t start_offset, size_t end_offset) const; @@ -64,6 +65,7 @@ private: int m_length; Painting::BorderRadiiData m_border_radii_data; RefPtr m_glyph_run; + CSS::WritingMode m_writing_mode; Vector m_shadows; ResolvedBackground m_resolved_background; };