Changeset 166860 in webkit


Ignore:
Timestamp:
Apr 6, 2014 5:16:35 PM (10 years ago)
Author:
Darin Adler
Message:

Source/WebCore: Rework CSS calc logic, fixing some reference count mistakes in Length
https://bugs.webkit.org/show_bug.cgi?id=131280
rdar://problem/16400823

Reviewed by Andreas Kling.

New unit test in TestWebKitAPI.

Changed the classes related to CSS "calc" to make the code a bit easier to read by
moving code out of class definitions. Also used final some more, made more things private,
used references instead of pointers, and other such changes. Biggest change, though, is to
Length, which had a broken system for managing reference counted calculated objects.
There were multiple bugs including a basic design mistake of not having a reference count
and trying to use the reference count in the object itself. Fixed and covered by the unit
test now; test found multiple problems in both the old and new implementations.

  • WebCore.exp.in: Updated exports, including symbols to make the unit test practical.
  • WebCore.xcodeproj/project.pbxproj: Made CalculationValue.h a Private file so it can

be used in a unit test. Also let Xcode update the file type for a gperf file.

  • css/CSSCalculationValue.cpp:

(WebCore::CSSCalcValue::equals): Updated since m_expression is a Ref now.
(WebCore::CSSCalcValue::clampToPermittedRange): Marked inline and updated for data member
name change.
(WebCore::isIntegerResult): Changed argument order to put the operator first and use
references instead of pointers. Also marked inline.
(WebCore::createBlendHalf): Added. Helper to make the other functions more readable.
(WebCore::createExpressionNode): Made non-member function private to this file. Also made
many small improvements.
(WebCore::CSSCalcValue::create): Updated so both of these call the same constructor.

  • css/CSSCalculationValue.h: Cut down CSSCalcValue class by making more things private

and deleting unneeded things. Also use Ref instead of RefPtr.

  • css/CSSComputedStyleDeclaration.cpp:

(WebCore::getPositionOffsetValue): Use isFixed function instead of type function.

  • css/CSSGradientValue.cpp:

(WebCore::CSSGradientValue::addStops): Updated code since toCalcValue now returns PassRef
instead of PassRefPtr. Unfortunately the new code is a bit more verbose.
(WebCore::positionFromValue): Ditto.

  • css/CSSParser.cpp:

(WebCore::CSSParser::parseCalculation):

  • css/CSSPrimitiveValue.cpp:

(WebCore::CSSPrimitiveValue::CSSPrimitiveValue): Updated to pass reference rather than pointer.
(WebCore::CSSPrimitiveValue::init): Ditto.

  • css/CSSToStyleMap.h: Removed unneeded include of LengthBox.h.
  • css/DeprecatedStyleBuilder.cpp:

(WebCore::ApplyPropertyLength::applyValue): Updated for function name change.
(WebCore::ApplyPropertyBorderRadius::applyValue): Removed extra parentheses.
(WebCore::ApplyPropertyFontSize::applyValue): Ditto. Also updated since toCalcValue returns Ref.

  • css/LengthFunctions.cpp:

(WebCore::floatValueForLength): Updated to call value instead of getFloatValue; both are the same.

  • css/StyleResolver.cpp:

(WebCore::addIntrinsicMargins): Updated for function name change.
(WebCore::createGridTrackBreadth): Ditto.

  • platform/CalculationValue.cpp:

(WebCore::CalculationValue::create): Changed to return PassRef.
(WebCore::CalcExpressionNumber::evaluate): Moved this function out of the header, since it's
virtual and not really going to be inlined.
(WebCore::CalcExpressionNumber::operator==): Ditto.
(WebCore::CalculationValue::evaluate): Ditto.
(WebCore::CalcExpressionBinaryOperation::operator==): Ditto.
(WebCore::CalcExpressionLength::evaluate): Ditto.
(WebCore::CalcExpressionLength::operator==): Ditto.
(WebCore::CalcExpressionBlendLength::evaluate): Ditto.
(WebCore::CalcExpressionBlendLength::operator==): Ditto.

  • platform/CalculationValue.h: Moved most functions out of the class bodies so the classes are

easier to see. Made all the == operator functions non-member ones except for the polymorphic
one from the base class. Changed the casting functions to work on references instead of pointers.
Tweaked name of some members.

  • platform/Length.cpp: Reworked the CalculationValueMap (formerly CalculationValueHandleMap) to

use unsigned instead of int, and store reference counts in the map rather than trying to share the
reference count of the underlying CalculationValue object, which can lead to storage leaks where
handles end up in the map permanently.
(WebCore::calculationValues): Use NeverDestroyed instead of DEPRECATED_DEFINE_STATIC_LOCAL.
(WebCore::Length::Length): Updated some data member names.
(WebCore::Length::calculationValue): Updated to return a reference instead of a PassRefPtr.
(WebCore::Length::ref): Renamed and updated for new interface to the map.
(WebCore::Length::deref): Ditto.
(WebCore::Length::nonNanCalculatedValue): Updated to use a reference instead of a pointer.
(WebCore::Length::isCalculatedEqual): Updated since this is now only called if both objects are
known to be calculated values.

  • platform/Length.h: Moved most functions out of the class definition to make the class definition

easier to read. Reworked the constructors and assignment operators to handle the reference counting
correctly. Added various FIXMEs and assertions. Removed some unused functions, made others private.

  • platform/LengthBox.h: Renamed some one-letter arguments to use words instead.
  • rendering/AutoTableLayout.cpp:

(WebCore::AutoTableLayout::recalcColumn): Updated for change to Length::setValue.

  • rendering/FixedTableLayout.cpp:

(WebCore::FixedTableLayout::calcWidthArray): Ditto.

  • rendering/style/FillLayer.h:

(WebCore::FillLayer::initialFillXPosition): Updated to not convert a double to a float at runtime.
(WebCore::FillLayer::initialFillYPosition): Ditto.

  • rendering/style/RenderStyle.cpp:

(WebCore::RenderStyle::setWordSpacing): Removed a bogus FALLTHROUGH that was clearly wrong, but
harmless. Updated for changes to Length.

  • rendering/style/RenderStyle.h: Updated for name changes and to avoid converting doubles to floats

at runtime.

Tools: Rework CSS calc logic, fixing some reference count mistakes in Length
https://bugs.webkit.org/show_bug.cgi?id=131280

Reviewed by Andreas Kling.

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Added CalculationValue.cpp.
  • TestWebKitAPI/Tests/WebCore/CalculationValue.cpp: Added.
