6a3f457e033fab68c263caf04303b5b514d29bec
[WebKit-https.git] / Source / WebCore / rendering / LogicalSelectionOffsetCaches.h
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #ifndef LogicalSelectionOffsetCaches_h
22 #define LogicalSelectionOffsetCaches_h
23
24 #include "RenderBlock.h"
25
26 namespace WebCore {
27
28 class LogicalSelectionOffsetCaches {
29 public:
30     class ContainingBlockInfo {
31     public:
32         ContainingBlockInfo()
33             : m_hasFloatsOrFlowThreads(false)
34             , m_cachedLogicalLeftSelectionOffset(false)
35             , m_cachedLogicalRightSelectionOffset(false)
36         { }
37
38         void setBlock(RenderBlock* block, const LogicalSelectionOffsetCaches* cache, bool parentCacheHasFloatsOrFlowThreads = false)
39         {
40             m_block = block;
41             bool blockHasFloatsOrFlowThreads = m_block ? (m_block->containsFloats() || m_block->flowThreadContainingBlock()) : false;
42             m_hasFloatsOrFlowThreads = parentCacheHasFloatsOrFlowThreads || m_hasFloatsOrFlowThreads || blockHasFloatsOrFlowThreads;
43             m_cache = cache;
44             m_cachedLogicalLeftSelectionOffset = false;
45             m_cachedLogicalRightSelectionOffset = false;
46         }
47
48         LayoutUnit logicalLeftSelectionOffset(RenderBlock& rootBlock, LayoutUnit position) const
49         {
50             ASSERT(m_cache);
51             if (m_hasFloatsOrFlowThreads || !m_cachedLogicalLeftSelectionOffset) {
52                 m_cachedLogicalLeftSelectionOffset = true;
53                 m_logicalLeftSelectionOffset = m_block ? m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0);
54             } else
55                 ASSERT(m_logicalLeftSelectionOffset == (m_block ? m_block->logicalLeftSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0)));
56             return m_logicalLeftSelectionOffset;
57         }
58
59         LayoutUnit logicalRightSelectionOffset(RenderBlock& rootBlock, LayoutUnit position) const
60         {
61             ASSERT(m_cache);
62             if (m_hasFloatsOrFlowThreads || !m_cachedLogicalRightSelectionOffset) {
63                 m_cachedLogicalRightSelectionOffset = true;
64                 m_logicalRightSelectionOffset = m_block ? m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0);
65             } else
66                 ASSERT(m_logicalRightSelectionOffset == (m_block ? m_block->logicalRightSelectionOffset(rootBlock, position, *m_cache) : LayoutUnit::fromPixel(0)));
67             return m_logicalRightSelectionOffset;
68         }
69
70         RenderBlock* block() const { return m_block; }
71         const LogicalSelectionOffsetCaches* cache() const { return m_cache; }
72         bool hasFloatsOrFlowThreads() const { return m_hasFloatsOrFlowThreads; }
73
74     private:
75         RenderBlock* m_block { nullptr };
76         const LogicalSelectionOffsetCaches* m_cache { nullptr };
77         bool m_hasFloatsOrFlowThreads : 1;
78         mutable bool m_cachedLogicalLeftSelectionOffset : 1;
79         mutable bool m_cachedLogicalRightSelectionOffset : 1;
80         mutable LayoutUnit m_logicalLeftSelectionOffset;
81         mutable LayoutUnit m_logicalRightSelectionOffset;
82         
83     };
84
85     explicit LogicalSelectionOffsetCaches(RenderBlock& rootBlock)
86     {
87 #if ENABLE(TEXT_SELECTION)
88         // FIXME: We should either move this assertion to the caller (if applicable) or structure the code
89         // such that we can remove this assertion.
90         ASSERT(rootBlock.isSelectionRoot());
91 #endif
92         // LogicalSelectionOffsetCaches should not be used on an orphaned tree.
93         m_containingBlockForFixedPosition.setBlock(rootBlock.containingBlockForFixedPosition(), nullptr);
94         m_containingBlockForAbsolutePosition.setBlock(rootBlock.containingBlockForAbsolutePosition(), nullptr);
95         m_containingBlockForInflowPosition.setBlock(rootBlock.containingBlockForObjectInFlow(), nullptr);
96     }
97
98     LogicalSelectionOffsetCaches(RenderBlock& block, const LogicalSelectionOffsetCaches& cache)
99         : m_containingBlockForFixedPosition(cache.m_containingBlockForFixedPosition)
100         , m_containingBlockForAbsolutePosition(cache.m_containingBlockForAbsolutePosition)
101     {
102         if (block.canContainFixedPositionObjects())
103             m_containingBlockForFixedPosition.setBlock(&block, &cache, cache.m_containingBlockForFixedPosition.hasFloatsOrFlowThreads());
104
105         if (block.canContainAbsolutelyPositionedObjects() && !block.isRenderInline() && !block.isAnonymousBlock())
106             m_containingBlockForAbsolutePosition.setBlock(&block, &cache, cache.m_containingBlockForAbsolutePosition.hasFloatsOrFlowThreads());
107
108         m_containingBlockForInflowPosition.setBlock(&block, &cache, cache.m_containingBlockForInflowPosition.hasFloatsOrFlowThreads());
109     }
110
111     const ContainingBlockInfo& containingBlockInfo(RenderBlock& block) const
112     {
113         EPosition position = block.style().position();
114         if (position == FixedPosition) {
115             ASSERT(block.containingBlock() == m_containingBlockForFixedPosition.block());
116             return m_containingBlockForFixedPosition;
117         }
118         if (position == AbsolutePosition) {
119             ASSERT(block.containingBlock() == m_containingBlockForAbsolutePosition.block());
120             return m_containingBlockForAbsolutePosition;
121         }
122         ASSERT(block.containingBlock() == m_containingBlockForInflowPosition.block());
123         return m_containingBlockForInflowPosition;
124     }
125
126 private:
127     ContainingBlockInfo m_containingBlockForFixedPosition;
128     ContainingBlockInfo m_containingBlockForAbsolutePosition;
129     ContainingBlockInfo m_containingBlockForInflowPosition;
130 };
131
132 } // namespace WebCore
133
134 #endif // LogicalSelectionOffsetCaches_h