mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 05:37:35 +00:00
LibGfx/OpenType: Load x-height metrics from OS/2 table if available
Before this change we always returned the font's point size as the x-height which was basically never correct. We now get it from the OS/2 table (if one with version >= 2 is available in the file). Otherwise we fall back to using the ascent of the 'x' glyph. Most fonts appear to have a sufficiently modern OS/2 table.
This commit is contained in:
parent
8090adf268
commit
69c33bd4ca
6 changed files with 50 additions and 1 deletions
4
Tests/LibWeb/Layout/expected/css-ex-unit.txt
Normal file
4
Tests/LibWeb/Layout/expected/css-ex-unit.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x177.132812 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x161.132812 children: not-inline
|
||||||
|
BlockContainer <div> at (8,8) content-size 107.421875x161.132812 children: not-inline
|
8
Tests/LibWeb/Layout/input/css-ex-unit.html
Normal file
8
Tests/LibWeb/Layout/input/css-ex-unit.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<!doctype html><style>
|
||||||
|
div {
|
||||||
|
font: 20px SerenitySans;
|
||||||
|
width: 10ex;
|
||||||
|
height: 15ex;
|
||||||
|
background: red;
|
||||||
|
}
|
||||||
|
</style><div>
|
|
@ -574,21 +574,28 @@ Gfx::ScaledFontMetrics Font::metrics([[maybe_unused]] float x_scale, float y_sca
|
||||||
i16 raw_ascender;
|
i16 raw_ascender;
|
||||||
i16 raw_descender;
|
i16 raw_descender;
|
||||||
i16 raw_line_gap;
|
i16 raw_line_gap;
|
||||||
|
Optional<i16> x_height;
|
||||||
|
|
||||||
if (m_os2.has_value() && m_os2->use_typographic_metrics()) {
|
if (m_os2.has_value() && m_os2->use_typographic_metrics()) {
|
||||||
raw_ascender = m_os2->typographic_ascender();
|
raw_ascender = m_os2->typographic_ascender();
|
||||||
raw_descender = m_os2->typographic_descender();
|
raw_descender = m_os2->typographic_descender();
|
||||||
raw_line_gap = m_os2->typographic_line_gap();
|
raw_line_gap = m_os2->typographic_line_gap();
|
||||||
|
x_height = m_os2->x_height();
|
||||||
} else {
|
} else {
|
||||||
raw_ascender = m_hhea.ascender();
|
raw_ascender = m_hhea.ascender();
|
||||||
raw_descender = m_hhea.descender();
|
raw_descender = m_hhea.descender();
|
||||||
raw_line_gap = m_hhea.line_gap();
|
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 {
|
return Gfx::ScaledFontMetrics {
|
||||||
.ascender = static_cast<float>(raw_ascender) * y_scale,
|
.ascender = static_cast<float>(raw_ascender) * y_scale,
|
||||||
.descender = -static_cast<float>(raw_descender) * y_scale,
|
.descender = -static_cast<float>(raw_descender) * y_scale,
|
||||||
.line_gap = static_cast<float>(raw_line_gap) * y_scale,
|
.line_gap = static_cast<float>(raw_line_gap) * y_scale,
|
||||||
|
.x_height = static_cast<float>(x_height.value()) * y_scale,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,6 +861,13 @@ bool OS2::use_typographic_metrics() const
|
||||||
return header().fs_selection & 0x80;
|
return header().fs_selection & 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<i16> OS2::x_height() const
|
||||||
|
{
|
||||||
|
if (header().version < 2)
|
||||||
|
return {};
|
||||||
|
return header_v2().sx_height;
|
||||||
|
}
|
||||||
|
|
||||||
Optional<ReadonlyBytes> Font::font_program() const
|
Optional<ReadonlyBytes> Font::font_program() const
|
||||||
{
|
{
|
||||||
if (m_fpgm.has_value())
|
if (m_fpgm.has_value())
|
||||||
|
|
|
@ -243,6 +243,8 @@ public:
|
||||||
|
|
||||||
bool use_typographic_metrics() const;
|
bool use_typographic_metrics() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Optional<i16> x_height() const;
|
||||||
|
|
||||||
explicit OS2(ReadonlyBytes slice)
|
explicit OS2(ReadonlyBytes slice)
|
||||||
: m_slice(slice)
|
: m_slice(slice)
|
||||||
{
|
{
|
||||||
|
@ -282,7 +284,27 @@ private:
|
||||||
BigEndian<u16> us_win_descent;
|
BigEndian<u16> us_win_descent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Version1 {
|
||||||
|
Version0 version0;
|
||||||
|
BigEndian<u32> ul_code_page_range1;
|
||||||
|
BigEndian<u32> ul_code_page_range2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Version2 {
|
||||||
|
Version1 version1;
|
||||||
|
BigEndian<i16> sx_height;
|
||||||
|
BigEndian<i16> s_cap_height;
|
||||||
|
BigEndian<u16> us_default_char;
|
||||||
|
BigEndian<u16> us_break_char;
|
||||||
|
BigEndian<u16> us_max_context;
|
||||||
|
};
|
||||||
|
|
||||||
Version0 const& header() const { return *bit_cast<Version0 const*>(m_slice.data()); }
|
Version0 const& header() const { return *bit_cast<Version0 const*>(m_slice.data()); }
|
||||||
|
Version2 const& header_v2() const
|
||||||
|
{
|
||||||
|
VERIFY(header().version >= 2);
|
||||||
|
return *bit_cast<Version2 const*>(m_slice.data());
|
||||||
|
}
|
||||||
|
|
||||||
ReadonlyBytes m_slice;
|
ReadonlyBytes m_slice;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,7 +27,7 @@ ScaledFont::ScaledFont(NonnullRefPtr<VectorFont> font, float point_width, float
|
||||||
|
|
||||||
m_pixel_metrics = Gfx::FontPixelMetrics {
|
m_pixel_metrics = Gfx::FontPixelMetrics {
|
||||||
.size = (float)pixel_size(),
|
.size = (float)pixel_size(),
|
||||||
.x_height = (float)x_height(),
|
.x_height = metrics.x_height,
|
||||||
.advance_of_ascii_zero = (float)glyph_width('0'),
|
.advance_of_ascii_zero = (float)glyph_width('0'),
|
||||||
.glyph_spacing = (float)glyph_spacing(),
|
.glyph_spacing = (float)glyph_spacing(),
|
||||||
.ascent = metrics.ascender,
|
.ascent = metrics.ascender,
|
||||||
|
|
|
@ -17,6 +17,7 @@ struct ScaledFontMetrics {
|
||||||
float ascender { 0 };
|
float ascender { 0 };
|
||||||
float descender { 0 };
|
float descender { 0 };
|
||||||
float line_gap { 0 };
|
float line_gap { 0 };
|
||||||
|
float x_height { 0 };
|
||||||
|
|
||||||
float height() const
|
float height() const
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue