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