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 |