OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2007 David Smith (catfish.man@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/RenderBlock.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), Float
ingObject_should_stay_small); |
| 44 |
| 45 template <FloatingObject::Type FloatTypeValue> |
| 46 class ComputeFloatOffsetAdapter { |
| 47 public: |
| 48 typedef FloatingObjectInterval IntervalType; |
| 49 |
| 50 ComputeFloatOffsetAdapter(const RenderBlock* renderer, int lineTop, int line
Bottom, LayoutUnit& offset) |
| 51 : m_renderer(renderer) |
| 52 , m_lineTop(lineTop) |
| 53 , m_lineBottom(lineBottom) |
| 54 , m_offset(offset) |
| 55 , m_outermostFloat(0) |
| 56 { |
| 57 } |
| 58 |
| 59 int lowValue() const { return m_lineTop; } |
| 60 int highValue() const { return m_lineBottom; } |
| 61 void collectIfNeeded(const IntervalType&); |
| 62 |
| 63 // When computing the offset caused by the floats on a given line, if |
| 64 // the outermost float on that line has a shape-outside, the inline |
| 65 // content that butts up against that float must be positioned using |
| 66 // the contours of the shape, not the margin box of the float. |
| 67 const FloatingObject* outermostFloat() const { return m_outermostFloat; } |
| 68 |
| 69 LayoutUnit getHeightRemaining() const; |
| 70 |
| 71 private: |
| 72 bool updateOffsetIfNeeded(const FloatingObject*); |
| 73 |
| 74 const RenderBlock* m_renderer; |
| 75 int m_lineTop; |
| 76 int m_lineBottom; |
| 77 LayoutUnit& m_offset; |
| 78 const FloatingObject* m_outermostFloat; |
| 79 }; |
| 80 |
| 81 |
| 82 FloatingObjects::~FloatingObjects() |
| 83 { |
| 84 // FIXME: m_set should use OwnPtr instead. |
| 85 deleteAllValues(m_set); |
| 86 } |
| 87 void FloatingObjects::clearLineBoxTreePointers() |
| 88 { |
| 89 // Clear references to originating lines, since the lines are being deleted |
| 90 FloatingObjectSetIterator end = m_set.end(); |
| 91 for (FloatingObjectSetIterator it = m_set.begin(); it != end; ++it) { |
| 92 ASSERT(!((*it)->originatingLine()) || (*it)->originatingLine()->renderer
() == m_renderer); |
| 93 (*it)->setOriginatingLine(0); |
| 94 } |
| 95 } |
| 96 |
| 97 template<> |
| 98 inline bool ComputeFloatOffsetAdapter<FloatingObject::FloatLeft>::updateOffsetIf
Needed(const FloatingObject* floatingObject) |
| 99 { |
| 100 LayoutUnit logicalRight = floatingObject->logicalRight(m_renderer->isHorizon
talWritingMode()); |
| 101 if (logicalRight > m_offset) { |
| 102 m_offset = logicalRight; |
| 103 return true; |
| 104 } |
| 105 return false; |
| 106 } |
| 107 |
| 108 FloatingObjects::FloatingObjects(const RenderBlock* renderer, bool horizontalWri
tingMode) |
| 109 : m_placedFloatsTree(UninitializedTree) |
| 110 , m_leftObjectsCount(0) |
| 111 , m_rightObjectsCount(0) |
| 112 , m_horizontalWritingMode(horizontalWritingMode) |
| 113 , m_renderer(renderer) |
| 114 { |
| 115 } |
| 116 |
| 117 void FloatingObjects::clear() |
| 118 { |
| 119 // FIXME: This should call deleteAllValues, except clearFloats |
| 120 // like to play fast and loose with ownership of these pointers. |
| 121 // If we move to OwnPtr that will fix this ownership oddness. |
| 122 m_set.clear(); |
| 123 m_placedFloatsTree.clear(); |
| 124 m_leftObjectsCount = 0; |
| 125 m_rightObjectsCount = 0; |
| 126 } |
| 127 |
| 128 inline void FloatingObjects::increaseObjectsCount(FloatingObject::Type type) |
| 129 { |
| 130 if (type == FloatingObject::FloatLeft) |
| 131 m_leftObjectsCount++; |
| 132 else |
| 133 m_rightObjectsCount++; |
| 134 } |
| 135 |
| 136 inline void FloatingObjects::decreaseObjectsCount(FloatingObject::Type type) |
| 137 { |
| 138 if (type == FloatingObject::FloatLeft) |
| 139 m_leftObjectsCount--; |
| 140 else |
| 141 m_rightObjectsCount--; |
| 142 } |
| 143 |
| 144 inline FloatingObjectInterval FloatingObjects::intervalForFloatingObject(Floatin
gObject* floatingObject) |
| 145 { |
| 146 if (m_horizontalWritingMode) |
| 147 return FloatingObjectInterval(floatingObject->frameRect().pixelSnappedY(
), floatingObject->frameRect().pixelSnappedMaxY(), floatingObject); |
| 148 return FloatingObjectInterval(floatingObject->frameRect().pixelSnappedX(), f
loatingObject->frameRect().pixelSnappedMaxX(), floatingObject); |
| 149 } |
| 150 |
| 151 void FloatingObjects::addPlacedObject(FloatingObject* floatingObject) |
| 152 { |
| 153 ASSERT(!floatingObject->isInPlacedTree()); |
| 154 |
| 155 floatingObject->setIsPlaced(true); |
| 156 if (m_placedFloatsTree.isInitialized()) |
| 157 m_placedFloatsTree.add(intervalForFloatingObject(floatingObject)); |
| 158 |
| 159 #ifndef NDEBUG |
| 160 floatingObject->setIsInPlacedTree(true); |
| 161 #endif |
| 162 } |
| 163 |
| 164 void FloatingObjects::removePlacedObject(FloatingObject* floatingObject) |
| 165 { |
| 166 ASSERT(floatingObject->isPlaced() && floatingObject->isInPlacedTree()); |
| 167 |
| 168 if (m_placedFloatsTree.isInitialized()) { |
| 169 bool removed = m_placedFloatsTree.remove(intervalForFloatingObject(float
ingObject)); |
| 170 ASSERT_UNUSED(removed, removed); |
| 171 } |
| 172 |
| 173 floatingObject->setIsPlaced(false); |
| 174 #ifndef NDEBUG |
| 175 floatingObject->setIsInPlacedTree(false); |
| 176 #endif |
| 177 } |
| 178 |
| 179 void FloatingObjects::add(FloatingObject* floatingObject) |
| 180 { |
| 181 increaseObjectsCount(floatingObject->type()); |
| 182 m_set.add(floatingObject); |
| 183 if (floatingObject->isPlaced()) |
| 184 addPlacedObject(floatingObject); |
| 185 } |
| 186 |
| 187 void FloatingObjects::remove(FloatingObject* floatingObject) |
| 188 { |
| 189 decreaseObjectsCount(floatingObject->type()); |
| 190 m_set.remove(floatingObject); |
| 191 ASSERT(floatingObject->isPlaced() || !floatingObject->isInPlacedTree()); |
| 192 if (floatingObject->isPlaced()) |
| 193 removePlacedObject(floatingObject); |
| 194 } |
| 195 |
| 196 void FloatingObjects::computePlacedFloatsTree() |
| 197 { |
| 198 ASSERT(!m_placedFloatsTree.isInitialized()); |
| 199 if (m_set.isEmpty()) |
| 200 return; |
| 201 m_placedFloatsTree.initIfNeeded(m_renderer->view()->intervalArena()); |
| 202 FloatingObjectSetIterator it = m_set.begin(); |
| 203 FloatingObjectSetIterator end = m_set.end(); |
| 204 for (; it != end; ++it) { |
| 205 FloatingObject* floatingObject = *it; |
| 206 if (floatingObject->isPlaced()) |
| 207 m_placedFloatsTree.add(intervalForFloatingObject(floatingObject)); |
| 208 } |
| 209 } |
| 210 |
| 211 LayoutUnit FloatingObjects::logicalLeftOffset(LayoutUnit fixedOffset, LayoutUnit
logicalTop, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode offsetMode, L
ayoutUnit *heightRemaining) |
| 212 { |
| 213 LayoutUnit offset = fixedOffset; |
| 214 ComputeFloatOffsetAdapter<FloatingObject::FloatLeft> adapter(m_renderer, rou
ndToInt(logicalTop), roundToInt(logicalTop + logicalHeight), offset); |
| 215 placedFloatsTree().allOverlapsWithAdapter(adapter); |
| 216 |
| 217 if (heightRemaining) |
| 218 *heightRemaining = adapter.getHeightRemaining(); |
| 219 |
| 220 const FloatingObject* outermostFloat = adapter.outermostFloat(); |
| 221 if (offsetMode == ShapeOutsideFloatShapeOffset && outermostFloat) { |
| 222 if (ShapeOutsideInfo* shapeOutside = outermostFloat->renderer()->shapeOu
tsideInfo()) { |
| 223 shapeOutside->computeSegmentsForContainingBlockLine(logicalTop, oute
rmostFloat->logicalTop(m_horizontalWritingMode), logicalHeight); |
| 224 offset += shapeOutside->rightSegmentMarginBoxDelta(); |
| 225 } |
| 226 } |
| 227 |
| 228 return offset; |
| 229 } |
| 230 |
| 231 LayoutUnit FloatingObjects::logicalRightOffset(LayoutUnit fixedOffset, LayoutUni
t logicalTop, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode offsetMode,
LayoutUnit *heightRemaining) |
| 232 { |
| 233 LayoutUnit offset = fixedOffset; |
| 234 ComputeFloatOffsetAdapter<FloatingObject::FloatRight> adapter(m_renderer, ro
undToInt(logicalTop), roundToInt(logicalTop + logicalHeight), offset); |
| 235 placedFloatsTree().allOverlapsWithAdapter(adapter); |
| 236 |
| 237 if (heightRemaining) |
| 238 *heightRemaining = adapter.getHeightRemaining(); |
| 239 |
| 240 const FloatingObject* outermostFloat = adapter.outermostFloat(); |
| 241 if (offsetMode == ShapeOutsideFloatShapeOffset && outermostFloat) { |
| 242 if (ShapeOutsideInfo* shapeOutside = outermostFloat->renderer()->shapeOu
tsideInfo()) { |
| 243 shapeOutside->computeSegmentsForContainingBlockLine(logicalTop, oute
rmostFloat->logicalTop(m_horizontalWritingMode), logicalHeight); |
| 244 offset += shapeOutside->leftSegmentMarginBoxDelta(); |
| 245 } |
| 246 } |
| 247 |
| 248 return min(fixedOffset, offset); |
| 249 } |
| 250 |
| 251 inline static bool rangesIntersect(int floatTop, int floatBottom, int objectTop,
int objectBottom) |
| 252 { |
| 253 if (objectTop >= floatBottom || objectBottom < floatTop) |
| 254 return false; |
| 255 |
| 256 // The top of the object overlaps the float |
| 257 if (objectTop >= floatTop) |
| 258 return true; |
| 259 |
| 260 // The object encloses the float |
| 261 if (objectTop < floatTop && objectBottom > floatBottom) |
| 262 return true; |
| 263 |
| 264 // The bottom of the object overlaps the float |
| 265 if (objectBottom > objectTop && objectBottom > floatTop && objectBottom <= f
loatBottom) |
| 266 return true; |
| 267 |
| 268 return false; |
| 269 } |
| 270 |
| 271 template<> |
| 272 inline bool ComputeFloatOffsetAdapter<FloatingObject::FloatRight>::updateOffsetI
fNeeded(const FloatingObject* floatingObject) |
| 273 { |
| 274 LayoutUnit logicalLeft = floatingObject->logicalLeft(m_renderer->isHorizonta
lWritingMode()); |
| 275 if (logicalLeft < m_offset) { |
| 276 m_offset = logicalLeft; |
| 277 return true; |
| 278 } |
| 279 return false; |
| 280 } |
| 281 |
| 282 template <FloatingObject::Type FloatTypeValue> |
| 283 inline void ComputeFloatOffsetAdapter<FloatTypeValue>::collectIfNeeded(const Int
ervalType& interval) |
| 284 { |
| 285 const FloatingObject* floatingObject = interval.data(); |
| 286 if (floatingObject->type() != FloatTypeValue || !rangesIntersect(interval.lo
w(), interval.high(), m_lineTop, m_lineBottom)) |
| 287 return; |
| 288 |
| 289 // Make sure the float hasn't changed since it was added to the placed float
s tree. |
| 290 ASSERT(floatingObject->isPlaced()); |
| 291 ASSERT(interval.low() == floatingObject->pixelSnappedLogicalTop(m_renderer->
isHorizontalWritingMode())); |
| 292 ASSERT(interval.high() == floatingObject->pixelSnappedLogicalBottom(m_render
er->isHorizontalWritingMode())); |
| 293 |
| 294 bool floatIsNewExtreme = updateOffsetIfNeeded(floatingObject); |
| 295 if (floatIsNewExtreme) |
| 296 m_outermostFloat = floatingObject; |
| 297 } |
| 298 |
| 299 template <FloatingObject::Type FloatTypeValue> |
| 300 LayoutUnit ComputeFloatOffsetAdapter<FloatTypeValue>::getHeightRemaining() const |
| 301 { |
| 302 return m_outermostFloat ? m_outermostFloat->logicalBottom(m_renderer->isHori
zontalWritingMode()) - m_lineTop : LayoutUnit(1); |
| 303 } |
| 304 |
| 305 #ifndef NDEBUG |
| 306 // These helpers are only used by the PODIntervalTree for debugging purposes. |
| 307 String ValueToString<int>::string(const int value) |
| 308 { |
| 309 return String::number(value); |
| 310 } |
| 311 |
| 312 String ValueToString<FloatingObject*>::string(const FloatingObject* floatingObje
ct) |
| 313 { |
| 314 return String::format("%p (%dx%d %dx%d)", floatingObject, floatingObject->fr
ameRect().pixelSnappedX(), floatingObject->frameRect().pixelSnappedY(), floating
Object->frameRect().pixelSnappedMaxX(), floatingObject->frameRect().pixelSnapped
MaxY()); |
| 315 } |
| 316 #endif |
| 317 |
| 318 |
| 319 } // namespace WebCore |
OLD | NEW |