[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[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/IsoMallocInlines.h>
38 #include <wtf/text/CString.h>
39
40 namespace WebCore {
41
42 WTF_MAKE_ISO_ALLOCATED_IMPL(InbandGenericTextTrack);
43
44 void GenericTextTrackCueMap::add(GenericCueData& cueData, TextTrackCueGeneric& cue)
45 {
46     m_dataToCueMap.add(&cueData, &cue);
47     m_cueToDataMap.add(&cue, &cueData);
48 }
49
50 TextTrackCueGeneric* GenericTextTrackCueMap::find(GenericCueData& cueData)
51 {
52     return m_dataToCueMap.get(&cueData);
53 }
54
55 GenericCueData* GenericTextTrackCueMap::find(TextTrackCue& cue)
56 {
57     return m_cueToDataMap.get(&cue);
58 }
59
60 void GenericTextTrackCueMap::remove(GenericCueData& cueData)
61 {
62     if (auto cue = m_dataToCueMap.take(&cueData))
63         m_cueToDataMap.remove(cue);
64 }
65
66 void GenericTextTrackCueMap::remove(TextTrackCue& cue)
67 {
68     if (auto data = m_cueToDataMap.take(&cue))
69         m_dataToCueMap.remove(data);
70 }
71
72 inline InbandGenericTextTrack::InbandGenericTextTrack(ScriptExecutionContext& context, TextTrackClient& client, InbandTextTrackPrivate& trackPrivate)
73     : InbandTextTrack(context, client, trackPrivate)
74 {
75 }
76
77 Ref<InbandGenericTextTrack> InbandGenericTextTrack::create(ScriptExecutionContext& context, TextTrackClient& client, InbandTextTrackPrivate& trackPrivate)
78 {
79     return adoptRef(*new InbandGenericTextTrack(context, client, trackPrivate));
80 }
81
82 InbandGenericTextTrack::~InbandGenericTextTrack() = default;
83
84 void InbandGenericTextTrack::updateCueFromCueData(TextTrackCueGeneric& cue, GenericCueData& cueData)
85 {
86     cue.willChange();
87
88     cue.setStartTime(cueData.startTime());
89     MediaTime endTime = cueData.endTime();
90     if (endTime.isPositiveInfinite() && mediaElement())
91         endTime = mediaElement()->durationMediaTime();
92     cue.setEndTime(endTime);
93     cue.setText(cueData.content());
94     cue.setId(cueData.id());
95     cue.setBaseFontSizeRelativeToVideoHeight(cueData.baseFontSize());
96     cue.setFontSizeMultiplier(cueData.relativeFontSize());
97     cue.setFontName(cueData.fontName());
98
99     if (cueData.position() > 0)
100         cue.setPosition(std::round(cueData.position()));
101     if (cueData.line() > 0)
102         cue.setLine(std::round(cueData.line()));
103     if (cueData.size() > 0)
104         cue.setSize(std::round(cueData.size()));
105     if (cueData.backgroundColor().isValid())
106         cue.setBackgroundColor(cueData.backgroundColor().rgb());
107     if (cueData.foregroundColor().isValid())
108         cue.setForegroundColor(cueData.foregroundColor().rgb());
109     if (cueData.highlightColor().isValid())
110         cue.setHighlightColor(cueData.highlightColor().rgb());
111
112     if (cueData.align() == GenericCueData::Start)
113         cue.setAlign("start"_s);
114     else if (cueData.align() == GenericCueData::Middle)
115         cue.setAlign("middle"_s);
116     else if (cueData.align() == GenericCueData::End)
117         cue.setAlign("end"_s);
118     cue.setSnapToLines(false);
119
120     cue.didChange();
121 }
122
123 void InbandGenericTextTrack::addGenericCue(GenericCueData& cueData)
124 {
125     if (m_cueMap.find(cueData))
126         return;
127
128     auto cue = TextTrackCueGeneric::create(*scriptExecutionContext(), cueData.startTime(), cueData.endTime(), cueData.content());
129     updateCueFromCueData(cue.get(), cueData);
130     if (hasCue(cue.ptr(), TextTrackCue::IgnoreDuration)) {
131         INFO_LOG(LOGIDENTIFIER, "ignoring already added cue: ", cue.get());
132         return;
133     }
134
135     INFO_LOG(LOGIDENTIFIER, "added cue: ", cue.get());
136
137     if (cueData.status() != GenericCueData::Complete)
138         m_cueMap.add(cueData, cue);
139
140     addCue(WTFMove(cue));
141 }
142
143 void InbandGenericTextTrack::updateGenericCue(GenericCueData& cueData)
144 {
145     auto cue = makeRefPtr(m_cueMap.find(cueData));
146     if (!cue)
147         return;
148
149     updateCueFromCueData(*cue, cueData);
150
151     if (cueData.status() == GenericCueData::Complete)
152         m_cueMap.remove(cueData);
153 }
154
155 void InbandGenericTextTrack::removeGenericCue(GenericCueData& cueData)
156 {
157     auto cue = makeRefPtr(m_cueMap.find(cueData));
158     if (cue) {
159         INFO_LOG(LOGIDENTIFIER, *cue);
160         removeCue(*cue);
161     } else
162         INFO_LOG(LOGIDENTIFIER, "UNABLE to find cue: ", cueData);
163
164 }
165
166 ExceptionOr<void> InbandGenericTextTrack::removeCue(TextTrackCue& cue)
167 {
168     auto result = TextTrack::removeCue(cue);
169     if (!result.hasException())
170         m_cueMap.remove(cue);
171     return result;
172 }
173
174 WebVTTParser& InbandGenericTextTrack::parser()
175 {
176     if (!m_webVTTParser)
177         m_webVTTParser = makeUnique<WebVTTParser>(static_cast<WebVTTParserClient*>(this), scriptExecutionContext());
178     return *m_webVTTParser;
179 }
180
181 void InbandGenericTextTrack::parseWebVTTCueData(const ISOWebVTTCue& cueData)
182 {
183     parser().parseCueData(cueData);
184 }
185
186 void InbandGenericTextTrack::parseWebVTTFileHeader(String&& header)
187 {
188     parser().parseFileHeader(WTFMove(header));
189 }
190
191 void InbandGenericTextTrack::newCuesParsed()
192 {
193     Vector<RefPtr<WebVTTCueData>> cues;
194     parser().getNewCues(cues);
195
196     for (auto& cueData : cues) {
197         auto vttCue = VTTCue::create(*scriptExecutionContext(), *cueData);
198
199         if (hasCue(vttCue.ptr(), TextTrackCue::IgnoreDuration)) {
200             INFO_LOG(LOGIDENTIFIER, "ignoring already added cue: ", vttCue.get());
201             return;
202         }
203
204         INFO_LOG(LOGIDENTIFIER, vttCue.get());
205
206         addCue(WTFMove(vttCue));
207     }
208 }
209
210 void InbandGenericTextTrack::newRegionsParsed()
211 {
212     Vector<RefPtr<VTTRegion>> newRegions;
213     parser().getNewRegions(newRegions);
214
215     for (auto& region : newRegions) {
216         region->setTrack(this);
217         regions()->add(region.releaseNonNull());
218     }
219 }
220
221 void InbandGenericTextTrack::newStyleSheetsParsed()
222 {
223 }
224
225 void InbandGenericTextTrack::fileFailedToParse()
226 {
227     ERROR_LOG(LOGIDENTIFIER);
228 }
229
230 } // namespace WebCore
231
232 #endif