mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This caused us to lose our gn check certification. :( Turns out gn check was just ignoring all the header paths it didn't understand and so gn check passing for sky wasn't meaning much. I tried to straighten out some of the mess in this CL, but its going to take several more rounds of massaging before gn check passes again. On the bright side (almost) all of our headers are absolute now. Turns out my script (attached to the bug) didn't notice ../ includes but I'll fix that in the next patch. R=abarth@chromium.org BUG=435361 Review URL: https://codereview.chromium.org/746023002
1331 lines
41 KiB
C++
1331 lines
41 KiB
C++
/*
|
|
* (C) 1999-2003 Lars Knoll (knoll@kde.org)
|
|
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012 Apple Inc. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "sky/engine/config.h"
|
|
#include "sky/engine/core/css/CSSPrimitiveValue.h"
|
|
|
|
#include "sky/engine/bindings/core/v8/ExceptionState.h"
|
|
#include "sky/engine/core/css/CSSBasicShapes.h"
|
|
#include "sky/engine/core/css/CSSCalculationValue.h"
|
|
#include "sky/engine/core/css/CSSHelper.h"
|
|
#include "sky/engine/core/css/CSSMarkup.h"
|
|
#include "sky/engine/core/css/CSSToLengthConversionData.h"
|
|
#include "sky/engine/core/css/Pair.h"
|
|
#include "sky/engine/core/css/RGBColor.h"
|
|
#include "sky/engine/core/css/Rect.h"
|
|
#include "sky/engine/core/css/StyleSheetContents.h"
|
|
#include "sky/engine/core/dom/ExceptionCode.h"
|
|
#include "sky/engine/core/dom/Node.h"
|
|
#include "sky/engine/core/rendering/style/RenderStyle.h"
|
|
#include "sky/engine/platform/Decimal.h"
|
|
#include "sky/engine/platform/LayoutUnit.h"
|
|
#include "sky/engine/platform/fonts/FontMetrics.h"
|
|
#include "sky/engine/wtf/StdLibExtras.h"
|
|
#include "sky/engine/wtf/text/StringBuffer.h"
|
|
#include "sky/engine/wtf/text/StringBuilder.h"
|
|
|
|
using namespace WTF;
|
|
|
|
namespace blink {
|
|
|
|
// Max/min values for CSS, needs to slightly smaller/larger than the true max/min values to allow for rounding without overflowing.
|
|
// Subtract two (rather than one) to allow for values to be converted to float and back without exceeding the LayoutUnit::max.
|
|
const int maxValueForCssLength = INT_MAX / kFixedPointDenominator - 2;
|
|
const int minValueForCssLength = INT_MIN / kFixedPointDenominator + 2;
|
|
|
|
static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::UnitType unitType)
|
|
{
|
|
switch (unitType) {
|
|
case CSSPrimitiveValue::CSS_CALC:
|
|
case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER:
|
|
case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH:
|
|
case CSSPrimitiveValue::CSS_CM:
|
|
case CSSPrimitiveValue::CSS_DEG:
|
|
case CSSPrimitiveValue::CSS_DIMENSION:
|
|
case CSSPrimitiveValue::CSS_DPPX:
|
|
case CSSPrimitiveValue::CSS_DPI:
|
|
case CSSPrimitiveValue::CSS_DPCM:
|
|
case CSSPrimitiveValue::CSS_EMS:
|
|
case CSSPrimitiveValue::CSS_EXS:
|
|
case CSSPrimitiveValue::CSS_GRAD:
|
|
case CSSPrimitiveValue::CSS_HZ:
|
|
case CSSPrimitiveValue::CSS_IN:
|
|
case CSSPrimitiveValue::CSS_KHZ:
|
|
case CSSPrimitiveValue::CSS_MM:
|
|
case CSSPrimitiveValue::CSS_MS:
|
|
case CSSPrimitiveValue::CSS_NUMBER:
|
|
case CSSPrimitiveValue::CSS_PERCENTAGE:
|
|
case CSSPrimitiveValue::CSS_PC:
|
|
case CSSPrimitiveValue::CSS_PT:
|
|
case CSSPrimitiveValue::CSS_PX:
|
|
case CSSPrimitiveValue::CSS_RAD:
|
|
case CSSPrimitiveValue::CSS_REMS:
|
|
case CSSPrimitiveValue::CSS_CHS:
|
|
case CSSPrimitiveValue::CSS_S:
|
|
case CSSPrimitiveValue::CSS_TURN:
|
|
case CSSPrimitiveValue::CSS_VW:
|
|
case CSSPrimitiveValue::CSS_VH:
|
|
case CSSPrimitiveValue::CSS_VMIN:
|
|
case CSSPrimitiveValue::CSS_VMAX:
|
|
case CSSPrimitiveValue::CSS_FR:
|
|
return true;
|
|
case CSSPrimitiveValue::CSS_ATTR:
|
|
case CSSPrimitiveValue::CSS_IDENT:
|
|
case CSSPrimitiveValue::CSS_PROPERTY_ID:
|
|
case CSSPrimitiveValue::CSS_VALUE_ID:
|
|
case CSSPrimitiveValue::CSS_PAIR:
|
|
case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR:
|
|
case CSSPrimitiveValue::CSS_RECT:
|
|
case CSSPrimitiveValue::CSS_QUAD:
|
|
case CSSPrimitiveValue::CSS_RGBCOLOR:
|
|
case CSSPrimitiveValue::CSS_SHAPE:
|
|
case CSSPrimitiveValue::CSS_STRING:
|
|
case CSSPrimitiveValue::CSS_UNICODE_RANGE:
|
|
case CSSPrimitiveValue::CSS_UNKNOWN:
|
|
case CSSPrimitiveValue::CSS_URI:
|
|
return false;
|
|
}
|
|
|
|
ASSERT_NOT_REACHED();
|
|
return false;
|
|
}
|
|
|
|
typedef HashMap<String, CSSPrimitiveValue::UnitType> StringToUnitTable;
|
|
|
|
StringToUnitTable createStringToUnitTable()
|
|
{
|
|
StringToUnitTable table;
|
|
table.set(String("em"), CSSPrimitiveValue::CSS_EMS);
|
|
table.set(String("ex"), CSSPrimitiveValue::CSS_EXS);
|
|
table.set(String("px"), CSSPrimitiveValue::CSS_PX);
|
|
table.set(String("cm"), CSSPrimitiveValue::CSS_CM);
|
|
table.set(String("mm"), CSSPrimitiveValue::CSS_MM);
|
|
table.set(String("in"), CSSPrimitiveValue::CSS_IN);
|
|
table.set(String("pt"), CSSPrimitiveValue::CSS_PT);
|
|
table.set(String("pc"), CSSPrimitiveValue::CSS_PC);
|
|
table.set(String("deg"), CSSPrimitiveValue::CSS_DEG);
|
|
table.set(String("rad"), CSSPrimitiveValue::CSS_RAD);
|
|
table.set(String("grad"), CSSPrimitiveValue::CSS_GRAD);
|
|
table.set(String("ms"), CSSPrimitiveValue::CSS_MS);
|
|
table.set(String("s"), CSSPrimitiveValue::CSS_S);
|
|
table.set(String("hz"), CSSPrimitiveValue::CSS_HZ);
|
|
table.set(String("khz"), CSSPrimitiveValue::CSS_KHZ);
|
|
table.set(String("dpi"), CSSPrimitiveValue::CSS_DPI);
|
|
table.set(String("dpcm"), CSSPrimitiveValue::CSS_DPCM);
|
|
table.set(String("dppx"), CSSPrimitiveValue::CSS_DPPX);
|
|
table.set(String("vw"), CSSPrimitiveValue::CSS_VW);
|
|
table.set(String("vh"), CSSPrimitiveValue::CSS_VH);
|
|
table.set(String("vmax"), CSSPrimitiveValue::CSS_VMIN);
|
|
table.set(String("vmin"), CSSPrimitiveValue::CSS_VMAX);
|
|
table.set(String("rem"), CSSPrimitiveValue::CSS_REMS);
|
|
table.set(String("fr"), CSSPrimitiveValue::CSS_FR);
|
|
table.set(String("turn"), CSSPrimitiveValue::CSS_TURN);
|
|
table.set(String("ch"), CSSPrimitiveValue::CSS_CHS);
|
|
return table;
|
|
}
|
|
|
|
CSSPrimitiveValue::UnitType CSSPrimitiveValue::fromName(const String& unit)
|
|
{
|
|
DEFINE_STATIC_LOCAL(StringToUnitTable, unitTable, (createStringToUnitTable()));
|
|
return unitTable.get(unit.lower());
|
|
}
|
|
|
|
CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::unitCategory(UnitType type)
|
|
{
|
|
// Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions
|
|
// between CSS_PX and relative lengths (see cssPixelsPerInch comment in core/css/CSSHelper.h for the topic treatment).
|
|
switch (type) {
|
|
case CSS_NUMBER:
|
|
return CSSPrimitiveValue::UNumber;
|
|
case CSS_PERCENTAGE:
|
|
return CSSPrimitiveValue::UPercent;
|
|
case CSS_PX:
|
|
case CSS_CM:
|
|
case CSS_MM:
|
|
case CSS_IN:
|
|
case CSS_PT:
|
|
case CSS_PC:
|
|
return CSSPrimitiveValue::ULength;
|
|
case CSS_MS:
|
|
case CSS_S:
|
|
return CSSPrimitiveValue::UTime;
|
|
case CSS_DEG:
|
|
case CSS_RAD:
|
|
case CSS_GRAD:
|
|
case CSS_TURN:
|
|
return CSSPrimitiveValue::UAngle;
|
|
case CSS_HZ:
|
|
case CSS_KHZ:
|
|
return CSSPrimitiveValue::UFrequency;
|
|
case CSS_DPPX:
|
|
case CSS_DPI:
|
|
case CSS_DPCM:
|
|
return CSSPrimitiveValue::UResolution;
|
|
default:
|
|
return CSSPrimitiveValue::UOther;
|
|
}
|
|
}
|
|
|
|
bool CSSPrimitiveValue::colorIsDerivedFromElement() const
|
|
{
|
|
return getValueID() == CSSValueCurrentcolor;
|
|
}
|
|
|
|
typedef HashMap<const CSSPrimitiveValue*, String> CSSTextCache;
|
|
static CSSTextCache& cssTextCache()
|
|
{
|
|
DEFINE_STATIC_LOCAL(CSSTextCache, cache, ());
|
|
return cache;
|
|
}
|
|
|
|
CSSPrimitiveValue::UnitType CSSPrimitiveValue::primitiveType() const
|
|
{
|
|
if (m_primitiveUnitType == CSS_PROPERTY_ID || m_primitiveUnitType == CSS_VALUE_ID)
|
|
return CSS_IDENT;
|
|
|
|
if (m_primitiveUnitType != CSS_CALC)
|
|
return static_cast<UnitType>(m_primitiveUnitType);
|
|
|
|
switch (m_value.calc->category()) {
|
|
case CalcAngle:
|
|
return CSS_DEG;
|
|
case CalcFrequency:
|
|
return CSS_HZ;
|
|
case CalcNumber:
|
|
return CSS_NUMBER;
|
|
case CalcPercent:
|
|
return CSS_PERCENTAGE;
|
|
case CalcLength:
|
|
return CSS_PX;
|
|
case CalcPercentNumber:
|
|
return CSS_CALC_PERCENTAGE_WITH_NUMBER;
|
|
case CalcPercentLength:
|
|
return CSS_CALC_PERCENTAGE_WITH_LENGTH;
|
|
case CalcTime:
|
|
return CSS_MS;
|
|
case CalcOther:
|
|
return CSS_UNKNOWN;
|
|
}
|
|
return CSS_UNKNOWN;
|
|
}
|
|
|
|
static const AtomicString& propertyName(CSSPropertyID propertyID)
|
|
{
|
|
ASSERT_ARG(propertyID, propertyID >= 0);
|
|
ASSERT_ARG(propertyID, (propertyID >= firstCSSProperty && propertyID < firstCSSProperty + numCSSProperties));
|
|
|
|
if (propertyID < 0)
|
|
return nullAtom;
|
|
|
|
return getPropertyNameAtomicString(propertyID);
|
|
}
|
|
|
|
static const AtomicString& valueName(CSSValueID valueID)
|
|
{
|
|
ASSERT_ARG(valueID, valueID >= 0);
|
|
ASSERT_ARG(valueID, valueID < numCSSValueKeywords);
|
|
|
|
if (valueID < 0)
|
|
return nullAtom;
|
|
|
|
static AtomicString* keywordStrings = new AtomicString[numCSSValueKeywords]; // Leaked intentionally.
|
|
AtomicString& keywordString = keywordStrings[valueID];
|
|
if (keywordString.isNull())
|
|
keywordString = getValueName(valueID);
|
|
return keywordString;
|
|
}
|
|
|
|
CSSPrimitiveValue::CSSPrimitiveValue(CSSValueID valueID)
|
|
: CSSValue(PrimitiveClass)
|
|
{
|
|
m_primitiveUnitType = CSS_VALUE_ID;
|
|
m_value.valueID = valueID;
|
|
}
|
|
|
|
CSSPrimitiveValue::CSSPrimitiveValue(CSSPropertyID propertyID)
|
|
: CSSValue(PrimitiveClass)
|
|
{
|
|
m_primitiveUnitType = CSS_PROPERTY_ID;
|
|
m_value.propertyID = propertyID;
|
|
}
|
|
|
|
CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitType type)
|
|
: CSSValue(PrimitiveClass)
|
|
{
|
|
m_primitiveUnitType = type;
|
|
ASSERT(std::isfinite(num));
|
|
m_value.num = num;
|
|
}
|
|
|
|
CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitType type)
|
|
: CSSValue(PrimitiveClass)
|
|
{
|
|
m_primitiveUnitType = type;
|
|
m_value.string = str.impl();
|
|
if (m_value.string)
|
|
m_value.string->ref();
|
|
}
|
|
|
|
CSSPrimitiveValue::CSSPrimitiveValue(const LengthSize& lengthSize, const RenderStyle& style)
|
|
: CSSValue(PrimitiveClass)
|
|
{
|
|
init(lengthSize, style);
|
|
}
|
|
|
|
CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color, UnitType type)
|
|
: CSSValue(PrimitiveClass)
|
|
{
|
|
ASSERT(type == CSS_RGBCOLOR);
|
|
m_primitiveUnitType = CSS_RGBCOLOR;
|
|
m_value.rgbcolor = color;
|
|
}
|
|
|
|
CSSPrimitiveValue::CSSPrimitiveValue(const Length& length)
|
|
: CSSValue(PrimitiveClass)
|
|
{
|
|
switch (length.type()) {
|
|
case Auto:
|
|
m_primitiveUnitType = CSS_VALUE_ID;
|
|
m_value.valueID = CSSValueAuto;
|
|
break;
|
|
case Intrinsic:
|
|
m_primitiveUnitType = CSS_VALUE_ID;
|
|
m_value.valueID = CSSValueIntrinsic;
|
|
break;
|
|
case MinIntrinsic:
|
|
m_primitiveUnitType = CSS_VALUE_ID;
|
|
m_value.valueID = CSSValueMinIntrinsic;
|
|
break;
|
|
case MinContent:
|
|
m_primitiveUnitType = CSS_VALUE_ID;
|
|
m_value.valueID = CSSValueMinContent;
|
|
break;
|
|
case MaxContent:
|
|
m_primitiveUnitType = CSS_VALUE_ID;
|
|
m_value.valueID = CSSValueMaxContent;
|
|
break;
|
|
case FillAvailable:
|
|
m_primitiveUnitType = CSS_VALUE_ID;
|
|
m_value.valueID = CSSValueWebkitFillAvailable;
|
|
break;
|
|
case FitContent:
|
|
m_primitiveUnitType = CSS_VALUE_ID;
|
|
m_value.valueID = CSSValueWebkitFitContent;
|
|
break;
|
|
case Percent:
|
|
m_primitiveUnitType = CSS_PERCENTAGE;
|
|
ASSERT(std::isfinite(length.percent()));
|
|
m_value.num = length.percent();
|
|
break;
|
|
case Fixed:
|
|
m_primitiveUnitType = CSS_PX;
|
|
m_value.num = length.value();
|
|
break;
|
|
case Calculated: {
|
|
const CalculationValue& calc = length.calculationValue();
|
|
if (calc.pixels() && calc.percent()) {
|
|
init(CSSCalcValue::create(
|
|
CSSCalcValue::createExpressionNode(calc.pixels(), calc.percent()),
|
|
calc.isNonNegative() ? ValueRangeNonNegative : ValueRangeAll));
|
|
break;
|
|
}
|
|
if (calc.percent()) {
|
|
m_primitiveUnitType = CSS_PERCENTAGE;
|
|
m_value.num = calc.percent();
|
|
} else {
|
|
m_primitiveUnitType = CSS_PX;
|
|
m_value.num = calc.pixels();
|
|
}
|
|
if (m_value.num < 0 && calc.isNonNegative())
|
|
m_value.num = 0;
|
|
break;
|
|
}
|
|
case DeviceWidth:
|
|
case DeviceHeight:
|
|
case MaxSizeNone:
|
|
ASSERT_NOT_REACHED();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CSSPrimitiveValue::init(const LengthSize& lengthSize, const RenderStyle& style)
|
|
{
|
|
m_primitiveUnitType = CSS_PAIR;
|
|
m_hasCachedCSSText = false;
|
|
m_value.pair = Pair::create(create(lengthSize.width()), create(lengthSize.height()), Pair::KeepIdenticalValues).leakRef();
|
|
}
|
|
|
|
void CSSPrimitiveValue::init(PassRefPtr<Rect> r)
|
|
{
|
|
m_primitiveUnitType = CSS_RECT;
|
|
m_hasCachedCSSText = false;
|
|
m_value.rect = r.leakRef();
|
|
}
|
|
|
|
void CSSPrimitiveValue::init(PassRefPtr<Quad> quad)
|
|
{
|
|
m_primitiveUnitType = CSS_QUAD;
|
|
m_hasCachedCSSText = false;
|
|
m_value.quad = quad.leakRef();
|
|
}
|
|
|
|
void CSSPrimitiveValue::init(PassRefPtr<Pair> p)
|
|
{
|
|
m_primitiveUnitType = CSS_PAIR;
|
|
m_hasCachedCSSText = false;
|
|
m_value.pair = p.leakRef();
|
|
}
|
|
|
|
void CSSPrimitiveValue::init(PassRefPtr<CSSCalcValue> c)
|
|
{
|
|
m_primitiveUnitType = CSS_CALC;
|
|
m_hasCachedCSSText = false;
|
|
m_value.calc = c.leakRef();
|
|
}
|
|
|
|
void CSSPrimitiveValue::init(PassRefPtr<CSSBasicShape> shape)
|
|
{
|
|
m_primitiveUnitType = CSS_SHAPE;
|
|
m_hasCachedCSSText = false;
|
|
m_value.shape = shape.leakRef();
|
|
}
|
|
|
|
CSSPrimitiveValue::~CSSPrimitiveValue()
|
|
{
|
|
cleanup();
|
|
}
|
|
|
|
void CSSPrimitiveValue::cleanup()
|
|
{
|
|
switch (static_cast<UnitType>(m_primitiveUnitType)) {
|
|
case CSS_STRING:
|
|
case CSS_URI:
|
|
case CSS_ATTR:
|
|
case CSS_PARSER_HEXCOLOR:
|
|
if (m_value.string)
|
|
m_value.string->deref();
|
|
break;
|
|
case CSS_RECT:
|
|
// We must not call deref() when oilpan is enabled because m_value.rect is traced.
|
|
#if !ENABLE(OILPAN)
|
|
m_value.rect->deref();
|
|
#endif
|
|
break;
|
|
case CSS_QUAD:
|
|
// We must not call deref() when oilpan is enabled because m_value.quad is traced.
|
|
#if !ENABLE(OILPAN)
|
|
m_value.quad->deref();
|
|
#endif
|
|
break;
|
|
case CSS_PAIR:
|
|
// We must not call deref() when oilpan is enabled because m_value.pair is traced.
|
|
#if !ENABLE(OILPAN)
|
|
m_value.pair->deref();
|
|
#endif
|
|
break;
|
|
case CSS_CALC:
|
|
// We must not call deref() when oilpan is enabled because m_value.calc is traced.
|
|
#if !ENABLE(OILPAN)
|
|
m_value.calc->deref();
|
|
#endif
|
|
break;
|
|
case CSS_CALC_PERCENTAGE_WITH_NUMBER:
|
|
case CSS_CALC_PERCENTAGE_WITH_LENGTH:
|
|
ASSERT_NOT_REACHED();
|
|
break;
|
|
case CSS_SHAPE:
|
|
// We must not call deref() when oilpan is enabled because m_value.shape is traced.
|
|
#if !ENABLE(OILPAN)
|
|
m_value.shape->deref();
|
|
#endif
|
|
break;
|
|
case CSS_NUMBER:
|
|
case CSS_PERCENTAGE:
|
|
case CSS_EMS:
|
|
case CSS_EXS:
|
|
case CSS_REMS:
|
|
case CSS_CHS:
|
|
case CSS_PX:
|
|
case CSS_CM:
|
|
case CSS_MM:
|
|
case CSS_IN:
|
|
case CSS_PT:
|
|
case CSS_PC:
|
|
case CSS_DEG:
|
|
case CSS_RAD:
|
|
case CSS_GRAD:
|
|
case CSS_MS:
|
|
case CSS_S:
|
|
case CSS_HZ:
|
|
case CSS_KHZ:
|
|
case CSS_TURN:
|
|
case CSS_VW:
|
|
case CSS_VH:
|
|
case CSS_VMIN:
|
|
case CSS_VMAX:
|
|
case CSS_DPPX:
|
|
case CSS_DPI:
|
|
case CSS_DPCM:
|
|
case CSS_FR:
|
|
case CSS_IDENT:
|
|
case CSS_RGBCOLOR:
|
|
case CSS_DIMENSION:
|
|
case CSS_UNKNOWN:
|
|
case CSS_UNICODE_RANGE:
|
|
case CSS_PROPERTY_ID:
|
|
case CSS_VALUE_ID:
|
|
break;
|
|
}
|
|
m_primitiveUnitType = 0;
|
|
if (m_hasCachedCSSText) {
|
|
cssTextCache().remove(this);
|
|
m_hasCachedCSSText = false;
|
|
}
|
|
}
|
|
|
|
double CSSPrimitiveValue::computeSeconds()
|
|
{
|
|
ASSERT(isTime() || (isCalculated() && cssCalcValue()->category() == CalcTime));
|
|
UnitType currentType = isCalculated() ? cssCalcValue()->expressionNode()->primitiveType() : static_cast<UnitType>(m_primitiveUnitType);
|
|
if (currentType == CSS_S)
|
|
return getDoubleValue();
|
|
if (currentType == CSS_MS)
|
|
return getDoubleValue() / 1000;
|
|
ASSERT_NOT_REACHED();
|
|
return 0;
|
|
}
|
|
|
|
double CSSPrimitiveValue::computeDegrees()
|
|
{
|
|
ASSERT(isAngle() || (isCalculated() && cssCalcValue()->category() == CalcAngle));
|
|
UnitType currentType = isCalculated() ? cssCalcValue()->expressionNode()->primitiveType() : static_cast<UnitType>(m_primitiveUnitType);
|
|
switch (currentType) {
|
|
case CSS_DEG:
|
|
return getDoubleValue();
|
|
case CSS_RAD:
|
|
return rad2deg(getDoubleValue());
|
|
case CSS_GRAD:
|
|
return grad2deg(getDoubleValue());
|
|
case CSS_TURN:
|
|
return turn2deg(getDoubleValue());
|
|
default:
|
|
ASSERT_NOT_REACHED();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
template<> int CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
|
|
{
|
|
return roundForImpreciseConversion<int>(computeLengthDouble(conversionData));
|
|
}
|
|
|
|
template<> unsigned CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
|
|
{
|
|
return roundForImpreciseConversion<unsigned>(computeLengthDouble(conversionData));
|
|
}
|
|
|
|
template<> Length CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
|
|
{
|
|
return Length(clampTo<float>(computeLengthDouble(conversionData), minValueForCssLength, maxValueForCssLength), Fixed);
|
|
}
|
|
|
|
template<> short CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
|
|
{
|
|
return roundForImpreciseConversion<short>(computeLengthDouble(conversionData));
|
|
}
|
|
|
|
template<> unsigned short CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
|
|
{
|
|
return roundForImpreciseConversion<unsigned short>(computeLengthDouble(conversionData));
|
|
}
|
|
|
|
template<> float CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
|
|
{
|
|
return static_cast<float>(computeLengthDouble(conversionData));
|
|
}
|
|
|
|
template<> double CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
|
|
{
|
|
return computeLengthDouble(conversionData);
|
|
}
|
|
|
|
double CSSPrimitiveValue::computeLengthDouble(const CSSToLengthConversionData& conversionData)
|
|
{
|
|
// The logic in this function is duplicated in MediaValues::computeLength
|
|
// because MediaValues::computeLength needs nearly identical logic, but we haven't found a way to make
|
|
// CSSPrimitiveValue::computeLengthDouble more generic (to solve both cases) without hurting performance.
|
|
if (m_primitiveUnitType == CSS_CALC)
|
|
return m_value.calc->computeLengthPx(conversionData);
|
|
|
|
const RenderStyle& style = conversionData.style();
|
|
const RenderStyle* rootStyle = conversionData.rootStyle();
|
|
bool computingFontSize = conversionData.computingFontSize();
|
|
|
|
double factor;
|
|
|
|
switch (primitiveType()) {
|
|
case CSS_EMS:
|
|
factor = computingFontSize ? style.fontDescription().specifiedSize() : style.fontDescription().computedSize();
|
|
break;
|
|
case CSS_EXS:
|
|
// FIXME: We have a bug right now where the zoom will be applied twice to EX units.
|
|
// We really need to compute EX using fontMetrics for the original specifiedSize and not use
|
|
// our actual constructed rendering font.
|
|
if (style.fontMetrics().hasXHeight())
|
|
factor = style.fontMetrics().xHeight();
|
|
else
|
|
factor = (computingFontSize ? style.fontDescription().specifiedSize() : style.fontDescription().computedSize()) / 2.0;
|
|
break;
|
|
case CSS_REMS:
|
|
if (rootStyle)
|
|
factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize();
|
|
else
|
|
factor = 1.0;
|
|
break;
|
|
case CSS_CHS:
|
|
factor = style.fontMetrics().zeroWidth();
|
|
break;
|
|
case CSS_PX:
|
|
factor = 1.0;
|
|
break;
|
|
case CSS_CM:
|
|
factor = cssPixelsPerCentimeter;
|
|
break;
|
|
case CSS_MM:
|
|
factor = cssPixelsPerMillimeter;
|
|
break;
|
|
case CSS_IN:
|
|
factor = cssPixelsPerInch;
|
|
break;
|
|
case CSS_PT:
|
|
factor = cssPixelsPerPoint;
|
|
break;
|
|
case CSS_PC:
|
|
factor = cssPixelsPerPica;
|
|
break;
|
|
case CSS_VW:
|
|
factor = conversionData.viewportWidthPercent();
|
|
break;
|
|
case CSS_VH:
|
|
factor = conversionData.viewportHeightPercent();
|
|
break;
|
|
case CSS_VMIN:
|
|
factor = conversionData.viewportMinPercent();
|
|
break;
|
|
case CSS_VMAX:
|
|
factor = conversionData.viewportMaxPercent();
|
|
break;
|
|
case CSS_CALC_PERCENTAGE_WITH_LENGTH:
|
|
case CSS_CALC_PERCENTAGE_WITH_NUMBER:
|
|
ASSERT_NOT_REACHED();
|
|
return -1.0;
|
|
default:
|
|
ASSERT_NOT_REACHED();
|
|
return -1.0;
|
|
}
|
|
|
|
// We do not apply the zoom factor when we are computing the value of the font-size property. The zooming
|
|
// for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference
|
|
// as well as enforcing the implicit "smart minimum."
|
|
double result = getDoubleValue() * factor;
|
|
if (computingFontSize || isFontRelativeLength())
|
|
return result;
|
|
|
|
return result;
|
|
}
|
|
|
|
void CSSPrimitiveValue::accumulateLengthArray(CSSLengthArray& lengthArray, double multiplier) const
|
|
{
|
|
ASSERT(lengthArray.size() == LengthUnitTypeCount);
|
|
|
|
if (m_primitiveUnitType == CSS_CALC) {
|
|
cssCalcValue()->accumulateLengthArray(lengthArray, multiplier);
|
|
return;
|
|
}
|
|
|
|
LengthUnitType lengthType;
|
|
if (unitTypeToLengthUnitType(static_cast<UnitType>(m_primitiveUnitType), lengthType))
|
|
lengthArray.at(lengthType) += m_value.num * conversionToCanonicalUnitsScaleFactor(static_cast<UnitType>(m_primitiveUnitType)) * multiplier;
|
|
}
|
|
|
|
void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionState& exceptionState)
|
|
{
|
|
// Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
|
|
// No other engine supports mutating style through this API. Computed style is always read-only anyway.
|
|
// Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
|
|
exceptionState.throwDOMException(NoModificationAllowedError, "CSSPrimitiveValue objects are read-only.");
|
|
}
|
|
|
|
double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(UnitType unitType)
|
|
{
|
|
double factor = 1.0;
|
|
// FIXME: the switch can be replaced by an array of scale factors.
|
|
switch (unitType) {
|
|
// These are "canonical" units in their respective categories.
|
|
case CSS_PX:
|
|
case CSS_DEG:
|
|
case CSS_MS:
|
|
case CSS_HZ:
|
|
break;
|
|
case CSS_CM:
|
|
factor = cssPixelsPerCentimeter;
|
|
break;
|
|
case CSS_DPCM:
|
|
factor = 1 / cssPixelsPerCentimeter;
|
|
break;
|
|
case CSS_MM:
|
|
factor = cssPixelsPerMillimeter;
|
|
break;
|
|
case CSS_IN:
|
|
factor = cssPixelsPerInch;
|
|
break;
|
|
case CSS_DPI:
|
|
factor = 1 / cssPixelsPerInch;
|
|
break;
|
|
case CSS_PT:
|
|
factor = cssPixelsPerPoint;
|
|
break;
|
|
case CSS_PC:
|
|
factor = cssPixelsPerPica;
|
|
break;
|
|
case CSS_RAD:
|
|
factor = 180 / piDouble;
|
|
break;
|
|
case CSS_GRAD:
|
|
factor = 0.9;
|
|
break;
|
|
case CSS_TURN:
|
|
factor = 360;
|
|
break;
|
|
case CSS_S:
|
|
case CSS_KHZ:
|
|
factor = 1000;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return factor;
|
|
}
|
|
|
|
double CSSPrimitiveValue::getDoubleValue(UnitType unitType, ExceptionState& exceptionState) const
|
|
{
|
|
double result = 0;
|
|
bool success = getDoubleValueInternal(unitType, &result);
|
|
if (!success) {
|
|
exceptionState.throwDOMException(InvalidAccessError, "Failed to obtain a double value.");
|
|
return 0.0;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
double CSSPrimitiveValue::getDoubleValue(UnitType unitType) const
|
|
{
|
|
double result = 0;
|
|
getDoubleValueInternal(unitType, &result);
|
|
return result;
|
|
}
|
|
|
|
double CSSPrimitiveValue::getDoubleValue() const
|
|
{
|
|
return m_primitiveUnitType != CSS_CALC ? m_value.num : m_value.calc->doubleValue();
|
|
}
|
|
|
|
CSSPrimitiveValue::UnitType CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category)
|
|
{
|
|
// The canonical unit type is chosen according to the way BisonCSSParser::validUnit() chooses the default unit
|
|
// in each category (based on unitflags).
|
|
switch (category) {
|
|
case UNumber:
|
|
return CSS_NUMBER;
|
|
case ULength:
|
|
return CSS_PX;
|
|
case UPercent:
|
|
return CSS_UNKNOWN; // Cannot convert between numbers and percent.
|
|
case UTime:
|
|
return CSS_MS;
|
|
case UAngle:
|
|
return CSS_DEG;
|
|
case UFrequency:
|
|
return CSS_HZ;
|
|
case UResolution:
|
|
return CSS_DPPX;
|
|
default:
|
|
return CSS_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
bool CSSPrimitiveValue::getDoubleValueInternal(UnitType requestedUnitType, double* result) const
|
|
{
|
|
if (!isValidCSSUnitTypeForDoubleConversion(static_cast<UnitType>(m_primitiveUnitType)) || !isValidCSSUnitTypeForDoubleConversion(requestedUnitType))
|
|
return false;
|
|
|
|
UnitType sourceUnitType = primitiveType();
|
|
if (requestedUnitType == sourceUnitType || requestedUnitType == CSS_DIMENSION) {
|
|
*result = getDoubleValue();
|
|
return true;
|
|
}
|
|
|
|
UnitCategory sourceCategory = unitCategory(sourceUnitType);
|
|
ASSERT(sourceCategory != UOther);
|
|
|
|
UnitType targetUnitType = requestedUnitType;
|
|
UnitCategory targetCategory = unitCategory(targetUnitType);
|
|
ASSERT(targetCategory != UOther);
|
|
|
|
// Cannot convert between unrelated unit categories if one of them is not UNumber.
|
|
if (sourceCategory != targetCategory && sourceCategory != UNumber && targetCategory != UNumber)
|
|
return false;
|
|
|
|
if (targetCategory == UNumber) {
|
|
// We interpret conversion to CSS_NUMBER as conversion to a canonical unit in this value's category.
|
|
targetUnitType = canonicalUnitTypeForCategory(sourceCategory);
|
|
if (targetUnitType == CSS_UNKNOWN)
|
|
return false;
|
|
}
|
|
|
|
if (sourceUnitType == CSS_NUMBER) {
|
|
// We interpret conversion from CSS_NUMBER in the same way as BisonCSSParser::validUnit() while using non-strict mode.
|
|
sourceUnitType = canonicalUnitTypeForCategory(targetCategory);
|
|
if (sourceUnitType == CSS_UNKNOWN)
|
|
return false;
|
|
}
|
|
|
|
double convertedValue = getDoubleValue();
|
|
|
|
// First convert the value from m_primitiveUnitType to canonical type.
|
|
double factor = conversionToCanonicalUnitsScaleFactor(sourceUnitType);
|
|
convertedValue *= factor;
|
|
|
|
// Now convert from canonical type to the target unitType.
|
|
factor = conversionToCanonicalUnitsScaleFactor(targetUnitType);
|
|
convertedValue /= factor;
|
|
|
|
*result = convertedValue;
|
|
return true;
|
|
}
|
|
|
|
bool CSSPrimitiveValue::unitTypeToLengthUnitType(UnitType unitType, LengthUnitType& lengthType)
|
|
{
|
|
switch (unitType) {
|
|
case CSSPrimitiveValue::CSS_PX:
|
|
case CSSPrimitiveValue::CSS_CM:
|
|
case CSSPrimitiveValue::CSS_MM:
|
|
case CSSPrimitiveValue::CSS_IN:
|
|
case CSSPrimitiveValue::CSS_PT:
|
|
case CSSPrimitiveValue::CSS_PC:
|
|
lengthType = UnitTypePixels;
|
|
return true;
|
|
case CSSPrimitiveValue::CSS_EMS:
|
|
lengthType = UnitTypeFontSize;
|
|
return true;
|
|
case CSSPrimitiveValue::CSS_EXS:
|
|
lengthType = UnitTypeFontXSize;
|
|
return true;
|
|
case CSSPrimitiveValue::CSS_REMS:
|
|
lengthType = UnitTypeRootFontSize;
|
|
return true;
|
|
case CSSPrimitiveValue::CSS_CHS:
|
|
lengthType = UnitTypeZeroCharacterWidth;
|
|
return true;
|
|
case CSSPrimitiveValue::CSS_PERCENTAGE:
|
|
lengthType = UnitTypePercentage;
|
|
return true;
|
|
case CSSPrimitiveValue::CSS_VW:
|
|
lengthType = UnitTypeViewportWidth;
|
|
return true;
|
|
case CSSPrimitiveValue::CSS_VH:
|
|
lengthType = UnitTypeViewportHeight;
|
|
return true;
|
|
case CSSPrimitiveValue::CSS_VMIN:
|
|
lengthType = UnitTypeViewportMin;
|
|
return true;
|
|
case CSSPrimitiveValue::CSS_VMAX:
|
|
lengthType = UnitTypeViewportMax;
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
CSSPrimitiveValue::UnitType CSSPrimitiveValue::lengthUnitTypeToUnitType(LengthUnitType type)
|
|
{
|
|
switch (type) {
|
|
case UnitTypePixels:
|
|
return CSSPrimitiveValue::CSS_PX;
|
|
case UnitTypeFontSize:
|
|
return CSSPrimitiveValue::CSS_EMS;
|
|
case UnitTypeFontXSize:
|
|
return CSSPrimitiveValue::CSS_EXS;
|
|
case UnitTypeRootFontSize:
|
|
return CSSPrimitiveValue::CSS_REMS;
|
|
case UnitTypeZeroCharacterWidth:
|
|
return CSSPrimitiveValue::CSS_CHS;
|
|
case UnitTypePercentage:
|
|
return CSSPrimitiveValue::CSS_PERCENTAGE;
|
|
case UnitTypeViewportWidth:
|
|
return CSSPrimitiveValue::CSS_VW;
|
|
case UnitTypeViewportHeight:
|
|
return CSSPrimitiveValue::CSS_VH;
|
|
case UnitTypeViewportMin:
|
|
return CSSPrimitiveValue::CSS_VMIN;
|
|
case UnitTypeViewportMax:
|
|
return CSSPrimitiveValue::CSS_VMAX;
|
|
case LengthUnitTypeCount:
|
|
break;
|
|
}
|
|
ASSERT_NOT_REACHED();
|
|
return CSSPrimitiveValue::CSS_UNKNOWN;
|
|
}
|
|
|
|
void CSSPrimitiveValue::setStringValue(unsigned short, const String&, ExceptionState& exceptionState)
|
|
{
|
|
// Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
|
|
// No other engine supports mutating style through this API. Computed style is always read-only anyway.
|
|
// Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
|
|
exceptionState.throwDOMException(NoModificationAllowedError, "CSSPrimitiveValue objects are read-only.");
|
|
}
|
|
|
|
String CSSPrimitiveValue::getStringValue(ExceptionState& exceptionState) const
|
|
{
|
|
switch (m_primitiveUnitType) {
|
|
case CSS_STRING:
|
|
case CSS_ATTR:
|
|
case CSS_URI:
|
|
return m_value.string;
|
|
case CSS_VALUE_ID:
|
|
return valueName(m_value.valueID);
|
|
case CSS_PROPERTY_ID:
|
|
return propertyName(m_value.propertyID);
|
|
default:
|
|
exceptionState.throwDOMException(InvalidAccessError, "This object's value cannot be represented as a string.");
|
|
break;
|
|
}
|
|
|
|
return String();
|
|
}
|
|
|
|
String CSSPrimitiveValue::getStringValue() const
|
|
{
|
|
switch (m_primitiveUnitType) {
|
|
case CSS_STRING:
|
|
case CSS_ATTR:
|
|
case CSS_URI:
|
|
return m_value.string;
|
|
case CSS_VALUE_ID:
|
|
return valueName(m_value.valueID);
|
|
case CSS_PROPERTY_ID:
|
|
return propertyName(m_value.propertyID);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return String();
|
|
}
|
|
|
|
Rect* CSSPrimitiveValue::getRectValue(ExceptionState& exceptionState) const
|
|
{
|
|
if (m_primitiveUnitType != CSS_RECT) {
|
|
exceptionState.throwDOMException(InvalidAccessError, "This object is not a rect value.");
|
|
return 0;
|
|
}
|
|
|
|
return m_value.rect;
|
|
}
|
|
|
|
Quad* CSSPrimitiveValue::getQuadValue(ExceptionState& exceptionState) const
|
|
{
|
|
if (m_primitiveUnitType != CSS_QUAD) {
|
|
exceptionState.throwDOMException(InvalidAccessError, "This object is not a quad value.");
|
|
return 0;
|
|
}
|
|
|
|
return m_value.quad;
|
|
}
|
|
|
|
PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionState& exceptionState) const
|
|
{
|
|
if (m_primitiveUnitType != CSS_RGBCOLOR) {
|
|
exceptionState.throwDOMException(InvalidAccessError, "This object is not an RGB color value.");
|
|
return nullptr;
|
|
}
|
|
|
|
// FIMXE: This should not return a new object for each invocation.
|
|
return RGBColor::create(m_value.rgbcolor);
|
|
}
|
|
|
|
Pair* CSSPrimitiveValue::getPairValue(ExceptionState& exceptionState) const
|
|
{
|
|
if (m_primitiveUnitType != CSS_PAIR) {
|
|
exceptionState.throwDOMException(InvalidAccessError, "This object is not a pair value.");
|
|
return 0;
|
|
}
|
|
|
|
return m_value.pair;
|
|
}
|
|
|
|
static String formatNumber(double number, const char* suffix, unsigned suffixLength)
|
|
{
|
|
Decimal decimal = Decimal::fromDouble(number);
|
|
String result = decimal.toString();
|
|
result.append(suffix, suffixLength);
|
|
return result;
|
|
}
|
|
|
|
template <unsigned characterCount>
|
|
ALWAYS_INLINE static String formatNumber(double number, const char (&characters)[characterCount])
|
|
{
|
|
return formatNumber(number, characters, characterCount - 1);
|
|
}
|
|
|
|
static String formatNumber(double number, const char* characters)
|
|
{
|
|
return formatNumber(number, characters, strlen(characters));
|
|
}
|
|
|
|
const char* CSSPrimitiveValue::unitTypeToString(UnitType type)
|
|
{
|
|
switch (type) {
|
|
case CSS_NUMBER:
|
|
return "";
|
|
case CSS_PERCENTAGE:
|
|
return "%";
|
|
case CSS_EMS:
|
|
return "em";
|
|
case CSS_EXS:
|
|
return "ex";
|
|
case CSS_REMS:
|
|
return "rem";
|
|
case CSS_CHS:
|
|
return "ch";
|
|
case CSS_PX:
|
|
return "px";
|
|
case CSS_CM:
|
|
return "cm";
|
|
case CSS_DPPX:
|
|
return "dppx";
|
|
case CSS_DPI:
|
|
return "dpi";
|
|
case CSS_DPCM:
|
|
return "dpcm";
|
|
case CSS_MM:
|
|
return "mm";
|
|
case CSS_IN:
|
|
return "in";
|
|
case CSS_PT:
|
|
return "pt";
|
|
case CSS_PC:
|
|
return "pc";
|
|
case CSS_DEG:
|
|
return "deg";
|
|
case CSS_RAD:
|
|
return "rad";
|
|
case CSS_GRAD:
|
|
return "grad";
|
|
case CSS_MS:
|
|
return "ms";
|
|
case CSS_S:
|
|
return "s";
|
|
case CSS_HZ:
|
|
return "hz";
|
|
case CSS_KHZ:
|
|
return "khz";
|
|
case CSS_TURN:
|
|
return "turn";
|
|
case CSS_FR:
|
|
return "fr";
|
|
case CSS_VW:
|
|
return "vw";
|
|
case CSS_VH:
|
|
return "vh";
|
|
case CSS_VMIN:
|
|
return "vmin";
|
|
case CSS_VMAX:
|
|
return "vmax";
|
|
case CSS_UNKNOWN:
|
|
case CSS_DIMENSION:
|
|
case CSS_STRING:
|
|
case CSS_URI:
|
|
case CSS_VALUE_ID:
|
|
case CSS_PROPERTY_ID:
|
|
case CSS_ATTR:
|
|
case CSS_RECT:
|
|
case CSS_QUAD:
|
|
case CSS_RGBCOLOR:
|
|
case CSS_PARSER_HEXCOLOR:
|
|
case CSS_PAIR:
|
|
case CSS_CALC:
|
|
case CSS_SHAPE:
|
|
case CSS_IDENT:
|
|
case CSS_UNICODE_RANGE:
|
|
case CSS_CALC_PERCENTAGE_WITH_NUMBER:
|
|
case CSS_CALC_PERCENTAGE_WITH_LENGTH:
|
|
break;
|
|
};
|
|
ASSERT_NOT_REACHED();
|
|
return "";
|
|
}
|
|
|
|
String CSSPrimitiveValue::customCSSText(CSSTextFormattingFlags formattingFlag) const
|
|
{
|
|
// FIXME: return the original value instead of a generated one (e.g. color
|
|
// name if it was specified) - check what spec says about this
|
|
|
|
if (m_hasCachedCSSText) {
|
|
ASSERT(cssTextCache().contains(this));
|
|
return cssTextCache().get(this);
|
|
}
|
|
|
|
String text;
|
|
switch (m_primitiveUnitType) {
|
|
case CSS_UNKNOWN:
|
|
// FIXME
|
|
break;
|
|
case CSS_NUMBER:
|
|
case CSS_PERCENTAGE:
|
|
case CSS_EMS:
|
|
case CSS_EXS:
|
|
case CSS_REMS:
|
|
case CSS_CHS:
|
|
case CSS_PX:
|
|
case CSS_CM:
|
|
case CSS_DPPX:
|
|
case CSS_DPI:
|
|
case CSS_DPCM:
|
|
case CSS_MM:
|
|
case CSS_IN:
|
|
case CSS_PT:
|
|
case CSS_PC:
|
|
case CSS_DEG:
|
|
case CSS_RAD:
|
|
case CSS_GRAD:
|
|
case CSS_MS:
|
|
case CSS_S:
|
|
case CSS_HZ:
|
|
case CSS_KHZ:
|
|
case CSS_TURN:
|
|
case CSS_FR:
|
|
case CSS_VW:
|
|
case CSS_VH:
|
|
case CSS_VMIN:
|
|
case CSS_VMAX:
|
|
text = formatNumber(m_value.num, unitTypeToString((UnitType)m_primitiveUnitType));
|
|
case CSS_DIMENSION:
|
|
// FIXME: We currently don't handle CSS_DIMENSION properly as we don't store
|
|
// the actual dimension, just the numeric value as a string.
|
|
break;
|
|
case CSS_STRING:
|
|
text = formattingFlag == AlwaysQuoteCSSString ? quoteCSSString(m_value.string) : quoteCSSStringIfNeeded(m_value.string);
|
|
break;
|
|
case CSS_URI:
|
|
text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")";
|
|
break;
|
|
case CSS_VALUE_ID:
|
|
text = valueName(m_value.valueID);
|
|
break;
|
|
case CSS_PROPERTY_ID:
|
|
text = propertyName(m_value.propertyID);
|
|
break;
|
|
case CSS_ATTR: {
|
|
StringBuilder result;
|
|
result.reserveCapacity(6 + m_value.string->length());
|
|
result.appendLiteral("attr(");
|
|
result.append(m_value.string);
|
|
result.append(')');
|
|
|
|
text = result.toString();
|
|
break;
|
|
}
|
|
case CSS_RECT:
|
|
text = getRectValue()->cssText();
|
|
break;
|
|
case CSS_QUAD:
|
|
text = getQuadValue()->cssText();
|
|
break;
|
|
case CSS_RGBCOLOR:
|
|
case CSS_PARSER_HEXCOLOR: {
|
|
RGBA32 rgbColor = m_value.rgbcolor;
|
|
if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR)
|
|
Color::parseHexColor(m_value.string, rgbColor);
|
|
Color color(rgbColor);
|
|
text = color.serializedAsCSSComponentValue();
|
|
break;
|
|
}
|
|
case CSS_PAIR:
|
|
text = getPairValue()->cssText();
|
|
break;
|
|
case CSS_CALC:
|
|
text = m_value.calc->cssText();
|
|
break;
|
|
case CSS_SHAPE:
|
|
text = m_value.shape->cssText();
|
|
break;
|
|
}
|
|
|
|
ASSERT(!cssTextCache().contains(this));
|
|
cssTextCache().set(this, text);
|
|
m_hasCachedCSSText = true;
|
|
return text;
|
|
}
|
|
|
|
PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::cloneForCSSOM() const
|
|
{
|
|
RefPtr<CSSPrimitiveValue> result = nullptr;
|
|
|
|
switch (m_primitiveUnitType) {
|
|
case CSS_STRING:
|
|
case CSS_URI:
|
|
case CSS_ATTR:
|
|
result = CSSPrimitiveValue::create(m_value.string, static_cast<UnitType>(m_primitiveUnitType));
|
|
break;
|
|
case CSS_RECT:
|
|
result = CSSPrimitiveValue::create(m_value.rect->cloneForCSSOM());
|
|
break;
|
|
case CSS_QUAD:
|
|
result = CSSPrimitiveValue::create(m_value.quad->cloneForCSSOM());
|
|
break;
|
|
case CSS_PAIR:
|
|
// Pair is not exposed to the CSSOM, no need for a deep clone.
|
|
result = CSSPrimitiveValue::create(m_value.pair);
|
|
break;
|
|
case CSS_CALC:
|
|
// CSSCalcValue is not exposed to the CSSOM, no need for a deep clone.
|
|
result = CSSPrimitiveValue::create(m_value.calc);
|
|
break;
|
|
case CSS_SHAPE:
|
|
// CSSShapeValue is not exposed to the CSSOM, no need for a deep clone.
|
|
result = CSSPrimitiveValue::create(m_value.shape);
|
|
break;
|
|
case CSS_NUMBER:
|
|
case CSS_PERCENTAGE:
|
|
case CSS_EMS:
|
|
case CSS_EXS:
|
|
case CSS_REMS:
|
|
case CSS_CHS:
|
|
case CSS_PX:
|
|
case CSS_CM:
|
|
case CSS_MM:
|
|
case CSS_IN:
|
|
case CSS_PT:
|
|
case CSS_PC:
|
|
case CSS_DEG:
|
|
case CSS_RAD:
|
|
case CSS_GRAD:
|
|
case CSS_MS:
|
|
case CSS_S:
|
|
case CSS_HZ:
|
|
case CSS_KHZ:
|
|
case CSS_TURN:
|
|
case CSS_VW:
|
|
case CSS_VH:
|
|
case CSS_VMIN:
|
|
case CSS_VMAX:
|
|
case CSS_DPPX:
|
|
case CSS_DPI:
|
|
case CSS_DPCM:
|
|
case CSS_FR:
|
|
result = CSSPrimitiveValue::create(m_value.num, static_cast<UnitType>(m_primitiveUnitType));
|
|
break;
|
|
case CSS_PROPERTY_ID:
|
|
result = CSSPrimitiveValue::createIdentifier(m_value.propertyID);
|
|
break;
|
|
case CSS_VALUE_ID:
|
|
result = CSSPrimitiveValue::createIdentifier(m_value.valueID);
|
|
break;
|
|
case CSS_RGBCOLOR:
|
|
result = CSSPrimitiveValue::createColor(m_value.rgbcolor);
|
|
break;
|
|
case CSS_DIMENSION:
|
|
case CSS_UNKNOWN:
|
|
case CSS_PARSER_HEXCOLOR:
|
|
ASSERT_NOT_REACHED();
|
|
break;
|
|
}
|
|
if (result)
|
|
result->setCSSOMSafe();
|
|
|
|
return result;
|
|
}
|
|
|
|
bool CSSPrimitiveValue::equals(const CSSPrimitiveValue& other) const
|
|
{
|
|
if (m_primitiveUnitType != other.m_primitiveUnitType)
|
|
return false;
|
|
|
|
switch (m_primitiveUnitType) {
|
|
case CSS_UNKNOWN:
|
|
return false;
|
|
case CSS_NUMBER:
|
|
case CSS_PERCENTAGE:
|
|
case CSS_EMS:
|
|
case CSS_EXS:
|
|
case CSS_REMS:
|
|
case CSS_PX:
|
|
case CSS_CM:
|
|
case CSS_DPPX:
|
|
case CSS_DPI:
|
|
case CSS_DPCM:
|
|
case CSS_MM:
|
|
case CSS_IN:
|
|
case CSS_PT:
|
|
case CSS_PC:
|
|
case CSS_DEG:
|
|
case CSS_RAD:
|
|
case CSS_GRAD:
|
|
case CSS_MS:
|
|
case CSS_S:
|
|
case CSS_HZ:
|
|
case CSS_KHZ:
|
|
case CSS_TURN:
|
|
case CSS_VW:
|
|
case CSS_VH:
|
|
case CSS_VMIN:
|
|
case CSS_VMAX:
|
|
case CSS_DIMENSION:
|
|
case CSS_FR:
|
|
return m_value.num == other.m_value.num;
|
|
case CSS_PROPERTY_ID:
|
|
return propertyName(m_value.propertyID) == propertyName(other.m_value.propertyID);
|
|
case CSS_VALUE_ID:
|
|
return valueName(m_value.valueID) == valueName(other.m_value.valueID);
|
|
case CSS_STRING:
|
|
case CSS_URI:
|
|
case CSS_ATTR:
|
|
case CSS_PARSER_HEXCOLOR:
|
|
return equal(m_value.string, other.m_value.string);
|
|
case CSS_RECT:
|
|
return m_value.rect && other.m_value.rect && m_value.rect->equals(*other.m_value.rect);
|
|
case CSS_QUAD:
|
|
return m_value.quad && other.m_value.quad && m_value.quad->equals(*other.m_value.quad);
|
|
case CSS_RGBCOLOR:
|
|
return m_value.rgbcolor == other.m_value.rgbcolor;
|
|
case CSS_PAIR:
|
|
return m_value.pair && other.m_value.pair && m_value.pair->equals(*other.m_value.pair);
|
|
case CSS_CALC:
|
|
return m_value.calc && other.m_value.calc && m_value.calc->equals(*other.m_value.calc);
|
|
case CSS_SHAPE:
|
|
return m_value.shape && other.m_value.shape && m_value.shape->equals(*other.m_value.shape);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
} // namespace blink
|