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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 exceptionState.throwDOMException( | 123 exceptionState.throwDOMException( |
124 IndexSizeError, | 124 IndexSizeError, |
125 ExceptionMessages::indexOutsideRange<double>( | 125 ExceptionMessages::indexOutsideRange<double>( |
126 "value", value, 0, ExceptionMessages::InclusiveBound, 100, | 126 "value", value, 0, ExceptionMessages::InclusiveBound, 100, |
127 ExceptionMessages::InclusiveBound)); | 127 ExceptionMessages::InclusiveBound)); |
128 return true; | 128 return true; |
129 } | 129 } |
130 return false; | 130 return false; |
131 } | 131 } |
132 | 132 |
133 // Sets inline CSS properties on passed in element if value is not an empty stri
ng | 133 // Sets inline CSS properties on passed in element if value is not an empty |
| 134 // string. |
134 static void setInlineStylePropertyIfNotEmpty(Element& element, | 135 static void setInlineStylePropertyIfNotEmpty(Element& element, |
135 CSSPropertyID propertyID, | 136 CSSPropertyID propertyID, |
136 const String& value) { | 137 const String& value) { |
137 if (!value.isEmpty()) | 138 if (!value.isEmpty()) |
138 element.setInlineStyleProperty(propertyID, value); | 139 element.setInlineStyleProperty(propertyID, value); |
139 } | 140 } |
140 | 141 |
141 VTTCueBox::VTTCueBox(Document& document) | 142 VTTCueBox::VTTCueBox(Document& document) |
142 : HTMLDivElement(document), | 143 : HTMLDivElement(document), |
143 m_snapToLinesPosition(std::numeric_limits<float>::quiet_NaN()) { | 144 m_snapToLinesPosition(std::numeric_limits<float>::quiet_NaN()) { |
144 setShadowPseudoId(AtomicString("-webkit-media-text-track-display")); | 145 setShadowPseudoId(AtomicString("-webkit-media-text-track-display")); |
145 } | 146 } |
146 | 147 |
147 void VTTCueBox::applyCSSProperties( | 148 void VTTCueBox::applyCSSProperties( |
148 const VTTDisplayParameters& displayParameters) { | 149 const VTTDisplayParameters& displayParameters) { |
149 // http://dev.w3.org/html5/webvtt/#applying-css-properties-to-webvtt-node-obje
cts | 150 // http://dev.w3.org/html5/webvtt/#applying-css-properties-to-webvtt-node-obje
cts |
150 | 151 |
151 // Initialize the (root) list of WebVTT Node Objects with the following CSS se
ttings: | 152 // Initialize the (root) list of WebVTT Node Objects with the following CSS |
| 153 // settings: |
152 | 154 |
153 // the 'position' property must be set to 'absolute' | 155 // the 'position' property must be set to 'absolute' |
154 setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute); | 156 setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute); |
155 | 157 |
156 // the 'unicode-bidi' property must be set to 'plaintext' | 158 // the 'unicode-bidi' property must be set to 'plaintext' |
157 setInlineStyleProperty(CSSPropertyUnicodeBidi, CSSValueWebkitPlaintext); | 159 setInlineStyleProperty(CSSPropertyUnicodeBidi, CSSValueWebkitPlaintext); |
158 | 160 |
159 // the 'direction' property must be set to direction | 161 // the 'direction' property must be set to direction |
160 setInlineStyleProperty(CSSPropertyDirection, displayParameters.direction); | 162 setInlineStyleProperty(CSSPropertyDirection, displayParameters.direction); |
161 | 163 |
162 // the 'writing-mode' property must be set to writing-mode | 164 // the 'writing-mode' property must be set to writing-mode |
163 setInlineStyleProperty(CSSPropertyWebkitWritingMode, | 165 setInlineStyleProperty(CSSPropertyWebkitWritingMode, |
164 displayParameters.writingMode); | 166 displayParameters.writingMode); |
165 | 167 |
166 const FloatPoint& position = displayParameters.position; | 168 const FloatPoint& position = displayParameters.position; |
167 | 169 |
168 // the 'top' property must be set to top, | 170 // the 'top' property must be set to top, |
169 setInlineStyleProperty(CSSPropertyTop, position.y(), | 171 setInlineStyleProperty(CSSPropertyTop, position.y(), |
170 CSSPrimitiveValue::UnitType::Percentage); | 172 CSSPrimitiveValue::UnitType::Percentage); |
171 | 173 |
172 // the 'left' property must be set to left | 174 // the 'left' property must be set to left |
173 setInlineStyleProperty(CSSPropertyLeft, position.x(), | 175 setInlineStyleProperty(CSSPropertyLeft, position.x(), |
174 CSSPrimitiveValue::UnitType::Percentage); | 176 CSSPrimitiveValue::UnitType::Percentage); |
175 | 177 |
176 // the 'width' property must be set to width, and the 'height' property must
be set to height | 178 // the 'width' property must be set to width, and the 'height' property must |
| 179 // be set to height |
177 if (displayParameters.writingMode == CSSValueHorizontalTb) { | 180 if (displayParameters.writingMode == CSSValueHorizontalTb) { |
178 setInlineStyleProperty(CSSPropertyWidth, displayParameters.size, | 181 setInlineStyleProperty(CSSPropertyWidth, displayParameters.size, |
179 CSSPrimitiveValue::UnitType::Percentage); | 182 CSSPrimitiveValue::UnitType::Percentage); |
180 setInlineStyleProperty(CSSPropertyHeight, CSSValueAuto); | 183 setInlineStyleProperty(CSSPropertyHeight, CSSValueAuto); |
181 } else { | 184 } else { |
182 setInlineStyleProperty(CSSPropertyWidth, CSSValueAuto); | 185 setInlineStyleProperty(CSSPropertyWidth, CSSValueAuto); |
183 setInlineStyleProperty(CSSPropertyHeight, displayParameters.size, | 186 setInlineStyleProperty(CSSPropertyHeight, displayParameters.size, |
184 CSSPrimitiveValue::UnitType::Percentage); | 187 CSSPrimitiveValue::UnitType::Percentage); |
185 } | 188 } |
186 | 189 |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 cueWillChange(); | 431 cueWillChange(); |
429 m_cueAlignment = alignment; | 432 m_cueAlignment = alignment; |
430 cueDidChange(); | 433 cueDidChange(); |
431 } | 434 } |
432 | 435 |
433 void VTTCue::setText(const String& text) { | 436 void VTTCue::setText(const String& text) { |
434 if (m_text == text) | 437 if (m_text == text) |
435 return; | 438 return; |
436 | 439 |
437 cueWillChange(); | 440 cueWillChange(); |
438 // Clear the document fragment but don't bother to create it again just yet as
we can do that | 441 // Clear the document fragment but don't bother to create it again just yet as |
439 // when it is requested. | 442 // we can do that when it is requested. |
440 m_vttNodeTree = nullptr; | 443 m_vttNodeTree = nullptr; |
441 m_text = text; | 444 m_text = text; |
442 cueDidChange(); | 445 cueDidChange(); |
443 } | 446 } |
444 | 447 |
445 void VTTCue::createVTTNodeTree() { | 448 void VTTCue::createVTTNodeTree() { |
446 if (!m_vttNodeTree) | 449 if (!m_vttNodeTree) |
447 m_vttNodeTree = | 450 m_vttNodeTree = |
448 VTTParser::createDocumentFragmentFromCueText(document(), m_text); | 451 VTTParser::createDocumentFragmentFromCueText(document(), m_text); |
449 } | 452 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 } | 526 } |
524 | 527 |
525 class VTTTextRunIterator : public TextRunIterator { | 528 class VTTTextRunIterator : public TextRunIterator { |
526 public: | 529 public: |
527 VTTTextRunIterator() {} | 530 VTTTextRunIterator() {} |
528 VTTTextRunIterator(const TextRun* textRun, unsigned offset) | 531 VTTTextRunIterator(const TextRun* textRun, unsigned offset) |
529 : TextRunIterator(textRun, offset) {} | 532 : TextRunIterator(textRun, offset) {} |
530 | 533 |
531 bool atParagraphSeparator() const { | 534 bool atParagraphSeparator() const { |
532 // Within a cue, paragraph boundaries are only denoted by Type B characters, | 535 // Within a cue, paragraph boundaries are only denoted by Type B characters, |
533 // such as U+000A LINE FEED (LF), U+0085 NEXT LINE (NEL), and U+2029 PARAGRA
PH SEPARATOR. | 536 // such as U+000A LINE FEED (LF), U+0085 NEXT LINE (NEL), |
| 537 // and U+2029 PARAGRAPH SEPARATOR. |
534 return WTF::Unicode::category(current()) & | 538 return WTF::Unicode::category(current()) & |
535 WTF::Unicode::Separator_Paragraph; | 539 WTF::Unicode::Separator_Paragraph; |
536 } | 540 } |
537 }; | 541 }; |
538 | 542 |
539 // Almost the same as determineDirectionality in core/html/HTMLElement.cpp, but | 543 // Almost the same as determineDirectionality in core/html/HTMLElement.cpp, but |
540 // that one uses a "plain" TextRunIterator (which only checks for '\n'). | 544 // that one uses a "plain" TextRunIterator (which only checks for '\n'). |
541 static TextDirection determineDirectionality(const String& value, | 545 static TextDirection determineDirectionality(const String& value, |
542 bool& hasStrongDirectionality) { | 546 bool& hasStrongDirectionality) { |
543 TextRun run(value); | 547 TextRun run(value); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 | 583 |
580 float VTTCue::calculateComputedTextPosition() const { | 584 float VTTCue::calculateComputedTextPosition() const { |
581 // http://dev.w3.org/html5/webvtt/#dfn-cue-computed-position | 585 // http://dev.w3.org/html5/webvtt/#dfn-cue-computed-position |
582 | 586 |
583 // 1. If the position is numeric, then return the value of the position and | 587 // 1. If the position is numeric, then return the value of the position and |
584 // abort these steps. (Otherwise, the position is the special value auto.) | 588 // abort these steps. (Otherwise, the position is the special value auto.) |
585 if (!textPositionIsAuto()) | 589 if (!textPositionIsAuto()) |
586 return m_textPosition; | 590 return m_textPosition; |
587 | 591 |
588 switch (m_cueAlignment) { | 592 switch (m_cueAlignment) { |
589 // 2. If the cue text alignment is start or left, return 0 and abort these s
teps. | 593 // 2. If the cue text alignment is start or left, return 0 and abort these |
| 594 // steps. |
590 case Start: | 595 case Start: |
591 case Left: | 596 case Left: |
592 return 0; | 597 return 0; |
593 // 3. If the cue text alignment is end or right, return 100 and abort these
steps. | 598 // 3. If the cue text alignment is end or right, return 100 and abort these |
| 599 // steps. |
594 case End: | 600 case End: |
595 case Right: | 601 case Right: |
596 return 100; | 602 return 100; |
597 // 4. If the cue text alignment is middle, return 50 and abort these steps. | 603 // 4. If the cue text alignment is middle, return 50 and abort these steps. |
598 case Middle: | 604 case Middle: |
599 return 50; | 605 return 50; |
600 default: | 606 default: |
601 NOTREACHED(); | 607 NOTREACHED(); |
602 return 0; | 608 return 0; |
603 } | 609 } |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 DCHECK(track() && track()->isRendered() && isActive()); | 792 DCHECK(track() && track()->isRendered() && isActive()); |
787 | 793 |
788 if (!m_displayTree) { | 794 if (!m_displayTree) { |
789 m_displayTree = VTTCueBox::create(document()); | 795 m_displayTree = VTTCueBox::create(document()); |
790 m_displayTree->appendChild(m_cueBackgroundBox); | 796 m_displayTree->appendChild(m_cueBackgroundBox); |
791 } | 797 } |
792 | 798 |
793 DCHECK_EQ(m_displayTree->firstChild(), m_cueBackgroundBox); | 799 DCHECK_EQ(m_displayTree->firstChild(), m_cueBackgroundBox); |
794 | 800 |
795 if (!m_displayTreeShouldChange) { | 801 if (!m_displayTreeShouldChange) { |
796 // Apply updated user style overrides for text tracks when display tree does
n't change. | 802 // Apply updated user style overrides for text tracks when display tree |
797 // This ensures that the track settings are refreshed when the video is | 803 // doesn't change. This ensures that the track settings are refreshed when |
798 // replayed or when the user slides back to an already rendered track. | 804 // the video is replayed or when the user slides back to an already rendered |
| 805 // track. |
799 applyUserOverrideCSSProperties(); | 806 applyUserOverrideCSSProperties(); |
800 return m_displayTree; | 807 return m_displayTree; |
801 } | 808 } |
802 | 809 |
803 createVTTNodeTree(); | 810 createVTTNodeTree(); |
804 | 811 |
805 m_cueBackgroundBox->removeChildren(); | 812 m_cueBackgroundBox->removeChildren(); |
806 m_vttNodeTree->cloneChildNodes(m_cueBackgroundBox.get()); | 813 m_vttNodeTree->cloneChildNodes(m_cueBackgroundBox.get()); |
807 | 814 |
808 // TODO(foolip): The region identifier may be non-empty without there being | 815 // TODO(foolip): The region identifier may be non-empty without there being |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
862 VTTCueBox* displayBox = getDisplayTree(); | 869 VTTCueBox* displayBox = getDisplayTree(); |
863 VTTRegion* region = 0; | 870 VTTRegion* region = 0; |
864 if (track()->regions()) | 871 if (track()->regions()) |
865 region = track()->regions()->getRegionById(regionId()); | 872 region = track()->regions()->getRegionById(regionId()); |
866 | 873 |
867 if (!region) { | 874 if (!region) { |
868 // If cue has an empty region identifier or there is no WebVTT region | 875 // If cue has an empty region identifier or there is no WebVTT region |
869 // whose region identifier is identical to cue's region identifier, run | 876 // whose region identifier is identical to cue's region identifier, run |
870 // the following substeps: | 877 // the following substeps: |
871 if (displayBox->hasChildren() && !container.contains(displayBox)) { | 878 if (displayBox->hasChildren() && !container.contains(displayBox)) { |
872 // Note: the display tree of a cue is removed when the active flag of the
cue is unset. | 879 // Note: the display tree of a cue is removed when the active flag of the |
| 880 // cue is unset. |
873 container.appendChild(displayBox); | 881 container.appendChild(displayBox); |
874 } | 882 } |
875 } else { | 883 } else { |
876 // Let region be the WebVTT region whose region identifier matches the | 884 // Let region be the WebVTT region whose region identifier matches the |
877 // region identifier of cue. | 885 // region identifier of cue. |
878 HTMLDivElement* regionNode = region->getDisplayTree(document()); | 886 HTMLDivElement* regionNode = region->getDisplayTree(document()); |
879 | 887 |
880 // Append the region to the viewport, if it was not already. | 888 // Append the region to the viewport, if it was not already. |
881 if (!container.contains(regionNode)) | 889 if (!container.contains(regionNode)) |
882 container.appendChild(regionNode); | 890 container.appendChild(regionNode); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 // number. Let that number be the percentage. | 931 // number. Let that number be the percentage. |
924 // 8. If percentage is outside the range 0..100, then fail. | 932 // 8. If percentage is outside the range 0..100, then fail. |
925 // 9. Return percentage. | 933 // 9. Return percentage. |
926 return input.scanPercentage(number) && !isInvalidPercentage(number); | 934 return input.scanPercentage(number) && !isInvalidPercentage(number); |
927 } | 935 } |
928 | 936 |
929 void VTTCue::parseSettings(const String& inputString) { | 937 void VTTCue::parseSettings(const String& inputString) { |
930 VTTScanner input(inputString); | 938 VTTScanner input(inputString); |
931 | 939 |
932 while (!input.isAtEnd()) { | 940 while (!input.isAtEnd()) { |
933 // The WebVTT cue settings part of a WebVTT cue consists of zero or more of
the following components, in any order, | 941 // The WebVTT cue settings part of a WebVTT cue consists of zero or more of |
934 // separated from each other by one or more U+0020 SPACE characters or U+000
9 CHARACTER TABULATION (tab) characters. | 942 // the following components, in any order, separated from each other by one |
| 943 // or more U+0020 SPACE characters or U+0009 CHARACTER TABULATION (tab) |
| 944 // characters. |
935 input.skipWhile<VTTParser::isValidSettingDelimiter>(); | 945 input.skipWhile<VTTParser::isValidSettingDelimiter>(); |
936 | 946 |
937 if (input.isAtEnd()) | 947 if (input.isAtEnd()) |
938 break; | 948 break; |
939 | 949 |
940 // When the user agent is to parse the WebVTT settings given by a string inp
ut for a text track cue cue, | 950 // When the user agent is to parse the WebVTT settings given by a string |
| 951 // input for a text track cue cue, |
941 // the user agent must run the following steps: | 952 // the user agent must run the following steps: |
942 // 1. Let settings be the result of splitting input on spaces. | 953 // 1. Let settings be the result of splitting input on spaces. |
943 // 2. For each token setting in the list settings, run the following substep
s: | 954 // 2. For each token setting in the list settings, run the following |
944 // 1. If setting does not contain a U+003A COLON character (:), or if the
first U+003A COLON character (:) | 955 // substeps: |
945 // in setting is either the first or last character of setting, then j
ump to the step labeled next setting. | 956 // 1. If setting does not contain a U+003A COLON character (:), or if the |
946 // 2. Let name be the leading substring of setting up to and excluding th
e first U+003A COLON character (:) in that string. | 957 // first U+003A COLON character (:) in setting is either the first or |
| 958 // last character of setting, then jump to the step labeled next |
| 959 // setting. |
| 960 // 2. Let name be the leading substring of setting up to and excluding |
| 961 // the first U+003A COLON character (:) in that string. |
947 CueSetting name = settingName(input); | 962 CueSetting name = settingName(input); |
948 | 963 |
949 // 3. Let value be the trailing substring of setting starting from the chara
cter immediately after the first U+003A COLON character (:) in that string. | 964 // 3. Let value be the trailing substring of setting starting from the |
| 965 // character immediately after the first U+003A COLON character (:) in |
| 966 // that string. |
950 VTTScanner::Run valueRun = | 967 VTTScanner::Run valueRun = |
951 input.collectUntil<VTTParser::isValidSettingDelimiter>(); | 968 input.collectUntil<VTTParser::isValidSettingDelimiter>(); |
952 | 969 |
953 // 4. Run the appropriate substeps that apply for the value of name, as foll
ows: | 970 // 4. Run the appropriate substeps that apply for the value of name, as |
| 971 // follows: |
954 switch (name) { | 972 switch (name) { |
955 case Vertical: { | 973 case Vertical: { |
956 // If name is a case-sensitive match for "vertical" | 974 // If name is a case-sensitive match for "vertical" |
957 // 1. If value is a case-sensitive match for the string "rl", then | 975 // 1. If value is a case-sensitive match for the string "rl", then |
958 // let cue's WebVTT cue writing direction be vertical | 976 // let cue's WebVTT cue writing direction be vertical |
959 // growing left. | 977 // growing left. |
960 if (input.scanRun(valueRun, verticalGrowingLeftKeyword())) | 978 if (input.scanRun(valueRun, verticalGrowingLeftKeyword())) |
961 m_writingDirection = VerticalGrowingLeft; | 979 m_writingDirection = VerticalGrowingLeft; |
962 | 980 |
963 // 2. Otherwise, if value is a case-sensitive match for the string | 981 // 2. Otherwise, if value is a case-sensitive match for the string |
964 // "lr", then let cue's WebVTT cue writing direction be | 982 // "lr", then let cue's WebVTT cue writing direction be |
965 // vertical growing right. | 983 // vertical growing right. |
966 else if (input.scanRun(valueRun, verticalGrowingRightKeyword())) | 984 else if (input.scanRun(valueRun, verticalGrowingRightKeyword())) |
967 m_writingDirection = VerticalGrowingRight; | 985 m_writingDirection = VerticalGrowingRight; |
968 break; | 986 break; |
969 } | 987 } |
970 case Line: { | 988 case Line: { |
971 // If name is a case-sensitive match for "line" | 989 // If name is a case-sensitive match for "line" |
972 // Steps 1 - 2 skipped. | 990 // Steps 1 - 2 skipped. |
973 float number; | 991 float number; |
974 // 3. If linepos does not contain at least one ASCII digit, then | 992 // 3. If linepos does not contain at least one ASCII digit, then |
975 // jump to the step labeled next setting. | 993 // jump to the step labeled next setting. |
976 // 4. If the last character in linepos is a U+0025 PERCENT SIGN characte
r (%) | 994 // 4. If the last character in linepos is a U+0025 PERCENT SIGN |
| 995 // character (%) |
977 // | 996 // |
978 // If parse a percentage string from linepos doesn't fail, let | 997 // If parse a percentage string from linepos doesn't fail, let |
979 // number be the returned percentage, otherwise jump to the step | 998 // number be the returned percentage, otherwise jump to the step |
980 // labeled next setting. | 999 // labeled next setting. |
981 bool isPercentage = scanPercentage(input, number); | 1000 bool isPercentage = scanPercentage(input, number); |
982 if (!isPercentage) { | 1001 if (!isPercentage) { |
983 // Otherwise | 1002 // Otherwise |
984 // | 1003 // |
985 // 1. If linepos contains any characters other than U+002D | 1004 // 1. If linepos contains any characters other than U+002D |
986 // HYPHEN-MINUS characters (-) and ASCII digits, then jump to | 1005 // HYPHEN-MINUS characters (-) and ASCII digits, then jump to |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1120 } | 1139 } |
1121 | 1140 |
1122 DEFINE_TRACE(VTTCue) { | 1141 DEFINE_TRACE(VTTCue) { |
1123 visitor->trace(m_vttNodeTree); | 1142 visitor->trace(m_vttNodeTree); |
1124 visitor->trace(m_cueBackgroundBox); | 1143 visitor->trace(m_cueBackgroundBox); |
1125 visitor->trace(m_displayTree); | 1144 visitor->trace(m_displayTree); |
1126 TextTrackCue::trace(visitor); | 1145 TextTrackCue::trace(visitor); |
1127 } | 1146 } |
1128 | 1147 |
1129 } // namespace blink | 1148 } // namespace blink |
OLD | NEW |