Chromium Code Reviews| Index: Source/core/layout/MultiColumnFragmentainerGroup.h |
| diff --git a/Source/core/layout/MultiColumnFragmentainerGroup.h b/Source/core/layout/MultiColumnFragmentainerGroup.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..afd6aee2e20251df356643b27634d01636f85317 |
| --- /dev/null |
| +++ b/Source/core/layout/MultiColumnFragmentainerGroup.h |
| @@ -0,0 +1,155 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef MultiColumnFragmentainerGroup_h |
| +#define MultiColumnFragmentainerGroup_h |
| + |
| +#include "core/rendering/RenderMultiColumnFlowThread.h" |
| + |
| +namespace blink { |
| + |
| +// A group of columns, that are laid out in the inline progression direction, all with the same |
| +// column height. |
| +// |
| +// When a multicol container is inside another fragmentation context, and said multicol container |
| +// lives in multiple outer fragmentainers (pages / columns), we need to put these inner columns into |
| +// separate groups, with one group per outer fragmentainer. Such a group of columns is what |
| +// comprises a "row of column boxes" in spec lingo. |
| +// |
| +// Column balancing, when enabled, takes place within a column fragmentainer group. |
| +// |
| +// Each fragmentainer group may have its own actual column count (if there are unused columns |
| +// because of forced breaks, for example). If there are multiple fragmentainer groups, the actual |
| +// column count must not exceed the used column count (the one calculated based on column-count and |
| +// column-width from CSS), or they'd overflow the outer fragmentainer in the inline direction. If we |
| +// need more columns than what a group has room for, we'll create another group and put them there |
| +// (and make them appear in the next outer fragmentainer). |
| +class MultiColumnFragmentainerGroup { |
| +public: |
| + MultiColumnFragmentainerGroup(RenderMultiColumnSet&); |
| + |
| + bool isLastGroup() const; |
| + |
| + // Position within the RenderMultiColumnSet. |
| + LayoutUnit logicalTop() const { return m_logicalTop; } |
| + |
| + LayoutUnit logicalHeight() const { return m_columnHeight; } |
| + |
| + LayoutSize offsetFromColumnSet() const; |
| + |
| + // The top of our flow thread portion |
| + LayoutUnit logicalTopInFlowThread() const { return m_logicalTopInFlowThread; } |
| + void setLogicalTopInFlowThread(LayoutUnit logicalTopInFlowThread) { m_logicalTopInFlowThread = logicalTopInFlowThread; } |
| + |
| + // The bottom of our flow thread portion |
| + LayoutUnit logicalBottomInFlowThread() const { return m_logicalBottomInFlowThread; } |
| + void setLogicalBottomInFlowThread(LayoutUnit logicalBottomInFlowThread) { m_logicalBottomInFlowThread = logicalBottomInFlowThread; } |
| + |
| + // The height of our flow thread portion |
| + LayoutUnit logicalHeightInFlowThread() const { return m_logicalBottomInFlowThread - m_logicalTopInFlowThread; } |
| + |
| + bool heightIsAuto() const; |
| + void resetColumnHeight(); |
| + void addContentRun(LayoutUnit endOffsetInFlowThread); |
| + void updateMinimumColumnHeight(LayoutUnit height) { m_minimumColumnHeight = std::max(height, m_minimumColumnHeight); } |
| + void recordSpaceShortage(LayoutUnit); |
| + bool recalculateColumnHeight(BalancedColumnHeightCalculation calculationMode); |
| + |
| + void expandToEncompassFlowThreadOverflow(); |
| + |
| + LayoutSize flowThreadTranslationAtOffset(LayoutUnit offsetInFlowThread) const; |
| + LayoutUnit columnLogicalTopForOffset(LayoutUnit offsetInFlowThread) const; |
| + void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect) const; |
| + LayoutRect calculateOverflow() const; |
| + |
| + // The "CSS actual" value of column-count. This includes overflowing columns, if any. |
| + unsigned actualColumnCount() const; |
| + |
| +private: |
| + LayoutUnit heightAdjustedForRowOffset(LayoutUnit height) const; |
| + LayoutUnit calculateMaxColumnHeight() const; |
| + void setAndConstrainColumnHeight(LayoutUnit); |
| + |
| + // Return the index of the content run with the currently tallest columns, taking all implicit |
| + // breaks assumed so far into account. |
| + unsigned findRunWithTallestColumns() const; |
|
Julien - ping for review
2015/02/11 07:25:29
I think we should use size_t for indexes (we are i
mstensho (USE GERRIT)
2015/02/11 09:49:55
This is just code that got moved. Let's fix this i
|
| + |
| + // Given the current list of content runs, make assumptions about where we need to insert |
| + // implicit breaks (if there's room for any at all; depending on the number of explicit breaks), |
| + // and store the results. This is needed in order to balance the columns. |
| + void distributeImplicitBreaks(); |
| + |
| + LayoutUnit calculateColumnHeight(BalancedColumnHeightCalculation) const; |
| + |
| + LayoutRect columnRectAt(unsigned columnIndex) const; |
| + LayoutRect flowThreadPortionRectAt(unsigned columnIndex) const; |
| + LayoutRect flowThreadPortionOverflowRect(const LayoutRect& flowThreadPortion, unsigned columnIndex, unsigned columnCount, LayoutUnit columnGap) const; |
| + |
| + enum ColumnIndexCalculationMode { |
| + ClampToExistingColumns, // Stay within the range of already existing columns. |
| + AssumeNewColumns // Allow column indices outside the range of already existing columns. |
| + }; |
| + unsigned columnIndexAtOffset(LayoutUnit offsetInFlowThread, ColumnIndexCalculationMode = ClampToExistingColumns) const; |
| + |
| + RenderMultiColumnSet& m_columnSet; |
| + |
| + LayoutUnit m_logicalTop; |
| + LayoutUnit m_logicalTopInFlowThread; |
| + LayoutUnit m_logicalBottomInFlowThread; |
| + |
| + LayoutUnit m_columnHeight; |
| + |
| + // The following variables are used when balancing the column set. |
| + LayoutUnit m_maxColumnHeight; // Maximum column height allowed. |
| + LayoutUnit m_minSpaceShortage; // The smallest amout of space shortage that caused a column break. |
| + LayoutUnit m_minimumColumnHeight; |
| + |
| + // A run of content without explicit (forced) breaks; i.e. a flow thread portion between two |
| + // explicit breaks, between flow thread start and an explicit break, between an explicit break |
| + // and flow thread end, or, in cases when there are no explicit breaks at all: between flow |
| + // thread portion start and flow thread portion end. We need to know where the explicit breaks |
| + // are, in order to figure out where the implicit breaks will end up, so that we get the columns |
| + // properly balanced. A content run starts out as representing one single column, and will |
| + // represent one additional column for each implicit break "inserted" there. |
| + class ContentRun { |
| + public: |
| + ContentRun(LayoutUnit breakOffset) |
| + : m_breakOffset(breakOffset) |
| + , m_assumedImplicitBreaks(0) { } |
| + |
| + unsigned assumedImplicitBreaks() const { return m_assumedImplicitBreaks; } |
| + void assumeAnotherImplicitBreak() { m_assumedImplicitBreaks++; } |
| + LayoutUnit breakOffset() const { return m_breakOffset; } |
| + |
| + // Return the column height that this content run would require, considering the implicit |
| + // breaks assumed so far. |
| + LayoutUnit columnLogicalHeight(LayoutUnit startOffset) const { return ceilf((m_breakOffset - startOffset).toFloat() / float(m_assumedImplicitBreaks + 1)); } |
| + |
| + private: |
| + LayoutUnit m_breakOffset; // Flow thread offset where this run ends. |
| + unsigned m_assumedImplicitBreaks; // Number of implicit breaks in this run assumed so far. |
| + }; |
| + Vector<ContentRun, 1> m_contentRuns; |
| +}; |
| + |
| +// List of all fragmentainer groups within a column set. There will always be at least one |
| +// group. Deleting the one group is not allowed (or possible). There will be more than one group if |
| +// the owning column set lives in multiple outer fragmentainers (e.g. multicol inside paged media). |
| +class MultiColumnFragmentainerGroupList : public Vector<MultiColumnFragmentainerGroup, 1> { |
|
Nico
2015/04/09 04:39:34
Let's not derive from container types. If your cla
|
| +public: |
| + MultiColumnFragmentainerGroupList(RenderMultiColumnSet&); |
| + |
| + // Add an additional fragmentainer group to the end of the list, and return it. |
| + MultiColumnFragmentainerGroup& addExtraGroup(); |
| + |
| + // Remove all fragmentainer groups but the first one. |
| + void deleteExtraGroups(); |
| + |
| +private: |
| + RenderMultiColumnSet& m_columnSet; |
| +}; |
| + |
| +} // namespace blink |
| + |
| +#endif // MultiColumnFragmentainerGroup_h |