Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 2003 Lars Knoll (knoll (at) kde.org)
      3  * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #include "config.h"
     22 #include "core/css/CSSParserValues.h"
     23 
     24 #include "core/css/CSSFunctionValue.h"
     25 #include "core/css/CSSPrimitiveValue.h"
     26 #include "core/css/CSSSelector.h"
     27 #include "core/css/CSSSelectorList.h"
     28 
     29 namespace WebCore {
     30 
     31 using namespace WTF;
     32 
     33 CSSParserValueList::~CSSParserValueList()
     34 {
     35     size_t numValues = m_values.size();
     36     for (size_t i = 0; i < numValues; i++) {
     37         if (m_values[i].unit == CSSParserValue::Function)
     38             delete m_values[i].function;
     39     }
     40 }
     41 
     42 void CSSParserValueList::addValue(const CSSParserValue& v)
     43 {
     44     m_values.append(v);
     45 }
     46 
     47 void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v)
     48 {
     49     m_values.insert(i, v);
     50 }
     51 
     52 void CSSParserValueList::deleteValueAt(unsigned i)
     53 {
     54     m_values.remove(i);
     55 }
     56 
     57 void CSSParserValueList::extend(CSSParserValueList& valueList)
     58 {
     59     for (unsigned int i = 0; i < valueList.size(); ++i)
     60         m_values.append(*(valueList.valueAt(i)));
     61 }
     62 
     63 PassRefPtr<CSSValue> CSSParserValue::createCSSValue()
     64 {
     65     RefPtr<CSSValue> parsedValue;
     66     if (id)
     67         return CSSPrimitiveValue::createIdentifier(id);
     68 
     69     if (unit == CSSParserValue::Operator) {
     70         RefPtr<CSSPrimitiveValue> primitiveValue = CSSPrimitiveValue::createParserOperator(iValue);
     71         primitiveValue->setPrimitiveType(CSSPrimitiveValue::CSS_PARSER_OPERATOR);
     72         return primitiveValue;
     73     }
     74     if (unit == CSSParserValue::Function)
     75         return CSSFunctionValue::create(function);
     76     if (unit >= CSSParserValue::Q_EMS)
     77         return CSSPrimitiveValue::createAllowingMarginQuirk(fValue, CSSPrimitiveValue::CSS_EMS);
     78 
     79     CSSPrimitiveValue::UnitTypes primitiveUnit = static_cast<CSSPrimitiveValue::UnitTypes>(unit);
     80     switch (primitiveUnit) {
     81     case CSSPrimitiveValue::CSS_IDENT:
     82     case CSSPrimitiveValue::CSS_PROPERTY_ID:
     83     case CSSPrimitiveValue::CSS_VALUE_ID:
     84         return CSSPrimitiveValue::create(string, CSSPrimitiveValue::CSS_PARSER_IDENTIFIER);
     85     case CSSPrimitiveValue::CSS_NUMBER:
     86         return CSSPrimitiveValue::create(fValue, isInt ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER);
     87     case CSSPrimitiveValue::CSS_STRING:
     88     case CSSPrimitiveValue::CSS_URI:
     89     case CSSPrimitiveValue::CSS_VARIABLE_NAME:
     90     case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR:
     91         return CSSPrimitiveValue::create(string, primitiveUnit);
     92     case CSSPrimitiveValue::CSS_PERCENTAGE:
     93     case CSSPrimitiveValue::CSS_EMS:
     94     case CSSPrimitiveValue::CSS_EXS:
     95     case CSSPrimitiveValue::CSS_PX:
     96     case CSSPrimitiveValue::CSS_CM:
     97     case CSSPrimitiveValue::CSS_MM:
     98     case CSSPrimitiveValue::CSS_IN:
     99     case CSSPrimitiveValue::CSS_PT:
    100     case CSSPrimitiveValue::CSS_PC:
    101     case CSSPrimitiveValue::CSS_DEG:
    102     case CSSPrimitiveValue::CSS_RAD:
    103     case CSSPrimitiveValue::CSS_GRAD:
    104     case CSSPrimitiveValue::CSS_MS:
    105     case CSSPrimitiveValue::CSS_S:
    106     case CSSPrimitiveValue::CSS_HZ:
    107     case CSSPrimitiveValue::CSS_KHZ:
    108     case CSSPrimitiveValue::CSS_VW:
    109     case CSSPrimitiveValue::CSS_VH:
    110     case CSSPrimitiveValue::CSS_VMIN:
    111     case CSSPrimitiveValue::CSS_VMAX:
    112     case CSSPrimitiveValue::CSS_TURN:
    113     case CSSPrimitiveValue::CSS_REMS:
    114     case CSSPrimitiveValue::CSS_CHS:
    115     case CSSPrimitiveValue::CSS_FR:
    116         return CSSPrimitiveValue::create(fValue, primitiveUnit);
    117     case CSSPrimitiveValue::CSS_UNKNOWN:
    118     case CSSPrimitiveValue::CSS_DIMENSION:
    119     case CSSPrimitiveValue::CSS_ATTR:
    120     case CSSPrimitiveValue::CSS_COUNTER:
    121     case CSSPrimitiveValue::CSS_RECT:
    122     case CSSPrimitiveValue::CSS_RGBCOLOR:
    123     case CSSPrimitiveValue::CSS_DPPX:
    124     case CSSPrimitiveValue::CSS_DPI:
    125     case CSSPrimitiveValue::CSS_DPCM:
    126     case CSSPrimitiveValue::CSS_PAIR:
    127     case CSSPrimitiveValue::CSS_UNICODE_RANGE:
    128     case CSSPrimitiveValue::CSS_PARSER_OPERATOR:
    129     case CSSPrimitiveValue::CSS_PARSER_INTEGER:
    130     case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER:
    131     case CSSPrimitiveValue::CSS_COUNTER_NAME:
    132     case CSSPrimitiveValue::CSS_SHAPE:
    133     case CSSPrimitiveValue::CSS_QUAD:
    134     case CSSPrimitiveValue::CSS_CALC:
    135     case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER:
    136     case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH:
    137         return 0;
    138     }
    139 
    140     ASSERT_NOT_REACHED();
    141     return 0;
    142 }
    143 
    144 CSSParserSelector::CSSParserSelector()
    145     : m_selector(adoptPtr(new CSSSelector()))
    146     , m_functionArgumentSelector(0)
    147 {
    148 }
    149 
    150 CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName)
    151     : m_selector(adoptPtr(new CSSSelector(tagQName)))
    152     , m_functionArgumentSelector(0)
    153 {
    154 }
    155 
    156 CSSParserSelector::~CSSParserSelector()
    157 {
    158     if (!m_tagHistory)
    159         return;
    160     Vector<OwnPtr<CSSParserSelector>, 16> toDelete;
    161     OwnPtr<CSSParserSelector> selector = m_tagHistory.release();
    162     while (true) {
    163         OwnPtr<CSSParserSelector> next = selector->m_tagHistory.release();
    164         toDelete.append(selector.release());
    165         if (!next)
    166             break;
    167         selector = next.release();
    168     }
    169 }
    170 
    171 void CSSParserSelector::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
    172 {
    173     CSSSelectorList* selectorList = new CSSSelectorList();
    174     selectorList->adoptSelectorVector(selectorVector);
    175     m_selector->setSelectorList(adoptPtr(selectorList));
    176 }
    177 
    178 bool CSSParserSelector::isSimple() const
    179 {
    180     if (m_selector->selectorList() || m_selector->matchesPseudoElement())
    181         return false;
    182 
    183     if (!m_tagHistory)
    184         return true;
    185 
    186     if (m_selector->m_match == CSSSelector::Tag) {
    187         // We can't check against anyQName() here because namespace may not be nullAtom.
    188         // Example:
    189         //     @namespace "http://www.w3.org/2000/svg";
    190         //     svg:not(:root) { ...
    191         if (m_selector->tagQName().localName() == starAtom)
    192             return m_tagHistory->isSimple();
    193     }
    194 
    195     return false;
    196 }
    197 
    198 void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector> selector, CSSSelector::Relation after)
    199 {
    200     if (m_tagHistory)
    201         selector->setTagHistory(m_tagHistory.release());
    202     setRelation(before);
    203     selector->setRelation(after);
    204     m_tagHistory = selector;
    205 }
    206 
    207 void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, PassOwnPtr<CSSParserSelector> selector)
    208 {
    209     CSSParserSelector* end = this;
    210     while (end->tagHistory())
    211         end = end->tagHistory();
    212     end->setRelation(relation);
    213     end->setTagHistory(selector);
    214 }
    215 
    216 void CSSParserSelector::prependTagSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule)
    217 {
    218     OwnPtr<CSSParserSelector> second = adoptPtr(new CSSParserSelector);
    219     second->m_selector = m_selector.release();
    220     second->m_tagHistory = m_tagHistory.release();
    221     m_tagHistory = second.release();
    222 
    223     m_selector = adoptPtr(new CSSSelector(tagQName, tagIsForNamespaceRule));
    224     m_selector->m_relation = CSSSelector::SubSelector;
    225 }
    226 
    227 CSSParserSelector* CSSParserSelector::findDistributedPseudoElementSelector() const
    228 {
    229     CSSParserSelector* selector = const_cast<CSSParserSelector*>(this);
    230     do {
    231         if (selector->isDistributedPseudoElement())
    232             return selector;
    233     } while ((selector = selector->tagHistory()));
    234     return 0;
    235 }
    236 
    237 }
    238 
    239