Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2012 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
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef TextAutosizer_h
     27 #define TextAutosizer_h
     28 
     29 #include "core/HTMLNames.h"
     30 #include "platform/text/WritingMode.h"
     31 #include "wtf/HashMap.h"
     32 #include "wtf/Noncopyable.h"
     33 #include "wtf/OwnPtr.h"
     34 #include "wtf/PassOwnPtr.h"
     35 
     36 namespace WebCore {
     37 
     38 class Document;
     39 class RenderBlock;
     40 class RenderObject;
     41 struct TextAutosizingWindowInfo;
     42 
     43 // Represents cluster related data. Instances should not persist between calls to processSubtree.
     44 struct TextAutosizingClusterInfo {
     45     explicit TextAutosizingClusterInfo(RenderBlock* root)
     46         : root(root)
     47         , blockContainingAllText(0)
     48         , maxAllowedDifferenceFromTextWidth(150)
     49     {
     50     }
     51 
     52     RenderBlock* root;
     53     const RenderBlock* blockContainingAllText;
     54 
     55     // Upper limit on the difference between the width of the cluster's block containing all
     56     // text and that of a narrow child before the child becomes a separate cluster.
     57     float maxAllowedDifferenceFromTextWidth;
     58 
     59     // Descendants of the cluster that are narrower than the block containing all text and must be
     60     // processed together.
     61     Vector<TextAutosizingClusterInfo> narrowDescendants;
     62 };
     63 
     64 class TextAutosizer FINAL {
     65     WTF_MAKE_NONCOPYABLE(TextAutosizer);
     66 
     67 public:
     68     static PassOwnPtr<TextAutosizer> create(Document* document) { return adoptPtr(new TextAutosizer(document)); }
     69 
     70     bool processSubtree(RenderObject* layoutRoot);
     71     void recalculateMultipliers();
     72 
     73     static float computeAutosizedFontSize(float specifiedSize, float multiplier);
     74 
     75 private:
     76     friend class FastTextAutosizer;
     77 
     78     enum TraversalDirection {
     79         FirstToLast,
     80         LastToFirst
     81     };
     82 
     83     explicit TextAutosizer(Document*);
     84 
     85     bool isApplicable() const;
     86     float clusterMultiplier(WritingMode, const TextAutosizingWindowInfo&, float textWidth) const;
     87 
     88     void processClusterInternal(TextAutosizingClusterInfo&, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&, float multiplier);
     89     void processCluster(TextAutosizingClusterInfo&, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&);
     90     void processCompositeCluster(Vector<TextAutosizingClusterInfo>&, const TextAutosizingWindowInfo&);
     91     void processContainer(float multiplier, RenderBlock* container, TextAutosizingClusterInfo&, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&);
     92 
     93     void setMultiplier(RenderObject*, float);
     94     void setMultiplierForList(RenderObject* renderer, float multiplier);
     95 
     96     unsigned getCachedHash(const RenderObject* renderer, bool putInCacheIfAbsent);
     97 
     98     static bool isAutosizingContainer(const RenderObject*);
     99     static bool isNarrowDescendant(const RenderBlock*, TextAutosizingClusterInfo& parentClusterInfo);
    100     static bool isWiderDescendant(const RenderBlock*, const TextAutosizingClusterInfo& parentClusterInfo);
    101     static bool isIndependentDescendant(const RenderBlock*);
    102     static bool isAutosizingCluster(const RenderBlock*, TextAutosizingClusterInfo& parentClusterInfo);
    103 
    104     static bool containerShouldBeAutosized(const RenderBlock* container);
    105     static bool containerContainsOneOfTags(const RenderBlock* cluster, const Vector<QualifiedName>& tags);
    106     static bool containerIsRowOfLinks(const RenderObject* container);
    107     static bool contentHeightIsConstrained(const RenderBlock* container);
    108     static bool compositeClusterShouldBeAutosized(Vector<TextAutosizingClusterInfo>&, float blockWidth);
    109     static void measureDescendantTextWidth(const RenderBlock* container, TextAutosizingClusterInfo&, float minTextWidth, float& textWidth);
    110     unsigned computeCompositeClusterHash(Vector<TextAutosizingClusterInfo>&);
    111     float computeMultiplier(Vector<TextAutosizingClusterInfo>&, const TextAutosizingWindowInfo&, float textWidth);
    112 
    113     // Use to traverse the tree of descendants, excluding descendants of containers (but returning the containers themselves).
    114     static RenderObject* nextInPreOrderSkippingDescendantsOfContainers(const RenderObject*, const RenderObject* stayWithin);
    115 
    116     static const RenderBlock* findDeepestBlockContainingAllText(const RenderBlock* cluster);
    117 
    118     // Depending on the traversal direction specified, finds the first or the last leaf text node child that doesn't
    119     // belong to any cluster.
    120     static const RenderObject* findFirstTextLeafNotInCluster(const RenderObject*, size_t& depth, TraversalDirection);
    121 
    122     // Returns groups of narrow descendants of a given autosizing cluster. The groups are combined
    123     // by the difference between the width of the descendant and the width of the parent cluster's
    124     // |blockContainingAllText|.
    125     static void getNarrowDescendantsGroupedByWidth(const TextAutosizingClusterInfo& parentClusterInfo, Vector<Vector<TextAutosizingClusterInfo> >&);
    126 
    127     void addNonAutosizedCluster(unsigned key, TextAutosizingClusterInfo& value);
    128     void secondPassProcessStaleNonAutosizedClusters();
    129     void processStaleContainer(float multiplier, RenderBlock* cluster, TextAutosizingClusterInfo&);
    130 
    131     Document* m_document;
    132 
    133     HashMap<const RenderObject*, unsigned> m_hashCache;
    134 
    135     // Mapping from all autosized (i.e. multiplier > 1) cluster hashes to their respective multipliers.
    136     HashMap<unsigned, float> m_hashToMultiplier;
    137     Vector<unsigned> m_hashesToAutosizeSecondPass;
    138 
    139     // Mapping from a cluster hash to the corresponding cluster infos which have not been autosized yet.
    140     HashMap<unsigned, OwnPtr<Vector<TextAutosizingClusterInfo> > > m_nonAutosizedClusters;
    141 
    142     bool m_previouslyAutosized;
    143 };
    144 
    145 } // namespace WebCore
    146 
    147 #endif // TextAutosizer_h
    148