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 RenderRegion; 45 46 typedef ListHashSet<RenderRegion*> RenderRegionList; 47 48 // RenderFlowThread is used to collect all the render objects that participate in a 49 // flow thread. It will also help in doing the layout. However, it will not render 50 // directly to screen. Instead, RenderRegion objects will redirect their paint 51 // and nodeAtPoint methods to this object. Each RenderRegion will actually be a viewPort 52 // of the RenderFlowThread. 53 54 class RenderFlowThread: public RenderBlockFlow { 55 public: 56 RenderFlowThread(); 57 virtual ~RenderFlowThread() { }; 58 59 virtual bool isRenderFlowThread() const OVERRIDE FINAL { return true; } 60 virtual bool isRenderMultiColumnFlowThread() const { return false; } 61 62 virtual void layout() OVERRIDE; 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 NormalLayer; } 67 68 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE FINAL; 69 70 virtual void addRegionToThread(RenderRegion*) = 0; 71 virtual void removeRegionFromThread(RenderRegion*); 72 const RenderRegionList& renderRegionList() const { return m_regionList; } 73 74 virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE; 75 76 bool hasRegions() const { return m_regionList.size(); } 77 78 void validateRegions(); 79 void invalidateRegions(); 80 bool hasValidRegionInfo() const { return !m_regionsInvalidated && !m_regionList.isEmpty(); } 81 82 void repaintRectangleInRegions(const LayoutRect&) const; 83 84 LayoutPoint adjustedPositionRelativeToOffsetParent(const RenderBoxModelObject&, const LayoutPoint&); 85 86 LayoutUnit pageLogicalTopForOffset(LayoutUnit); 87 LayoutUnit pageLogicalHeightForOffset(LayoutUnit); 88 LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule = IncludePageBoundary); 89 90 virtual void setPageBreak(LayoutUnit /*offset*/, LayoutUnit /*spaceShortage*/) { } 91 virtual void updateMinimumPageHeight(LayoutUnit /*offset*/, LayoutUnit /*minHeight*/) { } 92 93 virtual RenderRegion* regionAtBlockOffset(LayoutUnit) const; 94 95 bool regionsHaveUniformLogicalHeight() const { return m_regionsHaveUniformLogicalHeight; } 96 97 RenderRegion* firstRegion() const; 98 RenderRegion* lastRegion() const; 99 100 void setRegionRangeForBox(const RenderBox*, LayoutUnit offsetFromLogicalTopOfFirstPage); 101 void getRegionRangeForBox(const RenderBox*, RenderRegion*& startRegion, RenderRegion*& endRegion) const; 102 103 virtual bool addForcedRegionBreak(LayoutUnit, RenderObject* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment = 0) { return false; } 104 105 virtual bool isPageLogicalHeightKnown() const { return true; } 106 bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; } 107 108 void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect); 109 LayoutRect fragmentsBoundingBox(const LayoutRect& layerBoundingBox); 110 111 void pushFlowThreadLayoutState(const RenderObject&); 112 void popFlowThreadLayoutState(); 113 LayoutUnit offsetFromLogicalTopOfFirstRegion(const RenderBlock*) const; 114 115 // Used to estimate the maximum height of the flow thread. 116 static LayoutUnit maxLogicalHeight() { return LayoutUnit::max() / 2; } 117 118 protected: 119 virtual const char* renderName() const = 0; 120 121 void updateRegionsFlowThreadPortionRect(); 122 bool shouldRepaint(const LayoutRect&) const; 123 124 bool cachedOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit&) const; 125 void setOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit); 126 void clearOffsetFromLogicalTopOfFirstRegion(const RenderBox*); 127 128 const RenderBox* currentStatePusherRenderBox() const; 129 130 RenderRegionList m_regionList; 131 132 class RenderRegionRange { 133 public: 134 RenderRegionRange() 135 { 136 setRange(0, 0); 137 } 138 139 RenderRegionRange(RenderRegion* start, RenderRegion* end) 140 { 141 setRange(start, end); 142 } 143 144 void setRange(RenderRegion* start, RenderRegion* end) 145 { 146 m_startRegion = start; 147 m_endRegion = end; 148 } 149 150 RenderRegion* startRegion() const { return m_startRegion; } 151 RenderRegion* endRegion() const { return m_endRegion; } 152 153 private: 154 RenderRegion* m_startRegion; 155 RenderRegion* m_endRegion; 156 }; 157 158 typedef PODInterval<LayoutUnit, RenderRegion*> RegionInterval; 159 typedef PODIntervalTree<LayoutUnit, RenderRegion*> RegionIntervalTree; 160 161 class RegionSearchAdapter { 162 public: 163 RegionSearchAdapter(LayoutUnit offset) 164 : m_offset(offset) 165 , m_result(0) 166 { 167 } 168 169 const LayoutUnit& lowValue() const { return m_offset; } 170 const LayoutUnit& highValue() const { return m_offset; } 171 void collectIfNeeded(const RegionInterval&); 172 173 RenderRegion* result() const { return m_result; } 174 175 private: 176 LayoutUnit m_offset; 177 RenderRegion* m_result; 178 }; 179 180 // A maps from RenderBox 181 typedef HashMap<const RenderBox*, RenderRegionRange> RenderRegionRangeMap; 182 RenderRegionRangeMap m_regionRangeMap; 183 184 // Stack of objects that pushed a LayoutState object on the RenderView. The 185 // objects on the stack are the ones that are curently in the process of being 186 // laid out. 187 ListHashSet<const RenderObject*> m_statePusherObjectsStack; 188 typedef HashMap<const RenderBox*, LayoutUnit> RenderBoxToOffsetMap; 189 RenderBoxToOffsetMap m_boxesToOffsetMap; 190 191 RegionIntervalTree m_regionIntervalTree; 192 193 bool m_regionsInvalidated : 1; 194 bool m_regionsHaveUniformLogicalHeight : 1; 195 bool m_pageLogicalSizeChanged : 1; 196 }; 197 198 DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderFlowThread, isRenderFlowThread()); 199 200 class CurrentRenderFlowThreadMaintainer { 201 WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadMaintainer); 202 public: 203 CurrentRenderFlowThreadMaintainer(RenderFlowThread*); 204 ~CurrentRenderFlowThreadMaintainer(); 205 private: 206 RenderFlowThread* m_renderFlowThread; 207 RenderFlowThread* m_previousRenderFlowThread; 208 }; 209 210 // These structures are used by PODIntervalTree for debugging. 211 #ifndef NDEBUG 212 template <> struct ValueToString<LayoutUnit> { 213 static String string(const LayoutUnit value) { return String::number(value.toFloat()); } 214 }; 215 216 template <> struct ValueToString<RenderRegion*> { 217 static String string(const RenderRegion* value) { return String::format("%p", value); } 218 }; 219 #endif 220 221 } // namespace WebCore 222 223 #endif // RenderFlowThread_h 224