Commit a41285fb authored by Frédéric Wang's avatar Frédéric Wang Committed by Commit Bot

[mathml] Expose italic correction from OpenTypeMathSupport

This CL exposes italic correction from the OpenType MATH table, for
individual glyphs [1] and for glyph assemblies [2]. These will be
used by the StretchyOperatorShaper to expose italic correction of
stretchy operators and then will be used for MathML layout.

[1] https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathglyphinfo-table
[2] https://docs.microsoft.com/en-us/typography/opentype/spec/math#glyphassembly-table

Bug: 6606
Change-Id: I280aa404632683867b73e1682a5aa051ce682fbe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2100940
Commit-Queue: Frédéric Wang <fwang@igalia.com>
Reviewed-by: default avatarDominik Röttsches <drott@chromium.org>
Cr-Commit-Position: refs/heads/master@{#750399}
parent bf7e3b9b
...@@ -25,6 +25,13 @@ float HarfBuzzUnitsToFloat(hb_position_t value) { ...@@ -25,6 +25,13 @@ float HarfBuzzUnitsToFloat(hb_position_t value) {
// See https://chromium-review.googlesource.com/c/chromium/src/+/2074678 // See https://chromium-review.googlesource.com/c/chromium/src/+/2074678
unsigned kMaxHarfBuzzRecords = 20; unsigned kMaxHarfBuzzRecords = 20;
hb_direction_t HarfBuzzDirection(
blink::OpenTypeMathStretchData::StretchAxis stretch_axis) {
return stretch_axis == blink::OpenTypeMathStretchData::StretchAxis::Horizontal
? HB_DIRECTION_LTR
: HB_DIRECTION_BTT;
}
} // namespace } // namespace
namespace blink { namespace blink {
...@@ -120,6 +127,19 @@ base::Optional<float> OpenTypeMathSupport::MathConstant( ...@@ -120,6 +127,19 @@ base::Optional<float> OpenTypeMathSupport::MathConstant(
return base::nullopt; return base::nullopt;
} }
base::Optional<float> OpenTypeMathSupport::MathItalicCorrection(
const HarfBuzzFace* harfbuzz_face,
Glyph glyph) {
if (!harfbuzz_face)
return base::nullopt;
hb_font_t* font =
harfbuzz_face->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout);
return base::Optional<float>(HarfBuzzUnitsToFloat(
hb_ot_math_get_glyph_italics_correction(font, glyph)));
}
template <typename HarfBuzzRecordType> template <typename HarfBuzzRecordType>
using GetHarfBuzzMathRecordGetter = using GetHarfBuzzMathRecordGetter =
base::OnceCallback<unsigned int(hb_font_t* font, base::OnceCallback<unsigned int(hb_font_t* font,
...@@ -145,10 +165,7 @@ Vector<RecordType> GetHarfBuzzMathRecord( ...@@ -145,10 +165,7 @@ Vector<RecordType> GetHarfBuzzMathRecord(
harfbuzz_face->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout); harfbuzz_face->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout);
DCHECK(hb_font); DCHECK(hb_font);
hb_direction_t hb_stretch_axis = hb_direction_t hb_stretch_axis = HarfBuzzDirection(stretch_axis);
stretch_axis == OpenTypeMathStretchData::StretchAxis::Horizontal
? HB_DIRECTION_LTR
: HB_DIRECTION_BTT;
// In practice, math fonts have, for a given base glyph and stretch axis only // In practice, math fonts have, for a given base glyph and stretch axis only
// provide a few GlyphVariantRecords (size variants of increasing sizes) and // provide a few GlyphVariantRecords (size variants of increasing sizes) and
...@@ -195,7 +212,8 @@ Vector<OpenTypeMathStretchData::GlyphPartRecord> ...@@ -195,7 +212,8 @@ Vector<OpenTypeMathStretchData::GlyphPartRecord>
OpenTypeMathSupport::GetGlyphPartRecords( OpenTypeMathSupport::GetGlyphPartRecords(
const HarfBuzzFace* harfbuzz_face, const HarfBuzzFace* harfbuzz_face,
Glyph base_glyph, Glyph base_glyph,
OpenTypeMathStretchData::StretchAxis stretch_axis) { OpenTypeMathStretchData::StretchAxis stretch_axis,
float* italic_correction) {
DCHECK(harfbuzz_face); DCHECK(harfbuzz_face);
DCHECK(base_glyph); DCHECK(base_glyph);
...@@ -217,10 +235,24 @@ OpenTypeMathSupport::GetGlyphPartRecords( ...@@ -217,10 +235,24 @@ OpenTypeMathSupport::GetGlyphPartRecords(
HarfBuzzUnitsToFloat(record.full_advance), HarfBuzzUnitsToFloat(record.full_advance),
record.flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER}; record.flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER};
}); });
return GetHarfBuzzMathRecord( Vector<OpenTypeMathStretchData::GlyphPartRecord> parts =
harfbuzz_face, base_glyph, stretch_axis, std::move(getter), GetHarfBuzzMathRecord(
std::move(converter), harfbuzz_face, base_glyph, stretch_axis, std::move(getter),
base::Optional<OpenTypeMathStretchData::GlyphPartRecord>()); std::move(converter),
base::Optional<OpenTypeMathStretchData::GlyphPartRecord>());
if (italic_correction && !parts.IsEmpty()) {
hb_font_t* hb_font =
harfbuzz_face->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout);
// A GlyphAssembly subtable exists for the specified font, glyph and stretch
// axis since it has been possible to retrieve the GlyphPartRecords. This
// means that the following call is guaranteed to get an italic correction.
hb_position_t harfbuzz_italic_correction;
hb_ot_math_get_glyph_assembly(hb_font, base_glyph,
HarfBuzzDirection(stretch_axis), 0, nullptr,
nullptr, &harfbuzz_italic_correction);
*italic_correction = HarfBuzzUnitsToFloat(harfbuzz_italic_correction);
}
return parts;
} }
} // namespace blink } // namespace blink
...@@ -80,8 +80,21 @@ class PLATFORM_EXPORT OpenTypeMathSupport { ...@@ -80,8 +80,21 @@ class PLATFORM_EXPORT OpenTypeMathSupport {
kRadicalDegreeBottomRaisePercent = 55 kRadicalDegreeBottomRaisePercent = 55
}; };
// Returns the value of the requested math constant or null if the font does
// not have any OpenType MATH table. All values are 16.16 fixed-point values
// converted to float except percentages (kScriptPercentScaleDown,
// kScriptScriptPercentScaleDown and kRadicalDegreeBottomRaisePercent) which
// are represented by a number between 0 and 1.
// https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathconstants-table
static base::Optional<float> MathConstant(const HarfBuzzFace*, MathConstants); static base::Optional<float> MathConstant(const HarfBuzzFace*, MathConstants);
// Returns the italic correction corresponding to the specified glyph or null
// if the font does not have any OpenType MATH table. This value provides an
// estimation of how much the glyph is slanted, which can be used e.g. when
// attaching scripts to the glyph.
// https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathitalicscorrectioninfo-table
static base::Optional<float> MathItalicCorrection(const HarfBuzzFace*, Glyph);
// Returns a vector of GlyphVariantRecords corresponding to the specified // Returns a vector of GlyphVariantRecords corresponding to the specified
// glyph and stretch axis. The base glyph is always added as the first item. // glyph and stretch axis. The base glyph is always added as the first item.
// https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathvariants-table // https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathvariants-table
...@@ -91,12 +104,15 @@ class PLATFORM_EXPORT OpenTypeMathSupport { ...@@ -91,12 +104,15 @@ class PLATFORM_EXPORT OpenTypeMathSupport {
OpenTypeMathStretchData::StretchAxis); OpenTypeMathStretchData::StretchAxis);
// Returns a vector of GlyphPartRecords corresponding to the specified // Returns a vector of GlyphPartRecords corresponding to the specified
// glyph and stretch axis. It is empty if there is no such construction. // glyph and stretch axis or an empty vector if there is no such construction.
// If the italic_correction parameter is specified and a construction is
// available, then it is set to the italic correction of the glyph assembly.
// https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathvariants-table // https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathvariants-table
static Vector<OpenTypeMathStretchData::GlyphPartRecord> GetGlyphPartRecords( static Vector<OpenTypeMathStretchData::GlyphPartRecord> GetGlyphPartRecords(
const HarfBuzzFace*, const HarfBuzzFace*,
Glyph base_glyph, Glyph base_glyph,
OpenTypeMathStretchData::StretchAxis); OpenTypeMathStretchData::StretchAxis,
float* italic_correction = nullptr);
}; };
} // namespace blink } // namespace blink
......
...@@ -14,6 +14,7 @@ namespace { ...@@ -14,6 +14,7 @@ namespace {
const UChar32 kLeftBraceCodePoint = '{'; const UChar32 kLeftBraceCodePoint = '{';
const UChar32 kOverBraceCodePoint = 0x23DE; const UChar32 kOverBraceCodePoint = 0x23DE;
const UChar32 kArabicMathOperatorHahWithDalCodePoint = 0x1EEF1; const UChar32 kArabicMathOperatorHahWithDalCodePoint = 0x1EEF1;
const UChar32 kNAryWhiteVerticalBarCodePoint = 0x2AFF;
} // namespace } // namespace
namespace blink { namespace blink {
...@@ -409,4 +410,58 @@ TEST_F(OpenTypeMathSupportTest, MathVariantsWithTable) { ...@@ -409,4 +410,58 @@ TEST_F(OpenTypeMathSupportTest, MathVariantsWithTable) {
} }
} }
// See third_party/blink/web_tests/external/wpt/mathml/tools/largeop.py
TEST_F(OpenTypeMathSupportTest, MathItalicCorrection) {
{
Font math = CreateMathFont(
"largeop-displayoperatorminheight2000-2AFF-italiccorrection3000.woff");
Glyph base_glyph =
math.PrimaryFont()->GlyphForCharacter(kNAryWhiteVerticalBarCodePoint);
// Retrieve the glyph with italic correction.
Vector<OpenTypeMathStretchData::GlyphVariantRecord> variants =
OpenTypeMathSupport::GetGlyphVariantRecords(
math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), base_glyph,
OpenTypeMathStretchData::StretchAxis::Vertical);
EXPECT_EQ(variants.size(), 3u);
EXPECT_EQ(variants[0], base_glyph);
EXPECT_EQ(variants[1], base_glyph);
Glyph glyph_with_italic_correction = variants[2];
// MathItalicCorrection with a value.
base::Optional<float> glyph_with_italic_correction_value =
OpenTypeMathSupport::MathItalicCorrection(
math.PrimaryFont()->PlatformData().GetHarfBuzzFace(),
glyph_with_italic_correction);
EXPECT_TRUE(glyph_with_italic_correction_value);
EXPECT_FLOAT_EQ(*glyph_with_italic_correction_value, 3000);
// GetGlyphPartRecords does not set italic correction when there is no
// construction available.
float italic_correction = -1000;
Vector<OpenTypeMathStretchData::GlyphPartRecord> parts =
OpenTypeMathSupport::GetGlyphPartRecords(
math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), base_glyph,
OpenTypeMathStretchData::StretchAxis::Vertical, &italic_correction);
EXPECT_TRUE(parts.IsEmpty());
EXPECT_FLOAT_EQ(italic_correction, -1000);
}
{
Font math = CreateMathFont(
"largeop-displayoperatorminheight7000-2AFF-italiccorrection5000.woff");
Glyph base_glyph =
math.PrimaryFont()->GlyphForCharacter(kNAryWhiteVerticalBarCodePoint);
// OpenTypeMathSupport::GetGlyphPartRecords sets italic correction.
float italic_correction = -1000;
Vector<OpenTypeMathStretchData::GlyphPartRecord> parts =
OpenTypeMathSupport::GetGlyphPartRecords(
math.PrimaryFont()->PlatformData().GetHarfBuzzFace(), base_glyph,
OpenTypeMathStretchData::StretchAxis::Vertical, &italic_correction);
EXPECT_EQ(parts.size(), 3u);
EXPECT_FLOAT_EQ(italic_correction, 5000);
}
}
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment