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