e9112efcb414856023b3122c93b5983e8c903ecc
[WebKit-https.git] / Source / WebCore / html / track / TextTrackCue.cpp
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 "VTTRegionList.h"
51 #include <wtf/MathExtras.h>
52
53 namespace WebCore {
54
55 static const int invalidCueIndex = -1;
56
57 TextTrackCue::TextTrackCue(ScriptExecutionContext& context, const MediaTime& start, const MediaTime& end)
58     : m_startTime(start)
59     , m_endTime(end)
60     , m_cueIndex(invalidCueIndex)
61     , m_processingCueChanges(0)
62     , m_track(0)
63     , m_scriptExecutionContext(context)
64     , m_isActive(false)
65     , m_pauseOnExit(false)
66 {
67     ASSERT(m_scriptExecutionContext.isDocument());
68 }
69
70 TextTrackCue::~TextTrackCue()
71 {
72 }
73
74 void TextTrackCue::willChange()
75 {
76     if (++m_processingCueChanges > 1)
77         return;
78
79     if (m_track)
80         m_track->cueWillChange(this);
81 }
82
83 void TextTrackCue::didChange()
84 {
85     ASSERT(m_processingCueChanges);
86     if (--m_processingCueChanges)
87         return;
88
89     if (m_track)
90         m_track->cueDidChange(this);
91 }
92
93 TextTrack* TextTrackCue::track() const
94 {
95     return m_track;
96 }
97
98 void TextTrackCue::setTrack(TextTrack* track)
99 {
100     m_track = track;
101 }
102
103 void TextTrackCue::setId(const String& id)
104 {
105     if (m_id == id)
106         return;
107
108     willChange();
109     m_id = id;
110     didChange();
111 }
112
113 void TextTrackCue::setStartTime(double value, ExceptionCode& ec)
114 {
115     // NaN, Infinity and -Infinity values should trigger a TypeError.
116     if (std::isinf(value) || std::isnan(value)) {
117         ec = TypeError;
118         return;
119     }
120     
121     // TODO(93143): Add spec-compliant behavior for negative time values.
122     if (m_startTime.toDouble() == value || value < 0)
123         return;
124
125     setStartTime(MediaTime::createWithDouble(value));
126 }
127
128 void TextTrackCue::setStartTime(const MediaTime& value)
129 {
130     willChange();
131     m_startTime = value;
132     didChange();
133 }
134     
135 void TextTrackCue::setEndTime(double value, ExceptionCode& ec)
136 {
137     // NaN, Infinity and -Infinity values should trigger a TypeError.
138     if (std::isinf(value) || std::isnan(value)) {
139         ec = TypeError;
140         return;
141     }
142
143     // TODO(93143): Add spec-compliant behavior for negative time values.
144     if (m_endTime.toDouble() == value || value < 0)
145         return;
146
147     setEndTime(MediaTime::createWithDouble(value));
148 }
149
150 void TextTrackCue::setEndTime(const MediaTime& value)
151 {
152     willChange();
153     m_endTime = value;
154     didChange();
155 }
156     
157 void TextTrackCue::setPauseOnExit(bool value)
158 {
159     if (m_pauseOnExit == value)
160         return;
161     
162     m_pauseOnExit = value;
163 }
164
165 int TextTrackCue::cueIndex()
166 {
167     if (m_cueIndex == invalidCueIndex) {
168         ASSERT(track());
169         ASSERT(track()->cues());
170         if (TextTrackCueList* cueList = track()->cues())
171             m_cueIndex = cueList->getCueIndex(this);
172     }
173
174     return m_cueIndex;
175 }
176
177 void TextTrackCue::invalidateCueIndex()
178 {
179     m_cueIndex = invalidCueIndex;
180 }
181
182 bool TextTrackCue::dispatchEvent(Event& event)
183 {
184     // When a TextTrack's mode is disabled: no cues are active, no events fired.
185     if (!track() || track()->mode() == TextTrack::Mode::Disabled)
186         return false;
187
188     return EventTarget::dispatchEvent(event);
189 }
190
191 bool TextTrackCue::isActive()
192 {
193     return m_isActive && track() && track()->mode() != TextTrack::Mode::Disabled;
194 }
195
196 void TextTrackCue::setIsActive(bool active)
197 {
198     m_isActive = active;
199 }
200
201 bool TextTrackCue::isOrderedBefore(const TextTrackCue* other) const
202 {
203     return startMediaTime() < other->startMediaTime() || (startMediaTime() == other->startMediaTime() && endMediaTime() > other->endMediaTime());
204 }
205
206 bool TextTrackCue::cueContentsMatch(const TextTrackCue& cue) const
207 {
208     if (cueType() != cue.cueType())
209         return false;
210
211     if (id() != cue.id())
212         return false;
213
214     return true;
215 }
216
217 bool TextTrackCue::isEqual(const TextTrackCue& cue, TextTrackCue::CueMatchRules match) const
218 {
219     if (cueType() != cue.cueType())
220         return false;
221
222     if (match != IgnoreDuration && endMediaTime() != cue.endMediaTime())
223         return false;
224     if (!hasEquivalentStartTime(cue))
225         return false;
226     if (!cueContentsMatch(cue))
227         return false;
228
229     return true;
230 }
231
232 bool TextTrackCue::hasEquivalentStartTime(const TextTrackCue& cue) const
233 {
234     MediaTime startTimeVariance = MediaTime::zeroTime();
235     if (track())
236         startTimeVariance = track()->startTimeVariance();
237     else if (cue.track())
238         startTimeVariance = cue.track()->startTimeVariance();
239
240     return abs(abs(startMediaTime()) - abs(cue.startMediaTime())) <= startTimeVariance;
241 }
242
243 bool TextTrackCue::doesExtendCue(const TextTrackCue& cue) const
244 {
245     if (!cueContentsMatch(cue))
246         return false;
247
248     if (endMediaTime() != cue.startMediaTime())
249         return false;
250     
251     return true;
252 }
253
254 } // namespace WebCore
255
256 #endif