Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  StackingContextHelper.cpp   Sprache: C

 
/* -*- 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/. */


#include "mozilla/layers/StackingContextHelper.h"

#include "mozilla/PresShell.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/gfx/Matrix.h"
#include "UnitTransforms.h"
#include "nsDisplayList.h"
#include "mozilla/dom/BrowserChild.h"
#include "nsLayoutUtils.h"
#include "ActiveLayerTracker.h"

namespace mozilla {
namespace layers {
using namespace gfx;

StackingContextHelper::StackingContextHelper()
    : mBuilder(nullptr),
      mScale(1.0f, 1.0f),
      mAffectsClipPositioning(false),
      mDeferredTransformItem(nullptr),
      mRasterizeLocally(false) {
  // mOrigin remains at 0,0
}

static nsSize ComputeDesiredDisplaySizeForAnimation(nsIFrame* aContainerFrame) {
  // Use the size of the nearest widget as the maximum size.  This
  // is important since it might be a popup that is bigger than the
  // pres context's size.
  nsPresContext* presContext = aContainerFrame->PresContext();
  nsIWidget* widget = aContainerFrame->GetNearestWidget();
  if (widget) {
    return LayoutDevicePixel::ToAppUnits(widget->GetClientSize(),
                                         presContext->AppUnitsPerDevPixel());
  }

  return presContext->GetVisibleArea().Size();
}

/* static */
MatrixScales ChooseScale(nsIFrame* aContainerFrame,
                         nsDisplayItem* aContainerItem,
                         const nsRect& aVisibleRect, float aXScale,
                         float aYScale, const Matrix& aTransform2d,
                         bool aCanDraw2D) {
  MatrixScales scale;
  // XXX Should we do something for 3D transforms?
  if (aCanDraw2D && !aContainerFrame->Combines3DTransformWithAncestors() &&
      !aContainerFrame->HasPerspective()) {
    // If the container's transform is animated off main thread, fix a suitable
    // scale size for animation
    if (aContainerItem &&
        aContainerItem->GetType() == DisplayItemType::TYPE_TRANSFORM &&
        // FIXME: What we need is only transform, rotate, and scale, not
        // translate, so it's be better to use a property set, instead of
        // display item type here.
        EffectCompositor::HasAnimationsForCompositor(
            aContainerFrame, DisplayItemType::TYPE_TRANSFORM)) {
      nsSize displaySize =
          ComputeDesiredDisplaySizeForAnimation(aContainerFrame);
      // compute scale using the animation on the container, taking ancestors in
      // to account
      nsSize scaledVisibleSize = nsSize(aVisibleRect.Width() * aXScale,
                                        aVisibleRect.Height() * aYScale);
      scale = nsLayoutUtils::ComputeSuitableScaleForAnimation(
          aContainerFrame, scaledVisibleSize, displaySize);
      // multiply by the scale inherited from ancestors--we use a uniform
      // scale factor to prevent blurring when the layer is rotated.
      float incomingScale = std::max(aXScale, aYScale);
      scale = scale * ScaleFactor<UnknownUnits, UnknownUnits>(incomingScale);
    } else {
      // Scale factors are normalized to a power of 2 to reduce the number of
      // resolution changes
      scale = (aTransform2d * gfx::Matrix::Scaling(aXScale, aYScale))
                  .ScaleFactors();
      // For frames with a changing scale transform round scale factors up to
      // nearest power-of-2 boundary so that we don't keep having to redraw
      // the content as it scales up and down. Rounding up to nearest
      // power-of-2 boundary ensures we never scale up, only down --- avoiding
      // jaggies. It also ensures we never scale down by more than a factor of
      // 2, avoiding bad downscaling quality.
      Matrix frameTransform;
      if (ActiveLayerTracker::IsScaleSubjectToAnimation(aContainerFrame)) {
        scale.xScale = gfxUtils::ClampToScaleFactor(scale.xScale);
        scale.yScale = gfxUtils::ClampToScaleFactor(scale.yScale);

        // Limit animated scale factors to not grow excessively beyond the
        // display size.
        nsSize maxScale(4, 4);
        if (!aVisibleRect.IsEmpty()) {
          nsSize displaySize =
              ComputeDesiredDisplaySizeForAnimation(aContainerFrame);
          maxScale = Max(maxScale, displaySize / aVisibleRect.Size());
        }
        if (scale.xScale > maxScale.width) {
          scale.xScale = gfxUtils::ClampToScaleFactor(maxScale.width, true);
        }
        if (scale.yScale > maxScale.height) {
          scale.yScale = gfxUtils::ClampToScaleFactor(maxScale.height, true);
        }
      } else {
        // XXX Do we need to move nearly-integer values to integers here?
      }
    }
    // If the scale factors are too small, just use 1.0. The content is being
    // scaled out of sight anyway.
    if (fabs(scale.xScale) < 1e-8 || fabs(scale.yScale) < 1e-8) {
      scale = MatrixScales(1.0, 1.0);
    }
  } else {
    scale = MatrixScales(1.0, 1.0);
  }

  // Prevent the scale from getting too large, to avoid excessive memory
  // allocation. Usually memory allocation is limited by the visible region,
  // which should be restricted to the display port. But at very large scales
  // the visible region itself can become excessive due to rounding errors.
  // Clamping the scale here prevents that.
  return MatrixScales(std::min(scale.xScale, 32768.0f),
                      std::min(scale.yScale, 32768.0f));
}

StackingContextHelper::StackingContextHelper(
    const StackingContextHelper& aParentSC, const ActiveScrolledRoot* aAsr,
    nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem,
    wr::DisplayListBuilder& aBuilder, const wr::StackingContextParams& aParams,
    const LayoutDeviceRect& aBounds)
    : mBuilder(&aBuilder),
      mScale(1.0f, 1.0f),
      mDeferredTransformItem(aParams.mDeferredTransformItem),
      mRasterizeLocally(aParams.mRasterizeLocally ||
                        aParentSC.mRasterizeLocally) {
  MOZ_ASSERT(!aContainerItem || aContainerItem->CreatesStackingContextHelper());

  mOrigin = aParentSC.mOrigin + aBounds.TopLeft();
  // Compute scale for fallback rendering. We don't try to guess a scale for 3d
  // transformed items

  if (aParams.mBoundTransform) {
    gfx::Matrix transform2d;
    bool canDraw2D = aParams.mBoundTransform->CanDraw2D(&transform2d);
    if (canDraw2D &&
        aParams.reference_frame_kind != wr::WrReferenceFrameKind::Perspective &&
        !aContainerFrame->Combines3DTransformWithAncestors()) {
      mInheritedTransform = transform2d * aParentSC.mInheritedTransform;

      int32_t apd = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
      nsRect r = LayoutDevicePixel::ToAppUnits(aBounds, apd);
      mScale = ChooseScale(aContainerFrame, aContainerItem, r,
                           aParentSC.mScale.xScale, aParentSC.mScale.yScale,
                           transform2d,
                           /* aCanDraw2D = */ true);
    } else {
      mScale = gfx::MatrixScales(1.0f, 1.0f);
      mInheritedTransform = gfx::Matrix::Scaling(1.f, 1.f);
    }

    if (aParams.mAnimated) {
      mSnappingSurfaceTransform = gfx::Matrix::Scaling(mScale);
    } else {
      mSnappingSurfaceTransform =
          transform2d * aParentSC.mSnappingSurfaceTransform;
    }

  } else if (aParams.reference_frame_kind ==
                 wr::WrReferenceFrameKind::Transform &&
             aContainerItem &&
             aContainerItem->GetType() == DisplayItemType::TYPE_ASYNC_ZOOM &&
             aContainerItem->Frame()) {
    float resolution = aContainerItem->Frame()->PresShell()->GetResolution();
    gfx::Matrix transform = gfx::Matrix::Scaling(resolution, resolution);

    mInheritedTransform = transform * aParentSC.mInheritedTransform;
    mScale =
        ScaleFactor<UnknownUnits, UnknownUnits>(resolution) * aParentSC.mScale;

    MOZ_ASSERT(!aParams.mAnimated);
    mSnappingSurfaceTransform = transform * aParentSC.mSnappingSurfaceTransform;

  } else if (!aAsr && !aContainerFrame && !aContainerItem &&
             aParams.mRootReferenceFrame) {
    // this is the root stacking context helper
    Scale2D resolution;

    // If we are in a remote browser, then apply scaling from ancestor browsers
    if (mozilla::dom::BrowserChild* browserChild =
            mozilla::dom::BrowserChild::GetFrom(
                aParams.mRootReferenceFrame->PresShell())) {
      resolution = browserChild->GetEffectsInfo().mRasterScale;
    }

    gfx::Matrix transform =
        gfx::Matrix::Scaling(resolution.xScale, resolution.yScale);

    mInheritedTransform = transform * aParentSC.mInheritedTransform;
    mScale = aParentSC.mScale * resolution;

    MOZ_ASSERT(!aParams.mAnimated);
    mSnappingSurfaceTransform = transform * aParentSC.mSnappingSurfaceTransform;

  } else {
    mInheritedTransform = aParentSC.mInheritedTransform;
    mScale = aParentSC.mScale;
  }

  auto rasterSpace =
      mRasterizeLocally
          ? wr::RasterSpace::Local(std::max(mScale.xScale, mScale.yScale))
          : wr::RasterSpace::Screen();

  MOZ_ASSERT(!aParams.clip.IsNone());
  mReferenceFrameId = mBuilder->PushStackingContext(
      aParams, wr::ToLayoutRect(aBounds), rasterSpace, nullptr);

  if (mReferenceFrameId) {
    mSpaceAndClipChainHelper.emplace(aBuilder, mReferenceFrameId.ref());
  }

  mAffectsClipPositioning =
      mReferenceFrameId.isSome() || (aBounds.TopLeft() != LayoutDevicePoint());

  // If the parent stacking context has a deferred transform item, inherit it
  // into this stacking context, as long as the ASR hasn't changed. Refer to
  // the comments on StackingContextHelper::mDeferredTransformItem for an
  // explanation of what goes in these fields.
  if (aParentSC.mDeferredTransformItem &&
      aAsr == aParentSC.mDeferredTransformItem->GetActiveScrolledRoot()) {
    if (mDeferredTransformItem) {
      // If we are deferring another transform, put the combined transform from
      // all the ancestor deferred items into mDeferredAncestorTransform
      mDeferredAncestorTransform = aParentSC.GetDeferredTransformMatrix();
    } else {
      // We are not deferring another transform, so we can just inherit the
      // parent stacking context's deferred data without any modification.
      mDeferredTransformItem = aParentSC.mDeferredTransformItem;
      mDeferredAncestorTransform = aParentSC.mDeferredAncestorTransform;
    }
  }
}

StackingContextHelper::~StackingContextHelper() {
  if (mBuilder) {
    mSpaceAndClipChainHelper.reset();
    mBuilder->PopStackingContext(mReferenceFrameId.isSome());
  }
}

nsDisplayTransform* StackingContextHelper::GetDeferredTransformItem() const {
  return mDeferredTransformItem;
}

Maybe<gfx::Matrix4x4> StackingContextHelper::GetDeferredTransformMatrix()
    const {
  if (mDeferredTransformItem) {
    // See the comments on StackingContextHelper::mDeferredTransformItem for
    // an explanation of what's stored in mDeferredTransformItem and
    // mDeferredAncestorTransform. Here we need to return the combined transform
    // transform from all the deferred ancestors, including
    // mDeferredTransformItem.
    gfx::Matrix4x4 result = mDeferredTransformItem->GetTransform().GetMatrix();
    if (mDeferredAncestorTransform) {
      result = result * *mDeferredAncestorTransform;
    }
    return Some(result);
  } else {
    return Nothing();
  }
}

void StackingContextHelper::ClearDeferredTransformItem() const {
  mDeferredTransformItem = nullptr;
}

void StackingContextHelper::RestoreDeferredTransformItem(
    nsDisplayTransform* aItem) const {
  mDeferredTransformItem = aItem;
}

}  // namespace layers
}  // namespace mozilla

Messung V0.5
C=88 H=93 G=90

¤ Dauer der Verarbeitung: 0.28 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge