[Mac] process raw VTT in-band captions
[WebKit-https.git] / Source / WebCore / html / track / TextTrackCueGeneric.cpp
1 /*
2  * Copyright (C) 2013, 2014 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
28 #if ENABLE(VIDEO_TRACK)
29
30 #include "TextTrackCueGeneric.h"
31
32 #include "CSSPropertyNames.h"
33 #include "CSSValueKeywords.h"
34 #include "HTMLNames.h"
35 #include "HTMLSpanElement.h"
36 #include "InbandTextTrackPrivateClient.h"
37 #include "Logging.h"
38 #include "RenderObject.h"
39 #include "ScriptExecutionContext.h"
40 #include "TextTrackCue.h"
41
42 namespace WebCore {
43
44 class TextTrackCueGenericBoxElement final : public VTTCueBox {
45 public:
46     static PassRefPtr<TextTrackCueGenericBoxElement> create(Document& document, TextTrackCueGeneric& cue)
47     {
48         return adoptRef(new TextTrackCueGenericBoxElement(document, cue));
49     }
50     
51     virtual void applyCSSProperties(const IntSize&) override;
52     
53 private:
54     TextTrackCueGenericBoxElement(Document&, VTTCue&);
55 };
56
57 TextTrackCueGenericBoxElement::TextTrackCueGenericBoxElement(Document& document, VTTCue& cue)
58     : VTTCueBox(document, cue)
59 {
60 }
61
62 void TextTrackCueGenericBoxElement::applyCSSProperties(const IntSize& videoSize)
63 {
64     setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute);
65     setInlineStyleProperty(CSSPropertyUnicodeBidi, CSSValueWebkitPlaintext);
66     
67     TextTrackCueGeneric* cue = static_cast<TextTrackCueGeneric*>(getCue());
68     RefPtr<HTMLSpanElement> cueElement = cue->element();
69
70     float size = static_cast<float>(cue->getCSSSize());
71     if (cue->useDefaultPosition()) {
72         setInlineStyleProperty(CSSPropertyBottom, 0, CSSPrimitiveValue::CSS_PX);
73         setInlineStyleProperty(CSSPropertyMarginBottom, 1.0, CSSPrimitiveValue::CSS_PERCENTAGE);
74     } else {
75         setInlineStyleProperty(CSSPropertyLeft, static_cast<float>(cue->position()), CSSPrimitiveValue::CSS_PERCENTAGE);
76         setInlineStyleProperty(CSSPropertyTop, static_cast<float>(cue->line()), CSSPrimitiveValue::CSS_PERCENTAGE);
77
78         if (cue->getWritingDirection() == VTTCue::Horizontal)
79             setInlineStyleProperty(CSSPropertyWidth, size, CSSPrimitiveValue::CSS_PERCENTAGE);
80         else
81             setInlineStyleProperty(CSSPropertyHeight, size,  CSSPrimitiveValue::CSS_PERCENTAGE);
82     }
83
84     if (cue->foregroundColor().isValid())
85         cueElement->setInlineStyleProperty(CSSPropertyColor, cue->foregroundColor().serialized());
86     if (cue->highlightColor().isValid())
87         cueElement->setInlineStyleProperty(CSSPropertyBackgroundColor, cue->highlightColor().serialized());
88
89     if (cue->getWritingDirection() == VTTCue::Horizontal)
90         setInlineStyleProperty(CSSPropertyHeight, CSSValueAuto);
91     else
92         setInlineStyleProperty(CSSPropertyWidth, CSSValueAuto);
93
94     if (cue->baseFontSizeRelativeToVideoHeight())
95         cue->setFontSize(cue->baseFontSizeRelativeToVideoHeight(), videoSize, false);
96
97     if (cue->getAlignment() == VTTCue::Middle)
98         setInlineStyleProperty(CSSPropertyTextAlign, CSSValueCenter);
99     else if (cue->getAlignment() == VTTCue::End)
100         setInlineStyleProperty(CSSPropertyTextAlign, CSSValueEnd);
101     else
102         setInlineStyleProperty(CSSPropertyTextAlign, CSSValueStart);
103
104     if (cue->backgroundColor().isValid())
105         setInlineStyleProperty(CSSPropertyBackgroundColor, cue->backgroundColor().serialized());
106     setInlineStyleProperty(CSSPropertyWebkitWritingMode, cue->getCSSWritingMode(), false);
107     setInlineStyleProperty(CSSPropertyWhiteSpace, CSSValuePreWrap);
108     setInlineStyleProperty(CSSPropertyWordBreak, CSSValueNormal);
109 }
110
111 TextTrackCueGeneric::TextTrackCueGeneric(ScriptExecutionContext& context, double start, double end, const String& content)
112     : VTTCue(context, start, end, content)
113     , m_baseFontSizeRelativeToVideoHeight(0)
114     , m_fontSizeMultiplier(0)
115     , m_defaultPosition(true)
116 {
117 }
118
119 PassRefPtr<VTTCueBox> TextTrackCueGeneric::createDisplayTree()
120 {
121     return TextTrackCueGenericBoxElement::create(ownerDocument(), *this);
122 }
123
124 void TextTrackCueGeneric::setLine(int line, ExceptionCode& ec)
125 {
126     m_defaultPosition = false;
127     VTTCue::setLine(line, ec);
128 }
129
130 void TextTrackCueGeneric::setPosition(int position, ExceptionCode& ec)
131 {
132     m_defaultPosition = false;
133     VTTCue::setPosition(position, ec);
134 }
135
136 void TextTrackCueGeneric::setFontSize(int fontSize, const IntSize& videoSize, bool important)
137 {
138     if (!hasDisplayTree() || !fontSize)
139         return;
140     
141     if (important || !baseFontSizeRelativeToVideoHeight()) {
142         VTTCue::setFontSize(fontSize, videoSize, important);
143         return;
144     }
145
146     double size = videoSize.height() * baseFontSizeRelativeToVideoHeight() / 100;
147     if (fontSizeMultiplier())
148         size *= fontSizeMultiplier() / 100;
149     displayTreeInternal()->setInlineStyleProperty(CSSPropertyFontSize, lround(size), CSSPrimitiveValue::CSS_PX);
150
151     LOG(Media, "TextTrackCueGeneric::setFontSize - setting cue font size to %li", lround(size));
152 }
153
154 bool TextTrackCueGeneric::cueContentsMatch(const TextTrackCue& cue) const
155 {
156     // Do call the parent class cueContentsMatch here, because we want to confirm
157     // the content of the two cues are identical (even though the types are not the same).
158     if (!VTTCue::cueContentsMatch(cue))
159         return false;
160     
161     const TextTrackCueGeneric* other = static_cast<const TextTrackCueGeneric*>(&cue);
162
163     if (m_baseFontSizeRelativeToVideoHeight != other->baseFontSizeRelativeToVideoHeight())
164         return false;
165     if (m_fontSizeMultiplier != other->fontSizeMultiplier())
166         return false;
167     if (m_fontName != other->fontName())
168         return false;
169     if (m_foregroundColor != other->foregroundColor())
170         return false;
171     if (m_backgroundColor != other->backgroundColor())
172         return false;
173
174     return true;
175 }
176
177 bool TextTrackCueGeneric::isEqual(const TextTrackCue& cue, TextTrackCue::CueMatchRules match) const
178 {
179     // Do not call the parent class isEqual here, because we are not cueType() == VTTCue,
180     // and will fail that equality test.
181     if (!TextTrackCue::isEqual(cue, match))
182         return false;
183
184     if (cue.cueType() != TextTrackCue::Generic)
185         return false;
186
187     return cueContentsMatch(cue);
188 }
189
190     
191 bool TextTrackCueGeneric::doesExtendCue(const TextTrackCue& cue) const
192 {
193     if (!cueContentsMatch(cue))
194         return false;
195     
196     return VTTCue::doesExtendCue(cue);
197 }
198
199 bool TextTrackCueGeneric::isOrderedBefore(const TextTrackCue* that) const
200 {
201     if (VTTCue::isOrderedBefore(that))
202         return true;
203
204     if (that->cueType() == Generic && startTime() == that->startTime() && endTime() == that->endTime()) {
205         // Further order generic cues by their calculated line value.
206         std::pair<double, double> thisPosition = getPositionCoordinates();
207         std::pair<double, double> thatPosition = toVTTCue(that)->getPositionCoordinates();
208         return thisPosition.second > thatPosition.second || (thisPosition.second == thatPosition.second && thisPosition.first < thatPosition.first);
209     }
210
211     return false;
212 }
213     
214 } // namespace WebCore
215
216 #endif