diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h')
-rw-r--r-- | chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h | 248 |
1 files changed, 234 insertions, 14 deletions
diff --git a/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h b/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h index 16265fd899a..f3f5efb2eab 100644 --- a/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h +++ b/chromium/third_party/WebKit/Source/core/rendering/FastTextAutosizer.h @@ -31,17 +31,20 @@ #ifndef FastTextAutosizer_h #define FastTextAutosizer_h +#include "core/rendering/RenderObject.h" +#include "core/rendering/RenderTable.h" #include "wtf/HashMap.h" #include "wtf/HashSet.h" #include "wtf/Noncopyable.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" -#include "wtf/text/AtomicStringHash.h" namespace WebCore { class Document; class RenderBlock; +class RenderListItem; +class RenderListMarker; // Single-pass text autosizer (work in progress). Works in two stages: // (1) record information about page elements during style recalc @@ -52,38 +55,255 @@ class FastTextAutosizer FINAL { WTF_MAKE_NONCOPYABLE(FastTextAutosizer); public: - static PassOwnPtr<FastTextAutosizer> create(Document* document) + static PassOwnPtr<FastTextAutosizer> create(const Document* document) { return adoptPtr(new FastTextAutosizer(document)); } + void updatePageInfoInAllFrames(); + void updatePageInfo(); void record(const RenderBlock*); void destroy(const RenderBlock*); - void inflate(RenderBlock*); + void inflateListItem(RenderListItem*, RenderListMarker*); + + class LayoutScope { + public: + explicit LayoutScope(RenderBlock*); + ~LayoutScope(); + protected: + FastTextAutosizer* m_textAutosizer; + RenderBlock* m_block; + }; + + class TableLayoutScope : LayoutScope { + public: + explicit TableLayoutScope(RenderTable*); + }; + + class DeferUpdatePageInfo { + public: + explicit DeferUpdatePageInfo(Page*); + ~DeferUpdatePageInfo(); + private: + RefPtr<LocalFrame> m_mainFrame; + }; private: - // TODO: make a proper API for this class? + typedef HashSet<const RenderBlock*> BlockSet; + + enum HasEnoughTextToAutosize { + UnknownAmountOfText, + HasEnoughText, + NotEnoughText + }; + + enum RelayoutBehavior { + AlreadyInLayout, // The default; appropriate if we are already in layout. + LayoutNeeded // Use this if changing a multiplier outside of layout. + }; + + enum BeginLayoutBehavior { + StopLayout, + ContinueLayout + }; + + enum InflateBehavior { + ThisBlockOnly, + DescendToInnerBlocks + }; + + enum BlockFlag { + // A block that is evaluated for becoming a cluster root. + POTENTIAL_ROOT = 1 << 0, + // A cluster root that establishes an independent multiplier. + INDEPENDENT = 1 << 1, + // A cluster root with an explicit width. These are likely to be independent. + EXPLICIT_WIDTH = 1 << 2, + // A cluster that is wider or narrower than its parent. These also create an + // independent multiplier, but this state cannot be determined until layout. + WIDER_OR_NARROWER = 1 << 3, + // A cluster that suppresses autosizing. + SUPPRESSING = 1 << 4 + }; + + typedef unsigned BlockFlags; + + // A supercluster represents autosizing information about a set of two or + // more blocks that all have the same fingerprint. Clusters whose roots + // belong to a supercluster will share a common multiplier and + // text-length-based autosizing status. + struct Supercluster { + explicit Supercluster(const BlockSet* roots) + : m_roots(roots) + , m_hasEnoughTextToAutosize(UnknownAmountOfText) + , m_multiplier(0) + { + } + + const BlockSet* const m_roots; + HasEnoughTextToAutosize m_hasEnoughTextToAutosize; + float m_multiplier; + }; + struct Cluster { - explicit Cluster(AtomicString fingerprint) - : m_fingerprint(fingerprint) + explicit Cluster(const RenderBlock* root, BlockFlags flags, Cluster* parent, Supercluster* supercluster = 0) + : m_root(root) + , m_flags(flags) + , m_deepestBlockContainingAllText(0) + , m_parent(parent) , m_multiplier(0) + , m_hasEnoughTextToAutosize(UnknownAmountOfText) + , m_supercluster(supercluster) + , m_hasTableAncestor(root->isTableCell() || (m_parent && m_parent->m_hasTableAncestor)) { } - AtomicString m_fingerprint; - WTF::HashSet<const RenderBlock*> m_blocks; + const RenderBlock* const m_root; + BlockFlags m_flags; + // The deepest block containing all text is computed lazily (see: + // deepestBlockContainingAllText). A value of 0 indicates the value has not been computed yet. + const RenderBlock* m_deepestBlockContainingAllText; + Cluster* m_parent; + // The multiplier is computed lazily (see: clusterMultiplier) because it must be calculated + // after the lowest block containing all text has entered layout (the + // m_blocksThatHaveBegunLayout assertions cover this). Note: the multiplier is still + // calculated when m_autosize is false because child clusters may depend on this multiplier. float m_multiplier; + HasEnoughTextToAutosize m_hasEnoughTextToAutosize; + // A set of blocks that are similar to this block. + Supercluster* m_supercluster; + bool m_hasTableAncestor; + }; + + enum TextLeafSearch { + First, + Last + }; + + struct FingerprintSourceData { + FingerprintSourceData() + : m_parentHash(0) + , m_qualifiedNameHash(0) + , m_packedStyleProperties(0) + , m_column(0) + , m_width(0) + { + } + + unsigned m_parentHash; + unsigned m_qualifiedNameHash; + // Style specific selection of signals + unsigned m_packedStyleProperties; + unsigned m_column; + float m_width; + }; + // Ensures efficient hashing using StringHasher. + COMPILE_ASSERT(!(sizeof(FingerprintSourceData) % sizeof(UChar)), + Sizeof_FingerprintSourceData_must_be_multiple_of_UChar); + + typedef unsigned Fingerprint; + typedef HashMap<Fingerprint, OwnPtr<Supercluster> > SuperclusterMap; + typedef Vector<OwnPtr<Cluster> > ClusterStack; + + // Fingerprints are computed during style recalc, for (some subset of) + // blocks that will become cluster roots. + class FingerprintMapper { + public: + void add(const RenderObject*, Fingerprint); + void addTentativeClusterRoot(const RenderBlock*, Fingerprint); + // Returns true if any BlockSet was modified or freed by the removal. + bool remove(const RenderObject*); + Fingerprint get(const RenderObject*); + BlockSet& getTentativeClusterRoots(Fingerprint); + private: + typedef HashMap<const RenderObject*, Fingerprint> FingerprintMap; + typedef HashMap<Fingerprint, OwnPtr<BlockSet> > ReverseFingerprintMap; + + FingerprintMap m_fingerprints; + ReverseFingerprintMap m_blocksForFingerprint; +#ifndef NDEBUG + void assertMapsAreConsistent(); +#endif + }; + + struct PageInfo { + PageInfo() + : m_frameWidth(0) + , m_layoutWidth(0) + , m_baseMultiplier(0) + , m_pageNeedsAutosizing(false) + , m_hasAutosized(false) + , m_settingEnabled(false) + { + } + + int m_frameWidth; // LocalFrame width in density-independent pixels (DIPs). + int m_layoutWidth; // Layout width in CSS pixels. + float m_baseMultiplier; // Includes accessibility font scale factor and device scale adjustment. + bool m_pageNeedsAutosizing; + bool m_hasAutosized; + bool m_settingEnabled; }; - explicit FastTextAutosizer(Document*); + explicit FastTextAutosizer(const Document*); - AtomicString fingerprint(const RenderBlock*); - float computeMultiplier(const Cluster*); + void beginLayout(RenderBlock*); + void endLayout(RenderBlock*); + void inflateAutoTable(RenderTable*); + float inflate(RenderObject*, InflateBehavior = ThisBlockOnly, float multiplier = 0); + bool shouldHandleLayout() const; + void setAllTextNeedsLayout(); + void resetMultipliers(); + BeginLayoutBehavior prepareForLayout(const RenderBlock*); + void prepareClusterStack(const RenderObject*); + bool clusterHasEnoughTextToAutosize(Cluster*, const RenderBlock* widthProvider = 0); + bool superclusterHasEnoughTextToAutosize(Supercluster*, const RenderBlock* widthProvider = 0); + bool clusterWouldHaveEnoughTextToAutosize(const RenderBlock* root, const RenderBlock* widthProvider = 0); + Fingerprint getFingerprint(const RenderObject*); + Fingerprint computeFingerprint(const RenderObject*); + Cluster* maybeCreateCluster(const RenderBlock*); + Supercluster* getSupercluster(const RenderBlock*); + float clusterMultiplier(Cluster*); + float superclusterMultiplier(Cluster*); + // A cluster's width provider is typically the deepest block containing all text. + // There are exceptions, such as tables and table cells which use the table itself for width. + const RenderBlock* clusterWidthProvider(const RenderBlock*); + const RenderBlock* maxClusterWidthProvider(const Supercluster*, const RenderBlock* currentRoot); + // Typically this returns a block's computed width. In the case of tables layout, this + // width is not yet known so the fixed width is used if it's available, or the containing + // block's width otherwise. + float widthFromBlock(const RenderBlock*); + float multiplierFromBlock(const RenderBlock*); + void applyMultiplier(RenderObject*, float, RelayoutBehavior = AlreadyInLayout); + bool isWiderOrNarrowerDescendant(Cluster*); + Cluster* currentCluster() const; + const RenderBlock* deepestBlockContainingAllText(Cluster*); + const RenderBlock* deepestBlockContainingAllText(const RenderBlock*); + // Returns the first text leaf that is in the current cluster. We attempt to not include text + // from descendant clusters but because descendant clusters may not exist, this is only an approximation. + // The TraversalDirection controls whether we return the first or the last text leaf. + const RenderObject* findTextLeaf(const RenderObject*, size_t&, TextLeafSearch); + BlockFlags classifyBlock(const RenderObject*, BlockFlags mask = UINT_MAX); +#ifdef AUTOSIZING_DOM_DEBUG_INFO + void writeClusterDebugInfo(Cluster*); +#endif - Document* m_document; + const Document* m_document; + const RenderBlock* m_firstBlockToBeginLayout; +#ifndef NDEBUG + BlockSet m_blocksThatHaveBegunLayout; // Used to ensure we don't compute properties of a block before beginLayout() is called on it. +#endif - WTF::HashMap<const RenderBlock*, Cluster*> m_clusterForBlock; - WTF::HashMap<AtomicString, OwnPtr<Cluster> > m_clusterForFingerprint; + // Clusters are created and destroyed during layout. The map key is the + // cluster root. Clusters whose roots share the same fingerprint use the + // same multiplier. + SuperclusterMap m_superclusters; + ClusterStack m_clusterStack; + FingerprintMapper m_fingerprintMapper; + Vector<RefPtr<RenderStyle> > m_stylesRetainedDuringLayout; + // FIXME: All frames should share the same m_pageInfo instance. + PageInfo m_pageInfo; + bool m_updatePageInfoDeferred; }; } // namespace WebCore |