Remove redundant helper from RenderRegion.
[WebKit-https.git] / Source / WebCore / rendering / RenderRegion.cpp
1 /*
2  * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above
9  *    copyright notice, this list of conditions and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above
12  *    copyright notice, this list of conditions and the following
13  *    disclaimer in the documentation and/or other materials
14  *    provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "RenderRegion.h"
32
33 #include "FlowThreadController.h"
34 #include "GraphicsContext.h"
35 #include "HitTestResult.h"
36 #include "IntRect.h"
37 #include "LayoutRepainter.h"
38 #include "PaintInfo.h"
39 #include "Range.h"
40 #include "RenderBoxRegionInfo.h"
41 #include "RenderNamedFlowThread.h"
42 #include "RenderView.h"
43 #include "StyleResolver.h"
44 #include <wtf/StackStats.h>
45
46 using namespace std;
47
48 namespace WebCore {
49
50 RenderRegion::RenderRegion(Element* element, RenderFlowThread* flowThread)
51     : RenderBlock(element)
52     , m_flowThread(flowThread)
53     , m_parentNamedFlowThread(0)
54     , m_isValid(false)
55     , m_hasCustomRegionStyle(false)
56     , m_hasAutoLogicalHeight(false)
57 {
58 }
59
60 LayoutUnit RenderRegion::pageLogicalWidth() const
61 {
62     ASSERT(m_flowThread);
63     return m_flowThread->isHorizontalWritingMode() ? contentWidth() : contentHeight();
64 }
65
66 LayoutUnit RenderRegion::pageLogicalHeight() const
67 {
68     ASSERT(m_flowThread);
69     if (hasOverrideHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
70         ASSERT(hasAutoLogicalHeight());
71         return overrideLogicalContentHeight();
72     }
73     return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth();
74 }
75
76 // This method returns the maximum page size of a region with auto-height. This is the initial
77 // height value for auto-height regions in the first layout phase of the parent named flow.
78 LayoutUnit RenderRegion::maxPageLogicalHeight() const
79 {
80     ASSERT(m_flowThread);
81     ASSERT(hasAutoLogicalHeight() && !m_flowThread->inConstrainedLayoutPhase());
82     return style()->logicalMaxHeight().isUndefined() ? LayoutUnit::max() / 2 : computeReplacedLogicalHeightUsing(style()->logicalMaxHeight());
83 }
84
85 LayoutUnit RenderRegion::logicalHeightOfAllFlowThreadContent() const
86 {
87     ASSERT(m_flowThread);
88     if (hasOverrideHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
89         ASSERT(hasAutoLogicalHeight());
90         return overrideLogicalContentHeight();
91     }
92     return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth();
93 }
94
95 LayoutRect RenderRegion::flowThreadPortionOverflowRect() const
96 {
97     return overflowRectForFlowThreadPortion(flowThreadPortionRect(), isFirstRegion(), isLastRegion());
98 }
99
100 LayoutRect RenderRegion::overflowRectForFlowThreadPortion(const LayoutRect& flowThreadPortionRect, bool isFirstPortion, bool isLastPortion) const
101 {
102     ASSERT(isValid());
103
104     // FIXME: Would like to just use hasOverflowClip() but we aren't a block yet. When RenderRegion is eliminated and
105     // folded into RenderBlock, switch to hasOverflowClip().
106     bool clipX = style()->overflowX() != OVISIBLE;
107     bool clipY = style()->overflowY() != OVISIBLE;
108     bool isLastRegionWithRegionFragmentBreak = (isLastPortion && (style()->regionFragment() == BreakRegionFragment));
109     if ((clipX && clipY) || isLastRegionWithRegionFragmentBreak)
110         return flowThreadPortionRect;
111
112     LayoutRect flowThreadOverflow = m_flowThread->visualOverflowRect();
113
114     // Only clip along the flow thread axis.
115     LayoutUnit outlineSize = maximalOutlineSize(PaintPhaseOutline);
116     LayoutRect clipRect;
117     if (m_flowThread->isHorizontalWritingMode()) {
118         LayoutUnit minY = isFirstPortion ? (flowThreadOverflow.y() - outlineSize) : flowThreadPortionRect.y();
119         LayoutUnit maxY = isLastPortion ? max(flowThreadPortionRect.maxY(), flowThreadOverflow.maxY()) + outlineSize : flowThreadPortionRect.maxY();
120         LayoutUnit minX = clipX ? flowThreadPortionRect.x() : min(flowThreadPortionRect.x(), flowThreadOverflow.x() - outlineSize);
121         LayoutUnit maxX = clipX ? flowThreadPortionRect.maxX() : max(flowThreadPortionRect.maxX(), (flowThreadOverflow.maxX() + outlineSize));
122         clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
123     } else {
124         LayoutUnit minX = isFirstPortion ? (flowThreadOverflow.x() - outlineSize) : flowThreadPortionRect.x();
125         LayoutUnit maxX = isLastPortion ? max(flowThreadPortionRect.maxX(), flowThreadOverflow.maxX()) + outlineSize : flowThreadPortionRect.maxX();
126         LayoutUnit minY = clipY ? flowThreadPortionRect.y() : min(flowThreadPortionRect.y(), (flowThreadOverflow.y() - outlineSize));
127         LayoutUnit maxY = clipY ? flowThreadPortionRect.maxY() : max(flowThreadPortionRect.y(), (flowThreadOverflow.maxY() + outlineSize));
128         clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
129     }
130
131     return clipRect;
132 }
133
134 RegionOversetState RenderRegion::regionOversetState() const
135 {
136     ASSERT(node());
137
138     if (!isValid())
139         return RegionUndefined;
140
141     if (Element* element = toElement(node()))
142         return element->regionOversetState();
143     
144     return RegionUndefined;
145 }
146
147 void RenderRegion::setRegionOversetState(RegionOversetState state)
148 {
149     ASSERT(node());
150
151     if (Element* element = toElement(node()))
152         element->setRegionOversetState(state);
153 }
154
155 LayoutUnit RenderRegion::pageLogicalTopForOffset(LayoutUnit /* offset */) const
156 {
157     return flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x();
158 }
159
160 bool RenderRegion::isFirstRegion() const
161 {
162     ASSERT(isValid());
163
164     return m_flowThread->firstRegion() == this;
165 }
166
167 bool RenderRegion::isLastRegion() const
168 {
169     ASSERT(isValid());
170
171     return m_flowThread->lastRegion() == this;
172 }
173
174 static bool shouldPaintRegionContentsInPhase(PaintPhase phase)
175 {
176     return phase == PaintPhaseBlockBackground
177         || phase == PaintPhaseChildBlockBackground
178         || phase == PaintPhaseSelection
179         || phase == PaintPhaseTextClip;
180 }
181
182 void RenderRegion::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
183 {
184     if (style()->visibility() != VISIBLE)
185         return;
186
187     RenderBlock::paintObject(paintInfo, paintOffset);
188
189     if (!isValid())
190         return;
191
192     // We do not want to paint a region's contents multiple times (for each paint phase of the region object).
193     // Thus, we only paint the region's contents in certain phases.
194     if (!shouldPaintRegionContentsInPhase(paintInfo.phase))
195         return;
196
197     // Delegate the painting of a region's contents to RenderFlowThread.
198     // RenderFlowThread is a self painting layer because it's a positioned object.
199     // RenderFlowThread paints its children, the collected objects.
200     setRegionObjectsRegionStyle();
201     m_flowThread->paintFlowThreadPortionInRegion(paintInfo, this, flowThreadPortionRect(), flowThreadPortionOverflowRect(), LayoutPoint(paintOffset.x() + borderLeft() + paddingLeft(), paintOffset.y() + borderTop() + paddingTop()));
202     restoreRegionObjectsOriginalStyle();
203 }
204
205 // Hit Testing
206 bool RenderRegion::hitTestContents(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
207 {
208     if (!isValid() || action != HitTestForeground)
209         return false;
210
211     LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
212     boundsRect.moveBy(accumulatedOffset);
213     if (visibleToHitTesting() && locationInContainer.intersects(boundsRect)) {
214         if (m_flowThread->hitTestFlowThreadPortionInRegion(this, flowThreadPortionRect(), flowThreadPortionOverflowRect(), request, result,
215             locationInContainer, LayoutPoint(accumulatedOffset.x() + borderLeft() + paddingLeft(), accumulatedOffset.y() + borderTop() + paddingTop())))
216             return true;
217     }
218
219     return false;
220 }
221
222 void RenderRegion::checkRegionStyle()
223 {
224     ASSERT(m_flowThread);
225     bool customRegionStyle = false;
226
227     // FIXME: Region styling doesn't work for pseudo elements.
228     if (node()) {
229         Element* regionElement = toElement(node());
230         customRegionStyle = view()->document()->ensureStyleResolver()->checkRegionStyle(regionElement);
231     }
232     setHasCustomRegionStyle(customRegionStyle);
233     m_flowThread->checkRegionsWithStyling();
234 }
235
236 void RenderRegion::incrementAutoLogicalHeightCount()
237 {
238     ASSERT(isValid());
239     ASSERT(m_hasAutoLogicalHeight);
240
241     m_flowThread->incrementAutoLogicalHeightRegions();
242 }
243
244 void RenderRegion::decrementAutoLogicalHeightCount()
245 {
246     ASSERT(isValid());
247
248     m_flowThread->decrementAutoLogicalHeightRegions();
249 }
250
251 void RenderRegion::updateRegionHasAutoLogicalHeightFlag()
252 {
253     ASSERT(m_flowThread);
254
255     if (!isValid())
256         return;
257
258     bool didHaveAutoLogicalHeight = m_hasAutoLogicalHeight;
259     m_hasAutoLogicalHeight = shouldHaveAutoLogicalHeight();
260     if (m_hasAutoLogicalHeight != didHaveAutoLogicalHeight) {
261         if (m_hasAutoLogicalHeight)
262             incrementAutoLogicalHeightCount();
263         else {
264             clearOverrideLogicalContentHeight();
265             decrementAutoLogicalHeightCount();
266         }
267     }
268 }
269
270 bool RenderRegion::shouldHaveAutoLogicalHeight() const
271 {
272     bool hasSpecifiedEndpointsForHeight = style()->logicalTop().isSpecified() && style()->logicalBottom().isSpecified();
273     bool hasAnchoredEndpointsForHeight = isOutOfFlowPositioned() && hasSpecifiedEndpointsForHeight;
274     return style()->logicalHeight().isAuto() && !hasAnchoredEndpointsForHeight;
275 }
276     
277 void RenderRegion::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
278 {
279     RenderBlock::styleDidChange(diff, oldStyle);
280
281     // If the region is not attached to any thread, there is no need to check
282     // whether the region has region styling since no content will be displayed
283     // into the region.
284     if (!m_flowThread) {
285         setHasCustomRegionStyle(false);
286         return;
287     }
288
289     checkRegionStyle();
290     updateRegionHasAutoLogicalHeightFlag();
291 }
292
293 void RenderRegion::layoutBlock(bool relayoutChildren, LayoutUnit)
294 {
295     StackStats::LayoutCheckPoint layoutCheckPoint;
296     RenderBlock::layoutBlock(relayoutChildren);
297
298     if (isValid()) {
299         LayoutRect oldRegionRect(flowThreadPortionRect());
300         if (!isHorizontalWritingMode())
301             oldRegionRect = oldRegionRect.transposedRect();
302
303         if (hasAutoLogicalHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
304             m_flowThread->invalidateRegions();
305             clearOverrideLogicalContentHeight();
306             return;
307         }
308
309         if (!isRenderRegionSet() && (oldRegionRect.width() != pageLogicalWidth() || oldRegionRect.height() != pageLogicalHeight()))
310             // This can happen even if we are in the inConstrainedLayoutPhase and it will trigger a pathological layout of the flow thread.
311             m_flowThread->invalidateRegions();
312     }
313
314     // FIXME: We need to find a way to set up overflow properly. Our flow thread hasn't gotten a layout
315     // yet, so we can't look to it for correct information. It's possible we could wait until after the RenderFlowThread
316     // gets a layout, and then try to propagate overflow information back to the region, and then mark for a second layout.
317     // That second layout would then be able to use the information from the RenderFlowThread to set up overflow.
318     //
319     // The big problem though is that overflow needs to be region-specific. We can't simply use the RenderFlowThread's global
320     // overflow values, since then we'd always think any narrow region had huge overflow (all the way to the width of the
321     // RenderFlowThread itself).
322     //
323     // We'll need to expand RenderBoxRegionInfo to also hold left and right overflow values.
324 }
325
326 void RenderRegion::repaintFlowThreadContent(const LayoutRect& repaintRect, bool immediate) const
327 {
328     repaintFlowThreadContentRectangle(repaintRect, immediate, flowThreadPortionRect(), flowThreadPortionOverflowRect(), contentBoxRect().location());
329 }
330
331 void RenderRegion::repaintFlowThreadContentRectangle(const LayoutRect& repaintRect, bool immediate, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, const LayoutPoint& regionLocation) const
332 {
333     ASSERT(isValid());
334
335     // We only have to issue a repaint in this region if the region rect intersects the repaint rect.
336     LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
337     LayoutRect flippedFlowThreadPortionOverflowRect(flowThreadPortionOverflowRect);
338     flowThread()->flipForWritingMode(flippedFlowThreadPortionRect); // Put the region rects into physical coordinates.
339     flowThread()->flipForWritingMode(flippedFlowThreadPortionOverflowRect);
340
341     LayoutRect clippedRect(repaintRect);
342     clippedRect.intersect(flippedFlowThreadPortionOverflowRect);
343     if (clippedRect.isEmpty())
344         return;
345
346     // Put the region rect into the region's physical coordinate space.
347     clippedRect.setLocation(regionLocation + (clippedRect.location() - flippedFlowThreadPortionRect.location()));
348
349     // Now switch to the region's writing mode coordinate space and let it repaint itself.
350     flipForWritingMode(clippedRect);
351     
352     // Issue the repaint.
353     repaintRectangle(clippedRect, immediate);
354 }
355
356 void RenderRegion::installFlowThread()
357 {
358     ASSERT(view());
359
360     m_flowThread = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread());
361
362     // By now the flow thread should already be added to the rendering tree,
363     // so we go up the rendering parents and check that this region is not part of the same
364     // flow that it actually needs to display. It would create a circular reference.
365     RenderObject* parentObject = parent();
366     m_parentNamedFlowThread = 0;
367     for ( ; parentObject; parentObject = parentObject->parent()) {
368         if (parentObject->isRenderNamedFlowThread()) {
369             m_parentNamedFlowThread = toRenderNamedFlowThread(parentObject);
370             // Do not take into account a region that links a flow with itself. The dependency
371             // cannot change, so it is not worth adding it to the list.
372             if (m_flowThread == m_parentNamedFlowThread)
373                 m_flowThread = 0;
374             break;
375         }
376     }
377 }
378
379 void RenderRegion::attachRegion()
380 {
381     if (documentBeingDestroyed())
382         return;
383     
384     // A region starts off invalid.
385     setIsValid(false);
386
387     // Initialize the flow thread reference and create the flow thread object if needed.
388     // The flow thread lifetime is influenced by the number of regions attached to it,
389     // and we are attaching the region to the flow thread.
390     installFlowThread();
391     
392     if (!m_flowThread)
393         return;
394
395     // Only after adding the region to the thread, the region is marked to be valid.
396     m_flowThread->addRegionToThread(this);
397
398     // The region just got attached to the flow thread, lets check whether
399     // it has region styling rules associated.
400     checkRegionStyle();
401
402     if (!isValid())
403         return;
404
405     m_hasAutoLogicalHeight = shouldHaveAutoLogicalHeight();
406     if (hasAutoLogicalHeight())
407         incrementAutoLogicalHeightCount();
408 }
409
410 void RenderRegion::detachRegion()
411 {
412     if (m_flowThread) {
413         m_flowThread->removeRegionFromThread(this);
414         if (hasAutoLogicalHeight())
415             decrementAutoLogicalHeightCount();
416     }
417     m_flowThread = 0;
418 }
419
420 RenderBoxRegionInfo* RenderRegion::renderBoxRegionInfo(const RenderBox* box) const
421 {
422     ASSERT(isValid());
423     return m_renderBoxRegionInfo.get(box);
424 }
425
426 RenderBoxRegionInfo* RenderRegion::setRenderBoxRegionInfo(const RenderBox* box, LayoutUnit logicalLeftInset, LayoutUnit logicalRightInset,
427     bool containingBlockChainIsInset)
428 {
429     ASSERT(isValid());
430
431     OwnPtr<RenderBoxRegionInfo>& boxInfo = m_renderBoxRegionInfo.add(box, nullptr).iterator->value;
432     if (boxInfo)
433         *boxInfo = RenderBoxRegionInfo(logicalLeftInset, logicalRightInset, containingBlockChainIsInset);
434     else
435         boxInfo = adoptPtr(new RenderBoxRegionInfo(logicalLeftInset, logicalRightInset, containingBlockChainIsInset));
436
437     return boxInfo.get();
438 }
439
440 PassOwnPtr<RenderBoxRegionInfo> RenderRegion::takeRenderBoxRegionInfo(const RenderBox* box)
441 {
442     return m_renderBoxRegionInfo.take(box);
443 }
444
445 void RenderRegion::removeRenderBoxRegionInfo(const RenderBox* box)
446 {
447     m_renderBoxRegionInfo.remove(box);
448 }
449
450 void RenderRegion::deleteAllRenderBoxRegionInfo()
451 {
452     m_renderBoxRegionInfo.clear();
453 }
454
455 LayoutUnit RenderRegion::logicalTopOfFlowThreadContentRect(const LayoutRect& rect) const
456 {
457     ASSERT(isValid());
458     return flowThread()->isHorizontalWritingMode() ? rect.y() : rect.x();
459 }
460
461 LayoutUnit RenderRegion::logicalBottomOfFlowThreadContentRect(const LayoutRect& rect) const
462 {
463     ASSERT(isValid());
464     return flowThread()->isHorizontalWritingMode() ? rect.maxY() : rect.maxX();
465 }
466
467 void RenderRegion::setRegionObjectsRegionStyle()
468 {
469     if (!hasCustomRegionStyle())
470         return;
471
472     // Start from content nodes and recursively compute the style in region for the render objects below.
473     // If the style in region was already computed, used that style instead of computing a new one.
474     RenderNamedFlowThread* namedFlow = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread());
475     const NamedFlowContentNodes& contentNodes = namedFlow->contentNodes();
476
477     for (NamedFlowContentNodes::const_iterator iter = contentNodes.begin(), end = contentNodes.end(); iter != end; ++iter) {
478         const Node* node = *iter;
479         // The list of content nodes contains also the nodes with display:none.
480         if (!node->renderer())
481             continue;
482
483         RenderObject* object = node->renderer();
484         // If the content node does not flow any of its children in this region,
485         // we do not compute any style for them in this region.
486         if (!flowThread()->objectInFlowRegion(object, this))
487             continue;
488
489         // If the object has style in region, use that instead of computing a new one.
490         RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find(object);
491         RefPtr<RenderStyle> objectStyleInRegion;
492         bool objectRegionStyleCached = false;
493         if (it != m_renderObjectRegionStyle.end()) {
494             objectStyleInRegion = it->value.style;
495             ASSERT(it->value.cached);
496             objectRegionStyleCached = true;
497         } else
498             objectStyleInRegion = computeStyleInRegion(object);
499
500         setObjectStyleInRegion(object, objectStyleInRegion, objectRegionStyleCached);
501
502         computeChildrenStyleInRegion(object);
503     }
504 }
505
506 void RenderRegion::restoreRegionObjectsOriginalStyle()
507 {
508     if (!hasCustomRegionStyle())
509         return;
510
511     RenderObjectRegionStyleMap temp;
512     for (RenderObjectRegionStyleMap::iterator iter = m_renderObjectRegionStyle.begin(), end = m_renderObjectRegionStyle.end(); iter != end; ++iter) {
513         RenderObject* object = const_cast<RenderObject*>(iter->key);
514         RefPtr<RenderStyle> objectRegionStyle = object->style();
515         RefPtr<RenderStyle> objectOriginalStyle = iter->value.style;
516         object->setStyleInternal(objectOriginalStyle);
517
518         bool shouldCacheRegionStyle = iter->value.cached;
519         if (!shouldCacheRegionStyle) {
520             // Check whether we should cache the computed style in region.
521             unsigned changedContextSensitiveProperties = ContextSensitivePropertyNone;
522             StyleDifference styleDiff = objectOriginalStyle->diff(objectRegionStyle.get(), changedContextSensitiveProperties);
523             if (styleDiff < StyleDifferenceLayoutPositionedMovementOnly)
524                 shouldCacheRegionStyle = true;
525         }
526         if (shouldCacheRegionStyle) {
527             ObjectRegionStyleInfo styleInfo;
528             styleInfo.style = objectRegionStyle;
529             styleInfo.cached = true;
530             temp.set(object, styleInfo);
531         }
532     }
533
534     m_renderObjectRegionStyle.swap(temp);
535 }
536
537 void RenderRegion::insertedIntoTree()
538 {
539     RenderBlock::insertedIntoTree();
540
541     attachRegion();
542 }
543
544 void RenderRegion::willBeRemovedFromTree()
545 {
546     RenderBlock::willBeRemovedFromTree();
547
548     detachRegion();
549 }
550
551 PassRefPtr<RenderStyle> RenderRegion::computeStyleInRegion(const RenderObject* object)
552 {
553     ASSERT(object);
554     ASSERT(object->view());
555     ASSERT(object->view()->document());
556     ASSERT(!object->isAnonymous());
557     ASSERT(object->node() && object->node()->isElementNode());
558
559     // FIXME: Region styling fails for pseudo-elements because the renderers don't have a node.
560     Element* element = toElement(object->node());
561     RefPtr<RenderStyle> renderObjectRegionStyle = object->view()->document()->ensureStyleResolver()->styleForElement(element, 0, DisallowStyleSharing, MatchAllRules, this);
562
563     return renderObjectRegionStyle.release();
564 }
565
566 void RenderRegion::computeChildrenStyleInRegion(const RenderObject* object)
567 {
568     for (RenderObject* child = object->firstChild(); child; child = child->nextSibling()) {
569
570         RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find(child);
571
572         RefPtr<RenderStyle> childStyleInRegion;
573         bool objectRegionStyleCached = false;
574         if (it != m_renderObjectRegionStyle.end()) {
575             childStyleInRegion = it->value.style;
576             objectRegionStyleCached = true;
577         } else {
578             if (child->isAnonymous() || child->isInFlowRenderFlowThread())
579                 childStyleInRegion = RenderStyle::createAnonymousStyleWithDisplay(object->style(), child->style()->display());
580             else if (child->isText())
581                 childStyleInRegion = RenderStyle::clone(object->style());
582             else
583                 childStyleInRegion = computeStyleInRegion(child);
584         }
585
586         setObjectStyleInRegion(child, childStyleInRegion, objectRegionStyleCached);
587
588         computeChildrenStyleInRegion(child);
589     }
590 }
591
592 void RenderRegion::setObjectStyleInRegion(RenderObject* object, PassRefPtr<RenderStyle> styleInRegion, bool objectRegionStyleCached)
593 {
594     ASSERT(object->flowThreadContainingBlock());
595
596     RefPtr<RenderStyle> objectOriginalStyle = object->style();
597     object->setStyleInternal(styleInRegion);
598
599     if (object->isBoxModelObject() && !object->hasBoxDecorations()) {
600         bool hasBoxDecorations = object->isTableCell()
601         || object->style()->hasBackground()
602         || object->style()->hasBorder()
603         || object->style()->hasAppearance()
604         || object->style()->boxShadow();
605         object->setHasBoxDecorations(hasBoxDecorations);
606     }
607
608     ObjectRegionStyleInfo styleInfo;
609     styleInfo.style = objectOriginalStyle;
610     styleInfo.cached = objectRegionStyleCached;
611     m_renderObjectRegionStyle.set(object, styleInfo);
612 }
613
614 void RenderRegion::clearObjectStyleInRegion(const RenderObject* object)
615 {
616     ASSERT(object);
617     m_renderObjectRegionStyle.remove(object);
618
619     // Clear the style for the children of this object.
620     for (RenderObject* child = object->firstChild(); child; child = child->nextSibling())
621         clearObjectStyleInRegion(child);
622 }
623
624 void RenderRegion::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
625 {
626     if (!isValid()) {
627         RenderBlock::computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);
628         return;
629     }
630
631     minLogicalWidth = m_flowThread->minPreferredLogicalWidth();
632     maxLogicalWidth = m_flowThread->maxPreferredLogicalWidth();
633 }
634
635 void RenderRegion::computePreferredLogicalWidths()
636 {
637     ASSERT(preferredLogicalWidthsDirty());
638
639     if (!isValid()) {
640         RenderBlock::computePreferredLogicalWidths();
641         return;
642     }
643
644     // FIXME: Currently, the code handles only the <length> case for min-width/max-width.
645     // It should also support other values, like percentage, calc or viewport relative.
646     m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
647
648     RenderStyle* styleToUse = style();
649     if (styleToUse->logicalWidth().isFixed() && styleToUse->logicalWidth().value() > 0)
650         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalWidth().value());
651     else
652         computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
653
654     if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
655         m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
656         m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
657     }
658
659     if (styleToUse->logicalMaxWidth().isFixed()) {
660         m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
661         m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
662     }
663
664     LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
665     m_minPreferredLogicalWidth += borderAndPadding;
666     m_maxPreferredLogicalWidth += borderAndPadding;
667     setPreferredLogicalWidthsDirty(false);
668 }
669
670 void RenderRegion::getRanges(Vector<RefPtr<Range> >& rangeObjects) const
671 {
672     RenderNamedFlowThread* namedFlow = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread());
673     namedFlow->getRanges(rangeObjects, this);
674 }
675
676 void RenderRegion::updateLogicalHeight()
677 {
678     RenderBlock::updateLogicalHeight();
679
680     if (!hasAutoLogicalHeight())
681         return;
682
683     // We want to update the logical height based on the computed override logical
684     // content height only if the view is in the layout phase
685     // in which all the auto logical height regions have their override logical height set.
686     if (!m_flowThread->inConstrainedLayoutPhase())
687         return;
688
689     // There may be regions with auto logical height that during the prerequisite layout phase
690     // did not have the chance to layout flow thread content. Because of that, these regions do not
691     // have an overrideLogicalContentHeight computed and they will not be able to fragment any flow
692     // thread content.
693     if (!hasOverrideHeight())
694         return;
695
696     LayoutUnit newLogicalHeight = overrideLogicalContentHeight() + borderAndPaddingLogicalHeight();
697     ASSERT(newLogicalHeight < LayoutUnit::max() / 2);
698     if (newLogicalHeight > logicalHeight()) {
699         setLogicalHeight(newLogicalHeight);
700         // Recalculate position of the render block after new logical height is set.
701         // (needed in absolute positioning case with bottom alignment for example)
702         RenderBlock::updateLogicalHeight();
703     }
704 }
705
706 } // namespace WebCore