Bug 1472386 - Take overflow-wrap into account when calculating min-content intrinsic size. r?jfkthame
MozReview-Commit-ID: Fu6Gbmxs4PN
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -1228,16 +1228,44 @@ gfxTextRun::GetAdvanceWidth(Range aRange
aSpacing->mAfter = spacingBuffer.LastElement().mAfter;
}
}
}
return result + GetAdvanceForGlyphs(ligatureRange);
}
+gfxFloat
+gfxTextRun::GetMinAdvanceWidth(Range aRange)
+{
+ MOZ_ASSERT(aRange.end <= GetLength(), "Substring out of range");
+
+ Range ligatureRange = aRange;
+ ShrinkToLigatureBoundaries(&ligatureRange);
+
+ gfxFloat result = std::max(
+ ComputePartialLigatureWidth(Range(aRange.start, ligatureRange.start),
+ nullptr),
+ ComputePartialLigatureWidth(Range(ligatureRange.end, aRange.end),
+ nullptr));
+
+ // XXX Do we need to take spacing into account? When each grapheme cluster
+ // takes its own line, we shouldn't be adding spacings around them.
+ gfxFloat clusterAdvance = 0;
+ for (uint32_t i = ligatureRange.start; i < ligatureRange.end; ++i) {
+ clusterAdvance += GetAdvanceForGlyph(i);
+ if (i + 1 == ligatureRange.end || IsClusterStart(i + 1)) {
+ result = std::max(result, clusterAdvance);
+ clusterAdvance = 0;
+ }
+ }
+
+ return result;
+}
+
bool
gfxTextRun::SetLineBreaks(Range aRange,
bool aLineBreakBefore, bool aLineBreakAfter,
gfxFloat *aAdvanceWidthDelta)
{
// Do nothing because our shaping does not currently take linebreaks into
// account. There is no change in advance width.
if (aAdvanceWidthDelta) {
--- a/gfx/thebes/gfxTextRun.h
+++ b/gfx/thebes/gfxTextRun.h
@@ -322,16 +322,22 @@ public:
PropertyProvider::Spacing*
aSpacing = nullptr) const;
gfxFloat GetAdvanceWidth() const {
return GetAdvanceWidth(Range(this), nullptr);
}
/**
+ * Computes the minimum advance width for a substring assuming line
+ * breaking is allowed everywhere.
+ */
+ gfxFloat GetMinAdvanceWidth(Range aRange);
+
+ /**
* Clear all stored line breaks for the given range (both before and after),
* and then set the line-break state before aRange.start to aBreakBefore and
* after the last cluster to aBreakAfter.
*
* We require that before and after line breaks be consistent. For clusters
* i and i+1, we require that if there is a break after cluster i, a break
* will be specified before cluster i+1. This may be temporarily violated
* (e.g. after reflowing line L and before reflowing line L+1); to handle
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -8544,16 +8544,26 @@ nsTextFrame::AddInlineMinISizeForFlow(gf
if (start < flowEndInTextRun && textRun->CanBreakLineBefore(start)) {
aData->OptionallyBreak();
}
aData->mCurrentLine += provider.GetFontMetrics()->EmHeight();
aData->mTrailingWhitespace = 0;
return;
}
+ // If overflow-wrap is break-word, we can wrap everywhere.
+ if (textStyle->WordCanWrap(this)) {
+ aData->OptionallyBreak();
+ aData->mCurrentLine +=
+ textRun->GetMinAdvanceWidth(Range(start, flowEndInTextRun));
+ aData->mTrailingWhitespace = 0;
+ aData->OptionallyBreak();
+ return;
+ }
+
AutoTArray<gfxTextRun::HyphenType, BIG_TEXT_NODE_SIZE> hyphBuffer;
if (hyphenating) {
if (hyphBuffer.AppendElements(flowEndInTextRun - start, fallible)) {
provider.GetHyphenationBreaks(Range(start, flowEndInTextRun),
hyphBuffer.Elements());
} else {
hyphenating = false;
}
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -135074,16 +135074,28 @@
[
"/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-001-ref.html",
"=="
]
],
{}
]
],
+ "css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html": [
+ [
+ "/css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html",
+ [
+ [
+ "/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-text/overflow-wrap/word-wrap-001.html": [
[
"/css/css-text/overflow-wrap/word-wrap-001.html",
[
[
"/css/css-text/overflow-wrap/overflow-wrap-001-ref.html",
"=="
]
@@ -257551,16 +257563,21 @@
{}
]
],
"css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-001-ref.html": [
[
{}
]
],
+ "css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-text/support/1x1-green.png": [
[
{}
]
],
"css/css-text/support/1x1-lime.png": [
[
{}
@@ -534115,16 +534132,20 @@
"css/css-text/overflow-wrap/overflow-wrap-break-word-fit-content-001.html": [
"9f88a667825f8cb725dc348e17081e1a25b3f4de",
"reftest"
],
"css/css-text/overflow-wrap/overflow-wrap-min-content-size-001.html": [
"5858dbb88a775bb8975f338d866b6fc837485364",
"reftest"
],
+ "css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html": [
+ "ae7abc617493b9e2c9313215a3f38b77c37d9450",
+ "reftest"
+ ],
"css/css-text/overflow-wrap/reference/overflow-wrap-break-word-001-ref.html": [
"0b16a0bdb25ddd647ad96dd82e3430274667ee87",
"support"
],
"css/css-text/overflow-wrap/reference/overflow-wrap-break-word-002-ref.html": [
"e049fce2e9861c0386d47dced6f5ab15fb989063",
"support"
],
@@ -534135,16 +534156,20 @@
"css/css-text/overflow-wrap/reference/overflow-wrap-break-word-fit-content-001.html": [
"7daf4c0482ae02fdd5a6855b3f750e664373efcd",
"support"
],
"css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-001-ref.html": [
"f3e09183b565f71e38158cc5cd4d96ab5fbf25d4",
"support"
],
+ "css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html": [
+ "3686ae6a0e278a970b861c165f0f840df302db70",
+ "support"
+ ],
"css/css-text/overflow-wrap/word-wrap-001.html": [
"8bafc4d48bbfee1e6c465a95b29792ba33c30346",
"reftest"
],
"css/css-text/overflow-wrap/word-wrap-002.html": [
"1fc206422060160f3d987240f5fc946e7f8f2341",
"reftest"
],
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-text/overflow-wrap/overflow-wrap-min-content-size-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[overflow-wrap-min-content-size-001.html]
- expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Test: overflow-wrap: break-word and intrinsic sizing</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#overflow-wrap-property">
+<meta name="flags" content="">
+<link rel="match" href="reference/overflow-wrap-min-content-size-002-ref.html">
+<meta name="assert" content="overflow-wrap:break-word doesn't break grapheme cluster and min-content intrinsic size should take that into account.">
+<style>
+#wrapper {
+ width: 0px;
+ overflow-wrap: break-word;
+}
+#test {
+ float: left;
+ border: 2px solid blue;
+}
+</style>
+
+<p>Test passes if the glyphs are completely inside the blue box.
+<div id="wrapper">
+ <div id="test">நிிிிநிிிி</div>
+</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Test reference</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+<style>
+#test {
+ float: left;
+ border: 2px solid blue;
+}
+</style>
+
+<p>Test passes if the glyphs are completely inside the blue box.
+<div id="wrapper">
+ <div id="test">நிிிி<br>நிிிி</div>
+</div>