Bug 1463115 - Try to skip irrelevant (collapsed/trimmed) whitespace when collecting used font faces for devtools inspector. r=jwatt
authorJonathan Kew <jkew@mozilla.com>
Thu, 24 May 2018 14:44:09 +0100
changeset 477682 b7688ef14e3ae06221387df0820affe16f9b98a1
parent 477681 3518510139bbb70636739b271fb6fe602e5c644b
child 477683 d50a8eb8c327a69f4f25108b62cfa2f3230a18ba
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs1463115
milestone62.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 1463115 - Try to skip irrelevant (collapsed/trimmed) whitespace when collecting used font faces for devtools inspector. r=jwatt
dom/base/nsRange.cpp
dom/base/nsRange.h
dom/chrome-webidl/InspectorUtils.webidl
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/generic/nsTextFrame.cpp
layout/generic/nsTextFrame.h
layout/inspector/InspectorUtils.cpp
layout/inspector/InspectorUtils.h
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -3152,17 +3152,17 @@ nsRange::GetClientRectsAndTexts(
   nsLayoutUtils::RectListBuilder builder(aResult.mRectList);
 
   CollectClientRectsAndText(&builder, &aResult.mTextList, this,
     mStart.Container(), mStart.Offset(), mEnd.Container(), mEnd.Offset(), true, true);
 }
 
 nsresult
 nsRange::GetUsedFontFaces(nsTArray<nsAutoPtr<InspectorFontFace>>& aResult,
-                          uint32_t aMaxRanges)
+                          uint32_t aMaxRanges, bool aSkipCollapsedWhitespace)
 {
   NS_ENSURE_TRUE(mStart.Container(), NS_ERROR_UNEXPECTED);
 
   nsCOMPtr<nsINode> startContainer = do_QueryInterface(mStart.Container());
   nsCOMPtr<nsINode> endContainer = do_QueryInterface(mEnd.Container());
 
   // Flush out layout so our frames are up to date.
   nsIDocument* doc = mStart.Container()->OwnerDoc();
@@ -3196,27 +3196,30 @@ nsRange::GetUsedFontFaces(nsTArray<nsAut
       continue;
     }
 
     if (content->IsText()) {
        if (node == startContainer) {
          int32_t offset = startContainer == endContainer ?
            mEnd.Offset() : content->GetText()->GetLength();
          nsLayoutUtils::GetFontFacesForText(frame, mStart.Offset(), offset,
-                                            true, fontFaces, aMaxRanges);
+                                            true, fontFaces, aMaxRanges,
+                                            aSkipCollapsedWhitespace);
          continue;
        }
        if (node == endContainer) {
          nsLayoutUtils::GetFontFacesForText(frame, 0, mEnd.Offset(),
-                                            true, fontFaces, aMaxRanges);
+                                            true, fontFaces, aMaxRanges,
+                                            aSkipCollapsedWhitespace);
          continue;
        }
     }
 
-    nsLayoutUtils::GetFontFacesForFrames(frame, fontFaces, aMaxRanges);
+    nsLayoutUtils::GetFontFacesForFrames(frame, fontFaces, aMaxRanges,
+                                         aSkipCollapsedWhitespace);
   }
 
   // Take ownership of the InspectorFontFaces in the table and move them into
   // the aResult outparam.
   for (auto iter = fontFaces.Iter(); !iter.Done(); iter.Next()) {
     aResult.AppendElement(std::move(iter.Data()));
   }
 
--- a/dom/base/nsRange.h
+++ b/dom/base/nsRange.h
@@ -265,17 +265,18 @@ public:
     return parentNode;
   }
 
   // aMaxRanges is the maximum number of text ranges to record for each face
   // (pass 0 to just get the list of faces, without recording exact ranges
   // where each face was used).
   nsresult GetUsedFontFaces(
       nsTArray<nsAutoPtr<mozilla::dom::InspectorFontFace>>& aResult,
-      uint32_t aMaxRanges);
+      uint32_t aMaxRanges,
+      bool aSkipCollapsedWhitespace);
 
   // nsIMutationObserver methods
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
   NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
 
