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