// Used for 'position' and 'size'. static bool scanPercentage(VTTScanner& input, const VTTScanner::Run& valueRun, int& number) { // 1. If value contains any characters other than U+0025 PERCENT SIGN // characters (%) and characters in the range U+0030 DIGIT ZERO (0) to // U+0039 DIGIT NINE (9), then jump to the step labeled next setting. // 2. If value does not contain at least one character in the range U+0030 // DIGIT ZERO (0) to U+0039 DIGIT NINE (9), then jump to the step // labeled next setting. if (!input.scanDigits(number)) return false; // 3. If any character in value other than the last character is a U+0025 // PERCENT SIGN character (%), then jump to the step labeled next // setting. // 4. If the last character in value is not a U+0025 PERCENT SIGN character // (%), then jump to the step labeled next setting. if (!input.scan('%') || !input.isAt(valueRun.end())) return false; // 5. Ignoring the trailing percent sign, interpret value as an integer, // and let number be that number. // 6. If number is not in the range 0 ≤ number ≤ 100, then jump to the step // labeled next setting. return number >= 0 && number <= 100; }
void VTTRegion::parseSettingValue(RegionSetting setting, VTTScanner& input) { DEFINE_STATIC_LOCAL(const AtomicString, scrollUpValueKeyword, ("up", AtomicString::ConstructFromLiteral)); VTTScanner::Run valueRun = input.collectUntil<VTTParser::isASpace>(); switch (setting) { case Id: { String stringValue = input.extractString(valueRun); if (stringValue.find("-->") == kNotFound) m_id = stringValue; break; } case Width: { float floatWidth; if (VTTParser::parseFloatPercentageValue(input, floatWidth) && parsedEntireRun(input, valueRun)) m_width = floatWidth; else WTF_LOG(Media, "VTTRegion::parseSettingValue, invalid Width"); break; } case Height: { int number; if (input.scanDigits(number) && parsedEntireRun(input, valueRun)) m_heightInLines = number; else WTF_LOG(Media, "VTTRegion::parseSettingValue, invalid Height"); break; } case RegionAnchor: { FloatPoint anchor; if (VTTParser::parseFloatPercentageValuePair(input, ',', anchor) && parsedEntireRun(input, valueRun)) m_regionAnchor = anchor; else WTF_LOG(Media, "VTTRegion::parseSettingValue, invalid RegionAnchor"); break; } case ViewportAnchor: { FloatPoint anchor; if (VTTParser::parseFloatPercentageValuePair(input, ',', anchor) && parsedEntireRun(input, valueRun)) m_viewportAnchor = anchor; else WTF_LOG(Media, "VTTRegion::parseSettingValue, invalid ViewportAnchor"); break; } case Scroll: if (input.scanRun(valueRun, scrollUpValueKeyword)) m_scroll = true; else WTF_LOG(Media, "VTTRegion::parseSettingValue, invalid Scroll"); break; case None: break; } input.skipRun(valueRun); }
bool VTTParser::parseFloatPercentageValuePair(VTTScanner& valueScanner, char delimiter, FloatPoint& valuePair) { float firstCoord; if (!parseFloatPercentageValue(valueScanner, firstCoord)) return false; if (!valueScanner.scan(delimiter)) return false; float secondCoord; if (!parseFloatPercentageValue(valueScanner, secondCoord)) return false; valuePair = FloatPoint(firstCoord, secondCoord); return true; }
bool VTTParser::collectTimeStamp(VTTScanner& input, double& timeStamp) { // Collect a WebVTT timestamp (5.3 WebVTT cue timings and settings parsing.) // Steps 1 - 4 - Initial checks, let most significant units be minutes. enum Mode { Minutes, Hours }; Mode mode = Minutes; // Steps 5 - 7 - Collect a sequence of characters that are 0-9. // If not 2 characters or value is greater than 59, interpret as hours. int value1; unsigned value1Digits = input.scanDigits(value1); if (!value1Digits) return false; if (value1Digits != 2 || value1 > 59) mode = Hours; // Steps 8 - 11 - Collect the next sequence of 0-9 after ':' (must be 2 chars). int value2; if (!input.scan(':') || input.scanDigits(value2) != 2) return false; // Step 12 - Detect whether this timestamp includes hours. int value3; if (mode == Hours || input.match(':')) { if (!input.scan(':') || input.scanDigits(value3) != 2) return false; } else { value3 = value2; value2 = value1; value1 = 0; } // Steps 13 - 17 - Collect next sequence of 0-9 after '.' (must be 3 chars). int value4; if (!input.scan('.') || input.scanDigits(value4) != 3) return false; if (value2 > 59 || value3 > 59) return false; // Steps 18 - 19 - Calculate result. timeStamp = (value1 * secondsPerHour) + (value2 * secondsPerMinute) + value3 + (value4 * secondsPerMillisecond); return true; }
static bool scanPercentage(VTTScanner& input, float& number) { // http://dev.w3.org/html5/webvtt/#dfn-parse-a-percentage-string // 1. Let input be the string being parsed. // 2. If input contains any characters other than U+0025 PERCENT SIGN // characters (%), U+002E DOT characters (.) and ASCII digits, then // fail. // 3. If input does not contain at least one ASCII digit, then fail. // 4. If input contains more than one U+002E DOT character (.), then fail. // 5. If any character in input other than the last character is a U+0025 // PERCENT SIGN character (%), then fail. // 6. If the last character in input is not a U+0025 PERCENT SIGN character // (%), then fail. // 7. Ignoring the trailing percent sign, interpret input as a real // number. Let that number be the percentage. // 8. If percentage is outside the range 0..100, then fail. // 9. Return percentage. return input.scanPercentage(number) && !isInvalidPercentage(number); }
VTTCue::CueSetting VTTCue::settingName(VTTScanner& input) { CueSetting parsedSetting = None; if (input.scan("vertical")) parsedSetting = Vertical; else if (input.scan("line")) parsedSetting = Line; else if (input.scan("position")) parsedSetting = Position; else if (input.scan("size")) parsedSetting = Size; else if (input.scan("align")) parsedSetting = Align; else if (RuntimeEnabledFeatures::webVTTRegionsEnabled() && input.scan("region")) parsedSetting = RegionId; // Verify that a ':' follows. if (parsedSetting != None && input.scan(':')) return parsedSetting; return None; }
VTTRegion::RegionSetting VTTRegion::scanSettingName(VTTScanner& input) { if (input.scan("id")) return Id; if (input.scan("height")) return Height; if (input.scan("width")) return Width; if (input.scan("viewportanchor")) return ViewportAnchor; if (input.scan("regionanchor")) return RegionAnchor; if (input.scan("scroll")) return Scroll; return None; }
VTTCue::CueSetting VTTCue::settingName(VTTScanner& input) { CueSetting parsedSetting = None; if (input.scan("vertical")) parsedSetting = Vertical; else if (input.scan("line")) parsedSetting = Line; else if (input.scan("position")) parsedSetting = Position; else if (input.scan("size")) parsedSetting = Size; else if (input.scan("align")) parsedSetting = Align; #if ENABLE(WEBVTT_REGIONS) else if (input.scan("region")) parsedSetting = RegionId; #endif // Verify that a ':' follows. if (parsedSetting != None && input.scan(':')) return parsedSetting; return None; }
static inline bool parsedEntireRun(const VTTScanner& input, const VTTScanner::Run& run) { return input.isAt(run.end()); }