Changeset 282795 in webkit


Ignore:
Timestamp:
Sep 20, 2021 5:24:50 PM (10 months ago)
Author:
commit-queue@webkit.org
Message:

Implement exp,log functions calc functions
https://bugs.webkit.org/show_bug.cgi?id=229897

Patch by Nikos Mouchtaris <Nikos Mouchtaris> on 2021-09-20
Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

  • web-platform-tests/css/css-values/exp-log-compute.html: Added.
  • web-platform-tests/css/css-values/exp-log-invalid.html: Added.
  • web-platform-tests/css/css-values/exp-log-serialize.html: Added.

Source/WebCore:

Added support for calc functions exp and log. Involved adding exp and log CSS keywords and handling
for parsing these functions and their arguments as well as computing the result based on the arguments.
Spec for these functions: https://drafts.csswg.org/css-values-4/#exponent-funcs.

Tests: imported/w3c/web-platform-tests/css/css-values/exp-log-compute.html

imported/w3c/web-platform-tests/css/css-values/exp-log-invalid.html
imported/w3c/web-platform-tests/css/css-values/exp-log-serialize.html

  • css/CSSValueKeywords.in:
  • css/calc/CSSCalcExpressionNodeParser.cpp:

(WebCore::CSSCalcExpressionNodeParser::parseCalcFunction):

  • css/calc/CSSCalcOperationNode.cpp:

(WebCore::determineCategory):
(WebCore::functionFromOperator):
(WebCore::CSSCalcOperationNode::createLog):
(WebCore::CSSCalcOperationNode::createExp):
(WebCore::CSSCalcOperationNode::combineChildren):
(WebCore::CSSCalcOperationNode::simplifyNode):
(WebCore::functionPrefixForOperator):
(WebCore::CSSCalcOperationNode::evaluateOperator):

  • css/calc/CSSCalcOperationNode.h:
  • css/calc/CSSCalcValue.cpp:

(WebCore::createCSS):
(WebCore::CSSCalcValue::isCalcFunction):

  • platform/calc/CalcExpressionOperation.cpp:

(WebCore::CalcExpressionOperation::evaluate const):

  • platform/calc/CalcOperator.cpp:

(WebCore::operator<<):

  • platform/calc/CalcOperator.h:
