| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. | 2 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above | 8 * 1. Redistributions of source code must retain the above |
| 9 * copyright notice, this list of conditions and the following | 9 * copyright notice, this list of conditions and the following |
| 10 * disclaimer. | 10 * disclaimer. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include "config.h" | 30 #include "config.h" |
| 31 | 31 |
| 32 #include "core/rendering/RenderFlowThread.h" | 32 #include "core/rendering/RenderFlowThread.h" |
| 33 | 33 |
| 34 #include "core/dom/Node.h" | 34 #include "core/dom/Node.h" |
| 35 #include "core/rendering/FlowThreadController.h" | 35 #include "core/rendering/FlowThreadController.h" |
| 36 #include "core/rendering/HitTestRequest.h" | 36 #include "core/rendering/HitTestRequest.h" |
| 37 #include "core/rendering/HitTestResult.h" | 37 #include "core/rendering/HitTestResult.h" |
| 38 #include "core/rendering/LayoutRectRecorder.h" | 38 #include "core/rendering/LayoutRectRecorder.h" |
| 39 #include "core/rendering/PaintInfo.h" | 39 #include "core/rendering/PaintInfo.h" |
| 40 #include "core/rendering/RenderBoxRegionInfo.h" | |
| 41 #include "core/rendering/RenderInline.h" | 40 #include "core/rendering/RenderInline.h" |
| 42 #include "core/rendering/RenderLayer.h" | 41 #include "core/rendering/RenderLayer.h" |
| 43 #include "core/rendering/RenderRegion.h" | 42 #include "core/rendering/RenderRegion.h" |
| 44 #include "core/rendering/RenderView.h" | 43 #include "core/rendering/RenderView.h" |
| 45 #include "platform/PODIntervalTree.h" | 44 #include "platform/PODIntervalTree.h" |
| 46 #include "platform/geometry/TransformState.h" | 45 #include "platform/geometry/TransformState.h" |
| 47 | 46 |
| 48 namespace WebCore { | 47 namespace WebCore { |
| 49 | 48 |
| 50 RenderFlowThread::RenderFlowThread() | 49 RenderFlowThread::RenderFlowThread() |
| 51 : RenderBlockFlow(0) | 50 : RenderBlockFlow(0) |
| 52 , m_previousRegionCount(0) | 51 , m_previousRegionCount(0) |
| 53 , m_autoLogicalHeightRegionsCount(0) | |
| 54 , m_regionsInvalidated(false) | 52 , m_regionsInvalidated(false) |
| 55 , m_regionsHaveUniformLogicalWidth(true) | |
| 56 , m_regionsHaveUniformLogicalHeight(true) | 53 , m_regionsHaveUniformLogicalHeight(true) |
| 57 , m_hasRegionsWithStyling(false) | |
| 58 , m_dispatchRegionLayoutUpdateEvent(false) | |
| 59 , m_dispatchRegionOversetChangeEvent(false) | |
| 60 , m_pageLogicalSizeChanged(false) | 54 , m_pageLogicalSizeChanged(false) |
| 61 , m_inConstrainedLayoutPhase(false) | |
| 62 , m_needsTwoPhasesLayout(false) | |
| 63 { | 55 { |
| 64 setFlowThreadState(InsideOutOfFlowThread); | 56 setFlowThreadState(InsideOutOfFlowThread); |
| 65 } | 57 } |
| 66 | 58 |
| 67 PassRefPtr<RenderStyle> RenderFlowThread::createFlowThreadStyle(RenderStyle* par
entStyle) | 59 PassRefPtr<RenderStyle> RenderFlowThread::createFlowThreadStyle(RenderStyle* par
entStyle) |
| 68 { | 60 { |
| 69 RefPtr<RenderStyle> newStyle(RenderStyle::create()); | 61 RefPtr<RenderStyle> newStyle(RenderStyle::create()); |
| 70 newStyle->inheritFrom(parentStyle); | 62 newStyle->inheritFrom(parentStyle); |
| 71 newStyle->setDisplay(BLOCK); | 63 newStyle->setDisplay(BLOCK); |
| 72 newStyle->setPosition(AbsolutePosition); | 64 newStyle->setPosition(AbsolutePosition); |
| 73 newStyle->setZIndex(0); | 65 newStyle->setZIndex(0); |
| 74 newStyle->setLeft(Length(0, Fixed)); | 66 newStyle->setLeft(Length(0, Fixed)); |
| 75 newStyle->setTop(Length(0, Fixed)); | 67 newStyle->setTop(Length(0, Fixed)); |
| 76 newStyle->setWidth(Length(100, Percent)); | 68 newStyle->setWidth(Length(100, Percent)); |
| 77 newStyle->setHeight(Length(100, Percent)); | 69 newStyle->setHeight(Length(100, Percent)); |
| 78 newStyle->font().update(0); | 70 newStyle->font().update(0); |
| 79 | 71 |
| 80 return newStyle.release(); | 72 return newStyle.release(); |
| 81 } | 73 } |
| 82 | 74 |
| 83 void RenderFlowThread::styleDidChange(StyleDifference diff, const RenderStyle* o
ldStyle) | |
| 84 { | |
| 85 RenderBlock::styleDidChange(diff, oldStyle); | |
| 86 | |
| 87 if (oldStyle && oldStyle->writingMode() != style()->writingMode()) | |
| 88 invalidateRegions(); | |
| 89 } | |
| 90 | |
| 91 void RenderFlowThread::removeFlowChildInfo(RenderObject* child) | |
| 92 { | |
| 93 if (child->isBox()) | |
| 94 removeRenderBoxRegionInfo(toRenderBox(child)); | |
| 95 clearRenderObjectCustomStyle(child); | |
| 96 } | |
| 97 | |
| 98 void RenderFlowThread::addRegionToThread(RenderRegion* renderRegion) | 75 void RenderFlowThread::addRegionToThread(RenderRegion* renderRegion) |
| 99 { | 76 { |
| 100 ASSERT(renderRegion); | 77 ASSERT(renderRegion); |
| 101 m_regionList.add(renderRegion); | 78 m_regionList.add(renderRegion); |
| 102 renderRegion->setIsValid(true); | 79 renderRegion->setIsValid(true); |
| 103 } | 80 } |
| 104 | 81 |
| 105 void RenderFlowThread::removeRegionFromThread(RenderRegion* renderRegion) | 82 void RenderFlowThread::removeRegionFromThread(RenderRegion* renderRegion) |
| 106 { | 83 { |
| 107 ASSERT(renderRegion); | 84 ASSERT(renderRegion); |
| 108 m_regionList.remove(renderRegion); | 85 m_regionList.remove(renderRegion); |
| 109 } | 86 } |
| 110 | 87 |
| 111 void RenderFlowThread::invalidateRegions() | 88 void RenderFlowThread::invalidateRegions() |
| 112 { | 89 { |
| 113 if (m_regionsInvalidated) { | 90 if (m_regionsInvalidated) { |
| 114 ASSERT(selfNeedsLayout()); | 91 ASSERT(selfNeedsLayout()); |
| 115 return; | 92 return; |
| 116 } | 93 } |
| 117 | 94 |
| 118 m_regionRangeMap.clear(); | 95 m_regionRangeMap.clear(); |
| 119 m_breakBeforeToRegionMap.clear(); | |
| 120 m_breakAfterToRegionMap.clear(); | |
| 121 setNeedsLayout(); | 96 setNeedsLayout(); |
| 122 | 97 |
| 123 m_regionsInvalidated = true; | 98 m_regionsInvalidated = true; |
| 124 } | 99 } |
| 125 | 100 |
| 126 class CurrentRenderFlowThreadDisabler { | 101 class CurrentRenderFlowThreadDisabler { |
| 127 WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadDisabler); | 102 WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadDisabler); |
| 128 public: | 103 public: |
| 129 CurrentRenderFlowThreadDisabler(RenderView* view) | 104 CurrentRenderFlowThreadDisabler(RenderView* view) |
| 130 : m_view(view) | 105 : m_view(view) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 141 } | 116 } |
| 142 private: | 117 private: |
| 143 RenderView* m_view; | 118 RenderView* m_view; |
| 144 RenderFlowThread* m_renderFlowThread; | 119 RenderFlowThread* m_renderFlowThread; |
| 145 }; | 120 }; |
| 146 | 121 |
| 147 void RenderFlowThread::validateRegions() | 122 void RenderFlowThread::validateRegions() |
| 148 { | 123 { |
| 149 if (m_regionsInvalidated) { | 124 if (m_regionsInvalidated) { |
| 150 m_regionsInvalidated = false; | 125 m_regionsInvalidated = false; |
| 151 m_regionsHaveUniformLogicalWidth = true; | |
| 152 m_regionsHaveUniformLogicalHeight = true; | 126 m_regionsHaveUniformLogicalHeight = true; |
| 153 | 127 |
| 154 if (hasRegions()) { | 128 if (hasRegions()) { |
| 155 LayoutUnit previousRegionLogicalWidth = 0; | 129 LayoutUnit previousRegionLogicalWidth = 0; |
| 156 LayoutUnit previousRegionLogicalHeight = 0; | 130 LayoutUnit previousRegionLogicalHeight = 0; |
| 157 bool firstRegionVisited = false; | 131 bool firstRegionVisited = false; |
| 158 | 132 |
| 159 for (RenderRegionList::iterator iter = m_regionList.begin(); iter !=
m_regionList.end(); ++iter) { | 133 for (RenderRegionList::iterator iter = m_regionList.begin(); iter !=
m_regionList.end(); ++iter) { |
| 160 RenderRegion* region = *iter; | 134 RenderRegion* region = *iter; |
| 161 ASSERT(!region->needsLayout() || region->isRenderRegionSet()); | |
| 162 | |
| 163 region->deleteAllRenderBoxRegionInfo(); | |
| 164 | |
| 165 // In the normal layout phase we need to initialize the computed
AutoHeight for auto-height regions. | |
| 166 // See initializeRegionsComputedAutoHeight for the explanation. | |
| 167 // Also, if we have auto-height regions we can't assume m_region
sHaveUniformLogicalHeight to be true in the first phase | |
| 168 // because the auto-height regions don't have their height compu
ted yet. | |
| 169 if (!inConstrainedLayoutPhase() && region->hasAutoLogicalHeight(
)) { | |
| 170 region->setComputedAutoHeight(region->maxPageLogicalHeight()
); | |
| 171 m_regionsHaveUniformLogicalHeight = false; | |
| 172 } | |
| 173 | |
| 174 LayoutUnit regionLogicalWidth = region->pageLogicalWidth(); | 135 LayoutUnit regionLogicalWidth = region->pageLogicalWidth(); |
| 175 LayoutUnit regionLogicalHeight = region->pageLogicalHeight(); | 136 LayoutUnit regionLogicalHeight = region->pageLogicalHeight(); |
| 176 | 137 |
| 177 if (!firstRegionVisited) { | 138 if (!firstRegionVisited) { |
| 178 firstRegionVisited = true; | 139 firstRegionVisited = true; |
| 179 } else { | 140 } else { |
| 180 if (m_regionsHaveUniformLogicalWidth && previousRegionLogica
lWidth != regionLogicalWidth) | |
| 181 m_regionsHaveUniformLogicalWidth = false; | |
| 182 if (m_regionsHaveUniformLogicalHeight && previousRegionLogic
alHeight != regionLogicalHeight) | 141 if (m_regionsHaveUniformLogicalHeight && previousRegionLogic
alHeight != regionLogicalHeight) |
| 183 m_regionsHaveUniformLogicalHeight = false; | 142 m_regionsHaveUniformLogicalHeight = false; |
| 184 } | 143 } |
| 185 | 144 |
| 186 previousRegionLogicalWidth = regionLogicalWidth; | 145 previousRegionLogicalWidth = regionLogicalWidth; |
| 187 } | 146 } |
| 188 } | 147 } |
| 189 } | 148 } |
| 190 | 149 |
| 191 updateLogicalWidth(); // Called to get the maximum logical width for the reg
ion. | 150 updateLogicalWidth(); // Called to get the maximum logical width for the reg
ion. |
| 192 updateRegionsFlowThreadPortionRect(); | 151 updateRegionsFlowThreadPortionRect(); |
| 193 } | 152 } |
| 194 | 153 |
| 195 void RenderFlowThread::layout() | 154 void RenderFlowThread::layout() |
| 196 { | 155 { |
| 197 LayoutRectRecorder recorder(*this); | 156 LayoutRectRecorder recorder(*this); |
| 198 m_pageLogicalSizeChanged = m_regionsInvalidated && everHadLayout(); | 157 m_pageLogicalSizeChanged = m_regionsInvalidated && everHadLayout(); |
| 199 | 158 |
| 200 // In case this is the second pass of the normal phase we need to update the
auto-height regions to their initial value. | |
| 201 // If the region chain was invalidated this will happen anyway. | |
| 202 if (!m_regionsInvalidated && !inConstrainedLayoutPhase()) | |
| 203 initializeRegionsComputedAutoHeight(); | |
| 204 | |
| 205 validateRegions(); | 159 validateRegions(); |
| 206 | 160 |
| 207 // This is the first phase of the layout and because we have auto-height reg
ions we'll need a second | |
| 208 // pass to update the flow with the computed auto-height regions. | |
| 209 m_needsTwoPhasesLayout = !inConstrainedLayoutPhase() && hasAutoLogicalHeight
Regions(); | |
| 210 | |
| 211 CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this); | 161 CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this); |
| 212 RenderBlockFlow::layout(); | 162 RenderBlockFlow::layout(); |
| 213 | 163 |
| 214 m_pageLogicalSizeChanged = false; | 164 m_pageLogicalSizeChanged = false; |
| 215 | 165 |
| 216 if (lastRegion()) | 166 if (lastRegion()) |
| 217 lastRegion()->expandToEncompassFlowThreadContentsIfNeeded(); | 167 lastRegion()->expandToEncompassFlowThreadContentsIfNeeded(); |
| 218 | |
| 219 if (shouldDispatchRegionLayoutUpdateEvent()) | |
| 220 dispatchRegionLayoutUpdateEvent(); | |
| 221 | |
| 222 if (shouldDispatchRegionOversetChangeEvent()) | |
| 223 dispatchRegionOversetChangeEvent(); | |
| 224 } | 168 } |
| 225 | 169 |
| 226 void RenderFlowThread::updateLogicalWidth() | 170 void RenderFlowThread::updateLogicalWidth() |
| 227 { | 171 { |
| 228 LayoutUnit logicalWidth = initialLogicalWidth(); | 172 setLogicalWidth(initialLogicalWidth()); |
| 229 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regio
nList.end(); ++iter) { | |
| 230 RenderRegion* region = *iter; | |
| 231 ASSERT(!region->needsLayout() || region->isRenderRegionSet()); | |
| 232 logicalWidth = max(region->pageLogicalWidth(), logicalWidth); | |
| 233 } | |
| 234 setLogicalWidth(logicalWidth); | |
| 235 | |
| 236 // If the regions have non-uniform logical widths, then insert inset informa
tion for the RenderFlowThread. | |
| 237 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regio
nList.end(); ++iter) { | |
| 238 RenderRegion* region = *iter; | |
| 239 LayoutUnit regionLogicalWidth = region->pageLogicalWidth(); | |
| 240 if (regionLogicalWidth != logicalWidth) { | |
| 241 LayoutUnit logicalLeft = style()->direction() == LTR ? LayoutUnit()
: logicalWidth - regionLogicalWidth; | |
| 242 region->setRenderBoxRegionInfo(this, logicalLeft, regionLogicalWidth
, false); | |
| 243 } | |
| 244 } | |
| 245 } | 173 } |
| 246 | 174 |
| 247 void RenderFlowThread::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, L
ogicalExtentComputedValues& computedValues) const | 175 void RenderFlowThread::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, L
ogicalExtentComputedValues& computedValues) const |
| 248 { | 176 { |
| 249 computedValues.m_position = logicalTop; | 177 computedValues.m_position = logicalTop; |
| 250 computedValues.m_extent = 0; | 178 computedValues.m_extent = 0; |
| 251 | 179 |
| 252 for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m
_regionList.end(); ++iter) { | 180 for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m
_regionList.end(); ++iter) { |
| 253 RenderRegion* region = *iter; | 181 RenderRegion* region = *iter; |
| 254 ASSERT(!region->needsLayout() || region->isRenderRegionSet()); | |
| 255 | |
| 256 computedValues.m_extent += region->logicalHeightOfAllFlowThreadContent()
; | 182 computedValues.m_extent += region->logicalHeightOfAllFlowThreadContent()
; |
| 257 } | 183 } |
| 258 } | 184 } |
| 259 | 185 |
| 260 LayoutRect RenderFlowThread::computeRegionClippingRect(const LayoutPoint& offset
, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOv
erflowRect) const | 186 LayoutRect RenderFlowThread::computeRegionClippingRect(const LayoutPoint& offset
, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOv
erflowRect) const |
| 261 { | 187 { |
| 262 LayoutRect regionClippingRect(offset + (flowThreadPortionOverflowRect.locati
on() - flowThreadPortionRect.location()), flowThreadPortionOverflowRect.size()); | 188 LayoutRect regionClippingRect(offset + (flowThreadPortionOverflowRect.locati
on() - flowThreadPortionRect.location()), flowThreadPortionOverflowRect.size()); |
| 263 if (style()->isFlippedBlocksWritingMode()) | 189 if (style()->isFlippedBlocksWritingMode()) |
| 264 regionClippingRect.move(flowThreadPortionRect.size() - flowThreadPortion
OverflowRect.size()); | 190 regionClippingRect.move(flowThreadPortionRect.size() - flowThreadPortion
OverflowRect.size()); |
| 265 return regionClippingRect; | 191 return regionClippingRect; |
| 266 } | 192 } |
| 267 | 193 |
| 268 void RenderFlowThread::paintFlowThreadPortionInRegion(PaintInfo& paintInfo, Rend
erRegion* region, const LayoutRect& flowThreadPortionRect, const LayoutRect& flo
wThreadPortionOverflowRect, const LayoutPoint& paintOffset) const | |
| 269 { | |
| 270 GraphicsContext* context = paintInfo.context; | |
| 271 if (!context) | |
| 272 return; | |
| 273 | |
| 274 // RenderFlowThread should start painting its content in a position that is
offset | |
| 275 // from the region rect's current position. The amount of offset is equal to
the location of | |
| 276 // the flow thread portion in the flow thread's local coordinates. | |
| 277 // Note that we have to pixel snap the location at which we're going to pain
t, since this is necessary | |
| 278 // to minimize the amount of incorrect snapping that would otherwise occur. | |
| 279 // If we tried to paint by applying a non-integral translation, then all the | |
| 280 // layout code that attempted to pixel snap would be incorrect. | |
| 281 IntPoint adjustedPaintOffset; | |
| 282 LayoutPoint portionLocation; | |
| 283 if (style()->isFlippedBlocksWritingMode()) { | |
| 284 LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect); | |
| 285 flipForWritingMode(flippedFlowThreadPortionRect); | |
| 286 portionLocation = flippedFlowThreadPortionRect.location(); | |
| 287 } else { | |
| 288 portionLocation = flowThreadPortionRect.location(); | |
| 289 } | |
| 290 adjustedPaintOffset = roundedIntPoint(paintOffset - portionLocation); | |
| 291 | |
| 292 // The clipping rect for the region is set up by assuming the flowThreadPort
ionRect is going to paint offset from adjustedPaintOffset. | |
| 293 // Remember that we pixel snapped and moved the paintOffset and stored the s
napped result in adjustedPaintOffset. Now we add back in | |
| 294 // the flowThreadPortionRect's location to get the spot where we expect the
portion to actually paint. This can be non-integral and | |
| 295 // that's ok. We then pixel snap the resulting clipping rect to account for
snapping that will occur when the flow thread paints. | |
| 296 IntRect regionClippingRect = pixelSnappedIntRect(computeRegionClippingRect(a
djustedPaintOffset + portionLocation, flowThreadPortionRect, flowThreadPortionOv
erflowRect)); | |
| 297 | |
| 298 PaintInfo info(paintInfo); | |
| 299 info.rect.intersect(regionClippingRect); | |
| 300 | |
| 301 if (!info.rect.isEmpty()) { | |
| 302 context->save(); | |
| 303 | |
| 304 context->clip(regionClippingRect); | |
| 305 | |
| 306 context->translate(adjustedPaintOffset.x(), adjustedPaintOffset.y()); | |
| 307 info.rect.moveBy(-adjustedPaintOffset); | |
| 308 | |
| 309 if (info.phase == PaintPhaseTextClip) | |
| 310 info.paintBehavior = PaintBehaviorForceBlackText; | |
| 311 | |
| 312 layer()->paint(context, info.rect, info.paintBehavior, 0, region, PaintL
ayerTemporaryClipRects); | |
| 313 | |
| 314 context->restore(); | |
| 315 } | |
| 316 } | |
| 317 | |
| 318 bool RenderFlowThread::nodeAtPoint(const HitTestRequest& request, HitTestResult&
result, const HitTestLocation& locationInContainer, const LayoutPoint& accumula
tedOffset, HitTestAction hitTestAction) | 194 bool RenderFlowThread::nodeAtPoint(const HitTestRequest& request, HitTestResult&
result, const HitTestLocation& locationInContainer, const LayoutPoint& accumula
tedOffset, HitTestAction hitTestAction) |
| 319 { | 195 { |
| 320 if (hitTestAction == HitTestBlockBackground) | 196 if (hitTestAction == HitTestBlockBackground) |
| 321 return false; | 197 return false; |
| 322 return RenderBlock::nodeAtPoint(request, result, locationInContainer, accumu
latedOffset, hitTestAction); | 198 return RenderBlock::nodeAtPoint(request, result, locationInContainer, accumu
latedOffset, hitTestAction); |
| 323 } | 199 } |
| 324 | 200 |
| 325 bool RenderFlowThread::hitTestFlowThreadPortionInRegion(RenderRegion* region, co
nst LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverfl
owRect, const HitTestRequest& request, HitTestResult& result, const HitTestLocat
ion& locationInContainer, const LayoutPoint& accumulatedOffset) const | |
| 326 { | |
| 327 LayoutRect regionClippingRect = computeRegionClippingRect(accumulatedOffset,
flowThreadPortionRect, flowThreadPortionOverflowRect); | |
| 328 if (!regionClippingRect.contains(locationInContainer.point())) | |
| 329 return false; | |
| 330 | |
| 331 LayoutSize renderFlowThreadOffset; | |
| 332 if (style()->isFlippedBlocksWritingMode()) { | |
| 333 LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect); | |
| 334 flipForWritingMode(flippedFlowThreadPortionRect); | |
| 335 renderFlowThreadOffset = accumulatedOffset - flippedFlowThreadPortionRec
t.location(); | |
| 336 } else { | |
| 337 renderFlowThreadOffset = accumulatedOffset - flowThreadPortionRect.locat
ion(); | |
| 338 } | |
| 339 | |
| 340 // Always ignore clipping, since the RenderFlowThread has nothing to do with
the bounds of the FrameView. | |
| 341 HitTestRequest newRequest(request.type() | HitTestRequest::IgnoreClipping |
HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent); | |
| 342 | |
| 343 // Make a new temporary HitTestLocation in the new region. | |
| 344 HitTestLocation newHitTestLocation(locationInContainer, -renderFlowThreadOff
set, region); | |
| 345 | |
| 346 bool isPointInsideFlowThread = layer()->hitTest(newRequest, newHitTestLocati
on, result); | |
| 347 | |
| 348 // FIXME: Should we set result.m_localPoint back to the RenderRegion's coord
inate space or leave it in the RenderFlowThread's coordinate | |
| 349 // space? Right now it's staying in the RenderFlowThread's coordinate space,
which may end up being ok. We will know more when we get around to | |
| 350 // patching positionForPoint. | |
| 351 return isPointInsideFlowThread; | |
| 352 } | |
| 353 | |
| 354 bool RenderFlowThread::shouldRepaint(const LayoutRect& r) const | 201 bool RenderFlowThread::shouldRepaint(const LayoutRect& r) const |
| 355 { | 202 { |
| 356 if (view()->document().printing() || r.isEmpty()) | 203 if (view()->document().printing() || r.isEmpty()) |
| 357 return false; | 204 return false; |
| 358 | 205 |
| 359 return true; | 206 return true; |
| 360 } | 207 } |
| 361 | 208 |
| 362 void RenderFlowThread::repaintRectangleInRegions(const LayoutRect& repaintRect)
const | 209 void RenderFlowThread::repaintRectangleInRegions(const LayoutRect& repaintRect)
const |
| 363 { | 210 { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 385 autoGenerateRegionsToBlockOffset(offset); | 232 autoGenerateRegionsToBlockOffset(offset); |
| 386 | 233 |
| 387 if (offset <= 0) | 234 if (offset <= 0) |
| 388 return m_regionList.isEmpty() ? 0 : m_regionList.first(); | 235 return m_regionList.isEmpty() ? 0 : m_regionList.first(); |
| 389 | 236 |
| 390 RegionSearchAdapter adapter(offset); | 237 RegionSearchAdapter adapter(offset); |
| 391 m_regionIntervalTree.allOverlapsWithAdapter<RegionSearchAdapter>(adapter); | 238 m_regionIntervalTree.allOverlapsWithAdapter<RegionSearchAdapter>(adapter); |
| 392 | 239 |
| 393 // If no region was found, the offset is in the flow thread overflow. | 240 // If no region was found, the offset is in the flow thread overflow. |
| 394 // The last region will contain the offset if extendLastRegion is set or if
the last region is a set. | 241 // The last region will contain the offset if extendLastRegion is set or if
the last region is a set. |
| 395 if (!adapter.result() && !m_regionList.isEmpty() && (extendLastRegion || m_r
egionList.last()->isRenderRegionSet())) | 242 if (!adapter.result() && !m_regionList.isEmpty()) |
| 396 return m_regionList.last(); | 243 return m_regionList.last(); |
| 397 | 244 |
| 398 return adapter.result(); | 245 return adapter.result(); |
| 399 } | 246 } |
| 400 | 247 |
| 401 RenderRegion* RenderFlowThread::regionFromAbsolutePointAndBox(IntPoint absoluteP
oint, const RenderBox* flowedBox) | 248 RenderRegion* RenderFlowThread::regionFromAbsolutePointAndBox(IntPoint absoluteP
oint, const RenderBox* flowedBox) |
| 402 { | 249 { |
| 403 if (!flowedBox) | 250 if (!flowedBox) |
| 404 return 0; | 251 return 0; |
| 405 | 252 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 423 return 0; | 270 return 0; |
| 424 } | 271 } |
| 425 | 272 |
| 426 LayoutPoint RenderFlowThread::adjustedPositionRelativeToOffsetParent(const Rende
rBoxModelObject& boxModelObject, const LayoutPoint& startPoint) | 273 LayoutPoint RenderFlowThread::adjustedPositionRelativeToOffsetParent(const Rende
rBoxModelObject& boxModelObject, const LayoutPoint& startPoint) |
| 427 { | 274 { |
| 428 LayoutPoint referencePoint = startPoint; | 275 LayoutPoint referencePoint = startPoint; |
| 429 | 276 |
| 430 // FIXME: This needs to be adapted for different writing modes inside the fl
ow thread. | 277 // FIXME: This needs to be adapted for different writing modes inside the fl
ow thread. |
| 431 RenderRegion* startRegion = regionAtBlockOffset(referencePoint.y()); | 278 RenderRegion* startRegion = regionAtBlockOffset(referencePoint.y()); |
| 432 if (startRegion) { | 279 if (startRegion) { |
| 433 RenderBoxModelObject* startRegionBox = startRegion->isRenderNamedFlowFra
gment() ? toRenderBoxModelObject(startRegion->parent()) : startRegion; | |
| 434 // Take into account the offset coordinates of the region. | 280 // Take into account the offset coordinates of the region. |
| 435 RenderObject* currObject = startRegionBox; | 281 RenderObject* currObject = startRegion; |
| 436 RenderObject* currOffsetParentRenderer; | 282 RenderObject* currOffsetParentRenderer; |
| 437 Element* currOffsetParentElement; | 283 Element* currOffsetParentElement; |
| 438 while ((currOffsetParentElement = currObject->offsetParent()) && (currOf
fsetParentRenderer = currOffsetParentElement->renderer())) { | 284 while ((currOffsetParentElement = currObject->offsetParent()) && (currOf
fsetParentRenderer = currOffsetParentElement->renderer())) { |
| 439 if (currObject->isBoxModelObject()) | 285 if (currObject->isBoxModelObject()) |
| 440 referencePoint.move(toRenderBoxModelObject(currObject)->offsetLe
ft(), toRenderBoxModelObject(currObject)->offsetTop()); | 286 referencePoint.move(toRenderBoxModelObject(currObject)->offsetLe
ft(), toRenderBoxModelObject(currObject)->offsetTop()); |
| 441 | 287 |
| 442 // Since we're looking for the offset relative to the body, we must
also | 288 // Since we're looking for the offset relative to the body, we must
also |
| 443 // take into consideration the borders of the region's offsetParent. | 289 // take into consideration the borders of the region's offsetParent. |
| 444 if (currOffsetParentRenderer->isBox() && !currOffsetParentRenderer->
isBody()) | 290 if (currOffsetParentRenderer->isBox() && !currOffsetParentRenderer->
isBody()) |
| 445 referencePoint.move(toRenderBox(currOffsetParentRenderer)->borde
rLeft(), toRenderBox(currOffsetParentRenderer)->borderTop()); | 291 referencePoint.move(toRenderBox(currOffsetParentRenderer)->borde
rLeft(), toRenderBox(currOffsetParentRenderer)->borderTop()); |
| 446 | 292 |
| 447 currObject = currOffsetParentRenderer; | 293 currObject = currOffsetParentRenderer; |
| 448 } | 294 } |
| 449 | 295 |
| 450 // We need to check if any of this box's containing blocks start in a di
fferent region | 296 // We need to check if any of this box's containing blocks start in a di
fferent region |
| 451 // and if so, drop the object's top position (which was computed relativ
e to its containing block | 297 // and if so, drop the object's top position (which was computed relativ
e to its containing block |
| 452 // and is no longer valid) and recompute it using the region in which it
flows as reference. | 298 // and is no longer valid) and recompute it using the region in which it
flows as reference. |
| 453 bool wasComputedRelativeToOtherRegion = false; | 299 bool wasComputedRelativeToOtherRegion = false; |
| 454 const RenderBlock* objContainingBlock = boxModelObject.containingBlock()
; | 300 const RenderBlock* objContainingBlock = boxModelObject.containingBlock()
; |
| 455 while (objContainingBlock && !objContainingBlock->isRenderNamedFlowThrea
d()) { | 301 while (objContainingBlock) { |
| 456 // Check if this object is in a different region. | 302 // Check if this object is in a different region. |
| 457 RenderRegion* parentStartRegion = 0; | 303 RenderRegion* parentStartRegion = 0; |
| 458 RenderRegion* parentEndRegion = 0; | 304 RenderRegion* parentEndRegion = 0; |
| 459 getRegionRangeForBox(objContainingBlock, parentStartRegion, parentEn
dRegion); | 305 getRegionRangeForBox(objContainingBlock, parentStartRegion, parentEn
dRegion); |
| 460 if (parentStartRegion && parentStartRegion != startRegion) { | 306 if (parentStartRegion && parentStartRegion != startRegion) { |
| 461 wasComputedRelativeToOtherRegion = true; | 307 wasComputedRelativeToOtherRegion = true; |
| 462 break; | 308 break; |
| 463 } | 309 } |
| 464 objContainingBlock = objContainingBlock->containingBlock(); | 310 objContainingBlock = objContainingBlock->containingBlock(); |
| 465 } | 311 } |
| 466 | 312 |
| 467 if (wasComputedRelativeToOtherRegion) { | 313 if (wasComputedRelativeToOtherRegion) { |
| 468 if (boxModelObject.isBox()) { | |
| 469 // Use borderBoxRectInRegion to account for variations such as p
ercentage margins. | |
| 470 LayoutRect borderBoxRect = toRenderBox(&boxModelObject)->borderB
oxRectInRegion(startRegion, RenderBox::DoNotCacheRenderBoxRegionInfo); | |
| 471 referencePoint.move(borderBoxRect.location().x(), 0); | |
| 472 } | |
| 473 | |
| 474 // Get the logical top coordinate of the current object. | 314 // Get the logical top coordinate of the current object. |
| 475 LayoutUnit top = 0; | 315 LayoutUnit top = 0; |
| 476 if (boxModelObject.isRenderBlock()) { | 316 if (boxModelObject.isRenderBlock()) { |
| 477 top = toRenderBlock(&boxModelObject)->offsetFromLogicalTopOfFirs
tPage(); | 317 top = toRenderBlock(&boxModelObject)->offsetFromLogicalTopOfFirs
tPage(); |
| 478 } else { | 318 } else { |
| 479 if (boxModelObject.containingBlock()) | 319 if (boxModelObject.containingBlock()) |
| 480 top = boxModelObject.containingBlock()->offsetFromLogicalTop
OfFirstPage(); | 320 top = boxModelObject.containingBlock()->offsetFromLogicalTop
OfFirstPage(); |
| 481 | 321 |
| 482 if (boxModelObject.isBox()) | 322 if (boxModelObject.isBox()) |
| 483 top += toRenderBox(&boxModelObject)->topLeftLocation().y(); | 323 top += toRenderBox(&boxModelObject)->topLeftLocation().y(); |
| 484 else if (boxModelObject.isRenderInline()) | 324 else if (boxModelObject.isRenderInline()) |
| 485 top -= toRenderInline(&boxModelObject)->borderTop(); | 325 top -= toRenderInline(&boxModelObject)->borderTop(); |
| 486 } | 326 } |
| 487 | 327 |
| 488 // Get the logical top of the region this object starts in | 328 // Get the logical top of the region this object starts in |
| 489 // and compute the object's top, relative to the region's top. | 329 // and compute the object's top, relative to the region's top. |
| 490 LayoutUnit regionLogicalTop = startRegion->pageLogicalTopForOffset(t
op); | 330 LayoutUnit regionLogicalTop = startRegion->pageLogicalTopForOffset(t
op); |
| 491 LayoutUnit topRelativeToRegion = top - regionLogicalTop; | 331 LayoutUnit topRelativeToRegion = top - regionLogicalTop; |
| 492 referencePoint.setY(startRegionBox->offsetTop() + topRelativeToRegio
n); | 332 referencePoint.setY(startRegion->offsetTop() + topRelativeToRegion); |
| 493 | 333 |
| 494 // Since the top has been overriden, check if the | 334 // Since the top has been overriden, check if the |
| 495 // relative/sticky positioning must be reconsidered. | 335 // relative/sticky positioning must be reconsidered. |
| 496 if (boxModelObject.isRelPositioned()) | 336 if (boxModelObject.isRelPositioned()) |
| 497 referencePoint.move(0, boxModelObject.relativePositionOffset().h
eight()); | 337 referencePoint.move(0, boxModelObject.relativePositionOffset().h
eight()); |
| 498 else if (boxModelObject.isStickyPositioned()) | 338 else if (boxModelObject.isStickyPositioned()) |
| 499 referencePoint.move(0, boxModelObject.stickyPositionOffset().hei
ght()); | 339 referencePoint.move(0, boxModelObject.stickyPositionOffset().hei
ght()); |
| 500 } | 340 } |
| 501 | 341 |
| 502 // Since we're looking for the offset relative to the body, we must also | 342 // Since we're looking for the offset relative to the body, we must also |
| 503 // take into consideration the borders of the region. | 343 // take into consideration the borders of the region. |
| 504 referencePoint.move(startRegionBox->borderLeft(), startRegionBox->border
Top()); | 344 referencePoint.move(startRegion->borderLeft(), startRegion->borderTop())
; |
| 505 } | 345 } |
| 506 | 346 |
| 507 return referencePoint; | 347 return referencePoint; |
| 508 } | 348 } |
| 509 | 349 |
| 510 LayoutUnit RenderFlowThread::pageLogicalTopForOffset(LayoutUnit offset) | 350 LayoutUnit RenderFlowThread::pageLogicalTopForOffset(LayoutUnit offset) |
| 511 { | 351 { |
| 512 RenderRegion* region = regionAtBlockOffset(offset); | 352 RenderRegion* region = regionAtBlockOffset(offset); |
| 513 return region ? region->pageLogicalTopForOffset(offset) : LayoutUnit(); | 353 return region ? region->pageLogicalTopForOffset(offset) : LayoutUnit(); |
| 514 } | 354 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 return 0; | 404 return 0; |
| 565 | 405 |
| 566 LayoutRect flippedRegionRect(renderRegion->flowThreadPortionRect()); | 406 LayoutRect flippedRegionRect(renderRegion->flowThreadPortionRect()); |
| 567 flipForWritingMode(flippedRegionRect); | 407 flipForWritingMode(flippedRegionRect); |
| 568 | 408 |
| 569 transformState.move(renderRegion->contentBoxRect().location() - flippedRegio
nRect.location()); | 409 transformState.move(renderRegion->contentBoxRect().location() - flippedRegio
nRect.location()); |
| 570 | 410 |
| 571 return renderRegion; | 411 return renderRegion; |
| 572 } | 412 } |
| 573 | 413 |
| 574 void RenderFlowThread::removeRenderBoxRegionInfo(RenderBox* box) | |
| 575 { | |
| 576 if (!hasRegions()) | |
| 577 return; | |
| 578 | |
| 579 // If the region chain was invalidated the next layout will clear the box in
formation from all the regions. | |
| 580 if (m_regionsInvalidated) { | |
| 581 ASSERT(selfNeedsLayout()); | |
| 582 return; | |
| 583 } | |
| 584 | |
| 585 RenderRegion* startRegion; | |
| 586 RenderRegion* endRegion; | |
| 587 getRegionRangeForBox(box, startRegion, endRegion); | |
| 588 | |
| 589 for (RenderRegionList::iterator iter = m_regionList.find(startRegion); iter
!= m_regionList.end(); ++iter) { | |
| 590 RenderRegion* region = *iter; | |
| 591 region->removeRenderBoxRegionInfo(box); | |
| 592 if (region == endRegion) | |
| 593 break; | |
| 594 } | |
| 595 | |
| 596 #ifndef NDEBUG | |
| 597 // We have to make sure we did not leave any RenderBoxRegionInfo attached. | |
| 598 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regio
nList.end(); ++iter) { | |
| 599 RenderRegion* region = *iter; | |
| 600 ASSERT(!region->renderBoxRegionInfo(box)); | |
| 601 } | |
| 602 #endif | |
| 603 | |
| 604 m_regionRangeMap.remove(box); | |
| 605 } | |
| 606 | |
| 607 bool RenderFlowThread::logicalWidthChangedInRegionsForBlock(const RenderBlock* b
lock) | |
| 608 { | |
| 609 if (!hasRegions()) | |
| 610 return false; | |
| 611 | |
| 612 RenderRegion* startRegion; | |
| 613 RenderRegion* endRegion; | |
| 614 getRegionRangeForBox(block, startRegion, endRegion); | |
| 615 | |
| 616 // When the region chain is invalidated the box information is discarded so
we must assume the width has changed. | |
| 617 if (m_pageLogicalSizeChanged && !startRegion) | |
| 618 return true; | |
| 619 | |
| 620 // Not necessary for the flow thread, since we already computed the correct
info for it. | |
| 621 if (block == this) | |
| 622 return false; | |
| 623 | |
| 624 for (RenderRegionList::iterator iter = m_regionList.find(startRegion); iter
!= m_regionList.end(); ++iter) { | |
| 625 RenderRegion* region = *iter; | |
| 626 ASSERT(!region->needsLayout() || region->isRenderRegionSet()); | |
| 627 | |
| 628 OwnPtr<RenderBoxRegionInfo> oldInfo = region->takeRenderBoxRegionInfo(bl
ock); | |
| 629 if (!oldInfo) | |
| 630 continue; | |
| 631 | |
| 632 LayoutUnit oldLogicalWidth = oldInfo->logicalWidth(); | |
| 633 RenderBoxRegionInfo* newInfo = block->renderBoxRegionInfo(region); | |
| 634 if (!newInfo || newInfo->logicalWidth() != oldLogicalWidth) | |
| 635 return true; | |
| 636 | |
| 637 if (region == endRegion) | |
| 638 break; | |
| 639 } | |
| 640 | |
| 641 return false; | |
| 642 } | |
| 643 | |
| 644 LayoutUnit RenderFlowThread::contentLogicalWidthOfFirstRegion() const | |
| 645 { | |
| 646 RenderRegion* firstValidRegionInFlow = firstRegion(); | |
| 647 if (!firstValidRegionInFlow) | |
| 648 return 0; | |
| 649 return isHorizontalWritingMode() ? firstValidRegionInFlow->contentWidth() :
firstValidRegionInFlow->contentHeight(); | |
| 650 } | |
| 651 | |
| 652 LayoutUnit RenderFlowThread::contentLogicalHeightOfFirstRegion() const | |
| 653 { | |
| 654 RenderRegion* firstValidRegionInFlow = firstRegion(); | |
| 655 if (!firstValidRegionInFlow) | |
| 656 return 0; | |
| 657 return isHorizontalWritingMode() ? firstValidRegionInFlow->contentHeight() :
firstValidRegionInFlow->contentWidth(); | |
| 658 } | |
| 659 | |
| 660 LayoutUnit RenderFlowThread::contentLogicalLeftOfFirstRegion() const | |
| 661 { | |
| 662 RenderRegion* firstValidRegionInFlow = firstRegion(); | |
| 663 if (!firstValidRegionInFlow) | |
| 664 return 0; | |
| 665 return isHorizontalWritingMode() ? firstValidRegionInFlow->flowThreadPortion
Rect().x() : firstValidRegionInFlow->flowThreadPortionRect().y(); | |
| 666 } | |
| 667 | |
| 668 RenderRegion* RenderFlowThread::firstRegion() const | 414 RenderRegion* RenderFlowThread::firstRegion() const |
| 669 { | 415 { |
| 670 if (!hasValidRegionInfo()) | 416 if (!hasValidRegionInfo()) |
| 671 return 0; | 417 return 0; |
| 672 return m_regionList.first(); | 418 return m_regionList.first(); |
| 673 } | 419 } |
| 674 | 420 |
| 675 RenderRegion* RenderFlowThread::lastRegion() const | 421 RenderRegion* RenderFlowThread::lastRegion() const |
| 676 { | 422 { |
| 677 if (!hasValidRegionInfo()) | 423 if (!hasValidRegionInfo()) |
| 678 return 0; | 424 return 0; |
| 679 return m_regionList.last(); | 425 return m_regionList.last(); |
| 680 } | 426 } |
| 681 | 427 |
| 682 void RenderFlowThread::clearRenderObjectCustomStyle(const RenderObject* object, | |
| 683 const RenderRegion* oldStartRegion, const RenderRegion* oldEndRegion, | |
| 684 const RenderRegion* newStartRegion, const RenderRegion* newEndRegion) | |
| 685 { | |
| 686 // Clear the styles for the object in the regions. | |
| 687 // The styles are not cleared for the regions that are contained in both ran
ges. | |
| 688 bool insideOldRegionRange = false; | |
| 689 bool insideNewRegionRange = false; | |
| 690 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regio
nList.end(); ++iter) { | |
| 691 RenderRegion* region = *iter; | |
| 692 | |
| 693 if (oldStartRegion == region) | |
| 694 insideOldRegionRange = true; | |
| 695 if (newStartRegion == region) | |
| 696 insideNewRegionRange = true; | |
| 697 | |
| 698 if (!(insideOldRegionRange && insideNewRegionRange)) | |
| 699 region->clearObjectStyleInRegion(object); | |
| 700 | |
| 701 if (oldEndRegion == region) | |
| 702 insideOldRegionRange = false; | |
| 703 if (newEndRegion == region) | |
| 704 insideNewRegionRange = false; | |
| 705 } | |
| 706 } | |
| 707 | |
| 708 void RenderFlowThread::setRegionRangeForBox(const RenderBox* box, LayoutUnit off
setFromLogicalTopOfFirstPage) | 428 void RenderFlowThread::setRegionRangeForBox(const RenderBox* box, LayoutUnit off
setFromLogicalTopOfFirstPage) |
| 709 { | 429 { |
| 710 if (!hasRegions()) | 430 if (!hasRegions()) |
| 711 return; | 431 return; |
| 712 | 432 |
| 713 // FIXME: Not right for differing writing-modes. | 433 // FIXME: Not right for differing writing-modes. |
| 714 RenderRegion* startRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstP
age, true); | 434 RenderRegion* startRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstP
age, true); |
| 715 RenderRegion* endRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPag
e + box->logicalHeight(), true); | 435 RenderRegion* endRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPag
e + box->logicalHeight(), true); |
| 716 RenderRegionRangeMap::iterator it = m_regionRangeMap.find(box); | 436 RenderRegionRangeMap::iterator it = m_regionRangeMap.find(box); |
| 717 if (it == m_regionRangeMap.end()) { | 437 if (it == m_regionRangeMap.end()) { |
| 718 m_regionRangeMap.set(box, RenderRegionRange(startRegion, endRegion)); | 438 m_regionRangeMap.set(box, RenderRegionRange(startRegion, endRegion)); |
| 719 clearRenderObjectCustomStyle(box); | |
| 720 return; | 439 return; |
| 721 } | 440 } |
| 722 | 441 |
| 723 // If nothing changed, just bail. | 442 // If nothing changed, just bail. |
| 724 RenderRegionRange& range = it->value; | 443 RenderRegionRange& range = it->value; |
| 725 if (range.startRegion() == startRegion && range.endRegion() == endRegion) | 444 if (range.startRegion() == startRegion && range.endRegion() == endRegion) |
| 726 return; | 445 return; |
| 727 | 446 |
| 728 // Delete any info that we find before our new startRegion and after our new
endRegion. | |
| 729 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regio
nList.end(); ++iter) { | |
| 730 RenderRegion* region = *iter; | |
| 731 if (region == startRegion) { | |
| 732 iter = m_regionList.find(endRegion); | |
| 733 continue; | |
| 734 } | |
| 735 | |
| 736 region->removeRenderBoxRegionInfo(box); | |
| 737 | |
| 738 if (region == range.endRegion()) | |
| 739 break; | |
| 740 } | |
| 741 | |
| 742 clearRenderObjectCustomStyle(box, range.startRegion(), range.endRegion(), st
artRegion, endRegion); | |
| 743 range.setRange(startRegion, endRegion); | 447 range.setRange(startRegion, endRegion); |
| 744 } | 448 } |
| 745 | 449 |
| 746 void RenderFlowThread::getRegionRangeForBox(const RenderBox* box, RenderRegion*&
startRegion, RenderRegion*& endRegion) const | 450 void RenderFlowThread::getRegionRangeForBox(const RenderBox* box, RenderRegion*&
startRegion, RenderRegion*& endRegion) const |
| 747 { | 451 { |
| 748 startRegion = 0; | 452 startRegion = 0; |
| 749 endRegion = 0; | 453 endRegion = 0; |
| 750 RenderRegionRangeMap::const_iterator it = m_regionRangeMap.find(box); | 454 RenderRegionRangeMap::const_iterator it = m_regionRangeMap.find(box); |
| 751 if (it == m_regionRangeMap.end()) | 455 if (it == m_regionRangeMap.end()) |
| 752 return; | 456 return; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 772 const RenderRegion* currRegion = *it; | 476 const RenderRegion* currRegion = *it; |
| 773 if (targetRegion == currRegion) | 477 if (targetRegion == currRegion) |
| 774 return true; | 478 return true; |
| 775 if (currRegion == endRegion) | 479 if (currRegion == endRegion) |
| 776 break; | 480 break; |
| 777 } | 481 } |
| 778 | 482 |
| 779 return false; | 483 return false; |
| 780 } | 484 } |
| 781 | 485 |
| 782 // Check if the content is flown into at least a region with region styling rule
s. | 486 void RenderFlowThread::updateRegionsFlowThreadPortionRect() |
| 783 void RenderFlowThread::checkRegionsWithStyling() | |
| 784 { | 487 { |
| 785 bool hasRegionsWithStyling = false; | |
| 786 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regio
nList.end(); ++iter) { | |
| 787 RenderRegion* region = *iter; | |
| 788 if (region->hasCustomRegionStyle()) { | |
| 789 hasRegionsWithStyling = true; | |
| 790 break; | |
| 791 } | |
| 792 } | |
| 793 m_hasRegionsWithStyling = hasRegionsWithStyling; | |
| 794 } | |
| 795 | |
| 796 bool RenderFlowThread::objectInFlowRegion(const RenderObject* object, const Rend
erRegion* region) const | |
| 797 { | |
| 798 ASSERT(object); | |
| 799 ASSERT(region); | |
| 800 | |
| 801 RenderFlowThread* flowThread = object->flowThreadContainingBlock(); | |
| 802 if (flowThread != this) | |
| 803 return false; | |
| 804 if (!m_regionList.contains(const_cast<RenderRegion*>(region))) | |
| 805 return false; | |
| 806 | |
| 807 RenderBox* enclosingBox = object->enclosingBox(); | |
| 808 RenderRegion* enclosingBoxStartRegion = 0; | |
| 809 RenderRegion* enclosingBoxEndRegion = 0; | |
| 810 getRegionRangeForBox(enclosingBox, enclosingBoxStartRegion, enclosingBoxEndR
egion); | |
| 811 if (!regionInRange(region, enclosingBoxStartRegion, enclosingBoxEndRegion)) | |
| 812 return false; | |
| 813 | |
| 814 if (object->isBox()) | |
| 815 return true; | |
| 816 | |
| 817 LayoutRect objectABBRect = object->absoluteBoundingBoxRect(true); | |
| 818 if (!objectABBRect.width()) | |
| 819 objectABBRect.setWidth(1); | |
| 820 if (!objectABBRect.height()) | |
| 821 objectABBRect.setHeight(1); | |
| 822 if (objectABBRect.intersects(region->absoluteBoundingBoxRect(true))) | |
| 823 return true; | |
| 824 | |
| 825 if (region == lastRegion()) { | |
| 826 // If the object does not intersect any of the enclosing box regions | |
| 827 // then the object is in last region. | |
| 828 for (RenderRegionList::const_iterator it = m_regionList.find(enclosingBo
xStartRegion); it != m_regionList.end(); ++it) { | |
| 829 const RenderRegion* currRegion = *it; | |
| 830 if (currRegion == region) | |
| 831 break; | |
| 832 if (objectABBRect.intersects(currRegion->absoluteBoundingBoxRect(tru
e))) | |
| 833 return false; | |
| 834 } | |
| 835 return true; | |
| 836 } | |
| 837 | |
| 838 return false; | |
| 839 } | |
| 840 | |
| 841 #ifndef NDEBUG | |
| 842 bool RenderFlowThread::isAutoLogicalHeightRegionsCountConsistent() const | |
| 843 { | |
| 844 unsigned autoLogicalHeightRegions = 0; | |
| 845 for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m
_regionList.end(); ++iter) { | |
| 846 const RenderRegion* region = *iter; | |
| 847 if (region->hasAutoLogicalHeight()) | |
| 848 autoLogicalHeightRegions++; | |
| 849 } | |
| 850 | |
| 851 return autoLogicalHeightRegions == m_autoLogicalHeightRegionsCount; | |
| 852 } | |
| 853 #endif | |
| 854 | |
| 855 // During the normal layout phase of the named flow the regions are initialized
with a height equal to their max-height. | |
| 856 // This way unforced breaks are automatically placed when a region is full and t
he content height/position correctly estimated. | |
| 857 // Also, the region where a forced break falls is exactly the region found at th
e forced break offset inside the flow content. | |
| 858 void RenderFlowThread::initializeRegionsComputedAutoHeight(RenderRegion* startRe
gion) | |
| 859 { | |
| 860 ASSERT(!inConstrainedLayoutPhase()); | |
| 861 if (!hasAutoLogicalHeightRegions()) | |
| 862 return; | |
| 863 | |
| 864 RenderRegionList::iterator regionIter = startRegion ? m_regionList.find(star
tRegion) : m_regionList.begin(); | |
| 865 for (; regionIter != m_regionList.end(); ++regionIter) { | |
| 866 RenderRegion* region = *regionIter; | |
| 867 if (region->hasAutoLogicalHeight()) | |
| 868 region->setComputedAutoHeight(region->maxPageLogicalHeight()); | |
| 869 } | |
| 870 } | |
| 871 | |
| 872 void RenderFlowThread::markAutoLogicalHeightRegionsForLayout() | |
| 873 { | |
| 874 ASSERT(hasAutoLogicalHeightRegions()); | |
| 875 | |
| 876 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regio
nList.end(); ++iter) { | |
| 877 RenderRegion* region = *iter; | |
| 878 if (!region->hasAutoLogicalHeight()) | |
| 879 continue; | |
| 880 | |
| 881 // FIXME: We need to find a way to avoid marking all the regions ancesto
rs for layout | |
| 882 // as we are already inside layout. | |
| 883 region->setNeedsLayout(); | |
| 884 } | |
| 885 } | |
| 886 | |
| 887 void RenderFlowThread::updateRegionsFlowThreadPortionRect(const RenderRegion* la
stRegionWithContent) | |
| 888 { | |
| 889 ASSERT(!lastRegionWithContent || (!inConstrainedLayoutPhase() && hasAutoLogi
calHeightRegions())); | |
| 890 LayoutUnit logicalHeight = 0; | 488 LayoutUnit logicalHeight = 0; |
| 891 bool emptyRegionsSegment = false; | |
| 892 // FIXME: Optimize not to clear the interval all the time. This implies manu
ally managing the tree nodes lifecycle. | 489 // FIXME: Optimize not to clear the interval all the time. This implies manu
ally managing the tree nodes lifecycle. |
| 893 m_regionIntervalTree.clear(); | 490 m_regionIntervalTree.clear(); |
| 894 m_regionIntervalTree.initIfNeeded(); | 491 m_regionIntervalTree.initIfNeeded(); |
| 895 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regio
nList.end(); ++iter) { | 492 for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regio
nList.end(); ++iter) { |
| 896 RenderRegion* region = *iter; | 493 RenderRegion* region = *iter; |
| 897 | 494 |
| 898 // If we find an empty auto-height region, clear the computedAutoHeight
value. | |
| 899 if (emptyRegionsSegment && region->hasAutoLogicalHeight()) | |
| 900 region->clearComputedAutoHeight(); | |
| 901 | |
| 902 LayoutUnit regionLogicalWidth = region->pageLogicalWidth(); | 495 LayoutUnit regionLogicalWidth = region->pageLogicalWidth(); |
| 903 LayoutUnit regionLogicalHeight = std::min<LayoutUnit>(RenderFlowThread::
maxLogicalHeight() - logicalHeight, region->logicalHeightOfAllFlowThreadContent(
)); | 496 LayoutUnit regionLogicalHeight = std::min<LayoutUnit>(RenderFlowThread::
maxLogicalHeight() - logicalHeight, region->logicalHeightOfAllFlowThreadContent(
)); |
| 904 | 497 |
| 905 LayoutRect regionRect(style()->direction() == LTR ? LayoutUnit() : logic
alWidth() - regionLogicalWidth, logicalHeight, regionLogicalWidth, regionLogical
Height); | 498 LayoutRect regionRect(style()->direction() == LTR ? LayoutUnit() : logic
alWidth() - regionLogicalWidth, logicalHeight, regionLogicalWidth, regionLogical
Height); |
| 906 | 499 |
| 907 region->setFlowThreadPortionRect(isHorizontalWritingMode() ? regionRect
: regionRect.transposedRect()); | 500 region->setFlowThreadPortionRect(isHorizontalWritingMode() ? regionRect
: regionRect.transposedRect()); |
| 908 | 501 |
| 909 m_regionIntervalTree.add(RegionIntervalTree::createInterval(logicalHeigh
t, logicalHeight + regionLogicalHeight, region)); | 502 m_regionIntervalTree.add(RegionIntervalTree::createInterval(logicalHeigh
t, logicalHeight + regionLogicalHeight, region)); |
| 910 | 503 |
| 911 logicalHeight += regionLogicalHeight; | 504 logicalHeight += regionLogicalHeight; |
| 912 | |
| 913 // Once we find the last region with content the next regions are consid
ered empty. | |
| 914 if (lastRegionWithContent == region) | |
| 915 emptyRegionsSegment = true; | |
| 916 } | 505 } |
| 917 | |
| 918 ASSERT(!lastRegionWithContent || emptyRegionsSegment); | |
| 919 } | |
| 920 | |
| 921 // Even if we require the break to occur at offsetBreakInFlowThread, because reg
ions may have min/max-height values, | |
| 922 // it is possible that the break will occur at a different offset than the origi
nal one required. | |
| 923 // offsetBreakAdjustment measures the different between the requested break offs
et and the current break offset. | |
| 924 bool RenderFlowThread::addForcedRegionBreak(LayoutUnit offsetBreakInFlowThread,
RenderObject* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment) | |
| 925 { | |
| 926 // We take breaks into account for height computation for auto logical heigh
t regions | |
| 927 // only in the layout phase in which we lay out the flows threads unconstrai
ned | |
| 928 // and we use the content breaks to determine the computedAutoHeight for | |
| 929 // auto logical height regions. | |
| 930 if (inConstrainedLayoutPhase()) | |
| 931 return false; | |
| 932 | |
| 933 // Breaks can come before or after some objects. We need to track these obje
cts, so that if we get | |
| 934 // multiple breaks for the same object (for example because of multiple layo
uts on the same object), | |
| 935 // we need to invalidate every other region after the old one and start comp
uting from fresh. | |
| 936 RenderObjectToRegionMap& mapToUse = isBefore ? m_breakBeforeToRegionMap : m_
breakAfterToRegionMap; | |
| 937 RenderObjectToRegionMap::iterator iter = mapToUse.find(breakChild); | |
| 938 if (iter != mapToUse.end()) { | |
| 939 RenderRegionList::iterator regionIter = m_regionList.find(iter->value); | |
| 940 ASSERT_WITH_SECURITY_IMPLICATION(regionIter != m_regionList.end()); | |
| 941 ASSERT((*regionIter)->hasAutoLogicalHeight()); | |
| 942 initializeRegionsComputedAutoHeight(*regionIter); | |
| 943 | |
| 944 // We need to update the regions flow thread portion rect because we are
going to process | |
| 945 // a break on these regions. | |
| 946 updateRegionsFlowThreadPortionRect(); | |
| 947 } | |
| 948 | |
| 949 // Simulate a region break at offsetBreakInFlowThread. If it points inside a
n auto logical height region, | |
| 950 // then it determines the region computed auto height. | |
| 951 RenderRegion* region = regionAtBlockOffset(offsetBreakInFlowThread); | |
| 952 if (!region) | |
| 953 return false; | |
| 954 | |
| 955 bool lastBreakAfterContent = breakChild == this; | |
| 956 bool hasComputedAutoHeight = false; | |
| 957 | |
| 958 LayoutUnit currentRegionOffsetInFlowThread = isHorizontalWritingMode() ? reg
ion->flowThreadPortionRect().y() : region->flowThreadPortionRect().x(); | |
| 959 LayoutUnit offsetBreakInCurrentRegion = offsetBreakInFlowThread - currentReg
ionOffsetInFlowThread; | |
| 960 | |
| 961 if (region->hasAutoLogicalHeight()) { | |
| 962 // A forced break can appear only in an auto-height region that didn't h
ave a forced break before. | |
| 963 // This ASSERT is a good-enough heuristic to verify the above condition. | |
| 964 ASSERT(region->maxPageLogicalHeight() == region->computedAutoHeight()); | |
| 965 | |
| 966 mapToUse.set(breakChild, region); | |
| 967 | |
| 968 hasComputedAutoHeight = true; | |
| 969 | |
| 970 // Compute the region height pretending that the offsetBreakInCurrentReg
ion is the logicalHeight for the auto-height region. | |
| 971 LayoutUnit regionComputedAutoHeight = region->constrainContentBoxLogical
HeightByMinMax(offsetBreakInCurrentRegion, -1); | |
| 972 | |
| 973 // The new height of this region needs to be smaller than the initial va
lue, the max height. A forced break is the only way to change the initial | |
| 974 // height of an auto-height region besides content ending. | |
| 975 ASSERT(regionComputedAutoHeight <= region->maxPageLogicalHeight()); | |
| 976 | |
| 977 region->setComputedAutoHeight(regionComputedAutoHeight); | |
| 978 | |
| 979 currentRegionOffsetInFlowThread += regionComputedAutoHeight; | |
| 980 } else { | |
| 981 currentRegionOffsetInFlowThread += isHorizontalWritingMode() ? region->f
lowThreadPortionRect().height() : region->flowThreadPortionRect().width(); | |
| 982 } | |
| 983 | |
| 984 // If the break was found inside an auto-height region its size changed so w
e need to recompute the flow thread portion rectangles. | |
| 985 // Also, if this is the last break after the content we need to clear the co
mputedAutoHeight value on the last empty regions. | |
| 986 if (hasAutoLogicalHeightRegions() && lastBreakAfterContent) | |
| 987 updateRegionsFlowThreadPortionRect(region); | |
| 988 else if (hasComputedAutoHeight) | |
| 989 updateRegionsFlowThreadPortionRect(); | |
| 990 | |
| 991 if (offsetBreakAdjustment) | |
| 992 *offsetBreakAdjustment = max<LayoutUnit>(0, currentRegionOffsetInFlowThr
ead - offsetBreakInFlowThread); | |
| 993 | |
| 994 return hasComputedAutoHeight; | |
| 995 } | |
| 996 | |
| 997 void RenderFlowThread::incrementAutoLogicalHeightRegions() | |
| 998 { | |
| 999 if (!m_autoLogicalHeightRegionsCount) | |
| 1000 view()->flowThreadController()->incrementFlowThreadsWithAutoLogicalHeigh
tRegions(); | |
| 1001 ++m_autoLogicalHeightRegionsCount; | |
| 1002 } | |
| 1003 | |
| 1004 void RenderFlowThread::decrementAutoLogicalHeightRegions() | |
| 1005 { | |
| 1006 ASSERT(m_autoLogicalHeightRegionsCount > 0); | |
| 1007 --m_autoLogicalHeightRegionsCount; | |
| 1008 if (!m_autoLogicalHeightRegionsCount) | |
| 1009 view()->flowThreadController()->decrementFlowThreadsWithAutoLogicalHeigh
tRegions(); | |
| 1010 } | 506 } |
| 1011 | 507 |
| 1012 void RenderFlowThread::collectLayerFragments(LayerFragments& layerFragments, con
st LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect) | 508 void RenderFlowThread::collectLayerFragments(LayerFragments& layerFragments, con
st LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect) |
| 1013 { | 509 { |
| 1014 ASSERT(!m_regionsInvalidated); | 510 ASSERT(!m_regionsInvalidated); |
| 1015 | 511 |
| 1016 for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m
_regionList.end(); ++iter) { | 512 for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m
_regionList.end(); ++iter) { |
| 1017 RenderRegion* region = *iter; | 513 RenderRegion* region = *iter; |
| 1018 region->collectLayerFragments(layerFragments, layerBoundingBox, dirtyRec
t); | 514 region->collectLayerFragments(layerFragments, layerBoundingBox, dirtyRec
t); |
| 1019 } | 515 } |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1160 } | 656 } |
| 1161 | 657 |
| 1162 CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer(RenderFlowT
hread* renderFlowThread) | 658 CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer(RenderFlowT
hread* renderFlowThread) |
| 1163 : m_renderFlowThread(renderFlowThread) | 659 : m_renderFlowThread(renderFlowThread) |
| 1164 , m_previousRenderFlowThread(0) | 660 , m_previousRenderFlowThread(0) |
| 1165 { | 661 { |
| 1166 if (!m_renderFlowThread) | 662 if (!m_renderFlowThread) |
| 1167 return; | 663 return; |
| 1168 RenderView* view = m_renderFlowThread->view(); | 664 RenderView* view = m_renderFlowThread->view(); |
| 1169 m_previousRenderFlowThread = view->flowThreadController()->currentRenderFlow
Thread(); | 665 m_previousRenderFlowThread = view->flowThreadController()->currentRenderFlow
Thread(); |
| 1170 ASSERT(!m_previousRenderFlowThread || !renderFlowThread->isRenderNamedFlowTh
read()); | |
| 1171 view->flowThreadController()->setCurrentRenderFlowThread(m_renderFlowThread)
; | 666 view->flowThreadController()->setCurrentRenderFlowThread(m_renderFlowThread)
; |
| 1172 } | 667 } |
| 1173 | 668 |
| 1174 CurrentRenderFlowThreadMaintainer::~CurrentRenderFlowThreadMaintainer() | 669 CurrentRenderFlowThreadMaintainer::~CurrentRenderFlowThreadMaintainer() |
| 1175 { | 670 { |
| 1176 if (!m_renderFlowThread) | 671 if (!m_renderFlowThread) |
| 1177 return; | 672 return; |
| 1178 RenderView* view = m_renderFlowThread->view(); | 673 RenderView* view = m_renderFlowThread->view(); |
| 1179 ASSERT(view->flowThreadController()->currentRenderFlowThread() == m_renderFl
owThread); | 674 ASSERT(view->flowThreadController()->currentRenderFlowThread() == m_renderFl
owThread); |
| 1180 view->flowThreadController()->setCurrentRenderFlowThread(m_previousRenderFlo
wThread); | 675 view->flowThreadController()->setCurrentRenderFlowThread(m_previousRenderFlo
wThread); |
| 1181 } | 676 } |
| 1182 | 677 |
| 1183 | 678 |
| 1184 } // namespace WebCore | 679 } // namespace WebCore |
| OLD | NEW |