Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1243)

Unified Diff: third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp

Issue 2105273004: GeometryMapper: Support computing visual rects in spaces that are not direct ancestors. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: none Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
index 1f311419bea933c8545bf196c2d112687ca1adbc..71c62456052752bc27cc4494a541cf8483803185 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
@@ -8,41 +8,104 @@
#include "platform/graphics/paint/ClipPaintPropertyNode.h"
#include "platform/graphics/paint/EffectPaintPropertyNode.h"
#include "platform/graphics/paint/TransformPaintPropertyNode.h"
+#include "wtf/HashSet.h"
namespace blink {
-FloatRect GeometryMapper::LocalToVisualRectInAncestorSpace(
+PassRefPtr<TransformPaintPropertyNode> GeometryMapper::leastCommonAncestor(PassRefPtr<TransformPaintPropertyNode> a, PassRefPtr<TransformPaintPropertyNode> b)
+{
+ HashSet<RefPtr<TransformPaintPropertyNode>> intermediates;
pdr. 2016/07/01 18:39:40 We may want to use a lowest common ancestor approa
chrishtr 2016/07/01 22:01:12 Refactored to reuse that code, templated for all p
+ RefPtr<TransformPaintPropertyNode> currA = a;
+ RefPtr<TransformPaintPropertyNode> currB = b;
+ while (currA || currB) {
+ if (currA) {
+ auto it = intermediates.find(currA);
+ if (it != intermediates.end())
+ return *it;
+ intermediates.add(currA);
+ currA = currA->parent();
+ }
+
+ if (currB) {
+ auto it = intermediates.find(currB);
+ if (it != intermediates.end())
+ return *it;
+ intermediates.add(currB);
+ currB = currB->parent();
+ }
+ }
+ CHECK(false);
+ return nullptr;
+}
+
+FloatRect GeometryMapper::mapToVisualRectInDestinationSpace(const FloatRect& rect,
+ const PropertyTreeState& sourceState,
+ const PropertyTreeState& destinationState,
+ bool* success)
+{
+ FloatRect result = localToVisualRectInAncestorSpace(rect, sourceState, destinationState, success);
+ if (*success)
+ return result;
+
+ RefPtr<TransformPaintPropertyNode> lcaTransform = leastCommonAncestor(sourceState.transform.get(), destinationState.transform.get());
+ DCHECK(lcaTransform.get());
+ PropertyTreeState lcaState = sourceState;
+ lcaState.transform = lcaTransform;
+
+ result = localToAncestorMatrix(sourceState.transform.get(), lcaState, success).mapRect(rect);
+ DCHECK(*success);
+
+ const TransformationMatrix& destinationToLca = localToAncestorMatrix(destinationState.transform.get(), lcaState, success);
+ DCHECK(*success);
+ if (destinationToLca.isInvertible()) {
+ *success = true;
+ return destinationToLca.inverse().mapRect(result);
+ }
+ *success = false;
+ return rect;
+}
+
+FloatRect GeometryMapper::localToVisualRectInAncestorSpace(
const FloatRect& rect,
const PropertyTreeState& localState,
- const PropertyTreeState& ancestorState)
+ const PropertyTreeState& ancestorState, bool* success)
{
- const auto transformMatrix = LocalToAncestorMatrix(localState.transform, ancestorState);
+ const auto transformMatrix = localToAncestorMatrix(localState.transform.get(), ancestorState, success);
+ if (!(*success))
+ return rect;
+
FloatRect mappedRect = transformMatrix.mapRect(rect);
- const auto clipRect = LocalToAncestorClipRect(localState, ancestorState);
+ const auto clipRect = localToAncestorClipRect(localState, ancestorState);
mappedRect.intersect(clipRect);
return mappedRect;
}
-FloatRect GeometryMapper::LocalToAncestorRect(
+FloatRect GeometryMapper::localToAncestorRect(
const FloatRect& rect,
const PropertyTreeState& localState,
- const PropertyTreeState& ancestorState)
+ const PropertyTreeState& ancestorState,
+ bool* success)
{
- const auto transformMatrix = LocalToAncestorMatrix(localState.transform, ancestorState);
+ const auto transformMatrix = localToAncestorMatrix(localState.transform.get(), ancestorState, success);
+ if (!(*success))
+ return rect;
return transformMatrix.mapRect(rect);
}
-FloatRect GeometryMapper::AncestorToLocalRect(
+FloatRect GeometryMapper::ancestorToLocalRect(
const FloatRect& rect,
const PropertyTreeState& localState,
const PropertyTreeState& ancestorState, bool* success)
{
- const auto& transformMatrix = LocalToAncestorMatrix(localState.transform, ancestorState);
+ const auto& transformMatrix = localToAncestorMatrix(localState.transform.get(), ancestorState, success);
+ if (!(*success))
+ return rect;
+
if (!transformMatrix.isInvertible()) {
*success = false;
- return FloatRect();
+ return rect;
}
*success = true;
@@ -50,20 +113,20 @@ FloatRect GeometryMapper::AncestorToLocalRect(
return transformMatrix.inverse().mapRect(rect);
}
-PrecomputedDataForAncestor& GeometryMapper::GetPrecomputedDataForAncestor(const PropertyTreeState& ancestorState)
+PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor(const PropertyTreeState& ancestorState)
{
- auto addResult = m_data.add(ancestorState.transform, nullptr);
+ auto addResult = m_data.add(ancestorState.transform.get(), nullptr);
if (addResult.isNewEntry)
addResult.storedValue->value = PrecomputedDataForAncestor::create();
return *addResult.storedValue->value;
}
-const FloatRect& GeometryMapper::LocalToAncestorClipRect(
+const FloatRect& GeometryMapper::localToAncestorClipRect(
const PropertyTreeState& localState,
const PropertyTreeState& ancestorState)
{
- PrecomputedDataForAncestor& precomputedData = GetPrecomputedDataForAncestor(ancestorState);
- const ClipPaintPropertyNode* clipNode = localState.clip;
+ PrecomputedDataForAncestor& precomputedData = getPrecomputedDataForAncestor(ancestorState);
+ const ClipPaintPropertyNode* clipNode = localState.clip.get();
Vector<const ClipPaintPropertyNode*> intermediateNodes;
FloatRect clip(LayoutRect::infiniteIntRect());
@@ -90,7 +153,9 @@ const FloatRect& GeometryMapper::LocalToAncestorClipRect(
// Iterate down from the top intermediate node found in the previous loop, computing and memoizing clip rects as we go.
for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); ++it) {
if ((*it) != ancestorState.clip) {
- const TransformationMatrix transformMatrix = LocalToAncestorMatrix((*it)->localTransformSpace(), ancestorState);
+ bool success = false;
+ const TransformationMatrix transformMatrix = localToAncestorMatrix((*it)->localTransformSpace(), ancestorState, &success);
+ DCHECK(success);
FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect());
clip.intersect(mappedRect);
}
@@ -98,13 +163,13 @@ const FloatRect& GeometryMapper::LocalToAncestorClipRect(
precomputedData.toAncestorClipRects.set(*it, clip);
}
- return precomputedData.toAncestorClipRects.find(localState.clip)->value;
+ return precomputedData.toAncestorClipRects.find(localState.clip.get())->value;
}
-const TransformationMatrix& GeometryMapper::LocalToAncestorMatrix(
+const TransformationMatrix& GeometryMapper::localToAncestorMatrix(
const TransformPaintPropertyNode* localTransformNode,
- const PropertyTreeState& ancestorState) {
- PrecomputedDataForAncestor& precomputedData = GetPrecomputedDataForAncestor(ancestorState);
+ const PropertyTreeState& ancestorState, bool* success) {
+ PrecomputedDataForAncestor& precomputedData = getPrecomputedDataForAncestor(ancestorState);
const TransformPaintPropertyNode* transformNode = localTransformNode;
Vector<const TransformPaintPropertyNode*> intermediateNodes;
@@ -128,8 +193,10 @@ const TransformationMatrix& GeometryMapper::LocalToAncestorMatrix(
transformNode = transformNode->parent();
}
- // It's illegal to ask for a local-to-ancestor matrix when the ancestor is not an ancestor.
- DCHECK(transformNode == ancestorState.transform || found);
+ if (!found && transformNode != ancestorState.transform) {
+ *success = false;
+ return m_identity;
pdr. 2016/07/01 18:39:40 Instead of using a member, you can use a static li
chrishtr 2016/07/01 22:01:12 That doesn't work, because it requires a global co
+ }
// Iterate down from the top intermediate node found in the previous loop, computing and memoizing transforms as we go.
for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); it++) {
@@ -141,6 +208,7 @@ const TransformationMatrix& GeometryMapper::LocalToAncestorMatrix(
precomputedData.toAncestorTransforms.set(*it, transformMatrix);
}
+ *success = true;
return precomputedData.toAncestorTransforms.find(localTransformNode)->value;
}

Powered by Google App Engine
This is Rietveld 408576698