gecko-dev/dom/html/TimeRanges.cpp
Chris Pearce 4ffa31745b Bug 1392498 - Move TimeIntervals to dom::TimeRanges conversion into TimeRanges class. r=jya
If TimeUnits.h includes mozilla/dom/TimeRanges.h, then the build ends up
pulling in the Gecko DOM bindings, which pulls in a whole lot of JavaScript and
DOM bindings code. That makes it trickier to import GeckoMedia into Servo, and
makes Gecko's build slower, so move the code to convert TimeIntervals into
dom::TimeRanges.

Also remove an extraneous "virtual" and add "const" to some functions in TimeRanges.

MozReview-Commit-ID: BLeehaf9gCE

--HG--
extra : rebase_source : 84ef054cf8fd5b4434dc761a1b0a39803d3231f5
2017-08-21 15:08:25 +12:00

233 lines
5.0 KiB
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/dom/TimeRanges.h"
#include "mozilla/dom/TimeRangesBinding.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "TimeUnits.h"
#include "nsError.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TimeRanges, mParent)
NS_IMPL_CYCLE_COLLECTING_ADDREF(TimeRanges)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TimeRanges)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TimeRanges)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIDOMTimeRanges)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
TimeRanges::TimeRanges()
: mParent(nullptr)
{
}
TimeRanges::TimeRanges(nsISupports* aParent)
: mParent(aParent)
{
}
TimeRanges::TimeRanges(nsISupports* aParent,
const media::TimeIntervals& aTimeIntervals)
: TimeRanges(aParent)
{
if (aTimeIntervals.IsInvalid()) {
return;
}
for (const media::TimeInterval& interval : aTimeIntervals) {
Add(interval.mStart.ToSeconds(), interval.mEnd.ToSeconds());
}
}
TimeRanges::TimeRanges(const media::TimeIntervals& aTimeIntervals)
: TimeRanges(nullptr, aTimeIntervals)
{
}
media::TimeIntervals
TimeRanges::ToTimeIntervals() const
{
media::TimeIntervals t;
for (uint32_t i = 0; i < Length(); i++) {
ErrorResult rv;
t += media::TimeInterval(media::TimeUnit::FromSeconds(Start(i, rv)),
media::TimeUnit::FromSeconds(End(i, rv)));
}
return t;
}
TimeRanges::~TimeRanges()
{
}
NS_IMETHODIMP
TimeRanges::GetLength(uint32_t* aLength)
{
*aLength = Length();
return NS_OK;
}
double
TimeRanges::Start(uint32_t aIndex, ErrorResult& aRv) const
{
if (aIndex >= mRanges.Length()) {
aRv = NS_ERROR_DOM_INDEX_SIZE_ERR;
return 0;
}
return mRanges[aIndex].mStart;
}
NS_IMETHODIMP
TimeRanges::Start(uint32_t aIndex, double* aTime)
{
ErrorResult rv;
*aTime = Start(aIndex, rv);
return rv.StealNSResult();
}
double
TimeRanges::End(uint32_t aIndex, ErrorResult& aRv) const
{
if (aIndex >= mRanges.Length()) {
aRv = NS_ERROR_DOM_INDEX_SIZE_ERR;
return 0;
}
return mRanges[aIndex].mEnd;
}
NS_IMETHODIMP
TimeRanges::End(uint32_t aIndex, double* aTime)
{
ErrorResult rv;
*aTime = End(aIndex, rv);
return rv.StealNSResult();
}
void
TimeRanges::Add(double aStart, double aEnd)
{
if (aStart > aEnd) {
NS_WARNING("Can't add a range if the end is older that the start.");
return;
}
mRanges.AppendElement(TimeRange(aStart,aEnd));
}
double
TimeRanges::GetStartTime()
{
if (mRanges.IsEmpty()) {
return -1.0;
}
return mRanges[0].mStart;
}
double
TimeRanges::GetEndTime()
{
if (mRanges.IsEmpty()) {
return -1.0;
}
return mRanges[mRanges.Length() - 1].mEnd;
}
void
TimeRanges::Normalize(double aTolerance)
{
if (mRanges.Length() >= 2) {
AutoTArray<TimeRange,4> normalized;
mRanges.Sort(CompareTimeRanges());
// This merges the intervals.
TimeRange current(mRanges[0]);
for (uint32_t i = 1; i < mRanges.Length(); i++) {
if (current.mStart <= mRanges[i].mStart &&
current.mEnd >= mRanges[i].mEnd) {
continue;
}
if (current.mEnd + aTolerance >= mRanges[i].mStart) {
current.mEnd = mRanges[i].mEnd;
} else {
normalized.AppendElement(current);
current = mRanges[i];
}
}
normalized.AppendElement(current);
mRanges = normalized;
}
}
void
TimeRanges::Union(const TimeRanges* aOtherRanges, double aTolerance)
{
mRanges.AppendElements(aOtherRanges->mRanges);
Normalize(aTolerance);
}
void
TimeRanges::Intersection(const TimeRanges* aOtherRanges)
{
AutoTArray<TimeRange,4> intersection;
const nsTArray<TimeRange>& otherRanges = aOtherRanges->mRanges;
for (index_type i = 0, j = 0; i < mRanges.Length() && j < otherRanges.Length();) {
double start = std::max(mRanges[i].mStart, otherRanges[j].mStart);
double end = std::min(mRanges[i].mEnd, otherRanges[j].mEnd);
if (start < end) {
intersection.AppendElement(TimeRange(start, end));
}
if (mRanges[i].mEnd < otherRanges[j].mEnd) {
i += 1;
} else {
j += 1;
}
}
mRanges = intersection;
}
TimeRanges::index_type
TimeRanges::Find(double aTime, double aTolerance /* = 0 */)
{
for (index_type i = 0; i < mRanges.Length(); ++i) {
if (aTime < mRanges[i].mEnd && (aTime + aTolerance) >= mRanges[i].mStart) {
return i;
}
}
return NoIndex;
}
JSObject*
TimeRanges::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return TimeRangesBinding::Wrap(aCx, this, aGivenProto);
}
nsISupports*
TimeRanges::GetParentObject() const
{
return mParent;
}
void
TimeRanges::Shift(double aOffset)
{
for (index_type i = 0; i < mRanges.Length(); ++i) {
mRanges[i].mStart += aOffset;
mRanges[i].mEnd += aOffset;
}
}
} // namespace dom
} // namespace mozilla