dom/html/TimeRanges.cpp
author Masayuki Nakano <masayuki@d-toybox.com>
Fri, 19 May 2017 17:49:41 +0900
changeset 407399 b75c111837a802ceb953dba50a3c5a193d53ca22
parent 319078 75dfe10ec44a88bda2d9721d269ddf2429ac5426
child 426628 ac74aef901edd88bc3839a05039e0f9ed644a4a7
permissions -rw-r--r--
Bug 1339543 part 4 Change nsIWidget::ExecuteNativeKeyBinding() to nsIWidget::GetEditCommands() which just retrieves edit commands for the type r=smaug Now, nsIWidget::ExecuteNativeKeyBinding() isn't used by anybody for executing edit commands. Instead, they need array of edit commands for the key combination. So, the method should be renamed to GetEditCommands() and just return edit commands as an array. MozReview-Commit-ID: 4G0B1lJ8Lbe

/* -*- 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 "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()
{
}

NS_IMETHODIMP
TimeRanges::GetLength(uint32_t* aLength)
{
  *aLength = Length();
  return NS_OK;
}

double
TimeRanges::Start(uint32_t aIndex, ErrorResult& aRv)
{
  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)
{
  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