Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2007 David Smith (catfish.man (at) gmail.com)
      5  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      6  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Library General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Library General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Library General Public License
     19  * along with this library; see the file COPYING.LIB.  If not, write to
     20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21  * Boston, MA 02110-1301, USA.
     22  */
     23 
     24 #include "config.h"
     25 #include "core/rendering/FloatingObjects.h"
     26 
     27 #include "core/rendering/RenderBlockFlow.h"
     28 #include "core/rendering/RenderBox.h"
     29 #include "core/rendering/RenderView.h"
     30 
     31 using namespace std;
     32 using namespace WTF;
     33 
     34 namespace WebCore {
     35 
     36 struct SameSizeAsFloatingObject {
     37     void* pointers[2];
     38     LayoutRect rect;
     39     int paginationStrut;
     40     uint32_t bitfields : 8;
     41 };
     42 
     43 COMPILE_ASSERT(sizeof(FloatingObject) == sizeof(SameSizeAsFloatingObject), FloatingObject_should_stay_small);
     44 
     45 FloatingObject::FloatingObject(RenderBox* renderer)
     46     : m_renderer(renderer)
     47     , m_originatingLine(0)
     48     , m_paginationStrut(0)
     49     , m_shouldPaint(true)
     50     , m_isDescendant(false)
     51     , m_isPlaced(false)
     52 #ifndef NDEBUG
     53     , m_isInPlacedTree(false)
     54 #endif
     55 {
     56     EFloat type = renderer->style()->floating();
     57     ASSERT(type != NoFloat);
     58     if (type == LeftFloat)
     59         m_type = FloatLeft;
     60     else if (type == RightFloat)
     61         m_type = FloatRight;
     62 }
     63 
     64 FloatingObject::FloatingObject(RenderBox* renderer, Type type, const LayoutRect& frameRect, bool shouldPaint, bool isDescendant)
     65     : m_renderer(renderer)
     66     , m_originatingLine(0)
     67     , m_frameRect(frameRect)
     68     , m_paginationStrut(0)
     69     , m_type(type)
     70     , m_shouldPaint(shouldPaint)
     71     , m_isDescendant(isDescendant)
     72     , m_isPlaced(true)
     73 #ifndef NDEBUG
     74     , m_isInPlacedTree(false)
     75 #endif
     76 {
     77 }
     78 
     79 PassOwnPtr<FloatingObject> FloatingObject::create(RenderBox* renderer)
     80 {
     81     OwnPtr<FloatingObject> newObj = adoptPtr(new FloatingObject(renderer));
     82     newObj->setShouldPaint(!renderer->hasSelfPaintingLayer()); // If a layer exists, the float will paint itself. Otherwise someone else will.
     83     newObj->setIsDescendant(true);
     84 
     85     return newObj.release();
     86 }
     87 
     88 PassOwnPtr<FloatingObject> FloatingObject::copyToNewContainer(LayoutSize offset, bool shouldPaint, bool isDescendant) const
     89 {
     90     return adoptPtr(new FloatingObject(renderer(), type(), LayoutRect(frameRect().location() - offset, frameRect().size()), shouldPaint, isDescendant));
     91 }
     92 
     93 PassOwnPtr<FloatingObject> FloatingObject::unsafeClone() const
     94 {
     95     OwnPtr<FloatingObject> cloneObject = adoptPtr(new FloatingObject(renderer(), type(), m_frameRect, m_shouldPaint, m_isDescendant));
     96     cloneObject->m_paginationStrut = m_paginationStrut;
     97     cloneObject->m_isPlaced = m_isPlaced;
     98     return cloneObject.release();
     99 }
    100 
    101 template <FloatingObject::Type FloatTypeValue>
    102 class ComputeFloatOffsetAdapter {
    103 public:
    104     typedef FloatingObjectInterval IntervalType;
    105 
    106     ComputeFloatOffsetAdapter(const RenderBlockFlow* renderer, int lineTop, int lineBottom, LayoutUnit offset)
    107         : m_renderer(renderer)
    108         , m_lineTop(lineTop)
    109         , m_lineBottom(lineBottom)
    110         , m_offset(offset)
    111         , m_outermostFloat(0)
    112     {
    113     }
    114 
    115     virtual ~ComputeFloatOffsetAdapter() { }
    116 
    117     int lowValue() const { return m_lineTop; }
    118     int highValue() const { return m_lineBottom; }
    119     void collectIfNeeded(const IntervalType&);
    120 
    121     LayoutUnit offset() const { return m_offset; }
    122 
    123 protected:
    124     virtual bool updateOffsetIfNeeded(const FloatingObject*) = 0;
    125 
    126     const RenderBlockFlow* m_renderer;
    127     int m_lineTop;
    128     int m_lineBottom;
    129     LayoutUnit m_offset;
    130     const FloatingObject* m_outermostFloat;
    131 };
    132 
    133 template <FloatingObject::Type FloatTypeValue>
    134 class ComputeFloatOffsetForFloatLayoutAdapter : public ComputeFloatOffsetAdapter<FloatTypeValue> {
    135 public:
    136     ComputeFloatOffsetForFloatLayoutAdapter(const RenderBlockFlow* renderer, LayoutUnit lineTop, LayoutUnit lineBottom, LayoutUnit offset)
    137         : ComputeFloatOffsetAdapter<FloatTypeValue>(renderer, lineTop, lineBottom, offset)
    138     {
    139     }
    140 
    141     virtual ~ComputeFloatOffsetForFloatLayoutAdapter() { }
    142 
    143     LayoutUnit heightRemaining() const;
    144 
    145 protected:
    146     virtual bool updateOffsetIfNeeded(const FloatingObject*) OVERRIDE FINAL;
    147 };
    148 
    149 template <FloatingObject::Type FloatTypeValue>
    150 class ComputeFloatOffsetForLineLayoutAdapter : public ComputeFloatOffsetAdapter<FloatTypeValue> {
    151 public:
    152     ComputeFloatOffsetForLineLayoutAdapter(const RenderBlockFlow* renderer, LayoutUnit lineTop, LayoutUnit lineBottom, LayoutUnit offset)
    153         : ComputeFloatOffsetAdapter<FloatTypeValue>(renderer, lineTop, lineBottom, offset)
    154     {
    155     }
    156 
    157     virtual ~ComputeFloatOffsetForLineLayoutAdapter() { }
    158 
    159 protected:
    160     virtual bool updateOffsetIfNeeded(const FloatingObject*) OVERRIDE FINAL;
    161 };
    162 
    163 
    164 FloatingObjects::~FloatingObjects()
    165 {
    166 }
    167 void FloatingObjects::clearLineBoxTreePointers()
    168 {
    169     // Clear references to originating lines, since the lines are being deleted
    170     FloatingObjectSetIterator end = m_set.end();
    171     for (FloatingObjectSetIterator it = m_set.begin(); it != end; ++it) {
    172         ASSERT(!((*it)->originatingLine()) || (*it)->originatingLine()->renderer() == m_renderer);
    173         (*it)->setOriginatingLine(0);
    174     }
    175 }
    176 
    177 FloatingObjects::FloatingObjects(const RenderBlockFlow* renderer, bool horizontalWritingMode)
    178     : m_placedFloatsTree(UninitializedTree)
    179     , m_leftObjectsCount(0)
    180     , m_rightObjectsCount(0)
    181     , m_horizontalWritingMode(horizontalWritingMode)
    182     , m_renderer(renderer)
    183     , m_cachedHorizontalWritingMode(false)
    184 {
    185 }
    186 
    187 void FloatingObjects::clear()
    188 {
    189     m_set.clear();
    190     m_placedFloatsTree.clear();
    191     m_leftObjectsCount = 0;
    192     m_rightObjectsCount = 0;
    193     markLowestFloatLogicalBottomCacheAsDirty();
    194 }
    195 
    196 LayoutUnit FloatingObjects::lowestFloatLogicalBottom(FloatingObject::Type floatType)
    197 {
    198     bool isInHorizontalWritingMode = m_horizontalWritingMode;
    199     if (floatType != FloatingObject::FloatLeftRight) {
    200         if (hasLowestFloatLogicalBottomCached(isInHorizontalWritingMode, floatType))
    201             return getCachedlowestFloatLogicalBottom(floatType);
    202     } else {
    203         if (hasLowestFloatLogicalBottomCached(isInHorizontalWritingMode, FloatingObject::FloatLeft) && hasLowestFloatLogicalBottomCached(isInHorizontalWritingMode, FloatingObject::FloatRight)) {
    204             return max(getCachedlowestFloatLogicalBottom(FloatingObject::FloatLeft),
    205                 getCachedlowestFloatLogicalBottom(FloatingObject::FloatRight));
    206         }
    207     }
    208 
    209     LayoutUnit lowestFloatBottom = 0;
    210     const FloatingObjectSet& floatingObjectSet = set();
    211     FloatingObjectSetIterator end = floatingObjectSet.end();
    212     if (floatType == FloatingObject::FloatLeftRight) {
    213         LayoutUnit lowestFloatBottomLeft = 0;
    214         LayoutUnit lowestFloatBottomRight = 0;
    215         for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
    216             FloatingObject* floatingObject = it->get();
    217             if (floatingObject->isPlaced()) {
    218                 FloatingObject::Type curType = floatingObject->type();
    219                 LayoutUnit curFloatLogicalBottom = m_renderer->logicalBottomForFloat(floatingObject);
    220                 if (curType & FloatingObject::FloatLeft)
    221                     lowestFloatBottomLeft = max(lowestFloatBottomLeft, curFloatLogicalBottom);
    222                 if (curType & FloatingObject::FloatRight)
    223                     lowestFloatBottomRight = max(lowestFloatBottomRight, curFloatLogicalBottom);
    224             }
    225         }
    226         lowestFloatBottom = max(lowestFloatBottomLeft, lowestFloatBottomRight);
    227         setCachedLowestFloatLogicalBottom(isInHorizontalWritingMode, FloatingObject::FloatLeft, lowestFloatBottomLeft);
    228         setCachedLowestFloatLogicalBottom(isInHorizontalWritingMode, FloatingObject::FloatRight, lowestFloatBottomRight);
    229     } else {
    230         for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
    231             FloatingObject* floatingObject = it->get();
    232             if (floatingObject->isPlaced() && floatingObject->type() == floatType)
    233                 lowestFloatBottom = max(lowestFloatBottom, m_renderer->logicalBottomForFloat(floatingObject));
    234         }
    235         setCachedLowestFloatLogicalBottom(isInHorizontalWritingMode, floatType, lowestFloatBottom);
    236     }
    237 
    238     return lowestFloatBottom;
    239 }
    240 
    241 bool FloatingObjects::hasLowestFloatLogicalBottomCached(bool isHorizontal, FloatingObject::Type type) const
    242 {
    243     int floatIndex = static_cast<int>(type) - 1;
    244     ASSERT(floatIndex < static_cast<int>(sizeof(m_lowestFloatBottomCache) / sizeof(FloatBottomCachedValue)));
    245     ASSERT(floatIndex >= 0);
    246     return (m_cachedHorizontalWritingMode == isHorizontal && !m_lowestFloatBottomCache[floatIndex].dirty);
    247 }
    248 
    249 LayoutUnit FloatingObjects::getCachedlowestFloatLogicalBottom(FloatingObject::Type type) const
    250 {
    251     int floatIndex = static_cast<int>(type) - 1;
    252     ASSERT(floatIndex < static_cast<int>(sizeof(m_lowestFloatBottomCache) / sizeof(FloatBottomCachedValue)));
    253     ASSERT(floatIndex >= 0);
    254     return m_lowestFloatBottomCache[floatIndex].value;
    255 }
    256 
    257 void FloatingObjects::setCachedLowestFloatLogicalBottom(bool isHorizontal, FloatingObject::Type type, LayoutUnit value)
    258 {
    259     int floatIndex = static_cast<int>(type) - 1;
    260     ASSERT(floatIndex < static_cast<int>(sizeof(m_lowestFloatBottomCache) / sizeof(FloatBottomCachedValue)));
    261     ASSERT(floatIndex >= 0);
    262     m_cachedHorizontalWritingMode = isHorizontal;
    263     m_lowestFloatBottomCache[floatIndex].value = value;
    264     m_lowestFloatBottomCache[floatIndex].dirty = false;
    265 }
    266 
    267 void FloatingObjects::markLowestFloatLogicalBottomCacheAsDirty()
    268 {
    269     for (size_t i = 0; i < sizeof(m_lowestFloatBottomCache) / sizeof(FloatBottomCachedValue); ++i)
    270         m_lowestFloatBottomCache[i].dirty = true;
    271 }
    272 
    273 void FloatingObjects::moveAllToFloatInfoMap(RendererToFloatInfoMap& map)
    274 {
    275     while (!m_set.isEmpty()) {
    276         OwnPtr<FloatingObject> floatingObject = m_set.takeFirst();
    277         RenderBox* renderer = floatingObject->renderer();
    278         map.add(renderer, floatingObject.release());
    279     }
    280     clear();
    281 }
    282 
    283 inline void FloatingObjects::increaseObjectsCount(FloatingObject::Type type)
    284 {
    285     if (type == FloatingObject::FloatLeft)
    286         m_leftObjectsCount++;
    287     else
    288         m_rightObjectsCount++;
    289 }
    290 
    291 inline void FloatingObjects::decreaseObjectsCount(FloatingObject::Type type)
    292 {
    293     if (type == FloatingObject::FloatLeft)
    294         m_leftObjectsCount--;
    295     else
    296         m_rightObjectsCount--;
    297 }
    298 
    299 inline FloatingObjectInterval FloatingObjects::intervalForFloatingObject(FloatingObject* floatingObject)
    300 {
    301     if (m_horizontalWritingMode)
    302         return FloatingObjectInterval(floatingObject->frameRect().pixelSnappedY(), floatingObject->frameRect().pixelSnappedMaxY(), floatingObject);
    303     return FloatingObjectInterval(floatingObject->frameRect().pixelSnappedX(), floatingObject->frameRect().pixelSnappedMaxX(), floatingObject);
    304 }
    305 
    306 void FloatingObjects::addPlacedObject(FloatingObject* floatingObject)
    307 {
    308     ASSERT(!floatingObject->isInPlacedTree());
    309 
    310     floatingObject->setIsPlaced(true);
    311     if (m_placedFloatsTree.isInitialized())
    312         m_placedFloatsTree.add(intervalForFloatingObject(floatingObject));
    313 
    314 #ifndef NDEBUG
    315     floatingObject->setIsInPlacedTree(true);
    316 #endif
    317     markLowestFloatLogicalBottomCacheAsDirty();
    318 }
    319 
    320 void FloatingObjects::removePlacedObject(FloatingObject* floatingObject)
    321 {
    322     ASSERT(floatingObject->isPlaced() && floatingObject->isInPlacedTree());
    323 
    324     if (m_placedFloatsTree.isInitialized()) {
    325         bool removed = m_placedFloatsTree.remove(intervalForFloatingObject(floatingObject));
    326         ASSERT_UNUSED(removed, removed);
    327     }
    328 
    329     floatingObject->setIsPlaced(false);
    330 #ifndef NDEBUG
    331     floatingObject->setIsInPlacedTree(false);
    332 #endif
    333     markLowestFloatLogicalBottomCacheAsDirty();
    334 }
    335 
    336 FloatingObject* FloatingObjects::add(PassOwnPtr<FloatingObject> floatingObject)
    337 {
    338     FloatingObject* newObject = floatingObject.leakPtr();
    339     increaseObjectsCount(newObject->type());
    340     m_set.add(adoptPtr(newObject));
    341     if (newObject->isPlaced())
    342         addPlacedObject(newObject);
    343     markLowestFloatLogicalBottomCacheAsDirty();
    344     return newObject;
    345 }
    346 
    347 void FloatingObjects::remove(FloatingObject* toBeRemoved)
    348 {
    349     decreaseObjectsCount(toBeRemoved->type());
    350     OwnPtr<FloatingObject> floatingObject = m_set.take(toBeRemoved);
    351     ASSERT(floatingObject->isPlaced() || !floatingObject->isInPlacedTree());
    352     if (floatingObject->isPlaced())
    353         removePlacedObject(floatingObject.get());
    354     markLowestFloatLogicalBottomCacheAsDirty();
    355     ASSERT(!floatingObject->originatingLine());
    356 }
    357 
    358 void FloatingObjects::computePlacedFloatsTree()
    359 {
    360     ASSERT(!m_placedFloatsTree.isInitialized());
    361     if (m_set.isEmpty())
    362         return;
    363     m_placedFloatsTree.initIfNeeded(m_renderer->view()->intervalArena());
    364     FloatingObjectSetIterator it = m_set.begin();
    365     FloatingObjectSetIterator end = m_set.end();
    366     for (; it != end; ++it) {
    367         FloatingObject* floatingObject = it->get();
    368         if (floatingObject->isPlaced())
    369             m_placedFloatsTree.add(intervalForFloatingObject(floatingObject));
    370     }
    371 }
    372 
    373 LayoutUnit FloatingObjects::logicalLeftOffsetForPositioningFloat(LayoutUnit fixedOffset, LayoutUnit logicalTop, LayoutUnit *heightRemaining)
    374 {
    375     int logicalTopAsInt = roundToInt(logicalTop);
    376     ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatLeft> adapter(m_renderer, logicalTopAsInt, logicalTopAsInt, fixedOffset);
    377     placedFloatsTree().allOverlapsWithAdapter(adapter);
    378 
    379     if (heightRemaining)
    380         *heightRemaining = adapter.heightRemaining();
    381 
    382     return adapter.offset();
    383 }
    384 
    385 LayoutUnit FloatingObjects::logicalRightOffsetForPositioningFloat(LayoutUnit fixedOffset, LayoutUnit logicalTop, LayoutUnit *heightRemaining)
    386 {
    387     int logicalTopAsInt = roundToInt(logicalTop);
    388     ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatRight> adapter(m_renderer, logicalTopAsInt, logicalTopAsInt, fixedOffset);
    389     placedFloatsTree().allOverlapsWithAdapter(adapter);
    390 
    391     if (heightRemaining)
    392         *heightRemaining = adapter.heightRemaining();
    393 
    394     return min(fixedOffset, adapter.offset());
    395 }
    396 
    397 LayoutUnit FloatingObjects::logicalLeftOffset(LayoutUnit fixedOffset, LayoutUnit logicalTop, LayoutUnit logicalHeight)
    398 {
    399     ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatLeft> adapter(m_renderer, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), fixedOffset);
    400     placedFloatsTree().allOverlapsWithAdapter(adapter);
    401 
    402     return adapter.offset();
    403 }
    404 
    405 LayoutUnit FloatingObjects::logicalRightOffset(LayoutUnit fixedOffset, LayoutUnit logicalTop, LayoutUnit logicalHeight)
    406 {
    407     ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatRight> adapter(m_renderer, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), fixedOffset);
    408     placedFloatsTree().allOverlapsWithAdapter(adapter);
    409 
    410     return min(fixedOffset, adapter.offset());
    411 }
    412 
    413 FloatingObjects::FloatBottomCachedValue::FloatBottomCachedValue()
    414     : value(0)
    415     , dirty(true)
    416 {
    417 }
    418 
    419 inline static bool rangesIntersect(int floatTop, int floatBottom, int objectTop, int objectBottom)
    420 {
    421     if (objectTop >= floatBottom || objectBottom < floatTop)
    422         return false;
    423 
    424     // The top of the object overlaps the float
    425     if (objectTop >= floatTop)
    426         return true;
    427 
    428     // The object encloses the float
    429     if (objectTop < floatTop && objectBottom > floatBottom)
    430         return true;
    431 
    432     // The bottom of the object overlaps the float
    433     if (objectBottom > objectTop && objectBottom > floatTop && objectBottom <= floatBottom)
    434         return true;
    435 
    436     return false;
    437 }
    438 
    439 template<>
    440 inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatLeft>::updateOffsetIfNeeded(const FloatingObject* floatingObject)
    441 {
    442     LayoutUnit logicalRight = m_renderer->logicalRightForFloat(floatingObject);
    443     if (logicalRight > m_offset) {
    444         m_offset = logicalRight;
    445         return true;
    446     }
    447     return false;
    448 }
    449 
    450 template<>
    451 inline bool ComputeFloatOffsetForFloatLayoutAdapter<FloatingObject::FloatRight>::updateOffsetIfNeeded(const FloatingObject* floatingObject)
    452 {
    453     LayoutUnit logicalLeft = m_renderer->logicalLeftForFloat(floatingObject);
    454     if (logicalLeft < m_offset) {
    455         m_offset = logicalLeft;
    456         return true;
    457     }
    458     return false;
    459 }
    460 
    461 template <FloatingObject::Type FloatTypeValue>
    462 LayoutUnit ComputeFloatOffsetForFloatLayoutAdapter<FloatTypeValue>::heightRemaining() const
    463 {
    464     return this->m_outermostFloat ? this->m_renderer->logicalBottomForFloat(this->m_outermostFloat) - this->m_lineTop : LayoutUnit(1);
    465 }
    466 
    467 template <FloatingObject::Type FloatTypeValue>
    468 inline void ComputeFloatOffsetAdapter<FloatTypeValue>::collectIfNeeded(const IntervalType& interval)
    469 {
    470     const FloatingObject* floatingObject = interval.data();
    471     if (floatingObject->type() != FloatTypeValue || !rangesIntersect(interval.low(), interval.high(), m_lineTop, m_lineBottom))
    472         return;
    473 
    474     // Make sure the float hasn't changed since it was added to the placed floats tree.
    475     ASSERT(floatingObject->isPlaced());
    476     ASSERT(interval.low() == m_renderer->pixelSnappedLogicalTopForFloat(floatingObject));
    477     ASSERT(interval.high() == m_renderer->pixelSnappedLogicalBottomForFloat(floatingObject));
    478 
    479     bool floatIsNewExtreme = updateOffsetIfNeeded(floatingObject);
    480     if (floatIsNewExtreme)
    481         m_outermostFloat = floatingObject;
    482 }
    483 
    484 static inline ShapeOutsideInfo* shapeInfoForFloat(const FloatingObject& floatingObject, const RenderBlockFlow& containingBlock, LayoutUnit lineTop, LayoutUnit lineBottom)
    485 {
    486     if (ShapeOutsideInfo* shapeOutside = floatingObject.renderer()->shapeOutsideInfo()) {
    487         shapeOutside->updateDeltasForContainingBlockLine(containingBlock, floatingObject, lineTop, lineBottom - lineTop);
    488         return shapeOutside;
    489     }
    490 
    491     return 0;
    492 }
    493 
    494 template<>
    495 inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatLeft>::updateOffsetIfNeeded(const FloatingObject* floatingObject)
    496 {
    497     ASSERT(floatingObject);
    498     LayoutUnit logicalRight = m_renderer->logicalRightForFloat(floatingObject);
    499     if (ShapeOutsideInfo* shapeOutside = shapeInfoForFloat(*floatingObject, *m_renderer, m_lineTop, m_lineBottom)) {
    500         if (!shapeOutside->lineOverlapsShape())
    501             return false;
    502 
    503         logicalRight += shapeOutside->rightMarginBoxDelta();
    504     }
    505     if (logicalRight > m_offset) {
    506         m_offset = logicalRight;
    507         return true;
    508     }
    509 
    510     return false;
    511 }
    512 
    513 template<>
    514 inline bool ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatRight>::updateOffsetIfNeeded(const FloatingObject* floatingObject)
    515 {
    516     ASSERT(floatingObject);
    517     LayoutUnit logicalLeft = m_renderer->logicalLeftForFloat(floatingObject);
    518     if (ShapeOutsideInfo* shapeOutside = shapeInfoForFloat(*floatingObject, *m_renderer, m_lineTop, m_lineBottom)) {
    519         if (!shapeOutside->lineOverlapsShape())
    520             return false;
    521 
    522         logicalLeft += shapeOutside->leftMarginBoxDelta();
    523     }
    524     if (logicalLeft < m_offset) {
    525         m_offset = logicalLeft;
    526         return true;
    527     }
    528 
    529     return false;
    530 }
    531 
    532 #ifndef NDEBUG
    533 // These helpers are only used by the PODIntervalTree for debugging purposes.
    534 String ValueToString<int>::string(const int value)
    535 {
    536     return String::number(value);
    537 }
    538 
    539 String ValueToString<FloatingObject*>::string(const FloatingObject* floatingObject)
    540 {
    541     return String::format("%p (%dx%d %dx%d)", floatingObject, floatingObject->frameRect().pixelSnappedX(), floatingObject->frameRect().pixelSnappedY(), floatingObject->frameRect().pixelSnappedMaxX(), floatingObject->frameRect().pixelSnappedMaxY());
    542 }
    543 #endif
    544 
    545 
    546 } // namespace WebCore
    547