https://bugs.webkit.org/show_bug.cgi?id=71488
Reviewed by David Hyatt.
Source/WebCore:
Based on work by Alexandru Chiculita (achicu@adobe.com).
Previous patches for region styling were touching RenderObject::style() method. After several attempts to avoid regressions
(including caching of RenderObject::style() pointer in most used methods), we decided to attempt a different approach:
Step1: before each region is repainted, we compute the style for each box that falls into the region
Step2: before paint, we store the box original style
Step3: paint the region contents using the style in region
Step4: after paint is finished, we restore the box original style (and store the box style in region for future region paint)
Tests for region styling are also enabled with this patch.
* WebCore.exp.in:
* rendering/RenderFlowThread.cpp:
(WebCore::RenderFlowThread::clearRenderBoxCustomStyle):
(WebCore::RenderFlowThread::setRegionRangeForBox):
* rendering/RenderFlowThread.h:
():
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::paint):
(WebCore::RenderLayer::hitTest):
* rendering/RenderObject.cpp:
* rendering/RenderObject.h:
(WebCore::RenderObject::style):
(RenderObject):
* rendering/RenderObjectChildList.cpp:
(WebCore::RenderObjectChildList::removeChildNode):
* rendering/RenderRegion.cpp:
(WebCore::RenderRegion::RenderRegion):
(WebCore::RenderRegion::setRegionBoxesRegionStyle):
(WebCore):
(WebCore::RenderRegion::restoreRegionBoxesOriginalStyle):
(WebCore::RenderRegion::paintReplaced):
(WebCore::RenderRegion::setRenderBoxRegionInfo):
(WebCore::RenderRegion::takeRenderBoxRegionInfo):
(WebCore::RenderRegion::removeRenderBoxRegionInfo):
(WebCore::RenderRegion::renderBoxRegionStyle):
(WebCore::RenderRegion::computeStyleInRegion):
(WebCore::RenderRegion::clearBoxStyleInRegion):
* rendering/RenderRegion.h:
(RenderRegion):
* rendering/RenderView.cpp:
(WebCore::RenderView::RenderView):
* rendering/RenderView.h:
(WebCore):
(RenderView):
LayoutTests:
Enable the region styling tests again.
* platform/mac-snowleopard/Skipped:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@106281
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-01-30 Mihnea Ovidenie <mihnea@adobe.com>
+
+ [CSSRegions]Add support for background-color in region styling
+ https://bugs.webkit.org/show_bug.cgi?id=71488
+
+ Reviewed by David Hyatt.
+
+ Enable the region styling tests again.
+
+ * platform/mac-snowleopard/Skipped:
+
2012-01-30 Joshua Bell <jsbell@chromium.org>
IndexedDB: Add tests for structured clone data
# Regression in performance
# https://bugs.webkit.org/show_bug.cgi?id=74141
-fast/regions/region-style-block-background-color.html
-fast/regions/region-style-block-background-color2.html
-fast/regions/region-style-image-background-color.html
-fast/regions/region-style-inline-background-color.html
+#fast/regions/region-style-block-background-color.html
+#fast/regions/region-style-block-background-color2.html
+#fast/regions/region-style-image-background-color.html
+#fast/regions/region-style-inline-background-color.html
# HiDPI tests have lower-level platform dependencies on Mac
fast/hidpi
+2012-01-30 Mihnea Ovidenie <mihnea@adobe.com>
+
+ [CSSRegions]Add support for background-color in region styling
+ https://bugs.webkit.org/show_bug.cgi?id=71488
+
+ Reviewed by David Hyatt.
+
+ Based on work by Alexandru Chiculita (achicu@adobe.com).
+ Previous patches for region styling were touching RenderObject::style() method. After several attempts to avoid regressions
+ (including caching of RenderObject::style() pointer in most used methods), we decided to attempt a different approach:
+ Step1: before each region is repainted, we compute the style for each box that falls into the region
+ Step2: before paint, we store the box original style
+ Step3: paint the region contents using the style in region
+ Step4: after paint is finished, we restore the box original style (and store the box style in region for future region paint)
+
+ Tests for region styling are also enabled with this patch.
+
+ * WebCore.exp.in:
+ * rendering/RenderFlowThread.cpp:
+ (WebCore::RenderFlowThread::clearRenderBoxCustomStyle):
+ (WebCore::RenderFlowThread::setRegionRangeForBox):
+ * rendering/RenderFlowThread.h:
+ ():
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::paint):
+ (WebCore::RenderLayer::hitTest):
+ * rendering/RenderObject.cpp:
+ * rendering/RenderObject.h:
+ (WebCore::RenderObject::style):
+ (RenderObject):
+ * rendering/RenderObjectChildList.cpp:
+ (WebCore::RenderObjectChildList::removeChildNode):
+ * rendering/RenderRegion.cpp:
+ (WebCore::RenderRegion::RenderRegion):
+ (WebCore::RenderRegion::setRegionBoxesRegionStyle):
+ (WebCore):
+ (WebCore::RenderRegion::restoreRegionBoxesOriginalStyle):
+ (WebCore::RenderRegion::paintReplaced):
+ (WebCore::RenderRegion::setRenderBoxRegionInfo):
+ (WebCore::RenderRegion::takeRenderBoxRegionInfo):
+ (WebCore::RenderRegion::removeRenderBoxRegionInfo):
+ (WebCore::RenderRegion::renderBoxRegionStyle):
+ (WebCore::RenderRegion::computeStyleInRegion):
+ (WebCore::RenderRegion::clearBoxStyleInRegion):
+ * rendering/RenderRegion.h:
+ (RenderRegion):
+ * rendering/RenderView.cpp:
+ (WebCore::RenderView::RenderView):
+ * rendering/RenderView.h:
+ (WebCore):
+ (RenderView):
+
2012-01-30 Jessie Berlin <jberlin@apple.com>
WebCore build exceeds address space on 32-bit Windows builders (again).
__ZNK7WebCore12IconDatabase12databasePathEv
__ZNK7WebCore12IconDatabase24shouldStopThreadActivityEv
__ZNK7WebCore12IconDatabase9isEnabledEv
-__ZNK7WebCore12RenderObject13styleInRegionEv
__ZNK7WebCore12RenderObject14enclosingLayerEv
__ZNK7WebCore12RenderObject15localToAbsoluteERKNS_10FloatPointEbb
__ZNK7WebCore12RenderObject23absoluteBoundingBoxRectEb
return 0;
}
-void RenderFlowThread::clearRenderObjectCustomStyle(const RenderObject* object,
+void RenderFlowThread::clearRenderBoxCustomStyle(const RenderBox* box,
const RenderRegion* oldStartRegion, const RenderRegion* oldEndRegion,
const RenderRegion* newStartRegion, const RenderRegion* newEndRegion)
{
insideNewRegionRange = true;
if (!(insideOldRegionRange && insideNewRegionRange))
- region->clearObjectStyleInRegion(object);
+ region->clearBoxStyleInRegion(box);
if (oldEndRegion == region)
insideOldRegionRange = false;
break;
}
- clearRenderObjectCustomStyle(box, range.startRegion(), range.endRegion(), startRegion, endRegion);
+ clearRenderBoxCustomStyle(box, range.startRegion(), range.endRegion(), startRegion, endRegion);
range.setRange(startRegion, endRegion);
}
void setRegionRangeForBox(const RenderBox*, LayoutUnit offsetFromLogicalTopOfFirstPage);
void getRegionRangeForBox(const RenderBox*, RenderRegion*& startRegion, RenderRegion*& endRegion) const;
- void clearRenderObjectCustomStyle(const RenderObject*,
+ void clearRenderBoxCustomStyle(const RenderBox*,
const RenderRegion* oldStartRegion = 0, const RenderRegion* oldEndRegion = 0,
const RenderRegion* newStartRegion = 0, const RenderRegion* newEndRegion = 0);
WebKitNamedFlow* ensureNamedFlow();
return ScrollableArea::scroll(direction, granularity, multiplier);
}
-class CurrentRenderRegionMaintainer {
- WTF_MAKE_NONCOPYABLE(CurrentRenderRegionMaintainer);
-public:
- CurrentRenderRegionMaintainer(RenderView* view, RenderRegion* renderRegion)
- : m_view(view)
- , m_renderRegion(view->currentRenderRegion())
- {
- m_view->setCurrentRenderRegion(renderRegion);
- }
- ~CurrentRenderRegionMaintainer()
- {
- m_view->setCurrentRenderRegion(m_renderRegion);
- }
-private:
- RenderView* m_view;
- RenderRegion* m_renderRegion;
-};
-
void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, RenderRegion* region, PaintLayerFlags paintFlags)
{
- CurrentRenderRegionMaintainer renderRegionMaintainer(renderer()->view(), region);
OverlapTestRequestMap overlapTestRequests;
paintLayer(this, context, damageRect, paintBehavior, paintingRoot, region, &overlapTestRequests, paintFlags);
OverlapTestRequestMap::iterator end = overlapTestRequests.end();
bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
{
- CurrentRenderRegionMaintainer renderRegionMaintainer(renderer()->view(), result.region());
renderer()->document()->updateLayout();
LayoutRect hitTestArea = renderer()->view()->documentRect();
return diff;
}
-RenderStyle* RenderObject::styleInRegion() const
-{
- ASSERT(inRenderFlowThread());
-
- if (!canHaveRegionStyle()
- || !((view() && view()->currentRenderRegion() && view()->currentRenderRegion()->hasCustomRegionStyle())))
- return m_style.get();
-
- RenderStyle* regionStyle = view()->currentRenderRegion()->renderObjectRegionStyle(this);
- if (!regionStyle)
- view()->currentRenderRegion()->computeStyleInRegion(this);
- return view()->currentRenderRegion()->renderObjectRegionStyle(this);
-}
-
void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
{
if (m_style == style) {
virtual LayoutUnit minPreferredLogicalWidth() const { return 0; }
virtual LayoutUnit maxPreferredLogicalWidth() const { return 0; }
- RenderStyle* style() const;
+ RenderStyle* style() const { return m_style.get(); }
RenderStyle* firstLineStyle() const { return document()->usesFirstLineRules() ? firstLineStyleSlowCase() : style(); }
RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); }
virtual LayoutRect outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/, LayoutPoint* /*cachedOffsetToRepaintContainer*/ = 0) const { return LayoutRect(); }
private:
- RenderStyle* styleInRegion() const;
RenderStyle* firstLineStyleSlowCase() const;
StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const;
return style()->preserveNewline();
}
-inline RenderStyle* RenderObject::style() const
-{
- return m_style.get();
-}
-
inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering)
{
#if !ENABLE(3D_RENDERING)
if (oldChild->inRenderFlowThread() && oldChild->isBox()) {
oldChild->enclosingRenderFlowThread()->removeRenderBoxRegionInfo(toRenderBox(oldChild));
if (oldChild->canHaveRegionStyle())
- oldChild->enclosingRenderFlowThread()->clearRenderObjectCustomStyle(oldChild);
+ oldChild->enclosingRenderFlowThread()->clearRenderBoxCustomStyle(toRenderBox(oldChild));
}
if (RenderFlowThread* containerFlowThread = renderFlowThreadContainer(owner))
, m_parentFlowThread(0)
, m_isValid(false)
, m_hasCustomRegionStyle(false)
+#ifndef NDEBUG
+ , m_insideRegionPaint(false)
+#endif
{
}
return m_flowThread->lastRegion() == this;
}
+void RenderRegion::setRegionBoxesRegionStyle()
+{
+ for (RenderBoxRegionInfoMap::iterator iter = m_renderBoxRegionInfo.begin(), end = m_renderBoxRegionInfo.end(); iter != end; ++iter) {
+ const RenderBox* box = iter->first;
+ if (!box->canHaveRegionStyle())
+ continue;
+
+ // Save original box style to be restored later, after paint.
+ RefPtr<RenderStyle> boxOriginalStyle = box->style();
+
+ // Set the style to be used for box as the style computed in region.
+ (const_cast<RenderBox*>(box))->setStyleInternal(renderBoxRegionStyle(box));
+
+ m_renderBoxRegionStyle.set(box, boxOriginalStyle);
+ }
+}
+
+void RenderRegion::restoreRegionBoxesOriginalStyle()
+{
+ for (RenderBoxRegionInfoMap::iterator iter = m_renderBoxRegionInfo.begin(), end = m_renderBoxRegionInfo.end(); iter != end; ++iter) {
+ const RenderBox* box = iter->first;
+ RenderBoxRegionStyleMap::iterator it = m_renderBoxRegionStyle.find(box);
+ if (it == m_renderBoxRegionStyle.end())
+ continue;
+
+ // Restore the box style to the original style and store the box style in region for later use.
+ RefPtr<RenderStyle> boxRegionStyle = box->style();
+ (const_cast<RenderBox*>(box))->setStyleInternal(it->second);
+ m_renderBoxRegionStyle.set(box, boxRegionStyle);
+ }
+}
+
void RenderRegion::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
// Delegate painting of content in region to RenderFlowThread.
if (!m_flowThread || !isValid())
return;
+
+#ifndef NDEBUG
+ m_insideRegionPaint = true;
+#endif
+
+ setRegionBoxesRegionStyle();
m_flowThread->paintIntoRegion(paintInfo, this, LayoutPoint(paintOffset.x() + borderLeft() + paddingLeft(), paintOffset.y() + borderTop() + paddingTop()));
+ restoreRegionBoxesOriginalStyle();
+
+#ifndef NDEBUG
+ m_insideRegionPaint = false;
+#endif
}
// Hit Testing
if (!m_isValid || !m_flowThread)
return 0;
+#ifndef NDEBUG
+ ASSERT(!m_insideRegionPaint && "RenderBoxRegionInfo should not be modified inside region paint.");
+#endif
+
OwnPtr<RenderBoxRegionInfo>& boxInfo = m_renderBoxRegionInfo.add(box, nullptr).first->second;
if (boxInfo)
*boxInfo = RenderBoxRegionInfo(logicalLeftInset, logicalRightInset, containingBlockChainIsInset);
PassOwnPtr<RenderBoxRegionInfo> RenderRegion::takeRenderBoxRegionInfo(const RenderBox* box)
{
+#ifndef NDEBUG
+ ASSERT(!m_insideRegionPaint && "RenderBoxRegionInfo should not be modified inside region paint.");
+#endif
+
return m_renderBoxRegionInfo.take(box);
}
void RenderRegion::removeRenderBoxRegionInfo(const RenderBox* box)
{
+#ifndef NDEBUG
+ ASSERT(!m_insideRegionPaint && "RenderBoxRegionInfo should not be modified inside region paint.");
+#endif
+
m_renderBoxRegionInfo.remove(box);
}
return regionRect().x();
}
-RenderStyle* RenderRegion::renderObjectRegionStyle(const RenderObject* renderObject) const
+PassRefPtr<RenderStyle> RenderRegion::renderBoxRegionStyle(const RenderBox* renderBox)
{
- RenderObjectRegionStyleMap::const_iterator it = m_renderObjectRegionStyle.find(renderObject);
- return (it != m_renderObjectRegionStyle.end()) ? it->second.get() : 0;
+ // The box for which we are asking for style in region should have its info present
+ // in the region box info map.
+ ASSERT(m_renderBoxRegionInfo.find(renderBox) != m_renderBoxRegionInfo.end());
+
+ RenderBoxRegionStyleMap::iterator it = m_renderBoxRegionStyle.find(renderBox);
+ if (it != m_renderBoxRegionStyle.end())
+ return it->second;
+ return computeStyleInRegion(renderBox);
}
-void RenderRegion::computeStyleInRegion(const RenderObject* object)
+PassRefPtr<RenderStyle> RenderRegion::computeStyleInRegion(const RenderBox* box)
{
- ASSERT(object);
- ASSERT(object->view());
- ASSERT(object->view()->document());
- ASSERT(!object->isAnonymous());
- ASSERT(object->node() && object->node()->isElementNode());
-
- Element* element = toElement(object->node());
- RefPtr<RenderStyle> renderObjectStyle = object->view()->document()->styleSelector()->styleForElement(element, 0, false, false, this);
- m_renderObjectRegionStyle.set(object, renderObjectStyle);
-
- if (!object->hasBoxDecorations()) {
- RenderBox* box = const_cast<RenderBox*>(toRenderBox(object));
- RenderStyle* styleInRegion = renderObjectRegionStyle(object);
- ASSERT(styleInRegion);
-
- bool hasBoxDecorations = object->isTableCell() || styleInRegion->hasBackground() || styleInRegion->hasBorder() || styleInRegion->hasAppearance() || styleInRegion->boxShadow();
- box->setHasBoxDecorations(hasBoxDecorations);
+ ASSERT(box);
+ ASSERT(box->view());
+ ASSERT(box->view()->document());
+ ASSERT(!box->isAnonymous());
+ ASSERT(box->node() && box->node()->isElementNode());
+
+ Element* element = toElement(box->node());
+ RefPtr<RenderStyle> renderBoxRegionStyle = box->view()->document()->styleSelector()->styleForElement(element, 0, false, false, this);
+ m_renderBoxRegionStyle.add(box, renderBoxRegionStyle);
+
+ if (!box->hasBoxDecorations()) {
+ bool hasBoxDecorations = box->isTableCell() || renderBoxRegionStyle->hasBackground() || renderBoxRegionStyle->hasBorder() || renderBoxRegionStyle->hasAppearance() || renderBoxRegionStyle->boxShadow();
+ (const_cast<RenderBox*>(box))->setHasBoxDecorations(hasBoxDecorations);
}
+
+ return renderBoxRegionStyle.release();
}
-void RenderRegion::clearObjectStyleInRegion(const RenderObject* object)
+void RenderRegion::clearBoxStyleInRegion(const RenderBox* box)
{
- ASSERT(object);
- m_renderObjectRegionStyle.remove(object);
+ ASSERT(box);
+ m_renderBoxRegionStyle.remove(box);
}
} // namespace WebCore
bool isFirstRegion() const;
bool isLastRegion() const;
- RenderStyle* renderObjectRegionStyle(const RenderObject*) const;
- void computeStyleInRegion(const RenderObject*);
- void clearObjectStyleInRegion(const RenderObject*);
+ void clearBoxStyleInRegion(const RenderBox*);
private:
virtual const char* renderName() const { return "RenderRegion"; }
+ PassRefPtr<RenderStyle> renderBoxRegionStyle(const RenderBox*);
+ PassRefPtr<RenderStyle> computeStyleInRegion(const RenderBox*);
+ void setRegionBoxesRegionStyle();
+ void restoreRegionBoxesOriginalStyle();
+
RenderFlowThread* m_flowThread;
// If this RenderRegion is displayed as part of another flow,
// A RenderBoxRegionInfo* tells us about any layout information for a RenderBox that
// is unique to the region. For now it just holds logical width information for RenderBlocks, but eventually
// it will also hold a custom style for any box (for region styling).
- HashMap<const RenderBox*, OwnPtr<RenderBoxRegionInfo> > m_renderBoxRegionInfo;
+ typedef HashMap<const RenderBox*, OwnPtr<RenderBoxRegionInfo> > RenderBoxRegionInfoMap;
+ RenderBoxRegionInfoMap m_renderBoxRegionInfo;
- // This map holds information about the region style associated with the render objects that
- // are displayed into this region.
- typedef HashMap<const RenderObject*, RefPtr<RenderStyle> > RenderObjectRegionStyleMap;
- RenderObjectRegionStyleMap m_renderObjectRegionStyle;
+ typedef HashMap<const RenderBox*, RefPtr<RenderStyle> > RenderBoxRegionStyleMap;
+ RenderBoxRegionStyleMap m_renderBoxRegionStyle;
bool m_isValid;
bool m_hasCustomRegionStyle;
+
+#ifndef NDEBUG
+ bool m_insideRegionPaint;
+#endif
};
inline RenderRegion* toRenderRegion(RenderObject* object)
, m_layoutState(0)
, m_layoutStateDisableCount(0)
, m_currentRenderFlowThread(0)
- , m_currentRenderRegion(0)
{
// Clear our anonymous bit, set because RenderObject assumes
// any renderer with document as the node is anonymous.
namespace WebCore {
class RenderFlowThread;
-class RenderRegion;
class RenderWidget;
#if USE(ACCELERATED_COMPOSITING)
RenderFlowThread* currentRenderFlowThread() const { return m_currentRenderFlowThread; }
void setCurrentRenderFlowThread(RenderFlowThread* flowThread) { m_currentRenderFlowThread = flowThread; }
- RenderRegion* currentRenderRegion() const { return m_currentRenderRegion; }
- void setCurrentRenderRegion(RenderRegion* region) { m_currentRenderRegion = region; }
-
void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
IntervalArena* intervalArena();
#endif
OwnPtr<RenderFlowThreadList> m_renderFlowThreadList;
RenderFlowThread* m_currentRenderFlowThread;
- RenderRegion* m_currentRenderRegion;
RefPtr<IntervalArena> m_intervalArena;
};