Location:
trunk
Files:
1 added
27 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r166858 r166860  
     12014-04-06  Darin Adler  <darin@apple.com>
     2
     3        Rework CSS calc logic, fixing some reference count mistakes in Length
     4        https://bugs.webkit.org/show_bug.cgi?id=131280
     5        rdar://problem/16400823
     6
     7        Reviewed by Andreas Kling.
     8
     9        New unit test in TestWebKitAPI.
     10
     11        Changed the classes related to CSS "calc" to make the code a bit easier to read by
     12        moving code out of class definitions. Also used final some more, made more things private,
     13        used references instead of pointers, and other such changes. Biggest change, though, is to
     14        Length, which had a broken system for managing reference counted calculated objects.
     15        There were multiple bugs including a basic design mistake of not having a reference count
     16        and trying to use the reference count in the object itself. Fixed and covered by the unit
     17        test now; test found multiple problems in both the old and new implementations.
     18
     19        * WebCore.exp.in: Updated exports, including symbols to make the unit test practical.
     20
     21        * WebCore.xcodeproj/project.pbxproj: Made CalculationValue.h a Private file so it can
     22        be used in a unit test. Also let Xcode update the file type for a gperf file.
     23
     24        * css/CSSCalculationValue.cpp:
     25        (WebCore::CSSCalcValue::equals): Updated since m_expression is a Ref now.
     26        (WebCore::CSSCalcValue::clampToPermittedRange): Marked inline and updated for data member
     27        name change.
     28        (WebCore::isIntegerResult): Changed argument order to put the operator first and use
     29        references instead of pointers. Also marked inline.
     30        (WebCore::createBlendHalf): Added. Helper to make the other functions more readable.
     31        (WebCore::createExpressionNode): Made non-member function private to this file. Also made
     32        many small improvements.
     33        (WebCore::CSSCalcValue::create): Updated so both of these call the same constructor.
     34
     35        * css/CSSCalculationValue.h: Cut down CSSCalcValue class by making more things private
     36        and deleting unneeded things. Also use Ref instead of RefPtr.
     37
     38        * css/CSSComputedStyleDeclaration.cpp:
     39        (WebCore::getPositionOffsetValue): Use isFixed function instead of type function.
     40
     41        * css/CSSGradientValue.cpp:
     42        (WebCore::CSSGradientValue::addStops): Updated code since toCalcValue now returns PassRef
     43        instead of PassRefPtr. Unfortunately the new code is a bit more verbose.
     44        (WebCore::positionFromValue): Ditto.
     45
     46        * css/CSSParser.cpp:
     47        (WebCore::CSSParser::parseCalculation):
     48
     49        * css/CSSPrimitiveValue.cpp:
     50        (WebCore::CSSPrimitiveValue::CSSPrimitiveValue): Updated to pass reference rather than pointer.
     51        (WebCore::CSSPrimitiveValue::init): Ditto.
     52
     53        * css/CSSToStyleMap.h: Removed unneeded include of LengthBox.h.
     54
     55        * css/DeprecatedStyleBuilder.cpp:
     56        (WebCore::ApplyPropertyLength::applyValue): Updated for function name change.
     57        (WebCore::ApplyPropertyBorderRadius::applyValue): Removed extra parentheses.
     58        (WebCore::ApplyPropertyFontSize::applyValue): Ditto. Also updated since toCalcValue returns Ref.
     59
     60        * css/LengthFunctions.cpp:
     61        (WebCore::floatValueForLength): Updated to call value instead of getFloatValue; both are the same.
     62
     63        * css/StyleResolver.cpp:
     64        (WebCore::addIntrinsicMargins): Updated for function name change.
     65        (WebCore::createGridTrackBreadth): Ditto.
     66
     67        * platform/CalculationValue.cpp:
     68        (WebCore::CalculationValue::create): Changed to return PassRef.
     69        (WebCore::CalcExpressionNumber::evaluate): Moved this function out of the header, since it's
     70        virtual and not really going to be inlined.
     71        (WebCore::CalcExpressionNumber::operator==): Ditto.
     72        (WebCore::CalculationValue::evaluate): Ditto.
     73        (WebCore::CalcExpressionBinaryOperation::operator==): Ditto.
     74        (WebCore::CalcExpressionLength::evaluate): Ditto.
     75        (WebCore::CalcExpressionLength::operator==): Ditto.
     76        (WebCore::CalcExpressionBlendLength::evaluate): Ditto.
     77        (WebCore::CalcExpressionBlendLength::operator==): Ditto.
     78
     79        * platform/CalculationValue.h: Moved most functions out of the class bodies so the classes are
     80        easier to see. Made all the == operator functions non-member ones except for the polymorphic
     81        one from the base class. Changed the casting functions to work on references instead of pointers.
     82        Tweaked name of some members.
     83
     84        * platform/Length.cpp: Reworked the CalculationValueMap (formerly CalculationValueHandleMap) to
     85        use unsigned instead of int, and store reference counts in the map rather than trying to share the
     86        reference count of the underlying CalculationValue object, which can lead to storage leaks where
     87        handles end up in the map permanently.
     88        (WebCore::calculationValues): Use NeverDestroyed instead of DEPRECATED_DEFINE_STATIC_LOCAL.
     89        (WebCore::Length::Length): Updated some data member names.
     90        (WebCore::Length::calculationValue): Updated to return a reference instead of a PassRefPtr.
     91        (WebCore::Length::ref): Renamed and updated for new interface to the map.
     92        (WebCore::Length::deref): Ditto.
     93        (WebCore::Length::nonNanCalculatedValue): Updated to use a reference instead of a pointer.
     94        (WebCore::Length::isCalculatedEqual): Updated since this is now only called if both objects are
     95        known to be calculated values.
     96
     97        * platform/Length.h: Moved most functions out of the class definition to make the class definition
     98        easier to read. Reworked the constructors and assignment operators to handle the reference counting
     99        correctly. Added various FIXMEs and assertions. Removed some unused functions, made others private.
     100
     101        * platform/LengthBox.h: Renamed some one-letter arguments to use words instead.
     102
     103        * rendering/AutoTableLayout.cpp:
     104        (WebCore::AutoTableLayout::recalcColumn): Updated for change to Length::setValue.
     105        * rendering/FixedTableLayout.cpp:
     106        (WebCore::FixedTableLayout::calcWidthArray): Ditto.
     107
     108        * rendering/style/FillLayer.h:
     109        (WebCore::FillLayer::initialFillXPosition): Updated to not convert a double to a float at runtime.
     110        (WebCore::FillLayer::initialFillYPosition): Ditto.
     111
     112        * rendering/style/RenderStyle.cpp:
     113        (WebCore::RenderStyle::setWordSpacing): Removed a bogus FALLTHROUGH that was clearly wrong, but
     114        harmless. Updated for changes to Length.
     115
     116        * rendering/style/RenderStyle.h: Updated for name changes and to avoid converting doubles to floats
     117        at runtime.
     118
    11192014-04-06  Brent Fulgham  <bfulgham@apple.com>
    2120
  • trunk/Source/WebCore/WebCore.exp.in

    r166855 r166860  
    650650__ZN7WebCore16ApplicationCache20deleteCacheForOriginEPNS_14SecurityOriginE
    651651__ZN7WebCore16CSSParserContextC1ERNS_8DocumentERKNS_3URLERKN3WTF6StringE
     652__ZN7WebCore16CalculationValue6createENSt3__110unique_ptrINS_18CalcExpressionNodeENS1_14default_deleteIS3_EEEENS_30CalculationPermittedValueRangeE
    652653__ZN7WebCore16DatabaseStrategy17getDatabaseServerEv
    653654__ZN7WebCore16DatabaseStrategy23createIDBFactoryBackendERKN3WTF6StringE
     
    11731174__ZN7WebCore6Editor7outdentEv
    11741175__ZN7WebCore6JSNode6s_infoE
     1176__ZN7WebCore6LengthC1EN3WTF7PassRefINS_16CalculationValueEEE
    11751177__ZN7WebCore6Region21updateBoundsFromShapeEv
    11761178__ZN7WebCore6Region5uniteERKS0_
     
    18561858__ZNK7WebCore6Editor8canPasteEv
    18571859__ZNK7WebCore6Editor9canDeleteEv
    1858 __ZNK7WebCore6Length22decrementCalculatedRefEv
    1859 __ZNK7WebCore6Length22incrementCalculatedRefEv
     1860__ZNK7WebCore6Length3refEv
     1861__ZNK7WebCore6Length5derefEv
    18601862__ZNK7WebCore6Region5Shape7isValidEv
    18611863__ZNK7WebCore6Region5rectsEv
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r166847 r166860  
    15991599                49AE2D8F134EE50C0072920A /* CSSCalculationValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 49AE2D8D134EE50C0072920A /* CSSCalculationValue.h */; };
    16001600                49AE2D96134EE5F90072920A /* CalculationValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49AE2D94134EE5F90072920A /* CalculationValue.cpp */; };
    1601                 49AE2D97134EE5F90072920A /* CalculationValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 49AE2D95134EE5F90072920A /* CalculationValue.h */; };
     1601                49AE2D97134EE5F90072920A /* CalculationValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 49AE2D95134EE5F90072920A /* CalculationValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
    16021602                49AF2D6914435D050016A784 /* DisplayRefreshMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 49AF2D6814435D050016A784 /* DisplayRefreshMonitor.h */; settings = {ATTRIBUTES = (Private, ); }; };
    16031603                49AF2D6C14435D210016A784 /* DisplayRefreshMonitorMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49AF2D6B14435D210016A784 /* DisplayRefreshMonitorMac.cpp */; };
     
    84338433                43B85ED018CBEACE00E31AF4 /* makeSelectorPseudoClassAndCompatibilityElementMap.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = makeSelectorPseudoClassAndCompatibilityElementMap.py; sourceTree = "<group>"; };
    84348434                43B85ED218CBEC5200E31AF4 /* SelectorPseudoClassAndCompatibilityElementMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectorPseudoClassAndCompatibilityElementMap.cpp; sourceTree = "<group>"; };
    8435                 43B85ED318CBEC5200E31AF4 /* SelectorPseudoClassAndCompatibilityElementMap.gperf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file; path = SelectorPseudoClassAndCompatibilityElementMap.gperf; sourceTree = "<group>"; };
     8435                43B85ED318CBEC5200E31AF4 /* SelectorPseudoClassAndCompatibilityElementMap.gperf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SelectorPseudoClassAndCompatibilityElementMap.gperf; sourceTree = "<group>"; };
    84368436                43B85ED618CBEC9700E31AF4 /* SelectorPseudoClassAndCompatibilityElementMap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SelectorPseudoClassAndCompatibilityElementMap.in; sourceTree = "<group>"; };
    84378437                43B9336713B261B1004584BF /* SVGAnimatedPointList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedPointList.h; sourceTree = "<group>"; };
  • trunk/Source/WebCore/css/CSSCalculationValue.cpp

    r163888 r166860  
    11/*
    22 * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
     3 * Copyright (C) 2014 Apple Inc. All rights reserved.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    3334
    3435#include "CSSPrimitiveValueMappings.h"
    35 #include "CSSValueList.h"
    36 #include "Length.h"
    3736#include "StyleResolver.h"
    38 
    3937#include <wtf/MathExtras.h>
    4038#include <wtf/text/StringBuilder.h>
     
    4947
    5048namespace WebCore {
     49
     50static PassRefPtr<CSSCalcExpressionNode> createCSS(const CalcExpressionNode&, const RenderStyle&);
     51static PassRefPtr<CSSCalcExpressionNode> createCSS(const Length&, const RenderStyle&);
    5152
    5253static CalculationCategory unitCategory(CSSPrimitiveValue::UnitTypes type)
     
    158159bool CSSCalcValue::equals(const CSSCalcValue& other) const
    159160{
    160     return compareCSSValuePtr(m_expression, other.m_expression);
    161 }
    162 
    163 double CSSCalcValue::clampToPermittedRange(double value) const
    164 {
    165     return m_nonNegative && value < 0 ? 0 : value;
     161    return compareCSSValue(m_expression, other.m_expression);
     162}
     163
     164inline double CSSCalcValue::clampToPermittedRange(double value) const
     165{
     166    return m_shouldClampToNonNegative && value < 0 ? 0 : value;
    166167}
    167168
     
    176177}
    177178
    178 CSSCalcExpressionNode::~CSSCalcExpressionNode()
    179 {
    180 }
    181 
    182 class CSSCalcPrimitiveValue : public CSSCalcExpressionNode {
     179class CSSCalcPrimitiveValue final : public CSSCalcExpressionNode {
    183180    WTF_MAKE_FAST_ALLOCATED;
    184181public:
    185 
    186     static PassRefPtr<CSSCalcPrimitiveValue> create(PassRefPtr<CSSPrimitiveValue> value, bool isInteger)
    187     {
    188         return adoptRef(new CSSCalcPrimitiveValue(value, isInteger));
     182    static PassRef<CSSCalcPrimitiveValue> create(PassRefPtr<CSSPrimitiveValue> value, bool isInteger)
     183    {
     184        return adoptRef(*new CSSCalcPrimitiveValue(value, isInteger));
    189185    }
    190186
     
    192188    {
    193189        if (std::isnan(value) || std::isinf(value))
    194             return 0;
     190            return nullptr;
    195191        return adoptRef(new CSSCalcPrimitiveValue(CSSPrimitiveValue::create(value, type), isInteger));
    196192    }
    197193
    198     virtual bool isZero() const
     194private:
     195    virtual bool isZero() const override
    199196    {
    200197        return !m_value->getDoubleValue();
    201198    }
    202199
    203     virtual String customCSSText() const
     200    virtual String customCSSText() const override
    204201    {
    205202        return m_value->cssText();
    206203    }
    207204
    208     virtual std::unique_ptr<CalcExpressionNode> toCalcValue(const RenderStyle* style, const RenderStyle* rootStyle, double zoom) const
    209     {
    210         switch (m_category) {
     205    virtual std::unique_ptr<CalcExpressionNode> createCalcExpression(const RenderStyle* style, const RenderStyle* rootStyle, double zoom) const override
     206    {
     207        switch (category()) {
    211208        case CalcNumber:
    212209            return std::make_unique<CalcExpressionNumber>(m_value->getFloatValue());
     
    228225    }
    229226
    230     virtual double doubleValue() const
     227    virtual double doubleValue() const override
    231228    {
    232229        if (hasDoubleValue(primitiveType()))
     
    236233    }
    237234
    238     virtual double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier, bool computingFontSize) const
    239     {
    240         switch (m_category) {
     235    virtual double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier, bool computingFontSize) const override
     236    {
     237        switch (category()) {
    241238        case CalcLength:
    242239            return m_value->computeLength<double>(currentStyle, rootStyle, multiplier, computingFontSize);
     
    254251    }
    255252
    256     virtual bool equals(const CSSCalcExpressionNode& other) const
     253    virtual bool equals(const CSSCalcExpressionNode& other) const override
    257254    {
    258255        if (type() != other.type())
     
    262259    }
    263260
    264     virtual Type type() const { return CssCalcPrimitiveValue; }
    265     virtual CSSPrimitiveValue::UnitTypes primitiveType() const
     261    virtual Type type() const override { return CssCalcPrimitiveValue; }
     262    virtual CSSPrimitiveValue::UnitTypes primitiveType() const override
    266263    {
    267264        return CSSPrimitiveValue::UnitTypes(m_value->primitiveType());
     
    313310}
    314311
    315 static bool isIntegerResult(const CSSCalcExpressionNode* leftSide, const CSSCalcExpressionNode* rightSide, CalcOperator op)
     312static inline bool isIntegerResult(CalcOperator op, const CSSCalcExpressionNode& leftSide, const CSSCalcExpressionNode& rightSide)
    316313{
    317314    // Performs W3C spec's type checking for calc integers.
    318315    // http://www.w3.org/TR/css3-values/#calc-type-checking
    319     return op != CalcDivide && leftSide->isInteger() && rightSide->isInteger();
    320 }
    321 
    322 class CSSCalcBinaryOperation : public CSSCalcExpressionNode {
    323 
     316    return op != CalcDivide && leftSide.isInteger() && rightSide.isInteger();
     317}
     318
     319class CSSCalcBinaryOperation final : public CSSCalcExpressionNode {
     320    WTF_MAKE_FAST_ALLOCATED;
    324321public:
    325     static PassRefPtr<CSSCalcExpressionNode> create(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op)
     322    static PassRefPtr<CSSCalcBinaryOperation> create(CalcOperator op, PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide)
    326323    {
    327324        ASSERT(leftSide->category() != CalcOther && rightSide->category() != CalcOther);
     
    330327
    331328        if (newCategory == CalcOther)
    332             return 0;
    333 
    334         return adoptRef(new CSSCalcBinaryOperation(leftSide, rightSide, op, newCategory));
    335     }
    336 
    337     static PassRefPtr<CSSCalcExpressionNode> createSimplified(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op)
     329            return nullptr;
     330
     331        return adoptRef(new CSSCalcBinaryOperation(newCategory, op, leftSide, rightSide));
     332    }
     333
     334    static PassRefPtr<CSSCalcExpressionNode> createSimplified(CalcOperator op, PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide)
    338335    {
    339336        CalculationCategory leftCategory = leftSide->category();
     
    341338        ASSERT(leftCategory != CalcOther && rightCategory != CalcOther);
    342339
    343         bool isInteger = isIntegerResult(leftSide.get(), rightSide.get(), op);
     340        bool isInteger = isIntegerResult(op, *leftSide, *rightSide);
    344341
    345342        // Simplify numbers.
    346343        if (leftCategory == CalcNumber && rightCategory == CalcNumber) {
    347344            CSSPrimitiveValue::UnitTypes evaluationType = isInteger ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER;
    348             return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doubleValue(), rightSide->doubleValue(), op), evaluationType, isInteger);
     345            return CSSCalcPrimitiveValue::create(evaluateOperator(op, leftSide->doubleValue(), rightSide->doubleValue()), evaluationType, isInteger);
    349346        }
    350347
     
    356353                    CSSPrimitiveValue::UnitTypes rightType = rightSide->primitiveType();
    357354                    if (leftType == rightType)
    358                         return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doubleValue(), rightSide->doubleValue(), op), leftType, isInteger);
     355                        return CSSCalcPrimitiveValue::create(evaluateOperator(op, leftSide->doubleValue(), rightSide->doubleValue()), leftType, isInteger);
    359356                    CSSPrimitiveValue::UnitCategory leftUnitCategory = CSSPrimitiveValue::unitCategory(leftType);
    360357                    if (leftUnitCategory != CSSPrimitiveValue::UOther && leftUnitCategory == CSSPrimitiveValue::unitCategory(rightType)) {
     
    363360                            double leftValue = leftSide->doubleValue() * CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(leftType);
    364361                            double rightValue = rightSide->doubleValue() * CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(rightType);
    365                             return CSSCalcPrimitiveValue::create(evaluateOperator(leftValue, rightValue, op), canonicalType, isInteger);
     362                            return CSSCalcPrimitiveValue::create(evaluateOperator(op, leftValue, rightValue), canonicalType, isInteger);
    366363                        }
    367364                    }
     
    371368            // Simplify multiplying or dividing by a number for simplifiable types.
    372369            ASSERT(op == CalcMultiply || op == CalcDivide);
    373             CSSCalcExpressionNode* numberSide = getNumberSide(leftSide.get(), rightSide.get());
     370            CSSCalcExpressionNode* numberSide = getNumberSide(*leftSide, *rightSide);
    374371            if (!numberSide)
    375                 return create(leftSide, rightSide, op);
     372                return create(op, leftSide, rightSide);
    376373            if (numberSide == leftSide && op == CalcDivide)
    377                 return 0;
     374                return nullptr;
    378375            CSSCalcExpressionNode* otherSide = leftSide == numberSide ? rightSide.get() : leftSide.get();
    379376
    380377            double number = numberSide->doubleValue();
    381378            if (std::isnan(number) || std::isinf(number))
    382                 return 0;
     379                return nullptr;
    383380            if (op == CalcDivide && !number)
    384                 return 0;
     381                return nullptr;
    385382
    386383            CSSPrimitiveValue::UnitTypes otherType = otherSide->primitiveType();
    387384            if (hasDoubleValue(otherType))
    388                 return CSSCalcPrimitiveValue::create(evaluateOperator(otherSide->doubleValue(), number, op), otherType, isInteger);
    389         }
    390 
    391         return create(leftSide, rightSide, op);
    392     }
    393 
    394     virtual bool isZero() const
     385                return CSSCalcPrimitiveValue::create(evaluateOperator(op, otherSide->doubleValue(), number), otherType, isInteger);
     386        }
     387
     388        return create(op, leftSide, rightSide);
     389    }
     390
     391private:
     392    virtual bool isZero() const override
    395393    {
    396394        return !doubleValue();
    397395    }
    398396
    399     virtual std::unique_ptr<CalcExpressionNode> toCalcValue(const RenderStyle* style, const RenderStyle* rootStyle, double zoom) const
    400     {
    401         std::unique_ptr<CalcExpressionNode> left(m_leftSide->toCalcValue(style, rootStyle, zoom));
     397    virtual std::unique_ptr<CalcExpressionNode> createCalcExpression(const RenderStyle* style, const RenderStyle* rootStyle, double zoom) const override
     398    {
     399        std::unique_ptr<CalcExpressionNode> left(m_leftSide->createCalcExpression(style, rootStyle, zoom));
    402400        if (!left)
    403401            return nullptr;
    404         std::unique_ptr<CalcExpressionNode> right(m_rightSide->toCalcValue(style, rootStyle, zoom));
     402        std::unique_ptr<CalcExpressionNode> right(m_rightSide->createCalcExpression(style, rootStyle, zoom));
    405403        if (!right)
    406404            return nullptr;
     
    408406    }
    409407
    410     virtual double doubleValue() const
     408    virtual double doubleValue() const override
    411409    {
    412410        return evaluate(m_leftSide->doubleValue(), m_rightSide->doubleValue());
    413411    }
    414412
    415     virtual double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier, bool computingFontSize) const
     413    virtual double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier, bool computingFontSize) const override
    416414    {
    417415        const double leftValue = m_leftSide->computeLengthPx(currentStyle, rootStyle, multiplier, computingFontSize);
     
    434432    }
    435433
    436     virtual String customCSSText() const
     434    virtual String customCSSText() const override
    437435    {
    438436        return buildCssText(m_leftSide->customCSSText(), m_rightSide->customCSSText(), m_operator);
    439437    }
    440438
    441 
    442     virtual bool equals(const CSSCalcExpressionNode& exp) const
     439    virtual bool equals(const CSSCalcExpressionNode& exp) const override
    443440    {
    444441        if (type() != exp.type())
     
    451448    }
    452449
    453     virtual Type type() const { return CssCalcBinaryOperation; }
    454 
    455     virtual CSSPrimitiveValue::UnitTypes primitiveType() const
    456     {
    457         switch (m_category) {
     450    virtual Type type() const override { return CssCalcBinaryOperation; }
     451
     452    virtual CSSPrimitiveValue::UnitTypes primitiveType() const override
     453    {
     454        switch (category()) {
    458455        case CalcNumber:
    459456            ASSERT(m_leftSide->category() == CalcNumber && m_rightSide->category() == CalcNumber);
    460             if (m_isInteger)
     457            if (isInteger())
    461458                return CSSPrimitiveValue::CSS_PARSER_INTEGER;
    462459            return CSSPrimitiveValue::CSS_NUMBER;
     
    481478    }
    482479
    483 private:
    484     CSSCalcBinaryOperation(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op, CalculationCategory category)
    485         : CSSCalcExpressionNode(category, isIntegerResult(leftSide.get(), rightSide.get(), op))
     480    CSSCalcBinaryOperation(CalculationCategory category, CalcOperator op, PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide)
     481        : CSSCalcExpressionNode(category, isIntegerResult(op, *leftSide, *rightSide))
    486482        , m_leftSide(leftSide)
    487483        , m_rightSide(rightSide)
     
    490486    }
    491487
    492     static CSSCalcExpressionNode* getNumberSide(CSSCalcExpressionNode* leftSide, CSSCalcExpressionNode* rightSide)
    493     {
    494         if (leftSide->category() == CalcNumber)
    495             return leftSide;
    496         if (rightSide->category() == CalcNumber)
    497             return rightSide;
    498         return 0;
     488    static CSSCalcExpressionNode* getNumberSide(CSSCalcExpressionNode& leftSide, CSSCalcExpressionNode& rightSide)
     489    {
     490        if (leftSide.category() == CalcNumber)
     491            return &leftSide;
     492        if (rightSide.category() == CalcNumber)
     493            return &rightSide;
     494        return nullptr;
    499495    }
    500496
    501497    double evaluate(double leftSide, double rightSide) const
    502498    {
    503         return evaluateOperator(leftSide, rightSide, m_operator);
    504     }
    505 
    506     static double evaluateOperator(double leftValue, double rightValue, CalcOperator op)
     499        return evaluateOperator(m_operator, leftSide, rightSide);
     500    }
     501
     502    static double evaluateOperator(CalcOperator op, double leftValue, double rightValue)
    507503    {
    508504        switch (op) {
     
    518514            return std::numeric_limits<double>::quiet_NaN();
    519515        }
     516        ASSERT_NOT_REACHED();
    520517        return 0;
    521518    }
     
    545542        ASSERT_WITH_SECURITY_IMPLICATION(index <= tokens->size());
    546543        if (!ok || index != tokens->size())
    547             return 0;
     544            return nullptr;
    548545        return result.value;
    549546    }
     
    619616                return false;
    620617
    621             result->value = CSSCalcBinaryOperation::createSimplified(result->value, rhs.value, static_cast<CalcOperator>(operatorCharacter));
     618            result->value = CSSCalcBinaryOperation::createSimplified(static_cast<CalcOperator>(operatorCharacter), result->value, rhs.value);
    622619            if (!result->value)
    623620                return false;
     
    646643                return false;
    647644
    648             result->value = CSSCalcBinaryOperation::createSimplified(result->value, rhs.value, static_cast<CalcOperator>(operatorCharacter));
     645            result->value = CSSCalcBinaryOperation::createSimplified(static_cast<CalcOperator>(operatorCharacter), result->value, rhs.value);
    649646            if (!result->value)
    650647                return false;
     
    661658};
    662659
    663 PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(PassRefPtr<CSSPrimitiveValue> value, bool isInteger)
    664 {
    665     return CSSCalcPrimitiveValue::create(value, isInteger);
    666 }
    667 
    668 PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op)
    669 {
    670     return CSSCalcBinaryOperation::create(leftSide, rightSide, op);
    671 }
    672 
    673 PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(const CalcExpressionNode* node, const RenderStyle* style)
    674 {
    675     switch (node->type()) {
     660static inline PassRefPtr<CSSCalcBinaryOperation> createBlendHalf(const Length& length, const RenderStyle& style, float progress)
     661{
     662    return CSSCalcBinaryOperation::create(CalcMultiply, createCSS(length, style),
     663        CSSCalcPrimitiveValue::create(CSSPrimitiveValue::create(progress, CSSPrimitiveValue::CSS_NUMBER), !progress || progress == 1));
     664}
     665
     666static PassRefPtr<CSSCalcExpressionNode> createCSS(const CalcExpressionNode& node, const RenderStyle& style)
     667{
     668    switch (node.type()) {
    676669    case CalcExpressionNodeNumber: {
    677         float value = toCalcExpressionNumber(node)->value();
    678         return createExpressionNode(CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER), value == trunc(value));
     670        float value = toCalcExpressionNumber(node).value();
     671        return CSSCalcPrimitiveValue::create(CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER), value == truncf(value));
    679672    }
    680673    case CalcExpressionNodeLength:
    681         return createExpressionNode(toCalcExpressionLength(node)->length(), style);
     674        return createCSS(toCalcExpressionLength(node).length(), style);
    682675    case CalcExpressionNodeBinaryOperation: {
    683         const CalcExpressionBinaryOperation* binaryNode = toCalcExpressionBinaryOperation(node);
    684         return createExpressionNode(createExpressionNode(binaryNode->leftSide(), style), createExpressionNode(binaryNode->rightSide(), style), binaryNode->getOperator());
     676        auto& binaryNode = toCalcExpressionBinaryOperation(node);
     677        return CSSCalcBinaryOperation::create(binaryNode.getOperator(), createCSS(binaryNode.leftSide(), style), createCSS(binaryNode.rightSide(), style));
    685678    }
    686679    case CalcExpressionNodeBlendLength: {
    687680        // FIXME: (http://webkit.org/b/122036) Create a CSSCalcExpressionNode equivalent of CalcExpressionBlendLength.
    688         const CalcExpressionBlendLength* blendNode = toCalcExpressionBlendLength(node);
    689         const double progress = blendNode->progress();
    690         const bool isInteger = !progress || (progress == 1);
    691         return createExpressionNode(
    692             createExpressionNode(
    693                 createExpressionNode(blendNode->from(), style),
    694                 createExpressionNode(CSSPrimitiveValue::create(1 - progress, CSSPrimitiveValue::CSS_NUMBER), isInteger),
    695                 CalcMultiply),
    696             createExpressionNode(
    697                 createExpressionNode(blendNode->to(), style),
    698                 createExpressionNode(CSSPrimitiveValue::create(progress, CSSPrimitiveValue::CSS_NUMBER), isInteger),
    699                 CalcMultiply),
    700             CalcAdd);
     681        auto& blend = toCalcExpressionBlendLength(node);
     682        float progress = blend.progress();
     683        return CSSCalcBinaryOperation::create(CalcAdd, createBlendHalf(blend.from(), style, 1 - progress), createBlendHalf(blend.to(), style, progress));
    701684    }
    702685    case CalcExpressionNodeUndefined:
    703686        ASSERT_NOT_REACHED();
    704         return 0;
     687        return nullptr;
    705688    }
    706689    ASSERT_NOT_REACHED();
    707     return 0;
    708 }
    709 
    710 PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(const Length& length, const RenderStyle* style)
     690    return nullptr;
     691}
     692
     693static PassRefPtr<CSSCalcExpressionNode> createCSS(const Length& length, const RenderStyle& style)
    711694{
    712695    switch (length.type()) {
     
    717700    case ViewportPercentageMax:
    718701    case Fixed:
    719         return createExpressionNode(CSSPrimitiveValue::create(length, style), length.value() == trunc(length.value()));
     702        return CSSCalcPrimitiveValue::create(CSSPrimitiveValue::create(length, &style), length.value() == trunc(length.value()));
    720703    case Calculated:
    721         return createExpressionNode(length.calculationValue()->expression(), style);
     704        return createCSS(length.calculationValue().expression(), style);
    722705    case Auto:
    723706    case Intrinsic:
     
    730713    case Undefined:
    731714        ASSERT_NOT_REACHED();
    732         return 0;
     715        return nullptr;
    733716    }
    734717    ASSERT_NOT_REACHED();
    735     return 0;
    736 }
    737 
    738 PassRefPtr<CSSCalcValue> CSSCalcValue::create(CSSParserString name, CSSParserValueList* parserValueList, CalculationPermittedValueRange range)
     718    return nullptr;
     719}
     720
     721PassRefPtr<CSSCalcValue> CSSCalcValue::create(CSSParserString name, CSSParserValueList& parserValueList, CalculationPermittedValueRange range)
    739722{
    740723    CSSCalcExpressionNodeParser parser;
     
    742725
    743726    if (equalIgnoringCase(name, "calc(") || equalIgnoringCase(name, "-webkit-calc("))
    744         expression = parser.parseCalc(parserValueList);
     727        expression = parser.parseCalc(&parserValueList);
    745728    // FIXME: calc (http://webkit.org/b/16662) Add parsing for min and max here
    746729
    747     return expression ? adoptRef(new CSSCalcValue(expression, range)) : 0;
    748 }
    749 
    750 PassRef<CSSCalcValue> CSSCalcValue::create(PassRefPtr<CSSCalcExpressionNode> expression, CalculationPermittedValueRange range)
    751 {
    752     return adoptRef(*new CSSCalcValue(expression, range));
     730    return expression ? adoptRef(new CSSCalcValue(expression.releaseNonNull(), range != CalculationRangeAll)) : nullptr;
     731}
     732
     733PassRefPtr<CSSCalcValue> CSSCalcValue::create(const CalculationValue& value, const RenderStyle& style)
     734{
     735    RefPtr<CSSCalcExpressionNode> expression = createCSS(value.expression(), style);
     736    if (!expression)
     737        return nullptr;
     738    return adoptRef(new CSSCalcValue(expression.releaseNonNull(), value.shouldClampToNonNegative()));
    753739}
    754740
  • trunk/Source/WebCore/css/CSSCalculationValue.h

    r163439 r166860  
    3434#include "CSSParserValues.h"
    3535#include "CSSPrimitiveValue.h"
    36 #include "CSSValue.h"
    3736#include "CalculationValue.h"
    38 #include <memory>
    39 #include <wtf/RefCounted.h>
    40 #include <wtf/RefPtr.h>
    4137
    4238namespace WebCore {
    4339
    44 class CSSParserValueList;
    45 class CSSValueList;
    46 class CalculationValue;
    47 class CalcExpressionNode;
    4840class RenderStyle;
    49 struct Length;
    5041
    5142enum CalculationCategory {
     
    6556    };
    6657
    67     virtual ~CSSCalcExpressionNode() = 0;
     58    virtual ~CSSCalcExpressionNode() { }
    6859    virtual bool isZero() const = 0;
    69     virtual std::unique_ptr<CalcExpressionNode> toCalcValue(const RenderStyle*, const RenderStyle* rootStyle, double zoom = 1.0) const = 0;
     60    virtual std::unique_ptr<CalcExpressionNode> createCalcExpression(const RenderStyle*, const RenderStyle* rootStyle, double zoom = 1.0) const = 0;
    7061    virtual double doubleValue() const = 0;
    7162    virtual double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false) const = 0;
     
    7364    virtual bool equals(const CSSCalcExpressionNode& other) const { return m_category == other.m_category && m_isInteger == other.m_isInteger; }
    7465    virtual Type type() const = 0;
     66    virtual CSSPrimitiveValue::UnitTypes primitiveType() const = 0;
    7567
    7668    CalculationCategory category() const { return m_category; }
    77     virtual CSSPrimitiveValue::UnitTypes primitiveType() const = 0;
    7869    bool isInteger() const { return m_isInteger; }
    7970
     
    8576    }
    8677
     78private:
    8779    CalculationCategory m_category;
    8880    bool m_isInteger;
     
    9183class CSSCalcValue : public CSSValue {
    9284public:
    93     static PassRefPtr<CSSCalcValue> create(CSSParserString name, CSSParserValueList*, CalculationPermittedValueRange);
    94     static PassRef<CSSCalcValue> create(PassRefPtr<CSSCalcExpressionNode>, CalculationPermittedValueRange = CalculationRangeAll);
    95     static PassRef<CSSCalcValue> create(const CalculationValue* value, const RenderStyle* style) { return adoptRef(*new CSSCalcValue(value, style)); }
     85    static PassRefPtr<CSSCalcValue> create(CSSParserString name, CSSParserValueList& arguments, CalculationPermittedValueRange);
     86    static PassRefPtr<CSSCalcValue> create(const CalculationValue&, const RenderStyle&);
    9687
    97     static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(PassRefPtr<CSSPrimitiveValue>, bool isInteger = false);
    98     static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(PassRefPtr<CSSCalcExpressionNode>, PassRefPtr<CSSCalcExpressionNode>, CalcOperator);
    99     static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(const CalcExpressionNode*, const RenderStyle*);
    100     static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(const Length&, const RenderStyle*);
    101 
    102     PassRefPtr<CalculationValue> toCalcValue(const RenderStyle* style, const RenderStyle* rootStyle, double zoom = 1.0) const
    103     {
    104         return CalculationValue::create(m_expression->toCalcValue(style, rootStyle, zoom), m_nonNegative ? CalculationRangeNonNegative : CalculationRangeAll);
    105     }
    10688    CalculationCategory category() const { return m_expression->category(); }
    10789    bool isInt() const { return m_expression->isInteger(); }
    10890    double doubleValue() const;
    10991    bool isNegative() const { return m_expression->doubleValue() < 0; }
    110     CalculationPermittedValueRange permittedValueRange() { return m_nonNegative ? CalculationRangeNonNegative : CalculationRangeAll; }
    11192    double computeLengthPx(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false) const;
    112     CSSCalcExpressionNode* expressionNode() const { return m_expression.get(); }
     93
     94    PassRef<CalculationValue> createCalculationValue(const RenderStyle* currentStyle, const RenderStyle* rootStyle, double zoom = 1.0) const;
    11395
    11496    String customCSSText() const;
     
    11698
    11799private:
    118     CSSCalcValue(PassRefPtr<CSSCalcExpressionNode> expression, CalculationPermittedValueRange range)
    119         : CSSValue(CalculationClass)
    120         , m_expression(expression)
    121         , m_nonNegative(range == CalculationRangeNonNegative)
    122     {
    123     }
    124     CSSCalcValue(const CalculationValue* value, const RenderStyle* style)
    125         : CSSValue(CalculationClass)
    126         , m_expression(createExpressionNode(value->expression(), style))
    127         , m_nonNegative(value->isNonNegative())
    128     {
    129     }
     100    CSSCalcValue(PassRef<CSSCalcExpressionNode>, bool shouldClampToNonNegative);
    130101
    131102    double clampToPermittedRange(double) const;
    132103
    133     const RefPtr<CSSCalcExpressionNode> m_expression;
    134     const bool m_nonNegative;
     104    const Ref<CSSCalcExpressionNode> m_expression;
     105    const bool m_shouldClampToNonNegative;
    135106};
     107
     108inline CSSCalcValue::CSSCalcValue(PassRef<CSSCalcExpressionNode> expression, bool shouldClampToNonNegative)
     109    : CSSValue(CalculationClass)
     110    , m_expression(std::move(expression))
     111    , m_shouldClampToNonNegative(shouldClampToNonNegative)
     112{
     113}
     114
     115inline PassRef<CalculationValue> CSSCalcValue::createCalculationValue(const RenderStyle* style, const RenderStyle* rootStyle, double zoom) const
     116{
     117    return CalculationValue::create(m_expression->createCalcExpression(style, rootStyle, zoom),
     118        m_shouldClampToNonNegative ? CalculationRangeNonNegative : CalculationRangeAll);
     119}
    136120
    137121CSS_VALUE_TYPE_CASTS(CSSCalcValue, isCalcValue())
  • trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp

    r166786 r166860  
    678678
    679679    if (style->hasOutOfFlowPosition()) {
    680         if (l.type() == WebCore::Fixed)
     680        if (l.isFixed())
    681681            return zoomAdjustedPixelValue(l.value(), style);
    682         else if (l.isViewportPercentage())
     682        if (l.isViewportPercentage())
    683683            return zoomAdjustedPixelValue(valueForLength(l, 0, renderView), style);
    684684        return cssValuePool().createValue(l);
  • trunk/Source/WebCore/css/CSSGradientValue.cpp

    r166642 r166860  
    183183                if (stop.m_position->isLength())
    184184                    length = stop.m_position->computeLength<float>(&style, &rootStyle, style.effectiveZoom());
    185                 else
    186                     length = stop.m_position->cssCalcValue()->toCalcValue(&style, &rootStyle, style.effectiveZoom())->evaluate(gradientLength);
     185                else {
     186                    Ref<CalculationValue> calculationValue { stop.m_position->cssCalcValue()->createCalculationValue(&style, &rootStyle, style.effectiveZoom()) };
     187                    length = calculationValue->evaluate(gradientLength);
     188                }
    187189                stops[i].offset = (gradientLength > 0) ? length / gradientLength : 0;
    188190            } else {
     
    402404        return value->getFloatValue() / 100.f * edgeDistance;
    403405
    404     if (value->isCalculatedPercentageWithLength())
    405         return value->cssCalcValue()->toCalcValue(&style, &rootStyle, style.effectiveZoom())->evaluate(edgeDistance);
     406    if (value->isCalculatedPercentageWithLength()) {
     407        Ref<CalculationValue> calculationValue { value->cssCalcValue()->createCalculationValue(&style, &rootStyle, style.effectiveZoom()) };
     408        return calculationValue->evaluate(edgeDistance);
     409    }
    406410
    407411    switch (value->getValueID()) {
  • trunk/Source/WebCore/css/CSSParser.cpp

    r166813 r166860  
    95709570
    95719571    ASSERT(!m_parsedCalculation);
    9572     m_parsedCalculation = CSSCalcValue::create(value->function->name, args, range);
     9572    m_parsedCalculation = CSSCalcValue::create(value->function->name, *args, range);
    95739573   
    95749574    if (!m_parsedCalculation)
  • trunk/Source/WebCore/css/CSSPrimitiveValue.cpp

    r166486 r166860  
    306306        return;
    307307    case Calculated: {
    308         RefPtr<CSSCalcValue> calcValue = CSSCalcValue::create(length.calculationValue().get(), style);
     308        RefPtr<CSSCalcValue> calcValue = CSSCalcValue::create(length.calculationValue(), *style);
    309309        init(calcValue.release());
    310310        return;
     
    313313    case Undefined:
    314314        ASSERT_NOT_REACHED();
    315         break;
    316     }
     315        return;
     316    }
     317    ASSERT_NOT_REACHED();
    317318}
    318319
     
    329330        m_primitiveUnitType = CSS_VALUE_ID;
    330331        m_value.valueID = CSSValueAuto;
    331         break;
     332        return;
    332333    case WebCore::Fixed:
    333334        m_primitiveUnitType = CSS_PX;
    334335        m_value.num = length.value();
    335         break;
     336        return;
    336337    case Intrinsic:
    337338        m_primitiveUnitType = CSS_VALUE_ID;
    338339        m_value.valueID = CSSValueIntrinsic;
    339         break;
     340        return;
    340341    case MinIntrinsic:
    341342        m_primitiveUnitType = CSS_VALUE_ID;
    342343        m_value.valueID = CSSValueMinIntrinsic;
    343         break;
     344        return;
    344345    case MinContent:
    345346        m_primitiveUnitType = CSS_VALUE_ID;
    346347        m_value.valueID = CSSValueWebkitMinContent;
    347         break;
     348        return;
    348349    case MaxContent:
    349350        m_primitiveUnitType = CSS_VALUE_ID;
    350351        m_value.valueID = CSSValueWebkitMaxContent;
    351         break;
     352        return;
    352353    case FillAvailable:
    353354        m_primitiveUnitType = CSS_VALUE_ID;
    354355        m_value.valueID = CSSValueWebkitFillAvailable;
    355         break;
     356        return;
    356357    case FitContent:
    357358        m_primitiveUnitType = CSS_VALUE_ID;
    358359        m_value.valueID = CSSValueWebkitFitContent;
    359         break;
     360        return;
    360361    case Percent:
    361362        m_primitiveUnitType = CSS_PERCENTAGE;
    362363        ASSERT(std::isfinite(length.percent()));
    363364        m_value.num = length.percent();
    364         break;
     365        return;
    365366    case ViewportPercentageWidth:
    366367        m_primitiveUnitType = CSS_VW;
    367368        m_value.num = length.viewportPercentageLength();
    368         break;
     369        return;
    369370    case ViewportPercentageHeight:
    370371        m_primitiveUnitType = CSS_VH;
    371372        m_value.num = length.viewportPercentageLength();
    372         break;
     373        return;
    373374    case ViewportPercentageMin:
    374375        m_primitiveUnitType = CSS_VMIN;
    375376        m_value.num = length.viewportPercentageLength();
    376         break;
     377        return;
    377378    case ViewportPercentageMax:
    378379        m_primitiveUnitType = CSS_VMAX;
    379380        m_value.num = length.viewportPercentageLength();
    380         break;
     381        return;
    381382    case Calculated:
    382383    case Relative:
    383384    case Undefined:
    384385        ASSERT_NOT_REACHED();
    385         break;
    386     }
     386        return;
     387    }
     388    ASSERT_NOT_REACHED();
    387389}
    388390
  • trunk/Source/WebCore/css/CSSPrimitiveValueMappings.h

    r166618 r166860  
    46474647        return Length(Auto);
    46484648    if ((supported & CalculatedConversion) && isCalculated())
    4649         return Length(cssCalcValue()->toCalcValue(style, rootStyle, multiplier));
     4649        return Length(cssCalcValue()->createCalculationValue(style, rootStyle, multiplier));
    46504650    if ((supported & ViewportPercentageConversion) && isViewportPercentageLength())
    46514651        return viewportPercentageLength();
  • trunk/Source/WebCore/css/CSSToStyleMap.cpp

    r157024 r166860  
    252252        length = Length(primitiveValue->getDoubleValue(), Percent);
    253253    else if (primitiveValue->isCalculatedPercentageWithLength())
    254         length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor));
     254        length = Length(primitiveValue->cssCalcValue()->createCalculationValue(style(), rootElementStyle(), zoomFactor));
    255255    else if (primitiveValue->isViewportPercentageLength())
    256256        length = primitiveValue->viewportPercentageLength();
     
    288288        length = Length(primitiveValue->getDoubleValue(), Percent);
    289289    else if (primitiveValue->isCalculatedPercentageWithLength())
    290         length = Length(primitiveValue->cssCalcValue()->toCalcValue(style(), rootElementStyle(), zoomFactor));
     290        length = Length(primitiveValue->cssCalcValue()->createCalculationValue(style(), rootElementStyle(), zoomFactor));
    291291    else if (primitiveValue->isViewportPercentageLength())
    292292        length = primitiveValue->viewportPercentageLength();
  • trunk/Source/WebCore/css/CSSToStyleMap.h

    r166138 r166860  
    2424
    2525#include "CSSPropertyNames.h"
    26 #include "LengthBox.h"
    2726#include <wtf/FastMalloc.h>
    2827#include <wtf/Noncopyable.h>
     
    3029namespace WebCore {
    3130
     31class Animation;
     32class CSSValue;
    3233class FillLayer;
    33 class CSSValue;
    34 class Animation;
    3534class RenderStyle;
    3635class StyleImage;
    3736class StyleResolver;
    3837class NinePieceImage;
     38
     39struct LengthBox;
    3940
    4041class CSSToStyleMap {
  • trunk/Source/WebCore/css/DeprecatedStyleBuilder.cpp

    r166786 r166860  
    389389        else if (primitiveValue->isLength()) {
    390390            Length length = primitiveValue->computeLength<Length>(styleResolver->style(), styleResolver->rootElementStyle(), styleResolver->style()->effectiveZoom());
    391             length.setQuirk(primitiveValue->isQuirkValue());
     391            length.setHasQuirk(primitiveValue->isQuirkValue());
    392392            setValue(styleResolver->style(), length);
    393393        } else if (primitiveValue->isPercentage())
    394394            setValue(styleResolver->style(), Length(primitiveValue->getDoubleValue(), Percent));
    395395        else if (primitiveValue->isCalculatedPercentageWithLength())
    396             setValue(styleResolver->style(), Length(primitiveValue->cssCalcValue()->toCalcValue(styleResolver->style(), styleResolver->rootElementStyle(), styleResolver->style()->effectiveZoom())));
     396            setValue(styleResolver->style(), Length(primitiveValue->cssCalcValue()->createCalculationValue(styleResolver->style(), styleResolver->rootElementStyle(), styleResolver->style()->effectiveZoom())));
    397397        else if (primitiveValue->isViewportPercentageLength())
    398398            setValue(styleResolver->style(), primitiveValue->viewportPercentageLength());
     
    450450            radiusWidth = Length(styleResolver->viewportPercentageValue(*pair->first(), pair->first()->getIntValue()), Fixed);
    451451        else if (pair->first()->isCalculatedPercentageWithLength())
    452             radiusWidth = Length((pair->first()->cssCalcValue()->toCalcValue(styleResolver->style(), styleResolver->rootElementStyle(), styleResolver->style()->effectiveZoom())));
     452            radiusWidth = Length(pair->first()->cssCalcValue()->createCalculationValue(styleResolver->style(), styleResolver->rootElementStyle(), styleResolver->style()->effectiveZoom()));
    453453        else
    454454            radiusWidth = pair->first()->computeLength<Length>(styleResolver->style(), styleResolver->rootElementStyle(), styleResolver->style()->effectiveZoom());
     
    458458            radiusHeight = Length(styleResolver->viewportPercentageValue(*pair->second(), pair->second()->getIntValue()), Fixed);
    459459        else if (pair->second()->isCalculatedPercentageWithLength())
    460             radiusHeight = Length((pair->second()->cssCalcValue()->toCalcValue(styleResolver->style(), styleResolver->rootElementStyle(), styleResolver->style()->effectiveZoom())));
     460            radiusHeight = Length(pair->second()->cssCalcValue()->createCalculationValue(styleResolver->style(), styleResolver->rootElementStyle(), styleResolver->style()->effectiveZoom()));
    461461        else
    462462            radiusHeight = pair->second()->computeLength<Length>(styleResolver->style(), styleResolver->rootElementStyle(), styleResolver->style()->effectiveZoom());
     
    884884            else if (primitiveValue->isPercentage())
    885885                size = (primitiveValue->getFloatValue() * parentSize) / 100.0f;
    886             else if (primitiveValue->isCalculatedPercentageWithLength())
    887                 size = primitiveValue->cssCalcValue()->toCalcValue(styleResolver->parentStyle(), styleResolver->rootElementStyle())->evaluate(parentSize);
    888             else if (primitiveValue->isViewportPercentageLength())
     886            else if (primitiveValue->isCalculatedPercentageWithLength()) {
     887                Ref<CalculationValue> calculationValue { primitiveValue->cssCalcValue()->createCalculationValue(styleResolver->parentStyle(), styleResolver->rootElementStyle()) };
     888                size = calculationValue->evaluate(parentSize);
     889            } else if (primitiveValue->isViewportPercentageLength())
    889890                size = valueForLength(primitiveValue->viewportPercentageLength(), 0, styleResolver->document().renderView());
    890891            else
  • trunk/Source/WebCore/css/LengthFunctions.cpp

    r164697 r166860  
    123123    switch (length.type()) {
    124124    case Fixed:
    125         return length.getFloatValue();
     125        return length.value();
    126126    case Percent:
    127127        return static_cast<float>(maximumValue * length.percent() / 100.0f);
     
    169169    switch (length.type()) {
    170170    case Fixed:
    171         return length.getFloatValue();
     171        return length.value();
    172172    case Percent:
    173173        return static_cast<float>(maximumValue * length.percent() / 100.0f);
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r166741 r166860  
    10421042
    10431043    // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
    1044     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
     1044    // FIXME: Using "hasQuirk" to decide the margin wasn't set is kind of lame.
    10451045    if (style.width().isIntrinsicOrAuto()) {
    1046         if (style.marginLeft().quirk())
     1046        if (style.marginLeft().hasQuirk())
    10471047            style.setMarginLeft(Length(intrinsicMargin, Fixed));
    1048         if (style.marginRight().quirk())
     1048        if (style.marginRight().hasQuirk())
    10491049            style.setMarginRight(Length(intrinsicMargin, Fixed));
    10501050    }
    10511051
    10521052    if (style.height().isAuto()) {
    1053         if (style.marginTop().quirk())
     1053        if (style.marginTop().hasQuirk())
    10541054            style.setMarginTop(Length(intrinsicMargin, Fixed));
    1055         if (style.marginBottom().quirk())
     1055        if (style.marginBottom().hasQuirk())
    10561056            style.setMarginBottom(Length(intrinsicMargin, Fixed));
    10571057    }
     
    18611861
    18621862    if (primitiveValue->isLength())
    1863         workingLength.length().setQuirk(primitiveValue->isQuirkValue());
     1863        workingLength.length().setHasQuirk(primitiveValue->isQuirkValue());
    18641864
    18651865    return true;
  • trunk/Source/WebCore/platform/CalculationValue.cpp

    r163439 r166860  
    11/*
    22 * Copyright (C) 2011 Google Inc. All rights reserved.
     3 * Copyright (C) 2014 Apple Inc. All rights reserved.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    3637namespace WebCore {
    3738
     39PassRef<CalculationValue> CalculationValue::create(std::unique_ptr<CalcExpressionNode> value, CalculationPermittedValueRange range)
     40{
     41    return adoptRef(*new CalculationValue(std::move(value), range));
     42}
     43
     44float CalcExpressionNumber::evaluate(float) const
     45{
     46    return m_value;
     47}
     48
     49bool CalcExpressionNumber::operator==(const CalcExpressionNode& other) const
     50{
     51    return other.type() == CalcExpressionNodeNumber && *this == toCalcExpressionNumber(other);
     52}
     53
     54float CalculationValue::evaluate(float maxValue) const
     55{
     56    float result = m_expression->evaluate(maxValue);
     57    // FIXME: This test was originally needed when we did not detect division by zero at parse time.
     58    // It's possible that this is now unneeded code and can be removed.
     59    if (std::isnan(result))
     60        return 0;
     61    return m_shouldClampToNonNegative && result < 0 ? 0 : result;
     62}
     63
    3864float CalcExpressionBinaryOperation::evaluate(float maxValue) const
    3965{
     
    5682}
    5783
    58 PassRefPtr<CalculationValue> CalculationValue::create(std::unique_ptr<CalcExpressionNode> value, CalculationPermittedValueRange range)
     84bool CalcExpressionBinaryOperation::operator==(const CalcExpressionNode& other) const
    5985{
    60     return adoptRef(new CalculationValue(std::move(value), range));
     86    return other.type() == CalcExpressionNodeBinaryOperation && *this == toCalcExpressionBinaryOperation(other);
    6187}
    6288
    63 float CalculationValue::evaluate(float maxValue) const
     89float CalcExpressionLength::evaluate(float maxValue) const
    6490{
    65     float result = m_value->evaluate(maxValue);
    66     // FIXME calc https://webkit.org/b/80411 : result is NaN when there is a division
    67     // by zero which isn't found at parse time.
    68     if (std::isnan(result))
    69         return 0;
    70     return m_isNonNegative && result < 0 ? 0 : result;
     91    return floatValueForLength(m_length, maxValue);
     92}
     93
     94bool CalcExpressionLength::operator==(const CalcExpressionNode& other) const
     95{
     96    return other.type() == CalcExpressionNodeLength && *this == toCalcExpressionLength(other);
     97}
     98
     99float CalcExpressionBlendLength::evaluate(float maxValue) const
     100{
     101    return (1.0f - m_progress) * floatValueForLength(m_from, maxValue) + m_progress * floatValueForLength(m_to, maxValue);
     102}
     103
     104bool CalcExpressionBlendLength::operator==(const CalcExpressionNode& other) const
     105{
     106    return other.type() == CalcExpressionNodeBlendLength && *this == toCalcExpressionBlendLength(other);
    71107}
    72108
  • trunk/Source/WebCore/platform/CalculationValue.h

    r163439 r166860  
    6363    WTF_MAKE_FAST_ALLOCATED;
    6464public:
    65     CalcExpressionNode()
    66         : m_type(CalcExpressionNodeUndefined)
    67     {
    68     }
    69 
    70     virtual ~CalcExpressionNode()
    71     {
    72     }
     65    explicit CalcExpressionNode(CalcExpressionNodeType = CalcExpressionNodeUndefined);
     66    virtual ~CalcExpressionNode() { }
     67
     68    CalcExpressionNodeType type() const { return m_type; }
    7369
    7470    virtual float evaluate(float maxValue) const = 0;
    7571    virtual bool operator==(const CalcExpressionNode&) const = 0;
    7672
    77     CalcExpressionNodeType type() const { return m_type; }
    78 
    79 protected:
     73private:
    8074    CalcExpressionNodeType m_type;
    8175};
    8276
    83 class CalculationValue : public RefCounted<CalculationValue> {
    84 public:
    85     static PassRefPtr<CalculationValue> create(std::unique_ptr<CalcExpressionNode> value, CalculationPermittedValueRange);
    86     float evaluate(float maxValue) const;
    87 
    88     bool operator==(const CalculationValue& o) const
    89     {
    90         return *(m_value.get()) == *(o.m_value.get());
    91     }
    92 
    93     bool isNonNegative() const { return m_isNonNegative; }
    94     const CalcExpressionNode* expression() const { return m_value.get(); }
    95 
    96 private:
    97     CalculationValue(std::unique_ptr<CalcExpressionNode> value, CalculationPermittedValueRange range)
    98         : m_value(std::move(value))
    99         , m_isNonNegative(range == CalculationRangeNonNegative)
    100     {
    101     }
    102 
    103     std::unique_ptr<CalcExpressionNode> m_value;
    104     bool m_isNonNegative;
    105 };
    106 
    107 class CalcExpressionNumber : public CalcExpressionNode {
    108 public:
    109     explicit CalcExpressionNumber(float value)
    110         : m_value(value)
    111     {
    112         m_type = CalcExpressionNodeNumber;
    113     }
    114 
    115     bool operator==(const CalcExpressionNumber& o) const
    116     {
    117         return m_value == o.m_value;
    118     }
    119 
    120     virtual bool operator==(const CalcExpressionNode& o) const override
    121     {
    122         return type() == o.type() && *this == static_cast<const CalcExpressionNumber&>(o);
    123     }
    124 
    125     virtual float evaluate(float) const override
    126     {
    127         return m_value;
    128     }
     77class CalcExpressionNumber final : public CalcExpressionNode {
     78public:
     79    explicit CalcExpressionNumber(float);
    12980
    13081    float value() const { return m_value; }
    13182
    13283private:
     84    virtual float evaluate(float) const override;
     85    virtual bool operator==(const CalcExpressionNode&) const override;
     86
    13387    float m_value;
    13488};
    13589
    136 inline const CalcExpressionNumber* toCalcExpressionNumber(const CalcExpressionNode* value)
    137 {
    138     ASSERT_WITH_SECURITY_IMPLICATION(!value || value->type() == CalcExpressionNodeNumber);
    139     return static_cast<const CalcExpressionNumber*>(value);
    140 }
    141 
    142 class CalcExpressionLength : public CalcExpressionNode {
    143 public:
    144     explicit CalcExpressionLength(Length length)
    145         : m_length(length)
    146     {
    147         m_type = CalcExpressionNodeLength;
    148     }
    149 
    150     bool operator==(const CalcExpressionLength& o) const
    151     {
    152         return m_length == o.m_length;
    153     }
    154 
    155     virtual bool operator==(const CalcExpressionNode& o) const override
    156     {
    157         return type() == o.type() && *this == static_cast<const CalcExpressionLength&>(o);
    158     }
    159 
    160     virtual float evaluate(float maxValue) const override
    161     {
    162         return floatValueForLength(m_length, maxValue);
    163     }
     90class CalcExpressionLength final : public CalcExpressionNode {
     91public:
     92    explicit CalcExpressionLength(Length);
    16493
    16594    const Length& length() const { return m_length; }
    16695
    16796private:
     97    virtual float evaluate(float maxValue) const override;
     98    virtual bool operator==(const CalcExpressionNode&) const override;
     99
    168100    Length m_length;
    169101};
    170102
    171 inline const CalcExpressionLength* toCalcExpressionLength(const CalcExpressionNode* value)
    172 {
    173     ASSERT_WITH_SECURITY_IMPLICATION(!value || value->type() == CalcExpressionNodeLength);
    174     return static_cast<const CalcExpressionLength*>(value);
    175 }
    176 
    177 class CalcExpressionBinaryOperation : public CalcExpressionNode {
    178 public:
    179     CalcExpressionBinaryOperation(std::unique_ptr<CalcExpressionNode> leftSide, std::unique_ptr<CalcExpressionNode> rightSide, CalcOperator op)
    180         : m_leftSide(std::move(leftSide))
    181         , m_rightSide(std::move(rightSide))
    182         , m_operator(op)
    183     {
    184         m_type = CalcExpressionNodeBinaryOperation;
    185     }
    186 
    187     bool operator==(const CalcExpressionBinaryOperation& o) const
    188     {
    189         return m_operator == o.m_operator && *m_leftSide == *o.m_leftSide && *m_rightSide == *o.m_rightSide;
    190     }
    191 
    192     virtual bool operator==(const CalcExpressionNode& o) const override
    193     {
    194         return type() == o.type() && *this == static_cast<const CalcExpressionBinaryOperation&>(o);
    195     }
    196 
    197     virtual float evaluate(float) const override;
    198 
    199     const CalcExpressionNode* leftSide() const { return m_leftSide.get(); }
    200     const CalcExpressionNode* rightSide() const { return m_rightSide.get(); }
     103class CalcExpressionBinaryOperation final : public CalcExpressionNode {
     104public:
     105    CalcExpressionBinaryOperation(std::unique_ptr<CalcExpressionNode> leftSide, std::unique_ptr<CalcExpressionNode> rightSide, CalcOperator);
     106
     107    const CalcExpressionNode& leftSide() const { return *m_leftSide; }
     108    const CalcExpressionNode& rightSide() const { return *m_rightSide; }
    201109    CalcOperator getOperator() const { return m_operator; }
    202110
    203111private:
     112    virtual float evaluate(float maxValue) const override;
     113    virtual bool operator==(const CalcExpressionNode&) const override;
     114
    204115    std::unique_ptr<CalcExpressionNode> m_leftSide;
    205116    std::unique_ptr<CalcExpressionNode> m_rightSide;
     
    207118};
    208119
    209 inline const CalcExpressionBinaryOperation* toCalcExpressionBinaryOperation(const CalcExpressionNode* value)
    210 {
    211     ASSERT_WITH_SECURITY_IMPLICATION(!value || value->type() == CalcExpressionNodeBinaryOperation);
    212     return static_cast<const CalcExpressionBinaryOperation*>(value);
    213 }
    214 
    215 class CalcExpressionBlendLength : public CalcExpressionNode {
    216 public:
    217     CalcExpressionBlendLength(Length from, Length to, float progress)
    218         : m_from(from)
    219         , m_to(to)
    220         , m_progress(progress)
    221     {
    222         m_type = CalcExpressionNodeBlendLength;
    223     }
    224 
    225     bool operator==(const CalcExpressionBlendLength& o) const
    226     {
    227         return m_progress == o.m_progress && m_from == o.m_from && m_to == o.m_to;
    228     }
    229 
    230     virtual bool operator==(const CalcExpressionNode& o) const override
    231     {
    232         return type() == o.type() && *this == static_cast<const CalcExpressionBlendLength&>(o);
    233     }
    234 
    235     virtual float evaluate(float maxValue) const override
    236     {
    237         return (1.0f - m_progress) * floatValueForLength(m_from, maxValue) + m_progress * floatValueForLength(m_to, maxValue);
    238     }
     120class CalcExpressionBlendLength final : public CalcExpressionNode {
     121public:
     122    CalcExpressionBlendLength(Length from, Length to, float progress);
    239123
    240124    const Length& from() const { return m_from; }
     
    243127
    244128private:
     129    virtual float evaluate(float maxValue) const override;
     130    virtual bool operator==(const CalcExpressionNode&) const override;
     131
    245132    Length m_from;
    246133    Length m_to;
     
    248135};
    249136
    250 inline const CalcExpressionBlendLength* toCalcExpressionBlendLength(const CalcExpressionNode* value)
    251 {
    252     ASSERT_WITH_SECURITY_IMPLICATION(!value || value->type() == CalcExpressionNodeBlendLength);
    253     return static_cast<const CalcExpressionBlendLength*>(value);
     137class CalculationValue : public RefCounted<CalculationValue> {
     138public:
     139    static PassRef<CalculationValue> create(std::unique_ptr<CalcExpressionNode>, CalculationPermittedValueRange);
     140    float evaluate(float maxValue) const;
     141
     142    bool shouldClampToNonNegative() const { return m_shouldClampToNonNegative; }
     143    const CalcExpressionNode& expression() const { return *m_expression; }
     144
     145private:
     146    CalculationValue(std::unique_ptr<CalcExpressionNode>, CalculationPermittedValueRange);
     147
     148    std::unique_ptr<CalcExpressionNode> m_expression;
     149    bool m_shouldClampToNonNegative;
     150};
     151
     152inline CalcExpressionNode::CalcExpressionNode(CalcExpressionNodeType type)
     153    : m_type(type)
     154{
     155}
     156
     157inline CalculationValue::CalculationValue(std::unique_ptr<CalcExpressionNode> expression, CalculationPermittedValueRange range)
     158    : m_expression(std::move(expression))
     159    , m_shouldClampToNonNegative(range == CalculationRangeNonNegative)
     160{
     161}
     162
     163inline bool operator==(const CalculationValue& a, const CalculationValue& b)
     164{
     165    return a.expression() == b.expression();
     166}
     167
     168inline CalcExpressionNumber::CalcExpressionNumber(float value)
     169    : CalcExpressionNode(CalcExpressionNodeNumber)
     170    , m_value(value)
     171{
     172}
     173
     174inline bool operator==(const CalcExpressionNumber& a, const CalcExpressionNumber& b)
     175{
     176    return a.value() == b.value();
     177}
     178
     179inline const CalcExpressionNumber& toCalcExpressionNumber(const CalcExpressionNode& value)
     180{
     181    ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeNumber);
     182    return static_cast<const CalcExpressionNumber&>(value);
     183}
     184
     185inline CalcExpressionLength::CalcExpressionLength(Length length)
     186    : CalcExpressionNode(CalcExpressionNodeLength)
     187    , m_length(length)
     188{
     189}
     190
     191inline bool operator==(const CalcExpressionLength& a, const CalcExpressionLength& b)
     192{
     193    return a.length() == b.length();
     194}
     195
     196inline const CalcExpressionLength& toCalcExpressionLength(const CalcExpressionNode& value)
     197{
     198    ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeLength);
     199    return static_cast<const CalcExpressionLength&>(value);
     200}
     201
     202inline CalcExpressionBinaryOperation::CalcExpressionBinaryOperation(std::unique_ptr<CalcExpressionNode> leftSide, std::unique_ptr<CalcExpressionNode> rightSide, CalcOperator op)
     203    : CalcExpressionNode(CalcExpressionNodeBinaryOperation)
     204    , m_leftSide(std::move(leftSide))
     205    , m_rightSide(std::move(rightSide))
     206    , m_operator(op)
     207{
     208}
     209
     210inline bool operator==(const CalcExpressionBinaryOperation& a, const CalcExpressionBinaryOperation& b)
     211{
     212    return a.getOperator() == b.getOperator() && a.leftSide() == b.leftSide() && a.rightSide() == b.rightSide();
     213}
     214
     215inline const CalcExpressionBinaryOperation& toCalcExpressionBinaryOperation(const CalcExpressionNode& value)
     216{
     217    ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeBinaryOperation);
     218    return static_cast<const CalcExpressionBinaryOperation&>(value);
     219}
     220
     221inline CalcExpressionBlendLength::CalcExpressionBlendLength(Length from, Length to, float progress)
     222    : CalcExpressionNode(CalcExpressionNodeBlendLength)
     223    , m_from(from)
     224    , m_to(to)
     225    , m_progress(progress)
     226{
     227}
     228
     229inline bool operator==(const CalcExpressionBlendLength& a, const CalcExpressionBlendLength& b)
     230{
     231    return a.progress() == b.progress() && a.from() == b.from() && a.to() == b.to();
     232}
     233
     234inline const CalcExpressionBlendLength& toCalcExpressionBlendLength(const CalcExpressionNode& value)
     235{
     236    ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeBlendLength);
     237    return static_cast<const CalcExpressionBlendLength&>(value);
    254238}
    255239
  • trunk/Source/WebCore/platform/Length.cpp

    r165848 r166860  
    33 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
    44 *           (C) 2001 Dirk Mueller ( mueller@kde.org )
    5  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
     5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2014 Apple Inc. All rights reserved.
    66 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
    77 *
     
    2828#include "CalculationValue.h"
    2929#include <wtf/ASCIICType.h>
    30 #include <wtf/Assertions.h>
     30#include <wtf/HashMap.h>
     31#include <wtf/NeverDestroyed.h>
    3132#include <wtf/StdLibExtras.h>
    3233#include <wtf/text/StringBuffer.h>
     
    152153    return r;
    153154}
    154        
    155 class CalculationValueHandleMap {
    156     WTF_MAKE_FAST_ALLOCATED;
     155
     156class CalculationValueMap {
    157157public:
    158     CalculationValueHandleMap()
    159         : m_index(1)
    160     {
    161     }
     158    CalculationValueMap();
     159
     160    unsigned insert(PassRef<CalculationValue>);
     161    void ref(unsigned handle);
     162    void deref(unsigned handle);
     163
     164    CalculationValue& get(unsigned handle) const;
     165
     166private:
     167    struct Entry {
     168        uint64_t referenceCountMinusOne;
     169        CalculationValue* value;
     170        Entry();
     171        Entry(CalculationValue&);
     172    };
     173
     174    unsigned m_nextAvailableHandle;
     175    HashMap<unsigned, Entry> m_map;
     176};
     177
     178inline CalculationValueMap::Entry::Entry()
     179    : referenceCountMinusOne(0)
     180    , value(nullptr)
     181{
     182}
     183
     184inline CalculationValueMap::Entry::Entry(CalculationValue& value)
     185    : referenceCountMinusOne(0)
     186    , value(&value)
     187{
     188}
     189
     190inline CalculationValueMap::CalculationValueMap()
     191    : m_nextAvailableHandle(1)
     192{
     193}
    162194   
    163     int insert(PassRefPtr<CalculationValue> calcValue)
    164     {
    165         ASSERT(m_index);
    166         // FIXME calc(): https://bugs.webkit.org/show_bug.cgi?id=80489
    167         // This monotonically increasing handle generation scheme is potentially wasteful
    168         // of the handle space. Consider reusing empty handles.
    169         while (m_map.contains(m_index))
    170             m_index++;
    171        
    172         m_map.set(m_index, calcValue);       
    173        
    174         return m_index;
    175     }
    176 
    177     void remove(int index)
    178     {
    179         ASSERT(m_map.contains(index));
    180         m_map.remove(index);
    181     }
    182 
    183     void remove(HashMap<int, RefPtr<CalculationValue>>::iterator it)
    184     {
    185         ASSERT(it != m_map.end());
    186         m_map.remove(it);
    187     }
    188 
    189     PassRefPtr<CalculationValue> get(int index)
    190     {
    191         ASSERT(m_map.contains(index));
    192         return m_map.get(index);
    193     }
    194 
    195     HashMap<int, RefPtr<CalculationValue>>::iterator find(int index)
    196     {
    197         ASSERT(m_map.contains(index));
    198         return m_map.find(index);
    199     }
    200 
    201 private:       
    202     int m_index;
    203     HashMap<int, RefPtr<CalculationValue>> m_map;
    204 };
    205    
    206 static CalculationValueHandleMap& calcHandles()
    207 {
    208     DEPRECATED_DEFINE_STATIC_LOCAL(CalculationValueHandleMap, handleMap, ());
    209     return handleMap;
    210 }
    211 
    212 Length::Length(PassRefPtr<CalculationValue> calc)
    213     : m_quirk(false)
     195inline unsigned CalculationValueMap::insert(PassRef<CalculationValue> value)
     196{
     197    ASSERT(m_nextAvailableHandle);
     198
     199    // The leakRef below is balanced by the deref in the deref member function.
     200    Entry leakedValue = value.leakRef();
     201
     202    // FIXME: This monotonically increasing handle generation scheme is potentially wasteful
     203    // of the handle space. Consider reusing empty handles. https://bugs.webkit.org/show_bug.cgi?id=80489
     204    while (!m_map.isValidKey(m_nextAvailableHandle) || !m_map.add(m_nextAvailableHandle, leakedValue).isNewEntry)
     205        ++m_nextAvailableHandle;
     206
     207    return m_nextAvailableHandle++;
     208}
     209
     210inline CalculationValue& CalculationValueMap::get(unsigned handle) const
     211{
     212    ASSERT(m_map.contains(handle));
     213
     214    return *m_map.find(handle)->value.value;
     215}
     216
     217inline void CalculationValueMap::ref(unsigned handle)
     218{
     219    ASSERT(m_map.contains(handle));
     220
     221    ++m_map.find(handle)->value.referenceCountMinusOne;
     222}
     223
     224inline void CalculationValueMap::deref(unsigned handle)
     225{
     226    ASSERT(m_map.contains(handle));
     227
     228    auto it = m_map.find(handle);
     229    if (it->value.referenceCountMinusOne) {
     230        --it->value.referenceCountMinusOne;
     231        return;
     232    }
     233
     234    // The deref below is balanced by the leakRef in the insert member function.
     235    it->value.value->deref();
     236    m_map.remove(it);
     237}
     238
     239static CalculationValueMap& calculationValues()
     240{
     241    static NeverDestroyed<CalculationValueMap> map;
     242    return map;
     243}
     244
     245Length::Length(PassRef<CalculationValue> value)
     246    : m_hasQuirk(false)
    214247    , m_type(Calculated)
    215248    , m_isFloat(false)
    216249{
    217     m_intValue = calcHandles().insert(calc);
     250    m_calculationValueHandle = calculationValues().insert(std::move(value));
    218251}
    219252       
     
    229262    return Length(CalculationValue::create(std::move(blend), CalculationRangeAll));
    230263}
    231          
    232 PassRefPtr<CalculationValue> Length::calculationValue() const
     264
     265CalculationValue& Length::calculationValue() const
    233266{
    234267    ASSERT(isCalculated());
    235     return calcHandles().get(calculationHandle());
     268    return calculationValues().get(m_calculationValueHandle);
    236269}
    237270   
    238 void Length::incrementCalculatedRef() const
     271void Length::ref() const
    239272{
    240273    ASSERT(isCalculated());
    241     calculationValue()->ref();
    242 }
    243 
    244 void Length::decrementCalculatedRef() const
     274    calculationValues().ref(m_calculationValueHandle);
     275}
     276
     277void Length::deref() const
    245278{
    246279    ASSERT(isCalculated());
    247     auto it = calcHandles().find(calculationHandle());
    248     if (it->value->hasOneRef())
    249         calcHandles().remove(it);
     280    calculationValues().deref(m_calculationValueHandle);
    250281}
    251282
     
    253284{
    254285    ASSERT(isCalculated());
    255     float result = calculationValue()->evaluate(maxValue);
     286    float result = calculationValue().evaluate(maxValue);
    256287    if (std::isnan(result))
    257288        return 0;
     
    259290}
    260291
    261 bool Length::isCalculatedEqual(const Length& o) const
    262 {
    263     return isCalculated() && (calculationValue() == o.calculationValue() || *calculationValue() == *o.calculationValue());
     292bool Length::isCalculatedEqual(const Length& other) const
     293{
     294    return calculationValue() == other.calculationValue();
    264295}
    265296
  • trunk/Source/WebCore/platform/Length.h

    r156132 r166860  
    11/*
    22    Copyright (C) 1999 Lars Knoll (knoll@kde.org)
    3     Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
     3    Copyright (C) 2006, 2008, 2014 Apple Inc. All rights reserved.
    44    Copyright (C) 2011 Rik Cabanier (cabanier@adobe.com)
    55    Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
     
    3030#include <wtf/FastMalloc.h>
    3131#include <wtf/Forward.h>
    32 #include <wtf/HashMap.h>
    33 #include <wtf/MathExtras.h>
    3432
    3533namespace WebCore {
     
    4947    WTF_MAKE_FAST_ALLOCATED;
    5048public:
    51     Length()
    52         :  m_intValue(0), m_quirk(false), m_type(Auto), m_isFloat(false)
    53     {
    54     }
    55 
    56     Length(LengthType t)
    57         : m_intValue(0), m_quirk(false), m_type(t), m_isFloat(false)
    58     {
    59         ASSERT(t != Calculated);
    60     }
    61 
    62     Length(int v, LengthType t, bool q = false)
    63         : m_intValue(v), m_quirk(q), m_type(t), m_isFloat(false)
    64     {
    65         ASSERT(t != Calculated);
    66     }
    67    
    68     Length(LayoutUnit v, LengthType t, bool q = false)
    69         : m_floatValue(v.toFloat()), m_quirk(q), m_type(t), m_isFloat(true)
    70     {
    71         ASSERT(t != Calculated);
    72     }
    73    
    74     Length(float v, LengthType t, bool q = false)
    75         : m_floatValue(v), m_quirk(q), m_type(t), m_isFloat(true)
    76     {
    77         ASSERT(t != Calculated);
    78     }
    79 
    80     Length(double v, LengthType t, bool q = false)
    81         : m_quirk(q), m_type(t), m_isFloat(true)
    82     {
    83         m_floatValue = static_cast<float>(v);   
    84     }
    85 
    86     explicit Length(PassRefPtr<CalculationValue>);
    87 
    88     Length(const Length& length)
    89     {
    90         initFromLength(length);
    91     }
    92 
    93     Length(Length&& other)
    94     {
    95         moveFromLength(std::move(other));
    96     }
    97 
    98     Length& operator=(const Length& length)
    99     {
    100         initFromLength(length);
    101         return *this;
    102     }
    103 
    104     Length& operator=(Length&& other)
    105     {
    106         if (this != &other)
    107             moveFromLength(std::move(other));
    108         return *this;
    109     }
    110 
    111     ~Length()
    112     {
    113         if (isCalculated())
    114             decrementCalculatedRef();
    115     } 
    116    
    117     bool operator==(const Length& o) const { return (m_type == o.m_type) && (m_quirk == o.m_quirk) && (isUndefined() || (getFloatValue() == o.getFloatValue()) || isCalculatedEqual(o)); }
    118     bool operator!=(const Length& o) const { return !(*this == o); }
    119 
    120     const Length& operator*=(float v)
    121     {       
    122         if (isCalculated()) {
    123             ASSERT_NOT_REACHED();
    124             return *this;
    125         }
    126        
    127         if (m_isFloat)
    128             m_floatValue = static_cast<float>(m_floatValue * v);
    129         else       
    130             m_intValue = static_cast<int>(m_intValue * v);
    131        
    132         return *this;
    133     }
    134    
    135     inline float value() const
    136     {
    137         return getFloatValue();
    138     }
    139 
    140      int intValue() const
    141      {
    142         if (isCalculated()) {
    143             ASSERT_NOT_REACHED();
    144             return 0;
    145         }
    146         return getIntValue();
    147     }
    148 
    149     float percent() const
    150     {
    151         ASSERT(isPercent());
    152         return getFloatValue();
    153     }
    154 
    155     PassRefPtr<CalculationValue> calculationValue() const;
    156 
    157     LengthType type() const { return static_cast<LengthType>(m_type); }
    158     bool quirk() const { return m_quirk; }
    159 
    160     void setQuirk(bool quirk)
    161     {
    162         m_quirk = quirk;
    163     }
    164 
    165     void setValue(LengthType t, int value)
    166     {
    167         m_type = t;
    168         m_intValue = value;
    169         m_isFloat = false;
    170     }
    171 
    172     void setValue(int value)
    173     {
    174         if (isCalculated()) {
    175             ASSERT_NOT_REACHED();
    176             return;
    177         }
    178         setValue(Fixed, value);
    179     }
    180 
    181     void setValue(LengthType t, float value)
    182     {
    183         m_type = t;
    184         m_floatValue = value;
    185         m_isFloat = true;   
    186     }
    187 
    188     void setValue(LengthType t, LayoutUnit value)
    189     {
    190         m_type = t;
    191         m_floatValue = value;
    192         m_isFloat = true;   
    193     }
    194 
    195     void setValue(float value)
    196     {
    197         *this = Length(value, Fixed);
    198     }
    199 
    200     bool isUndefined() const { return type() == Undefined; }
    201 
    202     // FIXME calc: https://bugs.webkit.org/show_bug.cgi?id=80357. A calculated Length
     49    Length(LengthType = Auto);
     50
     51    Length(int value, LengthType, bool hasQuirk = false);
     52    Length(LayoutUnit value, LengthType, bool hasQuirk = false);
     53    Length(float value, LengthType, bool hasQuirk = false);
     54    Length(double value, LengthType, bool hasQuirk = false);
     55
     56    explicit Length(PassRef<CalculationValue>);
     57
     58    Length(const Length&);
     59    Length(Length&&);
     60    Length& operator=(const Length&);
     61    Length& operator=(Length&&);
     62
     63    ~Length();
     64
     65    void setValue(LengthType, int value);
     66    void setValue(LengthType, float value);
     67    void setValue(LengthType, LayoutUnit value);
     68    Length& operator*=(float);
     69
     70    void setHasQuirk(bool);
     71
     72    bool operator==(const Length&) const;
     73    bool operator!=(const Length&) const;
     74
     75    float value() const;
     76    int intValue() const;
     77    float percent() const;
     78    float viewportPercentageLength() const;
     79    CalculationValue& calculationValue() const;
     80
     81    LengthType type() const;
     82
     83    bool isAuto() const;
     84    bool isFixed() const;
     85    bool isMaxContent() const;
     86    bool isMinContent() const;
     87    bool isRelative() const;
     88    bool isUndefined() const;
     89
     90    bool hasQuirk() const;
     91
     92    // FIXME calc: https://bugs.webkit.org/show_bug.cgi?id=80357. A calculated Length
    20393    // always contains a percentage, and without a maxValue passed to these functions
    204     // it's impossible to determine the sign or zero-ness. We assume all calc values
    205     // are positive and non-zero for now.   
    206     bool isZero() const
    207     {
    208         ASSERT(!isUndefined());
    209         if (isCalculated())
    210             return false;
    211            
    212         return m_isFloat ? !m_floatValue : !m_intValue;
    213     }
    214     bool isPositive() const
    215     {
    216         if (isUndefined())
    217             return false;
    218         if (isCalculated())
    219             return true;
    220                
    221         return getFloatValue() > 0;
    222     }
    223     bool isNegative() const
    224     {
    225         if (isUndefined() || isCalculated())
    226             return false;
    227            
    228         return getFloatValue() < 0;
    229     }
    230    
    231     bool isAuto() const { return type() == Auto; }
    232     bool isRelative() const { return type() == Relative; }
    233     bool isPercent() const { return type() == Percent || type() == Calculated; }
    234     bool isFixed() const { return type() == Fixed; }
    235     bool isIntrinsicOrAuto() const { return type() == Auto || isLegacyIntrinsic() || isIntrinsic(); }
    236     bool isLegacyIntrinsic() const { return type() == Intrinsic || type() == MinIntrinsic; }
    237     bool isIntrinsic() const { return type() == MinContent || type() == MaxContent || type() == FillAvailable || type() == FitContent; }
    238     bool isSpecified() const { return type() == Fixed || type() == Percent || type() == Calculated || isViewportPercentage(); }
    239     bool isSpecifiedOrIntrinsic() const { return isSpecified() || isIntrinsic(); }
    240     bool isCalculated() const { return type() == Calculated; }
     94    // it's impossible to determine the sign or zero-ness. The following three functions
     95    // act as if all calculated values are positive.
     96    bool isZero() const;
     97    bool isPositive() const;
     98    bool isNegative() const;
     99
     100    // Returns true for both Percent and Calculated.
     101    // FIXME: Doesn't really seem OK to return true for Calculated given this function's name,
     102    // even though all calculated values are treated as percentages. Callers can tell Percent
     103    // from a Calculated already by looking at type, so this function only half-hides the distinction.
     104    bool isPercent() const;
     105
     106    bool isIntrinsic() const;
     107    bool isIntrinsicOrAuto() const;
     108    bool isSpecified() const;
     109    bool isSpecifiedOrIntrinsic() const;
     110    bool isViewportPercentage() const;
     111
     112    // Blend two lengths to produce a new length that is in between them. Used for animation.
     113    // FIXME: Why is this a member function?
     114    Length blend(const Length& from, double progress) const;
     115
     116    float nonNanCalculatedValue(int maxValue) const;
     117
     118private:
     119    bool isCalculated() const;
     120    bool isLegacyIntrinsic() const;
     121
    241122    bool isCalculatedEqual(const Length&) const;
    242     bool isMinContent() const { return type() == MinContent; }
    243     bool isMaxContent() const { return type() == MaxContent; }
    244 
    245     Length blend(const Length& from, double progress) const
    246     {
    247         // Blend two lengths to produce a new length that is in between them.  Used for animation.
    248         if (from.type() == Calculated || type() == Calculated)
    249             return blendMixedTypes(from, progress);
    250        
    251         if (!from.isZero() && !isZero() && from.type() != type())
    252             return blendMixedTypes(from, progress);
    253 
    254         if (from.isZero() && isZero())
    255             return *this;
    256        
    257         LengthType resultType = type();
    258         if (isZero())
    259             resultType = from.type();
    260        
    261         if (resultType == Percent) {
    262             float fromPercent = from.isZero() ? 0 : from.percent();
    263             float toPercent = isZero() ? 0 : percent();
    264             return Length(WebCore::blend(fromPercent, toPercent, progress), Percent);
    265         }
    266 
    267         float fromValue = from.isZero() ? 0 : from.value();
    268         float toValue = isZero() ? 0 : value();
    269         return Length(WebCore::blend(fromValue, toValue, progress), resultType);
    270     }
    271 
    272     float getFloatValue() const
    273     {
    274         ASSERT(!isUndefined());
    275         return m_isFloat ? m_floatValue : m_intValue;
    276     }
    277     float nonNanCalculatedValue(int maxValue) const;
    278 
    279     bool isViewportPercentage() const
    280     {
    281         LengthType lengthType = type();
    282         return lengthType >= ViewportPercentageWidth && lengthType <= ViewportPercentageMax;
    283     }
    284     float viewportPercentageLength() const
    285     {
    286         ASSERT(isViewportPercentage());
    287         return getFloatValue();
    288     }
    289 private:
    290     int getIntValue() const
    291     {
    292         ASSERT(!isUndefined());
    293         return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue;
    294     }
    295     void initFromLength(const Length& length)
    296     {
    297         memcpy(this, &length, sizeof(Length));
    298         if (isCalculated())
    299             incrementCalculatedRef();
    300     }
    301 
    302     void moveFromLength(Length&& length)
    303     {
    304         ASSERT(this != &length);
    305         memcpy(this, &length, sizeof(Length));
    306         length.m_type = Auto;
    307     }
    308 
    309123    Length blendMixedTypes(const Length& from, double progress) const;
    310124
    311     int calculationHandle() const
    312     {
    313         ASSERT(isCalculated());
    314         return getIntValue();
    315     }
    316     void incrementCalculatedRef() const;
    317     void decrementCalculatedRef() const;   
     125    void ref() const;
     126    void deref() const;
    318127   
    319128    union {
    320129        int m_intValue;
    321130        float m_floatValue;
     131        unsigned m_calculationValueHandle;
    322132    };
    323     bool m_quirk;
     133    bool m_hasQuirk;
    324134    unsigned char m_type;
    325135    bool m_isFloat;
    326136};
    327137
    328 std::unique_ptr<Length[]> newCoordsArray(const String&, int& len);
    329 std::unique_ptr<Length[]> newLengthArray(const String&, int& len);
     138std::unique_ptr<Length[]> newCoordsArray(const String&, int& length);
     139std::unique_ptr<Length[]> newLengthArray(const String&, int& length);
     140
     141inline Length::Length(LengthType type)
     142    : m_intValue(0), m_hasQuirk(false), m_type(type), m_isFloat(false)
     143{
     144    ASSERT(type != Calculated);
     145}
     146
     147inline Length::Length(int value, LengthType type, bool hasQuirk)
     148    : m_intValue(value), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(false)
     149{
     150    ASSERT(type != Calculated);
     151}
     152
     153inline Length::Length(LayoutUnit value, LengthType type, bool hasQuirk)
     154    : m_floatValue(value.toFloat()), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(true)
     155{
     156    ASSERT(type != Calculated);
     157}
     158
     159inline Length::Length(float value, LengthType type, bool hasQuirk)
     160    : m_floatValue(value), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(true)
     161{
     162    ASSERT(type != Calculated);
     163}
     164
     165inline Length::Length(double value, LengthType type, bool hasQuirk)
     166    : m_floatValue(static_cast<float>(value)), m_hasQuirk(hasQuirk), m_type(type), m_isFloat(true)
     167{
     168    ASSERT(type != Calculated);
     169}
     170
     171inline Length::Length(const Length& other)
     172{
     173    if (other.isCalculated())
     174        other.ref();
     175
     176    memcpy(this, &other, sizeof(Length));
     177}
     178
     179inline Length::Length(Length&& other)
     180{
     181    memcpy(this, &other, sizeof(Length));
     182    other.m_type = Auto;
     183}
     184
     185inline Length& Length::operator=(const Length& other)
     186{
     187    if (other.isCalculated())
     188        other.ref();
     189    if (isCalculated())
     190        deref();
     191
     192    memcpy(this, &other, sizeof(Length));
     193    return *this;
     194}
     195
     196inline Length& Length::operator=(Length&& other)
     197{
     198    if (this == &other)
     199        return *this;
     200
     201    if (isCalculated())
     202        deref();
     203
     204    memcpy(this, &other, sizeof(Length));
     205    other.m_type = Auto;
     206    return *this;
     207}
     208
     209inline Length::~Length()
     210{
     211    if (isCalculated())
     212        deref();
     213}
     214
     215inline bool Length::operator==(const Length& other) const
     216{
     217    // FIXME: This might be too long to be inline.
     218    if (type() != other.type() || hasQuirk() != other.hasQuirk())
     219        return false;
     220    if (isUndefined())
     221        return true;
     222    if (isCalculated())
     223        return isCalculatedEqual(other);
     224    return value() == other.value();
     225}
     226
     227inline bool Length::operator!=(const Length& other) const
     228{
     229    return !(*this == other);
     230}
     231
     232inline Length& Length::operator*=(float value)
     233{
     234    ASSERT(!isCalculated());
     235    if (isCalculated())
     236        return *this;
     237
     238    if (m_isFloat)
     239        m_floatValue *= value;
     240    else
     241        m_intValue *= value;
     242
     243    return *this;
     244}
     245
     246inline float Length::value() const
     247{
     248    ASSERT(!isUndefined());
     249    ASSERT(!isCalculated());
     250    return m_isFloat ? m_floatValue : m_intValue;
     251}
     252
     253inline int Length::intValue() const
     254{
     255    ASSERT(!isUndefined());
     256    ASSERT(!isCalculated());
     257    // FIXME: Makes no sense to return 0 here but not in the value() function above.
     258    if (isCalculated())
     259        return 0;
     260    return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue;
     261}
     262
     263inline float Length::percent() const
     264{
     265    ASSERT(isPercent());
     266    return value();
     267}
     268
     269inline float Length::viewportPercentageLength() const
     270{
     271    ASSERT(isViewportPercentage());
     272    return value();
     273}
     274
     275inline LengthType Length::type() const
     276{
     277    return static_cast<LengthType>(m_type);
     278}
     279
     280inline bool Length::hasQuirk() const
     281{
     282    return m_hasQuirk;
     283}
     284
     285inline void Length::setHasQuirk(bool hasQuirk)
     286{
     287    m_hasQuirk = hasQuirk;
     288}
     289
     290inline void Length::setValue(LengthType type, int value)
     291{
     292    ASSERT(m_type != Calculated);
     293    ASSERT(type != Calculated);
     294    m_type = type;
     295    m_intValue = value;
     296    m_isFloat = false;
     297}
     298
     299inline void Length::setValue(LengthType type, float value)
     300{
     301    ASSERT(m_type != Calculated);
     302    ASSERT(type != Calculated);
     303    m_type = type;
     304    m_floatValue = value;
     305    m_isFloat = true;
     306}
     307
     308inline void Length::setValue(LengthType type, LayoutUnit value)
     309{
     310    ASSERT(m_type != Calculated);
     311    ASSERT(type != Calculated);
     312    m_type = type;
     313    m_floatValue = value;
     314    m_isFloat = true;
     315}
     316
     317inline bool Length::isAuto() const
     318{
     319    return type() == Auto;
     320}
     321
     322inline bool Length::isFixed() const
     323{
     324    return type() == Fixed;
     325}
     326
     327inline bool Length::isMaxContent() const
     328{
     329    return type() == MaxContent;
     330}
     331
     332inline bool Length::isMinContent() const
     333{
     334    return type() == MinContent;
     335}
     336
     337inline bool Length::isNegative() const
     338{
     339    if (isUndefined() || isCalculated())
     340        return false;
     341    return m_isFloat ? (m_floatValue < 0) : (m_intValue < 0);
     342}
     343
     344inline bool Length::isRelative() const
     345{
     346    return type() == Relative;
     347}
     348
     349inline bool Length::isUndefined() const
     350{
     351    return type() == Undefined;
     352}
     353
     354inline bool Length::isPercent() const
     355{
     356    return type() == Percent || isCalculated();
     357}
     358
     359inline bool Length::isPositive() const
     360{
     361    if (isUndefined())
     362        return false;
     363    if (isCalculated())
     364        return true;
     365    return m_isFloat ? (m_floatValue > 0) : (m_intValue > 0);
     366}
     367
     368inline bool Length::isZero() const
     369{
     370    ASSERT(!isUndefined());
     371    if (isCalculated())
     372        return false;
     373    return m_isFloat ? !m_floatValue : !m_intValue;
     374}
     375
     376inline bool Length::isCalculated() const
     377{
     378    return type() == Calculated;
     379}
     380
     381inline bool Length::isLegacyIntrinsic() const
     382{
     383    return type() == Intrinsic || type() == MinIntrinsic;
     384}
     385
     386inline bool Length::isIntrinsic() const
     387{
     388    return type() == MinContent || type() == MaxContent || type() == FillAvailable || type() == FitContent;
     389}
     390
     391inline bool Length::isIntrinsicOrAuto() const
     392{
     393    return isAuto() || isIntrinsic() || isLegacyIntrinsic();
     394}
     395
     396inline bool Length::isSpecified() const
     397{
     398    return isFixed() || type() == Percent || isCalculated() || isViewportPercentage();
     399}
     400
     401inline bool Length::isSpecifiedOrIntrinsic() const
     402{
     403    return isSpecified() || isIntrinsic();
     404}
     405
     406inline bool Length::isViewportPercentage() const
     407{
     408    return type() >= ViewportPercentageWidth && type() <= ViewportPercentageMax;
     409}
     410
     411// FIXME: Does this need to be in the header? Is it valuable to inline? Does it get inlined?
     412inline Length Length::blend(const Length& from, double progress) const
     413{
     414    if (from.type() == Calculated || type() == Calculated)
     415        return blendMixedTypes(from, progress);
     416
     417    if (!from.isZero() && !isZero() && from.type() != type())
     418        return blendMixedTypes(from, progress);
     419
     420    if (from.isZero() && isZero())
     421        return *this;
     422
     423    LengthType resultType = type();
     424    if (isZero())
     425        resultType = from.type();
     426
     427    if (resultType == Percent) {
     428        float fromPercent = from.isZero() ? 0 : from.percent();
     429        float toPercent = isZero() ? 0 : percent();
     430        return Length(WebCore::blend(fromPercent, toPercent, progress), Percent);
     431    }
     432
     433    float fromValue = from.isZero() ? 0 : from.value();
     434    float toValue = isZero() ? 0 : value();
     435    return Length(WebCore::blend(fromValue, toValue, progress), resultType);
     436}
    330437
    331438} // namespace WebCore
  • trunk/Source/WebCore/platform/LengthBox.h

    r156132 r166860  
    2929namespace WebCore {
    3030
    31 class RenderStyle;
    32 
    3331struct LengthBox {
    3432    LengthBox()
     
    3634    }
    3735
    38     LengthBox(LengthType t)
    39         : m_left(t)
    40         , m_right(t)
    41         , m_top(t)
    42         , m_bottom(t)
     36    explicit LengthBox(LengthType type)
     37        : m_left(type)
     38        , m_right(type)
     39        , m_top(type)
     40        , m_bottom(type)
    4341    {
    4442    }
    4543
    46     LengthBox(int v)
     44    explicit LengthBox(int v)
    4745        : m_left(Length(v, Fixed))
    4846        , m_right(Length(v, Fixed))
     
    5250    }
    5351
    54     LengthBox(Length t, Length r, Length b, Length l)
    55         : m_left(std::move(l))
    56         , m_right(std::move(r))
    57         , m_top(std::move(t))
    58         , m_bottom(std::move(b))
     52    LengthBox(Length top, Length right, Length bottom, Length left)
     53        : m_left(std::move(left))
     54        , m_right(std::move(right))
     55        , m_top(std::move(top))
     56        , m_bottom(std::move(bottom))
    5957    {
    6058    }
    61    
    62     LengthBox(int t, int r, int b, int l)
    63         : m_left(Length(l, Fixed))
    64         , m_right(Length(r, Fixed))
    65         , m_top(Length(t, Fixed))
    66         , m_bottom(Length(b, Fixed))
     59
     60    LengthBox(int top, int right, int bottom, int left)
     61        : m_left(Length(left, Fixed))
     62        , m_right(Length(right, Fixed))
     63        , m_top(Length(top, Fixed))
     64        , m_bottom(Length(bottom, Fixed))
    6765    {
    6866    }
     
    8179    const Length& end(WritingMode, TextDirection) const;
    8280
    83     bool operator==(const LengthBox& o) const
     81    bool operator==(const LengthBox& other) const
    8482    {
    85         return m_left == o.m_left && m_right == o.m_right && m_top == o.m_top && m_bottom == o.m_bottom;
     83        return m_left == other.m_left && m_right == other.m_right && m_top == other.m_top && m_bottom == other.m_bottom;
    8684    }
    8785
    88     bool operator!=(const LengthBox& o) const
     86    bool operator!=(const LengthBox& other) const
    8987    {
    90         return !(*this == o);
     88        return !(*this == other);
    9189    }
    9290
  • trunk/Source/WebCore/rendering/AutoTableLayout.cpp

    r162907 r166860  
    8686                    Length cellLogicalWidth = cell->styleOrColLogicalWidth();
    8787                    if (cellLogicalWidth.value() > cCellMaxWidth)
    88                         cellLogicalWidth.setValue(cCellMaxWidth);
     88                        cellLogicalWidth.setValue(Fixed, cCellMaxWidth);
    8989                    if (cellLogicalWidth.isNegative())
    90                         cellLogicalWidth.setValue(0);
     90                        cellLogicalWidth.setValue(Fixed, 0);
    9191                    switch (cellLogicalWidth.type()) {
    9292                    case Fixed:
  • trunk/Source/WebCore/rendering/FixedTableLayout.cpp

    r159027 r166860  
    144144        if (logicalWidth.isFixed() && logicalWidth.isPositive()) {
    145145            fixedBorderBoxLogicalWidth = cell->adjustBorderBoxLogicalWidthForBoxSizing(logicalWidth.value());
    146             logicalWidth.setValue(fixedBorderBoxLogicalWidth);
     146            logicalWidth.setValue(Fixed, fixedBorderBoxLogicalWidth);
    147147        }
    148148
  • trunk/Source/WebCore/rendering/style/FillLayer.h

    r156622 r166860  
    188188    static LengthSize initialFillSizeLength(EFillLayerType) { return LengthSize(); }
    189189    static FillSize initialFillSize(EFillLayerType type) { return FillSize(initialFillSizeType(type), initialFillSizeLength(type)); }
    190     static Length initialFillXPosition(EFillLayerType) { return Length(0.0, Percent); }
    191     static Length initialFillYPosition(EFillLayerType) { return Length(0.0, Percent); }
     190    static Length initialFillXPosition(EFillLayerType) { return Length(0.0f, Percent); }
     191    static Length initialFillYPosition(EFillLayerType) { return Length(0.0f, Percent); }
    192192    static StyleImage* initialFillImage(EFillLayerType) { return 0; }
    193193    static EMaskSourceType initialMaskSourceType(EFillLayerType) { return MaskAlpha; }
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r166618 r166860  
    13491349}
    13501350
    1351 void RenderStyle::setWordSpacing(Length v)
     1351void RenderStyle::setWordSpacing(Length value)
    13521352{
    13531353    float fontWordSpacing;
    1354     switch (v.type()) {
     1354    switch (value.type()) {
    13551355    case Auto:
    13561356        fontWordSpacing = 0;
    1357         FALLTHROUGH;
     1357        break;
    13581358    case Percent:
    1359         fontWordSpacing = v.getFloatValue() * font().spaceWidth() / 100;
     1359        fontWordSpacing = value.percent() * font().spaceWidth() / 100;
    13601360        break;
    13611361    case Fixed:
    1362         fontWordSpacing = v.getFloatValue();
     1362        fontWordSpacing = value.value();
    13631363        break;
    13641364    default:
     
    13681368    }
    13691369    inherited.access()->font.setWordSpacing(fontWordSpacing);
    1370     rareInheritedData.access()->wordSpacing = std::move(v);
     1370    rareInheritedData.access()->wordSpacing = std::move(value);
    13711371}
    13721372
  • trunk/Source/WebCore/rendering/style/RenderStyle.h

    r166696 r166860  
    523523    bool hasPadding() const { return surround->padding.nonZero(); }
    524524    bool hasOffset() const { return surround->offset.nonZero(); }
    525     bool hasMarginBeforeQuirk() const { return marginBefore().quirk(); }
    526     bool hasMarginAfterQuirk() const { return marginAfter().quirk(); }
     525    bool hasMarginBeforeQuirk() const { return marginBefore().hasQuirk(); }
     526    bool hasMarginAfterQuirk() const { return marginAfter().hasQuirk(); }
    527527
    528528    bool hasBackgroundImage() const { return m_background->background().hasImage(); }
     
    17761776    static short initialWidows() { return 2; }
    17771777    static short initialOrphans() { return 2; }
    1778     static Length initialLineHeight() { return Length(-100.0, Percent); }
     1778    static Length initialLineHeight() { return Length(-100.0f, Percent); }
    17791779#if ENABLE(IOS_TEXT_AUTOSIZING)
    1780     static Length initialSpecifiedLineHeight() { return Length(-100, Percent); }
     1780    static Length initialSpecifiedLineHeight() { return Length(-100.0f, Percent); }
    17811781#endif
    17821782    static ETextAlign initialTextAlign() { return TASTART; }
     
    18471847    static ColumnSpan initialColumnSpan() { return ColumnSpanNone; }
    18481848    static const TransformOperations& initialTransform() { DEPRECATED_DEFINE_STATIC_LOCAL(TransformOperations, ops, ()); return ops; }
    1849     static Length initialTransformOriginX() { return Length(50.0, Percent); }
    1850     static Length initialTransformOriginY() { return Length(50.0, Percent); }
     1849    static Length initialTransformOriginX() { return Length(50.0f, Percent); }
     1850    static Length initialTransformOriginY() { return Length(50.0f, Percent); }
    18511851    static EPointerEvents initialPointerEvents() { return PE_AUTO; }
    18521852    static float initialTransformOriginZ() { return 0; }
     
    18541854    static EBackfaceVisibility initialBackfaceVisibility() { return BackfaceVisibilityVisible; }
    18551855    static float initialPerspective() { return 0; }
    1856     static Length initialPerspectiveOriginX() { return Length(50.0, Percent); }
    1857     static Length initialPerspectiveOriginY() { return Length(50.0, Percent); }
     1856    static Length initialPerspectiveOriginX() { return Length(50.0f, Percent); }
     1857    static Length initialPerspectiveOriginY() { return Length(50.0f, Percent); }
    18581858    static Color initialBackgroundColor() { return Color::transparent; }
    18591859    static Color initialTextEmphasisColor() { return TextEmphasisFillFilled; }
  • trunk/Tools/ChangeLog

    r166851 r166860  
     12014-04-06  Darin Adler  <darin@apple.com>
     2
     3        Rework CSS calc logic, fixing some reference count mistakes in Length
     4        https://bugs.webkit.org/show_bug.cgi?id=131280
     5
     6        Reviewed by Andreas Kling.
     7
     8        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Added CalculationValue.cpp.
     9        * TestWebKitAPI/Tests/WebCore/CalculationValue.cpp: Added.
     10
    1112014-04-04  Brian J. Burg  <burg@cs.washington.edu>
    212
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r166661 r166860  
    129129                93A427A9180D9B0700CD24D7 /* RefPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93A427A8180D9B0700CD24D7 /* RefPtr.cpp */; };
    130130                93A427AB180DA26400CD24D7 /* Ref.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93A427AA180DA26400CD24D7 /* Ref.cpp */; };
     131                93A720E618F1A0E800A848E1 /* CalculationValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93A720E518F1A0E800A848E1 /* CalculationValue.cpp */; };
    131132                93ABA80916DDAB91002DB2FA /* StringHasher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93ABA80816DDAB91002DB2FA /* StringHasher.cpp */; };
    132133                93AF4ECE1506F064007FD57E /* NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93AF4ECD1506F064007FD57E /* NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp */; };
     
    459460                93A427AC180DA60F00CD24D7 /* MoveOnly.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoveOnly.h; sourceTree = "<group>"; };
    460461                93A427AD180DA60F00CD24D7 /* RefLogger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RefLogger.h; sourceTree = "<group>"; };
     462                93A720E518F1A0E800A848E1 /* CalculationValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CalculationValue.cpp; sourceTree = "<group>"; };
    461463                93ABA80816DDAB91002DB2FA /* StringHasher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringHasher.cpp; sourceTree = "<group>"; };
    462464                93AF4ECA1506F035007FD57E /* NewFirstVisuallyNonEmptyLayoutForImages.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutForImages.cpp; sourceTree = "<group>"; };
     
    697699                        isa = PBXGroup;
    698700                        children = (
     701                                93A720E518F1A0E800A848E1 /* CalculationValue.cpp */,
    699702                                CDC2C7141797089D00E627FB /* TimeRanges.cpp */,
    700703                                440A1D3814A0103A008A66F2 /* URL.cpp */,
     
    12561259                                C0BD669D131D3CF700E18F2A /* ResponsivenessTimerDoesntFireEarly.cpp in Sources */,
    12571260                                C0ADBE8312FCA6AA00D2C129 /* RestoreSessionStateContainingFormData.cpp in Sources */,
     1261                                93A720E618F1A0E800A848E1 /* CalculationValue.cpp in Sources */,
    12581262                                1AEF994917A09F5400998EF0 /* GetPIDAfterAbortedProcessLaunch.cpp in Sources */,
    12591263                                BC029B181486AD6400817DA9 /* RetainPtr.cpp in Sources */,
Note: See TracChangeset for help on using the changeset viewer.