mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
LibGfx+LibWeb: Update for_each_glyph_position to use font cascade list
This change updates function that builds list of glyphs to use font cascade list to find font for each code point.
This commit is contained in:
parent
2cb0039a13
commit
df57d7ca68
Notes:
sideshowbarker
2024-07-17 05:41:34 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/df57d7ca68 Pull-request: https://github.com/SerenityOS/serenity/pull/22236 Issue: https://github.com/SerenityOS/serenity/issues/21213
8 changed files with 66 additions and 16 deletions
BIN
Tests/LibWeb/Ref/assets/HashSans.woff
Normal file
BIN
Tests/LibWeb/Ref/assets/HashSans.woff
Normal file
Binary file not shown.
23
Tests/LibWeb/Ref/reference/unicode-range-ref.html
Normal file
23
Tests/LibWeb/Ref/reference/unicode-range-ref.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'HashFont';
|
||||
src: url('../assets/HashSans.woff');
|
||||
}
|
||||
|
||||
.hash-font {
|
||||
font-family: 'HashFont';
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 100px;
|
||||
font-family: "SerenitySans";
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="text"><span class="hash-font">A</span>B</div>
|
||||
</body>
|
||||
</html>
|
21
Tests/LibWeb/Ref/unicode-range.html
Normal file
21
Tests/LibWeb/Ref/unicode-range.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="match" href="reference/unicode-range-ref.html" />
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'HashFont';
|
||||
src: url('assets/HashSans.woff');
|
||||
unicode-range: U+0041; /* Only letter 'A' */
|
||||
}
|
||||
|
||||
.text {
|
||||
font-family: 'HashFont', 'SerenitySans';
|
||||
font-size: 100px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="text">AB</div>
|
||||
</body>
|
||||
</html>
|
|
@ -2439,7 +2439,9 @@ void Painter::draw_text_run(IntPoint baseline_start, Utf8View const& string, Fon
|
|||
|
||||
void Painter::draw_text_run(FloatPoint baseline_start, Utf8View const& string, Font const& font, Color color)
|
||||
{
|
||||
for_each_glyph_position(baseline_start, string, font, [&](DrawGlyphOrEmoji glyph_or_emoji) {
|
||||
auto font_list = Gfx::FontCascadeList::create();
|
||||
font_list->add(font);
|
||||
for_each_glyph_position(baseline_start, string, font_list, [&](DrawGlyphOrEmoji glyph_or_emoji) {
|
||||
if (glyph_or_emoji.has<DrawGlyph>()) {
|
||||
auto& glyph = glyph_or_emoji.get<DrawGlyph>();
|
||||
draw_glyph(glyph.position, glyph.code_point, *glyph.font, color);
|
||||
|
|
|
@ -170,8 +170,10 @@ void Path::text(Utf8View text, Font const& font)
|
|||
}
|
||||
|
||||
auto& scaled_font = static_cast<ScaledFont const&>(font);
|
||||
auto font_list = Gfx::FontCascadeList::create();
|
||||
font_list->add(scaled_font);
|
||||
for_each_glyph_position(
|
||||
last_point(), text, font, [&](DrawGlyphOrEmoji glyph_or_emoji) {
|
||||
last_point(), text, font_list, [&](DrawGlyphOrEmoji glyph_or_emoji) {
|
||||
if (glyph_or_emoji.has<DrawGlyph>()) {
|
||||
auto& glyph = glyph_or_emoji.get<DrawGlyph>();
|
||||
move_to(glyph.position);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <AK/Utf8View.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibGfx/FontCascadeList.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
#include <LibGfx/Rect.h>
|
||||
#include <LibGfx/TextElision.h>
|
||||
|
@ -92,34 +93,35 @@ using DrawGlyphOrEmoji = Variant<DrawGlyph, DrawEmoji>;
|
|||
Variant<DrawGlyph, DrawEmoji> prepare_draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font);
|
||||
|
||||
template<typename Callback>
|
||||
void for_each_glyph_position(FloatPoint baseline_start, Utf8View string, Font const& font, Callback callback, IncludeLeftBearing include_left_bearing = IncludeLeftBearing::No, Optional<float&> width = {})
|
||||
void for_each_glyph_position(FloatPoint baseline_start, Utf8View string, FontCascadeList const& font_list, Callback callback, IncludeLeftBearing include_left_bearing = IncludeLeftBearing::No, Optional<float&> width = {})
|
||||
{
|
||||
float space_width = font.glyph_width(' ') + font.glyph_spacing();
|
||||
float space_width = font_list.first().glyph_width(' ') + font_list.first().glyph_spacing();
|
||||
|
||||
u32 last_code_point = 0;
|
||||
|
||||
auto point = baseline_start;
|
||||
point.translate_by(0, -font.pixel_metrics().ascent);
|
||||
|
||||
for (auto code_point_iterator = string.begin(); code_point_iterator != string.end(); ++code_point_iterator) {
|
||||
auto it = code_point_iterator; // The callback function will advance the iterator, so create a copy for this lookup.
|
||||
auto code_point = *code_point_iterator;
|
||||
RefPtr<Gfx::Font const> font = font_list.font_for_code_point(code_point);
|
||||
|
||||
point.set_y(baseline_start.y() - font->pixel_metrics().ascent);
|
||||
|
||||
if (should_paint_as_space(code_point)) {
|
||||
point.translate_by(space_width, 0);
|
||||
last_code_point = code_point;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto kerning = font.glyphs_horizontal_kerning(last_code_point, code_point);
|
||||
auto kerning = font->glyphs_horizontal_kerning(last_code_point, code_point);
|
||||
if (kerning != 0.0f)
|
||||
point.translate_by(kerning, 0);
|
||||
|
||||
auto it = code_point_iterator; // The callback function will advance the iterator, so create a copy for this lookup.
|
||||
auto glyph_width = font.glyph_or_emoji_width(it) + font.glyph_spacing();
|
||||
|
||||
auto glyph_or_emoji = prepare_draw_glyph_or_emoji(point, code_point_iterator, font);
|
||||
auto glyph_width = font->glyph_or_emoji_width(it) + font->glyph_spacing();
|
||||
auto glyph_or_emoji = prepare_draw_glyph_or_emoji(point, code_point_iterator, *font);
|
||||
if (include_left_bearing == IncludeLeftBearing::Yes) {
|
||||
if (glyph_or_emoji.has<DrawGlyph>())
|
||||
glyph_or_emoji.get<DrawGlyph>().position += FloatPoint(font.glyph_left_bearing(code_point), 0);
|
||||
glyph_or_emoji.get<DrawGlyph>().position += FloatPoint(font->glyph_left_bearing(code_point), 0);
|
||||
}
|
||||
|
||||
callback(glyph_or_emoji);
|
||||
|
@ -129,7 +131,7 @@ void for_each_glyph_position(FloatPoint baseline_start, Utf8View string, Font co
|
|||
}
|
||||
|
||||
if (width.has_value())
|
||||
*width = point.x() - font.glyph_spacing();
|
||||
*width = point.x() - font_list.first().glyph_spacing();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ Optional<InlineLevelIterator::Item> InlineLevelIterator::next_without_lookahead(
|
|||
Vector<Gfx::DrawGlyphOrEmoji> glyph_run;
|
||||
float glyph_run_width = 0;
|
||||
Gfx::for_each_glyph_position(
|
||||
{ 0, 0 }, chunk.view, text_node.first_available_font(), [&](Gfx::DrawGlyphOrEmoji const& glyph_or_emoji) {
|
||||
{ 0, 0 }, chunk.view, text_node.font_list(), [&](Gfx::DrawGlyphOrEmoji const& glyph_or_emoji) {
|
||||
glyph_run.append(glyph_or_emoji);
|
||||
return IterationDecision::Continue;
|
||||
},
|
||||
|
|
|
@ -638,12 +638,12 @@ static void paint_text_fragment(PaintContext& context, Layout::TextNode const& t
|
|||
auto text = text_node.text_for_rendering();
|
||||
|
||||
DevicePixelPoint baseline_start { fragment_absolute_device_rect.x(), fragment_absolute_device_rect.y() + context.rounded_device_pixels(fragment.baseline()) };
|
||||
auto const& scaled_font = fragment.layout_node().scaled_font(context);
|
||||
Vector<Gfx::DrawGlyphOrEmoji> scaled_glyph_run;
|
||||
scaled_glyph_run.ensure_capacity(fragment.glyph_run().size());
|
||||
auto& font_cache = text_node.document().style_computer().font_cache();
|
||||
for (auto glyph : fragment.glyph_run()) {
|
||||
glyph.visit([&](auto& glyph) {
|
||||
glyph.font = scaled_font;
|
||||
glyph.font = font_cache.scaled_font(*glyph.font, context.device_pixels_per_css_pixel());
|
||||
glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel());
|
||||
});
|
||||
scaled_glyph_run.append(move(glyph));
|
||||
|
|
Loading…
Reference in a new issue