1/* 2 * Copyright (C) 2011, 2013 Google Inc. All rights reserved. 3 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include "config.h" 33 34#if ENABLE(VIDEO_TRACK) 35 36#include "TextTrackCue.h" 37 38#include "CSSPropertyNames.h" 39#include "CSSValueKeywords.h" 40#include "DocumentFragment.h" 41#include "Event.h" 42#include "HTMLDivElement.h" 43#include "HTMLSpanElement.h" 44#include "Logging.h" 45#include "NodeTraversal.h" 46#include "Text.h" 47#include "TextTrack.h" 48#include "TextTrackCueList.h" 49#include "VTTCue.h" 50#include <wtf/MathExtras.h> 51#include <wtf/text/StringBuilder.h> 52 53#if ENABLE(WEBVTT_REGIONS) 54#include "VTTRegionList.h" 55#endif 56 57namespace WebCore { 58 59static const int invalidCueIndex = -1; 60 61PassRefPtr<TextTrackCue> TextTrackCue::create(ScriptExecutionContext& context, double start, double end, const String& content) 62{ 63 return VTTCue::create(context, start, end, content); 64} 65 66TextTrackCue::TextTrackCue(ScriptExecutionContext& context, double start, double end) 67 : m_startTime(start) 68 , m_endTime(end) 69 , m_cueIndex(invalidCueIndex) 70 , m_processingCueChanges(0) 71 , m_track(0) 72 , m_scriptExecutionContext(context) 73 , m_isActive(false) 74 , m_pauseOnExit(false) 75{ 76 ASSERT(m_scriptExecutionContext.isDocument()); 77} 78 79TextTrackCue::~TextTrackCue() 80{ 81} 82 83void TextTrackCue::willChange() 84{ 85 if (++m_processingCueChanges > 1) 86 return; 87 88 if (m_track) 89 m_track->cueWillChange(this); 90} 91 92void TextTrackCue::didChange() 93{ 94 ASSERT(m_processingCueChanges); 95 if (--m_processingCueChanges) 96 return; 97 98 if (m_track) 99 m_track->cueDidChange(this); 100} 101 102TextTrack* TextTrackCue::track() const 103{ 104 return m_track; 105} 106 107void TextTrackCue::setTrack(TextTrack* track) 108{ 109 m_track = track; 110} 111 112void TextTrackCue::setId(const String& id) 113{ 114 if (m_id == id) 115 return; 116 117 willChange(); 118 m_id = id; 119 didChange(); 120} 121 122void TextTrackCue::setStartTime(double value, ExceptionCode& ec) 123{ 124 // NaN, Infinity and -Infinity values should trigger a TypeError. 125 if (std::isinf(value) || std::isnan(value)) { 126 ec = TypeError; 127 return; 128 } 129 130 // TODO(93143): Add spec-compliant behavior for negative time values. 131 if (m_startTime == value || value < 0) 132 return; 133 134 willChange(); 135 m_startTime = value; 136 didChange(); 137} 138 139void TextTrackCue::setEndTime(double value, ExceptionCode& ec) 140{ 141 // NaN, Infinity and -Infinity values should trigger a TypeError. 142 if (std::isinf(value) || std::isnan(value)) { 143 ec = TypeError; 144 return; 145 } 146 147 // TODO(93143): Add spec-compliant behavior for negative time values. 148 if (m_endTime == value || value < 0) 149 return; 150 151 willChange(); 152 m_endTime = value; 153 didChange(); 154} 155 156void TextTrackCue::setPauseOnExit(bool value) 157{ 158 if (m_pauseOnExit == value) 159 return; 160 161 m_pauseOnExit = value; 162} 163 164int TextTrackCue::cueIndex() 165{ 166 if (m_cueIndex == invalidCueIndex) { 167 ASSERT(track()); 168 ASSERT(track()->cues()); 169 if (TextTrackCueList* cueList = track()->cues()) 170 m_cueIndex = cueList->getCueIndex(this); 171 } 172 173 return m_cueIndex; 174} 175 176void TextTrackCue::invalidateCueIndex() 177{ 178 m_cueIndex = invalidCueIndex; 179} 180 181bool TextTrackCue::dispatchEvent(PassRefPtr<Event> event) 182{ 183 // When a TextTrack's mode is disabled: no cues are active, no events fired. 184 if (!track() || track()->mode() == TextTrack::disabledKeyword()) 185 return false; 186 187 return EventTarget::dispatchEvent(event); 188} 189 190bool TextTrackCue::isActive() 191{ 192 return m_isActive && track() && track()->mode() != TextTrack::disabledKeyword(); 193} 194 195void TextTrackCue::setIsActive(bool active) 196{ 197 m_isActive = active; 198} 199 200bool TextTrackCue::isOrderedBefore(const TextTrackCue* other) const 201{ 202 return startTime() < other->startTime() || (startTime() == other->startTime() && endTime() > other->endTime()); 203} 204 205bool TextTrackCue::cueContentsMatch(const TextTrackCue& cue) const 206{ 207 if (cueType() != cue.cueType()) 208 return false; 209 210 if (id() != cue.id()) 211 return false; 212 213 return true; 214} 215 216bool TextTrackCue::isEqual(const TextTrackCue& cue, TextTrackCue::CueMatchRules match) const 217{ 218 if (cueType() != cue.cueType()) 219 return false; 220 221 if (match != IgnoreDuration && endTime() != cue.endTime()) 222 return false; 223 if (!hasEquivalentStartTime(cue)) 224 return false; 225 if (!cueContentsMatch(cue)) 226 return false; 227 228 return true; 229} 230 231bool TextTrackCue::hasEquivalentStartTime(const TextTrackCue& cue) const 232{ 233 double startTimeVariance = 0; 234 if (track()) 235 startTimeVariance = track()->startTimeVariance(); 236 else if (cue.track()) 237 startTimeVariance = cue.track()->startTimeVariance(); 238 239 return std::abs(std::abs(startTime()) - std::abs(cue.startTime())) <= startTimeVariance; 240} 241 242bool TextTrackCue::doesExtendCue(const TextTrackCue& cue) const 243{ 244 if (!cueContentsMatch(cue)) 245 return false; 246 247 if (endTime() != cue.startTime()) 248 return false; 249 250 return true; 251} 252 253} // namespace WebCore 254 255#endif 256