summaryrefslogtreecommitdiff
path: root/dom/smil/nsSMILInstanceTime.h
blob: 4602c9127f2b30ee226c6ab51534d885db792bc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* -*- 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 NS_SMILINSTANCETIME_H_
#define NS_SMILINSTANCETIME_H_

#include "nsSMILTimeValue.h"
#include "nsISupports.h"

class nsSMILInterval;
class nsSMILTimeContainer;
class nsSMILTimeValueSpec;

//----------------------------------------------------------------------
// nsSMILInstanceTime
//
// An instant in document simple time that may be used in creating a new
// interval.
//
// For an overview of how this class is related to other SMIL time classes see
// the documentation in nsSMILTimeValue.h
//
// These objects are owned by an nsSMILTimedElement but MAY also be referenced
// by:
//
// a) nsSMILIntervals that belong to the same nsSMILTimedElement and which refer
//    to the nsSMILInstanceTimes which form the interval endpoints; and/or
// b) nsSMILIntervals that belong to other nsSMILTimedElements but which need to
//    update dependent instance times when they change or are deleted.
//    E.g. for begin='a.begin', 'a' needs to inform dependent
//    nsSMILInstanceTimes if its begin time changes. This notification is
//    performed by the nsSMILInterval.

class nsSMILInstanceTime final
{
public:
  // Instance time source. Times generated by events, syncbase relationships,
  // and DOM calls behave differently in some circumstances such as when a timed
  // element is reset.
  enum nsSMILInstanceTimeSource {
    // No particularly significant source, e.g. offset time, 'indefinite'
    SOURCE_NONE,
    // Generated by a DOM call such as beginElement
    SOURCE_DOM,
    // Generated by a syncbase relationship
    SOURCE_SYNCBASE,
    // Generated by an event
    SOURCE_EVENT
  };

  explicit nsSMILInstanceTime(const nsSMILTimeValue& aTime,
                              nsSMILInstanceTimeSource aSource = SOURCE_NONE,
                              nsSMILTimeValueSpec* aCreator = nullptr,
                              nsSMILInterval* aBaseInterval = nullptr);

  void Unlink();
  void HandleChangedInterval(const nsSMILTimeContainer* aSrcContainer,
                             bool aBeginObjectChanged,
                             bool aEndObjectChanged);
  void HandleDeletedInterval();
  void HandleFilteredInterval();

  const nsSMILTimeValue& Time() const { return mTime; }
  const nsSMILTimeValueSpec* GetCreator() const { return mCreator; }

  bool IsDynamic() const { return !!(mFlags & kDynamic); }
  bool IsFixedTime() const { return !(mFlags & kMayUpdate); }
  bool FromDOM() const { return !!(mFlags & kFromDOM); }

  bool ShouldPreserve() const;
  void   UnmarkShouldPreserve();

  void AddRefFixedEndpoint();
  void ReleaseFixedEndpoint();

  void DependentUpdate(const nsSMILTimeValue& aNewTime)
  {
    MOZ_ASSERT(!IsFixedTime(),
               "Updating an instance time that is not expected to be updated");
    mTime = aNewTime;
  }

  bool IsDependent() const { return !!mBaseInterval; }
  bool IsDependentOn(const nsSMILInstanceTime& aOther) const;
  const nsSMILInterval* GetBaseInterval() const { return mBaseInterval; }
  const nsSMILInstanceTime* GetBaseTime() const;

  bool SameTimeAndBase(const nsSMILInstanceTime& aOther) const
  {
    return mTime == aOther.mTime && GetBaseTime() == aOther.GetBaseTime();
  }

  // Get and set a serial number which may be used by a containing class to
  // control the sort order of otherwise similar instance times.
  uint32_t Serial() const { return mSerial; }
  void SetSerial(uint32_t aIndex) { mSerial = aIndex; }

  NS_INLINE_DECL_REFCOUNTING(nsSMILInstanceTime)

private:
  // Private destructor, to discourage deletion outside of Release():
  ~nsSMILInstanceTime();

  void SetBaseInterval(nsSMILInterval* aBaseInterval);

  nsSMILTimeValue mTime;

  // Internal flags used to represent the behaviour of different instance times
  enum {
    // Indicates that this instance time was generated by an event or a DOM
    // call. Such instance times require special handling when (i) the owning
    // element is reset, (ii) when they are to be added as a new end instance
    // times (as per SMIL's event sensitivity contraints), and (iii) when
    // a backwards seek is performed and the timing model is reconstructed.
    kDynamic = 1,

    // Indicates that this instance time is referred to by an
    // nsSMILTimeValueSpec and as such may be updated. Such instance time should
    // not be filtered out by the nsSMILTimedElement even if they appear to be
    // in the past as they may be updated to a future time.
    kMayUpdate = 2,

    // Indicates that this instance time was generated from the DOM as opposed
    // to an nsSMILTimeValueSpec. When a 'begin' or 'end' attribute is set or
    // reset we should clear all the instance times that have been generated by
    // that attribute (and hence an nsSMILTimeValueSpec), but not those from the
    // DOM.
    kFromDOM = 4,

    // Indicates that this instance time was used as the endpoint of an interval
    // that has been filtered or removed. However, since it is a dynamic time it
    // should be preserved and not filtered.
    kWasDynamicEndpoint = 8
  };
  uint8_t       mFlags;   // Combination of kDynamic, kMayUpdate, etc.
  mutable bool  mVisited; // Cycle tracking

  // Additional reference count to determine if this instance time is currently
  // used as a fixed endpoint in any intervals. Instance times that are used in
  // this way should not be removed when the owning nsSMILTimedElement removes
  // instance times in response to a restart or in an attempt to free up memory
  // by filtering out old instance times.
  //
  // Instance times are only shared in a few cases, namely:
  // a) early ends,
  // b) zero-duration intervals,
  // c) momentarily whilst establishing new intervals and updating the current
  //    interval, and
  // d) trimmed intervals
  // Hence the limited range of a uint16_t should be more than adequate.
  uint16_t      mFixedEndpointRefCnt;

  uint32_t      mSerial; // A serial number used by the containing class to
                         // specify the sort order for instance times with the
                         // same mTime.

  nsSMILTimeValueSpec* mCreator; // The nsSMILTimeValueSpec object that created
                                 // us. (currently only needed for syncbase
                                 // instance times.)
  nsSMILInterval* mBaseInterval; // Interval from which this time is derived
                                 // (only used for syncbase instance times)
};

#endif // NS_SMILINSTANCETIME_H_