|
Lines 39-44
namespace WebCore {
a/Source/WebCore/style/InlineTextBoxStyle.cpp_sec1
|
| 39 |
|
39 |
|
| 40 |
struct UnderlineOffsetArguments { |
40 |
struct UnderlineOffsetArguments { |
| 41 |
const RenderStyle& lineStyle; |
41 |
const RenderStyle& lineStyle; |
|
|
42 |
TextUnderlinePosition resolvedUnderlinePosition { TextUnderlinePosition::Auto }; |
| 42 |
float defaultGap { 0 }; |
43 |
float defaultGap { 0 }; |
| 43 |
std::optional<TextUnderlinePositionUnder> textUnderlinePositionUnder { }; |
44 |
std::optional<TextUnderlinePositionUnder> textUnderlinePositionUnder { }; |
| 44 |
}; |
45 |
}; |
|
Lines 130-140
static inline float defaultGap(const RenderStyle& style)
a/Source/WebCore/style/InlineTextBoxStyle.cpp_sec2
|
| 130 |
return style.computedFontSize() / textDecorationBaseFontSize; |
131 |
return style.computedFontSize() / textDecorationBaseFontSize; |
| 131 |
} |
132 |
} |
| 132 |
|
133 |
|
| 133 |
static float computeUnderlineOffset(const UnderlineOffsetArguments& context) |
134 |
static inline TextUnderlinePosition resolvedUnderlinePosition(const RenderStyle& decoratingBoxStyle, std::optional<FontBaseline> baselineType) |
|
|
135 |
{ |
| 136 |
auto underlinePosition = decoratingBoxStyle.textUnderlinePosition(); |
| 137 |
if (underlinePosition == TextUnderlinePosition::Auto && decoratingBoxStyle.textUnderlineOffset().isAuto()) { |
| 138 |
if (baselineType) |
| 139 |
return *baselineType == IdeographicBaseline ? TextUnderlinePosition::Under : TextUnderlinePosition::Auto; |
| 140 |
return TextUnderlinePosition::Auto; |
| 141 |
} |
| 142 |
return underlinePosition; |
| 143 |
} |
| 144 |
|
| 145 |
static float computedUnderlineOffset(const UnderlineOffsetArguments& context) |
| 134 |
{ |
146 |
{ |
| 135 |
// This represents the gap between the baseline and the closest edge of the underline. |
147 |
// This represents the gap between the baseline and the closest edge of the underline. |
| 136 |
float gap = std::max<int>(1, std::ceil(context.defaultGap / 2.0f)); |
148 |
auto gap = std::max(1.f, std::ceil(context.defaultGap / 2.f)); |
| 137 |
|
149 |
|
| 138 |
// FIXME: The code for visual overflow detection passes in a null inline text box. This means it is now |
150 |
// FIXME: The code for visual overflow detection passes in a null inline text box. This means it is now |
| 139 |
// broken for the case where auto needs to behave like "under". |
151 |
// broken for the case where auto needs to behave like "under". |
| 140 |
|
152 |
|
|
Lines 142-178
static float computeUnderlineOffset(const UnderlineOffsetArguments& context)
a/Source/WebCore/style/InlineTextBoxStyle.cpp_sec3
|
| 142 |
// scripts where it would not be appropriate (e.g., ideographs). |
154 |
// scripts where it would not be appropriate (e.g., ideographs). |
| 143 |
// Strictly speaking this can occur whenever the line contains ideographs |
155 |
// Strictly speaking this can occur whenever the line contains ideographs |
| 144 |
// even if it is horizontal, but detecting this has performance implications. For now we only work with |
156 |
// even if it is horizontal, but detecting this has performance implications. For now we only work with |
| 145 |
// vertical text, since we already determined the baseline type to be ideographic in that |
157 |
// vertical text, since we already determined the baseline type to be ideographic in that case. |
| 146 |
// case. |
|
|
| 147 |
auto underlinePosition = context.lineStyle.textUnderlinePosition(); |
| 148 |
auto underlineOffset = context.lineStyle.textUnderlineOffset(); |
158 |
auto underlineOffset = context.lineStyle.textUnderlineOffset(); |
| 149 |
auto& fontMetrics = context.lineStyle.metricsOfPrimaryFont(); |
159 |
auto& fontMetrics = context.lineStyle.metricsOfPrimaryFont(); |
| 150 |
|
160 |
|
| 151 |
auto resolvedUnderlinePosition = underlinePosition; |
161 |
float computedUnderlineOffset = fontMetrics.ascent() + gap; |
| 152 |
if (resolvedUnderlinePosition == TextUnderlinePosition::Auto && underlineOffset.isAuto()) { |
162 |
switch (context.resolvedUnderlinePosition) { |
| 153 |
if (context.textUnderlinePositionUnder) |
|
|
| 154 |
resolvedUnderlinePosition = context.textUnderlinePositionUnder->baselineType == IdeographicBaseline ? TextUnderlinePosition::Under : TextUnderlinePosition::Auto; |
| 155 |
else |
| 156 |
resolvedUnderlinePosition = TextUnderlinePosition::Auto; |
| 157 |
} |
| 158 |
|
| 159 |
switch (resolvedUnderlinePosition) { |
| 160 |
case TextUnderlinePosition::Auto: |
163 |
case TextUnderlinePosition::Auto: |
| 161 |
if (underlineOffset.isAuto()) |
164 |
computedUnderlineOffset = fontMetrics.ascent() + underlineOffset.lengthOr(gap); |
| 162 |
return fontMetrics.ascent() + gap; |
165 |
break; |
| 163 |
return fontMetrics.ascent() + underlineOffset.lengthValue(); |
|
|
| 164 |
case TextUnderlinePosition::FromFont: |
166 |
case TextUnderlinePosition::FromFont: |
| 165 |
return fontMetrics.ascent() + fontMetrics.underlinePosition() + underlineOffset.lengthOr(0); |
167 |
computedUnderlineOffset = fontMetrics.ascent() + fontMetrics.underlinePosition() + underlineOffset.lengthOr(0.f); |
|
|
168 |
break; |
| 166 |
case TextUnderlinePosition::Under: { |
169 |
case TextUnderlinePosition::Under: { |
| 167 |
ASSERT(context.textUnderlinePositionUnder); |
170 |
ASSERT(context.textUnderlinePositionUnder); |
| 168 |
// Position underline relative to the bottom edge of the lowest element's content box. |
171 |
// Position underline relative to the bottom edge of the lowest element's content box. |
| 169 |
auto desiredOffset = context.textUnderlinePositionUnder->textRunLogicalHeight + gap + std::max(context.textUnderlinePositionUnder->textRunOffsetFromBottomMost, 0.0f) + underlineOffset.lengthOr(0); |
172 |
auto desiredOffset = context.textUnderlinePositionUnder->textRunLogicalHeight + gap + std::max(context.textUnderlinePositionUnder->textRunOffsetFromBottomMost, 0.f) + underlineOffset.lengthOr(0.f); |
| 170 |
return std::max<float>(desiredOffset, fontMetrics.ascent()); |
173 |
computedUnderlineOffset = std::max<float>(desiredOffset, fontMetrics.ascent()); |
|
|
174 |
break; |
| 171 |
} |
175 |
} |
|
|
176 |
default: |
| 177 |
ASSERT_NOT_REACHED(); |
| 178 |
break; |
| 172 |
} |
179 |
} |
| 173 |
|
180 |
|
| 174 |
ASSERT_NOT_REACHED(); |
181 |
return computedUnderlineOffset; |
| 175 |
return fontMetrics.ascent() + gap; |
|
|
| 176 |
} |
182 |
} |
| 177 |
|
183 |
|
| 178 |
WavyStrokeParameters getWavyStrokeParameters(float fontSize) |
184 |
WavyStrokeParameters getWavyStrokeParameters(float fontSize) |
|
Lines 254-269
static GlyphOverflow computedVisualOverflowForDecorations(const RenderStyle& lin
a/Source/WebCore/style/InlineTextBoxStyle.cpp_sec4
|
| 254 |
GlyphOverflow visualOverflowForDecorations(const InlineIterator::LineBoxIterator& lineBox, const RenderText& renderer, float textBoxLogicalTop, float textBoxLogicalBottom) |
260 |
GlyphOverflow visualOverflowForDecorations(const InlineIterator::LineBoxIterator& lineBox, const RenderText& renderer, float textBoxLogicalTop, float textBoxLogicalBottom) |
| 255 |
{ |
261 |
{ |
| 256 |
auto& style = lineBox->isFirst() ? renderer.firstLineStyle() : renderer.style(); |
262 |
auto& style = lineBox->isFirst() ? renderer.firstLineStyle() : renderer.style(); |
|
|
263 |
auto underlinePositionValue = resolvedUnderlinePosition(style, lineBox->baselineType()); |
| 264 |
auto textUnderlinePositionUnder = std::optional<TextUnderlinePositionUnder> { }; |
| 265 |
|
| 266 |
if (underlinePositionValue == TextUnderlinePosition::Under) { |
| 267 |
auto textRunOffset = textRunOffsetFromBottomMost(lineBox, renderer, textBoxLogicalTop, textBoxLogicalBottom); |
| 268 |
textUnderlinePositionUnder = TextUnderlinePositionUnder { textBoxLogicalBottom - textBoxLogicalTop, textRunOffset }; |
| 269 |
} |
| 270 |
|
| 257 |
auto underlineOffset = style.textDecorationsInEffect().contains(TextDecorationLine::Underline) |
271 |
auto underlineOffset = style.textDecorationsInEffect().contains(TextDecorationLine::Underline) |
| 258 |
? std::make_optional(computeUnderlineOffset({ style, defaultGap(style), TextUnderlinePositionUnder { lineBox->baselineType(), textBoxLogicalBottom - textBoxLogicalTop, textRunOffsetFromBottomMost(lineBox, renderer, textBoxLogicalTop, textBoxLogicalBottom) } })) |
272 |
? std::make_optional(computedUnderlineOffset({ style, underlinePositionValue, defaultGap(style), textUnderlinePositionUnder })) |
| 259 |
: std::nullopt; |
273 |
: std::nullopt; |
| 260 |
return computedVisualOverflowForDecorations(style, underlineOffset); |
274 |
return computedVisualOverflowForDecorations(style, underlineOffset); |
| 261 |
} |
275 |
} |
| 262 |
|
276 |
|
| 263 |
GlyphOverflow visualOverflowForDecorations(const RenderStyle& style, TextUnderlinePositionUnder textUnderlinePositionUnder) |
277 |
GlyphOverflow visualOverflowForDecorations(const RenderStyle& style, FontBaseline baselineType, TextUnderlinePositionUnder textUnderlinePositionUnder) |
| 264 |
{ |
278 |
{ |
| 265 |
auto underlineOffset = style.textDecorationsInEffect().contains(TextDecorationLine::Underline) |
279 |
auto underlineOffset = style.textDecorationsInEffect().contains(TextDecorationLine::Underline) |
| 266 |
? std::make_optional(computeUnderlineOffset({ style, defaultGap(style), textUnderlinePositionUnder })) |
280 |
? std::make_optional(computedUnderlineOffset({ style, resolvedUnderlinePosition(style, baselineType), defaultGap(style), textUnderlinePositionUnder })) |
| 267 |
: std::nullopt; |
281 |
: std::nullopt; |
| 268 |
return computedVisualOverflowForDecorations(style, underlineOffset); |
282 |
return computedVisualOverflowForDecorations(style, underlineOffset); |
| 269 |
} |
283 |
} |
|
Lines 271-289
GlyphOverflow visualOverflowForDecorations(const RenderStyle& style, TextUnderli
a/Source/WebCore/style/InlineTextBoxStyle.cpp_sec5
|
| 271 |
GlyphOverflow visualOverflowForDecorations(const RenderStyle& style) |
285 |
GlyphOverflow visualOverflowForDecorations(const RenderStyle& style) |
| 272 |
{ |
286 |
{ |
| 273 |
auto underlineOffset = style.textDecorationsInEffect().contains(TextDecorationLine::Underline) |
287 |
auto underlineOffset = style.textDecorationsInEffect().contains(TextDecorationLine::Underline) |
| 274 |
? std::make_optional(computeUnderlineOffset({ style, defaultGap(style), { } })) |
288 |
? std::make_optional(computedUnderlineOffset({ style, resolvedUnderlinePosition(style, { }), defaultGap(style), { } })) |
| 275 |
: std::nullopt; |
289 |
: std::nullopt; |
| 276 |
return computedVisualOverflowForDecorations(style, underlineOffset); |
290 |
return computedVisualOverflowForDecorations(style, underlineOffset); |
| 277 |
} |
291 |
} |
| 278 |
|
292 |
|
| 279 |
float underlineOffsetForTextBoxPainting(const RenderStyle& style, const InlineIterator::TextBoxIterator& textBox) |
293 |
float underlineOffsetForTextBoxPainting(const RenderStyle& style, const InlineIterator::TextBoxIterator& textBox) |
| 280 |
{ |
294 |
{ |
| 281 |
auto textUnderlinePositionUnder = TextUnderlinePositionUnder { |
295 |
auto lineBox = textBox->lineBox(); |
| 282 |
textBox->lineBox()->baselineType(), |
296 |
auto textUnderlinePositionUnder = std::optional<TextUnderlinePositionUnder> { }; |
| 283 |
textBox->logicalBottom() - textBox->logicalTop(), |
297 |
auto underlinePositionValue = resolvedUnderlinePosition(style, lineBox->baselineType()); |
| 284 |
textRunOffsetFromBottomMost(textBox->lineBox(), textBox->renderer(), textBox->logicalTop(), textBox->logicalBottom()) |
298 |
|
| 285 |
}; |
299 |
if (underlinePositionValue == TextUnderlinePosition::Under) { |
| 286 |
return computeUnderlineOffset({ style , defaultGap(style), textUnderlinePositionUnder }); |
300 |
auto textRunOffset = textRunOffsetFromBottomMost(lineBox, textBox->renderer(), textBox->logicalTop(), textBox->logicalBottom()); |
|
|
301 |
textUnderlinePositionUnder = TextUnderlinePositionUnder { textBox->logicalBottom() - textBox->logicalTop(), textRunOffset }; |
| 302 |
} |
| 303 |
|
| 304 |
return computedUnderlineOffset({ style, underlinePositionValue, defaultGap(style), textUnderlinePositionUnder }); |
| 287 |
} |
305 |
} |
| 288 |
|
306 |
|
| 289 |
} |
307 |
} |