017a6a0afdbaacf440f656864f71b2978ff62b63
[WebKit-https.git] / Source / WebCore / html / track / InbandGenericTextTrack.cpp
1 /*
2  * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "InbandGenericTextTrack.h"
28
29 #if ENABLE(VIDEO_TRACK)
30
31 #include "DataCue.h"
32 #include "HTMLMediaElement.h"
33 #include "InbandTextTrackPrivate.h"
34 #include "Logging.h"
35 #include "VTTRegionList.h"
36 #include <math.h>
37 #include <wtf/text/CString.h>
38
39 namespace WebCore {
40
41 void GenericTextTrackCueMap::add(GenericCueData& cueData, TextTrackCueGeneric& cue)
42 {
43     m_dataToCueMap.add(&cueData, &cue);
44     m_cueToDataMap.add(&cue, &cueData);
45 }
46
47 TextTrackCueGeneric* GenericTextTrackCueMap::find(GenericCueData& cueData)
48 {
49     return m_dataToCueMap.get(&cueData);
50 }
51
52 GenericCueData* GenericTextTrackCueMap::find(TextTrackCue& cue)
53 {
54     return m_cueToDataMap.get(&cue);
55 }
56
57 void GenericTextTrackCueMap::remove(GenericCueData& cueData)
58 {
59     if (auto cue = m_dataToCueMap.take(&cueData))
60         m_cueToDataMap.remove(cue);
61 }
62
63 void GenericTextTrackCueMap::remove(TextTrackCue& cue)
64 {
65     if (auto data = m_cueToDataMap.take(&cue))
66         m_dataToCueMap.remove(data);
67 }
68
69 inline InbandGenericTextTrack::InbandGenericTextTrack(ScriptExecutionContext& context, TextTrackClient& client, InbandTextTrackPrivate& trackPrivate)
70     : InbandTextTrack(context, client, trackPrivate)
71 {
72 }
73
74 Ref<InbandGenericTextTrack> InbandGenericTextTrack::create(ScriptExecutionContext& context, TextTrackClient& client, InbandTextTrackPrivate& trackPrivate)
75 {
76     return adoptRef(*new InbandGenericTextTrack(context, client, trackPrivate));
77 }
78
79 InbandGenericTextTrack::~InbandGenericTextTrack() = default;
80
81 void InbandGenericTextTrack::updateCueFromCueData(TextTrackCueGeneric& cue, GenericCueData& cueData)
82 {
83     cue.willChange();
84
85     cue.setStartTime(cueData.startTime());
86     MediaTime endTime = cueData.endTime();
87     if (endTime.isPositiveInfinite() && mediaElement())
88         endTime = mediaElement()->durationMediaTime();
89     cue.setEndTime(endTime);
90     cue.setText(cueData.content());
91     cue.setId(cueData.id());
92     cue.setBaseFontSizeRelativeToVideoHeight(cueData.baseFontSize());
93     cue.setFontSizeMultiplier(cueData.relativeFontSize());
94     cue.setFontName(cueData.fontName());
95
96     if (cueData.position() > 0)
97         cue.setPosition(std::round(cueData.position()));
98     if (cueData.line() > 0)
99         cue.setLine(std::round(cueData.line()));
100     if (cueData.size() > 0)
101         cue.setSize(std::round(cueData.size()));
102     if (cueData.backgroundColor().isValid())
103         cue.setBackgroundColor(cueData.backgroundColor().rgb());
104     if (cueData.foregroundColor().isValid())
105         cue.setForegroundColor(cueData.foregroundColor().rgb());
106     if (cueData.highlightColor().isValid())
107         cue.setHighlightColor(cueData.highlightColor().rgb());
108
109     if (cueData.align() == GenericCueData::Start)
110         cue.setAlign(ASCIILiteral("start"));
111     else if (cueData.align() == GenericCueData::Middle)
112         cue.setAlign(ASCIILiteral("middle"));
113     else if (cueData.align() == GenericCueData::End)
114         cue.setAlign(ASCIILiteral("end"));
115     cue.setSnapToLines(false);
116
117     cue.didChange();
118 }
119
120 void InbandGenericTextTrack::addGenericCue(GenericCueData& cueData)
121 {
122     if (m_cueMap.find(cueData))
123         return;
124
125     auto cue = TextTrackCueGeneric::create(*scriptExecutionContext(), cueData.startTime(), cueData.endTime(), cueData.content());
126     updateCueFromCueData(cue.get(), cueData);
127     if (hasCue(cue.ptr(), TextTrackCue::IgnoreDuration)) {
128         DEBUG_LOG(LOGIDENTIFIER, "ignoring already added cue: ", cue.get());
129         return;
130     }
131
132     DEBUG_LOG(LOGIDENTIFIER, "added cue: ", cue.get());
133
134     if (cueData.status() != GenericCueData::Complete)
135         m_cueMap.add(cueData, cue);
136
137     addCue(WTFMove(cue));
138 }
139
140 void InbandGenericTextTrack::updateGenericCue(GenericCueData& cueData)
141 {
142     auto* cue = m_cueMap.find(cueData);
143     if (!cue)
144         return;
145
146     updateCueFromCueData(*cue, cueData);
147
148     if (cueData.status() == GenericCueData::Complete)
149         m_cueMap.remove(cueData);
150 }
151
152 void InbandGenericTextTrack::removeGenericCue(GenericCueData& cueData)
153 {
154     auto* cue = m_cueMap.find(cueData);
155     if (cue) {
156         DEBUG_LOG(LOGIDENTIFIER, *cue);
157         removeCue(*cue);
158     } else
159         DEBUG_LOG(LOGIDENTIFIER, "UNABLE to find cue: ", *cue);
160
161 }
162
163 ExceptionOr<void> InbandGenericTextTrack::removeCue(TextTrackCue& cue)
164 {
165     auto result = TextTrack::removeCue(cue);
166     if (!result.hasException())
167         m_cueMap.remove(cue);
168     return result;
169 }
170
171 WebVTTParser& InbandGenericTextTrack::parser()
172 {
173     if (!m_webVTTParser)
174         m_webVTTParser = std::make_unique<WebVTTParser>(static_cast<WebVTTParserClient*>(this), scriptExecutionContext());
175     return *m_webVTTParser;
176 }
177
178 void InbandGenericTextTrack::parseWebVTTCueData(const ISOWebVTTCue& cueData)
179 {
180     parser().parseCueData(cueData);
181 }
182
183 void InbandGenericTextTrack::parseWebVTTFileHeader(String&& header)
184 {
185     parser().parseFileHeader(WTFMove(header));
186 }
187
188 void InbandGenericTextTrack::newCuesParsed()
189 {
190     Vector<RefPtr<WebVTTCueData>> cues;
191     parser().getNewCues(cues);
192
193     for (auto& cueData : cues) {
194         auto vttCue = VTTCue::create(*scriptExecutionContext(), *cueData);
195
196         if (hasCue(vttCue.ptr(), TextTrackCue::IgnoreDuration)) {
197             DEBUG_LOG(LOGIDENTIFIER, "ignoring already added cue: ", vttCue.get());
198             return;
199         }
200
201         DEBUG_LOG(LOGIDENTIFIER, vttCue.get());
202
203         addCue(WTFMove(vttCue));
204     }
205 }
206
207 void InbandGenericTextTrack::newRegionsParsed()
208 {
209     Vector<RefPtr<VTTRegion>> newRegions;
210     parser().getNewRegions(newRegions);
211
212     for (auto& region : newRegions) {
213         region->setTrack(this);
214         regions()->add(region.releaseNonNull());
215     }
216 }
217
218 void InbandGenericTextTrack::fileFailedToParse()
219 {
220     ERROR_LOG(LOGIDENTIFIER);
221 }
222
223 } // namespace WebCore
224
225 #endif