diff options
Diffstat (limited to 'WebCore/rendering/RenderLayer.cpp')
-rw-r--r-- | WebCore/rendering/RenderLayer.cpp | 217 |
1 files changed, 141 insertions, 76 deletions
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 8f2805a..ee7814c 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -243,14 +243,6 @@ bool RenderLayer::hasAcceleratedCompositing() const #endif } -void RenderLayer::setStaticY(int staticY) -{ - if (m_staticY == staticY) - return; - m_staticY = staticY; - renderer()->setChildNeedsLayout(true, false); -} - void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags) { if (flags & DoFullRepaint) { @@ -383,6 +375,20 @@ TransformationMatrix RenderLayer::currentTransform() const return *m_transform; } +TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const +{ + if (!m_transform) + return TransformationMatrix(); + + if (paintBehavior & PaintBehaviorFlattenCompositingLayers) { + TransformationMatrix matrix = *m_transform; + makeMatrixRenderable(matrix, false /* flatten 3d */); + return matrix; + } + + return *m_transform; +} + void RenderLayer::setHasVisibleContent(bool b) { if (m_hasVisibleContent == b && !m_visibleContentStatusDirty) @@ -689,6 +695,27 @@ RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const } #endif +RenderLayer* RenderLayer::clippingRoot() const +{ + const RenderLayer* current = this; + while (current) { + if (current->renderer()->isRenderView()) + return const_cast<RenderLayer*>(current); + + current = compositingContainer(current); + ASSERT(current); + if (current->transform() +#if USE(ACCELERATED_COMPOSITING) + || current->isComposited() +#endif + ) + return const_cast<RenderLayer*>(current); + } + + ASSERT_NOT_REACHED(); + return 0; +} + IntPoint RenderLayer::absoluteToContents(const IntPoint& absolutePoint) const { // We don't use convertToLayerCoords because it doesn't know about transforms @@ -727,46 +754,18 @@ RenderLayer* RenderLayer::transparentPaintingAncestor() return 0; } -static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransform, const RenderLayer* l, const RenderLayer* rootLayer) -{ - // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the - // paintDirtyRect, and that should cut down on the amount we have to paint. Still it - // would be better to respect clips. - - if (rootLayer != l && l->paintsWithTransform()) { - // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass - // the transformed layer and all of its children. - int x = 0; - int y = 0; - l->convertToLayerCoords(rootLayer, x, y); - - TransformationMatrix transform; - transform.translate(x, y); - transform = *l->transform() * transform; - transform = transform * enclosingTransform; +static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior); - // We now have a transform that will produce a rectangle in our view's space. - IntRect clipRect = transform.mapRect(l->boundingBox(l)); - - // Now shift the root layer to be us and pass down the new enclosing transform. - for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) { - if (!l->reflection() || l->reflectionLayer() != curr) - clipRect.unite(transparencyClipBox(transform, curr, l)); - } - - return clipRect; - } - - // Note: we don't have to walk z-order lists since transparent elements always establish - // a stacking context. This means we can just walk the layer tree directly. - IntRect clipRect = l->boundingBox(rootLayer); - +static void expandClipRectForDescendantsAndReflection(IntRect& clipRect, const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior) +{ // If we have a mask, then the clip is limited to the border box area (and there is // no need to examine child layers). if (!l->renderer()->hasMask()) { + // Note: we don't have to walk z-order lists since transparent elements always establish + // a stacking context. This means we can just walk the layer tree directly. for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) { if (!l->reflection() || l->reflectionLayer() != curr) - clipRect.unite(transparencyClipBox(enclosingTransform, curr, rootLayer)); + clipRect.unite(transparencyClipBox(curr, rootLayer, paintBehavior)); } } @@ -782,25 +781,54 @@ static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransfor clipRect.unite(l->renderBox()->reflectedRect(clipRect)); clipRect.move(deltaX, deltaY); } +} - // Now map the clipRect via the enclosing transform - return enclosingTransform.mapRect(clipRect); +static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior) +{ + // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the + // paintDirtyRect, and that should cut down on the amount we have to paint. Still it + // would be better to respect clips. + + if (rootLayer != l && l->paintsWithTransform(paintBehavior)) { + // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass + // the transformed layer and all of its children. + int x = 0; + int y = 0; + l->convertToLayerCoords(rootLayer, x, y); + + TransformationMatrix transform; + transform.translate(x, y); + transform = *l->transform() * transform; + + IntRect clipRect = l->boundingBox(l); + expandClipRectForDescendantsAndReflection(clipRect, l, l, paintBehavior); + return transform.mapRect(clipRect); + } + + IntRect clipRect = l->boundingBox(rootLayer); + expandClipRectForDescendantsAndReflection(clipRect, l, rootLayer, paintBehavior); + return clipRect; } -void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer) +void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer, PaintBehavior paintBehavior) { - if (p->paintingDisabled() || (paintsWithTransparency() && m_usedTransparency)) + if (p->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency)) return; RenderLayer* ancestor = transparentPaintingAncestor(); if (ancestor) - ancestor->beginTransparencyLayers(p, rootLayer); + ancestor->beginTransparencyLayers(p, rootLayer, paintBehavior); - if (paintsWithTransparency()) { + if (paintsWithTransparency(paintBehavior)) { m_usedTransparency = true; p->save(); - p->clip(transparencyClipBox(TransformationMatrix(), this, rootLayer)); + IntRect clipRect = transparencyClipBox(this, rootLayer, paintBehavior); + p->clip(clipRect); p->beginTransparencyLayer(renderer()->opacity()); +#ifdef REVEAL_TRANSPARENCY_LAYERS + p->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f)); + p->fillRect(clipRect); +#endif } } @@ -1061,7 +1089,7 @@ void RenderLayer::scrollByRecursively(int xDelta, int yDelta) bool restrictedByLineClamp = false; if (renderer()->parent()) - restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0; + restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone(); if (renderer()->hasOverflowClip() && !restrictedByLineClamp) { int newOffsetX = scrollXOffset() + xDelta; @@ -1205,7 +1233,7 @@ void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor, bool restrictedByLineClamp = false; if (renderer()->parent()) { parentLayer = renderer()->parent()->enclosingLayer(); - restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0; + restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone(); } if (renderer()->hasOverflowClip() && !restrictedByLineClamp) { @@ -1921,7 +1949,7 @@ void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, co return; } - context->fillRect(absRect, Color::white); + context->fillRect(absRect, Color::white, box->style()->colorSpace()); } void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect) @@ -1950,7 +1978,7 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I // Paint the resizer control. DEFINE_STATIC_LOCAL(RefPtr<Image>, resizeCornerImage, (Image::loadPlatformResource("textAreaResizeCorner"))); IntPoint imagePoint(absRect.right() - resizeCornerImage->width(), absRect.bottom() - resizeCornerImage->height()); - context->drawImage(resizeCornerImage.get(), imagePoint); + context->drawImage(resizeCornerImage.get(), box->style()->colorSpace(), imagePoint); // Draw a frame around the resizer (1px grey line) if there are any scrollbars present. // Clipping will exclude the right and bottom edges of this frame. @@ -1959,9 +1987,9 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I context->clip(absRect); IntRect largerCorner = absRect; largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1)); - context->setStrokeColor(Color(makeRGB(217, 217, 217))); + context->setStrokeColor(Color(makeRGB(217, 217, 217)), DeviceColorSpace); context->setStrokeThickness(1.0f); - context->setFillColor(Color::transparent); + context->setFillColor(Color::transparent, DeviceColorSpace); context->drawRect(largerCorner); context->restore(); } @@ -2044,10 +2072,10 @@ bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularit return (didHorizontalScroll || didVerticalScroll); } -void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintRestriction paintRestriction, RenderObject *paintingRoot) +void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot) { RenderObject::OverlapTestRequestMap overlapTestRequests; - paintLayer(this, p, damageRect, paintRestriction, paintingRoot, &overlapTestRequests); + paintLayer(this, p, damageRect, paintBehavior, paintingRoot, &overlapTestRequests); RenderObject::OverlapTestRequestMap::iterator end = overlapTestRequests.end(); for (RenderObject::OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) it->first->setOverlapTestResult(false); @@ -2091,7 +2119,7 @@ static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflect #endif void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, - const IntRect& paintDirtyRect, PaintRestriction paintRestriction, + const IntRect& paintDirtyRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests, PaintLayerFlags paintFlags) { @@ -2099,7 +2127,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, if (isComposited()) { // The updatingControlTints() painting pass goes through compositing layers, // but we need to ensure that we don't cache clip rects computed with the wrong root in this case. - if (p->updatingControlTints()) + if (p->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers)) paintFlags |= PaintLayerTemporaryClipRects; else if (!backing()->paintingGoesToWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) { // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer(). @@ -2118,19 +2146,20 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, if (!renderer()->opacity()) return; - if (paintsWithTransparency()) + if (paintsWithTransparency(paintBehavior)) paintFlags |= PaintLayerHaveTransparency; // Apply a transform if we have one. A reflection is considered to be a transform, since it is a flip and a translate. - if (paintsWithTransform() && !(paintFlags & PaintLayerAppliedTransform)) { + if (paintsWithTransform(paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) { + TransformationMatrix layerTransform = renderableTransform(paintBehavior); // If the transform can't be inverted, then don't paint anything. - if (!m_transform->isInvertible()) + if (!layerTransform.isInvertible()) return; // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency // layer from the parent now. if (paintFlags & PaintLayerHaveTransparency) - parent()->beginTransparencyLayers(p, rootLayer); + parent()->beginTransparencyLayers(p, rootLayer, paintBehavior); // Make sure the parent's clip rects have been calculated. IntRect clipRect = paintDirtyRect; @@ -2153,15 +2182,19 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, #else TransformationMatrix transform; transform.translate(x, y); +<<<<<<< HEAD:WebCore/rendering/RenderLayer.cpp transform = *m_transform * transform; #endif +======= + transform = layerTransform * transform; +>>>>>>> webkit.org at r51976:WebCore/rendering/RenderLayer.cpp // Apply the transform. p->save(); p->concatCTM(transform); // Now do a paint with the root layer shifted to be us. - paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintRestriction, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform); + paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform); p->restore(); @@ -2178,7 +2211,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, if (m_reflection && !m_paintingInsideReflection) { // Mark that we are now inside replica painting. m_paintingInsideReflection = true; - reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection); + reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection); m_paintingInsideReflection = false; } @@ -2193,8 +2226,8 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, // Ensure our lists are up-to-date. updateCompositingAndLayerListsIfNeeded(); - bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText; - bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText; + bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText; + bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly; // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set). @@ -2212,7 +2245,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, if (shouldPaint && !selectionOnly && !damageRect.isEmpty()) { // Begin transparency layers lazily now that we know we have to paint something. if (haveTransparency) - beginTransparencyLayers(p, rootLayer); + beginTransparencyLayers(p, rootLayer, paintBehavior); // Paint our background first, before painting any child layers. // Establish the clip used to paint our background. @@ -2229,13 +2262,13 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, // Now walk the sorted list of children with negative z-indices. if (m_negZOrderList) for (Vector<RenderLayer*>::iterator it = m_negZOrderList->begin(); it != m_negZOrderList->end(); ++it) - it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags); + it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); // Now establish the appropriate clip and paint our child RenderObjects. if (shouldPaint && !clipRectToApply.isEmpty()) { // Begin transparency layers lazily now that we know we have to paint something. if (haveTransparency) - beginTransparencyLayers(p, rootLayer); + beginTransparencyLayers(p, rootLayer, paintBehavior); // Set up the clip used when painting our children. setClip(p, paintDirtyRect, clipRectToApply); @@ -2268,12 +2301,12 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, // Paint any child layers that have overflow. if (m_normalFlowList) for (Vector<RenderLayer*>::iterator it = m_normalFlowList->begin(); it != m_normalFlowList->end(); ++it) - it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags); + it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); // Now walk the sorted list of children with positive z-indices. if (m_posZOrderList) for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it) - it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags); + it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags); if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty()) { setClip(p, paintDirtyRect, damageRect); @@ -2813,17 +2846,49 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa IntRect RenderLayer::childrenClipRect() const { RenderLayer* rootLayer = renderer()->view()->layer(); + RenderLayer* clippingRootLayer = clippingRoot(); IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; - calculateRects(rootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect); - return foregroundRect; + calculateRects(clippingRootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect); + return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect)).enclosingBoundingBox(); } IntRect RenderLayer::selfClipRect() const { RenderLayer* rootLayer = renderer()->view()->layer(); + RenderLayer* clippingRootLayer = clippingRoot(); IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; - calculateRects(rootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect); - return backgroundRect; + calculateRects(clippingRootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect); + return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect)).enclosingBoundingBox(); +} + +void RenderLayer::addBlockSelectionGapsBounds(const IntRect& bounds) +{ + m_blockSelectionGapsBounds.unite(bounds); +} + +void RenderLayer::clearBlockSelectionGapsBounds() +{ + m_blockSelectionGapsBounds = IntRect(); + for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) + child->clearBlockSelectionGapsBounds(); +} + +void RenderLayer::repaintBlockSelectionGaps() +{ + for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) + child->repaintBlockSelectionGaps(); + + if (m_blockSelectionGapsBounds.isEmpty()) + return; + + IntRect rect = m_blockSelectionGapsBounds; + rect.move(-scrolledContentOffset()); + if (renderer()->hasOverflowClip()) + rect.intersect(toRenderBox(renderer())->overflowClipRect(0, 0)); + if (renderer()->hasClip()) + rect.intersect(toRenderBox(renderer())->clipRect(0, 0)); + if (!rect.isEmpty()) + renderer()->repaintRectangle(rect); } bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const |