summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/rendering/TextAutosizer.h
blob: aac87074bb4c1f410123a1888767330743a0262a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef TextAutosizer_h
#define TextAutosizer_h

#include "core/HTMLNames.h"
#include "platform/text/WritingMode.h"
#include "wtf/HashMap.h"
#include "wtf/Noncopyable.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"

namespace WebCore {

class Document;
class RenderBlock;
class RenderObject;
struct TextAutosizingWindowInfo;

// Represents cluster related data. Instances should not persist between calls to processSubtree.
struct TextAutosizingClusterInfo {
    explicit TextAutosizingClusterInfo(RenderBlock* root)
        : root(root)
        , blockContainingAllText(0)
        , maxAllowedDifferenceFromTextWidth(150)
    {
    }

    RenderBlock* root;
    const RenderBlock* blockContainingAllText;

    // Upper limit on the difference between the width of the cluster's block containing all
    // text and that of a narrow child before the child becomes a separate cluster.
    float maxAllowedDifferenceFromTextWidth;

    // Descendants of the cluster that are narrower than the block containing all text and must be
    // processed together.
    Vector<TextAutosizingClusterInfo> narrowDescendants;
};

class TextAutosizer FINAL {
    WTF_MAKE_NONCOPYABLE(TextAutosizer);

public:
    static PassOwnPtr<TextAutosizer> create(Document* document) { return adoptPtr(new TextAutosizer(document)); }

    bool processSubtree(RenderObject* layoutRoot);
    void recalculateMultipliers();

    static float computeAutosizedFontSize(float specifiedSize, float multiplier);

private:
    friend class FastTextAutosizer;

    enum TraversalDirection {
        FirstToLast,
        LastToFirst
    };

    explicit TextAutosizer(Document*);

    bool isApplicable() const;
    float clusterMultiplier(WritingMode, const TextAutosizingWindowInfo&, float textWidth) const;

    void processClusterInternal(TextAutosizingClusterInfo&, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&, float multiplier);
    void processCluster(TextAutosizingClusterInfo&, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&);
    void processCompositeCluster(Vector<TextAutosizingClusterInfo>&, const TextAutosizingWindowInfo&);
    void processContainer(float multiplier, RenderBlock* container, TextAutosizingClusterInfo&, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&);

    void setMultiplier(RenderObject*, float);
    void setMultiplierForList(RenderObject* renderer, float multiplier);

    unsigned getCachedHash(const RenderObject* renderer, bool putInCacheIfAbsent);

    static bool isAutosizingContainer(const RenderObject*);
    static bool isNarrowDescendant(const RenderBlock*, TextAutosizingClusterInfo& parentClusterInfo);
    static bool isWiderDescendant(const RenderBlock*, const TextAutosizingClusterInfo& parentClusterInfo);
    static bool isIndependentDescendant(const RenderBlock*);
    static bool isAutosizingCluster(const RenderBlock*, TextAutosizingClusterInfo& parentClusterInfo);

    static bool containerShouldBeAutosized(const RenderBlock* container);
    static bool containerContainsOneOfTags(const RenderBlock* cluster, const Vector<QualifiedName>& tags);
    static bool containerIsRowOfLinks(const RenderObject* container);
    static bool contentHeightIsConstrained(const RenderBlock* container);
    static bool compositeClusterShouldBeAutosized(Vector<TextAutosizingClusterInfo>&, float blockWidth);
    static void measureDescendantTextWidth(const RenderBlock* container, TextAutosizingClusterInfo&, float minTextWidth, float& textWidth);
    unsigned computeCompositeClusterHash(Vector<TextAutosizingClusterInfo>&);
    float computeMultiplier(Vector<TextAutosizingClusterInfo>&, const TextAutosizingWindowInfo&, float textWidth);

    // Use to traverse the tree of descendants, excluding descendants of containers (but returning the containers themselves).
    static RenderObject* nextInPreOrderSkippingDescendantsOfContainers(const RenderObject*, const RenderObject* stayWithin);

    static const RenderBlock* findDeepestBlockContainingAllText(const RenderBlock* cluster);

    // Depending on the traversal direction specified, finds the first or the last leaf text node child that doesn't
    // belong to any cluster.
    static const RenderObject* findFirstTextLeafNotInCluster(const RenderObject*, size_t& depth, TraversalDirection);

    // Returns groups of narrow descendants of a given autosizing cluster. The groups are combined
    // by the difference between the width of the descendant and the width of the parent cluster's
    // |blockContainingAllText|.
    static void getNarrowDescendantsGroupedByWidth(const TextAutosizingClusterInfo& parentClusterInfo, Vector<Vector<TextAutosizingClusterInfo> >&);

    void addNonAutosizedCluster(unsigned key, TextAutosizingClusterInfo& value);
    void secondPassProcessStaleNonAutosizedClusters();
    void processStaleContainer(float multiplier, RenderBlock* cluster, TextAutosizingClusterInfo&);

    Document* m_document;

    HashMap<const RenderObject*, unsigned> m_hashCache;

    // Mapping from all autosized (i.e. multiplier > 1) cluster hashes to their respective multipliers.
    HashMap<unsigned, float> m_hashToMultiplier;
    Vector<unsigned> m_hashesToAutosizeSecondPass;

    // Mapping from a cluster hash to the corresponding cluster infos which have not been autosized yet.
    HashMap<unsigned, OwnPtr<Vector<TextAutosizingClusterInfo> > > m_nonAutosizedClusters;

    bool m_previouslyAutosized;
};

} // namespace WebCore

#endif // TextAutosizer_h