Title: [149597] trunk/Source/WebCore
Revision
149597
Author
[email protected]
Date
2013-05-06 08:23:10 -0700 (Mon, 06 May 2013)

Log Message

Improve the performance of RenderDeprecatedFlexibleBox.
https://bugs.webkit.org/show_bug.cgi?id=115543.

Optimize deprecated flexible box layout to be much faster. This patch implements
the following optimizations in the deprecated flexible box:
        
(1) Defer repainting of children until they have been placed into their final
positions. This is done by collecting all of the old frame rects into a Vector
and then doing a walk after layout is finished to repaint any of the children if
they moved from that position. This code matches the new RenderFlexibleBox's system
for repainting moved children.
        
(2) Implement support for layout deltas. We keep a Vector of layout deltas for each
child as we shift them around, and every time we lay a child out again, we apply that
child's current layout delta to avoid repainting at the new position. RenderFlexibleBox
does not have support for layout deltas yet, so we'll need to implement this in the
new flexbox code as well.
        
(3) Optimize flexible objects to avoid laying them out unflexed. When laying out
horizontal and vertical boxes now, we lay out the inflexible items first. We then
check to see if the inflexible extent of all those children has changed.
        
If this extent didn't change, and the flexible items either don't need layout or there
is only one flexing item, then we avoid laying out the item in an unflexed state
and simply lay out one time with the flex applied instead. The new RenderFlexibleBox
does not have these optimizations and would benefit from them in the block-direction box
case (it uses preferred logical widths in the inline-direction box case, and so avoided
layouts in that direction already).
        
Reviewed by Beth Dakin.

* rendering/RenderDeprecatedFlexibleBox.cpp:
(WebCore::appendChildFrameRects):
Cache all of the old child frame rects so that we can compare them with the final
positions for repaintDuringLayoutIfMoved. This collection is identical to what the
new flexbox code does.
        
(WebCore::appendChildLayoutDeltas):
Build up a vector that tracks layout deltas. We apply these layout deltas every
time we lay out a child so that any repainting done during layout ignores our shifted
position and just keeps using the old position. The new flexbox does not have this
code yet.

(WebCore::repaintChildrenDuringLayoutIfMoved):
After final placement of children, we do a single pass over all of the children and
repaint them if they shifted their positions. This matches how the new flexbox works.
        
(WebCore::RenderDeprecatedFlexibleBox::layoutBlock):
Collect the frame rects and layout deltas, and defer repainting of children to the
end of layout.
        
(WebCore::gatherFlexChildrenInfo):
Don't clear flex overrides when gathering flex information. Add additional information
such as the number of flexing items so that we can use it to optimize flex layout.
        
(WebCore::layoutChildIfNeededApplyingDelta):
A helper for applying your current layout delta for a child when laying that child out.
        
(WebCore::RenderDeprecatedFlexibleBox::layoutHorizontalBox):
(WebCore::RenderDeprecatedFlexibleBox::layoutVerticalBox):
Both methods are patched to aggregate layout deltas as children move around during
the multiple passes. In addition we now optimize layout in a couple of cases, such
as when the inflexible space stays the same (thus giving a flexible object the
same amount of available space, avoiding a need to lay out unflexed first).
        
(WebCore::RenderDeprecatedFlexibleBox::placeChild):
Patched to add to our cached layout delta for that child when we do a movement.

* rendering/RenderDeprecatedFlexibleBox.h:
Changes to method signatures.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (149596 => 149597)


