layout/painting/TransformClipNode.h
author alwu <alwu@mozilla.com>
Mon, 07 Jan 2019 19:57:48 +0000
changeset 512757 0e229bbdaae5c8fa9f83796c628a4fdf88f057ba
parent 508163 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Bug 1513039 - part5 : log warning when autoplay is blocked. r=cpearce,karlt Wrap 'nsContentUtils::ReportToConsole()' to reduce necessary input parameters and call it when we need to log error or warning message. Show the warning when autoplay is blocked. For web audio, this restores the console messages removed in part4 and also reports the same message when the AudioContext is blocked in the constructor. Differential Revision: https://phabricator.services.mozilla.com/D14330

/* -*- 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:
  ~TransformClipNode() { MOZ_COUNT_DTOR(TransformClipNode); }

  const RefPtr<TransformClipNode> mParent;
  const gfx::Matrix4x4Flagged mTransform;
  const Maybe<gfx::IntRect> mClip;
};

}  // namespace mozilla

#endif /* MOZILLA_PAINTING_TRANSFORMCLIPNODE_H */