Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / TextAutosizer.h
1 /*
2  * Copyright (C) 2013 Google Inc. 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 are
6  * met:
7  *
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
13  * distribution.
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.
17  *
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.
29  */
30
31 #ifndef TextAutosizer_h
32 #define TextAutosizer_h
33
34 #include "core/rendering/RenderObject.h"
35 #include "core/rendering/RenderTable.h"
36 #include "platform/heap/Handle.h"
37 #include "wtf/HashMap.h"
38 #include "wtf/HashSet.h"
39 #include "wtf/Noncopyable.h"
40 #include "wtf/OwnPtr.h"
41 #include "wtf/PassOwnPtr.h"
42
43 namespace blink {
44
45 class Document;
46 class RenderBlock;
47 class RenderListItem;
48 class RenderListMarker;
49
50 // Single-pass text autosizer. Documentation at:
51 // http://tinyurl.com/TextAutosizer
52
53 class TextAutosizer FINAL : public NoBaseWillBeGarbageCollectedFinalized<TextAutosizer> {
54     WTF_MAKE_NONCOPYABLE(TextAutosizer);
55 public:
56     static PassOwnPtrWillBeRawPtr<TextAutosizer> create(const Document* document)
57     {
58         return adoptPtrWillBeNoop(new TextAutosizer(document));
59     }
60     static float computeAutosizedFontSize(float specifiedSize, float multiplier);
61
62     void updatePageInfoInAllFrames();
63     void updatePageInfo();
64     void record(const RenderBlock*);
65     void destroy(const RenderBlock*);
66     void inflateListItem(RenderListItem*, RenderListMarker*);
67
68     void trace(Visitor*);
69
70     class LayoutScope {
71     public:
72         explicit LayoutScope(RenderBlock*);
73         ~LayoutScope();
74     protected:
75         TextAutosizer* m_textAutosizer;
76         RenderBlock* m_block;
77     };
78
79     class TableLayoutScope : LayoutScope {
80     public:
81         explicit TableLayoutScope(RenderTable*);
82     };
83
84     class DeferUpdatePageInfo {
85         STACK_ALLOCATED();
86     public:
87         explicit DeferUpdatePageInfo(Page*);
88         ~DeferUpdatePageInfo();
89     private:
90         RefPtrWillBeMember<LocalFrame> m_mainFrame;
91     };
92
93 private:
94     typedef HashSet<const RenderBlock*> BlockSet;
95
96     enum HasEnoughTextToAutosize {
97         UnknownAmountOfText,
98         HasEnoughText,
99         NotEnoughText
100     };
101
102     enum RelayoutBehavior {
103         AlreadyInLayout, // The default; appropriate if we are already in layout.
104         LayoutNeeded // Use this if changing a multiplier outside of layout.
105     };
106
107     enum BeginLayoutBehavior {
108         StopLayout,
109         ContinueLayout
110     };
111
112     enum InflateBehavior {
113         ThisBlockOnly,
114         DescendToInnerBlocks
115     };
116
117     enum BlockFlag {
118         // A block that is evaluated for becoming a cluster root.
119         POTENTIAL_ROOT = 1 << 0,
120         // A cluster root that establishes an independent multiplier.
121         INDEPENDENT = 1 << 1,
122         // A cluster root with an explicit width. These are likely to be independent.
123         EXPLICIT_WIDTH = 1 << 2,
124         // A cluster that is wider or narrower than its parent. These also create an
125         // independent multiplier, but this state cannot be determined until layout.
126         WIDER_OR_NARROWER = 1 << 3,
127         // A cluster that suppresses autosizing.
128         SUPPRESSING = 1 << 4
129     };
130
131     typedef unsigned BlockFlags;
132
133     // A supercluster represents autosizing information about a set of two or
134     // more blocks that all have the same fingerprint. Clusters whose roots
135     // belong to a supercluster will share a common multiplier and
136     // text-length-based autosizing status.
137     struct Supercluster {
138         explicit Supercluster(const BlockSet* roots)
139             : m_roots(roots)
140             , m_hasEnoughTextToAutosize(UnknownAmountOfText)
141             , m_multiplier(0)
142         {
143         }
144
145         const BlockSet* const m_roots;
146         HasEnoughTextToAutosize m_hasEnoughTextToAutosize;
147         float m_multiplier;
148     };
149
150     struct Cluster {
151         explicit Cluster(const RenderBlock* root, BlockFlags flags, Cluster* parent, Supercluster* supercluster = 0)
152             : m_root(root)
153             , m_flags(flags)
154             , m_deepestBlockContainingAllText(0)
155             , m_parent(parent)
156             , m_multiplier(0)
157             , m_hasEnoughTextToAutosize(UnknownAmountOfText)
158             , m_supercluster(supercluster)
159             , m_hasTableAncestor(root->isTableCell() || (m_parent && m_parent->m_hasTableAncestor))
160         {
161         }
162
163         const RenderBlock* const m_root;
164         BlockFlags m_flags;
165         // The deepest block containing all text is computed lazily (see:
166         // deepestBlockContainingAllText). A value of 0 indicates the value has not been computed yet.
167         const RenderBlock* m_deepestBlockContainingAllText;
168         Cluster* m_parent;
169         // The multiplier is computed lazily (see: clusterMultiplier) because it must be calculated
170         // after the lowest block containing all text has entered layout (the
171         // m_blocksThatHaveBegunLayout assertions cover this). Note: the multiplier is still
172         // calculated when m_autosize is false because child clusters may depend on this multiplier.
173         float m_multiplier;
174         HasEnoughTextToAutosize m_hasEnoughTextToAutosize;
175         // A set of blocks that are similar to this block.
176         Supercluster* m_supercluster;
177         bool m_hasTableAncestor;
178     };
179
180     enum TextLeafSearch {
181         First,
182         Last
183     };
184
185     struct FingerprintSourceData {
186         FingerprintSourceData()
187             : m_parentHash(0)
188             , m_qualifiedNameHash(0)
189             , m_packedStyleProperties(0)
190             , m_column(0)
191             , m_width(0)
192         {
193         }
194
195         unsigned m_parentHash;
196         unsigned m_qualifiedNameHash;
197         // Style specific selection of signals
198         unsigned m_packedStyleProperties;
199         unsigned m_column;
200         float m_width;
201     };
202     // Ensures efficient hashing using StringHasher.
203     COMPILE_ASSERT(!(sizeof(FingerprintSourceData) % sizeof(UChar)),
204         Sizeof_FingerprintSourceData_must_be_multiple_of_UChar);
205
206     typedef unsigned Fingerprint;
207     typedef HashMap<Fingerprint, OwnPtr<Supercluster> > SuperclusterMap;
208     typedef Vector<OwnPtr<Cluster> > ClusterStack;
209
210     // Fingerprints are computed during style recalc, for (some subset of)
211     // blocks that will become cluster roots.
212     class FingerprintMapper {
213     public:
214         void add(const RenderObject*, Fingerprint);
215         void addTentativeClusterRoot(const RenderBlock*, Fingerprint);
216         // Returns true if any BlockSet was modified or freed by the removal.
217         bool remove(const RenderObject*);
218         Fingerprint get(const RenderObject*);
219         BlockSet* getTentativeClusterRoots(Fingerprint);
220         bool hasFingerprints() const { return !m_fingerprints.isEmpty(); }
221     private:
222         typedef HashMap<const RenderObject*, Fingerprint> FingerprintMap;
223         typedef HashMap<Fingerprint, OwnPtr<BlockSet> > ReverseFingerprintMap;
224
225         FingerprintMap m_fingerprints;
226         ReverseFingerprintMap m_blocksForFingerprint;
227 #if ENABLE(ASSERT)
228         void assertMapsAreConsistent();
229 #endif
230     };
231
232     struct PageInfo {
233         PageInfo()
234             : m_frameWidth(0)
235             , m_layoutWidth(0)
236             , m_baseMultiplier(0)
237             , m_pageNeedsAutosizing(false)
238             , m_hasAutosized(false)
239             , m_settingEnabled(false)
240         {
241         }
242
243         int m_frameWidth; // LocalFrame width in density-independent pixels (DIPs).
244         int m_layoutWidth; // Layout width in CSS pixels.
245         float m_baseMultiplier; // Includes accessibility font scale factor and device scale adjustment.
246         bool m_pageNeedsAutosizing;
247         bool m_hasAutosized;
248         bool m_settingEnabled;
249     };
250
251     explicit TextAutosizer(const Document*);
252
253     void beginLayout(RenderBlock*);
254     void endLayout(RenderBlock*);
255     void inflateAutoTable(RenderTable*);
256     float inflate(RenderObject*, InflateBehavior = ThisBlockOnly, float multiplier = 0);
257     bool shouldHandleLayout() const;
258     void setAllTextNeedsLayout();
259     void resetMultipliers();
260     BeginLayoutBehavior prepareForLayout(const RenderBlock*);
261     void prepareClusterStack(const RenderObject*);
262     bool clusterHasEnoughTextToAutosize(Cluster*, const RenderBlock* widthProvider = 0);
263     bool superclusterHasEnoughTextToAutosize(Supercluster*, const RenderBlock* widthProvider = 0);
264     bool clusterWouldHaveEnoughTextToAutosize(const RenderBlock* root, const RenderBlock* widthProvider = 0);
265     Fingerprint getFingerprint(const RenderObject*);
266     Fingerprint computeFingerprint(const RenderObject*);
267     Cluster* maybeCreateCluster(const RenderBlock*);
268     Supercluster* getSupercluster(const RenderBlock*);
269     float clusterMultiplier(Cluster*);
270     float superclusterMultiplier(Cluster*);
271     // A cluster's width provider is typically the deepest block containing all text.
272     // There are exceptions, such as tables and table cells which use the table itself for width.
273     const RenderBlock* clusterWidthProvider(const RenderBlock*) const;
274     const RenderBlock* maxClusterWidthProvider(const Supercluster*, const RenderBlock* currentRoot) const;
275     // Typically this returns a block's computed width. In the case of tables layout, this
276     // width is not yet known so the fixed width is used if it's available, or the containing
277     // block's width otherwise.
278     float widthFromBlock(const RenderBlock*) const;
279     float multiplierFromBlock(const RenderBlock*);
280     void applyMultiplier(RenderObject*, float, RelayoutBehavior = AlreadyInLayout);
281     bool isWiderOrNarrowerDescendant(Cluster*);
282     Cluster* currentCluster() const;
283     const RenderBlock* deepestBlockContainingAllText(Cluster*);
284     const RenderBlock* deepestBlockContainingAllText(const RenderBlock*) const;
285     // Returns the first text leaf that is in the current cluster. We attempt to not include text
286     // from descendant clusters but because descendant clusters may not exist, this is only an approximation.
287     // The TraversalDirection controls whether we return the first or the last text leaf.
288     const RenderObject* findTextLeaf(const RenderObject*, size_t&, TextLeafSearch) const;
289     BlockFlags classifyBlock(const RenderObject*, BlockFlags mask = UINT_MAX) const;
290 #ifdef AUTOSIZING_DOM_DEBUG_INFO
291     void writeClusterDebugInfo(Cluster*);
292 #endif
293
294     RawPtrWillBeMember<const Document> m_document;
295     const RenderBlock* m_firstBlockToBeginLayout;
296 #if ENABLE(ASSERT)
297     BlockSet m_blocksThatHaveBegunLayout; // Used to ensure we don't compute properties of a block before beginLayout() is called on it.
298 #endif
299
300     // Clusters are created and destroyed during layout. The map key is the
301     // cluster root. Clusters whose roots share the same fingerprint use the
302     // same multiplier.
303     SuperclusterMap m_superclusters;
304     ClusterStack m_clusterStack;
305     FingerprintMapper m_fingerprintMapper;
306     Vector<RefPtr<RenderStyle> > m_stylesRetainedDuringLayout;
307     // FIXME: All frames should share the same m_pageInfo instance.
308     PageInfo m_pageInfo;
309     bool m_updatePageInfoDeferred;
310 };
311
312 } // namespace blink
313
314 #endif // TextAutosizer_h