| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions | |
| 6 * are met: | |
| 7 * | |
| 8 * 1. Redistributions of source code must retain the above | |
| 9 * copyright notice, this list of conditions and the following | |
| 10 * disclaimer. | |
| 11 * 2. Redistributions in binary form must reproduce the above | |
| 12 * copyright notice, this list of conditions and the following | |
| 13 * disclaimer in the documentation and/or other materials | |
| 14 * provided with the distribution. | |
| 15 * | |
| 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY | |
| 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE | |
| 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, | |
| 21 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | |
| 25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF | |
| 26 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 27 * SUCH DAMAGE. | |
| 28 */ | |
| 29 | |
| 30 #ifndef RenderFlowThread_h | |
| 31 #define RenderFlowThread_h | |
| 32 | |
| 33 | |
| 34 #include "core/rendering/RenderBlockFlow.h" | |
| 35 #include "wtf/HashCountedSet.h" | |
| 36 #include "wtf/ListHashSet.h" | |
| 37 #include "wtf/PassRefPtr.h" | |
| 38 | |
| 39 namespace WebCore { | |
| 40 | |
| 41 struct LayerFragment; | |
| 42 typedef Vector<LayerFragment, 1> LayerFragments; | |
| 43 class RenderFlowThread; | |
| 44 class RenderStyle; | |
| 45 class RenderRegion; | |
| 46 | |
| 47 typedef ListHashSet<RenderRegion*> RenderRegionList; | |
| 48 | |
| 49 // RenderFlowThread is used to collect all the render objects that participate i
n a | |
| 50 // flow thread. It will also help in doing the layout. However, it will not rend
er | |
| 51 // directly to screen. Instead, RenderRegion objects will redirect their paint | |
| 52 // and nodeAtPoint methods to this object. Each RenderRegion will actually be a
viewPort | |
| 53 // of the RenderFlowThread. | |
| 54 | |
| 55 class RenderFlowThread: public RenderBlockFlow { | |
| 56 public: | |
| 57 RenderFlowThread(); | |
| 58 virtual ~RenderFlowThread() { }; | |
| 59 | |
| 60 virtual bool isRenderFlowThread() const OVERRIDE FINAL { return true; } | |
| 61 | |
| 62 virtual void layout() OVERRIDE FINAL; | |
| 63 | |
| 64 // Always create a RenderLayer for the RenderFlowThread so that we | |
| 65 // can easily avoid drawing the children directly. | |
| 66 virtual LayerType layerTypeRequired() const OVERRIDE FINAL { return NormalLa
yer; } | |
| 67 | |
| 68 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTes
tLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAct
ion) OVERRIDE FINAL; | |
| 69 | |
| 70 void removeFlowChildInfo(RenderObject*); | |
| 71 #ifndef NDEBUG | |
| 72 bool hasChildInfo(RenderObject* child) const { return child && child->isBox(
) && m_regionRangeMap.contains(toRenderBox(child)); } | |
| 73 #endif | |
| 74 | |
| 75 virtual void addRegionToThread(RenderRegion*); | |
| 76 virtual void removeRegionFromThread(RenderRegion*); | |
| 77 const RenderRegionList& renderRegionList() const { return m_regionList; } | |
| 78 | |
| 79 virtual void updateLogicalWidth() OVERRIDE FINAL; | |
| 80 virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logic
alTop, LogicalExtentComputedValues&) const OVERRIDE; | |
| 81 | |
| 82 void paintFlowThreadPortionInRegion(PaintInfo&, RenderRegion*, const LayoutR
ect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, con
st LayoutPoint&) const; | |
| 83 bool hitTestFlowThreadPortionInRegion(RenderRegion*, const LayoutRect& flowT
hreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, const HitTest
Request&, HitTestResult&, const HitTestLocation& locationInContainer, const Layo
utPoint& accumulatedOffset) const; | |
| 84 | |
| 85 bool hasRegions() const { return m_regionList.size(); } | |
| 86 // Check if the content is flown into at least a region with region styling
rules. | |
| 87 bool hasRegionsWithStyling() const { return m_hasRegionsWithStyling; } | |
| 88 void checkRegionsWithStyling(); | |
| 89 virtual void regionChangedWritingMode(RenderRegion*) { } | |
| 90 | |
| 91 void validateRegions(); | |
| 92 void invalidateRegions(); | |
| 93 bool hasValidRegionInfo() const { return !m_regionsInvalidated && !m_regionL
ist.isEmpty(); } | |
| 94 | |
| 95 static PassRefPtr<RenderStyle> createFlowThreadStyle(RenderStyle* parentStyl
e); | |
| 96 | |
| 97 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OV
ERRIDE; | |
| 98 | |
| 99 void repaintRectangleInRegions(const LayoutRect&) const; | |
| 100 | |
| 101 LayoutPoint adjustedPositionRelativeToOffsetParent(const RenderBoxModelObjec
t&, const LayoutPoint&); | |
| 102 | |
| 103 LayoutUnit pageLogicalTopForOffset(LayoutUnit); | |
| 104 LayoutUnit pageLogicalWidthForOffset(LayoutUnit); | |
| 105 LayoutUnit pageLogicalHeightForOffset(LayoutUnit); | |
| 106 LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule
= IncludePageBoundary); | |
| 107 | |
| 108 virtual void setPageBreak(LayoutUnit /*offset*/, LayoutUnit /*spaceShortage*
/) { } | |
| 109 virtual void updateMinimumPageHeight(LayoutUnit /*offset*/, LayoutUnit /*min
Height*/) { } | |
| 110 | |
| 111 enum RegionAutoGenerationPolicy { | |
| 112 AllowRegionAutoGeneration, | |
| 113 DisallowRegionAutoGeneration, | |
| 114 }; | |
| 115 RenderRegion* regionAtBlockOffset(LayoutUnit, bool extendLastRegion = false,
RegionAutoGenerationPolicy = AllowRegionAutoGeneration); | |
| 116 | |
| 117 RenderRegion* regionFromAbsolutePointAndBox(IntPoint, const RenderBox* flowe
dBox); | |
| 118 | |
| 119 bool regionsHaveUniformLogicalWidth() const { return m_regionsHaveUniformLog
icalWidth; } | |
| 120 bool regionsHaveUniformLogicalHeight() const { return m_regionsHaveUniformLo
gicalHeight; } | |
| 121 | |
| 122 RenderRegion* mapFromFlowToRegion(TransformState&) const; | |
| 123 | |
| 124 void removeRenderBoxRegionInfo(RenderBox*); | |
| 125 bool logicalWidthChangedInRegionsForBlock(const RenderBlock*); | |
| 126 | |
| 127 LayoutUnit contentLogicalWidthOfFirstRegion() const; | |
| 128 LayoutUnit contentLogicalHeightOfFirstRegion() const; | |
| 129 LayoutUnit contentLogicalLeftOfFirstRegion() const; | |
| 130 | |
| 131 RenderRegion* firstRegion() const; | |
| 132 RenderRegion* lastRegion() const; | |
| 133 | |
| 134 bool previousRegionCountChanged() const { return m_previousRegionCount != m_
regionList.size(); } | |
| 135 void updatePreviousRegionCount() { m_previousRegionCount = m_regionList.size
(); } | |
| 136 | |
| 137 void setRegionRangeForBox(const RenderBox*, LayoutUnit offsetFromLogicalTopO
fFirstPage); | |
| 138 void getRegionRangeForBox(const RenderBox*, RenderRegion*& startRegion, Rend
erRegion*& endRegion) const; | |
| 139 | |
| 140 void clearRenderObjectCustomStyle(const RenderObject*, | |
| 141 const RenderRegion* oldStartRegion = 0, const RenderRegion* oldEndRegion
= 0, | |
| 142 const RenderRegion* newStartRegion = 0, const RenderRegion* newEndRegion
= 0); | |
| 143 | |
| 144 // Check if the object is in region and the region is part of this flow thre
ad. | |
| 145 bool objectInFlowRegion(const RenderObject*, const RenderRegion*) const; | |
| 146 | |
| 147 void markAutoLogicalHeightRegionsForLayout(); | |
| 148 | |
| 149 bool addForcedRegionBreak(LayoutUnit, RenderObject* breakChild, bool isBefor
e, LayoutUnit* offsetBreakAdjustment = 0); | |
| 150 void applyBreakAfterContent(LayoutUnit); | |
| 151 | |
| 152 bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; } | |
| 153 | |
| 154 bool hasAutoLogicalHeightRegions() const { ASSERT(isAutoLogicalHeightRegions
CountConsistent()); return m_autoLogicalHeightRegionsCount; } | |
| 155 void incrementAutoLogicalHeightRegions(); | |
| 156 void decrementAutoLogicalHeightRegions(); | |
| 157 | |
| 158 #ifndef NDEBUG | |
| 159 bool isAutoLogicalHeightRegionsCountConsistent() const; | |
| 160 #endif | |
| 161 | |
| 162 void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingB
ox, const LayoutRect& dirtyRect); | |
| 163 LayoutRect fragmentsBoundingBox(const LayoutRect& layerBoundingBox); | |
| 164 | |
| 165 void setInConstrainedLayoutPhase(bool value) { m_inConstrainedLayoutPhase =
value; } | |
| 166 bool inConstrainedLayoutPhase() const { return m_inConstrainedLayoutPhase; } | |
| 167 | |
| 168 bool needsTwoPhasesLayout() const { return m_needsTwoPhasesLayout; } | |
| 169 void clearNeedsTwoPhasesLayout() { m_needsTwoPhasesLayout = false; } | |
| 170 | |
| 171 void pushFlowThreadLayoutState(const RenderObject*); | |
| 172 void popFlowThreadLayoutState(); | |
| 173 LayoutUnit offsetFromLogicalTopOfFirstRegion(const RenderBlock*) const; | |
| 174 | |
| 175 // Used to estimate the maximum height of the flow thread. | |
| 176 static LayoutUnit maxLogicalHeight() { return LayoutUnit::max() / 2; } | |
| 177 | |
| 178 protected: | |
| 179 virtual const char* renderName() const = 0; | |
| 180 | |
| 181 // Overridden by columns/pages to set up an initial logical width of the pag
e width even when | |
| 182 // no regions have been generated yet. | |
| 183 virtual LayoutUnit initialLogicalWidth() const { return 0; }; | |
| 184 | |
| 185 virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContai
ner, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed =
0) const OVERRIDE FINAL; | |
| 186 | |
| 187 void updateRegionsFlowThreadPortionRect(const RenderRegion* = 0); | |
| 188 bool shouldRepaint(const LayoutRect&) const; | |
| 189 bool regionInRange(const RenderRegion* targetRegion, const RenderRegion* sta
rtRegion, const RenderRegion* endRegion) const; | |
| 190 | |
| 191 LayoutRect computeRegionClippingRect(const LayoutPoint&, const LayoutRect&,
const LayoutRect&) const; | |
| 192 | |
| 193 void setDispatchRegionLayoutUpdateEvent(bool value) { m_dispatchRegionLayout
UpdateEvent = value; } | |
| 194 bool shouldDispatchRegionLayoutUpdateEvent() { return m_dispatchRegionLayout
UpdateEvent; } | |
| 195 | |
| 196 void setDispatchRegionOversetChangeEvent(bool value) { m_dispatchRegionOvers
etChangeEvent = value; } | |
| 197 bool shouldDispatchRegionOversetChangeEvent() const { return m_dispatchRegio
nOversetChangeEvent; } | |
| 198 | |
| 199 // Override if the flow thread implementation supports dispatching events wh
en the flow layout is updated (e.g. for named flows) | |
| 200 virtual void dispatchRegionLayoutUpdateEvent() { m_dispatchRegionLayoutUpdat
eEvent = false; } | |
| 201 virtual void dispatchRegionOversetChangeEvent() { m_dispatchRegionOversetCha
ngeEvent = false; } | |
| 202 | |
| 203 void initializeRegionsComputedAutoHeight(RenderRegion* = 0); | |
| 204 | |
| 205 virtual void autoGenerateRegionsToBlockOffset(LayoutUnit) { }; | |
| 206 | |
| 207 bool cachedOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit&)
const; | |
| 208 void setOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit); | |
| 209 void clearOffsetFromLogicalTopOfFirstRegion(const RenderBox*); | |
| 210 | |
| 211 const RenderBox* currentStatePusherRenderBox() const; | |
| 212 | |
| 213 RenderRegionList m_regionList; | |
| 214 unsigned short m_previousRegionCount; | |
| 215 | |
| 216 class RenderRegionRange { | |
| 217 public: | |
| 218 RenderRegionRange() | |
| 219 { | |
| 220 setRange(0, 0); | |
| 221 } | |
| 222 | |
| 223 RenderRegionRange(RenderRegion* start, RenderRegion* end) | |
| 224 { | |
| 225 setRange(start, end); | |
| 226 } | |
| 227 | |
| 228 void setRange(RenderRegion* start, RenderRegion* end) | |
| 229 { | |
| 230 m_startRegion = start; | |
| 231 m_endRegion = end; | |
| 232 } | |
| 233 | |
| 234 RenderRegion* startRegion() const { return m_startRegion; } | |
| 235 RenderRegion* endRegion() const { return m_endRegion; } | |
| 236 | |
| 237 private: | |
| 238 RenderRegion* m_startRegion; | |
| 239 RenderRegion* m_endRegion; | |
| 240 }; | |
| 241 | |
| 242 typedef PODInterval<LayoutUnit, RenderRegion*> RegionInterval; | |
| 243 typedef PODIntervalTree<LayoutUnit, RenderRegion*> RegionIntervalTree; | |
| 244 | |
| 245 class RegionSearchAdapter { | |
| 246 public: | |
| 247 RegionSearchAdapter(LayoutUnit offset) | |
| 248 : m_offset(offset) | |
| 249 , m_result(0) | |
| 250 { | |
| 251 } | |
| 252 | |
| 253 const LayoutUnit& lowValue() const { return m_offset; } | |
| 254 const LayoutUnit& highValue() const { return m_offset; } | |
| 255 void collectIfNeeded(const RegionInterval&); | |
| 256 | |
| 257 RenderRegion* result() const { return m_result; } | |
| 258 | |
| 259 private: | |
| 260 LayoutUnit m_offset; | |
| 261 RenderRegion* m_result; | |
| 262 }; | |
| 263 | |
| 264 // A maps from RenderBox | |
| 265 typedef HashMap<const RenderBox*, RenderRegionRange> RenderRegionRangeMap; | |
| 266 RenderRegionRangeMap m_regionRangeMap; | |
| 267 | |
| 268 typedef HashMap<RenderObject*, RenderRegion*> RenderObjectToRegionMap; | |
| 269 RenderObjectToRegionMap m_breakBeforeToRegionMap; | |
| 270 RenderObjectToRegionMap m_breakAfterToRegionMap; | |
| 271 | |
| 272 // Stack of objects that pushed a LayoutState object on the RenderView. The | |
| 273 // objects on the stack are the ones that are curently in the process of bei
ng | |
| 274 // laid out. | |
| 275 ListHashSet<const RenderObject*> m_statePusherObjectsStack; | |
| 276 typedef HashMap<const RenderBox*, LayoutUnit> RenderBoxToOffsetMap; | |
| 277 RenderBoxToOffsetMap m_boxesToOffsetMap; | |
| 278 | |
| 279 unsigned m_autoLogicalHeightRegionsCount; | |
| 280 | |
| 281 RegionIntervalTree m_regionIntervalTree; | |
| 282 | |
| 283 bool m_regionsInvalidated : 1; | |
| 284 bool m_regionsHaveUniformLogicalWidth : 1; | |
| 285 bool m_regionsHaveUniformLogicalHeight : 1; | |
| 286 bool m_hasRegionsWithStyling : 1; | |
| 287 bool m_dispatchRegionLayoutUpdateEvent : 1; | |
| 288 bool m_dispatchRegionOversetChangeEvent : 1; | |
| 289 bool m_pageLogicalSizeChanged : 1; | |
| 290 bool m_inConstrainedLayoutPhase : 1; | |
| 291 bool m_needsTwoPhasesLayout : 1; | |
| 292 | |
| 293 private: | |
| 294 virtual bool supportsPartialLayout() const OVERRIDE FINAL { return false; } | |
| 295 | |
| 296 }; | |
| 297 | |
| 298 DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderFlowThread, isRenderFlowThread()); | |
| 299 | |
| 300 class CurrentRenderFlowThreadMaintainer { | |
| 301 WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadMaintainer); | |
| 302 public: | |
| 303 CurrentRenderFlowThreadMaintainer(RenderFlowThread*); | |
| 304 ~CurrentRenderFlowThreadMaintainer(); | |
| 305 private: | |
| 306 RenderFlowThread* m_renderFlowThread; | |
| 307 RenderFlowThread* m_previousRenderFlowThread; | |
| 308 }; | |
| 309 | |
| 310 // These structures are used by PODIntervalTree for debugging. | |
| 311 #ifndef NDEBUG | |
| 312 template <> struct ValueToString<LayoutUnit> { | |
| 313 static String string(const LayoutUnit value) { return String::number(value.t
oFloat()); } | |
| 314 }; | |
| 315 | |
| 316 template <> struct ValueToString<RenderRegion*> { | |
| 317 static String string(const RenderRegion* value) { return String::format("%p"
, value); } | |
| 318 }; | |
| 319 #endif | |
| 320 | |
| 321 } // namespace WebCore | |
| 322 | |
| 323 #endif // RenderFlowThread_h | |
| OLD | NEW |