Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / dom / html / TimeRanges.cpp
blob21f1f56baac63827b6d2a73dca0a850f6009d013
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/TimeRanges.h"
8 #include "mozilla/dom/TimeRangesBinding.h"
9 #include "mozilla/dom/HTMLMediaElement.h"
10 #include "TimeUnits.h"
11 #include "nsError.h"
13 namespace mozilla::dom {
15 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TimeRanges, mParent)
16 NS_IMPL_CYCLE_COLLECTING_ADDREF(TimeRanges)
17 NS_IMPL_CYCLE_COLLECTING_RELEASE(TimeRanges)
18 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TimeRanges)
19 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
20 NS_INTERFACE_MAP_ENTRY(nsISupports)
21 NS_INTERFACE_MAP_END
23 TimeRanges::TimeRanges() : mParent(nullptr) {}
25 TimeRanges::TimeRanges(nsISupports* aParent) : mParent(aParent) {}
27 TimeRanges::TimeRanges(nsISupports* aParent,
28 const media::TimeIntervals& aTimeIntervals)
29 : TimeRanges(aParent) {
30 if (aTimeIntervals.IsInvalid()) {
31 return;
33 for (const media::TimeInterval& interval : aTimeIntervals) {
34 Add(interval.mStart.ToSeconds(), interval.mEnd.ToSeconds());
38 TimeRanges::TimeRanges(nsISupports* aParent,
39 const media::TimeRanges& aTimeRanges)
40 : TimeRanges(aParent) {
41 if (aTimeRanges.IsInvalid()) {
42 return;
44 for (const media::TimeRange& interval : aTimeRanges) {
45 Add(interval.mStart, interval.mEnd);
49 TimeRanges::TimeRanges(const media::TimeIntervals& aTimeIntervals)
50 : TimeRanges(nullptr, aTimeIntervals) {}
52 TimeRanges::TimeRanges(const media::TimeRanges& aTimeRanges)
53 : TimeRanges(nullptr, aTimeRanges) {}
55 media::TimeIntervals TimeRanges::ToTimeIntervals() const {
56 media::TimeIntervals t;
57 for (uint32_t i = 0; i < Length(); i++) {
58 t += media::TimeInterval(media::TimeUnit::FromSeconds(Start(i)),
59 media::TimeUnit::FromSeconds(End(i)));
61 return t;
64 TimeRanges::~TimeRanges() = default;
66 double TimeRanges::Start(uint32_t aIndex, ErrorResult& aRv) const {
67 if (aIndex >= mRanges.Length()) {
68 aRv = NS_ERROR_DOM_INDEX_SIZE_ERR;
69 return 0;
72 return Start(aIndex);
75 double TimeRanges::End(uint32_t aIndex, ErrorResult& aRv) const {
76 if (aIndex >= mRanges.Length()) {
77 aRv = NS_ERROR_DOM_INDEX_SIZE_ERR;
78 return 0;
81 return End(aIndex);
84 void TimeRanges::Add(double aStart, double aEnd) {
85 if (aStart > aEnd) {
86 NS_WARNING("Can't add a range if the end is older that the start.");
87 return;
89 mRanges.AppendElement(TimeRange(aStart, aEnd));
92 double TimeRanges::GetStartTime() {
93 if (mRanges.IsEmpty()) {
94 return -1.0;
96 return mRanges[0].mStart;
99 double TimeRanges::GetEndTime() {
100 if (mRanges.IsEmpty()) {
101 return -1.0;
103 return mRanges[mRanges.Length() - 1].mEnd;
106 void TimeRanges::Normalize(double aTolerance) {
107 if (mRanges.Length() >= 2) {
108 AutoTArray<TimeRange, 4> normalized;
110 mRanges.Sort(CompareTimeRanges());
112 // This merges the intervals.
113 TimeRange current(mRanges[0]);
114 for (uint32_t i = 1; i < mRanges.Length(); i++) {
115 if (current.mStart <= mRanges[i].mStart &&
116 current.mEnd >= mRanges[i].mEnd) {
117 continue;
119 if (current.mEnd + aTolerance >= mRanges[i].mStart) {
120 current.mEnd = mRanges[i].mEnd;
121 } else {
122 normalized.AppendElement(current);
123 current = mRanges[i];
127 normalized.AppendElement(current);
129 mRanges = std::move(normalized);
133 void TimeRanges::Union(const TimeRanges* aOtherRanges, double aTolerance) {
134 mRanges.AppendElements(aOtherRanges->mRanges);
135 Normalize(aTolerance);
138 void TimeRanges::Intersection(const TimeRanges* aOtherRanges) {
139 AutoTArray<TimeRange, 4> intersection;
141 const nsTArray<TimeRange>& otherRanges = aOtherRanges->mRanges;
142 for (index_type i = 0, j = 0;
143 i < mRanges.Length() && j < otherRanges.Length();) {
144 double start = std::max(mRanges[i].mStart, otherRanges[j].mStart);
145 double end = std::min(mRanges[i].mEnd, otherRanges[j].mEnd);
146 if (start < end) {
147 intersection.AppendElement(TimeRange(start, end));
149 if (mRanges[i].mEnd < otherRanges[j].mEnd) {
150 i += 1;
151 } else {
152 j += 1;
156 mRanges = std::move(intersection);
159 TimeRanges::index_type TimeRanges::Find(double aTime,
160 double aTolerance /* = 0 */) {
161 for (index_type i = 0; i < mRanges.Length(); ++i) {
162 if (aTime < mRanges[i].mEnd && (aTime + aTolerance) >= mRanges[i].mStart) {
163 return i;
166 return NoIndex;
169 JSObject* TimeRanges::WrapObject(JSContext* aCx,
170 JS::Handle<JSObject*> aGivenProto) {
171 return TimeRanges_Binding::Wrap(aCx, this, aGivenProto);
174 nsISupports* TimeRanges::GetParentObject() const { return mParent; }
176 void TimeRanges::Shift(double aOffset) {
177 for (index_type i = 0; i < mRanges.Length(); ++i) {
178 mRanges[i].mStart += aOffset;
179 mRanges[i].mEnd += aOffset;
183 } // namespace mozilla::dom