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/CSSSelectorList.h"
     26 #include "core/html/parser/HTMLParserIdioms.h"
     27 
     28 namespace WebCore {
     29 
     30 using namespace WTF;
     31 
     32 static void destroy(Vector<CSSParserValue, 4>& values)
     33 {
     34     size_t numValues = values.size();
     35     for (size_t i = 0; i < numValues; i++) {
     36         if (values[i].unit == CSSParserValue::Function)
     37             delete values[i].function;
     38         else if (values[i].unit == CSSParserValue::ValueList)
     39             delete values[i].valueList;
     40     }
     41 }
     42 
     43 void CSSParserValueList::destroyAndClear()
     44 {
     45     destroy(m_values);
     46     clearAndLeakValues();
     47 }
     48 
     49 CSSParserValueList::~CSSParserValueList()
     50 {
     51     destroy(m_values);
     52 }
     53 
     54 void CSSParserValueList::addValue(const CSSParserValue& v)
     55 {
     56     m_values.append(v);
     57 }
     58 
     59 void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v)
     60 {
     61     m_values.insert(i, v);
     62 }
     63 
     64 void CSSParserValueList::stealValues(CSSParserValueList& valueList)
     65 {
     66     for (unsigned i = 0; i < valueList.size(); ++i)
     67         m_values.append(*(valueList.valueAt(i)));
     68     valueList.clearAndLeakValues();
     69 }
     70 
     71 PassRefPtrWillBeRawPtr<CSSValue> CSSParserValue::createCSSValue()
     72 {
     73     if (id)
     74         return CSSPrimitiveValue::createIdentifier(id);
     75 
     76     if (unit == CSSParserValue::Operator)
     77         return CSSPrimitiveValue::createParserOperator(iValue);
     78     if (unit == CSSParserValue::Function)
     79         return CSSFunctionValue::create(function);
     80     if (unit == CSSParserValue::ValueList)
     81         return CSSValueList::createFromParserValueList(valueList);
     82     if (unit >= CSSParserValue::Q_EMS)
     83         return CSSPrimitiveValue::createAllowingMarginQuirk(fValue, CSSPrimitiveValue::CSS_EMS);
     84 
     85     CSSPrimitiveValue::UnitType primitiveUnit = static_cast<CSSPrimitiveValue::UnitType>(unit);
     86     switch (primitiveUnit) {
     87     case CSSPrimitiveValue::CSS_IDENT:
     88     case CSSPrimitiveValue::CSS_PROPERTY_ID:
     89     case CSSPrimitiveValue::CSS_VALUE_ID:
     90         return CSSPrimitiveValue::create(string, CSSPrimitiveValue::CSS_PARSER_IDENTIFIER);
     91     case CSSPrimitiveValue::CSS_NUMBER:
     92         return CSSPrimitiveValue::create(fValue, isInt ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER);
     93     case CSSPrimitiveValue::CSS_STRING:
     94     case CSSPrimitiveValue::CSS_URI:
     95     case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR:
     96         return CSSPrimitiveValue::create(string, primitiveUnit);
     97     case CSSPrimitiveValue::CSS_PERCENTAGE:
     98     case CSSPrimitiveValue::CSS_EMS:
     99     case CSSPrimitiveValue::CSS_EXS:
    100     case CSSPrimitiveValue::CSS_PX:
    101     case CSSPrimitiveValue::CSS_CM:
    102     case CSSPrimitiveValue::CSS_MM:
    103     case CSSPrimitiveValue::CSS_IN:
    104     case CSSPrimitiveValue::CSS_PT:
    105     case CSSPrimitiveValue::CSS_PC:
    106     case CSSPrimitiveValue::CSS_DEG:
    107     case CSSPrimitiveValue::CSS_RAD:
    108     case CSSPrimitiveValue::CSS_GRAD:
    109     case CSSPrimitiveValue::CSS_MS:
    110     case CSSPrimitiveValue::CSS_S:
    111     case CSSPrimitiveValue::CSS_HZ:
    112     case CSSPrimitiveValue::CSS_KHZ:
    113     case CSSPrimitiveValue::CSS_VW:
    114     case CSSPrimitiveValue::CSS_VH:
    115     case CSSPrimitiveValue::CSS_VMIN:
    116     case CSSPrimitiveValue::CSS_VMAX:
    117     case CSSPrimitiveValue::CSS_TURN:
    118     case CSSPrimitiveValue::CSS_REMS:
    119     case CSSPrimitiveValue::CSS_CHS:
    120     case CSSPrimitiveValue::CSS_FR:
    121         return CSSPrimitiveValue::create(fValue, primitiveUnit);
    122     case CSSPrimitiveValue::CSS_UNKNOWN:
    123     case CSSPrimitiveValue::CSS_DIMENSION:
    124     case CSSPrimitiveValue::CSS_ATTR:
    125     case CSSPrimitiveValue::CSS_COUNTER:
    126     case CSSPrimitiveValue::CSS_RECT:
    127     case CSSPrimitiveValue::CSS_RGBCOLOR:
    128     case CSSPrimitiveValue::CSS_DPPX:
    129     case CSSPrimitiveValue::CSS_DPI:
    130     case CSSPrimitiveValue::CSS_DPCM:
    131     case CSSPrimitiveValue::CSS_PAIR:
    132     case CSSPrimitiveValue::CSS_UNICODE_RANGE:
    133     case CSSPrimitiveValue::CSS_PARSER_INTEGER:
    134     case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER:
    135     case CSSPrimitiveValue::CSS_PARSER_OPERATOR:
    136     case CSSPrimitiveValue::CSS_COUNTER_NAME:
    137     case CSSPrimitiveValue::CSS_SHAPE:
    138     case CSSPrimitiveValue::CSS_QUAD:
    139     case CSSPrimitiveValue::CSS_CALC:
    140     case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER:
    141     case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH:
    142         return nullptr;
    143     }
    144 
    145     ASSERT_NOT_REACHED();
    146     return nullptr;
    147 }
    148 
    149 CSSParserSelector::CSSParserSelector()
    150     : m_selector(adoptPtr(new CSSSelector()))
    151 {
    152 }
    153 
    154 CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName)
    155     : m_selector(adoptPtr(new CSSSelector(tagQName)))
    156 {
    157 }
    158 
    159 CSSParserSelector::~CSSParserSelector()
    160 {
    161     if (!m_tagHistory)
    162         return;
    163     Vector<OwnPtr<CSSParserSelector>, 16> toDelete;
    164     OwnPtr<CSSParserSelector> selector = m_tagHistory.release();
    165     while (true) {
    166         OwnPtr<CSSParserSelector> next = selector->m_tagHistory.release();
    167         toDelete.append(selector.release());
    168         if (!next)
    169             break;
    170         selector = next.release();
    171     }
    172 }
    173 
    174 void CSSParserSelector::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
    175 {
    176     CSSSelectorList* selectorList = new CSSSelectorList();
    177     selectorList->adoptSelectorVector(selectorVector);
    178     m_selector->setSelectorList(adoptPtr(selectorList));
    179 }
    180 
    181 bool CSSParserSelector::isSimple() const
    182 {
    183     if (m_selector->selectorList() || m_selector->matchesPseudoElement())
    184         return false;
    185 
    186     if (!m_tagHistory)
    187         return true;
    188 
    189     if (m_selector->match() == CSSSelector::Tag) {
    190         // We can't check against anyQName() here because namespace may not be nullAtom.
    191         // Example:
    192         //     @namespace "http://www.w3.org/2000/svg";
    193         //     svg:not(:root) { ...
    194         if (m_selector->tagQName().localName() == starAtom)
    195             return m_tagHistory->isSimple();
    196     }
    197 
    198     return false;
    199 }
    200 
    201 void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector> selector, CSSSelector::Relation after)
    202 {
    203     if (m_tagHistory)
    204         selector->setTagHistory(m_tagHistory.release());
    205     setRelation(before);
    206     selector->setRelation(after);
    207     m_tagHistory = selector;
    208 }
    209 
    210 void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, PassOwnPtr<CSSParserSelector> selector)
    211 {
    212     CSSParserSelector* end = this;
    213     while (end->tagHistory())
    214         end = end->tagHistory();
    215     end->setRelation(relation);
    216     end->setTagHistory(selector);
    217 }
    218 
    219 void CSSParserSelector::prependTagSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule)
    220 {
    221     OwnPtr<CSSParserSelector> second = adoptPtr(new CSSParserSelector);
    222     second->m_selector = m_selector.release();
    223     second->m_tagHistory = m_tagHistory.release();
    224     m_tagHistory = second.release();
    225 
    226     m_selector = adoptPtr(new CSSSelector(tagQName, tagIsForNamespaceRule));
    227     m_selector->setRelation(CSSSelector::SubSelector);
    228 }
    229 
    230 bool CSSParserSelector::hasHostPseudoSelector() const
    231 {
    232     CSSParserSelector* selector = const_cast<CSSParserSelector*>(this);
    233     do {
    234         if (selector->pseudoType() == CSSSelector::PseudoHost || selector->pseudoType() == CSSSelector::PseudoHostContext)
    235             return true;
    236     } while ((selector = selector->tagHistory()));
    237     return false;
    238 }
    239 
    240 } // namespace WebCore
    241