Changeset 117738 in webkit
- Timestamp:
- May 21, 2012 12:15:38 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r117736 r117738 1 2012-05-21 Yoshifumi Inoue <yosin@chromium.org> 2 3 [Forms] Move numeric related methods in HTMLInputElement class to another place 4 https://bugs.webkit.org/show_bug.cgi?id=82034 5 6 Reviewed by Kent Tamura. 7 8 This patch moves step and range related methods into StepRange class 9 for ease of using step calculation other than double floating point 10 number arithmetic, e.g. decimal, long double, and so on. 11 12 New class StepRange::StepDescription holds values for calculating 13 stepped value, defaultStep, defaultStepBase, integer rounding flags, 14 step scale factor instead of virtual methods in InputType class. 15 16 No new tests because of this patch doesn't change behavior. 17 18 * WebCore.xcodeproj/project.pbxproj: Set attribute of StepRange.h to "Private" for including it in HTMLInputElement.cpp. 19 * html/BaseDateAndTimeInputType.cpp: 20 (WebCore::InputType::rangeOverflow): Moved to use InputType class. 21 (WebCore::InputType::rangeUnderflow): Moved to use InputType class. 22 (WebCore::BaseDateAndTimeInputType::stepMismatch): Moved to use stepRange. 23 * html/BaseDateAndTimeInputType.h: 24 (BaseDateAndTimeInputType): Removed method declaration for stepBase. 25 * html/DateInputType.cpp: 26 (WebCore::DateInputType::setupStepRange): Added. 27 * html/DateInputType.h: 28 (DateInputType): Removed method declarations. 29 * html/DateTimeInputType.cpp: 30 (WebCore::DateTimeInputType::defaultStep): Removed. 31 (WebCore::DateTimeInputType::maximum): Removed. 32 (WebCore::DateTimeInputType::minimum): Removed. 33 (WebCore::DateTimeInputType::setupStepRange): Added 34 (WebCore::DateTimeInputType::stepScaleFactor): Removed. 35 * html/DateTimeInputType.h: 36 (DateTimeInputType): Removed deprecated method declarations. 37 * html/DateTimeLocalInputType.cpp: 38 (WebCore::DateTimeLocalInputType::defaultStep): Removed. 39 (WebCore::DateTimeLocalInputType::maximum): Removed. 40 (WebCore::DateTimeLocalInputType::minimum): Removed. 41 (WebCore::DateTimeLocalInputType::setupStepRange): Added. 42 (WebCore::DateTimeLocalInputType::stepScaleFactor): Removed. 43 * html/DateTimeLocalInputType.h: 44 (DateTimeLocalInputType): 45 * html/HTMLInputElement.cpp: 46 (WebCore::HTMLInputElement::isInRange): Changed to call InputType::isInRange. 47 (WebCore::HTMLInputElement::isOutOfRange): Changed to call InputType::isOutOfRange. 48 (WebCore::HTMLInputElement::setupStepRange): Added. 49 * html/HTMLInputElement.h: 50 (HTMLInputElement): 51 * html/InputType.cpp: 52 (WebCore::InputType::acceptableError): Moved to StepRange class. 53 (WebCore::InputType::alignValueForStep): Moved to StepRange class. 54 (WebCore::InputType::minimum): Changed to use StepRange class. 55 (WebCore::InputType::maximum): Changed to use StepRange class. 56 (WebCore::InputType::parseToDouble): Changed to have ASSERT_NOT_REACHED. 57 (WebCore::InputType::stepBaseWithDecimalPlaces): Changed to use StepRange class. 58 (WebCore::InputType::validationMessage): Changed to use StepRange class. 59 (WebCore::InputType::applyStep): Changed to use StepRange class. 60 (WebCore::InputType::getAllowedValueStep): Changed to use StepRange class. 61 (WebCore::InputType::isInRange): Added. 62 (WebCore::InputType::isOutOfRange): Added. 63 (WebCore::InputType::rangeOverflow): Changed to use StepRange class. 64 (WebCore::InputType::rangeUnderflow): Changed to use StepRange class. 65 (WebCore::InputType::setupStepRange): Added. 66 (WebCore::InputType::stepUpFromRenderer): Changed to use StepRange class. 67 (WebCore::InputType::stepMismatch): Changed to use StepRange class. 68 * html/InputType.h: 69 (InputType): 70 * html/MonthInputType.cpp: 71 (WebCore::MonthInputType::defaultStep): Removed. 72 (WebCore::MonthInputType::maximum): Removed. 73 (WebCore::MonthInputType::minimum): Removed. 74 (WebCore::MonthInputType::setupStepRange): Added. 75 (WebCore::MonthInputType::stepScaleFactor): Removed. 76 * html/MonthInputType.h: 77 (MonthInputType): 78 * html/NumberInputType.cpp: 79 (WebCore): 80 (WebCore::NumberInputType::defaultStep): Removed. 81 (WebCore::NumberInputType::maximum): Removed. 82 (WebCore::NumberInputType::minimum): Removed. 83 (WebCore::NumberInputType::rangeOverflow): Moved to InputType class. 84 (WebCore::NumberInputType::rangeUnderflow): Moved to InputType class. 85 (WebCore::NumberInputType::setupStepRange): Added. 86 (WebCore::NumberInputType::stepMismatch): Moved to InputType class. 87 (WebCore::NumberInputType::stepBaseWithDecimalPlaces): Changed to use StepRange class. 88 (WebCore::NumberInputType::stepScaleFactor): Removed. 89 * html/NumberInputType.h: 90 (NumberInputType): 91 * html/RangeInputType.cpp: 92 (WebCore::RangeInputType::defaultStep): Removed. 93 (WebCore::RangeInputType::maximum): Removed. 94 (WebCore::RangeInputType::minimum): Removed. 95 (WebCore::RangeInputType::setupStepRange): Added. 96 (WebCore::RangeInputType::stepScaleFactor): Removed. 97 (WebCore::RangeInputType::handleKeydownEvent): Changed to use StepRange class. 98 (WebCore::RangeInputType::fallbackValue): Changed to use StepRange class. 99 (WebCore::RangeInputType::sanitizeValue): Changed to use StepRange class. 100 * html/RangeInputType.h: 101 (RangeInputType): 102 * html/StepRange.cpp: 103 (WebCore::StepRange::StepRange): Added. 104 (WebCore::StepRange::clampValue): Changed for member variable name changes. 105 (WebCore::StepRange::hasStep): Added. 106 (WebCore::StepRange::maximum): Added. 107 (WebCore::StepRange::minimum): Added. 108 (WebCore::StepRange::step): Added. 109 (WebCore::StepRange::stepBase): Added. 110 (WebCore::StepRange::stepDecimalPlaces): Added. 111 (WebCore::StepRange::stepScaleFactor): Added. 112 (WebCore::StepRange::setHasStep): Added. 113 (WebCore::StepRange::setup): Added. 114 (WebCore::StepRange::parse): Added. 115 * html/StepRange.h: 116 (StepDescription): Added 117 (WebCore::StepRange::StepDescription::StepDescription): 118 (WebCore::StepRange::acceptableError): Moved from InputType class. 119 (WebCore::StepRange::alignValueForStep): Moved from InputType class. 120 (WebCore::StepRange::defaultValue): Changed for member variable name changes. 121 (WebCore::StepRange::proportionFromValue): Changed for member variable name changes. 122 (WebCore::StepRange::valueFromProportion): Changed for member variable name changes. 123 * html/TimeInputType.cpp: 124 (WebCore::TimeInputType::defaultStep): Removed. 125 (WebCore::TimeInputType::maximum): Removed. 126 (WebCore::TimeInputType::minimum): Removed. 127 (WebCore::TimeInputType::setupStepRange): Added. 128 (WebCore::TimeInputType::stepScaleFactor): Removed. 129 * html/TimeInputType.h: 130 (TimeInputType): 131 * html/WeekInputType.cpp: 132 (WebCore): 133 (WebCore::WeekInputType::defaultStep): Removed. 134 (WebCore::WeekInputType::maximum): Removed. 135 (WebCore::WeekInputType::minimum): Removed. 136 (WebCore::WeekInputType::setupStepRange): Added. 137 (WebCore::WeekInputType::stepScaleFactor): Removed. 138 * html/WeekInputType.h: 139 (WeekInputType): 140 * html/shadow/SliderThumbElement.cpp: 141 (WebCore::sliderPosition): Changed to use StepRange class. 142 (WebCore::SliderThumbElement::setPositionFromPoint): Changed to use StepRange class. 143 1 144 2012-05-21 Kentaro Hara <haraken@chromium.org> 2 145 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r117607 r117738 3714 3714 A5ABB78713B904BC00F197E3 /* LineBreakIteratorPoolICU.h in Headers */ = {isa = PBXBuildFile; fileRef = A5ABB78613B904BC00F197E3 /* LineBreakIteratorPoolICU.h */; }; 3715 3715 A5AFB34F115151A700B045CB /* StepRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5AFB34D115151A700B045CB /* StepRange.cpp */; }; 3716 A5AFB350115151A700B045CB /* StepRange.h in Headers */ = {isa = PBXBuildFile; fileRef = A5AFB34E115151A700B045CB /* StepRange.h */; };3716 A5AFB350115151A700B045CB /* StepRange.h in Headers */ = {isa = PBXBuildFile; fileRef = A5AFB34E115151A700B045CB /* StepRange.h */; settings = {ATTRIBUTES = (Private, ); }; }; 3717 3717 A5D214B112E905510090F370 /* HTTPRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5D214AE12E905510090F370 /* HTTPRequest.cpp */; }; 3718 3718 A5D214B212E905510090F370 /* HTTPRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A5D214AF12E905510090F370 /* HTTPRequest.h */; }; -
trunk/Source/WebCore/html/BaseDateAndTimeInputType.cpp
r115155 r117738 81 81 } 82 82 83 bool BaseDateAndTimeInputType::rangeUnderflow(const String& value) const84 {85 const double nan = numeric_limits<double>::quiet_NaN();86 double doubleValue = parseToDouble(value, nan);87 return isfinite(doubleValue) && doubleValue < minimum();88 }89 90 bool BaseDateAndTimeInputType::rangeOverflow(const String& value) const91 {92 const double nan = numeric_limits<double>::quiet_NaN();93 double doubleValue = parseToDouble(value, nan);94 return isfinite(doubleValue) && doubleValue > maximum();95 }96 97 bool BaseDateAndTimeInputType::supportsRangeLimitation() const98 {99 return true;100 }101 102 83 double BaseDateAndTimeInputType::defaultValueForStepUp() const 103 84 { … … 112 93 { 113 94 return true; 114 }115 116 bool BaseDateAndTimeInputType::stepMismatch(const String& value, double step) const117 {118 const double nan = numeric_limits<double>::quiet_NaN();119 double doubleValue = parseToDouble(value, nan);120 doubleValue = fabs(doubleValue - stepBase());121 if (!isfinite(doubleValue))122 return false;123 ASSERT(round(doubleValue) == doubleValue);124 ASSERT(round(step) == step);125 return fmod(doubleValue, step);126 }127 128 double BaseDateAndTimeInputType::stepBase() const129 {130 return parseToDouble(element()->fastGetAttribute(minAttr), defaultStepBase());131 95 } 132 96 -
trunk/Source/WebCore/html/BaseDateAndTimeInputType.h
r115155 r117738 57 57 virtual bool typeMismatchFor(const String&) const OVERRIDE; 58 58 virtual bool typeMismatch() const OVERRIDE; 59 virtual bool rangeUnderflow(const String&) const OVERRIDE;60 virtual bool rangeOverflow(const String&) const OVERRIDE;61 virtual bool supportsRangeLimitation() const OVERRIDE;62 59 virtual double defaultValueForStepUp() const OVERRIDE; 63 60 virtual bool isSteppable() const OVERRIDE; 64 virtual bool stepMismatch(const String&, double) const OVERRIDE;65 virtual double stepBase() const OVERRIDE;66 61 virtual void handleWheelEvent(WheelEvent*) OVERRIDE; 67 62 virtual String serialize(double) const OVERRIDE; -
trunk/Source/WebCore/html/DateInputType.cpp
r116499 r117738 47 47 48 48 static const double dateDefaultStep = 1.0; 49 static const double dateDefaultStepBase = 0.0; 49 50 static const double dateStepScaleFactor = 86400000.0; 50 51 … … 69 70 } 70 71 71 double DateInputType::minimum() const72 StepRange DateInputType::createStepRange(AnyStepHandling anyStepHandling) const 72 73 { 73 return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumDate()); 74 } 74 DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (dateDefaultStep, dateDefaultStepBase, dateStepScaleFactor, StepRange::ParsedStepValueShouldBeInteger)); 75 75 76 double DateInputType::maximum() const 77 { 78 return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumDate()); 79 } 80 81 double DateInputType::defaultStep() const 82 { 83 return dateDefaultStep; 84 } 85 86 double DateInputType::stepScaleFactor() const 87 { 88 return dateStepScaleFactor; 89 } 90 91 bool DateInputType::parsedStepValueShouldBeInteger() const 92 { 93 return true; 76 double stepBase = parseToDouble(element()->fastGetAttribute(minAttr), 0); 77 double minimum = parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumDate()); 78 double maximum = parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumDate()); 79 StepRange::DoubleWithDecimalPlacesOrMissing step = StepRange::parseStep(anyStepHandling, stepDescription, element()->fastGetAttribute(stepAttr)); 80 return StepRange(stepBase, minimum, maximum, step, stepDescription); 94 81 } 95 82 -
trunk/Source/WebCore/html/DateInputType.h
r116499 r117738 49 49 virtual const AtomicString& formControlType() const OVERRIDE; 50 50 virtual DateComponents::Type dateType() const OVERRIDE; 51 virtual double minimum() const OVERRIDE; 52 virtual double maximum() const OVERRIDE; 53 virtual double defaultStep() const OVERRIDE; 54 virtual double stepScaleFactor() const OVERRIDE; 55 virtual bool parsedStepValueShouldBeInteger() const OVERRIDE; 51 virtual StepRange createStepRange(AnyStepHandling) const OVERRIDE; 56 52 virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const OVERRIDE; 57 53 virtual bool setMillisecondToDateComponents(double, DateComponents*) const OVERRIDE; -
trunk/Source/WebCore/html/DateTimeInputType.cpp
r116499 r117738 45 45 46 46 static const double dateTimeDefaultStep = 60.0; 47 static const double dateTimeDefaultStepBase = 0.0; 47 48 static const double dateTimeStepScaleFactor = 1000.0; 48 49 … … 67 68 } 68 69 69 double DateTimeInputType::minimum() const70 StepRange DateTimeInputType::createStepRange(AnyStepHandling anyStepHandling) const 70 71 { 71 return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumDateTime()); 72 } 72 DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (dateTimeDefaultStep, dateTimeDefaultStepBase, dateTimeStepScaleFactor, StepRange::ScaledStepValueShouldBeInteger)); 73 73 74 double DateTimeInputType::maximum() const 75 { 76 return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumDateTime()); 77 } 78 79 double DateTimeInputType::defaultStep() const 80 { 81 return dateTimeDefaultStep; 82 } 83 84 double DateTimeInputType::stepScaleFactor() const 85 { 86 return dateTimeStepScaleFactor; 87 } 88 89 bool DateTimeInputType::scaledStepValueShouldBeInteger() const 90 { 91 return true; 74 double stepBase = parseToDouble(element()->fastGetAttribute(minAttr), 0); 75 double minimum = parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumDateTime()); 76 double maximum = parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumDateTime()); 77 StepRange::DoubleWithDecimalPlacesOrMissing step = StepRange::parseStep(anyStepHandling, stepDescription, element()->fastGetAttribute(stepAttr)); 78 return StepRange(stepBase, minimum, maximum, step, stepDescription); 92 79 } 93 80 -
trunk/Source/WebCore/html/DateTimeInputType.h
r116499 r117738 46 46 virtual const AtomicString& formControlType() const OVERRIDE; 47 47 virtual DateComponents::Type dateType() const OVERRIDE; 48 virtual StepRange createStepRange(AnyStepHandling) const OVERRIDE; 48 49 virtual double defaultValueForStepUp() const OVERRIDE; 49 virtual double minimum() const OVERRIDE;50 virtual double maximum() const OVERRIDE;51 virtual double defaultStep() const OVERRIDE;52 virtual double stepScaleFactor() const OVERRIDE;53 virtual bool scaledStepValueShouldBeInteger() const OVERRIDE;54 50 virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const OVERRIDE; 55 51 virtual bool setMillisecondToDateComponents(double, DateComponents*) const OVERRIDE; -
trunk/Source/WebCore/html/DateTimeLocalInputType.cpp
r116499 r117738 44 44 45 45 static const double dateTimeLocalDefaultStep = 60.0; 46 static const double dateTimeLocalDefaultStepBase = 0.0; 46 47 static const double dateTimeLocalStepScaleFactor = 1000.0; 47 48 … … 73 74 } 74 75 75 double DateTimeLocalInputType::minimum() const76 StepRange DateTimeLocalInputType::createStepRange(AnyStepHandling anyStepHandling) const 76 77 { 77 return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumDateTime()); 78 } 78 DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (dateTimeLocalDefaultStep, dateTimeLocalDefaultStepBase, dateTimeLocalStepScaleFactor, StepRange::ScaledStepValueShouldBeInteger)); 79 79 80 double DateTimeLocalInputType::maximum() const 81 { 82 return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumDateTime()); 83 } 84 85 double DateTimeLocalInputType::defaultStep() const 86 { 87 return dateTimeLocalDefaultStep; 88 } 89 90 double DateTimeLocalInputType::stepScaleFactor() const 91 { 92 return dateTimeLocalStepScaleFactor; 93 } 94 95 bool DateTimeLocalInputType::scaledStepValueShouldBeInteger() const 96 { 97 return true; 80 double stepBase = parseToDouble(element()->fastGetAttribute(minAttr), 0); 81 double minimum = parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumDateTime()); 82 double maximum = parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumDateTime()); 83 StepRange::DoubleWithDecimalPlacesOrMissing step = StepRange::parseStep(anyStepHandling, stepDescription, element()->fastGetAttribute(stepAttr)); 84 return StepRange(stepBase, minimum, maximum, step, stepDescription); 98 85 } 99 86 -
trunk/Source/WebCore/html/DateTimeLocalInputType.h
r116499 r117738 48 48 virtual double valueAsDate() const OVERRIDE; 49 49 virtual void setValueAsDate(double, ExceptionCode&) const OVERRIDE; 50 virtual double minimum() const OVERRIDE; 51 virtual double maximum() const OVERRIDE; 52 virtual double defaultStep() const OVERRIDE; 53 virtual double stepScaleFactor() const OVERRIDE; 54 virtual bool scaledStepValueShouldBeInteger() const OVERRIDE; 50 virtual StepRange createStepRange(AnyStepHandling) const; 55 51 virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const OVERRIDE; 56 52 virtual bool setMillisecondToDateComponents(double, DateComponents*) const OVERRIDE; -
trunk/Source/WebCore/html/HTMLInputElement.cpp
r117323 r117738 277 277 { 278 278 return m_inputType->getAllowedValueStep(step); 279 } 280 281 StepRange HTMLInputElement::createStepRange(AnyStepHandling anyStepHandling) const 282 { 283 return m_inputType->createStepRange(anyStepHandling); 279 284 } 280 285 … … 1269 1274 bool HTMLInputElement::isInRange() const 1270 1275 { 1271 return m_inputType-> supportsRangeLimitation() && !m_inputType->rangeUnderflow(value()) && !m_inputType->rangeOverflow(value());1276 return m_inputType->isInRange(value()); 1272 1277 } 1273 1278 1274 1279 bool HTMLInputElement::isOutOfRange() const 1275 1280 { 1276 return m_inputType-> supportsRangeLimitation() && (m_inputType->rangeUnderflow(value()) || m_inputType->rangeOverflow(value()));1281 return m_inputType->isOutOfRange(value()); 1277 1282 } 1278 1283 -
trunk/Source/WebCore/html/HTMLInputElement.h
r117323 r117738 27 27 28 28 #include "HTMLTextFormControlElement.h" 29 #include "StepRange.h" 29 30 30 31 namespace WebCore { … … 66 67 // Returns false if there is no "allowed value step." 67 68 bool getAllowedValueStep(double*) const; 69 StepRange createStepRange(AnyStepHandling) const; 68 70 69 71 // Implementations of HTMLInputElement::stepUp() and stepDown(). -
trunk/Source/WebCore/html/InputType.cpp
r116915 r117738 246 246 } 247 247 248 bool InputType::rangeUnderflow(const String&) const 249 { 250 return false; 251 } 252 253 bool InputType::rangeOverflow(const String&) const 254 { 255 return false; 256 } 257 258 bool InputType::supportsRangeLimitation() const 259 { 260 return false; 248 bool InputType::rangeUnderflow(const String& value) const 249 { 250 if (!isSteppable()) 251 return false; 252 253 double doubleValue = parseToDouble(value, numeric_limits<double>::quiet_NaN()); 254 if (isnan(doubleValue)) 255 return false; 256 257 return doubleValue < createStepRange(RejectAny).minimum(); 258 } 259 260 bool InputType::rangeOverflow(const String& value) const 261 { 262 if (!isSteppable()) 263 return false; 264 265 double doubleValue = parseToDouble(value, numeric_limits<double>::quiet_NaN()); 266 if (isnan(doubleValue)) 267 return false; 268 269 return doubleValue > createStepRange(RejectAny).maximum(); 261 270 } 262 271 … … 268 277 double InputType::minimum() const 269 278 { 270 ASSERT_NOT_REACHED(); 271 return 0; 279 return createStepRange(RejectAny).minimum(); 272 280 } 273 281 274 282 double InputType::maximum() const 275 283 { 276 ASSERT_NOT_REACHED(); 277 return 0; 284 return createStepRange(RejectAny).maximum(); 278 285 } 279 286 … … 284 291 } 285 292 293 bool InputType::isInRange(const String& value) const 294 { 295 if (!isSteppable()) 296 return false; 297 298 double doubleValue = parseToDouble(value, numeric_limits<double>::quiet_NaN()); 299 if (isnan(doubleValue)) 300 return true; 301 302 StepRange stepRange(createStepRange(RejectAny)); 303 return doubleValue >= stepRange.minimum() && doubleValue <= stepRange.maximum(); 304 } 305 306 bool InputType::isOutOfRange(const String& value) const 307 { 308 if (!isSteppable()) 309 return false; 310 311 double doubleValue = parseToDouble(value, numeric_limits<double>::quiet_NaN()); 312 if (isnan(doubleValue)) 313 return true; 314 315 StepRange stepRange(createStepRange(RejectAny)); 316 return doubleValue < stepRange.minimum() || doubleValue > stepRange.maximum(); 317 } 318 286 319 bool InputType::stepMismatch(const String& value) const 287 320 { 288 double step; 289 if (!getAllowedValueStep(&step)) 321 if (!isSteppable()) 290 322 return false; 291 return stepMismatch(value, step); 292 } 293 294 bool InputType::stepMismatch(const String&, double) const 295 { 296 // Non-supported types should be rejected by HTMLInputElement::getAllowedValueStep(). 297 ASSERT_NOT_REACHED(); 298 return false; 299 } 300 301 double InputType::stepBase() const 302 { 303 ASSERT_NOT_REACHED(); 304 return 0; 305 } 306 307 double InputType::stepBaseWithDecimalPlaces(unsigned* decimalPlaces) const 308 { 309 if (decimalPlaces) 310 *decimalPlaces = 0; 311 return stepBase(); 312 } 313 314 double InputType::defaultStep() const 315 { 316 return numeric_limits<double>::quiet_NaN(); 317 } 318 319 double InputType::stepScaleFactor() const 320 { 321 return numeric_limits<double>::quiet_NaN(); 322 } 323 324 bool InputType::parsedStepValueShouldBeInteger() const 325 { 326 return false; 327 } 328 329 bool InputType::scaledStepValueShouldBeInteger() const 330 { 331 return false; 332 } 333 334 double InputType::acceptableError(double) const 335 { 336 return 0; 323 324 double doubleValue = parseToDouble(value, numeric_limits<double>::quiet_NaN()); 325 if (isnan(doubleValue)) 326 return false; 327 328 return createStepRange(RejectAny).stepMismatch(doubleValue); 337 329 } 338 330 … … 365 357 return validationMessageTooLongText(numGraphemeClusters(value), element()->maxLength()); 366 358 367 if (rangeUnderflow(value)) 368 return validationMessageRangeUnderflowText(serialize(minimum())); 369 370 if (rangeOverflow(value)) 371 return validationMessageRangeOverflowText(serialize(maximum())); 372 373 if (stepMismatch(value)) { 374 String stepString; 375 double step; 376 if (getAllowedValueStep(&step)) 377 stepString = serializeForNumberType(step / stepScaleFactor()); 378 return validationMessageStepMismatchText(serialize(stepBase()), stepString); 359 if (!isSteppable()) 360 return emptyString(); 361 362 double doubleValue = parseToDouble(value, numeric_limits<double>::quiet_NaN()); 363 if (isnan(doubleValue)) 364 return emptyString(); 365 366 StepRange stepRange(createStepRange(RejectAny)); 367 368 if (doubleValue < stepRange.minimum()) 369 return validationMessageRangeUnderflowText(serialize(stepRange.minimum())); 370 371 if (doubleValue < stepRange.maximum()) 372 return validationMessageRangeOverflowText(serialize(stepRange.maximum())); 373 374 if (stepRange.stepMismatch(doubleValue)) { 375 const String stepString = stepRange.hasStep() ? serializeForNumberType(stepRange.step() / stepRange.stepScaleFactor()) : emptyString(); 376 return validationMessageStepMismatchText(serialize(stepRange.stepBase()), stepString); 379 377 } 380 378 381 return String();379 return emptyString(); 382 380 } 383 381 … … 457 455 double InputType::parseToDouble(const String&, double defaultValue) const 458 456 { 457 ASSERT_NOT_REACHED(); 459 458 return defaultValue; 460 459 } … … 862 861 void InputType::applyStep(double count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionCode& ec) 863 862 { 864 double step; 865 unsigned stepDecimalPlaces, currentDecimalPlaces; 866 if (!getAllowedValueStepWithDecimalPlaces(anyStepHandling, &step, &stepDecimalPlaces)) { 863 StepRange stepRange(createStepRange(anyStepHandling)); 864 if (!stepRange.hasStep()) { 867 865 ec = INVALID_STATE_ERR; 868 866 return; … … 870 868 871 869 const double nan = numeric_limits<double>::quiet_NaN(); 870 unsigned currentDecimalPlaces; 872 871 double current = parseToDoubleWithDecimalPlaces(element()->value(), nan, ¤tDecimalPlaces); 873 872 if (!isfinite(current)) { … … 875 874 return; 876 875 } 877 double newValue = current + step * count;876 double newValue = current + stepRange.step() * count; 878 877 if (isinf(newValue)) { 879 878 ec = INVALID_STATE_ERR; … … 881 880 } 882 881 883 double acceptableErrorValue = acceptableError(step);884 if (newValue - minimum() < -acceptableErrorValue) {882 double acceptableErrorValue = stepRange.acceptableError(); 883 if (newValue - stepRange.minimum() < -acceptableErrorValue) { 885 884 ec = INVALID_STATE_ERR; 886 885 return; 887 886 } 888 if (newValue < minimum())889 newValue = minimum();887 if (newValue < stepRange.minimum()) 888 newValue = stepRange.minimum(); 890 889 891 890 const AtomicString& stepString = element()->fastGetAttribute(stepAttr); 892 891 if (!equalIgnoringCase(stepString, "any")) 893 newValue = alignValueForStep(newValue, step, currentDecimalPlaces, stepDecimalPlaces);894 895 if (newValue - maximum() > acceptableErrorValue) {892 newValue = stepRange.alignValueForStep(current, currentDecimalPlaces, newValue); 893 894 if (newValue - stepRange.maximum() > acceptableErrorValue) { 896 895 ec = INVALID_STATE_ERR; 897 896 return; 898 897 } 899 if (newValue > maximum())900 newValue = maximum();898 if (newValue > stepRange.maximum()) 899 newValue = stepRange.maximum(); 901 900 902 901 element()->setValueAsNumber(newValue, ec, eventBehavior); … … 906 905 } 907 906 908 double InputType::alignValueForStep(double newValue, double step, unsigned currentDecimalPlaces, unsigned stepDecimalPlaces) 909 { 910 if (newValue >= pow(10.0, 21.0)) 911 return newValue; 912 913 unsigned baseDecimalPlaces; 914 double base = stepBaseWithDecimalPlaces(&baseDecimalPlaces); 915 baseDecimalPlaces = min(baseDecimalPlaces, 16u); 916 if (stepMismatch(element()->value())) { 917 double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, currentDecimalPlaces))); 918 newValue = round(newValue * scale) / scale; 919 } else { 920 double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, baseDecimalPlaces))); 921 newValue = round((base + round((newValue - base) / step) * step) * scale) / scale; 907 bool InputType::getAllowedValueStep(double* step) const 908 { 909 StepRange stepRange(createStepRange(RejectAny)); 910 *step = stepRange.step(); 911 return stepRange.hasStep(); 912 } 913 914 StepRange InputType::createStepRange(AnyStepHandling) const 915 { 916 ASSERT_NOT_REACHED(); 917 return StepRange(); 918 } 919 920 void InputType::stepUp(int n, ExceptionCode& ec) 921 { 922 if (!isSteppable()) { 923 ec = INVALID_STATE_ERR; 924 return; 922 925 } 923 924 return newValue;925 }926 927 bool InputType::getAllowedValueStep(double* step) const928 {929 return getAllowedValueStepWithDecimalPlaces(RejectAny, step, 0);930 }931 932 bool InputType::getAllowedValueStepWithDecimalPlaces(AnyStepHandling anyStepHandling, double* step, unsigned* decimalPlaces) const933 {934 ASSERT(step);935 double defaultStepValue = defaultStep();936 double stepScaleFactorValue = stepScaleFactor();937 if (!isfinite(defaultStepValue) || !isfinite(stepScaleFactorValue))938 return false;939 const AtomicString& stepString = element()->fastGetAttribute(stepAttr);940 if (stepString.isEmpty()) {941 *step = defaultStepValue * stepScaleFactorValue;942 if (decimalPlaces)943 *decimalPlaces = 0;944 return true;945 }946 947 if (equalIgnoringCase(stepString, "any")) {948 switch (anyStepHandling) {949 case RejectAny:950 return false;951 case AnyIsDefaultStep:952 *step = defaultStepValue * stepScaleFactorValue;953 if (decimalPlaces)954 *decimalPlaces = 0;955 return true;956 default:957 ASSERT_NOT_REACHED();958 }959 }960 961 double parsed;962 if (!decimalPlaces) {963 if (!parseToDoubleForNumberType(stepString, &parsed) || parsed <= 0.0) {964 *step = defaultStepValue * stepScaleFactorValue;965 return true;966 }967 } else {968 if (!parseToDoubleForNumberTypeWithDecimalPlaces(stepString, &parsed, decimalPlaces) || parsed <= 0.0) {969 *step = defaultStepValue * stepScaleFactorValue;970 *decimalPlaces = 0;971 return true;972 }973 }974 // For date, month, week, the parsed value should be an integer for some types.975 if (parsedStepValueShouldBeInteger())976 parsed = max(round(parsed), 1.0);977 double result = parsed * stepScaleFactorValue;978 // For datetime, datetime-local, time, the result should be an integer.979 if (scaledStepValueShouldBeInteger())980 result = max(round(result), 1.0);981 ASSERT(result > 0);982 *step = result;983 return true;984 }985 986 void InputType::stepUp(int n, ExceptionCode& ec)987 {988 926 applyStep(n, RejectAny, DispatchNoEvent, ec); 989 927 } … … 1033 971 return; 1034 972 1035 unsigned stepDecimalPlaces, baseDecimalPlaces;1036 double step, base; 973 StepRange stepRange(createStepRange(AnyIsDefaultStep)); 974 1037 975 // FIXME: Not any changes after stepping, even if it is an invalid value, may be better. 1038 976 // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "foo") 1039 if (! getAllowedValueStepWithDecimalPlaces(AnyIsDefaultStep, &step, &stepDecimalPlaces))977 if (!stepRange.hasStep()) 1040 978 return; 1041 base = stepBaseWithDecimalPlaces(&baseDecimalPlaces); 1042 baseDecimalPlaces = min(baseDecimalPlaces, 16u);979 980 double step = stepRange.step(); 1043 981 1044 982 int sign; … … 1057 995 current = defaultValueForStepUp(); 1058 996 double nextDiff = step * n; 1059 if (current < minimum() - nextDiff)1060 current = minimum() - nextDiff;1061 if (current > maximum() - nextDiff)1062 current = maximum() - nextDiff;997 if (current < stepRange.minimum() - nextDiff) 998 current = stepRange.minimum() - nextDiff; 999 if (current > stepRange.maximum() - nextDiff) 1000 current = stepRange.maximum() - nextDiff; 1063 1001 element()->setValueAsNumber(current, ec, DispatchInputAndChangeEvent); 1064 1002 } 1065 if ((sign > 0 && current < minimum()) || (sign < 0 && current >maximum()))1066 element()->setValue(serialize(sign > 0 ? minimum() :maximum()), DispatchInputAndChangeEvent);1003 if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > stepRange.maximum())) 1004 element()->setValue(serialize(sign > 0 ? stepRange.minimum() : stepRange.maximum()), DispatchInputAndChangeEvent); 1067 1005 else { 1068 1006 ExceptionCode ec; … … 1070 1008 ASSERT(step); 1071 1009 double newValue; 1072 double scale = pow(10.0, static_cast<double>(max(stepDecimalPlaces, baseDecimalPlaces))); 1010 double scale = pow(10.0, static_cast<double>(max(stepRange.stepDecimalPlaces(), stepRange.stepBaseDecimalPlaces()))); 1011 double base = stepRange.stepBase(); 1073 1012 1074 1013 if (sign < 0) … … 1079 1018 newValue = current; 1080 1019 1081 if (newValue < minimum())1082 newValue = minimum();1083 if (newValue > maximum())1084 newValue = maximum();1020 if (newValue < stepRange.minimum()) 1021 newValue = stepRange.minimum(); 1022 if (newValue > stepRange.maximum()) 1023 newValue = stepRange.maximum(); 1085 1024 1086 1025 element()->setValueAsNumber(newValue, ec, n == 1 || n == -1 ? DispatchInputAndChangeEvent : DispatchNoEvent); -
trunk/Source/WebCore/html/InputType.h
r116915 r117738 35 35 36 36 #include "HTMLTextFormControlElement.h" 37 #include "StepRange.h" 37 38 #include <wtf/Forward.h> 38 39 #include <wtf/FastAllocBase.h> … … 151 152 virtual bool valueMissing(const String&) const; 152 153 virtual bool patternMismatch(const String&) const; 153 virtual bool rangeUnderflow(const String&) const; 154 virtual bool rangeOverflow(const String&) const; 155 virtual bool supportsRangeLimitation() const; 154 bool rangeUnderflow(const String&) const; 155 bool rangeOverflow(const String&) const; 156 bool isInRange(const String&) const; 157 bool isOutOfRange(const String&) const; 156 158 virtual double defaultValueForStepUp() const; 157 virtualdouble minimum() const;158 virtualdouble maximum() const;159 double minimum() const; 160 double maximum() const; 159 161 virtual bool sizeShouldIncludeDecoration(int defaultSize, int& preferredSize) const; 160 162 bool stepMismatch(const String&) const; 161 virtual bool stepMismatch(const String&, double step) const;162 virtual double stepBase() const;163 virtual double stepBaseWithDecimalPlaces(unsigned*) const;164 163 virtual bool getAllowedValueStep(double*) const; 164 virtual StepRange createStepRange(AnyStepHandling) const; 165 165 virtual void stepUp(int, ExceptionCode&); 166 166 virtual void stepUpFromRenderer(int); 167 virtual double defaultStep() const;168 virtual double stepScaleFactor() const;169 virtual bool parsedStepValueShouldBeInteger() const;170 virtual bool scaledStepValueShouldBeInteger() const;171 virtual double acceptableError(double) const;172 167 virtual String typeMismatchText() const; 173 168 virtual String valueMissingText() const; … … 296 291 HTMLInputElement* element() const { return m_element; } 297 292 void dispatchSimulatedClickIfActive(KeyboardEvent*) const; 298 // We can't make this a static const data member because VC++ doesn't like it.299 static double defaultStepBase() { return 0.0; }300 293 Chrome* chrome() const; 301 294 302 295 private: 303 enum AnyStepHandling { RejectAny, AnyIsDefaultStep };304 305 296 // Helper for stepUp()/stepDown(). Adds step value * count to the current value. 306 297 void applyStep(double count, AnyStepHandling, TextFieldEventBehavior, ExceptionCode&); 307 double alignValueForStep(double value, double step, unsigned currentDecimalPlaces, unsigned stepDecimalPlaces);308 bool getAllowedValueStepWithDecimalPlaces(AnyStepHandling, double*, unsigned*) const;309 298 310 299 // Raw pointer because the HTMLInputElement object owns this InputType object. -
trunk/Source/WebCore/html/MonthInputType.cpp
r116499 r117738 47 47 48 48 static const double monthDefaultStep = 1.0; 49 static const double monthDefaultStepBase = 0.0; 49 50 static const double monthStepScaleFactor = 1.0; 50 51 … … 97 98 } 98 99 99 double MonthInputType::minimum() const100 StepRange MonthInputType::createStepRange(AnyStepHandling anyStepHandling) const 100 101 { 101 return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumMonth()); 102 } 102 DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (monthDefaultStep, monthDefaultStepBase, monthStepScaleFactor, StepRange::ParsedStepValueShouldBeInteger)); 103 103 104 double MonthInputType::maximum() const 105 { 106 return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumMonth()); 107 } 108 109 double MonthInputType::defaultStep() const 110 { 111 return monthDefaultStep; 112 } 113 114 double MonthInputType::stepScaleFactor() const 115 { 116 return monthStepScaleFactor; 117 } 118 119 bool MonthInputType::parsedStepValueShouldBeInteger() const 120 { 121 return true; 104 double stepBase = parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumMonth()); 105 double minimum = parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumMonth()); 106 double maximum = parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumMonth()); 107 StepRange::DoubleWithDecimalPlacesOrMissing step = StepRange::parseStep(anyStepHandling, stepDescription, element()->fastGetAttribute(stepAttr)); 108 return StepRange(stepBase, minimum, maximum, step, stepDescription); 122 109 } 123 110 -
trunk/Source/WebCore/html/MonthInputType.h
r116499 r117738 50 50 virtual double parseToDouble(const String&, double) const OVERRIDE; 51 51 virtual double defaultValueForStepUp() const OVERRIDE; 52 virtual double minimum() const OVERRIDE; 53 virtual double maximum() const OVERRIDE; 54 virtual double defaultStep() const OVERRIDE; 55 virtual double stepScaleFactor() const OVERRIDE; 56 virtual bool parsedStepValueShouldBeInteger() const OVERRIDE; 52 virtual StepRange createStepRange(AnyStepHandling) const OVERRIDE; 57 53 virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const OVERRIDE; 58 54 virtual bool setMillisecondToDateComponents(double, DateComponents*) const OVERRIDE; -
trunk/Source/WebCore/html/NumberInputType.cpp
r107555 r117738 52 52 53 53 static const double numberDefaultStep = 1.0; 54 static const double numberDefaultStepBase = 0.0; 54 55 static const double numberStepScaleFactor = 1.0; 55 56 … … 108 109 } 109 110 110 bool NumberInputType::rangeUnderflow(const String& value) const 111 { 112 const double nan = numeric_limits<double>::quiet_NaN(); 113 double doubleValue = parseToDouble(value, nan); 114 return isfinite(doubleValue) && doubleValue < minimum(); 115 } 116 117 bool NumberInputType::rangeOverflow(const String& value) const 118 { 119 const double nan = numeric_limits<double>::quiet_NaN(); 120 double doubleValue = parseToDouble(value, nan); 121 return isfinite(doubleValue) && doubleValue > maximum(); 122 } 123 124 bool NumberInputType::supportsRangeLimitation() const 125 { 126 return true; 127 } 128 129 double NumberInputType::minimum() const 130 { 131 return parseToDouble(element()->fastGetAttribute(minAttr), -numeric_limits<float>::max()); 132 } 133 134 double NumberInputType::maximum() const 135 { 136 return parseToDouble(element()->fastGetAttribute(maxAttr), numeric_limits<float>::max()); 111 StepRange NumberInputType::createStepRange(AnyStepHandling anyStepHandling) const 112 { 113 DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (numberDefaultStep, numberDefaultStepBase, numberStepScaleFactor)); 114 115 unsigned stepBaseDecimalPlaces; 116 double stepBaseValue = parseToDoubleWithDecimalPlaces(element()->fastGetAttribute(minAttr), numberDefaultStepBase, &stepBaseDecimalPlaces); 117 StepRange::DoubleWithDecimalPlaces stepBase(stepBaseValue, min(stepBaseDecimalPlaces, 16u)); 118 double minimum = parseToDouble(element()->fastGetAttribute(minAttr), -numeric_limits<float>::max()); 119 double maximum = parseToDouble(element()->fastGetAttribute(maxAttr), numeric_limits<float>::max()); 120 121 StepRange::DoubleWithDecimalPlacesOrMissing step = StepRange::parseStep(anyStepHandling, stepDescription, element()->fastGetAttribute(stepAttr)); 122 return StepRange(stepBase, minimum, maximum, step, stepDescription); 137 123 } 138 124 … … 189 175 } 190 176 191 bool NumberInputType::stepMismatch(const String& value, double step) const192 {193 double doubleValue;194 if (!parseToDoubleForNumberType(value, &doubleValue))195 return false;196 doubleValue = fabs(doubleValue - stepBase());197 if (isinf(doubleValue))198 return false;199 // double's fractional part size is DBL_MAN_DIG-bit. If the current value200 // is greater than step*2^DBL_MANT_DIG, the following computation for201 // remainder makes no sense.202 if (doubleValue / pow(2.0, DBL_MANT_DIG) > step)203 return false;204 // The computation follows HTML5 4.10.7.2.10 `The step attribute' :205 // ... that number subtracted from the step base is not an integral multiple206 // of the allowed value step, the element is suffering from a step mismatch.207 double remainder = fabs(doubleValue - step * round(doubleValue / step));208 // Accepts erros in lower fractional part which IEEE 754 single-precision209 // can't represent.210 double computedAcceptableError = acceptableError(step);211 return computedAcceptableError < remainder && remainder < (step - computedAcceptableError);212 }213 214 double NumberInputType::stepBase() const215 {216 return parseToDouble(element()->fastGetAttribute(minAttr), defaultStepBase());217 }218 219 double NumberInputType::stepBaseWithDecimalPlaces(unsigned* decimalPlaces) const220 {221 return parseToDoubleWithDecimalPlaces(element()->fastGetAttribute(minAttr), defaultStepBase(), decimalPlaces);222 }223 224 double NumberInputType::defaultStep() const225 {226 return numberDefaultStep;227 }228 229 double NumberInputType::stepScaleFactor() const230 {231 return numberStepScaleFactor;232 }233 234 177 void NumberInputType::handleKeydownEvent(KeyboardEvent* event) 235 178 { … … 267 210 return String(); 268 211 return serializeForNumberType(value); 269 }270 271 double NumberInputType::acceptableError(double step) const272 {273 return step / pow(2.0, FLT_MANT_DIG);274 212 } 275 213 -
trunk/Source/WebCore/html/NumberInputType.h
r107555 r117738 47 47 virtual bool typeMismatchFor(const String&) const OVERRIDE; 48 48 virtual bool typeMismatch() const OVERRIDE; 49 virtual bool rangeUnderflow(const String&) const OVERRIDE;50 virtual bool rangeOverflow(const String&) const OVERRIDE;51 virtual bool supportsRangeLimitation() const OVERRIDE;52 virtual double minimum() const OVERRIDE;53 virtual double maximum() const OVERRIDE;54 49 virtual bool sizeShouldIncludeDecoration(int defaultSize, int& preferredSize) const OVERRIDE; 55 50 virtual bool isSteppable() const OVERRIDE; 56 virtual bool stepMismatch(const String&, double) const OVERRIDE; 57 virtual double stepBase() const OVERRIDE; 58 virtual double stepBaseWithDecimalPlaces(unsigned*) const OVERRIDE; 59 virtual double defaultStep() const OVERRIDE; 60 virtual double stepScaleFactor() const OVERRIDE; 51 virtual StepRange createStepRange(AnyStepHandling) const OVERRIDE; 61 52 virtual void handleKeydownEvent(KeyboardEvent*) OVERRIDE; 62 53 virtual void handleWheelEvent(WheelEvent*) OVERRIDE; … … 64 55 virtual double parseToDoubleWithDecimalPlaces(const String&, double, unsigned*) const OVERRIDE; 65 56 virtual String serialize(double) const OVERRIDE; 66 virtual double acceptableError(double) const OVERRIDE;67 57 virtual void handleBlurEvent() OVERRIDE; 68 58 virtual String visibleValue() const OVERRIDE; -
trunk/Source/WebCore/html/RangeInputType.cpp
r116730 r117738 58 58 static const double rangeDefaultMaximum = 100.0; 59 59 static const double rangeDefaultStep = 1.0; 60 static const double rangeDefaultStepBase = 0.0; 60 61 static const double rangeStepScaleFactor = 1.0; 61 62 … … 90 91 } 91 92 92 bool RangeInputType::rangeUnderflow(const String& value) const 93 { 94 // Guaranteed by sanitization. 95 ASSERT_UNUSED(value, parseToDouble(value, numeric_limits<double>::quiet_NaN()) >= minimum()); 96 return false; 97 } 98 99 bool RangeInputType::rangeOverflow(const String& value) const 100 { 101 // Guaranteed by sanitization. 102 ASSERT_UNUSED(value, parseToDouble(value, numeric_limits<double>::quiet_NaN()) <= maximum()); 103 return false; 104 } 105 106 bool RangeInputType::supportsRangeLimitation() const 93 StepRange RangeInputType::createStepRange(AnyStepHandling anyStepHandling) const 94 { 95 DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (rangeDefaultStep, rangeDefaultStepBase, rangeStepScaleFactor)); 96 97 double minimum = parseToDouble(element()->fastGetAttribute(minAttr), rangeDefaultMinimum); 98 double maximum = parseToDouble(element()->fastGetAttribute(maxAttr), rangeDefaultMaximum); 99 if (maximum < minimum) 100 maximum = max(minimum, rangeDefaultMaximum); 101 102 const AtomicString& precisionValue = element()->fastGetAttribute(precisionAttr); 103 if (!precisionValue.isNull()) { 104 StepRange::DoubleWithDecimalPlacesOrMissing step(1, !equalIgnoringCase(precisionValue, "float")); 105 return StepRange(minimum, minimum, maximum, step, stepDescription); 106 } 107 108 StepRange::DoubleWithDecimalPlacesOrMissing step = StepRange::parseStep(anyStepHandling, stepDescription, element()->fastGetAttribute(stepAttr)); 109 return StepRange(minimum, minimum, maximum, step, stepDescription); 110 } 111 112 bool RangeInputType::isSteppable() const 107 113 { 108 114 return true; 109 }110 111 double RangeInputType::minimum() const112 {113 return parseToDouble(element()->fastGetAttribute(minAttr), rangeDefaultMinimum);114 }115 116 double RangeInputType::maximum() const117 {118 double max = parseToDouble(element()->fastGetAttribute(maxAttr), rangeDefaultMaximum);119 // A remedy for the inconsistent min/max values.120 // Sets the maximum to the default or the minimum value.121 double min = minimum();122 if (max < min)123 max = std::max(min, rangeDefaultMaximum);124 return max;125 }126 127 bool RangeInputType::isSteppable() const128 {129 return true;130 }131 132 bool RangeInputType::stepMismatch(const String&, double) const133 {134 // stepMismatch doesn't occur for type=range. RenderSlider guarantees the135 // value matches to step on user input, and sanitization takes care136 // of the general case.137 return false;138 }139 140 double RangeInputType::stepBase() const141 {142 return minimum();143 }144 145 double RangeInputType::defaultStep() const146 {147 return rangeDefaultStep;148 }149 150 double RangeInputType::stepScaleFactor() const151 {152 return rangeStepScaleFactor;153 115 } 154 116 … … 179 141 double current = parseToDouble(element()->value(), numeric_limits<double>::quiet_NaN()); 180 142 ASSERT(isfinite(current)); 143 144 StepRange stepRange(createStepRange(RejectAny)); 181 145 182 146 double step, bigStep; … … 184 148 // FIXME: We can't use stepUp() for the step value "any". So, we increase 185 149 // or decrease the value by 1/100 of the value range. Is it reasonable? 186 step = ( maximum() -minimum()) / 100;150 step = (stepRange.maximum() - stepRange.minimum()) / 100; 187 151 bigStep = step * 10; 188 152 } else { … … 190 154 ASSERT_NOT_REACHED(); 191 155 192 bigStep = ( maximum() -minimum()) / 10;156 bigStep = (stepRange.maximum() - stepRange.minimum()) / 10; 193 157 if (bigStep < step) 194 158 bigStep = step; … … 215 179 newValue = current - bigStep; 216 180 else if (key == "Home") 217 newValue = isVertical ? maximum() :minimum();181 newValue = isVertical ? stepRange.maximum() : stepRange.minimum(); 218 182 else if (key == "End") 219 newValue = isVertical ? minimum() :maximum();183 newValue = isVertical ? stepRange.minimum() : stepRange.maximum(); 220 184 else 221 185 return; // Did not match any key binding. 222 186 223 newValue = StepRange(element()).clampValue(newValue);187 newValue = stepRange.clampValue(newValue); 224 188 225 189 if (newValue != current) { … … 304 268 String RangeInputType::fallbackValue() const 305 269 { 306 return serializeForNumberType( StepRange(element()).defaultValue());270 return serializeForNumberType(createStepRange(RejectAny).defaultValue()); 307 271 } 308 272 309 273 String RangeInputType::sanitizeValue(const String& proposedValue) const 310 274 { 311 return serializeForNumberType(StepRange(element()).clampValue(proposedValue)); 275 StepRange stepRange(createStepRange(RejectAny)); 276 double proposedDoubleValue = parseToDouble(proposedValue, stepRange.defaultValue()); 277 return serializeForNumberType(stepRange.clampValue(proposedDoubleValue)); 312 278 } 313 279 -
trunk/Source/WebCore/html/RangeInputType.h
r107555 r117738 49 49 virtual void setValueAsNumber(double, TextFieldEventBehavior, ExceptionCode&) const OVERRIDE; 50 50 virtual bool supportsRequired() const OVERRIDE; 51 virtual bool rangeUnderflow(const String&) const OVERRIDE; 52 virtual bool rangeOverflow(const String&) const OVERRIDE; 53 virtual bool supportsRangeLimitation() const OVERRIDE; 54 virtual double minimum() const OVERRIDE; 55 virtual double maximum() const OVERRIDE; 51 virtual StepRange createStepRange(AnyStepHandling) const OVERRIDE; 56 52 virtual bool isSteppable() const OVERRIDE; 57 virtual bool stepMismatch(const String&, double) const OVERRIDE;58 virtual double stepBase() const OVERRIDE;59 virtual double defaultStep() const OVERRIDE;60 virtual double stepScaleFactor() const OVERRIDE;61 53 virtual void handleMouseDownEvent(MouseEvent*) OVERRIDE; 62 54 virtual void handleKeydownEvent(KeyboardEvent*) OVERRIDE; -
trunk/Source/WebCore/html/StepRange.cpp
r115434 r117738 22 22 #include "StepRange.h" 23 23 24 #include "HTMLInputElement.h"25 24 #include "HTMLNames.h" 26 25 #include "HTMLParserIdioms.h" … … 34 33 using namespace HTMLNames; 35 34 36 StepRange::StepRange(const HTMLInputElement* element) 35 StepRange::StepRange() 36 : m_maximum(100) 37 , m_minimum(0) 38 , m_step(1) 39 , m_stepBase(0) 40 , m_stepBaseDecimalPlaces(0) 41 , m_stepDecimalPlaces(0) 42 , m_hasStep(false) 37 43 { 38 step = 1; 39 const AtomicString& precisionValue = element->fastGetAttribute(precisionAttr); 40 if (!precisionValue.isNull()) 41 hasStep = !equalIgnoringCase(precisionValue, "float"); 42 else 43 hasStep = element->getAllowedValueStep(&step); 44 45 maximum = element->maximum(); 46 minimum = element->minimum(); 44 ASSERT_NOT_REACHED(); 47 45 } 48 46 49 double StepRange::clampValue(double value) 47 StepRange::StepRange(const StepRange& stepRange) 48 : m_maximum(stepRange.m_maximum) 49 , m_minimum(stepRange.m_minimum) 50 , m_step(stepRange.m_step) 51 , m_stepBase(stepRange.m_stepBase) 52 , m_stepDescription(stepRange.m_stepDescription) 53 , m_stepBaseDecimalPlaces(stepRange.m_stepBaseDecimalPlaces) 54 , m_stepDecimalPlaces(stepRange.m_stepDecimalPlaces) 55 , m_hasStep(stepRange.m_hasStep) 50 56 { 51 double clampedValue = max(minimum, min(value, maximum)); 52 if (!hasStep) 57 } 58 59 StepRange::StepRange(const DoubleWithDecimalPlaces& stepBase, double minimum, double maximum, const DoubleWithDecimalPlacesOrMissing& step, const StepDescription& stepDescription) 60 : m_maximum(maximum) 61 , m_minimum(minimum) 62 , m_step(step.value.value) 63 , m_stepBase(stepBase.value) 64 , m_stepDescription(stepDescription) 65 , m_stepBaseDecimalPlaces(stepBase.decimalPlaces) 66 , m_stepDecimalPlaces(step.value.decimalPlaces) 67 , m_hasStep(step.hasValue) 68 { 69 ASSERT(isfinite(m_maximum)); 70 ASSERT(isfinite(m_minimum)); 71 ASSERT(isfinite(m_step)); 72 ASSERT(isfinite(m_stepBase)); 73 } 74 75 double StepRange::acceptableError() const 76 { 77 return m_step / pow(2.0, FLT_MANT_DIG); 78 } 79 80 double StepRange::alignValueForStep(double currentValue, unsigned currentDecimalPlaces, double newValue) const 81 { 82 if (newValue >= pow(10.0, 21.0)) 83 return newValue; 84 85 if (stepMismatch(currentValue)) { 86 double scale = pow(10.0, static_cast<double>(max(m_stepDecimalPlaces, currentDecimalPlaces))); 87 newValue = round(newValue * scale) / scale; 88 } else { 89 double scale = pow(10.0, static_cast<double>(max(m_stepDecimalPlaces, m_stepBaseDecimalPlaces))); 90 newValue = round((m_stepBase + round((newValue - m_stepBase) / m_step) * m_step) * scale) / scale; 91 } 92 93 return newValue; 94 } 95 double StepRange::clampValue(double value) const 96 { 97 double clampedValue = max(m_minimum, min(value, m_maximum)); 98 if (!m_hasStep) 53 99 return clampedValue; 54 100 // Rounds clampedValue to minimum + N * step. 55 clampedValue = m inimum + round((clampedValue - minimum) / step) *step;56 if (clampedValue > m aximum)57 clampedValue -= step;58 ASSERT(clampedValue >= m inimum);59 ASSERT(clampedValue <= m aximum);101 clampedValue = m_minimum + round((clampedValue - m_minimum) / m_step) * m_step; 102 if (clampedValue > m_maximum) 103 clampedValue -= m_step; 104 ASSERT(clampedValue >= m_minimum); 105 ASSERT(clampedValue <= m_maximum); 60 106 return clampedValue; 61 107 } 62 108 63 double StepRange::clampValue(const String& stringValue)109 StepRange::DoubleWithDecimalPlacesOrMissing StepRange::parseStep(AnyStepHandling anyStepHandling, const StepDescription& stepDescription, const String& stepString) 64 110 { 65 double value; 66 bool parseSuccess = parseToDoubleForNumberType(stringValue, &value); 67 if (!parseSuccess) 68 value = (minimum + maximum) / 2; 69 return clampValue(value); 111 ASSERT(isfinite(stepDescription.defaultStep)); 112 ASSERT(isfinite(stepDescription.stepScaleFactor)); 113 114 if (stepString.isEmpty()) 115 return DoubleWithDecimalPlacesOrMissing(stepDescription.defaultValue()); 116 117 if (equalIgnoringCase(stepString, "any")) { 118 switch (anyStepHandling) { 119 case RejectAny: 120 return DoubleWithDecimalPlacesOrMissing(DoubleWithDecimalPlaces(1), false); 121 case AnyIsDefaultStep: 122 return DoubleWithDecimalPlacesOrMissing(stepDescription.defaultValue()); 123 default: 124 ASSERT_NOT_REACHED(); 125 } 126 } 127 128 DoubleWithDecimalPlacesOrMissing step(0); 129 if (!parseToDoubleForNumberTypeWithDecimalPlaces(stepString, &step.value.value, &step.value.decimalPlaces) || step.value.value <= 0.0) 130 return DoubleWithDecimalPlacesOrMissing(stepDescription.defaultValue()); 131 132 switch (stepDescription.stepValueShouldBe) { 133 case StepValueShouldBeReal: 134 step.value.value *= stepDescription.stepScaleFactor; 135 break; 136 case ParsedStepValueShouldBeInteger: 137 // For date, month, and week, the parsed value should be an integer for some types. 138 step.value.value = max(round(step.value.value), 1.0); 139 step.value.value *= stepDescription.stepScaleFactor; 140 break; 141 case ScaledStepValueShouldBeInteger: 142 // For datetime, datetime-local, time, the result should be an integer. 143 step.value.value *= stepDescription.stepScaleFactor; 144 step.value.value = max(round(step.value.value), 1.0); 145 break; 146 default: 147 ASSERT_NOT_REACHED(); 148 } 149 150 ASSERT(step.value.value > 0); 151 return step; 70 152 } 71 153 72 double StepRange::valueFromElement(HTMLInputElement* element, bool* wasClamped) 154 bool StepRange::stepMismatch(double doubleValue) const 73 155 { 74 double oldValue; 75 bool parseSuccess = parseToDoubleForNumberType(element->value(), &oldValue); 76 if (!parseSuccess) 77 oldValue = (minimum + maximum) / 2; 78 double newValue = clampValue(oldValue); 79 80 if (wasClamped) 81 *wasClamped = !parseSuccess || newValue != oldValue; 82 83 return newValue; 156 if (!m_hasStep) 157 return false; 158 if (!isfinite(doubleValue)) 159 return false; 160 doubleValue = fabs(doubleValue - m_stepBase); 161 if (isinf(doubleValue)) 162 return false; 163 // double's fractional part size is DBL_MAN_DIG-bit. If the current value 164 // is greater than step*2^DBL_MANT_DIG, the following computation for 165 // remainder makes no sense. 166 if (doubleValue / pow(2.0, DBL_MANT_DIG) > m_step) 167 return false; 168 // The computation follows HTML5 4.10.7.2.10 `The step attribute' : 169 // ... that number subtracted from the step base is not an integral multiple 170 // of the allowed value step, the element is suffering from a step mismatch. 171 double remainder = fabs(doubleValue - m_step * round(doubleValue / m_step)); 172 // Accepts erros in lower fractional part which IEEE 754 single-precision 173 // can't represent. 174 double computedAcceptableError = acceptableError(); 175 return computedAcceptableError < remainder && remainder < (m_step - computedAcceptableError); 84 176 } 85 177 86 } 178 } // namespace WebCore -
trunk/Source/WebCore/html/StepRange.h
r95901 r117738 29 29 class HTMLInputElement; 30 30 31 enum AnyStepHandling { RejectAny, AnyIsDefaultStep }; 32 31 33 class StepRange { 32 WTF_MAKE_NONCOPYABLE(StepRange);33 34 public: 34 bool hasStep; 35 double step; 36 double minimum; 37 double maximum; // maximum must be >= minimum. 35 struct DoubleWithDecimalPlaces { 36 unsigned decimalPlaces; 37 double value; 38 38 39 explicit StepRange(const HTMLInputElement*); 40 double clampValue(double value); 41 double clampValue(const String& stringValue); 39 DoubleWithDecimalPlaces(double value = 0, unsigned decimalPlaces = 0) 40 : decimalPlaces(decimalPlaces) 41 , value(value) 42 { 43 } 44 }; 45 46 struct DoubleWithDecimalPlacesOrMissing { 47 bool hasValue; 48 DoubleWithDecimalPlaces value; 49 50 DoubleWithDecimalPlacesOrMissing(DoubleWithDecimalPlaces value, bool hasValue = true) 51 : hasValue(hasValue) 52 , value(value) 53 { 54 } 55 }; 56 57 enum StepValueShouldBe { 58 StepValueShouldBeReal, 59 ParsedStepValueShouldBeInteger, 60 ScaledStepValueShouldBeInteger, 61 }; 62 63 struct StepDescription { 64 int defaultStep; 65 int defaultStepBase; 66 int stepScaleFactor; 67 StepValueShouldBe stepValueShouldBe; 68 69 StepDescription(int defaultStep, int defaultStepBase, int stepScaleFactor, StepValueShouldBe stepValueShouldBe = StepValueShouldBeReal) 70 : defaultStep(defaultStep) 71 , defaultStepBase(defaultStepBase) 72 , stepScaleFactor(stepScaleFactor) 73 , stepValueShouldBe(stepValueShouldBe) 74 { 75 } 76 77 StepDescription() 78 : defaultStep(1) 79 , defaultStepBase(0) 80 , stepScaleFactor(1) 81 , stepValueShouldBe(StepValueShouldBeReal) 82 { 83 ASSERT_NOT_REACHED(); 84 } 85 86 double defaultValue() const 87 { 88 return defaultStep * stepScaleFactor; 89 } 90 }; 91 92 StepRange(); 93 StepRange(const StepRange&); 94 StepRange(const DoubleWithDecimalPlaces& stepBase, double minimum, double maximum, const DoubleWithDecimalPlacesOrMissing& step, const StepDescription&); 95 double acceptableError() const; 96 double alignValueForStep(double currentValue, unsigned currentDecimalPlaces, double newValue) const; 97 double clampValue(double value) const; 98 bool hasStep() const { return m_hasStep; } 99 double maximum() const { return m_maximum; } 100 double minimum() const { return m_minimum; } 101 static DoubleWithDecimalPlacesOrMissing parseStep(AnyStepHandling, const StepDescription&, const String&); 102 double step() const { return m_step; } 103 double stepBase() const { return m_stepBase; } 104 unsigned stepBaseDecimalPlaces() const { return m_stepBaseDecimalPlaces; } 105 unsigned stepDecimalPlaces() const { return m_stepDecimalPlaces; } 106 int stepScaleFactor() const { return m_stepDescription.stepScaleFactor; } 107 bool stepMismatch(double) const; 42 108 43 109 // Clamp the middle value according to the step 44 110 double defaultValue() 45 111 { 46 return clampValue((m inimum +maximum) / 2);112 return clampValue((m_minimum + m_maximum) / 2); 47 113 } 48 114 … … 50 116 double proportionFromValue(double value) 51 117 { 52 if (m inimum ==maximum)118 if (m_minimum == m_maximum) 53 119 return 0; 54 120 55 return (value - m inimum) / (maximum -minimum);121 return (value - m_minimum) / (m_maximum - m_minimum); 56 122 } 57 123 … … 59 125 double valueFromProportion(double proportion) 60 126 { 61 return m inimum + proportion * (maximum -minimum);127 return m_minimum + proportion * (m_maximum - m_minimum); 62 128 } 63 129 64 double valueFromElement(HTMLInputElement*, bool* wasClamped = 0); 130 private: 131 StepRange& operator =(const StepRange&); 132 133 const double m_maximum; // maximum must be >= minimum. 134 const double m_minimum; 135 const double m_step; 136 const double m_stepBase; 137 const StepDescription m_stepDescription; 138 const unsigned m_stepBaseDecimalPlaces; 139 const unsigned m_stepDecimalPlaces; 140 const bool m_hasStep; 65 141 }; 66 142 -
trunk/Source/WebCore/html/TimeInputType.cpp
r116499 r117738 47 47 48 48 static const double timeDefaultStep = 60.0; 49 static const double timeDefaultStepBase = 0.0; 49 50 static const double timeStepScaleFactor = 1000.0; 50 51 … … 79 80 } 80 81 81 double TimeInputType::minimum() const82 StepRange TimeInputType::createStepRange(AnyStepHandling anyStepHandling) const 82 83 { 83 return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumTime()); 84 } 84 DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (timeDefaultStep, timeDefaultStepBase, timeStepScaleFactor, StepRange::ScaledStepValueShouldBeInteger)); 85 85 86 double TimeInputType::maximum() const 87 { 88 return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumTime()); 89 } 90 91 double TimeInputType::defaultStep() const 92 { 93 return timeDefaultStep; 94 } 95 96 double TimeInputType::stepScaleFactor() const 97 { 98 return timeStepScaleFactor; 99 } 100 101 bool TimeInputType::scaledStepValueShouldBeInteger() const 102 { 103 return true; 86 double stepBase = parseToDouble(element()->fastGetAttribute(minAttr), 0); 87 double minimum = parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumTime()); 88 double maximum = parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumTime()); 89 StepRange::DoubleWithDecimalPlacesOrMissing step = StepRange::parseStep(anyStepHandling, stepDescription, element()->fastGetAttribute(stepAttr)); 90 return StepRange(stepBase, minimum, maximum, step, stepDescription); 104 91 } 105 92 -
trunk/Source/WebCore/html/TimeInputType.h
r116499 r117738 47 47 virtual DateComponents::Type dateType() const OVERRIDE; 48 48 virtual double defaultValueForStepUp() const OVERRIDE; 49 virtual double minimum() const OVERRIDE; 50 virtual double maximum() const OVERRIDE; 51 virtual double defaultStep() const OVERRIDE; 52 virtual double stepScaleFactor() const OVERRIDE; 53 virtual bool scaledStepValueShouldBeInteger() const OVERRIDE; 49 virtual StepRange createStepRange(AnyStepHandling) const OVERRIDE; 54 50 virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const OVERRIDE; 55 51 virtual bool setMillisecondToDateComponents(double, DateComponents*) const OVERRIDE; -
trunk/Source/WebCore/html/WeekInputType.cpp
r116499 r117738 62 62 } 63 63 64 double WeekInputType::minimum() const64 StepRange WeekInputType::createStepRange(AnyStepHandling anyStepHandling) const 65 65 { 66 return parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumWeek()); 67 } 66 DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (weekDefaultStep, weekDefaultStepBase, weekStepScaleFactor, StepRange::ParsedStepValueShouldBeInteger)); 68 67 69 double WeekInputType::maximum() const 70 { 71 return parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumWeek()); 72 } 73 74 double WeekInputType::stepBase() const 75 { 76 return parseToDouble(element()->fastGetAttribute(minAttr), weekDefaultStepBase); 77 } 78 79 double WeekInputType::defaultStep() const 80 { 81 return weekDefaultStep; 82 } 83 84 double WeekInputType::stepScaleFactor() const 85 { 86 return weekStepScaleFactor; 87 } 88 89 bool WeekInputType::parsedStepValueShouldBeInteger() const 90 { 91 return true; 68 double stepBase = parseToDouble(element()->fastGetAttribute(minAttr), weekDefaultStepBase); 69 double minimum = parseToDouble(element()->fastGetAttribute(minAttr), DateComponents::minimumWeek()); 70 double maximum = parseToDouble(element()->fastGetAttribute(maxAttr), DateComponents::maximumWeek()); 71 StepRange::DoubleWithDecimalPlacesOrMissing step = StepRange::parseStep(anyStepHandling, stepDescription, element()->fastGetAttribute(stepAttr)); 72 return StepRange(stepBase, minimum, maximum, step, stepDescription); 92 73 } 93 74 -
trunk/Source/WebCore/html/WeekInputType.h
r116499 r117738 46 46 virtual const AtomicString& formControlType() const OVERRIDE; 47 47 virtual DateComponents::Type dateType() const OVERRIDE; 48 virtual double minimum() const OVERRIDE; 49 virtual double maximum() const OVERRIDE; 50 virtual double stepBase() const OVERRIDE; 51 virtual double defaultStep() const OVERRIDE; 52 virtual double stepScaleFactor() const OVERRIDE; 53 virtual bool parsedStepValueShouldBeInteger() const OVERRIDE; 48 virtual StepRange createStepRange(AnyStepHandling) const OVERRIDE; 54 49 virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const OVERRIDE; 55 50 virtual bool setMillisecondToDateComponents(double, DateComponents*) const OVERRIDE; -
trunk/Source/WebCore/html/shadow/SliderThumbElement.cpp
r116730 r117738 54 54 inline static double sliderPosition(HTMLInputElement* element) 55 55 { 56 StepRange range(element); 57 return range.proportionFromValue(range.valueFromElement(element)); 56 StepRange stepRange(element->createStepRange(RejectAny)); 57 58 double oldValue; 59 bool parseSuccess = parseToDoubleForNumberType(element->value(), &oldValue); 60 if (!parseSuccess) 61 oldValue = stepRange.defaultValue(); 62 double newValue = stepRange.clampValue(oldValue); 63 return stepRange.proportionFromValue(newValue); 58 64 } 59 65 … … 236 242 return; 237 243 238 StepRange range(input);239 244 double fraction = static_cast<double>(position) / trackSize; 240 245 if (isVertical || !renderBox()->style()->isLeftToRightDirection()) 241 246 fraction = 1 - fraction; 242 double value = range.clampValue(range.valueFromProportion(fraction)); 247 StepRange stepRange(input->createStepRange(RejectAny)); 248 double value = stepRange.clampValue(stepRange.valueFromProportion(fraction)); 243 249 244 250 // FIXME: This is no longer being set from renderer. Consider updating the method name.
Note: See TracChangeset
for help on using the changeset viewer.