Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / core / layout / LayoutMultiColumnSet.h
blobb7c28b9f483c9e3ca42d774bee5802cd08a2a839
1 /*
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
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 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #ifndef LayoutMultiColumnSet_h
28 #define LayoutMultiColumnSet_h
30 #include "core/CoreExport.h"
31 #include "core/layout/LayoutMultiColumnFlowThread.h"
32 #include "core/layout/MultiColumnFragmentainerGroup.h"
33 #include "wtf/Vector.h"
35 namespace blink {
37 // A set of columns in a multicol container. A column set is inserted as an anonymous child of the
38 // actual multicol container (i.e. the layoutObject whose style computes to non-auto column-count and/or
39 // column-width), next to the flow thread. There'll be one column set for each contiguous run of
40 // column content. The only thing that can interrupt a contiguous run of column content is a column
41 // spanner, which means that if there are no spanners, there'll only be one column set.
43 // Since a spanner interrupts an otherwise contiguous run of column content, inserting one may
44 // result in the creation of additional new column sets. A placeholder for the spanning layoutObject has
45 // to be placed in between the column sets that come before and after the spanner, if there's
46 // actually column content both before and after the spanner.
48 // A column set has no children on its own, but is merely used to slice a portion of the tall
49 // "single-column" flow thread into actual columns visually, to convert from flow thread coordinates
50 // to visual ones. It is in charge of both positioning columns correctly relatively to the parent
51 // multicol container, and to calculate the correct translation for each column's contents, and to
52 // paint any rules between them. LayoutMultiColumnSet objects are used for painting, hit testing,
53 // and any other type of operation that requires mapping from flow thread coordinates to visual
54 // coordinates.
56 // Columns are normally laid out in the inline progression direction, but if the multicol container
57 // is inside another fragmentation context (e.g. paged media, or an another multicol container), we
58 // may need to group the columns, so that we get one MultiColumnFragmentainerGroup for each outer
59 // fragmentainer (page / column) that the inner multicol container lives in. Each fragmentainer
60 // group has its own column height, but the column height is uniform within a group.
61 class CORE_EXPORT LayoutMultiColumnSet : public LayoutBlockFlow {
62 public:
63 static LayoutMultiColumnSet* createAnonymous(LayoutFlowThread&, const ComputedStyle& parentStyle);
65 const MultiColumnFragmentainerGroup& firstFragmentainerGroup() const { return m_fragmentainerGroups.first(); }
66 const MultiColumnFragmentainerGroup& lastFragmentainerGroup() const { return m_fragmentainerGroups.last(); }
67 MultiColumnFragmentainerGroup& fragmentainerGroupAtFlowThreadOffset(LayoutUnit flowThreadOffset)
69 return m_fragmentainerGroups[fragmentainerGroupIndexAtFlowThreadOffset(flowThreadOffset)];
71 const MultiColumnFragmentainerGroup& fragmentainerGroupAtFlowThreadOffset(LayoutUnit flowThreadOffset) const
73 return m_fragmentainerGroups[fragmentainerGroupIndexAtFlowThreadOffset(flowThreadOffset)];
75 const MultiColumnFragmentainerGroup& fragmentainerGroupAtVisualPoint(const LayoutPoint&) const;
77 bool isOfType(LayoutObjectType type) const override { return type == LayoutObjectLayoutMultiColumnSet || LayoutBlockFlow::isOfType(type); }
78 bool canHaveChildren() const final { return false; }
80 // Return the width and height of a single column or page in the set.
81 LayoutUnit pageLogicalWidth() const { return flowThread()->logicalWidth(); }
82 LayoutUnit pageLogicalHeightForOffset(LayoutUnit) const;
83 LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule) const;
84 bool isPageLogicalHeightKnown() const;
86 LayoutFlowThread* flowThread() const { return m_flowThread; }
88 LayoutBlockFlow* multiColumnBlockFlow() const { return toLayoutBlockFlow(parent()); }
89 LayoutMultiColumnFlowThread* multiColumnFlowThread() const { return toLayoutMultiColumnFlowThread(flowThread()); }
91 LayoutMultiColumnSet* nextSiblingMultiColumnSet() const;
92 LayoutMultiColumnSet* previousSiblingMultiColumnSet() const;
94 MultiColumnFragmentainerGroup& appendNewFragmentainerGroup();
96 LayoutUnit logicalTopInFlowThread() const;
97 LayoutUnit logicalBottomInFlowThread() const;
98 LayoutUnit logicalHeightInFlowThread() const { return logicalBottomInFlowThread() - logicalTopInFlowThread(); }
99 LayoutRect flowThreadPortionRect() const;
100 LayoutRect flowThreadPortionOverflowRect() const;
101 LayoutRect overflowRectForFlowThreadPortion(const LayoutRect& flowThreadPortionRect, bool isFirstPortion, bool isLastPortion) const;
103 // The used CSS value of column-count, i.e. how many columns there are room for without overflowing.
104 unsigned usedColumnCount() const { return multiColumnFlowThread()->columnCount(); }
106 bool heightIsAuto() const;
108 // Find the column that contains the given block offset, and return the translation needed to
109 // get from flow thread coordinates to visual coordinates.
110 LayoutSize flowThreadTranslationAtOffset(LayoutUnit) const;
112 LayoutPoint visualPointToFlowThreadPoint(const LayoutPoint& visualPoint) const;
114 void updateMinimumColumnHeight(LayoutUnit offsetInFlowThread, LayoutUnit height);
116 // Add a content run, specified by its end position. A content run is appended at every
117 // forced/explicit break and at the end of the column set. The content runs are used to
118 // determine where implicit/soft breaks will occur, in order to calculate an initial column
119 // height.
120 void addContentRun(LayoutUnit endOffsetFromFirstPage);
122 // (Re-)calculate the column height if it's auto. This is first and foremost needed by sets that
123 // are to balance the column height, but even when it isn't to be balanced, this is necessary if
124 // the multicol container's height is constrained.
125 bool recalculateColumnHeight(BalancedColumnHeightCalculation);
127 // Record space shortage (the amount of space that would have been enough to prevent some
128 // element from being moved to the next column) at a column break. The smallest amount of space
129 // shortage we find is the amount with which we will stretch the column height, if it turns out
130 // after layout that the columns weren't tall enough.
131 void recordSpaceShortage(LayoutUnit offsetInFlowThread, LayoutUnit);
133 // Reset previously calculated column height. Will mark for layout if needed.
134 void resetColumnHeight();
136 // Layout of flow thread content that's to be rendered inside this column set begins. This
137 // happens at the beginning of flow thread layout, and when advancing from a previous column set
138 // or spanner to this one.
139 void beginFlow(LayoutUnit offsetInFlowThread);
141 // Layout of flow thread content that was to be rendered inside this column set has
142 // finished. This happens at end of flow thread layout, and when advancing to the next column
143 // set or spanner.
144 void endFlow(LayoutUnit offsetInFlowThread);
146 void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const final;
148 void attachToFlowThread();
149 void detachFromFlowThread();
151 // The top of the page nearest to the specified block offset. All in flowthread coordinates.
152 LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
154 LayoutRect fragmentsBoundingBox(const LayoutRect& boundingBoxInFlowThread) const;
156 void collectLayerFragments(DeprecatedPaintLayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect);
158 LayoutUnit columnGap() const;
160 // The "CSS actual" value of column-count. This includes overflowing columns, if any.
161 unsigned actualColumnCount() const;
163 const char* name() const override { return "LayoutMultiColumnSet"; }
165 protected:
166 LayoutMultiColumnSet(LayoutFlowThread*);
168 private:
169 unsigned fragmentainerGroupIndexAtFlowThreadOffset(LayoutUnit) const;
171 void insertedIntoTree() final;
172 void willBeRemovedFromTree() final;
174 bool isSelfCollapsingBlock() const override { return false; }
176 void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const override;
177 PositionWithAffinity positionForPoint(const LayoutPoint&) override;
179 void paintObject(const PaintInfo&, const LayoutPoint& paintOffset) override;
181 void addOverflowFromChildren() override;
183 MultiColumnFragmentainerGroupList m_fragmentainerGroups;
184 LayoutFlowThread* m_flowThread;
187 DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutMultiColumnSet, isLayoutMultiColumnSet());
189 } // namespace blink
191 #endif // LayoutMultiColumnSet_h