⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cssprimitivevalue.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * (C) 1999-2003 Lars Knoll (knoll@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "config.h"#include "CSSPrimitiveValue.h"#include "CSSHelper.h"#include "CSSPropertyNames.h"#include "CSSStyleSheet.h"#include "CSSValueKeywords.h"#include "Color.h"#include "Counter.h"#include "ExceptionCode.h"#include "Node.h"#include "Pair.h"#include "Rect.h"#include "RenderStyle.h"#include <wtf/ASCIICType.h>#include <wtf/StdLibExtras.h>#if ENABLE(DASHBOARD_SUPPORT)#include "DashboardRegion.h"#endifusing namespace WTF;namespace WebCore {// A more stylish solution than sharing would be to turn CSSPrimitiveValue (or CSSValues in general) into non-virtual,// non-refcounted simple type with value semantics. In practice these sharing tricks get similar memory benefits // with less need for refactoring.PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createIdentifier(int ident){    static RefPtr<CSSPrimitiveValue>* identValueCache = new RefPtr<CSSPrimitiveValue>[numCSSValueKeywords];    if (ident >= 0 && ident < numCSSValueKeywords) {        RefPtr<CSSPrimitiveValue> primitiveValue = identValueCache[ident];        if (!primitiveValue) {            primitiveValue = adoptRef(new CSSPrimitiveValue(ident));            identValueCache[ident] = primitiveValue;        }        return primitiveValue.release();    }     return adoptRef(new CSSPrimitiveValue(ident));}PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createColor(unsigned rgbValue){    typedef HashMap<unsigned, RefPtr<CSSPrimitiveValue> > ColorValueCache;    static ColorValueCache* colorValueCache = new ColorValueCache;    // These are the empty and deleted values of the hash table.    if (rgbValue == Color::transparent) {        static CSSPrimitiveValue* colorTransparent = new CSSPrimitiveValue(Color::transparent);        return colorTransparent;    }    if (rgbValue == Color::white) {        static CSSPrimitiveValue* colorWhite = new CSSPrimitiveValue(Color::white);        return colorWhite;    }    RefPtr<CSSPrimitiveValue> primitiveValue = colorValueCache->get(rgbValue);    if (primitiveValue)        return primitiveValue.release();    primitiveValue = adoptRef(new CSSPrimitiveValue(rgbValue));    // Just wipe out the cache and start rebuilding when it gets too big.    const int maxColorCacheSize = 512;    if (colorValueCache->size() >= maxColorCacheSize)        colorValueCache->clear();    colorValueCache->add(rgbValue, primitiveValue);        return primitiveValue.release();}PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(double value, UnitTypes type){    // Small integers are very common. Try to share them.    const int cachedIntegerCount = 128;    // Other common primitive types have UnitTypes smaller than this.    const int maxCachedUnitType = CSS_PX;    typedef RefPtr<CSSPrimitiveValue>(* IntegerValueCache)[maxCachedUnitType + 1];    static IntegerValueCache integerValueCache = new RefPtr<CSSPrimitiveValue>[cachedIntegerCount][maxCachedUnitType + 1];    if (type <= maxCachedUnitType && value >= 0 && value < cachedIntegerCount) {        int intValue = static_cast<int>(value);        if (value == intValue) {            RefPtr<CSSPrimitiveValue> primitiveValue = integerValueCache[intValue][type];            if (!primitiveValue) {                primitiveValue = adoptRef(new CSSPrimitiveValue(value, type));                integerValueCache[intValue][type] = primitiveValue;            }            return primitiveValue.release();        }    }    return adoptRef(new CSSPrimitiveValue(value, type));}PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(const String& value, UnitTypes type){    return adoptRef(new CSSPrimitiveValue(value, type));}static const char* valueOrPropertyName(int valueOrPropertyID){    if (const char* valueName = getValueName(valueOrPropertyID))        return valueName;    return getPropertyName(static_cast<CSSPropertyID>(valueOrPropertyID));}// "ident" from the CSS tokenizer, minus backslash-escape sequencesstatic bool isCSSTokenizerIdentifier(const String& string){    const UChar* p = string.characters();    const UChar* end = p + string.length();    // -?    if (p != end && p[0] == '-')        ++p;    // {nmstart}    if (p == end || !(p[0] == '_' || p[0] >= 128 || isASCIIAlpha(p[0])))        return false;    ++p;    // {nmchar}*    for (; p != end; ++p) {        if (!(p[0] == '_' || p[0] == '-' || p[0] >= 128 || isASCIIAlphanumeric(p[0])))            return false;    }    return true;}// "url" from the CSS tokenizer, minus backslash-escape sequencesstatic bool isCSSTokenizerURL(const String& string){    const UChar* p = string.characters();    const UChar* end = p + string.length();    for (; p != end; ++p) {        UChar c = p[0];        switch (c) {            case '!':            case '#':            case '$':            case '%':            case '&':                break;            default:                if (c < '*')                    return false;                if (c <= '~')                    break;                if (c < 128)                    return false;        }    }    return true;}// We use single quotes for now because markup.cpp uses double quotes.static String quoteString(const String& string){    // FIXME: Also need to escape characters like '\n'.    String s = string;    s.replace('\\', "\\\\");    s.replace('\'', "\\'");    return "'" + s + "'";}static String quoteStringIfNeeded(const String& string){    return isCSSTokenizerIdentifier(string) ? string : quoteString(string);}static String quoteURLIfNeeded(const String& string){    return isCSSTokenizerURL(string) ? string : quoteString(string);}CSSPrimitiveValue::CSSPrimitiveValue()    : m_type(0){}CSSPrimitiveValue::CSSPrimitiveValue(int ident)    : m_type(CSS_IDENT){    m_value.ident = ident;}CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type)    : m_type(type){    m_value.num = num;}CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type)    : m_type(type){    if ((m_value.string = str.impl()))        m_value.string->ref();}CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color)    : m_type(CSS_RGBCOLOR){    m_value.rgbcolor = color;}CSSPrimitiveValue::CSSPrimitiveValue(const Length& length){    switch (length.type()) {        case Auto:            m_type = CSS_IDENT;            m_value.ident = CSSValueAuto;            break;        case WebCore::Fixed:            m_type = CSS_PX;            m_value.num = length.value();            break;        case Intrinsic:            m_type = CSS_IDENT;            m_value.ident = CSSValueIntrinsic;            break;        case MinIntrinsic:            m_type = CSS_IDENT;            m_value.ident = CSSValueMinIntrinsic;            break;        case Percent:            m_type = CSS_PERCENTAGE;            m_value.num = length.percent();            break;        case Relative:        case Static:            ASSERT_NOT_REACHED();            break;    }}void CSSPrimitiveValue::init(PassRefPtr<Counter> c){    m_type = CSS_COUNTER;    m_value.counter = c.releaseRef();}void CSSPrimitiveValue::init(PassRefPtr<Rect> r){    m_type = CSS_RECT;    m_value.rect = r.releaseRef();}#if ENABLE(DASHBOARD_SUPPORT)void CSSPrimitiveValue::init(PassRefPtr<DashboardRegion> r){    m_type = CSS_DASHBOARD_REGION;    m_value.region = r.releaseRef();}#endifvoid CSSPrimitiveValue::init(PassRefPtr<Pair> p){    m_type = CSS_PAIR;    m_value.pair = p.releaseRef();}CSSPrimitiveValue::~CSSPrimitiveValue(){    cleanup();}void CSSPrimitiveValue::cleanup(){    switch (m_type) {        case CSS_STRING:        case CSS_URI:        case CSS_ATTR:        case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:        case CSS_PARSER_HEXCOLOR:            if (m_value.string)                m_value.string->deref();            break;        case CSS_COUNTER:            m_value.counter->deref();            break;        case CSS_RECT:            m_value.rect->deref();            break;        case CSS_PAIR:            m_value.pair->deref();            break;#if ENABLE(DASHBOARD_SUPPORT)        case CSS_DASHBOARD_REGION:            if (m_value.region)                m_value.region->deref();            break;#endif        default:            break;    }    m_type = 0;}int CSSPrimitiveValue::computeLengthInt(RenderStyle* style){    double result = computeLengthDouble(style);    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We    // need to go ahead and round if we're really close to the next integer value.    result += result < 0 ? -0.01 : +0.01;    if (result > INT_MAX || result < INT_MIN)        return 0;    return static_cast<int>(result);}int CSSPrimitiveValue::computeLengthInt(RenderStyle* style, double multiplier){    double result = computeLengthDouble(style, multiplier);    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We    // need to go ahead and round if we're really close to the next integer value.    result += result < 0 ? -0.01 : +0.01;    if (result > INT_MAX || result < INT_MIN)        return 0;    return static_cast<int>(result);}const int intMaxForLength = 0x7ffffff; // max value for a 28-bit intconst int intMinForLength = (-0x7ffffff - 1); // min value for a 28-bit int// Lengths expect an int that is only 28-bits, so we have to check for a different overflow.int CSSPrimitiveValue::computeLengthIntForLength(RenderStyle* style){    double result = computeLengthDouble(style);    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We    // need to go ahead and round if we're really close to the next integer value.    result += result < 0 ? -0.01 : +0.01;    if (result > intMaxForLength || result < intMinForLength)        return 0;    return static_cast<int>(result);}// Lengths expect an int that is only 28-bits, so we have to check for a different overflow.int CSSPrimitiveValue::computeLengthIntForLength(RenderStyle* style, double multiplier){    double result = computeLengthDouble(style, multiplier);    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We    // need to go ahead and round if we're really close to the next integer value.    result += result < 0 ? -0.01 : +0.01;    if (result > intMaxForLength || result < intMinForLength)        return 0;    return static_cast<int>(result);}short CSSPrimitiveValue::computeLengthShort(RenderStyle* style){    double result = computeLengthDouble(style);    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We    // need to go ahead and round if we're really close to the next integer value.    result += result < 0 ? -0.01 : +0.01;    if (result > SHRT_MAX || result < SHRT_MIN)        return 0;    return static_cast<short>(result);}short CSSPrimitiveValue::computeLengthShort(RenderStyle* style, double multiplier){    double result = computeLengthDouble(style, multiplier);    // This conversion is imprecise, often resulting in values of, e.g., 44.99998.  We    // need to go ahead and round if we're really close to the next integer value.    result += result < 0 ? -0.01 : +0.01;    if (result > SHRT_MAX || result < SHRT_MIN)        return 0;    return static_cast<short>(result);}float CSSPrimitiveValue::computeLengthFloat(RenderStyle* style, bool computingFontSize){    return static_cast<float>(computeLengthDouble(style, 1.0, computingFontSize));}float CSSPrimitiveValue::computeLengthFloat(RenderStyle* style, double multiplier, bool computingFontSize){    return static_cast<float>(computeLengthDouble(style, multiplier, computingFontSize));}double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, double multiplier, bool computingFontSize){    unsigned short type = primitiveType();    // 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."  In addition the CSS property text-size-adjust is used to    // prevent text from zooming at all.  Therefore we will not apply the zoom here if we are computing font-size.    bool applyZoomMultiplier = !computingFontSize;    double factor = 1.0;    switch (type) {        case CSS_EMS:            applyZoomMultiplier = false;            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.            applyZoomMultiplier = false;            factor = style->font().xHeight();            break;        case CSS_PX:            break;        case CSS_CM:            factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)            break;        case CSS_MM:            factor = cssPixelsPerInch / 25.4;            break;        case CSS_IN:            factor = cssPixelsPerInch;            break;        case CSS_PT:            factor = cssPixelsPerInch / 72.0;            break;        case CSS_PC:            // 1 pc == 12 pt            factor = cssPixelsPerInch * 12.0 / 72.0;            break;        default:            return -1.0;    }    double result = getDoubleValue() * factor;    if (!applyZoomMultiplier || multiplier == 1.0)        return result;         // Any original result that was >= 1 should not be allowed to fall below 1.  This keeps border lines from    // vanishing.    double zoomedResult = result * multiplier;    if (result >= 1.0)        zoomedResult = max(1.0, zoomedResult);    return zoomedResult;}void CSSPrimitiveValue::setFloatValue(unsigned short unitType, double floatValue, ExceptionCode& ec){    ec = 0;    // FIXME: check if property supports this type    if (m_type > CSS_DIMENSION) {        ec = SYNTAX_ERR;        return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -