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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PaintInvalidationState_h
#define PaintInvalidationState_h
#include "core/CoreExport.h"
#include "core/paint/PaintInvalidator.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/graphics/PaintInvalidationReason.h"
#include "platform/transforms/AffineTransform.h"
#include "wtf/Allocator.h"
#include "wtf/Noncopyable.h"
namespace blink {
class LayoutBoxModelObject;
class LayoutObject;
class LayoutView;
class PaintLayer;
enum VisualRectFlags { DefaultVisualRectFlags = 0, EdgeInclusive = 1 };
// PaintInvalidationState is an optimization used during the paint
// invalidation phase.
//
// This class is extremely close to LayoutState so see the documentation
// of LayoutState for the class existence and performance benefits.
//
// The main difference with LayoutState is that it was customized for the
// needs of the paint invalidation systems (keeping visual rectangles
// instead of layout specific information).
//
// See Source/core/paint/README.md#Paint-invalidation for more details.
class CORE_EXPORT PaintInvalidationState {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
WTF_MAKE_NONCOPYABLE(PaintInvalidationState);
public:
PaintInvalidationState(const PaintInvalidationState& parentState,
const LayoutObject&);
// For root LayoutView, or when sub-frame LayoutView's
// invalidateTreeIfNeeded() is called directly from
// FrameView::invalidateTreeIfNeededRecursive() instead of the owner
// LayoutPart.
// TODO(wangxianzhu): Eliminate the latter case.
PaintInvalidationState(
const LayoutView&,
Vector<const LayoutObject*>& pendingDelayedPaintInvalidations);
// When a PaintInvalidationState is constructed, it can be used to map
// points/rects in the object's local space (border box space for
// LayoutBoxes). After invalidation of the current object, before invalidation
// of the subtrees, this method must be called to apply clip and scroll offset
// etc. for creating child PaintInvalidationStates.
void updateForChildren(PaintInvalidationReason);
bool hasForcedSubtreeInvalidationFlags() const {
return m_forcedSubtreeInvalidationFlags;
}
bool forcedSubtreeInvalidationCheckingWithinContainer() const {
return m_forcedSubtreeInvalidationFlags &
PaintInvalidatorContext::ForcedSubtreeInvalidationChecking;
}
void setForceSubtreeInvalidationCheckingWithinContainer() {
m_forcedSubtreeInvalidationFlags |=
PaintInvalidatorContext::ForcedSubtreeInvalidationChecking;
}
bool forcedSubtreeFullInvalidationWithinContainer() const {
return m_forcedSubtreeInvalidationFlags &
PaintInvalidatorContext::ForcedSubtreeFullInvalidation;
}
bool forcedSubtreeInvalidationRectUpdateWithinContainerOnly() const {
return m_forcedSubtreeInvalidationFlags ==
PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate;
}
void setForceSubtreeInvalidationRectUpdateWithinContainer() {
m_forcedSubtreeInvalidationFlags |=
PaintInvalidatorContext::ForcedSubtreeInvalidationRectUpdate;
}
const LayoutBoxModelObject& paintInvalidationContainer() const {
return *m_paintInvalidationContainer;
}
// Computes the location of the current object ((0,0) in the space of the
// object) in the space of paint invalidation backing.
LayoutPoint computeLocationInBacking(
const LayoutPoint& visualRectLocation) const;
// Returns the rect bounds needed to invalidate paint of this object,
// in the space of paint invalidation backing.
LayoutRect computeVisualRectInBacking() const;
void mapLocalRectToPaintInvalidationBacking(LayoutRect&) const;
PaintLayer& paintingLayer() const;
const LayoutObject& currentObject() const { return m_currentObject; }
private:
friend class VisualRectMappingTest;
friend class PaintInvalidatorContextAdapter;
inline PaintLayer& childPaintingLayer(const LayoutObject& child) const;
void mapLocalRectToPaintInvalidationContainer(LayoutRect&) const;
void updateForCurrentObject(const PaintInvalidationState& parentState);
void updateForNormalChildren();
LayoutRect computeVisualRectInBackingForSVG() const;
void addClipRectRelativeToPaintOffset(const LayoutRect& localClipRect);
const LayoutObject& m_currentObject;
unsigned m_forcedSubtreeInvalidationFlags;
bool m_clipped;
bool m_clippedForAbsolutePosition;
// Clip rect from paintInvalidationContainer if m_cachedOffsetsEnabled is
// true.
LayoutRect m_clipRect;
LayoutRect m_clipRectForAbsolutePosition;
// x/y offset from the paintInvalidationContainer if m_cachedOffsetsEnabled is
// true.
// It includes relative positioning and scroll offsets.
LayoutSize m_paintOffset;
LayoutSize m_paintOffsetForAbsolutePosition;
// Whether m_paintOffset[XXX] and m_clipRect[XXX] are valid and can be used
// to map a rect from space of the current object to space of
// paintInvalidationContainer.
bool m_cachedOffsetsEnabled;
bool m_cachedOffsetsForAbsolutePositionEnabled;
// The following two fields are never null. Declare them as pointers because
// we need some logic to initialize them in the body of the constructor.
// The current paint invalidation container for normal flow objects.
// It is the enclosing composited object.
const LayoutBoxModelObject* m_paintInvalidationContainer;
// The current paint invalidation container for stacked contents (stacking
// contexts or positioned objects). It is the nearest ancestor composited
// object which establishes a stacking context. See
// Source/core/paint/README.md ### PaintInvalidationState for details on how
// stacked contents' paint invalidation containers differ.
const LayoutBoxModelObject* m_paintInvalidationContainerForStackedContents;
const LayoutObject& m_containerForAbsolutePosition;
// Transform from the initial viewport coordinate system of an outermost
// SVG root to the userspace _before_ the relevant element. Combining this
// with |m_paintOffset| yields the "final" offset.
AffineTransform m_svgTransform;
// Records objects needing paint invalidation on the next frame. See the
// definition of PaintInvalidationDelayedFull for more details.
Vector<const LayoutObject*>& m_pendingDelayedPaintInvalidations;
PaintLayer& m_paintingLayer;
#if DCHECK_IS_ON()
bool m_didUpdateForChildren = false;
#endif
#if DCHECK_IS_ON() && !defined(NDEBUG)
// #define CHECK_FAST_PATH_SLOW_PATH_EQUALITY
#endif
#ifdef CHECK_FAST_PATH_SLOW_PATH_EQUALITY
void assertFastPathAndSlowPathRectsEqual(
const LayoutRect& fastPathRect,
const LayoutRect& slowPathRect) const;
bool m_canCheckFastPathSlowPathEquality;
#endif
};
// This is temporary to adapt legacy PaintInvalidationState to
// PaintInvalidatorContext
class PaintInvalidatorContextAdapter : public PaintInvalidatorContext {
public:
PaintInvalidatorContextAdapter(const PaintInvalidationState&);
void mapLocalRectToPaintInvalidationBacking(const LayoutObject&,
LayoutRect&) const override;
private:
const PaintInvalidationState& m_paintInvalidationState;
};
} // namespace blink
#endif // PaintInvalidationState_h
|