Bug 1355531: Represent temporary TextOverflow instances using Maybe instead of UniquePtr. r?mats draft
authorDaniel Holbert <dholbert@cs.stanford.edu>
Tue, 11 Apr 2017 11:32:32 -0700
changeset 560637 5a9a713ffffeeb8167828bac390da80f45525cc6
parent 560069 5c208749f37a06043f6bed70a4e8b11993873af1
child 623767 a2cddbb0a28cdb2ca99c7077f4f417847b5818c5
push id53492
push userdholbert@mozilla.com
push dateTue, 11 Apr 2017 18:32:39 +0000
reviewersmats
bugs1355531
milestone55.0a1
Bug 1355531: Represent temporary TextOverflow instances using Maybe instead of UniquePtr. r?mats (This means we'll be storing it on the stack instead of the heap.) MozReview-Commit-ID: IsIn2BlpHIu
layout/generic/TextOverflow.cpp
layout/generic/TextOverflow.h
layout/generic/nsBlockFrame.cpp
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -316,31 +316,33 @@ TextOverflow::TextOverflow(nsDisplayList
   } else {
     mIStart.Init(style->mTextOverflow.GetRight(direction));
     mIEnd.Init(style->mTextOverflow.GetLeft(direction));
   }
   // The left/right marker string is setup in ExamineLineFrames when a line
   // has overflow on that side.
 }
 