--- trunk/Source/WebCore/ChangeLog	2013-05-06 13:54:58 UTC (rev 149596)
+++ trunk/Source/WebCore/ChangeLog	2013-05-06 15:23:10 UTC (rev 149597)
@@ -1,3 +1,76 @@
+2013-05-02  David Hyatt  <[email protected]>
+
+        Improve the performance of RenderDeprecatedFlexibleBox.
+        https://bugs.webkit.org/show_bug.cgi?id=115543.
+
+        Optimize deprecated flexible box layout to be much faster. This patch implements
+        the following optimizations in the deprecated flexible box:
+        
+        (1) Defer repainting of children until they have been placed into their final
+        positions. This is done by collecting all of the old frame rects into a Vector
+        and then doing a walk after layout is finished to repaint any of the children if
+        they moved from that position. This code matches the new RenderFlexibleBox's system
+        for repainting moved children.
+        
+        (2) Implement support for layout deltas. We keep a Vector of layout deltas for each
+        child as we shift them around, and every time we lay a child out again, we apply that
+        child's current layout delta to avoid repainting at the new position. RenderFlexibleBox
+        does not have support for layout deltas yet, so we'll need to implement this in the
+        new flexbox code as well.
+        
+        (3) Optimize flexible objects to avoid laying them out unflexed. When laying out
+        horizontal and vertical boxes now, we lay out the inflexible items first. We then
+        check to see if the inflexible extent of all those children has changed.
+        
+        If this extent didn't change, and the flexible items either don't need layout or there
+        is only one flexing item, then we avoid laying out the item in an unflexed state
+        and simply lay out one time with the flex applied instead. The new RenderFlexibleBox
+        does not have these optimizations and would benefit from them in the block-direction box
+        case (it uses preferred logical widths in the inline-direction box case, and so avoided
+        layouts in that direction already).
+        
+        Reviewed by Beth Dakin.
+
+        * rendering/RenderDeprecatedFlexibleBox.cpp:
+        (WebCore::appendChildFrameRects):
+        Cache all of the old child frame rects so that we can compare them with the final
+        positions for repaintDuringLayoutIfMoved. This collection is identical to what the
+        new flexbox code does.
+        
+        (WebCore::appendChildLayoutDeltas):
+        Build up a vector that tracks layout deltas. We apply these layout deltas every
+        time we lay out a child so that any repainting done during layout ignores our shifted
+        position and just keeps using the old position. The new flexbox does not have this
+        code yet.
+
+        (WebCore::repaintChildrenDuringLayoutIfMoved):
+        After final placement of children, we do a single pass over all of the children and
+        repaint them if they shifted their positions. This matches how the new flexbox works.
+        
+        (WebCore::RenderDeprecatedFlexibleBox::layoutBlock):
+        Collect the frame rects and layout deltas, and defer repainting of children to the
+        end of layout.
+        
+        (WebCore::gatherFlexChildrenInfo):
+        Don't clear flex overrides when gathering flex information. Add additional information
+        such as the number of flexing items so that we can use it to optimize flex layout.
+        
+        (WebCore::layoutChildIfNeededApplyingDelta):
+        A helper for applying your current layout delta for a child when laying that child out.
+        
+        (WebCore::RenderDeprecatedFlexibleBox::layoutHorizontalBox):
+        (WebCore::RenderDeprecatedFlexibleBox::layoutVerticalBox):
+        Both methods are patched to aggregate layout deltas as children move around during
+        the multiple passes. In addition we now optimize layout in a couple of cases, such
+        as when the inflexible space stays the same (thus giving a flexible object the
+        same amount of available space, avoiding a need to lay out unflexed first).
+        
+        (WebCore::RenderDeprecatedFlexibleBox::placeChild):
+        Patched to add to our cached layout delta for that child when we do a movement.
+
+        * rendering/RenderDeprecatedFlexibleBox.h:
+        Changes to method signatures.
+
 2013-05-04  Andy Estes  <[email protected]>
 
         REGRESSION (r125592): Reproducible crash in DOMWindow::open when a delegate closes the new window in decidePolicyForNavigationAction

Modified: trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp (149596 => 149597)


--- trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp	2013-05-06 13:54:58 UTC (rev 149596)
+++ trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp	2013-05-06 15:23:10 UTC (rev 149597)
@@ -250,6 +250,47 @@
     setPreferredLogicalWidthsDirty(false);
 }
 
+// Use an inline capacity of 8, since flexbox containers usually have less than 8 children.
+typedef Vector<LayoutRect, 8> ChildFrameRects;
+typedef Vector<LayoutSize, 8> ChildLayoutDeltas;
+
+static void appendChildFrameRects(RenderDeprecatedFlexibleBox* box, ChildFrameRects& childFrameRects)
+{
+    FlexBoxIterator iterator(box);
+    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        if (!child->isOutOfFlowPositioned())
+            childFrameRects.append(child->frameRect());
+    }
+}
+
+static void appendChildLayoutDeltas(RenderDeprecatedFlexibleBox* box, ChildLayoutDeltas& childLayoutDeltas)
+{
+    FlexBoxIterator iterator(box);
+    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        if (!child->isOutOfFlowPositioned())
+            childLayoutDeltas.append(LayoutSize());
+    }
+}
+
+static void repaintChildrenDuringLayoutIfMoved(RenderDeprecatedFlexibleBox* box, const ChildFrameRects& oldChildRects)
+{
+    size_t childIndex = 0;
+    FlexBoxIterator iterator(box);
+    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        if (child->isOutOfFlowPositioned())
+            continue;
+
+        // If the child moved, we have to repaint it as well as any floating/positioned
+        // descendants. An exception is if we need a layout. In this case, we know we're going to
+        // repaint ourselves (and the child) anyway.
+        if (!box->selfNeedsLayout() && child->checkForRepaintDuringLayout())
+            child->repaintDuringLayoutIfMoved(oldChildRects[childIndex]);
+        
+        ++childIndex;
+    }
+    ASSERT(childIndex == oldChildRects.size());
+}
+
 void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
 {
     ASSERT(needsLayout());
@@ -283,11 +324,21 @@
 
     initMaxMarginValues();
 
+#if !ASSERT_DISABLED
+    LayoutSize oldLayoutDelta = view()->layoutDelta();
+#endif
+
+    ChildFrameRects oldChildRects;
+    appendChildFrameRects(this, oldChildRects);
+    
     if (isHorizontal())
         layoutHorizontalBox(relayoutChildren);
     else
         layoutVerticalBox(relayoutChildren);
 
+    repaintChildrenDuringLayoutIfMoved(this, oldChildRects);
+    ASSERT(view()->layoutDeltaMatches(oldLayoutDelta));
+
     LayoutUnit oldClientAfterEdge = clientLogicalBottom();
     updateLogicalHeight();
 
@@ -337,17 +388,19 @@
 }
 
 // The first walk over our kids is to find out if we have any flexible children.