--- a/dom/chrome-webidl/InspectorUtils.webidl
+++ b/dom/chrome-webidl/InspectorUtils.webidl
@@ -60,17 +60,18 @@ namespace InspectorUtils {
 
   // Get the font face(s) actually used to render the text in /range/,
   // as a collection of InspectorFontFace objects (below).
   // If /maxRanges/ is greater than zero, each InspectorFontFace will record
   // up to /maxRanges/ fragments of content that used the face, for the caller
   // to access via its .ranges attribute.
   [NewObject, Throws] sequence<InspectorFontFace> getUsedFontFaces(
       Range range,
-      optional unsigned long maxRanges = 0);
+      optional unsigned long maxRanges = 0,
+      optional boolean skipCollapsedWhitespace = true);
 
   sequence<DOMString> getCSSPseudoElementNames();
   void addPseudoClassLock(Element element,
                           DOMString pseudoClass,
                           optional boolean enabled = true);
   void removePseudoClassLock(Element element, DOMString pseudoClass);
   boolean hasPseudoClassLock(Element element, DOMString pseudoClass);
   void clearPseudoClassLocks(Element element);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -7859,49 +7859,54 @@ nsLayoutUtils::AssertTreeOnlyEmptyNextIn
     }
   }
 }
 #endif
 
 static void
 GetFontFacesForFramesInner(nsIFrame* aFrame,
                            nsLayoutUtils::UsedFontFaceTable& aFontFaces,
-                           uint32_t aMaxRanges)
+                           uint32_t aMaxRanges,
+                           bool aSkipCollapsedWhitespace)
 {
   MOZ_ASSERT(aFrame, "NULL frame pointer");
 
   if (aFrame->IsTextFrame()) {
     if (!aFrame->GetPrevContinuation()) {
       nsLayoutUtils::GetFontFacesForText(aFrame, 0, INT32_MAX, true,
-                                         aFontFaces, aMaxRanges);
+                                         aFontFaces, aMaxRanges,
+                                         aSkipCollapsedWhitespace);
     }
     return;
   }
 
   nsIFrame::ChildListID childLists[] = { nsIFrame::kPrincipalList,
                                          nsIFrame::kPopupList };
   for (size_t i = 0; i < ArrayLength(childLists); ++i) {
     nsFrameList children(aFrame->GetChildList(childLists[i]));
     for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) {
       nsIFrame* child = e.get();
       child = nsPlaceholderFrame::GetRealFrameFor(child);
-      GetFontFacesForFramesInner(child, aFontFaces, aMaxRanges);
+      GetFontFacesForFramesInner(child, aFontFaces, aMaxRanges,
+                                 aSkipCollapsedWhitespace);
     }
   }
 }
 
 /* static */ nsresult
 nsLayoutUtils::GetFontFacesForFrames(nsIFrame* aFrame,
                                      UsedFontFaceTable& aFontFaces,
-                                     uint32_t aMaxRanges)
+                                     uint32_t aMaxRanges,
+                                     bool aSkipCollapsedWhitespace)
 {
   MOZ_ASSERT(aFrame, "NULL frame pointer");
 
   while (aFrame) {
-    GetFontFacesForFramesInner(aFrame, aFontFaces, aMaxRanges);
+    GetFontFacesForFramesInner(aFrame, aFontFaces, aMaxRanges,
+                               aSkipCollapsedWhitespace);
     aFrame = GetNextContinuationOrIBSplitSibling(aFrame);
   }
 
   return NS_OK;
 }
 
 static void
 AddFontsFromTextRun(gfxTextRun* aTextRun,
@@ -7962,17 +7967,18 @@ AddFontsFromTextRun(gfxTextRun* aTextRun
 }
 
 /* static */ void
 nsLayoutUtils::GetFontFacesForText(nsIFrame* aFrame,
                                    int32_t aStartOffset,
                                    int32_t aEndOffset,
                                    bool aFollowContinuations,
                                    UsedFontFaceTable& aFontFaces,
-                                   uint32_t aMaxRanges)
+                                   uint32_t aMaxRanges,
+                                   bool aSkipCollapsedWhitespace)
 {
   MOZ_ASSERT(aFrame, "NULL frame pointer");
 
   if (!aFrame->IsTextFrame()) {
     return;
   }
 
   if (!aFrame->StyleVisibility()->IsVisible()) {
@@ -8002,19 +8008,23 @@ nsLayoutUtils::GetFontFacesForText(nsIFr
       next = static_cast<nsTextFrame*>(curr->GetNextContinuation());
       while (next && next->GetTextRun(nsTextFrame::eInflated) == textRun) {
         fend = std::min(next->GetContentEnd(), aEndOffset);
         next = fend < aEndOffset ?
           static_cast<nsTextFrame*>(next->GetNextContinuation()) : nullptr;
       }
     }
 
-    gfxTextRun::Range range(iter.ConvertOriginalToSkipped(fstart),
-                            iter.ConvertOriginalToSkipped(fend));
-    AddFontsFromTextRun(textRun, curr, iter, range, aFontFaces, aMaxRanges);
+    if (!aSkipCollapsedWhitespace ||
+        (curr->HasAnyNoncollapsedCharacters() &&
+         curr->HasNonSuppressedText())) {
+      gfxTextRun::Range range(iter.ConvertOriginalToSkipped(fstart),
+                              iter.ConvertOriginalToSkipped(fend));
+      AddFontsFromTextRun(textRun, curr, iter, range, aFontFaces, aMaxRanges);
+    }
 
     curr = next;
   } while (aFollowContinuations && curr);
 }
 
 /* static */
 size_t
 nsLayoutUtils::SizeOfTextRunsForFrames(nsIFrame* aFrame,
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -2283,31 +2283,33 @@ public:
 
   /**
    * Adds all font faces used in the frame tree starting from aFrame
    * to the list aFontFaceList.
    * aMaxRanges: maximum number of text ranges to record for each face.
    */
   static nsresult GetFontFacesForFrames(nsIFrame* aFrame,
                                         UsedFontFaceTable& aResult,
-                                        uint32_t aMaxRanges);
+                                        uint32_t aMaxRanges,
+                                        bool aSkipCollapsedWhitespace);
 
   /**
    * Adds all font faces used within the specified range of text in aFrame,
    * and optionally its continuations, to the list in aFontFaceList.
    * Pass 0 and INT32_MAX for aStartOffset and aEndOffset to specify the
    * entire text is to be considered.
    * aMaxRanges: maximum number of text ranges to record for each face.
    */
   static void GetFontFacesForText(nsIFrame* aFrame,
                                   int32_t aStartOffset,
                                   int32_t aEndOffset,
                                   bool aFollowContinuations,
                                   UsedFontFaceTable& aResult,
-                                  uint32_t aMaxRanges);
+                                  uint32_t aMaxRanges,
+                                  bool aSkipCollapsedWhitespace);
 
   /**
    * Walks the frame tree starting at aFrame looking for textRuns.
    * If |clear| is true, just clears the TEXT_RUN_MEMORY_ACCOUNTED flag
    * on each textRun found (and |aMallocSizeOf| is not used).
    * If |clear| is false, adds the storage used for each textRun to the
    * total, and sets the TEXT_RUN_MEMORY_ACCOUNTED flag to avoid double-
    * accounting. (Runs with this flag already set will be skipped.)
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -10415,17 +10415,21 @@ nsTextFrame::CountGraphemeClusters() con
   nsAutoString content;
   frag->AppendTo(content, GetContentOffset(), GetContentLength());
   return unicode::CountGraphemeClusters(content.Data(), content.Length());
 }
 
 bool
 nsTextFrame::HasNonSuppressedText()
 {
-  if (HasAnyStateBits(TEXT_ISNOT_ONLY_WHITESPACE)) {
+  if (HasAnyStateBits(TEXT_ISNOT_ONLY_WHITESPACE |
+                      // If we haven't reflowed yet, or are currently doing so,
+                      // just return true because we can't be sure.
+                      NS_FRAME_FIRST_REFLOW |
+                      NS_FRAME_IN_REFLOW)) {
     return true;
   }
 
   if (!GetTextRun(nsTextFrame::eInflated)) {
     return false;
   }
 
   TrimmedOffsets offsets = GetTrimmedOffsets(mContent->GetText(), false);
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -661,16 +661,18 @@ public:
 
   bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override;
 
   void AssignJustificationGaps(const mozilla::JustificationAssignment& aAssign);
   mozilla::JustificationAssignment GetJustificationAssignment() const;
 
   uint32_t CountGraphemeClusters() const;
 
+  bool HasAnyNoncollapsedCharacters() override;
+
 protected:
   virtual ~nsTextFrame();
 
   RefPtr<gfxTextRun> mTextRun;
   nsTextFrame* mNextContinuation;
   // The key invariant here is that mContentOffset never decreases along
   // a next-continuation chain. And of course mContentOffset is always <= the
   // the text node's content length, and the mContentOffset for the first frame
@@ -877,18 +879,16 @@ protected:
     SelectionType aSelectionType);
 
   ContentOffsets GetCharacterOffsetAtFramePointInternal(
     const nsPoint& aPoint,
     bool aForInsertionPoint);
 
   void ClearFrameOffsetCache();
 
-  bool HasAnyNoncollapsedCharacters() override;
-
   void ClearMetrics(ReflowOutput& aMetrics);
 
   /**
    * UpdateIteratorFromOffset() updates the iterator from a given offset.
    * Also, aInOffset may be updated to cluster start if aInOffset isn't
    * the offset of cluster start.
    */
   void UpdateIteratorFromOffset(const PropertyProvider& aProperties,
--- a/layout/inspector/InspectorUtils.cpp
+++ b/layout/inspector/InspectorUtils.cpp
@@ -612,20 +612,22 @@ InspectorUtils::GetCleanComputedStyleFor
 
   return nsComputedDOMStyle::GetComputedStyle(aElement, aPseudo);
 }
 
 /* static */ void
 InspectorUtils::GetUsedFontFaces(GlobalObject& aGlobalObject,
                                  nsRange& aRange,
                                  uint32_t aMaxRanges,
+                                 bool aSkipCollapsedWhitespace,
                                  nsTArray<nsAutoPtr<InspectorFontFace>>& aResult,
                                  ErrorResult& aRv)
 {
-  nsresult rv = aRange.GetUsedFontFaces(aResult, aMaxRanges);
+  nsresult rv = aRange.GetUsedFontFaces(aResult, aMaxRanges,
+                                        aSkipCollapsedWhitespace);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
 }
 
 static EventStates
 GetStatesForPseudoClass(const nsAString& aStatePseudo)
 {
--- a/layout/inspector/InspectorUtils.h
+++ b/layout/inspector/InspectorUtils.h
@@ -220,16 +220,17 @@ public:
                                  bool aClearActiveDocument,
                                  ErrorResult& aRv);
   static uint64_t GetContentState(GlobalObject& aGlobal, Element& aElement);
 
   static void GetUsedFontFaces(GlobalObject& aGlobal,
                                nsRange& aRange,
                                uint32_t aMaxRanges, // max number of ranges to
                                                     // record for each face
+                               bool aSkipCollapsedWhitespace,
                                nsTArray<nsAutoPtr<InspectorFontFace>>& aResult,
                                ErrorResult& aRv);
 
   /**
    * Get the names of all the supported pseudo-elements.
    * Pseudo-elements which are only accepted in UA style sheets are
    * not included.
    */