-/* static */ TextOverflow*
+/* static */ Maybe<TextOverflow>
 TextOverflow::WillProcessLines(nsDisplayListBuilder*   aBuilder,
                                nsIFrame*               aBlockFrame)
 {
+  Maybe<TextOverflow> textOverflow;
   if (aBuilder->IsForEventDelivery() ||
       aBuilder->IsForFrameVisibility() ||
       !CanHaveTextOverflow(aBlockFrame)) {
-    return nullptr;
+    return textOverflow; // Nothing()
   }
   nsIScrollableFrame* scrollableFrame = nsLayoutUtils::GetScrollableFrameFor(aBlockFrame);
   if (scrollableFrame && scrollableFrame->IsTransformingByAPZ()) {
     // If the APZ is actively scrolling this, don't bother with markers.
-    return nullptr;
+    return textOverflow; // Nothing()
   }
-  return new TextOverflow(aBuilder, aBlockFrame);
+  textOverflow.emplace(aBuilder, aBlockFrame);
+  return textOverflow;
 }
 
 void
 TextOverflow::ExamineFrameSubtree(nsIFrame*       aFrame,
                                   const LogicalRect& aContentArea,
                                   const LogicalRect& aInsideMarkersArea,
                                   FrameHashtable* aFramesToHide,
                                   AlignmentEdges* aAlignmentEdges,
--- a/layout/generic/TextOverflow.h
+++ b/layout/generic/TextOverflow.h
@@ -5,39 +5,45 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef TextOverflow_h_
 #define TextOverflow_h_
 
 #include "nsDisplayList.h"
 #include "nsTHashtable.h"
 #include "mozilla/Likely.h"
+#include "mozilla/Maybe.h"
 #include "mozilla/WritingModes.h"
 #include <algorithm>
 
 class nsIScrollableFrame;
 class nsLineBox;
 
 namespace mozilla {
 namespace css {
 
 /**
  * A class for rendering CSS3 text-overflow.
  * Usage:
  *  1. allocate an object using WillProcessLines
  *  2. then call ProcessLine for each line you are building display lists for
  */
-class TextOverflow {
+class MOZ_STACK_CLASS TextOverflow {
  public:
+  // Do not instantiate directly; use WillProcessLines() instead.
+  TextOverflow(nsDisplayListBuilder* aBuilder,
+               nsIFrame* aBlockFrame);
+
   /**
-   * Allocate an object for text-overflow processing.
-   * @return nullptr if no processing is necessary.  The caller owns the object.
+   * Instantiate an object for text-overflow processing.
+   * @return a TextOverflow object, or Nothing() if no processing is necessary.
    */
-  static TextOverflow* WillProcessLines(nsDisplayListBuilder*   aBuilder,
-                                        nsIFrame*               aBlockFrame);
+  static Maybe<TextOverflow> WillProcessLines(nsDisplayListBuilder* aBuilder,
+                                              nsIFrame* aBlockFrame);
+
   /**
    * Analyze the display lists for text overflow and what kind of item is at
    * the content edges.  Add display items for text-overflow markers as needed
    * and remove or clip items that would overlap a marker.
    */
   void ProcessLine(const nsDisplayListSet& aLists, nsLineBox* aLine);
 
   /**
@@ -53,19 +59,16 @@ class TextOverflow {
   /**
    * @return true if aBlockFrame needs analysis for text overflow.
    */
   static bool CanHaveTextOverflow(nsIFrame* aBlockFrame);
 
   typedef nsTHashtable<nsPtrHashKey<nsIFrame> > FrameHashtable;
 
  protected:
-  TextOverflow(nsDisplayListBuilder* aBuilder,
-               nsIFrame* aBlockFrame);
-
   typedef mozilla::WritingMode WritingMode;
   typedef mozilla::LogicalRect LogicalRect;
 
   struct AlignmentEdges {
     AlignmentEdges() : mAssigned(false) {}
     void Accumulate(WritingMode aWM, const LogicalRect& aRect)
     {
       if (MOZ_LIKELY(mAssigned)) {
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -6558,17 +6558,17 @@ static void DebugOutputDrawLine(int32_t 
   }
 }
 #endif
 
 static void
 DisplayLine(nsDisplayListBuilder* aBuilder, const nsRect& aLineArea,
             const nsRect& aDirtyRect, nsBlockFrame::LineIterator& aLine,
             int32_t aDepth, int32_t& aDrawnLines, const nsDisplayListSet& aLists,
-            nsBlockFrame* aFrame, TextOverflow* aTextOverflow) {
+            nsBlockFrame* aFrame, Maybe<TextOverflow>& aTextOverflow) {
   // If the line's combined area (which includes child frames that
   // stick outside of the line's bounding box or our bounding box)
   // intersects the dirty rect then paint the line.
   bool intersect = aLineArea.Intersects(aDirtyRect);
 #ifdef DEBUG
   if (nsBlockFrame::gLamePaintMetrics) {
     aDrawnLines++;
   }
@@ -6648,18 +6648,18 @@ nsBlockFrame::BuildDisplayList(nsDisplay
       if (f->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT)
          BuildDisplayListForChild(aBuilder, f, aDirtyRect, aLists);
     }
   }
 
   aBuilder->MarkFramesForDisplayList(this, mFloats, aDirtyRect);
 
   // Prepare for text-overflow processing.
-  UniquePtr<TextOverflow> textOverflow(
-    TextOverflow::WillProcessLines(aBuilder, this));
+  Maybe<TextOverflow> textOverflow = TextOverflow::WillProcessLines(aBuilder,
+                                                                    this);
 
   // We'll collect our lines' display items here, & then append this to aLists.
   nsDisplayListCollection linesDisplayListCollection;
 
   // Don't use the line cursor if we might have a descendant placeholder ...
   // it might skip lines that contain placeholders but don't themselves
   // intersect with the dirty area.
   // In particular, we really want to check ShouldDescendIntoFrame()
@@ -6677,30 +6677,30 @@ nsBlockFrame::BuildDisplayList(nsDisplay
       nsRect lineArea = line->GetVisualOverflowArea();
       if (!lineArea.IsEmpty()) {
         // Because we have a cursor, the combinedArea.ys are non-decreasing.
         // Once we've passed aDirtyRect.YMost(), we can never see it again.
         if (lineArea.y >= aDirtyRect.YMost()) {
           break;
         }
         DisplayLine(aBuilder, lineArea, aDirtyRect, line, depth, drawnLines,
-                    linesDisplayListCollection, this, textOverflow.get());
+                    linesDisplayListCollection, this, textOverflow);
       }
     }
   } else {
     bool nonDecreasingYs = true;
     int32_t lineCount = 0;
     nscoord lastY = INT32_MIN;
     nscoord lastYMost = INT32_MIN;
     for (LineIterator line = LinesBegin();
          line != line_end;
          ++line) {
       nsRect lineArea = line->GetVisualOverflowArea();
       DisplayLine(aBuilder, lineArea, aDirtyRect, line, depth, drawnLines,
-                  linesDisplayListCollection, this, textOverflow.get());
+                  linesDisplayListCollection, this, textOverflow);
       if (!lineArea.IsEmpty()) {
         if (lineArea.y < lastY
             || lineArea.YMost() < lastYMost) {
           nonDecreasingYs = false;
         }
         lastY = lineArea.y;
         lastYMost = lineArea.YMost();
       }