diff --git a/Tests/LibWeb/Layout/expected/css-ex-unit.txt b/Tests/LibWeb/Layout/expected/css-ex-unit.txt new file mode 100644 index 0000000000..62644b4cc8 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/css-ex-unit.txt @@ -0,0 +1,4 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x177.132812 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x161.132812 children: not-inline + BlockContainer
at (8,8) content-size 107.421875x161.132812 children: not-inline diff --git a/Tests/LibWeb/Layout/input/css-ex-unit.html b/Tests/LibWeb/Layout/input/css-ex-unit.html new file mode 100644 index 0000000000..f583eb8fad --- /dev/null +++ b/Tests/LibWeb/Layout/input/css-ex-unit.html @@ -0,0 +1,8 @@ +
\ No newline at end of file diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp index 8e1efccf00..45cb2fccb5 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp +++ b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp @@ -574,21 +574,28 @@ Gfx::ScaledFontMetrics Font::metrics([[maybe_unused]] float x_scale, float y_sca i16 raw_ascender; i16 raw_descender; i16 raw_line_gap; + Optional x_height; if (m_os2.has_value() && m_os2->use_typographic_metrics()) { raw_ascender = m_os2->typographic_ascender(); raw_descender = m_os2->typographic_descender(); raw_line_gap = m_os2->typographic_line_gap(); + x_height = m_os2->x_height(); } else { raw_ascender = m_hhea.ascender(); raw_descender = m_hhea.descender(); raw_line_gap = m_hhea.line_gap(); } + if (!x_height.has_value()) { + x_height = glyph_metrics(glyph_id_for_code_point('x'), 1, 1, 1, 1).ascender; + } + return Gfx::ScaledFontMetrics { .ascender = static_cast(raw_ascender) * y_scale, .descender = -static_cast(raw_descender) * y_scale, .line_gap = static_cast(raw_line_gap) * y_scale, + .x_height = static_cast(x_height.value()) * y_scale, }; } @@ -854,6 +861,13 @@ bool OS2::use_typographic_metrics() const return header().fs_selection & 0x80; } +Optional OS2::x_height() const +{ + if (header().version < 2) + return {}; + return header_v2().sx_height; +} + Optional Font::font_program() const { if (m_fpgm.has_value()) diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Tables.h b/Userland/Libraries/LibGfx/Font/OpenType/Tables.h index 15c0b301d9..b70b059b3d 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Tables.h +++ b/Userland/Libraries/LibGfx/Font/OpenType/Tables.h @@ -243,6 +243,8 @@ public: bool use_typographic_metrics() const; + [[nodiscard]] Optional x_height() const; + explicit OS2(ReadonlyBytes slice) : m_slice(slice) { @@ -282,7 +284,27 @@ private: BigEndian us_win_descent; }; + struct Version1 { + Version0 version0; + BigEndian ul_code_page_range1; + BigEndian ul_code_page_range2; + }; + + struct Version2 { + Version1 version1; + BigEndian sx_height; + BigEndian s_cap_height; + BigEndian us_default_char; + BigEndian us_break_char; + BigEndian us_max_context; + }; + Version0 const& header() const { return *bit_cast(m_slice.data()); } + Version2 const& header_v2() const + { + VERIFY(header().version >= 2); + return *bit_cast(m_slice.data()); + } ReadonlyBytes m_slice; }; diff --git a/Userland/Libraries/LibGfx/Font/ScaledFont.cpp b/Userland/Libraries/LibGfx/Font/ScaledFont.cpp index 441639bc97..f5022eefcd 100644 --- a/Userland/Libraries/LibGfx/Font/ScaledFont.cpp +++ b/Userland/Libraries/LibGfx/Font/ScaledFont.cpp @@ -27,7 +27,7 @@ ScaledFont::ScaledFont(NonnullRefPtr font, float point_width, float m_pixel_metrics = Gfx::FontPixelMetrics { .size = (float)pixel_size(), - .x_height = (float)x_height(), + .x_height = metrics.x_height, .advance_of_ascii_zero = (float)glyph_width('0'), .glyph_spacing = (float)glyph_spacing(), .ascent = metrics.ascender, diff --git a/Userland/Libraries/LibGfx/Font/VectorFont.h b/Userland/Libraries/LibGfx/Font/VectorFont.h index 06a5693488..945eb1e54e 100644 --- a/Userland/Libraries/LibGfx/Font/VectorFont.h +++ b/Userland/Libraries/LibGfx/Font/VectorFont.h @@ -17,6 +17,7 @@ struct ScaledFontMetrics { float ascender { 0 }; float descender { 0 }; float line_gap { 0 }; + float x_height { 0 }; float height() const {