mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-03 14:50:02 +00:00
LibWeb: Draw text vertically, for fragments with vertical writing-mode
For fragments with a vertical `writing-mode`. Rotate the text, so that it is rendered on its side. This makes it fit into its layout box.
This commit is contained in:
parent
80e7e6dd7d
commit
02276360e9
Notes:
github-actions[bot]
2024-11-03 16:02:57 +00:00
Author: https://github.com/BenJilks
Commit: 02276360e9
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2135
Reviewed-by: https://github.com/kalenikaliaksandr ✅
9 changed files with 41 additions and 7 deletions
|
@ -53,6 +53,7 @@ public:
|
|||
bool is_atomic_inline() const;
|
||||
|
||||
RefPtr<Gfx::GlyphRun> glyph_run() const { return m_glyph_run; }
|
||||
CSS::WritingMode writing_mode() const { return m_writing_mode; }
|
||||
void append_glyph_run(RefPtr<Gfx::GlyphRun> const&, CSSPixels run_width);
|
||||
|
||||
private:
|
||||
|
|
|
@ -31,7 +31,7 @@ static RefPtr<DisplayList> 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<int>(), *glyph_run, Gfx::Color::Black, fragment_absolute_device_rect.to_type<int>(), scale);
|
||||
display_list_recorder.draw_text_run(baseline_start.to_type<int>(), *glyph_run, Gfx::Color::Black, fragment_absolute_device_rect.to_type<int>(), scale, fragment.orientation());
|
||||
};
|
||||
|
||||
paintable.for_each_in_inclusive_subtree([&](auto& paintable) {
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<float>(rect.y()) + metrics.ascent + (static_cast<float>(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<float>(),
|
||||
.scale = scale,
|
||||
.orientation = orientation,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<int>(), *glyph_run, paintable.computed_values().webkit_text_fill_color(), fragment_absolute_device_rect.to_type<int>(), scale);
|
||||
painter.draw_text_run(baseline_start.to_type<int>(), *glyph_run, paintable.computed_values().webkit_text_fill_color(), fragment_absolute_device_rect.to_type<int>(), scale, fragment.orientation());
|
||||
|
||||
auto selection_rect = context.enclosing_device_rect(fragment.selection_rect(paintable.layout_node().first_available_font())).to_type<int>();
|
||||
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<int>(), *glyph_run, CSS::SystemColor::highlight_text(), fragment_absolute_device_rect.to_type<int>(), scale);
|
||||
painter.draw_text_run(baseline_start.to_type<int>(), *glyph_run, CSS::SystemColor::highlight_text(), fragment_absolute_device_rect.to_type<int>(), scale, fragment.orientation());
|
||||
}
|
||||
|
||||
paint_text_decoration(context, paintable, fragment);
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
CSSPixelRect const absolute_rect() const;
|
||||
|
||||
RefPtr<Gfx::GlyphRun> 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<Gfx::GlyphRun> m_glyph_run;
|
||||
CSS::WritingMode m_writing_mode;
|
||||
Vector<ShadowData> m_shadows;
|
||||
ResolvedBackground m_resolved_background;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue