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


Quelle  ViewTimeline.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 "ViewTimeline.h"

#include "mozilla/dom/Animation.h"
#include "mozilla/dom/ElementInlines.h"
#include "mozilla/ScrollContainerFrame.h"
#include "nsLayoutUtils.h"

namespace mozilla::dom {

NS_IMPL_CYCLE_COLLECTION_INHERITED(ViewTimeline, ScrollTimeline, mSubject)
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(ViewTimeline, ScrollTimeline)

/* static */
already_AddRefed<ViewTimeline> ViewTimeline::MakeNamed(
    Document* aDocument, Element* aSubject,
    const PseudoStyleRequest& aPseudoRequest,
    const StyleViewTimeline& aStyleTimeline) {
  MOZ_ASSERT(NS_IsMainThread());

  // 1. Lookup scroller. We have to find the nearest scroller from |aSubject|
  // and |aPseudoType|.
  auto [element, pseudo] = FindNearestScroller(aSubject, aPseudoRequest);
  auto scroller =
      Scroller::Nearest(const_cast<Element*>(element), pseudo.mType);

  // 2. Create timeline.
  return MakeAndAddRef<ViewTimeline>(
      aDocument, scroller, aStyleTimeline.GetAxis(), aSubject,
      aPseudoRequest.mType, aStyleTimeline.GetInset());
}

/* static */
already_AddRefed<ViewTimeline> ViewTimeline::MakeAnonymous(
    Document* aDocument, const NonOwningAnimationTarget& aTarget,
    StyleScrollAxis aAxis, const StyleViewTimelineInset& aInset) {
  // view() finds the nearest scroll container from the animation target.
  auto [element, pseudo] =
      FindNearestScroller(aTarget.mElement, aTarget.mPseudoRequest);
  Scroller scroller =
      Scroller::Nearest(const_cast<Element*>(element), pseudo.mType);
  return MakeAndAddRef<ViewTimeline>(aDocument, scroller, aAxis,
                                     aTarget.mElement,
                                     aTarget.mPseudoRequest.mType, aInset);
}

void ViewTimeline::ReplacePropertiesWith(
    Element* aSubjectElement, const PseudoStyleRequest& aPseudoRequest,
    const StyleViewTimeline& aNew) {
  mSubject = aSubjectElement;
  mSubjectPseudoType = aPseudoRequest.mType;
  mAxis = aNew.GetAxis();
  // FIXME: Bug 1817073. We assume it is a non-animatable value for now.
  mInset = aNew.GetInset();

  for (auto* anim = mAnimationOrder.getFirst(); anim;
       anim = static_cast<LinkedListElement<Animation>*>(anim)->getNext()) {
    MOZ_ASSERT(anim->GetTimeline() == this);
    // Set this so we just PostUpdate() for this animation.
    anim->SetTimeline(this);
  }
}

Maybe<ScrollTimeline::ScrollOffsets> ViewTimeline::ComputeOffsets(
    const ScrollContainerFrame* aScrollContainerFrame,
    layers::ScrollDirection aOrientation) const {
  MOZ_ASSERT(mSubject);
  MOZ_ASSERT(aScrollContainerFrame);

  const Element* subjectElement =
      mSubject->GetPseudoElement(PseudoStyleRequest(mSubjectPseudoType));
  const nsIFrame* subject = subjectElement->GetPrimaryFrame();
  if (!subject) {
    // No principal box of the subject, so we cannot compute the offset. This
    // may happen when we clear all animation collections during unbinding from
    // the tree.
    return Nothing();
  }

  // In order to get the distance between the subject and the scrollport
  // properly, we use the position based on the domain of the scrolled frame,
  // instead of the scroll container frame.
  const nsIFrame* scrolledFrame = aScrollContainerFrame->GetScrolledFrame();
  MOZ_ASSERT(scrolledFrame);
  const nsRect subjectRect(subject->GetOffsetTo(scrolledFrame),
                           subject->GetSize());

  // Use scrollport size (i.e. padding box size - scrollbar size), which is used
  // for calculating the view progress visibility range.
  // https://drafts.csswg.org/scroll-animations/#view-progress-visibility-range
  const nsRect scrollPort = aScrollContainerFrame->GetScrollPortRect();

  // Adjuct the positions and sizes based on the physical axis.
  nscoord subjectPosition = subjectRect.y;
  nscoord subjectSize = subjectRect.height;
  nscoord scrollPortSize = scrollPort.height;
  if (aOrientation == layers::ScrollDirection::eHorizontal) {
    // |subjectPosition| should be the position of the start border edge of the
    // subject, so for R-L case, we have to use XMost() as the start border
    // edge of the subject, and compute its position by using the x-most side of
    // the scrolled frame as the origin on the horizontal axis.
    subjectPosition = scrolledFrame->GetWritingMode().IsPhysicalRTL()
                          ? scrolledFrame->GetSize().width - subjectRect.XMost()
                          : subjectRect.x;
    subjectSize = subjectRect.width;
    scrollPortSize = scrollPort.width;
  }

  // |sideInsets.mEnd| is used to adjust the start offset, and
  // |sideInsets.mStart| is used to adjust the end offset. This is because
  // |sideInsets.mStart| refers to logical start side [1] of the source box
  // (i.e. the box of the scrollport), where as |startOffset| refers to the
  // start of the timeline, and similarly for end side/offset. [1]
  // https://drafts.csswg.org/css-writing-modes-4/#css-start
  const auto sideInsets = ComputeInsets(aScrollContainerFrame, aOrientation);

  // Basically, we are computing the "cover" timeline range name, which
  // represents the full range of the view progress timeline.
  // https://drafts.csswg.org/scroll-animations-1/#valdef-animation-timeline-range-cover

  // Note: `subjectPosition - scrollPortSize` means the distance between the
  // start border edge of the subject and the end edge of the scrollport.
  nscoord startOffset = subjectPosition - scrollPortSize + sideInsets.mEnd;
  // Note: `subjectPosition + subjectSize` means the position of the end border
  // edge of the subject. When it touches the start edge of the scrollport, it
  // is 100%.
  nscoord endOffset = subjectPosition + subjectSize - sideInsets.mStart;
  return Some(ScrollOffsets{startOffset, endOffset});
}

ScrollTimeline::ScrollOffsets ViewTimeline::ComputeInsets(
    const ScrollContainerFrame* aScrollContainerFrame,
    layers::ScrollDirection aOrientation) const {
  // If view-timeline-inset is auto, it indicates to use the value of
  // scroll-padding. We use logical dimension to map that start/end offset to
  // the corresponding scroll-padding-{inline|block}-{start|end} values.
  const WritingMode wm =
      aScrollContainerFrame->GetScrolledFrame()->GetWritingMode();
  const auto& scrollPadding =
      LogicalMargin(wm, aScrollContainerFrame->GetScrollPadding());
  const bool isBlockAxis = mAxis == StyleScrollAxis::Block ||
                           (mAxis == StyleScrollAxis::X && wm.IsVertical()) ||
                           (mAxis == StyleScrollAxis::Y && !wm.IsVertical());

  // The percentages of view-timelne-inset is relative to the corresponding
  // dimension of the relevant scrollport.
  // https://drafts.csswg.org/scroll-animations-1/#view-timeline-inset
  const nsRect scrollPort = aScrollContainerFrame->GetScrollPortRect();
  const nscoord percentageBasis =
      aOrientation == layers::ScrollDirection::eHorizontal ? scrollPort.width
                                                           : scrollPort.height;

  nscoord startInset =
      mInset.start.IsAuto()
          ? (isBlockAxis ? scrollPadding.BStart(wm) : scrollPadding.IStart(wm))
          : mInset.start.AsLengthPercentage().Resolve(percentageBasis);
  nscoord endInset =
      mInset.end.IsAuto()
          ? (isBlockAxis ? scrollPadding.BEnd(wm) : scrollPadding.IEnd(wm))
          : mInset.end.AsLengthPercentage().Resolve(percentageBasis);
  return {startInset, endInset};
}

}  // namespace mozilla::dom

Messung V0.5
C=88 H=92 G=89

¤ Dauer der Verarbeitung: 0.13 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