-static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, bool relayoutChildren, unsigned int& highestFlexGroup, unsigned int& lowestFlexGroup, bool& haveFlex)
+static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, unsigned& highestFlexGroup, unsigned& lowestFlexGroup, bool& flexibleChildrenNeedLayout, unsigned& flexibleChildCount)
 {
     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
         // Check to see if this child flexes.
-        if (!childDoesNotAffectWidthOrFlexing(child) && child->style()->boxFlex() > 0.0f) {
+        if (childDoesNotAffectWidthOrFlexing(child))
+            continue;
+        
+        if (child->style()->boxFlex() > 0.0f) {
             // We always have to lay out flexible objects again, since the flex distribution
             // may have changed, and we need to reallocate space.
-            child->clearOverrideSize();
-            if (!relayoutChildren)
-                child->setChildNeedsLayout(true, MarkOnlyThis);
-            haveFlex = true;
+            flexibleChildCount++;
+            if (child->needsLayout())
+                flexibleChildrenNeedLayout = true;
             unsigned int flexGroup = child->style()->boxFlexGroup();
             if (lowestFlexGroup == 0)
                 lowestFlexGroup = flexGroup;
@@ -359,6 +412,16 @@
     }
 }
 
+static void layoutChildIfNeededApplyingDelta(RenderBox* child, const LayoutSize& layoutDelta)
+{
+    if (!child->needsLayout())
+        return;
+    
+    child->view()->addLayoutDelta(layoutDelta);
+    child->layoutIfNeeded();
+    child->view()->addLayoutDelta(-layoutDelta);
+}
+
 void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
 {
     LayoutUnit toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
@@ -369,44 +432,73 @@
 
     LayoutUnit remainingSpace = 0;
 
-
     FlexBoxIterator iterator(this);
     unsigned int highestFlexGroup = 0;
     unsigned int lowestFlexGroup = 0;
-    bool haveFlex = false, flexingChildren = false;
-    gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
+    bool flexingChildren = false;
+    bool flexibleChildrenNeedLayout = relayoutChildren;
+    unsigned flexibleChildCount = 0;
+    gatherFlexChildrenInfo(iterator, highestFlexGroup, lowestFlexGroup, flexibleChildrenNeedLayout, flexibleChildCount);
+    bool haveFlex = flexibleChildCount > 0;
+    bool inflexibleObjectsExtentChanged = false;
+    bool doingInflexibleLayoutPass = true;
+    bool clearingFlexibleItemsOverridePass = false;
 
     RenderBlock::startDelayUpdateScrollInfo();
 
+    ChildLayoutDeltas childLayoutDeltas;
+    appendChildLayoutDeltas(this, childLayoutDeltas);
+
     // We do 2 passes.  The first pass is simply to lay everyone out at
-    // their preferred widths.  The second pass handles flexing the children.
+    // their preferred widths. The subsequent passes handle flexing the children.
+    // The first pass skips flexible objects completely.
     do {
         // Reset our height.
         setHeight(yPos);
 
         xPos = borderLeft() + paddingLeft();
 
+        size_t childIndex = 0;
+
         // Our first pass is done without flexing.  We simply lay the children
         // out within the box.  We have to do a layout first in order to determine
         // our box's intrinsic height.
         LayoutUnit maxAscent = 0, maxDescent = 0;
         for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
-            // make sure we relayout children if we need it.
             if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))
                 child->setChildNeedsLayout(true, MarkOnlyThis);
 
             if (child->isOutOfFlowPositioned())
                 continue;
+            
+            LayoutSize& childLayoutDelta = childLayoutDeltas[childIndex++];
+            
+            // Just skip the flexible items initially.
+            if (child->style()->boxFlex() && doingInflexibleLayoutPass)
+                continue;
 
             // Compute the child's vertical margins.
             child->computeAndSetBlockDirectionMargins(this);
 
             if (!child->needsLayout())
                 child->markForPaginationRelayoutIfNeeded();
+            
+            if (clearingFlexibleItemsOverridePass && child->style()->boxFlex()) {
+                child->clearOverrideSize();
+                child->setNeedsLayout(true, MarkOnlyThis);
+            }
 
+            LayoutUnit oldChildWidth = child->width();
+            
+            // Apply the child's current layout delta.
+            layoutChildIfNeededApplyingDelta(child, childLayoutDelta);
+            
             // Now do the layout.
-            child->layoutIfNeeded();
+            layoutChildIfNeededApplyingDelta(child, childLayoutDelta);
 
+            if (doingInflexibleLayoutPass && child->width() != oldChildWidth)
+                inflexibleObjectsExtentChanged = true;
+
             // Update our height and overflow height.
             if (style()->boxAlign() == BBASELINE) {
                 LayoutUnit ascent = child->firstLineBoxBaseline();
@@ -427,6 +519,7 @@
             else
                 setHeight(max(height(), yPos + child->height() + child->marginHeight()));
         }
+        ASSERT(childIndex == childLayoutDeltas.size());
 
         if (!iterator.first() && hasLineIfEmpty())
             setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
@@ -441,6 +534,7 @@
             heightSpecified = true;
 
         // Now that our height is actually known, we can place our boxes.
+        childIndex = 0;
         m_stretchingChildren = (style()->boxAlign() == BSTRETCH);
         for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
             if (child->isOutOfFlowPositioned()) {
@@ -455,14 +549,19 @@
                 continue;
             }
             
+            LayoutSize& childLayoutDelta = childLayoutDeltas[childIndex++];
+            
+            // Just skip the flexible items initially.
+            if (child->style()->boxFlex() && doingInflexibleLayoutPass)
+                continue;
+                
             if (child->style()->visibility() == COLLAPSE) {
                 // visibility: collapsed children do not participate in our positioning.
-                // But we need to lay them down.
-                child->layoutIfNeeded();
+                // But we need to lay them out.
+                layoutChildIfNeededApplyingDelta(child, childLayoutDelta);
                 continue;
             }
 
-
             // We need to see if this child's height has changed, since we make block elements
             // fill the height of a containing box by default.
             // Now do a layout.
@@ -474,7 +573,7 @@
             if (!child->needsLayout())
                 child->markForPaginationRelayoutIfNeeded();
 
-            child->layoutIfNeeded();
+            layoutChildIfNeededApplyingDelta(child, childLayoutDelta);
 
             // We can place the child now, using our value of box-align.
             xPos += child->marginLeft();
@@ -499,13 +598,23 @@
                     break;
             }
 
