Support min() and max() in calc()
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Sep 2017 23:36:20 +0000 (23:36 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Sep 2017 23:36:20 +0000 (23:36 +0000)
commit56043b12e6741ae0dec70e9501b09a638c174a50
treec4e13423b9834f821ca7e245e8575bf3d6717d6c
parent88c0a5cdcbb71b4310254d97875eb776cc7ba952
Support min() and max() in calc()
https://bugs.webkit.org/show_bug.cgi?id=167000
<rdar://problem/30153481>

Reviewed by David Hyatt.
Patch originally by Myles Maxfield.

Source/WebCore:

Add two new toplevel functions to CSS, min() and max(), which take an
arbirary number of arguments and resolve to the minimum and maximum of
the resolved value of the arguments, respectively. It is also possible
to use min() and max() inside calc(), and to use calc()-like math
inside min() and max().

* css/CSSCalculationValue.cpp:
(WebCore::determineCategory):
min and max operators don't use determineCategory; we have a specific
implementation for them in createMinOrMax.

(WebCore::resolvedTypeForMinOrMax):
The spec says that min() and max() should be marked as invalid if they
have values of more than one type, but that percentages should resolve
against the destination type before making this determination. So,
if the destination type is length, percent turns into percent-length,
and similarly for number.

(WebCore::isIntegerResult):
Add an n-way implementation of isIntegerResult.

(WebCore::isSamePair):
(WebCore::CSSCalcOperation::createMinOrMax): Create a min() or max()
operation, as long as the types of arguments are all the same. Allow
lengths to upgrade the whole operation to percent-length, and numbers
to percent-number, which will cause us to use CalculationValue and friends
in order to do proper resolution of all of the parameters instead of
just comparing their numeric values.

(WebCore::CSSCalcOperation::createCalcExpression):
(WebCore::CSSCalcOperation::doubleValue):
(WebCore::CSSCalcOperation::computeLengthPx):
(WebCore::CSSCalcOperation::customCSSText):
(WebCore::CSSCalcOperation::primitiveType):
(WebCore::CSSCalcOperation::CSSCalcOperation):
(WebCore::CSSCalcOperation::evaluate):
(WebCore::CSSCalcOperation::evaluateOperator):
Adapt to child counts greater than two.

(WebCore::CSSCalcOperation::buildCssText):
Add support for min() and max().

(WebCore::CSSCalcExpressionNodeParser::parseCalc):
parseCalc now accepts a CSSValueID parameter indicating which calc function
it should parse (calc, webkit-calc, min, or max), and delegates to either
parseValueExpression or parseMinMaxExpression.

(WebCore::CSSCalcExpressionNodeParser::operatorValue):
(WebCore::CSSCalcExpressionNodeParser::parseValue):
If min() or max() are found while parsing a value (i.e. nested inside
either calc or themselves), use parseMinMaxExpression on that subtree.

(WebCore::CSSCalcExpressionNodeParser::parseValueTerm):
(WebCore::CSSCalcExpressionNodeParser::parseValueMultiplicativeExpression):
(WebCore::CSSCalcExpressionNodeParser::parseAdditiveValueExpression):
Adjust to the CSSCalcBinaryOperation->CSSCalcOperation rename.

(WebCore::CSSCalcExpressionNodeParser::parseMinMaxExpression):
Added. Parse an arbitrary number of comma-and-whitespace-separated children.

(WebCore::createBlendHalf):
Adjust to the CSSCalcBinaryOperation->CSSCalcOperation rename.

(WebCore::createCSS):
Build the CSSCalcOperation for the platform-independent min and max operations.

(WebCore::CSSCalcValue::create):
Pass the function being parsed and the destination calc category for the
property being parsed for into create, and then into the parser so that
it can know which function it is parsing for, and what kind of result it
needs (as previously mentioned above in resolvedTypeForMinOrMax).

* css/CSSCalculationValue.h:
* css/CSSValueKeywords.in:
Add min and max functions as CSS keywords.

* css/StyleBuilderConverter.h:
(WebCore::StyleBuilderConverter::convertLength):
(WebCore::StyleBuilderConverter::convertTo100PercentMinusLength):
* platform/Length.cpp:
(WebCore::convertTo100PercentMinusLength):
Adapt to the CalcExpressionOperation constructor taking a vector of
arguments instead of two.

* css/parser/CSSPropertyParserHelpers.cpp:
(WebCore::CSSPropertyParserHelpers::CalcParser::CalcParser):
Store and pass the specific function being parsed down into CSSCalcValue.

(WebCore::CSSPropertyParserHelpers::consumeInteger):
(WebCore::CSSPropertyParserHelpers::consumePositiveIntegerRaw):
(WebCore::CSSPropertyParserHelpers::consumeNumberRaw):
(WebCore::CSSPropertyParserHelpers::consumeNumber):
(WebCore::CSSPropertyParserHelpers::consumeFontWeightNumber):
(WebCore::CSSPropertyParserHelpers::consumeLength):
(WebCore::CSSPropertyParserHelpers::consumePercent):
(WebCore::CSSPropertyParserHelpers::consumeLengthOrPercent):
(WebCore::CSSPropertyParserHelpers::consumeAngle):
(WebCore::CSSPropertyParserHelpers::consumeTime):
Pass the destination type into each calc parser.

* platform/CalculationValue.cpp:
(WebCore::CalcExpressionOperation::evaluate const):
(WebCore::CalcExpressionOperation::operator== const):
(WebCore::CalcExpressionOperation::dump const):
(WebCore::operator<<):
(WebCore::CalcExpressionBinaryOperation::evaluate const): Deleted.
(WebCore::CalcExpressionBinaryOperation::operator== const): Deleted.
(WebCore::CalcExpressionBinaryOperation::dump const): Deleted.
* platform/CalculationValue.h:
(WebCore::CalcExpressionOperation::CalcExpressionOperation):
(WebCore::operator==):
(WebCore::toCalcExpressionOperation):
(WebCore::CalcExpressionBinaryOperation::CalcExpressionBinaryOperation): Deleted.
(WebCore::toCalcExpressionBinaryOperation): Deleted.
Adjust to the CSSCalcBinaryOperation->CSSCalcOperation rename.
Adjust to having n>2 children.
Support min() and max() operators in various places.

LayoutTests:

* css3/calc/minmax-errors-expected.txt:
* css3/calc/minmax-errors.html:
* css3/calc/simple-minmax-expected.txt:
* css3/calc/simple-minmax.html:
Revive previously-unused tests for an earlier never-implemented version
of this feature, and add a bunch more interesting test cases from reading the spec.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@222190 268f45cc-cd09-0410-ab3c-d52691b4dbfc
14 files changed:
LayoutTests/ChangeLog
LayoutTests/css3/calc/minmax-errors-expected.txt
LayoutTests/css3/calc/minmax-errors.html
LayoutTests/css3/calc/simple-minmax-expected.txt
LayoutTests/css3/calc/simple-minmax.html
Source/WebCore/ChangeLog
Source/WebCore/css/CSSCalculationValue.cpp
Source/WebCore/css/CSSCalculationValue.h
Source/WebCore/css/CSSValueKeywords.in
Source/WebCore/css/StyleBuilderConverter.h
Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp
Source/WebCore/platform/CalculationValue.cpp
Source/WebCore/platform/CalculationValue.h
Source/WebCore/platform/Length.cpp