2 * Copyright (C) 2013 Google 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 are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef FastTextAutosizer_h
32 #define FastTextAutosizer_h
34 #include "core/rendering/RenderObject.h"
35 #include "core/rendering/TextAutosizer.h"
36 #include "wtf/HashMap.h"
37 #include "wtf/HashSet.h"
38 #include "wtf/Noncopyable.h"
39 #include "wtf/OwnPtr.h"
40 #include "wtf/PassOwnPtr.h"
41 #include "wtf/text/AtomicStringHash.h"
48 class RenderListMarker;
50 // Single-pass text autosizer (work in progress). Works in two stages:
51 // (1) record information about page elements during style recalc
52 // (2) inflate sizes during layout
53 // See: http://tinyurl.com/chromium-fast-autosizer
55 class FastTextAutosizer FINAL {
56 WTF_MAKE_NONCOPYABLE(FastTextAutosizer);
59 static PassOwnPtr<FastTextAutosizer> create(const Document* document)
61 return adoptPtr(new FastTextAutosizer(document));
64 void record(const RenderBlock*);
65 void destroy(const RenderBlock*);
66 void inflateListItem(RenderListItem*, RenderListMarker*);
70 explicit LayoutScope(Document& document, RenderBlock* block)
73 m_textAutosizer = document.fastTextAutosizer();
74 if (m_textAutosizer) {
75 if (!m_textAutosizer->enabled()) {
80 m_textAutosizer->beginLayout(m_block);
87 m_textAutosizer->endLayout(m_block);
90 FastTextAutosizer* m_textAutosizer;
95 typedef HashSet<const RenderBlock*> BlockSet;
97 // A supercluster represents autosizing information about a set of two or
98 // more blocks that all have the same fingerprint. Clusters whose roots
99 // belong to a supercluster will share a common multiplier and
100 // text-length-based autosizing status.
101 struct Supercluster {
102 explicit Supercluster(const BlockSet* roots)
105 , m_anyClusterHasEnoughText(false)
109 const BlockSet* const m_roots;
111 bool m_anyClusterHasEnoughText;
115 explicit Cluster(const RenderBlock* root, bool autosize, Cluster* parent, Supercluster* supercluster = 0)
117 , m_deepestBlockContainingAllText(0)
119 , m_autosize(autosize)
122 , m_supercluster(supercluster)
126 const RenderBlock* const m_root;
127 // The deepest block containing all text is computed lazily (see:
128 // deepestBlockContainingAllText). A value of 0 indicates the value has not been computed yet.
129 const RenderBlock* m_deepestBlockContainingAllText;
132 // The multiplier is computed lazily (see: clusterMultiplier) because it must be calculated
133 // after the lowest block containing all text has entered layout (the
134 // m_blocksThatHaveBegunLayout assertions cover this). Note: the multiplier is still
135 // calculated when m_autosize is false because child clusters may depend on this multiplier.
137 // Text length is computed lazily (see: textLength). This is an approximation and characters
138 // are assumed to be 1em wide. Negative values indicate the length has not been computed.
140 // A set of blocks that are similar to this block.
141 Supercluster* m_supercluster;
144 enum TextLeafSearch {
149 typedef HashMap<AtomicString, OwnPtr<Supercluster> > SuperclusterMap;
150 typedef Vector<OwnPtr<Cluster> > ClusterStack;
152 // Fingerprints are computed during style recalc, for (some subset of)
153 // blocks that will become cluster roots.
154 class FingerprintMapper {
156 void add(const RenderBlock*, AtomicString);
157 void remove(const RenderBlock*);
158 AtomicString get(const RenderBlock*);
159 BlockSet& getBlocks(AtomicString);
161 typedef HashMap<const RenderBlock*, AtomicString> FingerprintMap;
162 typedef HashMap<AtomicString, OwnPtr<BlockSet> > ReverseFingerprintMap;
164 FingerprintMap m_fingerprints;
165 ReverseFingerprintMap m_blocksForFingerprint;
168 explicit FastTextAutosizer(const Document*);
170 void beginLayout(RenderBlock*);
171 void endLayout(RenderBlock*);
172 void inflate(RenderBlock*);
174 void prepareRenderViewInfo();
175 bool isFingerprintingCandidate(const RenderBlock*);
176 bool clusterHasEnoughTextToAutosize(Cluster*);
177 bool clusterWouldHaveEnoughTextToAutosize(const RenderBlock*);
178 float textLength(Cluster*);
179 AtomicString computeFingerprint(const RenderBlock*);
180 Cluster* maybeCreateCluster(const RenderBlock*);
181 Supercluster* getSupercluster(const RenderBlock*);
182 const RenderBlock* deepestCommonAncestor(BlockSet&);
183 float clusterMultiplier(Cluster*);
184 float superclusterMultiplier(Supercluster*);
185 float multiplierFromBlock(const RenderBlock*);
186 void applyMultiplier(RenderObject*, float);
187 bool mightBeWiderOrNarrowerDescendant(const RenderBlock*);
188 bool isWiderDescendant(Cluster*);
189 bool isNarrowerDescendant(Cluster*);
190 bool isLayoutRoot(const RenderBlock*) const;
192 Cluster* currentCluster() const;
194 RenderObject* nextChildSkippingChildrenOfBlocks(const RenderObject*, const RenderObject*);
196 const RenderBlock* deepestBlockContainingAllText(Cluster*);
197 const RenderBlock* deepestBlockContainingAllText(const RenderBlock*);
198 // Returns the first text leaf that is in the current cluster. We attempt to not include text
199 // from descendant clusters but because descendant clusters may not exist, this is only an approximation.
200 // The TraversalDirection controls whether we return the first or the last text leaf.
201 const RenderObject* findTextLeaf(const RenderObject*, size_t&, TextLeafSearch);
203 const Document* m_document;
204 int m_frameWidth; // Frame width in density-independent pixels (DIPs).
205 int m_layoutWidth; // Layout width in CSS pixels.
206 float m_baseMultiplier; // Includes accessibility font scale factor and device scale adjustment.
208 bool m_renderViewInfoPrepared;
209 BlockSet m_blocksThatHaveBegunLayout; // Used to ensure we don't compute properties of a block before beginLayout() is called on it.
212 // Clusters are created and destroyed during layout. The map key is the
213 // cluster root. Clusters whose roots share the same fingerprint use the
215 SuperclusterMap m_superclusters;
216 ClusterStack m_clusterStack;
217 FingerprintMapper m_fingerprintMapper;
220 } // namespace WebCore
222 #endif // FastTextAutosizer_h