Bug 1472386 - Take overflow-wrap into account when calculating min-content intrinsic size. r=jfkthame
authorXidorn Quan <me@upsuper.org>
Mon, 09 Jul 2018 14:54:34 +1000
changeset 426783 f52422f008ed88d270b9af0ba0379e07a7c2268c
parent 426782 465f6e311e6db2cfda4ca5400c43cbd7ced82619
child 426784 633b1aae6b2ebb4af909cfa85cd51a02c66242dd
push id34285
push userbtara@mozilla.com
push dateMon, 16 Jul 2018 21:58:41 +0000
treeherdermozilla-central@f6df6a982ee9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1472386
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1472386 - Take overflow-wrap into account when calculating min-content intrinsic size. r=jfkthame MozReview-Commit-ID: Fu6Gbmxs4PN
gfx/thebes/gfxTextRun.cpp
gfx/thebes/gfxTextRun.h
layout/generic/nsTextFrame.cpp
testing/web-platform/meta/MANIFEST.json
testing/web-platform/meta/css/css-text/overflow-wrap/overflow-wrap-min-content-size-001.html.ini
testing/web-platform/tests/css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html
testing/web-platform/tests/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html
--- 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",
        "=="
       ]
@@ -257587,16 +257599,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": [
     [
      {}
@@ -534171,16 +534188,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"
   ],
@@ -534191,16 +534212,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">&#x0ba8;&#x0bbf;&#x0bbf;&#x0bbf;&#x0bbf;&#x0ba8;&#x0bbf;&#x0bbf;&#x0bbf;&#x0bbf;</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">&#x0ba8;&#x0bbf;&#x0bbf;&#x0bbf;&#x0bbf;<br>&#x0ba8;&#x0bbf;&#x0bbf;&#x0bbf;&#x0bbf;</div>
+</div>