OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013, Opera Software ASA. All rights reserved. | 2 * Copyright (c) 2013, Opera Software ASA. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 } | 138 } |
139 | 139 |
140 // Sets inline CSS properties on passed in element if value is not an empty stri
ng | 140 // Sets inline CSS properties on passed in element if value is not an empty stri
ng |
141 static void setInlineStylePropertyIfNotEmpty(Element& element, | 141 static void setInlineStylePropertyIfNotEmpty(Element& element, |
142 CSSPropertyID propertyID, const String& value) | 142 CSSPropertyID propertyID, const String& value) |
143 { | 143 { |
144 if (!value.isEmpty()) | 144 if (!value.isEmpty()) |
145 element.setInlineStyleProperty(propertyID, value); | 145 element.setInlineStyleProperty(propertyID, value); |
146 } | 146 } |
147 | 147 |
148 VTTCueBox::VTTCueBox(Document& document, VTTCue* cue) | 148 VTTCueBox::VTTCueBox(Document& document) |
149 : HTMLDivElement(document) | 149 : HTMLDivElement(document) |
150 , m_cue(cue) | 150 , m_snapToLinesPosition(std::numeric_limits<float>::quiet_NaN()) |
151 { | 151 { |
152 setShadowPseudoId(AtomicString("-webkit-media-text-track-display", AtomicStr
ing::ConstructFromLiteral)); | 152 setShadowPseudoId(AtomicString("-webkit-media-text-track-display", AtomicStr
ing::ConstructFromLiteral)); |
153 } | 153 } |
154 | 154 |
155 void VTTCueBox::applyCSSProperties(const VTTDisplayParameters& displayParameters
) | 155 void VTTCueBox::applyCSSProperties(const VTTDisplayParameters& displayParameters
) |
156 { | 156 { |
157 // FIXME: Apply all the initial CSS positioning properties. http://wkb.ug/79
916 | 157 // http://dev.w3.org/html5/webvtt/#applying-css-properties-to-webvtt-node-ob
jects |
158 if (!m_cue->regionId().isEmpty()) { | |
159 setInlineStyleProperty(CSSPropertyPosition, CSSValueRelative); | |
160 return; | |
161 } | |
162 | 158 |
163 // 3.5.1 On the (root) List of WebVTT Node Objects: | 159 // Initialize the (root) list of WebVTT Node Objects with the following CSS
settings: |
164 | 160 |
165 // the 'position' property must be set to 'absolute' | 161 // the 'position' property must be set to 'absolute' |
166 setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute); | 162 setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute); |
167 | 163 |
168 // the 'unicode-bidi' property must be set to 'plaintext' | 164 // the 'unicode-bidi' property must be set to 'plaintext' |
169 setInlineStyleProperty(CSSPropertyUnicodeBidi, CSSValueWebkitPlaintext); | 165 setInlineStyleProperty(CSSPropertyUnicodeBidi, CSSValueWebkitPlaintext); |
170 | 166 |
171 // the 'direction' property must be set to direction | 167 // the 'direction' property must be set to direction |
172 setInlineStyleProperty(CSSPropertyDirection, displayParameters.direction); | 168 setInlineStyleProperty(CSSPropertyDirection, displayParameters.direction); |
173 | 169 |
174 // the 'writing-mode' property must be set to writing-mode | 170 // the 'writing-mode' property must be set to writing-mode |
175 setInlineStyleProperty(CSSPropertyWebkitWritingMode, displayParameters.writi
ngMode); | 171 setInlineStyleProperty(CSSPropertyWebkitWritingMode, displayParameters.writi
ngMode); |
176 | 172 |
177 const FloatPoint& position = displayParameters.position; | 173 const FloatPoint& position = displayParameters.position; |
178 | 174 |
179 // the 'top' property must be set to top, | 175 // the 'top' property must be set to top, |
180 setInlineStyleProperty(CSSPropertyTop, position.y(), CSSPrimitiveValue::CSS_
PERCENTAGE); | 176 setInlineStyleProperty(CSSPropertyTop, position.y(), CSSPrimitiveValue::CSS_
PERCENTAGE); |
181 | 177 |
182 // the 'left' property must be set to left | 178 // the 'left' property must be set to left |
183 setInlineStyleProperty(CSSPropertyLeft, position.x(), CSSPrimitiveValue::CSS
_PERCENTAGE); | 179 setInlineStyleProperty(CSSPropertyLeft, position.x(), CSSPrimitiveValue::CSS
_PERCENTAGE); |
184 | 180 |
185 // the 'width' property must be set to width, and the 'height' property mus
t be set to height | 181 // the 'width' property must be set to width, and the 'height' property mus
t be set to height |
186 if (m_cue->vertical() == horizontalKeyword()) { | 182 if (displayParameters.writingMode == CSSValueHorizontalTb) { |
187 setInlineStyleProperty(CSSPropertyWidth, displayParameters.size, CSSPrim
itiveValue::CSS_PERCENTAGE); | 183 setInlineStyleProperty(CSSPropertyWidth, displayParameters.size, CSSPrim
itiveValue::CSS_PERCENTAGE); |
188 setInlineStyleProperty(CSSPropertyHeight, CSSValueAuto); | 184 setInlineStyleProperty(CSSPropertyHeight, CSSValueAuto); |
189 } else { | 185 } else { |
190 setInlineStyleProperty(CSSPropertyWidth, CSSValueAuto); | 186 setInlineStyleProperty(CSSPropertyWidth, CSSValueAuto); |
191 setInlineStyleProperty(CSSPropertyHeight, displayParameters.size, CSSPr
imitiveValue::CSS_PERCENTAGE); | 187 setInlineStyleProperty(CSSPropertyHeight, displayParameters.size, CSSPr
imitiveValue::CSS_PERCENTAGE); |
192 } | 188 } |
193 | 189 |
194 // The 'text-align' property on the (root) List of WebVTT Node Objects must | 190 // The 'text-align' property on the (root) List of WebVTT Node Objects must |
195 // be set to the value in the second cell of the row of the table below | 191 // be set to the value in the second cell of the row of the table below |
196 // whose first cell is the value of the corresponding cue's text track cue | 192 // whose first cell is the value of the corresponding cue's text track cue |
197 // alignment: | 193 // alignment: |
198 setInlineStyleProperty(CSSPropertyTextAlign, displayAlignmentMap[m_cue->cueA
lignment()]); | 194 setInlineStyleProperty(CSSPropertyTextAlign, displayParameters.textAlign); |
199 | 195 |
200 if (!m_cue->snapToLines()) { | 196 // TODO(philipj): The position adjustment for non-snap-to-lines cues has |
| 197 // been removed from the spec: |
| 198 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=19178 |
| 199 if (std::isnan(displayParameters.snapToLinesPosition)) { |
201 // 10.13.1 Set up x and y: | 200 // 10.13.1 Set up x and y: |
202 // Note: x and y are set through the CSS left and top above. | 201 // Note: x and y are set through the CSS left and top above. |
203 | 202 |
204 // 10.13.2 Position the boxes in boxes such that the point x% along the | 203 // 10.13.2 Position the boxes in boxes such that the point x% along the |
205 // width of the bounding box of the boxes in boxes is x% of the way | 204 // width of the bounding box of the boxes in boxes is x% of the way |
206 // across the width of the video's rendering area, and the point y% | 205 // across the width of the video's rendering area, and the point y% |
207 // along the height of the bounding box of the boxes in boxes is y% | 206 // along the height of the bounding box of the boxes in boxes is y% |
208 // of the way across the height of the video's rendering area, while | 207 // of the way across the height of the video's rendering area, while |
209 // maintaining the relative positions of the boxes in boxes to each | 208 // maintaining the relative positions of the boxes in boxes to each |
210 // other. | 209 // other. |
211 setInlineStyleProperty(CSSPropertyTransform, | 210 setInlineStyleProperty(CSSPropertyTransform, |
212 String::format("translate(-%.2f%%, -%.2f%%)", position.x(), position
.y())); | 211 String::format("translate(-%.2f%%, -%.2f%%)", position.x(), position
.y())); |
213 | 212 |
214 setInlineStyleProperty(CSSPropertyWhiteSpace, CSSValuePre); | 213 setInlineStyleProperty(CSSPropertyWhiteSpace, CSSValuePre); |
215 } | 214 } |
| 215 |
| 216 // The snap-to-lines position is propagated to LayoutVTTCue. |
| 217 m_snapToLinesPosition = displayParameters.snapToLinesPosition; |
216 } | 218 } |
217 | 219 |
218 LayoutObject* VTTCueBox::createLayoutObject(const ComputedStyle&) | 220 LayoutObject* VTTCueBox::createLayoutObject(const ComputedStyle& style) |
219 { | 221 { |
220 return new LayoutVTTCue(this); | 222 // If WebVTT Regions are used, the regular WebVTT layout algorithm is no |
221 } | 223 // longer necessary, since cues having the region parameter set do not have |
| 224 // any positioning parameters. Also, in this case, the regions themselves |
| 225 // have positioning information. |
| 226 if (style.position() == RelativePosition) |
| 227 return HTMLDivElement::createLayoutObject(style); |
222 | 228 |
223 DEFINE_TRACE(VTTCueBox) | 229 return new LayoutVTTCue(this, m_snapToLinesPosition); |
224 { | |
225 visitor->trace(m_cue); | |
226 HTMLDivElement::trace(visitor); | |
227 } | 230 } |
228 | 231 |
229 VTTCue::VTTCue(Document& document, double startTime, double endTime, const Strin
g& text) | 232 VTTCue::VTTCue(Document& document, double startTime, double endTime, const Strin
g& text) |
230 : TextTrackCue(startTime, endTime) | 233 : TextTrackCue(startTime, endTime) |
231 , m_text(text) | 234 , m_text(text) |
232 , m_linePosition(std::numeric_limits<float>::quiet_NaN()) | 235 , m_linePosition(std::numeric_limits<float>::quiet_NaN()) |
233 , m_textPosition(std::numeric_limits<float>::quiet_NaN()) | 236 , m_textPosition(std::numeric_limits<float>::quiet_NaN()) |
234 , m_cueSize(100) | 237 , m_cueSize(100) |
235 , m_writingDirection(Horizontal) | 238 , m_writingDirection(Horizontal) |
236 , m_cueAlignment(Middle) | 239 , m_cueAlignment(Middle) |
237 , m_vttNodeTree(nullptr) | 240 , m_vttNodeTree(nullptr) |
238 , m_cueBackgroundBox(HTMLDivElement::create(document)) | 241 , m_cueBackgroundBox(HTMLDivElement::create(document)) |
239 , m_snapToLines(true) | 242 , m_snapToLines(true) |
240 , m_displayTreeShouldChange(true) | 243 , m_displayTreeShouldChange(true) |
241 { | 244 { |
242 UseCounter::count(document, UseCounter::VTTCue); | 245 UseCounter::count(document, UseCounter::VTTCue); |
243 m_cueBackgroundBox->setShadowPseudoId(cueShadowPseudoId()); | 246 m_cueBackgroundBox->setShadowPseudoId(cueShadowPseudoId()); |
244 } | 247 } |
245 | 248 |
246 VTTCue::~VTTCue() | 249 VTTCue::~VTTCue() |
247 { | 250 { |
248 // Using oilpan, if m_displayTree is in the document it will strongly keep | |
249 // the cue alive. Thus, if the cue is dead, either m_displayTree is not in | |
250 // the document or the entire document is dead too. | |
251 #if !ENABLE(OILPAN) | |
252 // FIXME: This is scary, we should make the life cycle smarter so the destru
ctor | |
253 // doesn't need to do DOM mutations. | |
254 if (m_displayTree) | |
255 m_displayTree->remove(ASSERT_NO_EXCEPTION); | |
256 #endif | |
257 } | 251 } |
258 | 252 |
259 #ifndef NDEBUG | 253 #ifndef NDEBUG |
260 String VTTCue::toString() const | 254 String VTTCue::toString() const |
261 { | 255 { |
262 return String::format("%p id=%s interval=%f-->%f cue=%s)", this, id().utf8()
.data(), startTime(), endTime(), text().utf8().data()); | 256 return String::format("%p id=%s interval=%f-->%f cue=%s)", this, id().utf8()
.data(), startTime(), endTime(), text().utf8().data()); |
263 } | 257 } |
264 #endif | 258 #endif |
265 | 259 |
266 void VTTCue::cueDidChange() | 260 void VTTCue::cueDidChange() |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 case VTTCue::Right: | 632 case VTTCue::Right: |
639 return VTTCue::End; | 633 return VTTCue::End; |
640 default: | 634 default: |
641 return m_cueAlignment; | 635 return m_cueAlignment; |
642 } | 636 } |
643 } | 637 } |
644 | 638 |
645 VTTDisplayParameters::VTTDisplayParameters() | 639 VTTDisplayParameters::VTTDisplayParameters() |
646 : size(std::numeric_limits<float>::quiet_NaN()) | 640 : size(std::numeric_limits<float>::quiet_NaN()) |
647 , direction(CSSValueNone) | 641 , direction(CSSValueNone) |
648 , writingMode(CSSValueNone) { } | 642 , textAlign(CSSValueNone) |
| 643 , writingMode(CSSValueNone) |
| 644 , snapToLinesPosition(std::numeric_limits<float>::quiet_NaN()) { } |
649 | 645 |
650 VTTDisplayParameters VTTCue::calculateDisplayParameters() const | 646 VTTDisplayParameters VTTCue::calculateDisplayParameters() const |
651 { | 647 { |
652 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings | 648 // http://dev.w3.org/html5/webvtt/#dfn-apply-webvtt-cue-settings |
653 | 649 |
654 VTTDisplayParameters displayParameters; | 650 VTTDisplayParameters displayParameters; |
| 651 |
655 // Steps 1 and 2. | 652 // Steps 1 and 2. |
656 displayParameters.direction = determineTextDirection(m_vttNodeTree.get()); | 653 displayParameters.direction = determineTextDirection(m_vttNodeTree.get()); |
657 | 654 |
658 if (displayParameters.direction == CSSValueRtl) | 655 if (displayParameters.direction == CSSValueRtl) |
659 UseCounter::count(document(), UseCounter::VTTCueRenderRtl); | 656 UseCounter::count(document(), UseCounter::VTTCueRenderRtl); |
660 | 657 |
| 658 // Note: The 'text-align' property is also determined here so that |
| 659 // VTTCueBox::applyCSSProperties need not have access to a VTTCue. |
| 660 displayParameters.textAlign = displayAlignmentMap[cueAlignment()]; |
| 661 |
661 // 3. If the text track cue writing direction is horizontal, then let | 662 // 3. If the text track cue writing direction is horizontal, then let |
662 // block-flow be 'tb'. Otherwise, if the text track cue writing direction is | 663 // block-flow be 'tb'. Otherwise, if the text track cue writing direction is |
663 // vertical growing left, then let block-flow be 'lr'. Otherwise, the text | 664 // vertical growing left, then let block-flow be 'lr'. Otherwise, the text |
664 // track cue writing direction is vertical growing right; let block-flow be | 665 // track cue writing direction is vertical growing right; let block-flow be |
665 // 'rl'. | 666 // 'rl'. |
666 displayParameters.writingMode = displayWritingModeMap[m_writingDirection]; | 667 displayParameters.writingMode = displayWritingModeMap[m_writingDirection]; |
667 | 668 |
668 // Resolve the cue alignment to one of the values {start, end, middle}. | 669 // Resolve the cue alignment to one of the values {start, end, middle}. |
669 CueAlignment computedCueAlignment = calculateComputedCueAlignment(); | 670 CueAlignment computedCueAlignment = calculateComputedCueAlignment(); |
670 | 671 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 displayParameters.position.setX(computedLinePosition); | 741 displayParameters.position.setX(computedLinePosition); |
741 } else { | 742 } else { |
742 if (m_writingDirection == Horizontal) | 743 if (m_writingDirection == Horizontal) |
743 displayParameters.position.setY(0); | 744 displayParameters.position.setY(0); |
744 else | 745 else |
745 displayParameters.position.setX(0); | 746 displayParameters.position.setX(0); |
746 } | 747 } |
747 | 748 |
748 // Step 9 not implemented (margin == 0). | 749 // Step 9 not implemented (margin == 0). |
749 | 750 |
| 751 // The snap-to-lines position is propagated to LayoutVTTCue. |
| 752 displayParameters.snapToLinesPosition = m_snapToLines |
| 753 ? computedLinePosition |
| 754 : std::numeric_limits<float>::quiet_NaN(); |
| 755 |
750 ASSERT(std::isfinite(displayParameters.size)); | 756 ASSERT(std::isfinite(displayParameters.size)); |
751 ASSERT(displayParameters.direction != CSSValueNone); | 757 ASSERT(displayParameters.direction != CSSValueNone); |
752 ASSERT(displayParameters.writingMode != CSSValueNone); | 758 ASSERT(displayParameters.writingMode != CSSValueNone); |
753 return displayParameters; | 759 return displayParameters; |
754 } | 760 } |
755 | 761 |
756 void VTTCue::updatePastAndFutureNodes(double movieTime) | 762 void VTTCue::updatePastAndFutureNodes(double movieTime) |
757 { | 763 { |
758 DEFINE_STATIC_LOCAL(const String, timestampTag, ("timestamp")); | 764 DEFINE_STATIC_LOCAL(const String, timestampTag, ("timestamp")); |
759 | 765 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 toElement(child).setIdAttribute(id()); | 799 toElement(child).setIdAttribute(id()); |
794 } | 800 } |
795 } | 801 } |
796 } | 802 } |
797 | 803 |
798 PassRefPtrWillBeRawPtr<VTTCueBox> VTTCue::getDisplayTree() | 804 PassRefPtrWillBeRawPtr<VTTCueBox> VTTCue::getDisplayTree() |
799 { | 805 { |
800 ASSERT(track() && track()->isRendered() && isActive()); | 806 ASSERT(track() && track()->isRendered() && isActive()); |
801 | 807 |
802 if (!m_displayTree) { | 808 if (!m_displayTree) { |
803 m_displayTree = VTTCueBox::create(document(), this); | 809 m_displayTree = VTTCueBox::create(document()); |
804 m_displayTree->appendChild(m_cueBackgroundBox); | 810 m_displayTree->appendChild(m_cueBackgroundBox); |
805 } | 811 } |
806 | 812 |
807 ASSERT(m_displayTree->firstChild() == m_cueBackgroundBox); | 813 ASSERT(m_displayTree->firstChild() == m_cueBackgroundBox); |
808 | 814 |
809 if (!m_displayTreeShouldChange) { | 815 if (!m_displayTreeShouldChange) { |
810 // Apply updated user style overrides for text tracks when display tree
doesn't change. | 816 // Apply updated user style overrides for text tracks when display tree
doesn't change. |
811 // This ensures that the track settings are refreshed when the video is | 817 // This ensures that the track settings are refreshed when the video is |
812 // replayed or when the user slides back to an already rendered track. | 818 // replayed or when the user slides back to an already rendered track. |
813 applyUserOverrideCSSProperties(); | 819 applyUserOverrideCSSProperties(); |
814 return m_displayTree; | 820 return m_displayTree; |
815 } | 821 } |
816 | 822 |
817 createVTTNodeTree(); | 823 createVTTNodeTree(); |
818 | 824 |
819 m_cueBackgroundBox->removeChildren(); | 825 m_cueBackgroundBox->removeChildren(); |
820 m_vttNodeTree->cloneChildNodes(m_cueBackgroundBox.get()); | 826 m_vttNodeTree->cloneChildNodes(m_cueBackgroundBox.get()); |
821 | 827 |
822 VTTDisplayParameters displayParameters = calculateDisplayParameters(); | 828 // TODO(philipj): The region identifier may be non-empty without there being |
823 m_displayTree->applyCSSProperties(displayParameters); | 829 // a corresponding region, in which case this VTTCueBox will be added |
| 830 // directly to the text track container in updateDisplay(). |
| 831 if (regionId().isEmpty()) { |
| 832 VTTDisplayParameters displayParameters = calculateDisplayParameters(); |
| 833 m_displayTree->applyCSSProperties(displayParameters); |
| 834 } else { |
| 835 m_displayTree->setInlineStyleProperty(CSSPropertyPosition, CSSValueRelat
ive); |
| 836 } |
824 | 837 |
825 // Apply user override settings for text tracks | 838 // Apply user override settings for text tracks |
826 applyUserOverrideCSSProperties(); | 839 applyUserOverrideCSSProperties(); |
827 | 840 |
828 m_displayTreeShouldChange = false; | 841 m_displayTreeShouldChange = false; |
829 | 842 |
830 return m_displayTree; | 843 return m_displayTree; |
831 } | 844 } |
832 | 845 |
833 void VTTCue::removeDisplayTree(RemovalNotification removalNotification) | 846 void VTTCue::removeDisplayTree(RemovalNotification removalNotification) |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 | 1146 |
1134 DEFINE_TRACE(VTTCue) | 1147 DEFINE_TRACE(VTTCue) |
1135 { | 1148 { |
1136 visitor->trace(m_vttNodeTree); | 1149 visitor->trace(m_vttNodeTree); |
1137 visitor->trace(m_cueBackgroundBox); | 1150 visitor->trace(m_cueBackgroundBox); |
1138 visitor->trace(m_displayTree); | 1151 visitor->trace(m_displayTree); |
1139 TextTrackCue::trace(visitor); | 1152 TextTrackCue::trace(visitor); |
1140 } | 1153 } |
1141 | 1154 |
1142 } // namespace blink | 1155 } // namespace blink |
OLD | NEW |