Location:
trunk
Files:
6 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r282778 r282795  
     12021-09-20  Nikos Mouchtaris  <nmouchtaris@apple.com>
     2
     3        Implement exp,log functions calc functions
     4        https://bugs.webkit.org/show_bug.cgi?id=229897
     5
     6        Reviewed by Simon Fraser.
     7
     8        * web-platform-tests/css/css-values/exp-log-compute.html: Added.
     9        * web-platform-tests/css/css-values/exp-log-invalid.html: Added.
     10        * web-platform-tests/css/css-values/exp-log-serialize.html: Added.
     11
    1122021-09-20  Youenn Fablet  <youenn@apple.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r282788 r282795  
     12021-09-20  Nikos Mouchtaris  <nmouchtaris@apple.com>
     2
     3        Implement exp,log functions calc functions
     4        https://bugs.webkit.org/show_bug.cgi?id=229897
     5
     6        Reviewed by Simon Fraser.
     7
     8        Added support for calc functions exp and log. Involved adding exp and log CSS keywords and handling
     9        for parsing these functions and their arguments as well as computing the result based on the arguments.
     10        Spec for these functions: https://drafts.csswg.org/css-values-4/#exponent-funcs.
     11
     12        Tests: imported/w3c/web-platform-tests/css/css-values/exp-log-compute.html
     13               imported/w3c/web-platform-tests/css/css-values/exp-log-invalid.html
     14               imported/w3c/web-platform-tests/css/css-values/exp-log-serialize.html
     15
     16        * css/CSSValueKeywords.in:
     17        * css/calc/CSSCalcExpressionNodeParser.cpp:
     18        (WebCore::CSSCalcExpressionNodeParser::parseCalcFunction):
     19        * css/calc/CSSCalcOperationNode.cpp:
     20        (WebCore::determineCategory):
     21        (WebCore::functionFromOperator):
     22        (WebCore::CSSCalcOperationNode::createLog):
     23        (WebCore::CSSCalcOperationNode::createExp):
     24        (WebCore::CSSCalcOperationNode::combineChildren):
     25        (WebCore::CSSCalcOperationNode::simplifyNode):
     26        (WebCore::functionPrefixForOperator):
     27        (WebCore::CSSCalcOperationNode::evaluateOperator):
     28        * css/calc/CSSCalcOperationNode.h:
     29        * css/calc/CSSCalcValue.cpp:
     30        (WebCore::createCSS):
     31        (WebCore::CSSCalcValue::isCalcFunction):
     32        * platform/calc/CalcExpressionOperation.cpp:
     33        (WebCore::CalcExpressionOperation::evaluate const):
     34        * platform/calc/CalcOperator.cpp:
     35        (WebCore::operator<<):
     36        * platform/calc/CalcOperator.h:
     37
    1382021-09-20  Ross Kirsling  <ross.kirsling@sony.com>
    239
  • trunk/Source/WebCore/css/CSSValueKeywords.in

    r282723 r282795  
    13521352e
    13531353pi
     1354exp
     1355log
    13541356
    13551357from-image
  • trunk/Source/WebCore/css/calc/CSSCalcExpressionNodeParser.cpp

    r282162 r282795  
    130130        maxArgumentCount = 3;
    131131        break;
     132
     133    case CSSValueLog:
     134        maxArgumentCount = 2;
     135        break;
     136    case CSSValueExp:
    132137    case CSSValueSin:
    133138    case CSSValueCos:
     
    187192    case CSSValueCalc:
    188193        result = CSSCalcOperationNode::createSum(WTFMove(nodes));
     194        break;
     195    case CSSValueLog:
     196        result = CSSCalcOperationNode::createLog(WTFMove(nodes));
     197        break;
     198    case CSSValueExp:
     199        result = CSSCalcOperationNode::createExp(WTFMove(nodes));
    189200        break;
    190201    // TODO: clamp, sin, cos, tan, asin, acos, atan, atan2, pow, sqrt, hypot
  • trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp

    r282430 r282795  
    8080    case CalcOperator::Max:
    8181    case CalcOperator::Clamp:
     82    case CalcOperator::Log:
     83    case CalcOperator::Exp:
    8284        ASSERT_NOT_REACHED();
    8385        return CalculationCategory::Other;
     
    151153        case CalcOperator::Max:
    152154        case CalcOperator::Clamp:
     155        case CalcOperator::Log:
     156        case CalcOperator::Exp:
    153157            // The type of a min(), max(), or clamp() expression is the result of adding the types of its comma-separated calculations
    154158            return CalculationCategory::Other;
     
    268272    case CalcOperator::Tan:
    269273        return CSSValueTan;
     274    case CalcOperator::Exp:
     275        return CSSValueExp;
     276    case CalcOperator::Log:
     277        return CSSValueLog;
    270278    }
    271279    return CSSValueCalc;
     
    318326
    319327    return adoptRef(new CSSCalcOperationNode(newCategory, CalcOperator::Multiply, WTFMove(values)));
     328}
     329
     330RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createLog(Vector<Ref<CSSCalcExpressionNode>>&& values)
     331{
     332    if (values.size() != 1 && values.size() != 2)
     333        return nullptr;
     334    for (auto& value : values) {
     335        // TODO: Support infinity
     336        if (value->category() != CalculationCategory::Number || !value->doubleValue(value->primitiveType())) {
     337            LOG_WITH_STREAM(Calc, stream << "Failed to create log node because unable to determine category from " << prettyPrintNodes(values));
     338            return nullptr;
     339        }
     340    }
     341   
     342    // TODO: Support infinity
     343    if ((values.size() == 2 && values[1]->doubleValue(values[1]->primitiveType()) == 1)) {
     344        LOG_WITH_STREAM(Calc, stream << "Failed to create log node because unable to determine category from " << prettyPrintNodes(values));
     345        return nullptr;
     346    }
     347
     348    return adoptRef(new CSSCalcOperationNode(CalculationCategory::Number, CalcOperator::Log, WTFMove(values)));
     349}
     350
     351RefPtr<CSSCalcOperationNode> CSSCalcOperationNode::createExp(Vector<Ref<CSSCalcExpressionNode>>&& values)
     352{
     353    if (values.size() != 1)
     354        return nullptr;
     355
     356    if (values[0]->category() != CalculationCategory::Number) {
     357        LOG_WITH_STREAM(Calc, stream << "Failed to create exp node because unable to determine category from " << prettyPrintNodes(values));
     358        return nullptr;
     359    }
     360
     361    return adoptRef(new CSSCalcOperationNode(CalculationCategory::Number, CalcOperator::Exp, WTFMove(values)));
    320362}
    321363
     
    434476    if (m_children.size() < 2) {
    435477        if (m_children.size() == 1 && isTrigNode()) {
     478            double resolvedValue = doubleValue(m_children[0]->primitiveType());
     479            auto newChild = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(resolvedValue, CSSUnitType::CSS_NUMBER));
     480            m_children.clear();
     481            m_children.append(WTFMove(newChild));
     482        }
     483       
     484        if (isExpNode()) {
    436485            double resolvedValue = doubleValue(m_children[0]->primitiveType());
    437486            auto newChild = CSSCalcPrimitiveValueNode::create(CSSPrimitiveValue::create(resolvedValue, CSSUnitType::CSS_NUMBER));
     
    631680        auto& calcOperationNode = downcast<CSSCalcOperationNode>(rootNode.get());
    632681        // Simplify operations with only one child node (other than root and operations that only need one node).
    633         if (calcOperationNode.children().size() == 1 && depth && !calcOperationNode.isTrigNode())
     682        if (calcOperationNode.children().size() == 1 && depth && !calcOperationNode.isTrigNode() && !calcOperationNode.isExpNode())
    634683            return WTFMove(calcOperationNode.children()[0]);
    635684       
     
    648697       
    649698        if (calcOperationNode.isTrigNode() && depth)
     699            calcOperationNode.combineChildren();
     700       
     701        if (calcOperationNode.isExpNode() && depth)
    650702            calcOperationNode.combineChildren();
    651703       
     
    841893    case CalcOperator::Max: return "max(";
    842894    case CalcOperator::Clamp: return "clamp(";
     895    case CalcOperator::Exp: return "exp(";
     896    case CalcOperator::Log: return "log(";
    843897    }
    844898   
     
    10571111        return std::tan(children[0]);
    10581112    }
     1113    case CalcOperator::Log: {
     1114        if (children.size() != 1 && children.size() != 2)
     1115            return std::numeric_limits<double>::quiet_NaN();
     1116        if (children.size() == 1)
     1117            return std::log(children[0]);
     1118        return std::log(children[0]) / std::log(children[1]);
     1119    }
     1120    case CalcOperator::Exp: {
     1121        if (children.size() != 1)
     1122            return std::numeric_limits<double>::quiet_NaN();
     1123        return std::exp(children[0]);
     1124    }
    10591125    }
    10601126    ASSERT_NOT_REACHED();
  • trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h

    r282162 r282795  
    3939    static RefPtr<CSSCalcOperationNode> createMinOrMaxOrClamp(CalcOperator, Vector<Ref<CSSCalcExpressionNode>>&& values, CalculationCategory destinationCategory);
    4040    static RefPtr<CSSCalcOperationNode> createTrig(CalcOperator, Vector<Ref<CSSCalcExpressionNode>>&& values);
     41    static RefPtr<CSSCalcOperationNode> createLog(Vector<Ref<CSSCalcExpressionNode>>&& values);
     42    static RefPtr<CSSCalcOperationNode> createExp(Vector<Ref<CSSCalcExpressionNode>>&& values);
    4143
    4244    static Ref<CSSCalcExpressionNode> simplify(Ref<CSSCalcExpressionNode>&&);
     
    4951    bool isMinOrMaxNode() const { return m_operator == CalcOperator::Min || m_operator == CalcOperator::Max; }
    5052    bool isTrigNode() const { return m_operator == CalcOperator::Sin || m_operator == CalcOperator::Cos || m_operator == CalcOperator::Tan; }
     53    bool isExpNode() const { return m_operator == CalcOperator::Exp || m_operator == CalcOperator::Log; }
    5154    bool shouldSortChildren() const { return isCalcSumNode() || isCalcProductNode(); }
    5255
  • trunk/Source/WebCore/css/calc/CSSCalcValue.cpp

    r282162 r282795  
    181181            return CSSCalcOperationNode::createMinOrMaxOrClamp(op, WTFMove(children), operationNode.destinationCategory());
    182182        }
     183        case CalcOperator::Log: {
     184            auto children = createCSS(operationChildren, style);
     185            if (children.size() != 1 && children.size() != 2)
     186                return nullptr;
     187            return CSSCalcOperationNode::createLog(WTFMove(children));
     188        }
     189        case CalcOperator::Exp: {
     190            auto children = createCSS(operationChildren, style);
     191            if (children.size() != 1)
     192                return nullptr;
     193            return CSSCalcOperationNode::createExp(WTFMove(children));
     194        }
    183195        }
    184196        return nullptr;
     
    295307    case CSSValueCos:
    296308    case CSSValueTan:
     309    case CSSValueExp:
     310    case CSSValueLog:
    297311        return true;
    298312    default:
  • trunk/Source/WebCore/platform/calc/CalcExpressionOperation.cpp

    r282162 r282795  
    103103        return std::tan(m_children[0]->evaluate(maxValue));
    104104    }
     105    case CalcOperator::Log: {
     106        if (m_children.size() != 1 && m_children.size() != 2)
     107            return std::numeric_limits<float>::quiet_NaN();
     108        if (m_children.size() == 1)
     109            return std::log(m_children[0]->evaluate(maxValue));
     110        return std::log(m_children[0]->evaluate(maxValue)) / std::log(m_children[1]->evaluate(maxValue));
     111    }
     112    case CalcOperator::Exp: {
     113        if (m_children.size() != 1)
     114            return std::numeric_limits<float>::quiet_NaN();
     115        return std::exp(m_children[0]->evaluate(maxValue));
     116    }
    105117    }
    106118    ASSERT_NOT_REACHED();
  • trunk/Source/WebCore/platform/calc/CalcOperator.cpp

    r282162 r282795  
    4444    case CalcOperator::Cos: ts << "cos"; break;
    4545    case CalcOperator::Tan: ts << "tan"; break;
     46    case CalcOperator::Exp: ts << "exp"; break;
     47    case CalcOperator::Log: ts << "log"; break;
    4648    }
    4749    return ts;
  • trunk/Source/WebCore/platform/calc/CalcOperator.h

    r282162 r282795  
    4242    Cos,
    4343    Tan,
     44    Exp,
     45    Log,
    4446};
    4547
Note: See TracChangeset for help on using the changeset viewer.