-            placeChild(child, LayoutPoint(xPos, childY));
+            placeChild(child, LayoutPoint(xPos, childY), &childLayoutDelta);
 
             xPos += child->width() + child->marginRight();
         }
+        ASSERT(childIndex == childLayoutDeltas.size());
 
         remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos;
 
+        clearingFlexibleItemsOverridePass = false;
+    
+        if (doingInflexibleLayoutPass) {
+            doingInflexibleLayoutPass = false;
+            if (inflexibleObjectsExtentChanged || (flexibleChildrenNeedLayout && flexibleChildCount > 1))
+                clearingFlexibleItemsOverridePass = true;
+            continue;
+        }
+
         m_stretchingChildren = false;
         if (flexingChildren)
             haveFlex = false; // We're done.
@@ -660,8 +769,14 @@
     FlexBoxIterator iterator(this);
     unsigned int highestFlexGroup = 0;
     unsigned int lowestFlexGroup = 0;
-    bool haveFlex = false, flexingChildren = false;
-    gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
+    bool flexingChildren = false;
+    bool flexibleChildrenNeedLayout = relayoutChildren;
+    unsigned flexibleChildCount = 0;
+    gatherFlexChildrenInfo(iterator, highestFlexGroup, lowestFlexGroup, flexibleChildrenNeedLayout, flexibleChildCount);
+    bool haveFlex = flexibleChildCount > 0;
+    bool inflexibleObjectsExtentChanged = false;
+    bool doingInflexibleLayoutPass = true;
+    bool clearingFlexibleItemsOverridePass = false;
 
     // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of
     // mainstream block layout); this is not really part of the XUL box model.
@@ -671,6 +786,9 @@
 
     RenderBlock::startDelayUpdateScrollInfo();
 
+    ChildLayoutDeltas childLayoutDeltas;
+    appendChildLayoutDeltas(this, childLayoutDeltas);
+
     // We do 2 passes.  The first pass is simply to lay everyone out at
     // their preferred widths.  The second pass handles flexing the children.
     // Our first pass is done without flexing.  We simply lay the children
@@ -679,6 +797,7 @@
         setHeight(borderTop() + paddingTop());
         LayoutUnit minHeight = height() + toAdd;
 
+        size_t childIndex = 0;
         for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
             // Make sure we relayout children if we need it.
             if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))))
@@ -696,10 +815,15 @@
                 continue;
             }
             
