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 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1035 | 1035 |
1036 context->clipPath(clipPath->path(rootRelativeBounds), clipPath-> windRule()); | 1036 context->clipPath(clipPath->path(rootRelativeBounds), clipPath-> windRule()); |
1037 } | 1037 } |
1038 } | 1038 } |
1039 } | 1039 } |
1040 | 1040 |
1041 LayerPaintingInfo localPaintingInfo(paintingInfo); | 1041 LayerPaintingInfo localPaintingInfo(paintingInfo); |
1042 bool deferredFiltersEnabled = renderer()->document().settings()->deferredFil tersEnabled(); | 1042 bool deferredFiltersEnabled = renderer()->document().settings()->deferredFil tersEnabled(); |
1043 FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilte rs()); | 1043 FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilte rs()); |
1044 | 1044 |
1045 // FIXME(sky): There's only one fragment. Get rid of the vector. | |
1045 LayerFragments layerFragments; | 1046 LayerFragments layerFragments; |
1046 // Collect the fragments. This will compute the clip rectangles and paint of fsets for each layer fragment, as well as whether or not the content of each | 1047 LayerFragment fragment; |
1047 // fragment should paint. | 1048 ClipRectsContext clipRectsContext(localPaintingInfo.rootLayer, PaintingClipR ects, localPaintingInfo.subPixelAccumulation); |
1048 collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingI nfo.paintDirtyRect, | 1049 clipper().calculateRects(clipRectsContext, localPaintingInfo.paintDirtyRect, |
1049 PaintingClipRects, &offsetFromRoot, localPaintingInfo.subPixelAccumulati on); | 1050 fragment.layerBounds, fragment.backgroundRect, fragment.foregroundRect, fragment.outlineRect, |
1051 &offsetFromRoot); | |
1052 layerFragments.append(fragment); | |
1050 | 1053 |
1051 bool isPaintingOverlayScrollbars = paintFlags == PaintOverlayScrollbars; | 1054 bool isPaintingOverlayScrollbars = paintFlags == PaintOverlayScrollbars; |
1052 bool shouldPaintContent = isSelfPaintingLayer() && !isPaintingOverlayScrollb ars; | 1055 bool shouldPaintContent = isSelfPaintingLayer() && !isPaintingOverlayScrollb ars; |
1053 updatePaintingInfoForFragments(layerFragments, localPaintingInfo, shouldPain tContent, &offsetFromRoot); | 1056 updatePaintingInfoForFragments(layerFragments, localPaintingInfo, shouldPain tContent, &offsetFromRoot); |
1054 | 1057 |
1055 bool haveTransparency = isTransparent(); | 1058 bool haveTransparency = isTransparent(); |
1056 | 1059 |
1057 if (filterPainter.haveFilterEffect()) { | 1060 if (filterPainter.haveFilterEffect()) { |
1058 ASSERT(this->filterInfo()); | 1061 ASSERT(this->filterInfo()); |
1059 | 1062 |
(...skipping 10 matching lines...) Expand all Loading... | |
1070 // filter processing. | 1073 // filter processing. |
1071 // FIXME: when the legacy path is removed, remove the transparencyLa yerContext as well. | 1074 // FIXME: when the legacy path is removed, remove the transparencyLa yerContext as well. |
1072 if (deferredFiltersEnabled) { | 1075 if (deferredFiltersEnabled) { |
1073 if (haveTransparency) { | 1076 if (haveTransparency) { |
1074 // If we have a filter and transparency, we have to eagerly start a transparency layer here, rather than risk a child layer lazily starts on e after filter processing. | 1077 // If we have a filter and transparency, we have to eagerly start a transparency layer here, rather than risk a child layer lazily starts on e after filter processing. |
1075 beginTransparencyLayers(context, localPaintingInfo.rootLayer , paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation); | 1078 beginTransparencyLayers(context, localPaintingInfo.rootLayer , paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation); |
1076 } | 1079 } |
1077 // We'll handle clipping to the dirty rect before filter rasteri zation. | 1080 // We'll handle clipping to the dirty rect before filter rasteri zation. |
1078 // Filter processing will automatically expand the clip rect and the offscreen to accommodate any filter outsets. | 1081 // Filter processing will automatically expand the clip rect and the offscreen to accommodate any filter outsets. |
1079 // FIXME: It is incorrect to just clip to the damageRect here on ce multiple fragments are involved. | 1082 // FIXME: It is incorrect to just clip to the damageRect here on ce multiple fragments are involved. |
1080 ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect; | 1083 ClipRect backgroundRect = fragment.backgroundRect; |
1081 clipToRect(localPaintingInfo, context, backgroundRect); | 1084 clipToRect(localPaintingInfo, context, backgroundRect); |
1082 // Subsequent code should not clip to the dirty rect, since we'v e already | 1085 // Subsequent code should not clip to the dirty rect, since we'v e already |
1083 // done it above, and doing it later will defeat the outsets. | 1086 // done it above, and doing it later will defeat the outsets. |
1084 localPaintingInfo.clipToDirtyRect = false; | 1087 localPaintingInfo.clipToDirtyRect = false; |
1085 } | 1088 } |
1086 context = filterPainter.beginFilterEffect(context); | 1089 context = filterPainter.beginFilterEffect(context); |
1087 | 1090 |
1088 // Check that we didn't fail to allocate the graphics context for th e offscreen buffer. | 1091 // Check that we didn't fail to allocate the graphics context for th e offscreen buffer. |
1089 if (filterPainter.hasStartedFilterEffect() && !deferredFiltersEnable d) { | 1092 if (filterPainter.hasStartedFilterEffect() && !deferredFiltersEnable d) { |
1090 localPaintingInfo.paintDirtyRect = filterPainter.paintInvalidati onRect(); | 1093 localPaintingInfo.paintDirtyRect = filterPainter.paintInvalidati onRect(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1123 | 1126 |
1124 paintOutlineForFragments(layerFragments, context, localPaintingInfo, paintin gRootForRenderer); | 1127 paintOutlineForFragments(layerFragments, context, localPaintingInfo, paintin gRootForRenderer); |
1125 paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, painting Info, paintFlags); | 1128 paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, painting Info, paintFlags); |
1126 | 1129 |
1127 if (isPaintingOverlayScrollbars) | 1130 if (isPaintingOverlayScrollbars) |
1128 paintOverflowControlsForFragments(layerFragments, context, localPainting Info); | 1131 paintOverflowControlsForFragments(layerFragments, context, localPainting Info); |
1129 | 1132 |
1130 if (filterPainter.hasStartedFilterEffect()) { | 1133 if (filterPainter.hasStartedFilterEffect()) { |
1131 // Apply the correct clipping (ie. overflow: hidden). | 1134 // Apply the correct clipping (ie. overflow: hidden). |
1132 // FIXME: It is incorrect to just clip to the damageRect here once multi ple fragments are involved. | 1135 // FIXME: It is incorrect to just clip to the damageRect here once multi ple fragments are involved. |
1133 ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerF ragments[0].backgroundRect; | 1136 ClipRect backgroundRect = fragment.backgroundRect; |
1134 if (!deferredFiltersEnabled) | 1137 if (!deferredFiltersEnabled) |
1135 clipToRect(localPaintingInfo, transparencyLayerContext, backgroundRe ct); | 1138 clipToRect(localPaintingInfo, transparencyLayerContext, backgroundRe ct); |
1136 | 1139 |
1137 context = filterPainter.applyFilterEffect(); | 1140 context = filterPainter.applyFilterEffect(); |
1138 restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect); | 1141 restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect); |
1139 } | 1142 } |
1140 | 1143 |
1141 // Make sure that we now use the original transparency context. | 1144 // Make sure that we now use the original transparency context. |
1142 ASSERT(transparencyLayerContext == context); | 1145 ASSERT(transparencyLayerContext == context); |
1143 | 1146 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1185 #if ENABLE(ASSERT) | 1188 #if ENABLE(ASSERT) |
1186 LayerListMutationDetector mutationChecker(m_stackingNode.get()); | 1189 LayerListMutationDetector mutationChecker(m_stackingNode.get()); |
1187 #endif | 1190 #endif |
1188 | 1191 |
1189 RenderLayerStackingNodeIterator iterator(*m_stackingNode, childrenToVisit); | 1192 RenderLayerStackingNodeIterator iterator(*m_stackingNode, childrenToVisit); |
1190 while (RenderLayerStackingNode* child = iterator.next()) { | 1193 while (RenderLayerStackingNode* child = iterator.next()) { |
1191 child->layer()->paintLayer(context, paintingInfo, paintFlags); | 1194 child->layer()->paintLayer(context, paintingInfo, paintFlags); |
1192 } | 1195 } |
1193 } | 1196 } |
1194 | 1197 |
1195 void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* rootLayer, const LayoutRect& dirtyRect, | |
1196 ClipRectsCacheSlot clipRectsCacheSlot, const LayoutPoint* offsetFromRoot, | |
1197 const LayoutSize& subPixelAccumulation, const LayoutRect* layerBoundingBox) | |
1198 { | |
1199 // For unpaginated layers, there is only one fragment. | |
1200 LayerFragment fragment; | |
1201 ClipRectsContext clipRectsContext(rootLayer, clipRectsCacheSlot, subPixelAcc umulation); | |
1202 clipper().calculateRects(clipRectsContext, dirtyRect, fragment.layerBounds, fragment.backgroundRect, fragment.foregroundRect, fragment.outlineRect, offsetFr omRoot); | |
1203 fragments.append(fragment); | |
1204 } | |
1205 | |
1206 void RenderLayer::updatePaintingInfoForFragments(LayerFragments& fragments, cons t LayerPaintingInfo& localPaintingInfo, | 1198 void RenderLayer::updatePaintingInfoForFragments(LayerFragments& fragments, cons t LayerPaintingInfo& localPaintingInfo, |
1207 bool shouldPaintContent, const LayoutPoint* offsetFromRoot) | 1199 bool shouldPaintContent, const LayoutPoint* offsetFromRoot) |
1208 { | 1200 { |
1209 ASSERT(offsetFromRoot); | 1201 ASSERT(offsetFromRoot); |
1210 for (size_t i = 0; i < fragments.size(); ++i) { | 1202 for (size_t i = 0; i < fragments.size(); ++i) { |
1211 LayerFragment& fragment = fragments.at(i); | 1203 LayerFragment& fragment = fragments.at(i); |
1212 LayoutPoint newOffsetFromRoot = *offsetFromRoot; | 1204 LayoutPoint newOffsetFromRoot = *offsetFromRoot; |
1213 fragment.shouldPaintContent = shouldPaintContent && intersectsDamageRect (fragment.layerBounds, fragment.backgroundRect.rect(), localPaintingInfo.rootLay er, &newOffsetFromRoot); | 1205 fragment.shouldPaintContent = shouldPaintContent && intersectsDamageRect (fragment.layerBounds, fragment.backgroundRect.rect(), localPaintingInfo.rootLay er, &newOffsetFromRoot); |
1214 } | 1206 } |
1215 } | 1207 } |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1564 | 1556 |
1565 // Now check our overflow objects. | 1557 // Now check our overflow objects. |
1566 hitLayer = hitTestChildren(NormalFlowChildren, rootLayer, request, result, h itTestRect, hitTestLocation, | 1558 hitLayer = hitTestChildren(NormalFlowChildren, rootLayer, request, result, h itTestRect, hitTestLocation, |
1567 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); | 1559 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); |
1568 if (hitLayer) { | 1560 if (hitLayer) { |
1569 if (!depthSortDescendants) | 1561 if (!depthSortDescendants) |
1570 return hitLayer; | 1562 return hitLayer; |
1571 candidateLayer = hitLayer; | 1563 candidateLayer = hitLayer; |
1572 } | 1564 } |
1573 | 1565 |
1574 // Collect the fragments. This will compute the clip rectangles for each lay er fragment. | 1566 LayoutRect layerBounds; |
1575 LayerFragments layerFragments; | 1567 ClipRect backgroundRect, foregroundRect, outlineRect; |
1576 collectFragments(layerFragments, rootLayer, hitTestRect, RootRelativeClipRec ts); | 1568 ClipRectsContext clipRectsContext(rootLayer, RootRelativeClipRects); |
1569 clipper().calculateRects(clipRectsContext, hitTestRect, layerBounds, backgro undRect, foregroundRect, outlineRect); | |
1577 | 1570 |
1578 // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. Check | 1571 // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. |
1579 // every fragment in reverse order. | 1572 if (isSelfPaintingLayer() && !foregroundRect.intersects(hitTestLocation)) { |
eseidel
2014/12/10 21:43:50
This ! looks wrong.
| |
1580 if (isSelfPaintingLayer()) { | |
1581 // Hit test with a temporary HitTestResult, because we only want to comm it to 'result' if we know we're frontmost. | 1573 // Hit test with a temporary HitTestResult, because we only want to comm it to 'result' if we know we're frontmost. |
1582 HitTestResult tempResult(result.hitTestLocation()); | 1574 HitTestResult tempResult(result.hitTestLocation()); |
1583 bool insideFragmentForegroundRect = false; | 1575 if (hitTestContents(request, tempResult, layerBounds, hitTestLocation, H itTestDescendants) |
1584 if (hitTestContentsForFragments(layerFragments, request, tempResult, hit TestLocation, HitTestDescendants, insideFragmentForegroundRect) | |
1585 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTra nsformState.get())) { | 1576 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTra nsformState.get())) { |
1586 if (result.isRectBasedTest()) | 1577 if (result.isRectBasedTest()) |
1587 result.append(tempResult); | 1578 result.append(tempResult); |
1588 else | 1579 else |
1589 result = tempResult; | 1580 result = tempResult; |
1590 if (!depthSortDescendants) | 1581 if (!depthSortDescendants) |
1591 return this; | 1582 return this; |
1592 // Foreground can depth-sort with descendant layers, so keep this as a candidate. | 1583 // Foreground can depth-sort with descendant layers, so keep this as a candidate. |
1593 candidateLayer = this; | 1584 candidateLayer = this; |
1594 } else if (insideFragmentForegroundRect && result.isRectBasedTest()) | 1585 } else if (result.isRectBasedTest()) { |
1595 result.append(tempResult); | 1586 result.append(tempResult); |
1587 } | |
1596 } | 1588 } |
1597 | 1589 |
1598 // Now check our negative z-index children. | 1590 // Now check our negative z-index children. |
1599 hitLayer = hitTestChildren(NegativeZOrderChildren, rootLayer, request, resul t, hitTestRect, hitTestLocation, | 1591 hitLayer = hitTestChildren(NegativeZOrderChildren, rootLayer, request, resul t, hitTestRect, hitTestLocation, |
1600 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattene dTransformState.get(), depthSortDescendants); | 1592 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattene dTransformState.get(), depthSortDescendants); |
1601 if (hitLayer) { | 1593 if (hitLayer) { |
1602 if (!depthSortDescendants) | 1594 if (!depthSortDescendants) |
1603 return hitLayer; | 1595 return hitLayer; |
1604 candidateLayer = hitLayer; | 1596 candidateLayer = hitLayer; |
1605 } | 1597 } |
1606 | 1598 |
1607 // If we found a layer, return. Child layers, and foreground always render i n front of background. | 1599 // If we found a layer, return. Child layers, and foreground always render i n front of background. |
1608 if (candidateLayer) | 1600 if (candidateLayer) |
1609 return candidateLayer; | 1601 return candidateLayer; |
1610 | 1602 |
1611 if (isSelfPaintingLayer()) { | 1603 if (isSelfPaintingLayer() && !backgroundRect.intersects(hitTestLocation)) { |
1612 HitTestResult tempResult(result.hitTestLocation()); | 1604 HitTestResult tempResult(result.hitTestLocation()); |
1613 bool insideFragmentBackgroundRect = false; | 1605 if (hitTestContents(request, tempResult, layerBounds, hitTestLocation, H itTestSelf) |
1614 if (hitTestContentsForFragments(layerFragments, request, tempResult, hit TestLocation, HitTestSelf, insideFragmentBackgroundRect) | |
1615 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTra nsformState.get())) { | 1606 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTra nsformState.get())) { |
1616 if (result.isRectBasedTest()) | 1607 if (result.isRectBasedTest()) |
1617 result.append(tempResult); | 1608 result.append(tempResult); |
1618 else | 1609 else |
1619 result = tempResult; | 1610 result = tempResult; |
1620 return this; | 1611 return this; |
1621 } | 1612 } |
1622 if (insideFragmentBackgroundRect && result.isRectBasedTest()) | 1613 if (result.isRectBasedTest()) |
1623 result.append(tempResult); | 1614 result.append(tempResult); |
1624 } | 1615 } |
1625 | 1616 |
1626 return 0; | 1617 return 0; |
1627 } | 1618 } |
1628 | 1619 |
1629 bool RenderLayer::hitTestContentsForFragments(const LayerFragments& layerFragmen ts, const HitTestRequest& request, HitTestResult& result, | |
1630 const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter, bool& i nsideClipRect) const | |
1631 { | |
1632 if (layerFragments.isEmpty()) | |
1633 return false; | |
1634 | |
1635 for (int i = layerFragments.size() - 1; i >= 0; --i) { | |
1636 const LayerFragment& fragment = layerFragments.at(i); | |
1637 if ((hitTestFilter == HitTestSelf && !fragment.backgroundRect.intersects (hitTestLocation)) | |
1638 || (hitTestFilter == HitTestDescendants && !fragment.foregroundRect. intersects(hitTestLocation))) | |
1639 continue; | |
1640 insideClipRect = true; | |
1641 if (hitTestContents(request, result, fragment.layerBounds, hitTestLocati on, hitTestFilter)) | |
1642 return true; | |
1643 } | |
1644 | |
1645 return false; | |
1646 } | |
1647 | |
1648 RenderLayer* RenderLayer::hitTestLayerByApplyingTransform(RenderLayer* rootLayer , RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& res ult, | 1620 RenderLayer* RenderLayer::hitTestLayerByApplyingTransform(RenderLayer* rootLayer , RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& res ult, |
1649 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset, | 1621 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset, |
1650 const LayoutPoint& translationOffset) | 1622 const LayoutPoint& translationOffset) |
1651 { | 1623 { |
1652 // Create a transform state to accumulate this transform. | 1624 // Create a transform state to accumulate this transform. |
1653 RefPtr<HitTestingTransformState> newTransformState = createLocalTransformSta te(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState, tran slationOffset); | 1625 RefPtr<HitTestingTransformState> newTransformState = createLocalTransformSta te(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState, tran slationOffset); |
1654 | 1626 |
1655 // If the transform can't be inverted, then don't hit test this layer at all . | 1627 // If the transform can't be inverted, then don't hit test this layer at all . |
1656 if (!newTransformState->m_accumulatedTransform.isInvertible()) | 1628 if (!newTransformState->m_accumulatedTransform.isInvertible()) |
1657 return 0; | 1629 return 0; |
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2144 } | 2116 } |
2145 } | 2117 } |
2146 | 2118 |
2147 void showLayerTree(const blink::RenderObject* renderer) | 2119 void showLayerTree(const blink::RenderObject* renderer) |
2148 { | 2120 { |
2149 if (!renderer) | 2121 if (!renderer) |
2150 return; | 2122 return; |
2151 showLayerTree(renderer->enclosingLayer()); | 2123 showLayerTree(renderer->enclosingLayer()); |
2152 } | 2124 } |
2153 #endif | 2125 #endif |
OLD | NEW |