| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
reserved. |
| 3 * | 3 * |
| 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. | 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. |
| 5 * | 5 * |
| 6 * Other contributors: | 6 * Other contributors: |
| 7 * Robert O'Callahan <roc+@cs.cmu.edu> | 7 * Robert O'Callahan <roc+@cs.cmu.edu> |
| 8 * David Baron <dbaron@fas.harvard.edu> | 8 * David Baron <dbaron@fas.harvard.edu> |
| 9 * Christian Biesinger <cbiesinger@web.de> | 9 * Christian Biesinger <cbiesinger@web.de> |
| 10 * Randall Jesup <rjesup@wgate.com> | 10 * Randall Jesup <rjesup@wgate.com> |
| (...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 } | 734 } |
| 735 | 735 |
| 736 void RenderLayer::updateStackingNode() | 736 void RenderLayer::updateStackingNode() |
| 737 { | 737 { |
| 738 if (requiresStackingNode()) | 738 if (requiresStackingNode()) |
| 739 m_stackingNode = adoptPtr(new RenderLayerStackingNode(this)); | 739 m_stackingNode = adoptPtr(new RenderLayerStackingNode(this)); |
| 740 else | 740 else |
| 741 m_stackingNode = nullptr; | 741 m_stackingNode = nullptr; |
| 742 } | 742 } |
| 743 | 743 |
| 744 void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect) | |
| 745 { | |
| 746 TRACE_EVENT0("blink", "RenderLayer::paint"); | |
| 747 LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), LayoutSiz
e()); | |
| 748 paintLayer(context, paintingInfo, PaintContent); | |
| 749 } | |
| 750 | |
| 751 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLaye
r) | 744 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLaye
r) |
| 752 { | 745 { |
| 753 if (startLayer == endLayer) | 746 if (startLayer == endLayer) |
| 754 return true; | 747 return true; |
| 755 | 748 |
| 756 RenderView* view = startLayer->renderer()->view(); | 749 RenderView* view = startLayer->renderer()->view(); |
| 757 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock();
currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlo
ck()) { | 750 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock();
currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlo
ck()) { |
| 758 if (currentBlock->layer() == endLayer) | 751 if (currentBlock->layer() == endLayer) |
| 759 return true; | 752 return true; |
| 760 } | 753 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 788 } | 781 } |
| 789 } | 782 } |
| 790 | 783 |
| 791 void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintD
irtyRect, const ClipRect& clipRect) | 784 void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintD
irtyRect, const ClipRect& clipRect) |
| 792 { | 785 { |
| 793 if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius()) | 786 if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius()) |
| 794 return; | 787 return; |
| 795 context->restore(); | 788 context->restore(); |
| 796 } | 789 } |
| 797 | 790 |
| 798 void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo&
paintingInfo, PaintLayerFlags paintFlags) | |
| 799 { | |
| 800 // Non self-painting leaf layers don't need to be painted as their renderer(
) should properly paint itself. | |
| 801 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant()) | |
| 802 return; | |
| 803 | |
| 804 // If this layer is totally invisible then there is nothing to paint. | |
| 805 if (!renderer()->opacity()) | |
| 806 return; | |
| 807 | |
| 808 if (paintsWithTransform()) { | |
| 809 TransformationMatrix layerTransform = renderableTransform(); | |
| 810 // If the transform can't be inverted, then don't paint anything. | |
| 811 if (!layerTransform.isInvertible()) | |
| 812 return; | |
| 813 | |
| 814 // If we have a transparency layer enclosing us and we are the root of a
transform, then we need to establish the transparency | |
| 815 // layer from the parent now, assuming there is a parent | |
| 816 if (isTransparent()) { | |
| 817 if (parent()) | |
| 818 parent()->beginTransparencyLayers(context, paintingInfo.rootLaye
r, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation); | |
| 819 else | |
| 820 beginTransparencyLayers(context, paintingInfo.rootLayer, paintin
gInfo.paintDirtyRect, paintingInfo.subPixelAccumulation); | |
| 821 } | |
| 822 | |
| 823 // Make sure the parent's clip rects have been calculated. | |
| 824 ClipRect clipRect = paintingInfo.paintDirtyRect; | |
| 825 if (parent()) { | |
| 826 ClipRectsContext clipRectsContext(paintingInfo.rootLayer, PaintingCl
ipRects); | |
| 827 clipRect = clipper().backgroundClipRect(clipRectsContext); | |
| 828 clipRect.intersect(paintingInfo.paintDirtyRect); | |
| 829 | |
| 830 // Push the parent coordinate space's clip. | |
| 831 parent()->clipToRect(paintingInfo, context, clipRect); | |
| 832 } | |
| 833 | |
| 834 paintLayerByApplyingTransform(context, paintingInfo, paintFlags); | |
| 835 | |
| 836 // Restore the clip. | |
| 837 if (parent()) | |
| 838 parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect
); | |
| 839 | |
| 840 return; | |
| 841 } | |
| 842 | |
| 843 paintLayerContents(context, paintingInfo, paintFlags); | |
| 844 } | |
| 845 | |
| 846 void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
ngInfo& paintingInfo, PaintLayerFlags paintFlags) | |
| 847 { | |
| 848 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant()); | |
| 849 | |
| 850 float deviceScaleFactor = blink::deviceScaleFactor(renderer()->frame()); | |
| 851 context->setDeviceScaleFactor(deviceScaleFactor); | |
| 852 | |
| 853 GraphicsContext* transparencyLayerContext = context; | |
| 854 | |
| 855 m_stackingNode->updateLayerListsIfNeeded(); | |
| 856 | |
| 857 LayoutPoint offsetFromRoot; | |
| 858 convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); | |
| 859 | |
| 860 LayoutRect rootRelativeBounds; | |
| 861 bool rootRelativeBoundsComputed = false; | |
| 862 | |
| 863 // Apply clip-path to context. | |
| 864 GraphicsContextStateSaver clipStateSaver(*context, false); | |
| 865 RenderStyle* style = renderer()->style(); | |
| 866 | |
| 867 // Clip-path, like border radius, must not be applied to the contents of a c
omposited-scrolling container. | |
| 868 // It must, however, still be applied to the mask layer, so that the composi
tor can properly mask the | |
| 869 // scrolling contents and scrollbars. | |
| 870 if (renderer()->hasClipPath() && style) { | |
| 871 ASSERT(style->clipPath()); | |
| 872 if (style->clipPath()->type() == ClipPathOperation::SHAPE) { | |
| 873 ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style->c
lipPath()); | |
| 874 if (clipPath->isValid()) { | |
| 875 clipStateSaver.save(); | |
| 876 | |
| 877 if (!rootRelativeBoundsComputed) { | |
| 878 rootRelativeBounds = physicalBoundingBoxIncludingReflectionA
ndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); | |
| 879 rootRelativeBoundsComputed = true; | |
| 880 } | |
| 881 | |
| 882 context->clipPath(clipPath->path(rootRelativeBounds), clipPath->
windRule()); | |
| 883 } | |
| 884 } | |
| 885 } | |
| 886 | |
| 887 LayerPaintingInfo localPaintingInfo(paintingInfo); | |
| 888 FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilte
rs()); | |
| 889 | |
| 890 LayoutRect layerBounds; | |
| 891 // FIXME(sky): Remove foregroundRect. It's unused. | |
| 892 ClipRect backgroundRect, foregroundRect; | |
| 893 ClipRectsContext clipRectsContext(localPaintingInfo.rootLayer, PaintingClipR
ects, localPaintingInfo.subPixelAccumulation); | |
| 894 clipper().calculateRects(clipRectsContext, localPaintingInfo.paintDirtyRect, | |
| 895 layerBounds, backgroundRect, foregroundRect, | |
| 896 &offsetFromRoot); | |
| 897 | |
| 898 bool shouldPaintContent = isSelfPaintingLayer() && intersectsDamageRect(laye
rBounds, backgroundRect.rect(), localPaintingInfo.rootLayer, &offsetFromRoot); | |
| 899 | |
| 900 bool haveTransparency = isTransparent(); | |
| 901 | |
| 902 if (filterPainter.haveFilterEffect()) { | |
| 903 ASSERT(this->filterInfo()); | |
| 904 | |
| 905 if (!rootRelativeBoundsComputed) | |
| 906 rootRelativeBounds = physicalBoundingBoxIncludingReflectionAndStacki
ngChildren(paintingInfo.rootLayer, offsetFromRoot); | |
| 907 | |
| 908 if (filterPainter.prepareFilterEffect(this, rootRelativeBounds, painting
Info.paintDirtyRect)) { | |
| 909 // Rewire the old context to a memory buffer, so that we can capture
the contents of the layer. | |
| 910 // NOTE: We saved the old context in the "transparencyLayerContext"
local variable, to be able to start a transparency layer | |
| 911 // on the original context and avoid duplicating "beginFilterEffect"
after each transparency layer call. Also, note that | |
| 912 // beginTransparencyLayers will only create a single lazy transparen
cy layer, even though it is called twice in this method. | |
| 913 // With deferred filters, we don't need a separate context, but we d
o need to do transparency and clipping before starting | |
| 914 // filter processing. | |
| 915 // FIXME: when the legacy path is removed, remove the transparencyLa
yerContext as well. | |
| 916 if (haveTransparency) { | |
| 917 // If we have a filter and transparency, we have to eagerly star
t a transparency layer here, rather than risk a child layer lazily starts one af
ter filter processing. | |
| 918 beginTransparencyLayers(context, localPaintingInfo.rootLayer, pa
intingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation); | |
| 919 } | |
| 920 // We'll handle clipping to the dirty rect before filter rasterizati
on. | |
| 921 // Filter processing will automatically expand the clip rect and the
offscreen to accommodate any filter outsets. | |
| 922 // FIXME: It is incorrect to just clip to the damageRect here once m
ultiple fragments are involved. | |
| 923 clipToRect(localPaintingInfo, context, backgroundRect); | |
| 924 // Subsequent code should not clip to the dirty rect, since we've al
ready | |
| 925 // done it above, and doing it later will defeat the outsets. | |
| 926 localPaintingInfo.clipToDirtyRect = false; | |
| 927 | |
| 928 context = filterPainter.beginFilterEffect(context); | |
| 929 } | |
| 930 } | |
| 931 | |
| 932 LayoutPoint layerLocation = toPoint(layerBounds.location() - renderBoxLocati
on() + localPaintingInfo.subPixelAccumulation); | |
| 933 | |
| 934 if (shouldPaintContent) { | |
| 935 paintForeground(context, transparencyLayerContext, paintingInfo.paintDir
tyRect, haveTransparency, | |
| 936 localPaintingInfo, layerLocation, backgroundRect); | |
| 937 } | |
| 938 | |
| 939 paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, painting
Info, paintFlags); | |
| 940 | |
| 941 if (filterPainter.hasStartedFilterEffect()) { | |
| 942 context = filterPainter.applyFilterEffect(); | |
| 943 restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect,
backgroundRect); | |
| 944 } | |
| 945 | |
| 946 // Make sure that we now use the original transparency context. | |
| 947 ASSERT(transparencyLayerContext == context); | |
| 948 | |
| 949 // End our transparency layer | |
| 950 if (haveTransparency && m_usedTransparency) { | |
| 951 context->endLayer(); | |
| 952 context->restore(); | |
| 953 m_usedTransparency = false; | |
| 954 } | |
| 955 } | |
| 956 | |
| 957 void RenderLayer::paintLayerByApplyingTransform(GraphicsContext* context, const
LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, const LayoutPoint&
translationOffset) | |
| 958 { | |
| 959 // This involves subtracting out the position of the layer in our current co
ordinate space, but preserving | |
| 960 // the accumulated error for sub-pixel layout. | |
| 961 LayoutPoint delta; | |
| 962 convertToLayerCoords(paintingInfo.rootLayer, delta); | |
| 963 delta.moveBy(translationOffset); | |
| 964 TransformationMatrix transform(renderableTransform()); | |
| 965 IntPoint roundedDelta = roundedIntPoint(delta); | |
| 966 transform.translateRight(roundedDelta.x(), roundedDelta.y()); | |
| 967 LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation
+ (delta - roundedDelta); | |
| 968 | |
| 969 // Apply the transform. | |
| 970 GraphicsContextStateSaver stateSaver(*context, false); | |
| 971 if (!transform.isIdentity()) { | |
| 972 stateSaver.save(); | |
| 973 context->concatCTM(transform.toAffineTransform()); | |
| 974 } | |
| 975 | |
| 976 // Now do a paint with the root layer shifted to be us. | |
| 977 LayerPaintingInfo transformedPaintingInfo(this, enclosingIntRect(transform.i
nverse().mapRect(paintingInfo.paintDirtyRect)), | |
| 978 adjustedSubPixelAccumulation); | |
| 979 paintLayerContents(context, transformedPaintingInfo, paintFlags); | |
| 980 } | |
| 981 | |
| 982 void RenderLayer::paintChildren(unsigned childrenToVisit, GraphicsContext* conte
xt, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) | |
| 983 { | |
| 984 if (!hasSelfPaintingLayerDescendant()) | |
| 985 return; | |
| 986 | |
| 987 #if ENABLE(ASSERT) | |
| 988 LayerListMutationDetector mutationChecker(m_stackingNode.get()); | |
| 989 #endif | |
| 990 | |
| 991 RenderLayerStackingNodeIterator iterator(*m_stackingNode, childrenToVisit); | |
| 992 while (RenderLayerStackingNode* child = iterator.next()) { | |
| 993 child->layer()->paintLayer(context, paintingInfo, paintFlags); | |
| 994 } | |
| 995 } | |
| 996 | |
| 997 void RenderLayer::paintForeground(GraphicsContext* context, GraphicsContext* tra
nsparencyLayerContext, | |
| 998 const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const L
ayerPaintingInfo& localPaintingInfo, | |
| 999 LayoutPoint& layerLocation, ClipRect& layerForegroundRect) | |
| 1000 { | |
| 1001 bool foregroundRectIsEmpty = layerForegroundRect.isEmpty(); | |
| 1002 | |
| 1003 // Begin transparency if we have something to paint. | |
| 1004 if (haveTransparency && !foregroundRectIsEmpty) | |
| 1005 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.root
Layer, transparencyPaintDirtyRect, localPaintingInfo.subPixelAccumulation); | |
| 1006 | |
| 1007 // Optimize clipping for the single fragment case. | |
| 1008 bool shouldClip = localPaintingInfo.clipToDirtyRect && !foregroundRectIsEmpt
y; | |
| 1009 if (shouldClip) | |
| 1010 clipToRect(localPaintingInfo, context, layerForegroundRect); | |
| 1011 | |
| 1012 // TODO(ojan): We probably should early return at the beginning of this func
tion | |
| 1013 // if the rect is empty. | |
| 1014 if (!foregroundRectIsEmpty) { | |
| 1015 PaintInfo paintInfo(context, pixelSnappedIntRect(layerForegroundRect.rec
t()), localPaintingInfo.rootLayer->renderer()); | |
| 1016 renderer()->paint(paintInfo, layerLocation); | |
| 1017 } | |
| 1018 | |
| 1019 if (shouldClip) | |
| 1020 restoreClip(context, localPaintingInfo.paintDirtyRect, layerForegroundRe
ct); | |
| 1021 } | |
| 1022 | |
| 1023 static inline LayoutRect frameVisibleRect(RenderObject* renderer) | 791 static inline LayoutRect frameVisibleRect(RenderObject* renderer) |
| 1024 { | 792 { |
| 1025 FrameView* frameView = renderer->document().view(); | 793 FrameView* frameView = renderer->document().view(); |
| 1026 if (!frameView) | 794 if (!frameView) |
| 1027 return LayoutRect(); | 795 return LayoutRect(); |
| 1028 | 796 |
| 1029 return frameView->visibleContentRect(); | 797 return frameView->visibleContentRect(); |
| 1030 } | 798 } |
| 1031 | 799 |
| 1032 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result) | 800 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result) |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1668 } | 1436 } |
| 1669 } | 1437 } |
| 1670 | 1438 |
| 1671 void showLayerTree(const blink::RenderObject* renderer) | 1439 void showLayerTree(const blink::RenderObject* renderer) |
| 1672 { | 1440 { |
| 1673 if (!renderer) | 1441 if (!renderer) |
| 1674 return; | 1442 return; |
| 1675 showLayerTree(renderer->enclosingLayer()); | 1443 showLayerTree(renderer->enclosingLayer()); |
| 1676 } | 1444 } |
| 1677 #endif | 1445 #endif |
| OLD | NEW |