+            LayoutSize& childLayoutDelta = childLayoutDeltas[childIndex++];
+            
+            if (child->style()->boxFlex() && doingInflexibleLayoutPass)
+                continue;
+
             if (child->style()->visibility() == COLLAPSE) {
                 // visibility: collapsed children do not participate in our positioning.
                 // But we need to lay them down.
-                child->layoutIfNeeded();
+                layoutChildIfNeededApplyingDelta(child, childLayoutDelta);
                 continue;
             }
 
@@ -712,9 +836,19 @@
             if (!child->needsLayout())
                 child->markForPaginationRelayoutIfNeeded();
 
+            if (clearingFlexibleItemsOverridePass && child->style()->boxFlex()) {
+                child->clearOverrideSize();
+                child->setNeedsLayout(true, MarkOnlyThis);
+            }
+
+            LayoutUnit oldChildHeight = child->height();
+
             // Now do a layout.
-            child->layoutIfNeeded();
+            layoutChildIfNeededApplyingDelta(child, childLayoutDelta);
 
+            if (doingInflexibleLayoutPass && child->height() != oldChildHeight)
+                inflexibleObjectsExtentChanged = true;
+
             // We can place the child now, using our value of box-align.
             LayoutUnit childX = borderLeft() + paddingLeft();
             switch (style()->boxAlign()) {
@@ -737,9 +871,10 @@
             }
 
             // Place the child.
-            placeChild(child, LayoutPoint(childX, height()));
+            placeChild(child, LayoutPoint(childX, height()), &childLayoutDelta);
             setHeight(height() + child->height() + child->marginBottom());
         }
+        ASSERT(childIndex == childLayoutDeltas.size());
 
         yPos = height();
 
@@ -761,6 +896,15 @@
 
         remainingSpace = borderTop() + paddingTop() + contentHeight() - yPos;
 
+        clearingFlexibleItemsOverridePass = false;
+
+        if (doingInflexibleLayoutPass) {
+            doingInflexibleLayoutPass = false;
+            if (inflexibleObjectsExtentChanged || (flexibleChildrenNeedLayout && flexibleChildCount > 1))
+                clearingFlexibleItemsOverridePass = true;
+            continue;
+        }
+
         if (flexingChildren)
             haveFlex = false; // We're done.
         else if (haveFlex) {
@@ -1016,18 +1160,12 @@
     }
 }
 
-void RenderDeprecatedFlexibleBox::placeChild(RenderBox* child, const LayoutPoint& location)
+void RenderDeprecatedFlexibleBox::placeChild(RenderBox* child, const LayoutPoint& location, LayoutSize* childLayoutDelta)
 {
-    LayoutRect oldRect = child->frameRect();
-
-    // Place the child.
+    // Place the child and track the layout delta so we can apply it if we do another layout.
+    if (childLayoutDelta)
+        *childLayoutDelta += LayoutSize(child->x() - location.x(), child->y() - location.y());
     child->setLocation(location);
-
-    // If the child moved, we have to repaint it as well as any floating/positioned
-    // descendants.  An exception is if we need a layout.  In this case, we know we're going to
-    // repaint ourselves (and the child) anyway.
-    if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
-        child->repaintDuringLayoutIfMoved(oldRect);
 }
 
 LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsigned int group)

Modified: trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h (149596 => 149597)


--- trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h	2013-05-06 13:54:58 UTC (rev 149596)
+++ trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h	2013-05-06 15:23:10 UTC (rev 149597)
@@ -49,7 +49,7 @@
     virtual bool isStretchingChildren() const { return m_stretchingChildren; }
     virtual bool canCollapseAnonymousBlockChild() const OVERRIDE { return false; }
 
-    void placeChild(RenderBox* child, const LayoutPoint& location);
+    void placeChild(RenderBox* child, const LayoutPoint& location, LayoutSize* childLayoutDelta = 0);
 
 protected:
     virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to