Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp

Issue 1308273010: Adapt and reland old position sticky implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Store ancestor overflow layer on PaintLayer to compute before other dependent compositing inputs. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7 * Copyright (C) 2010 Google Inc. All rights reserved. 7 * Copyright (C) 2010 Google Inc. All rights reserved.
8 * 8 *
9 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public 10 * modify it under the terms of the GNU Library General Public
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 bool newStoleBodyBackground = toLayoutBoxModelObject(bodyLayout)->ba ckgroundStolenForBeingBody(style()); 275 bool newStoleBodyBackground = toLayoutBoxModelObject(bodyLayout)->ba ckgroundStolenForBeingBody(style());
276 bool oldStoleBodyBackground = oldStyle && toLayoutBoxModelObject(bod yLayout)->backgroundStolenForBeingBody(oldStyle); 276 bool oldStoleBodyBackground = oldStyle && toLayoutBoxModelObject(bod yLayout)->backgroundStolenForBeingBody(oldStyle);
277 if (newStoleBodyBackground != oldStoleBodyBackground 277 if (newStoleBodyBackground != oldStoleBodyBackground
278 && bodyLayout->style() && bodyLayout->style()->hasBackground()) { 278 && bodyLayout->style() && bodyLayout->style()->hasBackground()) {
279 bodyLayout->setShouldDoFullPaintInvalidation(); 279 bodyLayout->setShouldDoFullPaintInvalidation();
280 } 280 }
281 } 281 }
282 } 282 }
283 283
284 if (FrameView *frameView = view()->frameView()) { 284 if (FrameView *frameView = view()->frameView()) {
285 bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosit ion(); 285 bool newStyleIsViewportConstained = style()->position() == FixedPosition ;
286 bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportCo nstrainedPosition(); 286 bool oldStyleIsViewportConstrained = oldStyle && oldStyle->position() == FixedPosition;
287 bool newStyleIsSticky = style()->position() == StickyPosition;
288 bool oldStyleIsSticky = oldStyle && oldStyle->position() == StickyPositi on;
289
290 if (newStyleIsSticky != oldStyleIsSticky) {
291 if (newStyleIsSticky) {
292 frameView->addStickyPositionObject();
293 // During compositing inputs update we'll have the scroll
294 // ancestor without having to walk up the tree and can compute
295 // the sticky position constraints then.
296 if (layer())
297 layer()->setNeedsCompositingInputsUpdate();
298 } else {
299 // Clear sticky constraints for this element.
300 if (layer()) {
301 layer()->setNeedsCompositingInputsUpdate();
302 if (const PaintLayer* ancestorScrollingLayer = layer()->ance storOverflowLayer())
303 ancestorScrollingLayer->scrollableArea()->invalidateStic kyConstraintsFor(layer());
304 }
305 // This may get re-added to viewport constrained objects if the object went
306 // from sticky to fixed.
307 frameView->removeViewportConstrainedObject(this);
308 frameView->removeStickyPositionObject();
309 }
310 }
311
287 if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) { 312 if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
288 if (newStyleIsViewportConstained && layer()) 313 if (newStyleIsViewportConstained && layer())
289 frameView->addViewportConstrainedObject(this); 314 frameView->addViewportConstrainedObject(this);
290 else 315 else
291 frameView->removeViewportConstrainedObject(this); 316 frameView->removeViewportConstrainedObject(this);
292 } 317 }
293 } 318 }
294 } 319 }
295 320
296 void LayoutBoxModelObject::createLayer(PaintLayerType type) 321 void LayoutBoxModelObject::createLayer(PaintLayerType type)
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 { 374 {
350 if (TransformOperation* translate = style.translate()) { 375 if (TransformOperation* translate = style.translate()) {
351 if (translate->dependsOnBoxSize()) 376 if (translate->dependsOnBoxSize())
352 return true; 377 return true;
353 } 378 }
354 return style.transform().dependsOnBoxSize() 379 return style.transform().dependsOnBoxSize()
355 || (style.transformOriginX() != Length(50, Percent) && style.transformOr iginX().hasPercent()) 380 || (style.transformOriginX() != Length(50, Percent) && style.transformOr iginX().hasPercent())
356 || (style.transformOriginY() != Length(50, Percent) && style.transformOr iginY().hasPercent()); 381 || (style.transformOriginY() != Length(50, Percent) && style.transformOr iginY().hasPercent());
357 } 382 }
358 383
384 void LayoutBoxModelObject::invalidateScrollAncestorConstraints()
385 {
386 if (!layer())
387 return;
388 // This intentionally uses the stale ancestor overflow layer compositing
389 // input as if we have saved constraints for this layer they were saved
390 // in the previous frame.
391 DisableCompositingQueryAsserts disabler;
392 if (const PaintLayer* ancestorScrollingLayer = layer()->ancestorOverflowLaye r())
393 ancestorScrollingLayer->scrollableArea()->invalidateStickyConstraints();
394 }
395
359 void LayoutBoxModelObject::invalidateTreeIfNeeded(PaintInvalidationState& paintI nvalidationState) 396 void LayoutBoxModelObject::invalidateTreeIfNeeded(PaintInvalidationState& paintI nvalidationState)
360 { 397 {
361 ASSERT(!needsLayout()); 398 ASSERT(!needsLayout());
362 399
363 if (!shouldCheckForPaintInvalidation(paintInvalidationState)) 400 if (!shouldCheckForPaintInvalidation(paintInvalidationState))
364 return; 401 return;
365 402
366 bool establishesNewPaintInvalidationContainer = isPaintInvalidationContainer (); 403 bool establishesNewPaintInvalidationContainer = isPaintInvalidationContainer ();
367 const LayoutBoxModelObject& newPaintInvalidationContainer = establishesNewPa intInvalidationContainer ? *this : paintInvalidationState.paintInvalidationConta iner(); 404 const LayoutBoxModelObject& newPaintInvalidationContainer = establishesNewPa intInvalidationContainer ? *this : paintInvalidationState.paintInvalidationConta iner();
368 // FIXME: This assert should be re-enabled when we move paint invalidation t o after compositing update. crbug.com/360286 405 // FIXME: This assert should be re-enabled when we move paint invalidation t o after compositing update. crbug.com/360286
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 641
605 else if (!style()->bottom().isAuto() 642 else if (!style()->bottom().isAuto()
606 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight() 643 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
607 || !style()->bottom().hasPercent() 644 || !style()->bottom().hasPercent()
608 || containingBlock->stretchesToViewport())) 645 || containingBlock->stretchesToViewport()))
609 offset.expand(LayoutUnit(), -valueForLength(style()->bottom(), containin gBlock->availableHeight())); 646 offset.expand(LayoutUnit(), -valueForLength(style()->bottom(), containin gBlock->availableHeight()));
610 647
611 return offset; 648 return offset;
612 } 649 }
613 650
651 void LayoutBoxModelObject::updateStickyPositionConstraints(PaintLayer* ancestorO verflowLayer) const
652 {
653 const FloatSize constrainingSize = computeStickyConstrainingRect(ancestorOve rflowLayer).size();
654
655 PaintLayerScrollableArea* scrollableArea = ancestorOverflowLayer->scrollable Area();
656 StickyPositionScrollingConstraints constraints;
657 FloatSize skippedContainersOffset;
658 LayoutBlock* containingBlock = this->containingBlock();
659 // Skip anonymous containing blocks.
660 while (containingBlock->isAnonymous()) {
661 skippedContainersOffset += toFloatSize(FloatPoint(containingBlock->frame Rect().location()));
662 containingBlock = containingBlock->containingBlock();
663 }
664 LayoutBox* scrollAncestor = ancestorOverflowLayer->isRootLayer() ? nullptr : toLayoutBox(ancestorOverflowLayer->layoutObject());
665
666 LayoutRect containerContentRect = containingBlock->contentBoxRect();
667 LayoutUnit maxWidth = containingBlock->availableLogicalWidth();
668
669 // Sticky positioned element ignore any override logical width on the contai ning block (as they don't call
670 // containingBlockLogicalWidthForContent). It's unclear whether this is tota lly fine.
671 // Compute the container-relative area within which the sticky element is al lowed to move.
672 containerContentRect.contractEdges(
673 minimumValueForLength(style()->marginTop(), maxWidth),
674 minimumValueForLength(style()->marginRight(), maxWidth),
675 minimumValueForLength(style()->marginBottom(), maxWidth),
676 minimumValueForLength(style()->marginLeft(), maxWidth));
677
678 // Map to the scroll ancestor.
679 constraints.setScrollContainerRelativeContainingBlockRect(containingBlock->l ocalToAncestorQuad(FloatRect(containerContentRect), scrollAncestor).boundingBox( ));
680
681 FloatRect stickyBoxRect = isLayoutInline()
682 ? FloatRect(toLayoutInline(this)->linesBoundingBox())
683 : FloatRect(toLayoutBox(this)->frameRect());
684 FloatRect flippedStickyBoxRect = stickyBoxRect;
685 containingBlock->flipForWritingMode(flippedStickyBoxRect);
686 FloatPoint stickyLocation = flippedStickyBoxRect.location() + skippedContain ersOffset;
687
688 // TODO(flackr): Unfortunate to call localToAncestorQuad again, but we can't just offset from the previously computed rect if there are transforms.
689 // Map to the scroll ancestor.
690 FloatRect scrollContainerRelativeContainerFrame = containingBlock->localToAn cestorQuad(FloatRect(FloatPoint(), FloatSize(containingBlock->size())), scrollAn cestor).boundingBox();
691
692 // If the containing block is our scroll ancestor, its location will not inc lude the scroll offset which we need to include as
693 // part of the sticky box rect so we include it here.
694 if (containingBlock->hasOverflowClip()) {
695 FloatSize scrollOffset(toFloatSize(containingBlock->layer()->scrollableA rea()->adjustedScrollOffset()));
696 stickyLocation -= scrollOffset;
697 }
698
699 constraints.setScrollContainerRelativeStickyBoxRect(FloatRect(scrollContaine rRelativeContainerFrame.location() + toFloatSize(stickyLocation), flippedStickyB oxRect.size()));
700
701 // We skip the right or top sticky offset if there is not enough space to ho nor both the left/right or top/bottom offsets.
702 LayoutUnit horizontalOffsets = minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())) +
703 minimumValueForLength(style()->left(), LayoutUnit(constrainingSize.width ()));
704 bool skipRight = false;
705 bool skipLeft = false;
706 if (!style()->left().isAuto() && !style()->right().isAuto()) {
707 if (horizontalOffsets > containerContentRect.width()
708 || horizontalOffsets + containerContentRect.width() > constrainingSi ze.width()) {
709 skipRight = style()->isLeftToRightDirection();
710 skipLeft = !skipRight;
711 }
712 }
713
714 if (!style()->left().isAuto() && !skipLeft) {
715 constraints.setLeftOffset(minimumValueForLength(style()->left(), LayoutU nit(constrainingSize.width())));
716 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Left);
717 }
718
719 if (!style()->right().isAuto() && !skipRight) {
720 constraints.setRightOffset(minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())));
721 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Right);
722 }
723
724 bool skipBottom = false;
725 // TODO(flackr): Exclude top or bottom edge offset depending on the writing mode when related
726 // sections are fixed in spec: http://lists.w3.org/Archives/Public/www-style /2014May/0286.html
727 LayoutUnit verticalOffsets = minimumValueForLength(style()->top(), LayoutUni t(constrainingSize.height())) +
728 minimumValueForLength(style()->bottom(), LayoutUnit(constrainingSize.hei ght()));
729 if (!style()->top().isAuto() && !style()->bottom().isAuto()) {
730 if (verticalOffsets > containerContentRect.height()
731 || verticalOffsets + containerContentRect.height() > constrainingSiz e.height()) {
732 skipBottom = true;
733 }
734 }
735
736 if (!style()->top().isAuto()) {
737 constraints.setTopOffset(minimumValueForLength(style()->top(), LayoutUni t(constrainingSize.height())));
738 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Top);
739 }
740
741 if (!style()->bottom().isAuto() && !skipBottom) {
742 constraints.setBottomOffset(minimumValueForLength(style()->bottom(), Lay outUnit(constrainingSize.height())));
743 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Bottom);
744 }
745 scrollableArea->stickyConstraintsMap().set(layer(), constraints);
746 }
747
748 FloatRect LayoutBoxModelObject::computeStickyConstrainingRect(const PaintLayer* ancestorOverflowLayer) const
749 {
750 if (ancestorOverflowLayer->isRootLayer())
751 return view()->frameView()->visibleContentRect();
752
753 LayoutBox* enclosingClippingBox = toLayoutBox(ancestorOverflowLayer->layoutO bject());
754 FloatRect constrainingRect;
755 constrainingRect = FloatRect(enclosingClippingBox->overflowClipRect(LayoutPo int()));
756 constrainingRect.move(enclosingClippingBox->paddingLeft(), enclosingClipping Box->paddingTop());
757 constrainingRect.contract(FloatSize(enclosingClippingBox->paddingLeft() + en closingClippingBox->paddingRight(),
758 enclosingClippingBox->paddingTop() + enclosingClippingBox->paddingBottom ()));
759 return constrainingRect;
760 }
761
762 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const
763 {
764 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer();
765 // TODO: Force compositing input update if we ask for offset before composit ing inputs have been computed?
766 if (!ancestorOverflowLayer)
767 return LayoutSize();
768 FloatRect constrainingRect = computeStickyConstrainingRect(ancestorOverflowL ayer);
769 PaintLayerScrollableArea* scrollableArea = ancestorOverflowLayer->scrollable Area();
770
771 // The sticky offset is physical, so we can just return the delta computed i n absolute coords (though it may be wrong with transforms).
772 // TODO: Force compositing input update if we ask for offset with stale comp ositing inputs.
773 if (!scrollableArea->stickyConstraintsMap().contains(layer()))
774 return LayoutSize();
775 return LayoutSize(scrollableArea->stickyConstraintsMap().get(layer()).comput eStickyOffset(constrainingRect));
776 }
777
614 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeToOffsetParent(const L ayoutPoint& startPoint) const 778 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeToOffsetParent(const L ayoutPoint& startPoint) const
615 { 779 {
616 // If the element is the HTML body element or doesn't have a parent 780 // If the element is the HTML body element or doesn't have a parent
617 // return 0 and stop this algorithm. 781 // return 0 and stop this algorithm.
618 if (isBody() || !parent()) 782 if (isBody() || !parent())
619 return LayoutPoint(); 783 return LayoutPoint();
620 784
621 LayoutPoint referencePoint = startPoint; 785 LayoutPoint referencePoint = startPoint;
622 referencePoint.move(parent()->columnOffset(referencePoint)); 786 referencePoint.move(parent()->columnOffset(referencePoint));
623 787
624 // If the offsetParent of the element is null, or is the HTML body element, 788 // If the offsetParent of the element is null, or is the HTML body element,
625 // return the distance between the canvas origin and the left border edge 789 // return the distance between the canvas origin and the left border edge
626 // of the element and stop this algorithm. 790 // of the element and stop this algorithm.
627 Element* element = offsetParent(); 791 Element* element = offsetParent();
628 if (!element) 792 if (!element)
629 return referencePoint; 793 return referencePoint;
630 794
631 if (const LayoutBoxModelObject* offsetParent = element->layoutBoxModelObject ()) { 795 if (const LayoutBoxModelObject* offsetParent = element->layoutBoxModelObject ()) {
632 if (offsetParent->isBox() && !offsetParent->isBody()) 796 if (offsetParent->isBox() && !offsetParent->isBody())
633 referencePoint.move(-toLayoutBox(offsetParent)->borderLeft(), -toLay outBox(offsetParent)->borderTop()); 797 referencePoint.move(-toLayoutBox(offsetParent)->borderLeft(), -toLay outBox(offsetParent)->borderTop());
634 if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) { 798 if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) {
635 if (isInFlowPositioned()) 799 if (isInFlowPositioned())
636 referencePoint.move(relativePositionOffset()); 800 referencePoint.move(offsetForInFlowPosition());
637 801
638 LayoutObject* current; 802 LayoutObject* current;
639 for (current = parent(); current != offsetParent && current->parent( ); current = current->parent()) { 803 for (current = parent(); current != offsetParent && current->parent( ); current = current->parent()) {
640 // FIXME: What are we supposed to do inside SVG content? 804 // FIXME: What are we supposed to do inside SVG content?
641 if (!isOutOfFlowPositioned()) { 805 if (!isOutOfFlowPositioned()) {
642 if (current->isBox() && !current->isTableRow()) 806 if (current->isBox() && !current->isTableRow())
643 referencePoint.moveBy(toLayoutBox(current)->topLeftLocat ion()); 807 referencePoint.moveBy(toLayoutBox(current)->topLeftLocat ion());
644 referencePoint.move(current->parent()->columnOffset(referenc ePoint)); 808 referencePoint.move(current->parent()->columnOffset(referenc ePoint));
645 } 809 }
646 } 810 }
647 811
648 if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent ->isPositioned()) 812 if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent ->isPositioned())
649 referencePoint.moveBy(toLayoutBox(offsetParent)->topLeftLocation ()); 813 referencePoint.moveBy(toLayoutBox(offsetParent)->topLeftLocation ());
650 } 814 }
651 } 815 }
652 816
653 return referencePoint; 817 return referencePoint;
654 } 818 }
655 819
656 LayoutSize LayoutBoxModelObject::offsetForInFlowPosition() const 820 LayoutSize LayoutBoxModelObject::offsetForInFlowPosition() const
657 { 821 {
658 return isRelPositioned() ? relativePositionOffset() : LayoutSize(); 822 if (isRelPositioned())
823 return relativePositionOffset();
824
825 if (isStickyPositioned())
826 return stickyPositionOffset();
827
828 return LayoutSize();
659 } 829 }
660 830
661 LayoutUnit LayoutBoxModelObject::offsetLeft() const 831 LayoutUnit LayoutBoxModelObject::offsetLeft() const
662 { 832 {
663 // Note that LayoutInline and LayoutBox override this to pass a different 833 // Note that LayoutInline and LayoutBox override this to pass a different
664 // startPoint to adjustedPositionRelativeToOffsetParent. 834 // startPoint to adjustedPositionRelativeToOffsetParent.
665 return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x(); 835 return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x();
666 } 836 }
667 837
668 LayoutUnit LayoutBoxModelObject::offsetTop() const 838 LayoutUnit LayoutBoxModelObject::offsetTop() const
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 if (offsetDependsOnPoint) 1132 if (offsetDependsOnPoint)
963 flags |= IsNonUniform; 1133 flags |= IsNonUniform;
964 if (isFixedPos) 1134 if (isFixedPos)
965 flags |= IsFixedPosition; 1135 flags |= IsFixedPosition;
966 if (hasTransform) 1136 if (hasTransform)
967 flags |= HasTransform; 1137 flags |= HasTransform;
968 if (shouldUseTransformFromContainer(container)) { 1138 if (shouldUseTransformFromContainer(container)) {
969 TransformationMatrix t; 1139 TransformationMatrix t;
970 getTransformFromContainer(container, containerOffset, t); 1140 getTransformFromContainer(container, containerOffset, t);
971 t.translateRight(adjustmentForSkippedAncestor.width().toFloat(), adjustm entForSkippedAncestor.height().toFloat()); 1141 t.translateRight(adjustmentForSkippedAncestor.width().toFloat(), adjustm entForSkippedAncestor.height().toFloat());
972 geometryMap.push(this, t, flags); 1142 geometryMap.push(this, t, flags, LayoutSize());
973 } else { 1143 } else {
974 containerOffset += adjustmentForSkippedAncestor; 1144 containerOffset += adjustmentForSkippedAncestor;
975 geometryMap.push(this, containerOffset, flags); 1145 geometryMap.push(this, containerOffset, flags, LayoutSize());
976 } 1146 }
977 1147
978 return ancestorSkipped ? ancestorToStopAt : container; 1148 return ancestorSkipped ? ancestorToStopAt : container;
979 } 1149 }
980 1150
981 void LayoutBoxModelObject::moveChildTo(LayoutBoxModelObject* toBoxModelObject, L ayoutObject* child, LayoutObject* beforeChild, bool fullRemoveInsert) 1151 void LayoutBoxModelObject::moveChildTo(LayoutBoxModelObject* toBoxModelObject, L ayoutObject* child, LayoutObject* beforeChild, bool fullRemoveInsert)
982 { 1152 {
983 // We assume that callers have cleared their positioned objects list for chi ld moves (!fullRemoveInsert) so the 1153 // We assume that callers have cleared their positioned objects list for chi ld moves (!fullRemoveInsert) so the
984 // positioned layoutObject maps don't become stale. It would be too slow to do the map lookup on each call. 1154 // positioned layoutObject maps don't become stale. It would be too slow to do the map lookup on each call.
985 ASSERT(!fullRemoveInsert || !isLayoutBlock() || !toLayoutBlock(this)->hasPos itionedObjects()); 1155 ASSERT(!fullRemoveInsert || !isLayoutBlock() || !toLayoutBlock(this)->hasPos itionedObjects());
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 if (rootElementStyle->hasBackground()) 1217 if (rootElementStyle->hasBackground())
1048 return false; 1218 return false;
1049 1219
1050 if (node() != document().firstBodyElement()) 1220 if (node() != document().firstBodyElement())
1051 return false; 1221 return false;
1052 1222
1053 return true; 1223 return true;
1054 } 1224 }
1055 1225
1056 } // namespace blink 1226 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698