/platform/external/webkit/WebCore/css/CSSPrimitiveValue.cpp

https://github.com/aharish/totoro-gb-opensource-update2 · C++ · 971 lines · 779 code · 121 blank · 71 comment · 125 complexity · 960793e56dbb64de173ebf74eceb120b MD5 · raw file

  1. /*
  2. * (C) 1999-2003 Lars Knoll (knoll@kde.org)
  3. * Copyright (C) 2004, 2005, 2006, 2007, 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. #include "config.h"
  21. #include "CSSPrimitiveValue.h"
  22. #include "CSSHelper.h"
  23. #include "CSSPropertyNames.h"
  24. #include "CSSStyleSheet.h"
  25. #include "CSSValueKeywords.h"
  26. #include "Color.h"
  27. #include "Counter.h"
  28. #include "ExceptionCode.h"
  29. #include "Node.h"
  30. #include "Pair.h"
  31. #include "RGBColor.h"
  32. #include "Rect.h"
  33. #include "RenderStyle.h"
  34. #include <wtf/ASCIICType.h>
  35. #include <wtf/StdLibExtras.h>
  36. #if ENABLE(DASHBOARD_SUPPORT)
  37. #include "DashboardRegion.h"
  38. #endif
  39. using namespace WTF;
  40. namespace WebCore {
  41. // A more stylish solution than sharing would be to turn CSSPrimitiveValue (or CSSValues in general) into non-virtual,
  42. // non-refcounted simple type with value semantics. In practice these sharing tricks get similar memory benefits
  43. // with less need for refactoring.
  44. PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createIdentifier(int ident)
  45. {
  46. static RefPtr<CSSPrimitiveValue>* identValueCache = new RefPtr<CSSPrimitiveValue>[numCSSValueKeywords];
  47. if (ident >= 0 && ident < numCSSValueKeywords) {
  48. RefPtr<CSSPrimitiveValue> primitiveValue = identValueCache[ident];
  49. if (!primitiveValue) {
  50. primitiveValue = adoptRef(new CSSPrimitiveValue(ident));
  51. identValueCache[ident] = primitiveValue;
  52. }
  53. return primitiveValue.release();
  54. }
  55. return adoptRef(new CSSPrimitiveValue(ident));
  56. }
  57. PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createColor(unsigned rgbValue)
  58. {
  59. typedef HashMap<unsigned, RefPtr<CSSPrimitiveValue> > ColorValueCache;
  60. static ColorValueCache* colorValueCache = new ColorValueCache;
  61. // These are the empty and deleted values of the hash table.
  62. if (rgbValue == Color::transparent) {
  63. static CSSPrimitiveValue* colorTransparent = new CSSPrimitiveValue(Color::transparent);
  64. return colorTransparent;
  65. }
  66. if (rgbValue == Color::white) {
  67. static CSSPrimitiveValue* colorWhite = new CSSPrimitiveValue(Color::white);
  68. return colorWhite;
  69. }
  70. RefPtr<CSSPrimitiveValue> primitiveValue = colorValueCache->get(rgbValue);
  71. if (primitiveValue)
  72. return primitiveValue.release();
  73. primitiveValue = adoptRef(new CSSPrimitiveValue(rgbValue));
  74. // Just wipe out the cache and start rebuilding when it gets too big.
  75. const int maxColorCacheSize = 512;
  76. if (colorValueCache->size() >= maxColorCacheSize)
  77. colorValueCache->clear();
  78. colorValueCache->add(rgbValue, primitiveValue);
  79. return primitiveValue.release();
  80. }
  81. PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(double value, UnitTypes type)
  82. {
  83. // Small integers are very common. Try to share them.
  84. const int cachedIntegerCount = 128;
  85. // Other common primitive types have UnitTypes smaller than this.
  86. const int maxCachedUnitType = CSS_PX;
  87. typedef RefPtr<CSSPrimitiveValue>(* IntegerValueCache)[maxCachedUnitType + 1];
  88. static IntegerValueCache integerValueCache = new RefPtr<CSSPrimitiveValue>[cachedIntegerCount][maxCachedUnitType + 1];
  89. if (type <= maxCachedUnitType && value >= 0 && value < cachedIntegerCount) {
  90. int intValue = static_cast<int>(value);
  91. if (value == intValue) {
  92. RefPtr<CSSPrimitiveValue> primitiveValue = integerValueCache[intValue][type];
  93. if (!primitiveValue) {
  94. primitiveValue = adoptRef(new CSSPrimitiveValue(value, type));
  95. integerValueCache[intValue][type] = primitiveValue;
  96. }
  97. return primitiveValue.release();
  98. }
  99. }
  100. return adoptRef(new CSSPrimitiveValue(value, type));
  101. }
  102. PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(const String& value, UnitTypes type)
  103. {
  104. return adoptRef(new CSSPrimitiveValue(value, type));
  105. }
  106. static const char* valueOrPropertyName(int valueOrPropertyID)
  107. {
  108. if (const char* valueName = getValueName(valueOrPropertyID))
  109. return valueName;
  110. return getPropertyName(static_cast<CSSPropertyID>(valueOrPropertyID));
  111. }
  112. // "ident" from the CSS tokenizer, minus backslash-escape sequences
  113. static bool isCSSTokenizerIdentifier(const String& string)
  114. {
  115. const UChar* p = string.characters();
  116. const UChar* end = p + string.length();
  117. // -?
  118. if (p != end && p[0] == '-')
  119. ++p;
  120. // {nmstart}
  121. if (p == end || !(p[0] == '_' || p[0] >= 128 || isASCIIAlpha(p[0])))
  122. return false;
  123. ++p;
  124. // {nmchar}*
  125. for (; p != end; ++p) {
  126. if (!(p[0] == '_' || p[0] == '-' || p[0] >= 128 || isASCIIAlphanumeric(p[0])))
  127. return false;
  128. }
  129. return true;
  130. }
  131. // "url" from the CSS tokenizer, minus backslash-escape sequences
  132. static bool isCSSTokenizerURL(const String& string)
  133. {
  134. const UChar* p = string.characters();
  135. const UChar* end = p + string.length();
  136. for (; p != end; ++p) {
  137. UChar c = p[0];
  138. switch (c) {
  139. case '!':
  140. case '#':
  141. case '$':
  142. case '%':
  143. case '&':
  144. break;
  145. default:
  146. if (c < '*')
  147. return false;
  148. if (c <= '~')
  149. break;
  150. if (c < 128)
  151. return false;
  152. }
  153. }
  154. return true;
  155. }
  156. // We use single quotes for now because markup.cpp uses double quotes.
  157. static String quoteString(const String& string)
  158. {
  159. // FIXME: Also need to escape characters like '\n'.
  160. String s = string;
  161. s.replace('\\', "\\\\");
  162. s.replace('\'', "\\'");
  163. return "'" + s + "'";
  164. }
  165. static String quoteStringIfNeeded(const String& string)
  166. {
  167. return isCSSTokenizerIdentifier(string) ? string : quoteString(string);
  168. }
  169. static String quoteURLIfNeeded(const String& string)
  170. {
  171. return isCSSTokenizerURL(string) ? string : quoteString(string);
  172. }
  173. CSSPrimitiveValue::CSSPrimitiveValue()
  174. : m_type(0)
  175. {
  176. }
  177. CSSPrimitiveValue::CSSPrimitiveValue(int ident)
  178. : m_type(CSS_IDENT)
  179. {
  180. m_value.ident = ident;
  181. }
  182. CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type)
  183. : m_type(type)
  184. {
  185. m_value.num = num;
  186. }
  187. CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type)
  188. : m_type(type)
  189. {
  190. if ((m_value.string = str.impl()))
  191. m_value.string->ref();
  192. }
  193. CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color)
  194. : m_type(CSS_RGBCOLOR)
  195. {
  196. m_value.rgbcolor = color;
  197. }
  198. CSSPrimitiveValue::CSSPrimitiveValue(const Length& length)
  199. {
  200. switch (length.type()) {
  201. case Auto:
  202. m_type = CSS_IDENT;
  203. m_value.ident = CSSValueAuto;
  204. break;
  205. case WebCore::Fixed:
  206. m_type = CSS_PX;
  207. m_value.num = length.value();
  208. break;
  209. case Intrinsic:
  210. m_type = CSS_IDENT;
  211. m_value.ident = CSSValueIntrinsic;
  212. break;
  213. case MinIntrinsic:
  214. m_type = CSS_IDENT;
  215. m_value.ident = CSSValueMinIntrinsic;
  216. break;
  217. case Percent:
  218. m_type = CSS_PERCENTAGE;
  219. m_value.num = length.percent();
  220. break;
  221. case Relative:
  222. case Static:
  223. ASSERT_NOT_REACHED();
  224. break;
  225. }
  226. }
  227. void CSSPrimitiveValue::init(PassRefPtr<Counter> c)
  228. {
  229. m_type = CSS_COUNTER;
  230. m_value.counter = c.releaseRef();
  231. }
  232. void CSSPrimitiveValue::init(PassRefPtr<Rect> r)
  233. {
  234. m_type = CSS_RECT;
  235. m_value.rect = r.releaseRef();
  236. }
  237. #if ENABLE(DASHBOARD_SUPPORT)
  238. void CSSPrimitiveValue::init(PassRefPtr<DashboardRegion> r)
  239. {
  240. m_type = CSS_DASHBOARD_REGION;
  241. m_value.region = r.releaseRef();
  242. }
  243. #endif
  244. void CSSPrimitiveValue::init(PassRefPtr<Pair> p)
  245. {
  246. m_type = CSS_PAIR;
  247. m_value.pair = p.releaseRef();
  248. }
  249. CSSPrimitiveValue::~CSSPrimitiveValue()
  250. {
  251. cleanup();
  252. }
  253. void CSSPrimitiveValue::cleanup()
  254. {
  255. switch (m_type) {
  256. case CSS_STRING:
  257. case CSS_URI:
  258. case CSS_ATTR:
  259. case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
  260. case CSS_PARSER_HEXCOLOR:
  261. if (m_value.string)
  262. m_value.string->deref();
  263. break;
  264. case CSS_COUNTER:
  265. m_value.counter->deref();
  266. break;
  267. case CSS_RECT:
  268. m_value.rect->deref();
  269. break;
  270. case CSS_PAIR:
  271. m_value.pair->deref();
  272. break;
  273. #if ENABLE(DASHBOARD_SUPPORT)
  274. case CSS_DASHBOARD_REGION:
  275. if (m_value.region)
  276. m_value.region->deref();
  277. break;
  278. #endif
  279. default:
  280. break;
  281. }
  282. m_type = 0;
  283. }
  284. int CSSPrimitiveValue::computeLengthInt(RenderStyle* style, RenderStyle* rootStyle)
  285. {
  286. double result = computeLengthDouble(style, rootStyle);
  287. // This conversion is imprecise, often resulting in values of, e.g., 44.99998. We
  288. // need to go ahead and round if we're really close to the next integer value.
  289. result += result < 0 ? -0.01 : +0.01;
  290. if (result > INT_MAX || result < INT_MIN)
  291. return 0;
  292. return static_cast<int>(result);
  293. }
  294. int CSSPrimitiveValue::computeLengthInt(RenderStyle* style, RenderStyle* rootStyle, double multiplier)
  295. {
  296. double result = computeLengthDouble(style, rootStyle, multiplier);
  297. // This conversion is imprecise, often resulting in values of, e.g., 44.99998. We
  298. // need to go ahead and round if we're really close to the next integer value.
  299. result += result < 0 ? -0.01 : +0.01;
  300. if (result > INT_MAX || result < INT_MIN)
  301. return 0;
  302. return static_cast<int>(result);
  303. }
  304. const int intMaxForLength = 0x7ffffff; // max value for a 28-bit int
  305. const int intMinForLength = (-0x7ffffff - 1); // min value for a 28-bit int
  306. // Lengths expect an int that is only 28-bits, so we have to check for a different overflow.
  307. int CSSPrimitiveValue::computeLengthIntForLength(RenderStyle* style, RenderStyle* rootStyle)
  308. {
  309. double result = computeLengthDouble(style, rootStyle);
  310. // This conversion is imprecise, often resulting in values of, e.g., 44.99998. We
  311. // need to go ahead and round if we're really close to the next integer value.
  312. result += result < 0 ? -0.01 : +0.01;
  313. if (result > intMaxForLength || result < intMinForLength)
  314. return 0;
  315. return static_cast<int>(result);
  316. }
  317. // Lengths expect an int that is only 28-bits, so we have to check for a different overflow.
  318. int CSSPrimitiveValue::computeLengthIntForLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier)
  319. {
  320. double result = computeLengthDouble(style, rootStyle, multiplier);
  321. // This conversion is imprecise, often resulting in values of, e.g., 44.99998. We
  322. // need to go ahead and round if we're really close to the next integer value.
  323. result += result < 0 ? -0.01 : +0.01;
  324. if (result > intMaxForLength || result < intMinForLength)
  325. return 0;
  326. return static_cast<int>(result);
  327. }
  328. short CSSPrimitiveValue::computeLengthShort(RenderStyle* style, RenderStyle* rootStyle)
  329. {
  330. double result = computeLengthDouble(style, rootStyle);
  331. // This conversion is imprecise, often resulting in values of, e.g., 44.99998. We
  332. // need to go ahead and round if we're really close to the next integer value.
  333. result += result < 0 ? -0.01 : +0.01;
  334. if (result > SHRT_MAX || result < SHRT_MIN)
  335. return 0;
  336. return static_cast<short>(result);
  337. }
  338. short CSSPrimitiveValue::computeLengthShort(RenderStyle* style, RenderStyle* rootStyle, double multiplier)
  339. {
  340. double result = computeLengthDouble(style, rootStyle, multiplier);
  341. // This conversion is imprecise, often resulting in values of, e.g., 44.99998. We
  342. // need to go ahead and round if we're really close to the next integer value.
  343. result += result < 0 ? -0.01 : +0.01;
  344. if (result > SHRT_MAX || result < SHRT_MIN)
  345. return 0;
  346. return static_cast<short>(result);
  347. }
  348. float CSSPrimitiveValue::computeLengthFloat(RenderStyle* style, RenderStyle* rootStyle, bool computingFontSize)
  349. {
  350. return static_cast<float>(computeLengthDouble(style, rootStyle, 1.0, computingFontSize));
  351. }
  352. float CSSPrimitiveValue::computeLengthFloat(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize)
  353. {
  354. return static_cast<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize));
  355. }
  356. double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize)
  357. {
  358. unsigned short type = primitiveType();
  359. // We do not apply the zoom factor when we are computing the value of the font-size property. The zooming
  360. // for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference
  361. // as well as enforcing the implicit "smart minimum." In addition the CSS property text-size-adjust is used to
  362. // prevent text from zooming at all. Therefore we will not apply the zoom here if we are computing font-size.
  363. bool applyZoomMultiplier = !computingFontSize;
  364. double factor = 1.0;
  365. switch (type) {
  366. case CSS_EMS:
  367. applyZoomMultiplier = false;
  368. factor = computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize();
  369. break;
  370. case CSS_EXS:
  371. // FIXME: We have a bug right now where the zoom will be applied twice to EX units.
  372. // We really need to compute EX using fontMetrics for the original specifiedSize and not use
  373. // our actual constructed rendering font.
  374. applyZoomMultiplier = false;
  375. factor = style->font().xHeight();
  376. break;
  377. case CSS_REMS:
  378. applyZoomMultiplier = false;
  379. factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize();
  380. break;
  381. case CSS_PX:
  382. break;
  383. case CSS_CM:
  384. factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
  385. break;
  386. case CSS_MM:
  387. factor = cssPixelsPerInch / 25.4;
  388. break;
  389. case CSS_IN:
  390. factor = cssPixelsPerInch;
  391. break;
  392. case CSS_PT:
  393. factor = cssPixelsPerInch / 72.0;
  394. break;
  395. case CSS_PC:
  396. // 1 pc == 12 pt
  397. factor = cssPixelsPerInch * 12.0 / 72.0;
  398. break;
  399. default:
  400. return -1.0;
  401. }
  402. double result = getDoubleValue() * factor;
  403. if (!applyZoomMultiplier || multiplier == 1.0)
  404. return result;
  405. // Any original result that was >= 1 should not be allowed to fall below 1. This keeps border lines from
  406. // vanishing.
  407. double zoomedResult = result * multiplier;
  408. if (result >= 1.0)
  409. zoomedResult = max(1.0, zoomedResult);
  410. return zoomedResult;
  411. }
  412. void CSSPrimitiveValue::setFloatValue(unsigned short unitType, double floatValue, ExceptionCode& ec)
  413. {
  414. ec = 0;
  415. if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION) {
  416. ec = INVALID_ACCESS_ERR;
  417. return;
  418. }
  419. cleanup();
  420. //if(m_type > CSS_DIMENSION) throw DOMException(INVALID_ACCESS_ERR);
  421. m_value.num = floatValue;
  422. m_type = unitType;
  423. }
  424. static double scaleFactorForConversion(unsigned short unitType)
  425. {
  426. double factor = 1.0;
  427. switch (unitType) {
  428. case CSSPrimitiveValue::CSS_PX:
  429. break;
  430. case CSSPrimitiveValue::CSS_CM:
  431. factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
  432. break;
  433. case CSSPrimitiveValue::CSS_MM:
  434. factor = cssPixelsPerInch / 25.4;
  435. break;
  436. case CSSPrimitiveValue::CSS_IN:
  437. factor = cssPixelsPerInch;
  438. break;
  439. case CSSPrimitiveValue::CSS_PT:
  440. factor = cssPixelsPerInch / 72.0;
  441. break;
  442. case CSSPrimitiveValue::CSS_PC:
  443. factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt
  444. break;
  445. default:
  446. break;
  447. }
  448. return factor;
  449. }
  450. double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec)
  451. {
  452. ec = 0;
  453. if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION) {
  454. ec = INVALID_ACCESS_ERR;
  455. return 0.0;
  456. }
  457. if (unitType == m_type || unitType < CSS_PX || unitType > CSS_PC)
  458. return m_value.num;
  459. double convertedValue = m_value.num;
  460. // First convert the value from m_type into CSSPixels
  461. double factor = scaleFactorForConversion(m_type);
  462. convertedValue *= factor;
  463. // Now convert from CSSPixels to the specified unitType
  464. factor = scaleFactorForConversion(unitType);
  465. convertedValue /= factor;
  466. return convertedValue;
  467. }
  468. double CSSPrimitiveValue::getDoubleValue(unsigned short unitType)
  469. {
  470. if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION)
  471. return 0;
  472. if (unitType == m_type || unitType < CSS_PX || unitType > CSS_PC)
  473. return m_value.num;
  474. double convertedValue = m_value.num;
  475. // First convert the value from m_type into CSSPixels
  476. double factor = scaleFactorForConversion(m_type);
  477. convertedValue *= factor;
  478. // Now convert from CSSPixels to the specified unitType
  479. factor = scaleFactorForConversion(unitType);
  480. convertedValue /= factor;
  481. return convertedValue;
  482. }
  483. void CSSPrimitiveValue::setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode& ec)
  484. {
  485. ec = 0;
  486. if (m_type < CSS_STRING || m_type > CSS_ATTR || stringType < CSS_STRING || stringType > CSS_ATTR) {
  487. ec = INVALID_ACCESS_ERR;
  488. return;
  489. }
  490. cleanup();
  491. if (stringType != CSS_IDENT) {
  492. m_value.string = stringValue.impl();
  493. m_value.string->ref();
  494. m_type = stringType;
  495. }
  496. // FIXME: parse ident
  497. }
  498. String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const
  499. {
  500. ec = 0;
  501. switch (m_type) {
  502. case CSS_STRING:
  503. case CSS_ATTR:
  504. case CSS_URI:
  505. case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
  506. return m_value.string;
  507. case CSS_IDENT:
  508. return valueOrPropertyName(m_value.ident);
  509. default:
  510. ec = INVALID_ACCESS_ERR;
  511. break;
  512. }
  513. return String();
  514. }
  515. String CSSPrimitiveValue::getStringValue() const
  516. {
  517. switch (m_type) {
  518. case CSS_STRING:
  519. case CSS_ATTR:
  520. case CSS_URI:
  521. case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
  522. return m_value.string;
  523. case CSS_IDENT:
  524. return valueOrPropertyName(m_value.ident);
  525. default:
  526. break;
  527. }
  528. return String();
  529. }
  530. Counter* CSSPrimitiveValue::getCounterValue(ExceptionCode& ec) const
  531. {
  532. ec = 0;
  533. if (m_type != CSS_COUNTER) {
  534. ec = INVALID_ACCESS_ERR;
  535. return 0;
  536. }
  537. return m_value.counter;
  538. }
  539. Rect* CSSPrimitiveValue::getRectValue(ExceptionCode& ec) const
  540. {
  541. ec = 0;
  542. if (m_type != CSS_RECT) {
  543. ec = INVALID_ACCESS_ERR;
  544. return 0;
  545. }
  546. return m_value.rect;
  547. }
  548. PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionCode& ec) const
  549. {
  550. ec = 0;
  551. if (m_type != CSS_RGBCOLOR) {
  552. ec = INVALID_ACCESS_ERR;
  553. return 0;
  554. }
  555. // FIMXE: This should not return a new object for each invocation.
  556. return RGBColor::create(m_value.rgbcolor);
  557. }
  558. Pair* CSSPrimitiveValue::getPairValue(ExceptionCode& ec) const
  559. {
  560. ec = 0;
  561. if (m_type != CSS_PAIR) {
  562. ec = INVALID_ACCESS_ERR;
  563. return 0;
  564. }
  565. return m_value.pair;
  566. }
  567. unsigned short CSSPrimitiveValue::cssValueType() const
  568. {
  569. return CSS_PRIMITIVE_VALUE;
  570. }
  571. bool CSSPrimitiveValue::parseString(const String& /*string*/, bool /*strict*/)
  572. {
  573. // FIXME
  574. return false;
  575. }
  576. int CSSPrimitiveValue::getIdent()
  577. {
  578. if (m_type != CSS_IDENT)
  579. return 0;
  580. return m_value.ident;
  581. }
  582. String CSSPrimitiveValue::cssText() const
  583. {
  584. // FIXME: return the original value instead of a generated one (e.g. color
  585. // name if it was specified) - check what spec says about this
  586. String text;
  587. switch (m_type) {
  588. case CSS_UNKNOWN:
  589. // FIXME
  590. break;
  591. case CSS_NUMBER:
  592. case CSS_PARSER_INTEGER:
  593. text = String::number(m_value.num);
  594. break;
  595. case CSS_PERCENTAGE:
  596. text = String::format("%.6lg%%", m_value.num);
  597. break;
  598. case CSS_EMS:
  599. text = String::format("%.6lgem", m_value.num);
  600. break;
  601. case CSS_EXS:
  602. text = String::format("%.6lgex", m_value.num);
  603. break;
  604. case CSS_REMS:
  605. text = String::format("%.6lgrem", m_value.num);
  606. break;
  607. case CSS_PX:
  608. text = String::format("%.6lgpx", m_value.num);
  609. break;
  610. case CSS_CM:
  611. text = String::format("%.6lgcm", m_value.num);
  612. break;
  613. case CSS_MM:
  614. text = String::format("%.6lgmm", m_value.num);
  615. break;
  616. case CSS_IN:
  617. text = String::format("%.6lgin", m_value.num);
  618. break;
  619. case CSS_PT:
  620. text = String::format("%.6lgpt", m_value.num);
  621. break;
  622. case CSS_PC:
  623. text = String::format("%.6lgpc", m_value.num);
  624. break;
  625. case CSS_DEG:
  626. text = String::format("%.6lgdeg", m_value.num);
  627. break;
  628. case CSS_RAD:
  629. text = String::format("%.6lgrad", m_value.num);
  630. break;
  631. case CSS_GRAD:
  632. text = String::format("%.6lggrad", m_value.num);
  633. break;
  634. case CSS_MS:
  635. text = String::format("%.6lgms", m_value.num);
  636. break;
  637. case CSS_S:
  638. text = String::format("%.6lgs", m_value.num);
  639. break;
  640. case CSS_HZ:
  641. text = String::format("%.6lghz", m_value.num);
  642. break;
  643. case CSS_KHZ:
  644. text = String::format("%.6lgkhz", m_value.num);
  645. break;
  646. case CSS_TURN:
  647. text = String::format("%.6lgturn", m_value.num);
  648. break;
  649. case CSS_DIMENSION:
  650. // FIXME
  651. break;
  652. case CSS_STRING:
  653. text = quoteStringIfNeeded(m_value.string);
  654. break;
  655. case CSS_URI:
  656. text = "url(" + quoteURLIfNeeded(m_value.string) + ")";
  657. break;
  658. case CSS_IDENT:
  659. text = valueOrPropertyName(m_value.ident);
  660. break;
  661. case CSS_ATTR: {
  662. DEFINE_STATIC_LOCAL(const String, attrParen, ("attr("));
  663. Vector<UChar> result;
  664. result.reserveInitialCapacity(6 + m_value.string->length());
  665. append(result, attrParen);
  666. append(result, m_value.string);
  667. result.uncheckedAppend(')');
  668. return String::adopt(result);
  669. }
  670. case CSS_COUNTER:
  671. text = "counter(";
  672. text += String::number(m_value.num);
  673. text += ")";
  674. // FIXME: Add list-style and separator
  675. break;
  676. case CSS_RECT: {
  677. DEFINE_STATIC_LOCAL(const String, rectParen, ("rect("));
  678. Rect* rectVal = getRectValue();
  679. Vector<UChar> result;
  680. result.reserveInitialCapacity(32);
  681. append(result, rectParen);
  682. append(result, rectVal->top()->cssText());
  683. result.append(' ');
  684. append(result, rectVal->right()->cssText());
  685. result.append(' ');
  686. append(result, rectVal->bottom()->cssText());
  687. result.append(' ');
  688. append(result, rectVal->left()->cssText());
  689. result.append(')');
  690. return String::adopt(result);
  691. }
  692. case CSS_RGBCOLOR:
  693. case CSS_PARSER_HEXCOLOR: {
  694. DEFINE_STATIC_LOCAL(const String, commaSpace, (", "));
  695. DEFINE_STATIC_LOCAL(const String, rgbParen, ("rgb("));
  696. DEFINE_STATIC_LOCAL(const String, rgbaParen, ("rgba("));
  697. RGBA32 rgbColor = m_value.rgbcolor;
  698. if (m_type == CSS_PARSER_HEXCOLOR)
  699. Color::parseHexColor(m_value.string, rgbColor);
  700. Color color(rgbColor);
  701. Vector<UChar> result;
  702. result.reserveInitialCapacity(32);
  703. if (color.hasAlpha())
  704. append(result, rgbaParen);
  705. else
  706. append(result, rgbParen);
  707. appendNumber(result, static_cast<unsigned char>(color.red()));
  708. append(result, commaSpace);
  709. appendNumber(result, static_cast<unsigned char>(color.green()));
  710. append(result, commaSpace);
  711. appendNumber(result, static_cast<unsigned char>(color.blue()));
  712. if (color.hasAlpha()) {
  713. append(result, commaSpace);
  714. append(result, String::number(static_cast<float>(color.alpha()) / 256.0f));
  715. }
  716. result.append(')');
  717. return String::adopt(result);
  718. }
  719. case CSS_PAIR:
  720. text = m_value.pair->first()->cssText();
  721. text += " ";
  722. text += m_value.pair->second()->cssText();
  723. break;
  724. #if ENABLE(DASHBOARD_SUPPORT)
  725. case CSS_DASHBOARD_REGION:
  726. for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) {
  727. if (!text.isEmpty())
  728. text.append(' ');
  729. text += "dashboard-region(";
  730. text += region->m_label;
  731. if (region->m_isCircle)
  732. text += " circle";
  733. else if (region->m_isRectangle)
  734. text += " rectangle";
  735. else
  736. break;
  737. if (region->top()->m_type == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) {
  738. ASSERT(region->right()->m_type == CSS_IDENT);
  739. ASSERT(region->bottom()->m_type == CSS_IDENT);
  740. ASSERT(region->left()->m_type == CSS_IDENT);
  741. ASSERT(region->right()->getIdent() == CSSValueInvalid);
  742. ASSERT(region->bottom()->getIdent() == CSSValueInvalid);
  743. ASSERT(region->left()->getIdent() == CSSValueInvalid);
  744. } else {
  745. text.append(' ');
  746. text += region->top()->cssText() + " ";
  747. text += region->right()->cssText() + " ";
  748. text += region->bottom()->cssText() + " ";
  749. text += region->left()->cssText();
  750. }
  751. text += ")";
  752. }
  753. break;
  754. #endif
  755. case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
  756. text = "-webkit-var(";
  757. text += m_value.string;
  758. text += ")";
  759. break;
  760. case CSS_PARSER_OPERATOR: {
  761. char c = static_cast<char>(m_value.ident);
  762. text = String(&c, 1U);
  763. break;
  764. }
  765. case CSS_PARSER_IDENTIFIER:
  766. text = quoteStringIfNeeded(m_value.string);
  767. break;
  768. }
  769. return text;
  770. }
  771. CSSParserValue CSSPrimitiveValue::parserValue() const
  772. {
  773. // We only have to handle a subset of types.
  774. CSSParserValue value;
  775. value.id = 0;
  776. value.isInt = false;
  777. value.unit = CSSPrimitiveValue::CSS_IDENT;
  778. switch (m_type) {
  779. case CSS_NUMBER:
  780. case CSS_PERCENTAGE:
  781. case CSS_EMS:
  782. case CSS_EXS:
  783. case CSS_REMS:
  784. case CSS_PX:
  785. case CSS_CM:
  786. case CSS_MM:
  787. case CSS_IN:
  788. case CSS_PT:
  789. case CSS_PC:
  790. case CSS_DEG:
  791. case CSS_RAD:
  792. case CSS_GRAD:
  793. case CSS_MS:
  794. case CSS_S:
  795. case CSS_HZ:
  796. case CSS_KHZ:
  797. case CSS_DIMENSION:
  798. case CSS_TURN:
  799. value.fValue = m_value.num;
  800. value.unit = m_type;
  801. break;
  802. case CSS_STRING:
  803. case CSS_URI:
  804. case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
  805. case CSS_PARSER_HEXCOLOR:
  806. value.string.characters = const_cast<UChar*>(m_value.string->characters());
  807. value.string.length = m_value.string->length();
  808. value.unit = m_type;
  809. break;
  810. case CSS_IDENT: {
  811. value.id = m_value.ident;
  812. String name = valueOrPropertyName(m_value.ident);
  813. value.string.characters = const_cast<UChar*>(name.characters());
  814. value.string.length = name.length();
  815. break;
  816. }
  817. case CSS_PARSER_OPERATOR:
  818. value.iValue = m_value.ident;
  819. value.unit = CSSParserValue::Operator;
  820. break;
  821. case CSS_PARSER_INTEGER:
  822. value.fValue = m_value.num;
  823. value.unit = CSSPrimitiveValue::CSS_NUMBER;
  824. value.isInt = true;
  825. break;
  826. case CSS_PARSER_IDENTIFIER:
  827. value.string.characters = const_cast<UChar*>(m_value.string->characters());
  828. value.string.length = m_value.string->length();
  829. value.unit = CSSPrimitiveValue::CSS_IDENT;
  830. break;
  831. case CSS_UNKNOWN:
  832. case CSS_ATTR:
  833. case CSS_COUNTER:
  834. case CSS_RECT:
  835. case CSS_RGBCOLOR:
  836. case CSS_PAIR:
  837. #if ENABLE(DASHBOARD_SUPPORT)
  838. case CSS_DASHBOARD_REGION:
  839. #endif
  840. ASSERT_NOT_REACHED();
  841. break;
  842. }
  843. return value;
  844. }
  845. void CSSPrimitiveValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet)
  846. {
  847. if (m_type == CSS_URI)
  848. addSubresourceURL(urls, styleSheet->completeURL(m_value.string));
  849. }
  850. } // namespace WebCore