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 26 matching lines...) Expand all Loading... | |
37 #include "bindings/v8/ExceptionStatePlaceholder.h" | 37 #include "bindings/v8/ExceptionStatePlaceholder.h" |
38 #include "core/dom/DocumentFragment.h" | 38 #include "core/dom/DocumentFragment.h" |
39 #include "core/dom/NodeTraversal.h" | 39 #include "core/dom/NodeTraversal.h" |
40 #include "core/events/Event.h" | 40 #include "core/events/Event.h" |
41 #include "core/html/HTMLDivElement.h" | 41 #include "core/html/HTMLDivElement.h" |
42 #include "core/html/track/TextTrack.h" | 42 #include "core/html/track/TextTrack.h" |
43 #include "core/html/track/TextTrackCueList.h" | 43 #include "core/html/track/TextTrackCueList.h" |
44 #include "core/html/track/vtt/VTTElement.h" | 44 #include "core/html/track/vtt/VTTElement.h" |
45 #include "core/html/track/vtt/VTTParser.h" | 45 #include "core/html/track/vtt/VTTParser.h" |
46 #include "core/html/track/vtt/VTTRegionList.h" | 46 #include "core/html/track/vtt/VTTRegionList.h" |
47 #include "core/html/track/vtt/VTTScanner.h" | |
47 #include "core/rendering/RenderVTTCue.h" | 48 #include "core/rendering/RenderVTTCue.h" |
48 #include "platform/text/BidiResolver.h" | 49 #include "platform/text/BidiResolver.h" |
49 #include "platform/text/TextRunIterator.h" | 50 #include "platform/text/TextRunIterator.h" |
50 #include "wtf/MathExtras.h" | 51 #include "wtf/MathExtras.h" |
51 #include "wtf/text/StringBuilder.h" | 52 #include "wtf/text/StringBuilder.h" |
52 | 53 |
53 namespace WebCore { | 54 namespace WebCore { |
54 | 55 |
55 static const int undefinedPosition = -1; | 56 static const int undefinedPosition = -1; |
56 | 57 |
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
826 coordinates.second = m_textPosition; | 827 coordinates.second = m_textPosition; |
827 | 828 |
828 return coordinates; | 829 return coordinates; |
829 } | 830 } |
830 | 831 |
831 ASSERT_NOT_REACHED(); | 832 ASSERT_NOT_REACHED(); |
832 | 833 |
833 return coordinates; | 834 return coordinates; |
834 } | 835 } |
835 | 836 |
836 VTTCue::CueSetting VTTCue::settingName(const String& name) | 837 VTTCue::CueSetting VTTCue::settingName(VTTScanner& input) |
837 { | 838 { |
838 DEFINE_STATIC_LOCAL(const String, verticalKeyword, ("vertical")); | 839 CueSetting parsedSetting = None; |
839 DEFINE_STATIC_LOCAL(const String, lineKeyword, ("line")); | 840 if (input.scan("vertical")) |
840 DEFINE_STATIC_LOCAL(const String, positionKeyword, ("position")); | 841 parsedSetting = Vertical; |
841 DEFINE_STATIC_LOCAL(const String, sizeKeyword, ("size")); | 842 else if (input.scan("line")) |
842 DEFINE_STATIC_LOCAL(const String, alignKeyword, ("align")); | 843 parsedSetting = Line; |
843 DEFINE_STATIC_LOCAL(const String, regionIdKeyword, ("region")); | 844 else if (input.scan("position")) |
844 | 845 parsedSetting = Position; |
845 if (name == verticalKeyword) | 846 else if (input.scan("size")) |
846 return Vertical; | 847 parsedSetting = Size; |
847 if (name == lineKeyword) | 848 else if (input.scan("align")) |
848 return Line; | 849 parsedSetting = Align; |
849 if (name == positionKeyword) | 850 else if (RuntimeEnabledFeatures::webVTTRegionsEnabled() && input.scan("regio n")) |
850 return Position; | 851 parsedSetting = RegionId; |
851 if (name == sizeKeyword) | 852 // Verify that a ':' follows. |
852 return Size; | 853 if (parsedSetting != None && input.scan(':')) |
853 if (name == alignKeyword) | 854 return parsedSetting; |
854 return Align; | |
855 if (RuntimeEnabledFeatures::webVTTRegionsEnabled() && name == regionIdKeywor d) | |
856 return RegionId; | |
857 | |
858 return None; | 855 return None; |
859 } | 856 } |
860 | 857 |
861 // Used for 'position' and 'size'. | 858 // Used for 'position' and 'size'. |
862 static bool scanPercentage(const String& input, unsigned* position, int& number) | 859 static bool scanPercentage(VTTScanner& input, const VTTScanner::Run& valueRun, i nt& number) |
863 { | 860 { |
864 ASSERT(position); | |
865 // 1. If value contains any characters other than U+0025 PERCENT SIGN | 861 // 1. If value contains any characters other than U+0025 PERCENT SIGN |
866 // characters (%) and characters in the range U+0030 DIGIT ZERO (0) to | 862 // characters (%) and characters in the range U+0030 DIGIT ZERO (0) to |
867 // U+0039 DIGIT NINE (9), then jump to the step labeled next setting. | 863 // U+0039 DIGIT NINE (9), then jump to the step labeled next setting. |
868 // 2. If value does not contain at least one character in the range U+0030 | 864 // 2. If value does not contain at least one character in the range U+0030 |
869 // DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then jump to the step | 865 // DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then jump to the step |
870 // labeled next setting. | 866 // labeled next setting. |
871 if (!VTTParser::collectDigitsToInt(input, position, number)) | 867 if (!input.scanDigits(number)) |
872 return false; | |
873 if (*position >= input.length()) | |
874 return false; | 868 return false; |
875 | 869 |
876 // 3. If any character in value other than the last character is a U+0025 | 870 // 3. If any character in value other than the last character is a U+0025 |
877 // PERCENT SIGN character (%), then jump to the step labeled next | 871 // PERCENT SIGN character (%), then jump to the step labeled next |
878 // setting. | 872 // setting. |
879 // 4. If the last character in value is not a U+0025 PERCENT SIGN character | 873 // 4. If the last character in value is not a U+0025 PERCENT SIGN character |
880 // (%), then jump to the step labeled next setting. | 874 // (%), then jump to the step labeled next setting. |
881 if (input[(*position)++] != '%') | 875 if (!input.scan('%') || !input.isAt(valueRun.end())) |
882 return false; | |
883 if (*position < input.length() && !VTTParser::isValidSettingDelimiter(input[ *position])) | |
884 return false; | 876 return false; |
885 | 877 |
886 // 5. Ignoring the trailing percent sign, interpret value as an integer, | 878 // 5. Ignoring the trailing percent sign, interpret value as an integer, |
887 // and let number be that number. | 879 // and let number be that number. |
888 // 6. If number is not in the range 0 ≤ number ≤ 100, then jump to the step | 880 // 6. If number is not in the range 0 ≤ number ≤ 100, then jump to the step |
889 // labeled next setting. | 881 // labeled next setting. |
890 return number >= 0 && number <= 100; | 882 return number >= 0 && number <= 100; |
891 } | 883 } |
892 | 884 |
893 void VTTCue::parseSettings(const String& input) | 885 void VTTCue::parseSettings(const String& inputString) |
894 { | 886 { |
895 unsigned position = 0; | 887 VTTScanner input(inputString); |
896 | 888 |
897 while (position < input.length()) { | 889 while (!input.isAtEnd()) { |
898 | 890 |
899 // The WebVTT cue settings part of a WebVTT cue consists of zero or more of the following components, in any order, | 891 // The WebVTT cue settings part of a WebVTT cue consists of zero or more of the following components, in any order, |
900 // separated from each other by one or more U+0020 SPACE characters or U +0009 CHARACTER TABULATION (tab) characters. | 892 // separated from each other by one or more U+0020 SPACE characters or U +0009 CHARACTER TABULATION (tab) characters. |
901 while (position < input.length() && VTTParser::isValidSettingDelimiter(i nput[position])) | 893 input.skipWhile<VTTParser::isValidSettingDelimiter>(); |
902 position++; | 894 |
903 if (position >= input.length()) | 895 if (input.isAtEnd()) |
904 break; | 896 break; |
905 | 897 |
906 // When the user agent is to parse the WebVTT settings given by a string input for a text track cue cue, | 898 // When the user agent is to parse the WebVTT settings given by a string input for a text track cue cue, |
907 // the user agent must run the following steps: | 899 // the user agent must run the following steps: |
908 // 1. Let settings be the result of splitting input on spaces. | 900 // 1. Let settings be the result of splitting input on spaces. |
909 // 2. For each token setting in the list settings, run the following sub steps: | 901 // 2. For each token setting in the list settings, run the following sub steps: |
910 // 1. If setting does not contain a U+003A COLON character (:), or if the first U+003A COLON character (:) | 902 // 1. If setting does not contain a U+003A COLON character (:), or if the first U+003A COLON character (:) |
911 // in setting is either the first or last character of setting, th en jump to the step labeled next setting. | 903 // in setting is either the first or last character of setting, th en jump to the step labeled next setting. |
912 unsigned endOfSetting = position; | 904 // 2. Let name be the leading substring of setting up to and excludin g the first U+003A COLON character (:) in that string. |
913 String setting = VTTParser::collectWord(input, &endOfSetting); | 905 CueSetting name = settingName(input); |
914 CueSetting name; | |
915 size_t colonOffset = setting.find(':', 1); | |
916 if (colonOffset == kNotFound || !colonOffset || colonOffset == setting.l ength() - 1) | |
917 goto NextSetting; | |
918 | |
919 // 2. Let name be the leading substring of setting up to and excluding t he first U+003A COLON character (:) in that string. | |
920 name = settingName(setting.substring(0, colonOffset)); | |
921 | 906 |
922 // 3. Let value be the trailing substring of setting starting from the c haracter immediately after the first U+003A COLON character (:) in that string. | 907 // 3. Let value be the trailing substring of setting starting from the c haracter immediately after the first U+003A COLON character (:) in that string. |
923 position += colonOffset + 1; | 908 VTTScanner::Run valueRun = input.collectUntil<VTTParser::isValidSettingD elimiter>(); |
924 if (position >= input.length()) | |
925 break; | |
926 | 909 |
927 // 4. Run the appropriate substeps that apply for the value of name, as follows: | 910 // 4. Run the appropriate substeps that apply for the value of name, as follows: |
928 switch (name) { | 911 switch (name) { |
929 case Vertical: { | 912 case Vertical: { |
930 // If name is a case-sensitive match for "vertical" | 913 // If name is a case-sensitive match for "vertical" |
931 // 1. If value is a case-sensitive match for the string "rl", then l et cue's text track cue writing direction | 914 // 1. If value is a case-sensitive match for the string "rl", then l et cue's text track cue writing direction |
932 // be vertical growing left. | 915 // be vertical growing left. |
933 String writingDirection = VTTParser::collectWord(input, &position); | 916 if (input.scanRun(valueRun, verticalGrowingLeftKeyword())) |
934 if (writingDirection == verticalGrowingLeftKeyword()) | |
935 m_writingDirection = VerticalGrowingLeft; | 917 m_writingDirection = VerticalGrowingLeft; |
936 | 918 |
937 // 2. Otherwise, if value is a case-sensitive match for the string " lr", then let cue's text track cue writing | 919 // 2. Otherwise, if value is a case-sensitive match for the string " lr", then let cue's text track cue writing |
938 // direction be vertical growing right. | 920 // direction be vertical growing right. |
939 else if (writingDirection == verticalGrowingRightKeyword()) | 921 else if (input.scanRun(valueRun, verticalGrowingRightKeyword())) |
940 m_writingDirection = VerticalGrowingRight; | 922 m_writingDirection = VerticalGrowingRight; |
941 break; | 923 break; |
942 } | 924 } |
943 case Line: { | 925 case Line: { |
944 // 1-2 - Collect chars that are either '-', '%', or a digit. | 926 // 1-2 - Collect chars that are either '-', '%', or a digit. |
945 // 1. If value contains any characters other than U+002D HYPHEN-MINU S characters (-), U+0025 PERCENT SIGN | 927 // 1. If value contains any characters other than U+002D HYPHEN-MINU S characters (-), U+0025 PERCENT SIGN |
946 // characters (%), and characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then jump | 928 // characters (%), and characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then jump |
947 // to the step labeled next setting. | 929 // to the step labeled next setting. |
948 StringBuilder linePositionBuilder; | 930 bool isNegative = input.scan('-'); |
949 while (position < input.length() && (input[position] == '-' || input [position] == '%' || isASCIIDigit(input[position]))) | 931 int linePosition; |
950 linePositionBuilder.append(input[position++]); | 932 unsigned numDigits = input.scanDigits(linePosition); |
951 if (position < input.length() && !VTTParser::isValidSettingDelimiter (input[position])) | 933 bool isPercentage = input.scan('%'); |
934 | |
935 if (!input.isAt(valueRun.end())) | |
952 break; | 936 break; |
953 | 937 |
954 // 2. If value does not contain at least one character in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT | 938 // 2. If value does not contain at least one character in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT |
955 // NINE (9), then jump to the step labeled next setting. | 939 // NINE (9), then jump to the step labeled next setting. |
956 // 3. If any character in value other than the first character is a U+002D HYPHEN-MINUS character (-), then | 940 // 3. If any character in value other than the first character is a U+002D HYPHEN-MINUS character (-), then |
957 // jump to the step labeled next setting. | 941 // jump to the step labeled next setting. |
958 // 4. If any character in value other than the last character is a U +0025 PERCENT SIGN character (%), then | 942 // 4. If any character in value other than the last character is a U +0025 PERCENT SIGN character (%), then |
959 // jump to the step labeled next setting. | 943 // jump to the step labeled next setting. |
960 String linePosition = linePositionBuilder.toString(); | |
961 if (linePosition.find('-', 1) != kNotFound || linePosition.reverseFi nd("%", linePosition.length() - 2) != kNotFound) | |
962 break; | |
963 | 944 |
964 // 5. If the first character in value is a U+002D HYPHEN-MINUS chara cter (-) and the last character in value is a | 945 // 5. If the first character in value is a U+002D HYPHEN-MINUS chara cter (-) and the last character in value is a |
965 // U+0025 PERCENT SIGN character (%), then jump to the step label ed next setting. | 946 // U+0025 PERCENT SIGN character (%), then jump to the step label ed next setting. |
966 if (linePosition[0] == '-' && linePosition[linePosition.length() - 1 ] == '%') | 947 if (!numDigits || (isPercentage && isNegative)) |
967 break; | 948 break; |
968 | 949 |
969 // 6. Ignoring the trailing percent sign, if any, interpret value as a (potentially signed) integer, and | 950 // 6. Ignoring the trailing percent sign, if any, interpret value as a (potentially signed) integer, and |
970 // let number be that number. | 951 // let number be that number. |
971 // NOTE: toInt ignores trailing non-digit characters, such as '%'. | |
972 bool validNumber; | |
973 int number = linePosition.toInt(&validNumber); | |
974 if (!validNumber) | |
975 break; | |
976 | |
977 // 7. If the last character in value is a U+0025 PERCENT SIGN charac ter (%), but number is not in the range | 952 // 7. If the last character in value is a U+0025 PERCENT SIGN charac ter (%), but number is not in the range |
978 // 0 ≤ number ≤ 100, then jump to the step labeled next setting. | 953 // 0 ≤ number ≤ 100, then jump to the step labeled next setting. |
979 // 8. Let cue's text track cue line position be number. | 954 // 8. Let cue's text track cue line position be number. |
980 // 9. If the last character in value is a U+0025 PERCENT SIGN charac ter (%), then let cue's text track cue | 955 // 9. If the last character in value is a U+0025 PERCENT SIGN charac ter (%), then let cue's text track cue |
981 // snap-to-lines flag be false. Otherwise, let it be true. | 956 // snap-to-lines flag be false. Otherwise, let it be true. |
982 if (linePosition[linePosition.length() - 1] == '%') { | 957 if (isPercentage) { |
983 if (number < 0 || number > 100) | 958 if (linePosition < 0 || linePosition > 100) |
984 break; | 959 break; |
985 | |
986 // 10 - If '%' then set snap-to-lines flag to false. | 960 // 10 - If '%' then set snap-to-lines flag to false. |
987 m_snapToLines = false; | 961 m_snapToLines = false; |
962 } else { | |
963 if (isNegative) | |
964 linePosition = -linePosition; | |
Mike West
2014/01/13 07:24:20
Where does this come into play? I don't see it in
fs
2014/01/13 08:12:01
In the old code this was handled by toInt (line 97
| |
965 m_snapToLines = true; | |
988 } | 966 } |
989 | 967 m_linePosition = linePosition; |
990 m_linePosition = number; | |
991 break; | 968 break; |
992 } | 969 } |
993 case Position: { | 970 case Position: { |
994 int number; | 971 int number; |
995 // Steps 1 - 6. | 972 // Steps 1 - 6. |
996 if (!scanPercentage(input, &position, number)) | 973 if (!scanPercentage(input, valueRun, number)) |
997 break; | 974 break; |
998 | 975 |
999 // 7. Let cue's text track cue text position be number. | 976 // 7. Let cue's text track cue text position be number. |
1000 m_textPosition = number; | 977 m_textPosition = number; |
1001 break; | 978 break; |
1002 } | 979 } |
1003 case Size: { | 980 case Size: { |
1004 int number; | 981 int number; |
1005 // Steps 1 - 6. | 982 // Steps 1 - 6. |
1006 if (!scanPercentage(input, &position, number)) | 983 if (!scanPercentage(input, valueRun, number)) |
1007 break; | 984 break; |
1008 | 985 |
1009 // 7. Let cue's text track cue size be number. | 986 // 7. Let cue's text track cue size be number. |
1010 m_cueSize = number; | 987 m_cueSize = number; |
1011 break; | 988 break; |
1012 } | 989 } |
1013 case Align: { | 990 case Align: { |
1014 String cueAlignment = VTTParser::collectWord(input, &position); | |
1015 | |
1016 // 1. If value is a case-sensitive match for the string "start", the n let cue's text track cue alignment be start alignment. | 991 // 1. If value is a case-sensitive match for the string "start", the n let cue's text track cue alignment be start alignment. |
1017 if (cueAlignment == startKeyword()) | 992 if (input.scanRun(valueRun, startKeyword())) |
1018 m_cueAlignment = Start; | 993 m_cueAlignment = Start; |
1019 | 994 |
1020 // 2. If value is a case-sensitive match for the string "middle", th en let cue's text track cue alignment be middle alignment. | 995 // 2. If value is a case-sensitive match for the string "middle", th en let cue's text track cue alignment be middle alignment. |
1021 else if (cueAlignment == middleKeyword()) | 996 else if (input.scanRun(valueRun, middleKeyword())) |
1022 m_cueAlignment = Middle; | 997 m_cueAlignment = Middle; |
1023 | 998 |
1024 // 3. If value is a case-sensitive match for the string "end", then let cue's text track cue alignment be end alignment. | 999 // 3. If value is a case-sensitive match for the string "end", then let cue's text track cue alignment be end alignment. |
1025 else if (cueAlignment == endKeyword()) | 1000 else if (input.scanRun(valueRun, endKeyword())) |
1026 m_cueAlignment = End; | 1001 m_cueAlignment = End; |
1027 | 1002 |
1028 // 4. If value is a case-sensitive match for the string "left", then let cue's text track cue alignment be left alignment. | 1003 // 4. If value is a case-sensitive match for the string "left", then let cue's text track cue alignment be left alignment. |
1029 else if (cueAlignment == leftKeyword()) | 1004 else if (input.scanRun(valueRun, leftKeyword())) |
1030 m_cueAlignment = Left; | 1005 m_cueAlignment = Left; |
1031 | 1006 |
1032 // 5. If value is a case-sensitive match for the string "right", the n let cue's text track cue alignment be right alignment. | 1007 // 5. If value is a case-sensitive match for the string "right", the n let cue's text track cue alignment be right alignment. |
1033 else if (cueAlignment == rightKeyword()) | 1008 else if (input.scanRun(valueRun, rightKeyword())) |
1034 m_cueAlignment = Right; | 1009 m_cueAlignment = Right; |
1035 break; | 1010 break; |
1036 } | 1011 } |
1037 case RegionId: | 1012 case RegionId: |
1038 m_regionId = VTTParser::collectWord(input, &position); | 1013 m_regionId = input.extractString(valueRun); |
1039 break; | 1014 break; |
1040 case None: | 1015 case None: |
1041 break; | 1016 break; |
1042 } | 1017 } |
1043 | 1018 |
1044 NextSetting: | 1019 // Make sure the entire run is consumed. |
1045 position = endOfSetting; | 1020 input.skipRun(valueRun); |
1046 } | 1021 } |
1047 | 1022 |
1048 // If cue's line position is not auto or cue's size is not 100 or cue's | 1023 // If cue's line position is not auto or cue's size is not 100 or cue's |
1049 // writing direction is not horizontal, but cue's region identifier is not | 1024 // writing direction is not horizontal, but cue's region identifier is not |
1050 // the empty string, let cue's region identifier be the empty string. | 1025 // the empty string, let cue's region identifier be the empty string. |
1051 if (m_regionId.isEmpty()) | 1026 if (m_regionId.isEmpty()) |
1052 return; | 1027 return; |
1053 | 1028 |
1054 if (m_linePosition != undefinedPosition || m_cueSize != 100 || m_writingDire ction != Horizontal) | 1029 if (m_linePosition != undefinedPosition || m_cueSize != 100 || m_writingDire ction != Horizontal) |
1055 m_regionId = emptyString(); | 1030 m_regionId = emptyString(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1089 return m_cueBackgroundBox->executionContext(); | 1064 return m_cueBackgroundBox->executionContext(); |
1090 } | 1065 } |
1091 | 1066 |
1092 Document& VTTCue::document() const | 1067 Document& VTTCue::document() const |
1093 { | 1068 { |
1094 ASSERT(m_cueBackgroundBox); | 1069 ASSERT(m_cueBackgroundBox); |
1095 return m_cueBackgroundBox->document(); | 1070 return m_cueBackgroundBox->document(); |
1096 } | 1071 } |
1097 | 1072 |
1098 } // namespace WebCore | 1073 } // namespace WebCore |
OLD | NEW |