summaryrefslogtreecommitdiffstats
path: root/layout/painting/TransformClipNode.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/painting/TransformClipNode.h')
-rw-r--r--layout/painting/TransformClipNode.h138
1 files changed, 138 insertions, 0 deletions
diff --git a/layout/painting/TransformClipNode.h b/layout/painting/TransformClipNode.h
new file mode 100644
index 0000000000..a28dc3dbc0
--- /dev/null
+++ b/layout/painting/TransformClipNode.h
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_PAINTING_TRANSFORMCLIPNODE_H
+#define MOZILLA_PAINTING_TRANSFORMCLIPNODE_H
+
+#include "mozilla/gfx/MatrixFwd.h"
+#include "mozilla/gfx/Rect.h"
+#include "mozilla/Maybe.h"
+#include "nsISupports.h"
+#include "nsRegionFwd.h"
+
+namespace mozilla {
+
+/**
+ * TransformClipNode stores a transformation matrix and a post-transform
+ * clip rect.
+ * They can be used to transform and clip a display item inside a flattened
+ * nsDisplayTransform to the coordinate space of that nsDisplayTransform.
+ */
+class TransformClipNode {
+ NS_INLINE_DECL_REFCOUNTING(TransformClipNode);
+
+ public:
+ TransformClipNode(const RefPtr<TransformClipNode>& aParent,
+ const gfx::Matrix4x4Flagged& aTransform,
+ const Maybe<gfx::IntRect>& aClip)
+ : mParent(aParent), mTransform(aTransform), mClip(aClip) {
+ MOZ_COUNT_CTOR(TransformClipNode);
+ }
+
+ /**
+ * Returns the parent node, or nullptr if this is the root node.
+ */
+ const RefPtr<TransformClipNode>& Parent() const { return mParent; }
+
+ /**
+ * Transforms and clips |aRect| up to the root transform node.
+ * |aRect| is expected to be in app units.
+ */
+ nsRect TransformRect(const nsRect& aRect, const int32_t aA2D) const {
+ if (aRect.IsEmpty()) {
+ return aRect;
+ }
+
+ gfx::Rect result(NSAppUnitsToFloatPixels(aRect.x, aA2D),
+ NSAppUnitsToFloatPixels(aRect.y, aA2D),
+ NSAppUnitsToFloatPixels(aRect.width, aA2D),
+ NSAppUnitsToFloatPixels(aRect.height, aA2D));
+ TransformRect(result);
+ return nsRect(NSFloatPixelsToAppUnits(result.x, aA2D),
+ NSFloatPixelsToAppUnits(result.y, aA2D),
+ NSFloatPixelsToAppUnits(result.width, aA2D),
+ NSFloatPixelsToAppUnits(result.height, aA2D));
+ }
+
+ /**
+ * Transforms and clips |aRect| up to the root transform node.
+ * |aRect| is expected to be in integer pixels.
+ */
+ gfx::IntRect TransformRect(const gfx::IntRect& aRect) const {
+ if (aRect.IsEmpty()) {
+ return aRect;
+ }
+
+ gfx::Rect result(IntRectToRect(aRect));
+ TransformRect(result);
+ return RoundedToInt(result);
+ }
+
+ /**
+ * Transforms and clips |aRegion| up to the root transform node.
+ * |aRegion| is expected be in integer pixels.
+ */
+ nsIntRegion TransformRegion(const nsIntRegion& aRegion) {
+ if (aRegion.IsEmpty()) {
+ return aRegion;
+ }
+
+ nsIntRegion result = aRegion;
+
+ const TransformClipNode* node = this;
+ while (node) {
+ const gfx::Matrix4x4Flagged& transform = node->Transform();
+ result = result.Transform(transform.GetMatrix());
+
+ if (node->Clip()) {
+ const gfx::IntRect clipRect = *node->Clip();
+ result.AndWith(clipRect);
+ }
+
+ node = node->Parent();
+ }
+
+ return result;
+ }
+
+ protected:
+ /**
+ * Returns the post-transform clip, if there is one.
+ */
+ const Maybe<gfx::IntRect>& Clip() const { return mClip; }
+
+ /**
+ * Returns the matrix that transforms the item bounds to the coordinate space
+ * of the flattened nsDisplayTransform.
+ */
+ const gfx::Matrix4x4Flagged& Transform() const { return mTransform; }
+
+ void TransformRect(gfx::Rect& aRect) const {
+ const TransformClipNode* node = this;
+ while (node) {
+ const gfx::Matrix4x4Flagged& transform = node->Transform();
+ gfx::Rect maxBounds = gfx::Rect::MaxIntRect();
+
+ if (node->Clip()) {
+ maxBounds = IntRectToRect(*node->Clip());
+ }
+
+ aRect = transform.TransformAndClipBounds(aRect, maxBounds);
+ node = node->Parent();
+ }
+ }
+
+ private:
+ MOZ_COUNTED_DTOR(TransformClipNode)
+
+ const RefPtr<TransformClipNode> mParent;
+ const gfx::Matrix4x4Flagged mTransform;
+ const Maybe<gfx::IntRect> mClip;
+};
+
+} // namespace mozilla
+
+#endif /* MOZILLA_PAINTING_TRANSFORMCLIPNODE_H */