Commit 07c1ced3 authored by Rob Buis's avatar Rob Buis Committed by Commit Bot

[mathml] Implement italic correction

Implement italic correction [1] when laying out scripts. In order to
signal that an operator has an italic correction we add
SetMathItalicCorrection on the fragment builder and set it if
needed when laying out the operator. The script layout algorithm
uses this value when laying out the script, where appropriate.

[1] https://mathml-refresh.github.io/mathml-core/#dfn-italic-correction
Bug: 1125136, 6606

Change-Id: I2995b0fad1e1c8e96cc08818d50927d28cb54f4c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2414240Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarFrédéric Wang <fwang@igalia.com>
Commit-Queue: Rob Buis <rbuis@igalia.com>
Cr-Commit-Position: refs/heads/master@{#824055}
parent f56188d3
...@@ -64,6 +64,11 @@ scoped_refptr<const NGLayoutResult> NGMathOperatorLayoutAlgorithm::Layout() { ...@@ -64,6 +64,11 @@ scoped_refptr<const NGLayoutResult> NGMathOperatorLayoutAlgorithm::Layout() {
scoped_refptr<const ShapeResultView> shape_result_view = scoped_refptr<const ShapeResultView> shape_result_view =
ShapeResultView::Create(shape_result.get()); ShapeResultView::Create(shape_result.get());
if (metrics.italic_correction) {
container_builder_.SetMathItalicCorrection(
LayoutUnit(metrics.italic_correction));
}
LayoutUnit operator_ascent = LayoutUnit::FromFloatFloor(metrics.ascent); LayoutUnit operator_ascent = LayoutUnit::FromFloatFloor(metrics.ascent);
LayoutUnit operator_descent = LayoutUnit::FromFloatFloor(metrics.descent); LayoutUnit operator_descent = LayoutUnit::FromFloatFloor(metrics.descent);
......
...@@ -317,7 +317,8 @@ scoped_refptr<const NGLayoutResult> NGMathScriptsLayoutAlgorithm::Layout() { ...@@ -317,7 +317,8 @@ scoped_refptr<const NGLayoutResult> NGMathScriptsLayoutAlgorithm::Layout() {
content_start_offset.block_offset; content_start_offset.block_offset;
LayoutUnit descent = LayoutUnit descent =
std::max(base_metrics.descent, metrics.descent + metrics.sub_shift); std::max(base_metrics.descent, metrics.descent + metrics.sub_shift);
// TODO(crbug.com/1125136): take into account italic correction. LayoutUnit base_italic_correction = std::min(
base_metrics.inline_size, base_metrics.result->MathItalicCorrection());
LayoutUnit inline_offset = content_start_offset.inline_offset; LayoutUnit inline_offset = content_start_offset.inline_offset;
LayoutUnit space = GetSpaceAfterScript(Style()); LayoutUnit space = GetSpaceAfterScript(Style());
...@@ -366,7 +367,10 @@ scoped_refptr<const NGLayoutResult> NGMathScriptsLayoutAlgorithm::Layout() { ...@@ -366,7 +367,10 @@ scoped_refptr<const NGLayoutResult> NGMathScriptsLayoutAlgorithm::Layout() {
sup_metric = sup_metrics[idx]; sup_metric = sup_metrics[idx];
if (sub_metric.node) { if (sub_metric.node) {
LogicalOffset sub_offset(inline_offset + sub_metric.margins.inline_start, LogicalOffset sub_offset(
LayoutUnit(inline_offset + sub_metric.margins.inline_start -
base_italic_correction)
.ClampNegativeToZero(),
ascent + metrics.sub_shift - sub_metric.ascent + ascent + metrics.sub_shift - sub_metric.ascent +
sub_metric.margins.block_start); sub_metric.margins.block_start);
container_builder_.AddChild(sub_metric.result->PhysicalFragment(), container_builder_.AddChild(sub_metric.result->PhysicalFragment(),
...@@ -419,6 +423,9 @@ MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes( ...@@ -419,6 +423,9 @@ MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes(
MinMaxSizes sizes; MinMaxSizes sizes;
bool depends_on_percentage_block_size = false; bool depends_on_percentage_block_size = false;
ChildAndMetrics base_metrics = LayoutAndGetMetrics(base);
LayoutUnit base_italic_correction = std::min(
base_metrics.inline_size, base_metrics.result->MathItalicCorrection());
MinMaxSizesResult base_result = MinMaxSizesResult base_result =
ComputeMinAndMaxContentContribution(Style(), base, child_input); ComputeMinAndMaxContentContribution(Style(), base, child_input);
base_result.sizes += ComputeMinMaxMargins(Style(), base).InlineSum(); base_result.sizes += ComputeMinMaxMargins(Style(), base).InlineSum();
...@@ -433,7 +440,6 @@ MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes( ...@@ -433,7 +440,6 @@ MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes(
case MathScriptType::kUnder: case MathScriptType::kUnder:
case MathScriptType::kOver: case MathScriptType::kOver:
case MathScriptType::kSuper: { case MathScriptType::kSuper: {
// TODO(crbug.com/1125136): Take italic correction into account.
NGBlockNode sub = sub_sup_pairs[0].sub; NGBlockNode sub = sub_sup_pairs[0].sub;
NGBlockNode sup = sub_sup_pairs[0].sup; NGBlockNode sup = sub_sup_pairs[0].sup;
auto first_post_script = sub ? sub : sup; auto first_post_script = sub ? sub : sup;
...@@ -443,6 +449,8 @@ MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes( ...@@ -443,6 +449,8 @@ MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes(
ComputeMinMaxMargins(Style(), first_post_script).InlineSum(); ComputeMinMaxMargins(Style(), first_post_script).InlineSum();
sizes += first_post_script_result.sizes; sizes += first_post_script_result.sizes;
if (sub)
sizes -= base_italic_correction;
sizes += space; sizes += space;
depends_on_percentage_block_size |= depends_on_percentage_block_size |=
first_post_script_result.depends_on_percentage_block_size; first_post_script_result.depends_on_percentage_block_size;
...@@ -451,7 +459,6 @@ MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes( ...@@ -451,7 +459,6 @@ MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes(
case MathScriptType::kSubSup: case MathScriptType::kSubSup:
case MathScriptType::kUnderOver: case MathScriptType::kUnderOver:
case MathScriptType::kMultiscripts: { case MathScriptType::kMultiscripts: {
// TODO(crbug.com/1125136): Take italic correction into account.
MinMaxSizes sub_sup_pair_size; MinMaxSizes sub_sup_pair_size;
unsigned index = 0; unsigned index = 0;
do { do {
...@@ -461,6 +468,7 @@ MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes( ...@@ -461,6 +468,7 @@ MinMaxSizesResult NGMathScriptsLayoutAlgorithm::ComputeMinMaxSizes(
auto sub_result = auto sub_result =
ComputeMinAndMaxContentContribution(Style(), sub, child_input); ComputeMinAndMaxContentContribution(Style(), sub, child_input);
sub_result.sizes += ComputeMinMaxMargins(Style(), sub).InlineSum(); sub_result.sizes += ComputeMinMaxMargins(Style(), sub).InlineSum();
sub_result.sizes -= base_italic_correction;
sub_sup_pair_size.Encompass(sub_result.sizes); sub_sup_pair_size.Encompass(sub_result.sizes);
auto sup = sub_sup_pairs[index].sup; auto sup = sub_sup_pairs[index].sup;
......
...@@ -43,6 +43,7 @@ class CORE_EXPORT NGMathScriptsLayoutAlgorithm ...@@ -43,6 +43,7 @@ class CORE_EXPORT NGMathScriptsLayoutAlgorithm
LayoutUnit ascent; LayoutUnit ascent;
LayoutUnit descent; LayoutUnit descent;
LayoutUnit inline_size; LayoutUnit inline_size;
LayoutUnit base_italic_correction;
NGBoxStrut margins; NGBoxStrut margins;
NGBlockNode node = nullptr; NGBlockNode node = nullptr;
}; };
......
...@@ -604,6 +604,13 @@ void NGBoxFragmentBuilder::SetLastBaselineToBlockEndMarginEdgeIfNeeded() { ...@@ -604,6 +604,13 @@ void NGBoxFragmentBuilder::SetLastBaselineToBlockEndMarginEdgeIfNeeded() {
SetLastBaseline(FragmentBlockSize() + margins.block_end); SetLastBaseline(FragmentBlockSize() + margins.block_end);
} }
void NGBoxFragmentBuilder::SetMathItalicCorrection(
LayoutUnit italic_correction) {
if (!math_data_)
math_data_.emplace();
math_data_->italic_correction_ = italic_correction;
}
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
void NGBoxFragmentBuilder::CheckNoBlockFragmentation() const { void NGBoxFragmentBuilder::CheckNoBlockFragmentation() const {
......
...@@ -551,6 +551,8 @@ class CORE_EXPORT NGBoxFragmentBuilder final ...@@ -551,6 +551,8 @@ class CORE_EXPORT NGBoxFragmentBuilder final
// any baselines, OOFs, etc, are also moved by the appropriate amount). // any baselines, OOFs, etc, are also moved by the appropriate amount).
void MoveChildrenInBlockDirection(LayoutUnit offset); void MoveChildrenInBlockDirection(LayoutUnit offset);
void SetMathItalicCorrection(LayoutUnit italic_correction);
private: private:
// Update whether we have fragmented in this flow. // Update whether we have fragmented in this flow.
void PropagateBreak(const NGLayoutResult&); void PropagateBreak(const NGLayoutResult&);
...@@ -626,6 +628,7 @@ class CORE_EXPORT NGBoxFragmentBuilder final ...@@ -626,6 +628,7 @@ class CORE_EXPORT NGBoxFragmentBuilder final
base::Optional<int> lines_until_clamp_; base::Optional<int> lines_until_clamp_;
std::unique_ptr<NGMathMLPaintInfo> mathml_paint_info_; std::unique_ptr<NGMathMLPaintInfo> mathml_paint_info_;
base::Optional<NGLayoutResult::MathData> math_data_;
scoped_refptr<const NGBlockBreakToken> previous_break_token_; scoped_refptr<const NGBlockBreakToken> previous_break_token_;
......
...@@ -106,6 +106,8 @@ NGLayoutResult::NGLayoutResult( ...@@ -106,6 +106,8 @@ NGLayoutResult::NGLayoutResult(
} }
if (builder->table_column_count_) if (builder->table_column_count_)
EnsureRareData()->table_column_count_ = *builder->table_column_count_; EnsureRareData()->table_column_count_ = *builder->table_column_count_;
if (builder->math_data_.has_value())
EnsureRareData()->math_layout_data_ = builder->math_data_;
} }
NGLayoutResult::NGLayoutResult( NGLayoutResult::NGLayoutResult(
......
...@@ -220,6 +220,12 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> { ...@@ -220,6 +220,12 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
return HasRareData() ? rare_data_->table_column_count_ : 0; return HasRareData() ? rare_data_->table_column_count_ : 0;
} }
LayoutUnit MathItalicCorrection() const {
return HasRareData() && rare_data_->math_layout_data_
? rare_data_->math_layout_data_->italic_correction_
: LayoutUnit();
}
// The break-before value on the first child needs to be propagated to the // The break-before value on the first child needs to be propagated to the
// container, in search of a valid class A break point. // container, in search of a valid class A break point.
EBreakBetween InitialBreakBefore() const { EBreakBetween InitialBreakBefore() const {
...@@ -344,6 +350,11 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> { ...@@ -344,6 +350,11 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
scoped_refptr<const NGPhysicalContainerFragment> physical_fragment, scoped_refptr<const NGPhysicalContainerFragment> physical_fragment,
NGLineBoxFragmentBuilder*); NGLineBoxFragmentBuilder*);
// See https://mathml-refresh.github.io/mathml-core/#box-model
struct MathData {
LayoutUnit italic_correction_;
};
private: private:
friend class MutableForOutOfFlow; friend class MutableForOutOfFlow;
...@@ -416,6 +427,7 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> { ...@@ -416,6 +427,7 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
bool is_single_use = false; bool is_single_use = false;
int lines_until_clamp = 0; int lines_until_clamp = 0;
wtf_size_t table_column_count_ = 0; wtf_size_t table_column_count_ = 0;
base::Optional<MathData> math_layout_data_;
}; };
bool HasRareData() const { return bitfields_.has_rare_data; } bool HasRareData() const { return bitfields_.has_rare_data; }
......
This is a testharness.js-based test.
PASS Null Italic Correction
FAIL NonNull Italic Correction (MathGlyphVariantRecord) assert_approx_equals: msub expected 30 +/- 1 but got 0
FAIL NonNull Italic Correction (GlyphAssembly) assert_approx_equals: msub expected 50 +/- 1 but got 0
Harness: the test ran to completion.
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