| Index: third_party/WebKit/Source/core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h
|
| diff --git a/third_party/WebKit/Source/core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h b/third_party/WebKit/Source/core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..711bd68ba5e372168c2a953a14bc57bac4f20224
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h
|
| @@ -0,0 +1,181 @@
|
| +// Copyright 2017 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 FindPaintOffsetAndVisualRectNeedingUpdate_h
|
| +#define FindPaintOffsetAndVisualRectNeedingUpdate_h
|
| +
|
| +#if DCHECK_IS_ON()
|
| +
|
| +#include "core/layout/LayoutObject.h"
|
| +#include "core/paint/FindPropertiesNeedingUpdate.h"
|
| +#include "core/paint/ObjectPaintInvalidator.h"
|
| +#include "core/paint/PaintInvalidator.h"
|
| +#include "core/paint/PaintLayer.h"
|
| +#include "core/paint/PaintPropertyTreeBuilder.h"
|
| +
|
| +namespace blink {
|
| +
|
| +// This file contains scope classes for catching cases where paint offset or
|
| +// visual rect needed an update but were not marked as such. If paint offset or
|
| +// any visual rect (including visual rect of the object itself, scroll controls,
|
| +// caret, selection, etc.) will change, the object must be marked as such by
|
| +// LayoutObject::setNeedsPaintOffsetAndVisualRectUpdate() (which is a private
|
| +// function called by several public paint-invalidation-flag setting functions).
|
| +
|
| +class FindPaintOffsetNeedingUpdateScope {
|
| + public:
|
| + FindPaintOffsetNeedingUpdateScope(
|
| + const LayoutObject& object,
|
| + const PaintPropertyTreeBuilderContext& context)
|
| + : m_object(object),
|
| + m_context(context),
|
| + m_oldPaintOffset(object.paintOffset()) {
|
| + if (object.paintProperties() &&
|
| + object.paintProperties()->paintOffsetTranslation()) {
|
| + m_oldPaintOffsetTranslation =
|
| + object.paintProperties()->paintOffsetTranslation()->clone();
|
| + }
|
| + }
|
| +
|
| + ~FindPaintOffsetNeedingUpdateScope() {
|
| + if (m_context.isActuallyNeeded)
|
| + return;
|
| + DCHECK_OBJECT_PROPERTY_EQ(m_object, &m_oldPaintOffset,
|
| + &m_object.paintOffset());
|
| + const auto* paintOffsetTranslation =
|
| + m_object.paintProperties()
|
| + ? m_object.paintProperties()->paintOffsetTranslation()
|
| + : nullptr;
|
| + DCHECK_OBJECT_PROPERTY_EQ(m_object, m_oldPaintOffsetTranslation.get(),
|
| + paintOffsetTranslation);
|
| + }
|
| +
|
| + private:
|
| + const LayoutObject& m_object;
|
| + const PaintPropertyTreeBuilderContext& m_context;
|
| + LayoutPoint m_oldPaintOffset;
|
| + RefPtr<const TransformPaintPropertyNode> m_oldPaintOffsetTranslation;
|
| +};
|
| +
|
| +class FindVisualRectNeedingUpdateScopeBase {
|
| + protected:
|
| + FindVisualRectNeedingUpdateScopeBase(const LayoutObject& object,
|
| + const PaintInvalidatorContext& context,
|
| + const LayoutRect& oldVisualRect)
|
| + : m_object(object),
|
| + m_context(context),
|
| + m_oldVisualRect(oldVisualRect),
|
| + m_neededVisualRectUpdate(context.needsVisualRectUpdate(object)) {
|
| + if (m_neededVisualRectUpdate) {
|
| + DCHECK(!RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() ||
|
| + (context.m_treeBuilderContext &&
|
| + context.m_treeBuilderContext->isActuallyNeeded));
|
| + return;
|
| + }
|
| + context.m_forceVisualRectUpdateForChecking = true;
|
| + DCHECK(context.needsVisualRectUpdate(object));
|
| + }
|
| +
|
| + ~FindVisualRectNeedingUpdateScopeBase() {
|
| + m_context.m_forceVisualRectUpdateForChecking = false;
|
| + DCHECK_EQ(m_neededVisualRectUpdate,
|
| + m_context.needsVisualRectUpdate(m_object));
|
| + }
|
| +
|
| + static LayoutRect inflatedRect(const LayoutRect& r) {
|
| + LayoutRect result = r;
|
| + result.inflate(1);
|
| + return result;
|
| + }
|
| +
|
| + void checkVisualRect(const LayoutRect& newVisualRect) {
|
| + if (m_neededVisualRectUpdate)
|
| + return;
|
| + DCHECK((m_oldVisualRect.isEmpty() && newVisualRect.isEmpty()) ||
|
| + m_object.enclosingLayer()->subtreeIsInvisible() ||
|
| + m_oldVisualRect == newVisualRect ||
|
| + // The following check is to tolerate the differences caused by
|
| + // pixel snapping that may happen for one rect but not for another
|
| + // while we need neither paint invalidation nor raster invalidation
|
| + // for the change. This may miss some real subpixel changes of visual
|
| + // rects. TODO(wangxianzhu): Look into whether we can tighten this
|
| + // for SPv2.
|
| + inflatedRect(m_oldVisualRect).contains(newVisualRect) ||
|
| + inflatedRect(newVisualRect).contains(m_oldVisualRect))
|
| + << "Visual rect changed without needing update"
|
| + << " object=" << m_object.debugName()
|
| + << " old=" << m_oldVisualRect.toString()
|
| + << " new=" << newVisualRect.toString();
|
| + }
|
| +
|
| + const LayoutObject& m_object;
|
| + const PaintInvalidatorContext& m_context;
|
| + LayoutRect m_oldVisualRect;
|
| + bool m_neededVisualRectUpdate;
|
| +};
|
| +
|
| +// For updates of visual rects (e.g. of scroll controls, caret, selection,etc.)
|
| +// contained by an object.
|
| +class FindVisualRectNeedingUpdateScope : FindVisualRectNeedingUpdateScopeBase {
|
| + public:
|
| + FindVisualRectNeedingUpdateScope(const LayoutObject& object,
|
| + const PaintInvalidatorContext& context,
|
| + const LayoutRect& oldVisualRect,
|
| + // Must be a reference to a rect that
|
| + // outlives this scope.
|
| + const LayoutRect& newVisualRect)
|
| + : FindVisualRectNeedingUpdateScopeBase(object, context, oldVisualRect),
|
| + m_newVisualRectRef(newVisualRect) {}
|
| +
|
| + ~FindVisualRectNeedingUpdateScope() { checkVisualRect(m_newVisualRectRef); }
|
| +
|
| + private:
|
| + const LayoutRect& m_newVisualRectRef;
|
| +};
|
| +
|
| +// For updates of object visual rect and location.
|
| +class FindObjectVisualRectNeedingUpdateScope
|
| + : FindVisualRectNeedingUpdateScopeBase {
|
| + public:
|
| + FindObjectVisualRectNeedingUpdateScope(const LayoutObject& object,
|
| + const PaintInvalidatorContext& context)
|
| + : FindVisualRectNeedingUpdateScopeBase(object,
|
| + context,
|
| + object.visualRect()),
|
| + m_oldLocation(ObjectPaintInvalidator(object).locationInBacking()) {}
|
| +
|
| + ~FindObjectVisualRectNeedingUpdateScope() {
|
| + checkVisualRect(m_object.visualRect());
|
| + checkLocation();
|
| + }
|
| +
|
| + void checkLocation() {
|
| + if (m_neededVisualRectUpdate)
|
| + return;
|
| + LayoutPoint newLocation =
|
| + ObjectPaintInvalidator(m_object).locationInBacking();
|
| + // Location of LayoutText and non-root SVG is location of the visual rect
|
| + // which have been checked above.
|
| + DCHECK(m_object.isText() || m_object.isSVGChild() ||
|
| + newLocation == m_oldLocation ||
|
| + m_object.enclosingLayer()->subtreeIsInvisible() ||
|
| + // See checkVisualRect for the issue of approximation.
|
| + LayoutRect(-1, -1, 2, 2)
|
| + .contains(LayoutRect(LayoutPoint(newLocation - m_oldLocation),
|
| + LayoutSize())))
|
| + << "Location changed without needing update"
|
| + << " object=" << m_object.debugName()
|
| + << " old=" << m_oldLocation.toString()
|
| + << " new=" << newLocation.toString();
|
| + }
|
| +
|
| + private:
|
| + LayoutPoint m_oldLocation;
|
| +};
|
| +
|
| +} // namespace blink
|
| +
|
| +#endif // DCHECK_IS_ON()
|
| +
|
| +#endif // FindPaintOffsetAndVisualRectNeedingUpdate_h
|
|
|