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