CSSPrimitiveValue.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. /*
  2. * (C) 1999-2003 Lars Knoll (knoll@kde.org)
  3. * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012, 2013 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 "CSSBasicShapes.h"
  23. #include "CSSCalculationValue.h"
  24. #include "CSSHelper.h"
  25. #include "CSSParser.h"
  26. #include "CSSPropertyNames.h"
  27. #include "CSSValueKeywords.h"
  28. #include "CalculationValue.h"
  29. #include "Color.h"
  30. #include "Counter.h"
  31. #include "ExceptionCode.h"
  32. #include "Font.h"
  33. #include "LayoutUnit.h"
  34. #include "Node.h"
  35. #include "Pair.h"
  36. #include "RGBColor.h"
  37. #include "Rect.h"
  38. #include "RenderStyle.h"
  39. #include "StyleSheetContents.h"
  40. #include <wtf/ASCIICType.h>
  41. #include <wtf/DecimalNumber.h>
  42. #include <wtf/StdLibExtras.h>
  43. #include <wtf/text/StringBuffer.h>
  44. #include <wtf/text/StringBuilder.h>
  45. #if ENABLE(DASHBOARD_SUPPORT)
  46. #include "DashboardRegion.h"
  47. #endif
  48. using namespace WTF;
  49. namespace WebCore {
  50. // Max/min values for CSS, needs to slightly smaller/larger than the true max/min values to allow for rounding without overflowing.
  51. // Subtract two (rather than one) to allow for values to be converted to float and back without exceeding the LayoutUnit::max.
  52. const int maxValueForCssLength = INT_MAX / kFixedPointDenominator - 2;
  53. const int minValueForCssLength = INT_MIN / kFixedPointDenominator + 2;
  54. static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::UnitTypes unitType)
  55. {
  56. switch (unitType) {
  57. case CSSPrimitiveValue::CSS_CALC:
  58. case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER:
  59. case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH:
  60. case CSSPrimitiveValue::CSS_CM:
  61. case CSSPrimitiveValue::CSS_DEG:
  62. case CSSPrimitiveValue::CSS_DIMENSION:
  63. #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
  64. case CSSPrimitiveValue::CSS_DPPX:
  65. case CSSPrimitiveValue::CSS_DPI:
  66. case CSSPrimitiveValue::CSS_DPCM:
  67. #endif
  68. case CSSPrimitiveValue::CSS_EMS:
  69. case CSSPrimitiveValue::CSS_EXS:
  70. case CSSPrimitiveValue::CSS_GRAD:
  71. case CSSPrimitiveValue::CSS_HZ:
  72. case CSSPrimitiveValue::CSS_IN:
  73. case CSSPrimitiveValue::CSS_KHZ:
  74. case CSSPrimitiveValue::CSS_MM:
  75. case CSSPrimitiveValue::CSS_MS:
  76. case CSSPrimitiveValue::CSS_NUMBER:
  77. case CSSPrimitiveValue::CSS_PERCENTAGE:
  78. case CSSPrimitiveValue::CSS_PC:
  79. case CSSPrimitiveValue::CSS_PT:
  80. case CSSPrimitiveValue::CSS_PX:
  81. case CSSPrimitiveValue::CSS_RAD:
  82. case CSSPrimitiveValue::CSS_REMS:
  83. case CSSPrimitiveValue::CSS_CHS:
  84. case CSSPrimitiveValue::CSS_S:
  85. case CSSPrimitiveValue::CSS_TURN:
  86. case CSSPrimitiveValue::CSS_VW:
  87. case CSSPrimitiveValue::CSS_VH:
  88. case CSSPrimitiveValue::CSS_VMIN:
  89. case CSSPrimitiveValue::CSS_VMAX:
  90. return true;
  91. case CSSPrimitiveValue::CSS_ATTR:
  92. case CSSPrimitiveValue::CSS_COUNTER:
  93. case CSSPrimitiveValue::CSS_COUNTER_NAME:
  94. #if ENABLE(DASHBOARD_SUPPORT)
  95. case CSSPrimitiveValue::CSS_DASHBOARD_REGION:
  96. #endif
  97. #if !ENABLE(CSS_IMAGE_RESOLUTION) && !ENABLE(RESOLUTION_MEDIA_QUERY)
  98. case CSSPrimitiveValue::CSS_DPPX:
  99. case CSSPrimitiveValue::CSS_DPI:
  100. case CSSPrimitiveValue::CSS_DPCM:
  101. #endif
  102. case CSSPrimitiveValue::CSS_IDENT:
  103. case CSSPrimitiveValue::CSS_PAIR:
  104. case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR:
  105. case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER:
  106. case CSSPrimitiveValue::CSS_PARSER_INTEGER:
  107. case CSSPrimitiveValue::CSS_PARSER_OPERATOR:
  108. case CSSPrimitiveValue::CSS_RECT:
  109. case CSSPrimitiveValue::CSS_QUAD:
  110. case CSSPrimitiveValue::CSS_RGBCOLOR:
  111. case CSSPrimitiveValue::CSS_SHAPE:
  112. case CSSPrimitiveValue::CSS_STRING:
  113. case CSSPrimitiveValue::CSS_UNICODE_RANGE:
  114. case CSSPrimitiveValue::CSS_UNKNOWN:
  115. case CSSPrimitiveValue::CSS_URI:
  116. #if ENABLE(CSS_VARIABLES)
  117. case CSSPrimitiveValue::CSS_VARIABLE_NAME:
  118. #endif
  119. return false;
  120. }
  121. ASSERT_NOT_REACHED();
  122. return false;
  123. }
  124. static CSSPrimitiveValue::UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes type)
  125. {
  126. // Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions
  127. // between CSS_PX and relative lengths (see cssPixelsPerInch comment in CSSHelper.h for the topic treatment).
  128. switch (type) {
  129. case CSSPrimitiveValue::CSS_NUMBER:
  130. return CSSPrimitiveValue::UNumber;
  131. case CSSPrimitiveValue::CSS_PERCENTAGE:
  132. return CSSPrimitiveValue::UPercent;
  133. case CSSPrimitiveValue::CSS_PX:
  134. case CSSPrimitiveValue::CSS_CM:
  135. case CSSPrimitiveValue::CSS_MM:
  136. case CSSPrimitiveValue::CSS_IN:
  137. case CSSPrimitiveValue::CSS_PT:
  138. case CSSPrimitiveValue::CSS_PC:
  139. return CSSPrimitiveValue::ULength;
  140. case CSSPrimitiveValue::CSS_MS:
  141. case CSSPrimitiveValue::CSS_S:
  142. return CSSPrimitiveValue::UTime;
  143. case CSSPrimitiveValue::CSS_DEG:
  144. case CSSPrimitiveValue::CSS_RAD:
  145. case CSSPrimitiveValue::CSS_GRAD:
  146. case CSSPrimitiveValue::CSS_TURN:
  147. return CSSPrimitiveValue::UAngle;
  148. case CSSPrimitiveValue::CSS_HZ:
  149. case CSSPrimitiveValue::CSS_KHZ:
  150. return CSSPrimitiveValue::UFrequency;
  151. case CSSPrimitiveValue::CSS_VW:
  152. case CSSPrimitiveValue::CSS_VH:
  153. case CSSPrimitiveValue::CSS_VMIN:
  154. case CSSPrimitiveValue::CSS_VMAX:
  155. return CSSPrimitiveValue::UViewportPercentageLength;
  156. #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
  157. case CSSPrimitiveValue::CSS_DPPX:
  158. case CSSPrimitiveValue::CSS_DPI:
  159. case CSSPrimitiveValue::CSS_DPCM:
  160. return CSSPrimitiveValue::UResolution;
  161. #endif
  162. default:
  163. return CSSPrimitiveValue::UOther;
  164. }
  165. }
  166. typedef HashMap<const CSSPrimitiveValue*, String> CSSTextCache;
  167. static CSSTextCache& cssTextCache()
  168. {
  169. DEFINE_STATIC_LOCAL(CSSTextCache, cache, ());
  170. return cache;
  171. }
  172. unsigned short CSSPrimitiveValue::primitiveType() const
  173. {
  174. if (m_primitiveUnitType != CSSPrimitiveValue::CSS_CALC)
  175. return m_primitiveUnitType;
  176. switch (m_value.calc->category()) {
  177. case CalcNumber:
  178. return CSSPrimitiveValue::CSS_NUMBER;
  179. case CalcPercent:
  180. return CSSPrimitiveValue::CSS_PERCENTAGE;
  181. case CalcLength:
  182. return CSSPrimitiveValue::CSS_PX;
  183. case CalcPercentNumber:
  184. return CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER;
  185. case CalcPercentLength:
  186. return CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH;
  187. #if ENABLE(CSS_VARIABLES)
  188. case CalcVariable:
  189. return CSSPrimitiveValue::CSS_UNKNOWN; // The type of a calculation containing a variable cannot be known until the value of the variable is determined.
  190. #endif
  191. case CalcOther:
  192. return CSSPrimitiveValue::CSS_UNKNOWN;
  193. }
  194. return CSSPrimitiveValue::CSS_UNKNOWN;
  195. }
  196. static const AtomicString& valueOrPropertyName(int valueOrPropertyID)
  197. {
  198. ASSERT_ARG(valueOrPropertyID, valueOrPropertyID >= 0);
  199. ASSERT_ARG(valueOrPropertyID, valueOrPropertyID < numCSSValueKeywords || (valueOrPropertyID >= firstCSSProperty && valueOrPropertyID < firstCSSProperty + numCSSProperties));
  200. if (valueOrPropertyID < 0)
  201. return nullAtom;
  202. if (valueOrPropertyID < numCSSValueKeywords) {
  203. static AtomicString* keywordStrings = new AtomicString[numCSSValueKeywords]; // Leaked intentionally.
  204. AtomicString& keywordString = keywordStrings[valueOrPropertyID];
  205. if (keywordString.isNull())
  206. keywordString = getValueName(valueOrPropertyID);
  207. return keywordString;
  208. }
  209. return getPropertyNameAtomicString(static_cast<CSSPropertyID>(valueOrPropertyID));
  210. }
  211. CSSPrimitiveValue::CSSPrimitiveValue(int ident)
  212. : CSSValue(PrimitiveClass)
  213. {
  214. m_primitiveUnitType = CSS_IDENT;
  215. m_value.ident = ident;
  216. }
  217. CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type)
  218. : CSSValue(PrimitiveClass)
  219. {
  220. m_primitiveUnitType = type;
  221. ASSERT(std::isfinite(num));
  222. m_value.num = num;
  223. }
  224. CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type)
  225. : CSSValue(PrimitiveClass)
  226. {
  227. m_primitiveUnitType = type;
  228. if ((m_value.string = str.impl()))
  229. m_value.string->ref();
  230. }
  231. CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color)
  232. : CSSValue(PrimitiveClass)
  233. {
  234. m_primitiveUnitType = CSS_RGBCOLOR;
  235. m_value.rgbcolor = color;
  236. }
  237. CSSPrimitiveValue::CSSPrimitiveValue(const Length& length)
  238. : CSSValue(PrimitiveClass)
  239. {
  240. switch (length.type()) {
  241. case Auto:
  242. m_primitiveUnitType = CSS_IDENT;
  243. m_value.ident = CSSValueAuto;
  244. break;
  245. case WebCore::Fixed:
  246. m_primitiveUnitType = CSS_PX;
  247. m_value.num = length.value();
  248. break;
  249. case Intrinsic:
  250. m_primitiveUnitType = CSS_IDENT;
  251. m_value.ident = CSSValueIntrinsic;
  252. break;
  253. case MinIntrinsic:
  254. m_primitiveUnitType = CSS_IDENT;
  255. m_value.ident = CSSValueMinIntrinsic;
  256. break;
  257. case MinContent:
  258. m_primitiveUnitType = CSS_IDENT;
  259. m_value.ident = CSSValueWebkitMinContent;
  260. break;
  261. case MaxContent:
  262. m_primitiveUnitType = CSS_IDENT;
  263. m_value.ident = CSSValueWebkitMaxContent;
  264. break;
  265. case FillAvailable:
  266. m_primitiveUnitType = CSS_IDENT;
  267. m_value.ident = CSSValueWebkitFillAvailable;
  268. break;
  269. case FitContent:
  270. m_primitiveUnitType = CSS_IDENT;
  271. m_value.ident = CSSValueWebkitFitContent;
  272. break;
  273. case Percent:
  274. m_primitiveUnitType = CSS_PERCENTAGE;
  275. ASSERT(std::isfinite(length.percent()));
  276. m_value.num = length.percent();
  277. break;
  278. case ViewportPercentageWidth:
  279. m_primitiveUnitType = CSS_VW;
  280. m_value.num = length.viewportPercentageLength();
  281. break;
  282. case ViewportPercentageHeight:
  283. m_primitiveUnitType = CSS_VH;
  284. m_value.num = length.viewportPercentageLength();
  285. break;
  286. case ViewportPercentageMin:
  287. m_primitiveUnitType = CSS_VMIN;
  288. m_value.num = length.viewportPercentageLength();
  289. break;
  290. case ViewportPercentageMax:
  291. m_primitiveUnitType = CSS_VMAX;
  292. m_value.num = length.viewportPercentageLength();
  293. break;
  294. case Calculated:
  295. case Relative:
  296. case Undefined:
  297. ASSERT_NOT_REACHED();
  298. break;
  299. }
  300. }
  301. void CSSPrimitiveValue::init(PassRefPtr<Counter> c)
  302. {
  303. m_primitiveUnitType = CSS_COUNTER;
  304. m_hasCachedCSSText = false;
  305. m_value.counter = c.leakRef();
  306. }
  307. void CSSPrimitiveValue::init(PassRefPtr<Rect> r)
  308. {
  309. m_primitiveUnitType = CSS_RECT;
  310. m_hasCachedCSSText = false;
  311. m_value.rect = r.leakRef();
  312. }
  313. void CSSPrimitiveValue::init(PassRefPtr<Quad> quad)
  314. {
  315. m_primitiveUnitType = CSS_QUAD;
  316. m_hasCachedCSSText = false;
  317. m_value.quad = quad.leakRef();
  318. }
  319. #if ENABLE(DASHBOARD_SUPPORT)
  320. void CSSPrimitiveValue::init(PassRefPtr<DashboardRegion> r)
  321. {
  322. m_primitiveUnitType = CSS_DASHBOARD_REGION;
  323. m_hasCachedCSSText = false;
  324. m_value.region = r.leakRef();
  325. }
  326. #endif
  327. void CSSPrimitiveValue::init(PassRefPtr<Pair> p)
  328. {
  329. m_primitiveUnitType = CSS_PAIR;
  330. m_hasCachedCSSText = false;
  331. m_value.pair = p.leakRef();
  332. }
  333. void CSSPrimitiveValue::init(PassRefPtr<CSSCalcValue> c)
  334. {
  335. m_primitiveUnitType = CSS_CALC;
  336. m_hasCachedCSSText = false;
  337. m_value.calc = c.leakRef();
  338. }
  339. void CSSPrimitiveValue::init(PassRefPtr<CSSBasicShape> shape)
  340. {
  341. m_primitiveUnitType = CSS_SHAPE;
  342. m_hasCachedCSSText = false;
  343. m_value.shape = shape.leakRef();
  344. }
  345. CSSPrimitiveValue::~CSSPrimitiveValue()
  346. {
  347. cleanup();
  348. }
  349. void CSSPrimitiveValue::cleanup()
  350. {
  351. switch (static_cast<UnitTypes>(m_primitiveUnitType)) {
  352. case CSS_STRING:
  353. case CSS_URI:
  354. case CSS_ATTR:
  355. case CSS_COUNTER_NAME:
  356. #if ENABLE(CSS_VARIABLES)
  357. case CSS_VARIABLE_NAME:
  358. #endif
  359. case CSS_PARSER_HEXCOLOR:
  360. if (m_value.string)
  361. m_value.string->deref();
  362. break;
  363. case CSS_COUNTER:
  364. m_value.counter->deref();
  365. break;
  366. case CSS_RECT:
  367. m_value.rect->deref();
  368. break;
  369. case CSS_QUAD:
  370. m_value.quad->deref();
  371. break;
  372. case CSS_PAIR:
  373. m_value.pair->deref();
  374. break;
  375. #if ENABLE(DASHBOARD_SUPPORT)
  376. case CSS_DASHBOARD_REGION:
  377. if (m_value.region)
  378. m_value.region->deref();
  379. break;
  380. #endif
  381. case CSS_CALC:
  382. m_value.calc->deref();
  383. break;
  384. case CSS_CALC_PERCENTAGE_WITH_NUMBER:
  385. case CSS_CALC_PERCENTAGE_WITH_LENGTH:
  386. ASSERT_NOT_REACHED();
  387. break;
  388. case CSS_SHAPE:
  389. m_value.shape->deref();
  390. break;
  391. case CSS_NUMBER:
  392. case CSS_PARSER_INTEGER:
  393. case CSS_PERCENTAGE:
  394. case CSS_EMS:
  395. case CSS_EXS:
  396. case CSS_REMS:
  397. case CSS_CHS:
  398. case CSS_PX:
  399. case CSS_CM:
  400. case CSS_MM:
  401. case CSS_IN:
  402. case CSS_PT:
  403. case CSS_PC:
  404. case CSS_DEG:
  405. case CSS_RAD:
  406. case CSS_GRAD:
  407. case CSS_MS:
  408. case CSS_S:
  409. case CSS_HZ:
  410. case CSS_KHZ:
  411. case CSS_TURN:
  412. case CSS_VW:
  413. case CSS_VH:
  414. case CSS_VMIN:
  415. case CSS_VMAX:
  416. case CSS_DPPX:
  417. case CSS_DPI:
  418. case CSS_DPCM:
  419. case CSS_IDENT:
  420. case CSS_RGBCOLOR:
  421. case CSS_DIMENSION:
  422. case CSS_UNKNOWN:
  423. case CSS_UNICODE_RANGE:
  424. case CSS_PARSER_OPERATOR:
  425. case CSS_PARSER_IDENTIFIER:
  426. break;
  427. }
  428. m_primitiveUnitType = 0;
  429. if (m_hasCachedCSSText) {
  430. cssTextCache().remove(this);
  431. m_hasCachedCSSText = false;
  432. }
  433. }
  434. double CSSPrimitiveValue::computeDegrees()
  435. {
  436. switch (m_primitiveUnitType) {
  437. case CSS_DEG:
  438. return getDoubleValue();
  439. case CSS_RAD:
  440. return rad2deg(getDoubleValue());
  441. case CSS_GRAD:
  442. return grad2deg(getDoubleValue());
  443. case CSS_TURN:
  444. return turn2deg(getDoubleValue());
  445. default:
  446. ASSERT_NOT_REACHED();
  447. return 0;
  448. }
  449. }
  450. template<> int CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const
  451. {
  452. return roundForImpreciseConversion<int>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize));
  453. }
  454. template<> unsigned CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const
  455. {
  456. return roundForImpreciseConversion<unsigned>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize));
  457. }
  458. template<> Length CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const
  459. {
  460. #if ENABLE(SUBPIXEL_LAYOUT)
  461. return Length(clampTo<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize), minValueForCssLength, maxValueForCssLength), Fixed);
  462. #else
  463. return Length(clampTo<float>(roundForImpreciseConversion<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)), minValueForCssLength, maxValueForCssLength), Fixed);
  464. #endif
  465. }
  466. template<> short CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const
  467. {
  468. return roundForImpreciseConversion<short>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize));
  469. }
  470. template<> unsigned short CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const
  471. {
  472. return roundForImpreciseConversion<unsigned short>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize));
  473. }
  474. template<> float CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const
  475. {
  476. return static_cast<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize));
  477. }
  478. template<> double CSSPrimitiveValue::computeLength(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const
  479. {
  480. return computeLengthDouble(style, rootStyle, multiplier, computingFontSize);
  481. }
  482. double CSSPrimitiveValue::computeLengthDouble(const RenderStyle* style, const RenderStyle* rootStyle, float multiplier, bool computingFontSize) const
  483. {
  484. if (m_primitiveUnitType == CSS_CALC)
  485. // The multiplier and factor is applied to each value in the calc expression individually
  486. return m_value.calc->computeLengthPx(style, rootStyle, multiplier, computingFontSize);
  487. double factor;
  488. switch (primitiveType()) {
  489. case CSS_EMS:
  490. factor = computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize();
  491. break;
  492. case CSS_EXS:
  493. // FIXME: We have a bug right now where the zoom will be applied twice to EX units.
  494. // We really need to compute EX using fontMetrics for the original specifiedSize and not use
  495. // our actual constructed rendering font.
  496. if (style->fontMetrics().hasXHeight())
  497. factor = style->fontMetrics().xHeight();
  498. else
  499. factor = (computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize()) / 2.0;
  500. break;
  501. case CSS_REMS:
  502. if (rootStyle)
  503. factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize();
  504. else
  505. factor = 1.0;
  506. break;
  507. case CSS_CHS:
  508. factor = style->fontMetrics().zeroWidth();
  509. break;
  510. case CSS_PX:
  511. factor = 1.0;
  512. break;
  513. case CSS_CM:
  514. factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
  515. break;
  516. case CSS_MM:
  517. factor = cssPixelsPerInch / 25.4;
  518. break;
  519. case CSS_IN:
  520. factor = cssPixelsPerInch;
  521. break;
  522. case CSS_PT:
  523. factor = cssPixelsPerInch / 72.0;
  524. break;
  525. case CSS_PC:
  526. // 1 pc == 12 pt
  527. factor = cssPixelsPerInch * 12.0 / 72.0;
  528. break;
  529. case CSS_CALC_PERCENTAGE_WITH_LENGTH:
  530. case CSS_CALC_PERCENTAGE_WITH_NUMBER:
  531. ASSERT_NOT_REACHED();
  532. return -1.0;
  533. default:
  534. ASSERT_NOT_REACHED();
  535. return -1.0;
  536. }
  537. // We do not apply the zoom factor when we are computing the value of the font-size property. The zooming
  538. // for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference
  539. // as well as enforcing the implicit "smart minimum."
  540. double result = getDoubleValue() * factor;
  541. if (computingFontSize || isFontRelativeLength())
  542. return result;
  543. return result * multiplier;
  544. }
  545. void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionCode& ec)
  546. {
  547. // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
  548. // No other engine supports mutating style through this API. Computed style is always read-only anyway.
  549. // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
  550. ec = NO_MODIFICATION_ALLOWED_ERR;
  551. }
  552. static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType)
  553. {
  554. double factor = 1.0;
  555. // FIXME: the switch can be replaced by an array of scale factors.
  556. switch (unitType) {
  557. // These are "canonical" units in their respective categories.
  558. case CSSPrimitiveValue::CSS_PX:
  559. case CSSPrimitiveValue::CSS_DEG:
  560. case CSSPrimitiveValue::CSS_MS:
  561. case CSSPrimitiveValue::CSS_HZ:
  562. break;
  563. case CSSPrimitiveValue::CSS_CM:
  564. factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
  565. break;
  566. case CSSPrimitiveValue::CSS_DPCM:
  567. factor = 2.54 / cssPixelsPerInch; // (2.54 cm/in)
  568. break;
  569. case CSSPrimitiveValue::CSS_MM:
  570. factor = cssPixelsPerInch / 25.4;
  571. break;
  572. case CSSPrimitiveValue::CSS_IN:
  573. factor = cssPixelsPerInch;
  574. break;
  575. case CSSPrimitiveValue::CSS_DPI:
  576. factor = 1 / cssPixelsPerInch;
  577. break;
  578. case CSSPrimitiveValue::CSS_PT:
  579. factor = cssPixelsPerInch / 72.0;
  580. break;
  581. case CSSPrimitiveValue::CSS_PC:
  582. factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt
  583. break;
  584. case CSSPrimitiveValue::CSS_RAD:
  585. factor = 180 / piDouble;
  586. break;
  587. case CSSPrimitiveValue::CSS_GRAD:
  588. factor = 0.9;
  589. break;
  590. case CSSPrimitiveValue::CSS_TURN:
  591. factor = 360;
  592. break;
  593. case CSSPrimitiveValue::CSS_S:
  594. case CSSPrimitiveValue::CSS_KHZ:
  595. factor = 1000;
  596. break;
  597. default:
  598. break;
  599. }
  600. return factor;
  601. }
  602. double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec) const
  603. {
  604. double result = 0;
  605. bool success = getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
  606. if (!success) {
  607. ec = INVALID_ACCESS_ERR;
  608. return 0.0;
  609. }
  610. ec = 0;
  611. return result;
  612. }
  613. double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) const
  614. {
  615. double result = 0;
  616. getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
  617. return result;
  618. }
  619. double CSSPrimitiveValue::getDoubleValue() const
  620. {
  621. return m_primitiveUnitType != CSS_CALC ? m_value.num : m_value.calc->doubleValue();
  622. }
  623. CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category)
  624. {
  625. // The canonical unit type is chosen according to the way CSSParser::validUnit() chooses the default unit
  626. // in each category (based on unitflags).
  627. switch (category) {
  628. case UNumber:
  629. return CSS_NUMBER;
  630. case ULength:
  631. return CSS_PX;
  632. case UPercent:
  633. return CSS_UNKNOWN; // Cannot convert between numbers and percent.
  634. case UTime:
  635. return CSS_MS;
  636. case UAngle:
  637. return CSS_DEG;
  638. case UFrequency:
  639. return CSS_HZ;
  640. case UViewportPercentageLength:
  641. return CSS_UNKNOWN; // Cannot convert between numbers and relative lengths.
  642. #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
  643. case UResolution:
  644. return CSS_DPPX;
  645. #endif
  646. default:
  647. return CSS_UNKNOWN;
  648. }
  649. }
  650. bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, double* result) const
  651. {
  652. if (!isValidCSSUnitTypeForDoubleConversion(static_cast<UnitTypes>(m_primitiveUnitType)) || !isValidCSSUnitTypeForDoubleConversion(requestedUnitType))
  653. return false;
  654. UnitTypes sourceUnitType = static_cast<UnitTypes>(primitiveType());
  655. if (requestedUnitType == sourceUnitType || requestedUnitType == CSS_DIMENSION) {
  656. *result = getDoubleValue();
  657. return true;
  658. }
  659. UnitCategory sourceCategory = unitCategory(sourceUnitType);
  660. ASSERT(sourceCategory != UOther);
  661. UnitTypes targetUnitType = requestedUnitType;
  662. UnitCategory targetCategory = unitCategory(targetUnitType);
  663. ASSERT(targetCategory != UOther);
  664. // Cannot convert between unrelated unit categories if one of them is not UNumber.
  665. if (sourceCategory != targetCategory && sourceCategory != UNumber && targetCategory != UNumber)
  666. return false;
  667. if (targetCategory == UNumber) {
  668. // We interpret conversion to CSS_NUMBER as conversion to a canonical unit in this value's category.
  669. targetUnitType = canonicalUnitTypeForCategory(sourceCategory);
  670. if (targetUnitType == CSS_UNKNOWN)
  671. return false;
  672. }
  673. if (sourceUnitType == CSS_NUMBER) {
  674. // We interpret conversion from CSS_NUMBER in the same way as CSSParser::validUnit() while using non-strict mode.
  675. sourceUnitType = canonicalUnitTypeForCategory(targetCategory);
  676. if (sourceUnitType == CSS_UNKNOWN)
  677. return false;
  678. }
  679. double convertedValue = getDoubleValue();
  680. // First convert the value from m_primitiveUnitType to canonical type.
  681. double factor = conversionToCanonicalUnitsScaleFactor(sourceUnitType);
  682. convertedValue *= factor;
  683. // Now convert from canonical type to the target unitType.
  684. factor = conversionToCanonicalUnitsScaleFactor(targetUnitType);
  685. convertedValue /= factor;
  686. *result = convertedValue;
  687. return true;
  688. }
  689. void CSSPrimitiveValue::setStringValue(unsigned short, const String&, ExceptionCode& ec)
  690. {
  691. // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
  692. // No other engine supports mutating style through this API. Computed style is always read-only anyway.
  693. // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
  694. ec = NO_MODIFICATION_ALLOWED_ERR;
  695. }
  696. String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const
  697. {
  698. ec = 0;
  699. switch (m_primitiveUnitType) {
  700. case CSS_STRING:
  701. case CSS_ATTR:
  702. case CSS_URI:
  703. #if ENABLE(CSS_VARIABLES)
  704. case CSS_VARIABLE_NAME:
  705. #endif
  706. return m_value.string;
  707. case CSS_IDENT:
  708. return valueOrPropertyName(m_value.ident);
  709. default:
  710. ec = INVALID_ACCESS_ERR;
  711. break;
  712. }
  713. return String();
  714. }
  715. String CSSPrimitiveValue::getStringValue() const
  716. {
  717. switch (m_primitiveUnitType) {
  718. case CSS_STRING:
  719. case CSS_ATTR:
  720. case CSS_URI:
  721. #if ENABLE(CSS_VARIABLES)
  722. case CSS_VARIABLE_NAME:
  723. #endif
  724. return m_value.string;
  725. case CSS_IDENT:
  726. return valueOrPropertyName(m_value.ident);
  727. default:
  728. break;
  729. }
  730. return String();
  731. }
  732. Counter* CSSPrimitiveValue::getCounterValue(ExceptionCode& ec) const
  733. {
  734. ec = 0;
  735. if (m_primitiveUnitType != CSS_COUNTER) {
  736. ec = INVALID_ACCESS_ERR;
  737. return 0;
  738. }
  739. return m_value.counter;
  740. }
  741. Rect* CSSPrimitiveValue::getRectValue(ExceptionCode& ec) const
  742. {
  743. ec = 0;
  744. if (m_primitiveUnitType != CSS_RECT) {
  745. ec = INVALID_ACCESS_ERR;
  746. return 0;
  747. }
  748. return m_value.rect;
  749. }
  750. Quad* CSSPrimitiveValue::getQuadValue(ExceptionCode& ec) const
  751. {
  752. ec = 0;
  753. if (m_primitiveUnitType != CSS_QUAD) {
  754. ec = INVALID_ACCESS_ERR;
  755. return 0;
  756. }
  757. return m_value.quad;
  758. }
  759. PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionCode& ec) const
  760. {
  761. ec = 0;
  762. if (m_primitiveUnitType != CSS_RGBCOLOR) {
  763. ec = INVALID_ACCESS_ERR;
  764. return 0;
  765. }
  766. // FIMXE: This should not return a new object for each invocation.
  767. return RGBColor::create(m_value.rgbcolor);
  768. }
  769. Pair* CSSPrimitiveValue::getPairValue(ExceptionCode& ec) const
  770. {
  771. ec = 0;
  772. if (m_primitiveUnitType != CSS_PAIR) {
  773. ec = INVALID_ACCESS_ERR;
  774. return 0;
  775. }
  776. return m_value.pair;
  777. }
  778. static String formatNumber(double number, const char* suffix, unsigned suffixLength)
  779. {
  780. DecimalNumber decimal(number);
  781. StringBuffer<LChar> buffer(decimal.bufferLengthForStringDecimal() + suffixLength);
  782. unsigned length = decimal.toStringDecimal(buffer.characters(), buffer.length());
  783. ASSERT(length + suffixLength == buffer.length());
  784. for (unsigned i = 0; i < suffixLength; ++i)
  785. buffer[length + i] = static_cast<LChar>(suffix[i]);
  786. return String::adopt(buffer);
  787. }
  788. template <unsigned characterCount>
  789. ALWAYS_INLINE static String formatNumber(double number, const char (&characters)[characterCount])
  790. {
  791. return formatNumber(number, characters, characterCount - 1);
  792. }
  793. String CSSPrimitiveValue::customCssText() const
  794. {
  795. // FIXME: return the original value instead of a generated one (e.g. color
  796. // name if it was specified) - check what spec says about this
  797. if (m_hasCachedCSSText) {
  798. ASSERT(cssTextCache().contains(this));
  799. return cssTextCache().get(this);
  800. }
  801. String text;
  802. switch (m_primitiveUnitType) {
  803. case CSS_UNKNOWN:
  804. // FIXME
  805. break;
  806. case CSS_NUMBER:
  807. case CSS_PARSER_INTEGER:
  808. text = formatNumber(m_value.num, "");
  809. break;
  810. case CSS_PERCENTAGE:
  811. text = formatNumber(m_value.num, "%");
  812. break;
  813. case CSS_EMS:
  814. text = formatNumber(m_value.num, "em");
  815. break;
  816. case CSS_EXS:
  817. text = formatNumber(m_value.num, "ex");
  818. break;
  819. case CSS_REMS:
  820. text = formatNumber(m_value.num, "rem");
  821. break;
  822. case CSS_CHS:
  823. text = formatNumber(m_value.num, "ch");
  824. break;
  825. case CSS_PX:
  826. text = formatNumber(m_value.num, "px");
  827. break;
  828. case CSS_CM:
  829. text = formatNumber(m_value.num, "cm");
  830. break;
  831. #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
  832. case CSS_DPPX:
  833. text = formatNumber(m_value.num, "dppx");
  834. break;
  835. case CSS_DPI:
  836. text = formatNumber(m_value.num, "dpi");
  837. break;
  838. case CSS_DPCM:
  839. text = formatNumber(m_value.num, "dpcm");
  840. break;
  841. #endif
  842. case CSS_MM:
  843. text = formatNumber(m_value.num, "mm");
  844. break;
  845. case CSS_IN:
  846. text = formatNumber(m_value.num, "in");
  847. break;
  848. case CSS_PT:
  849. text = formatNumber(m_value.num, "pt");
  850. break;
  851. case CSS_PC:
  852. text = formatNumber(m_value.num, "pc");
  853. break;
  854. case CSS_DEG:
  855. text = formatNumber(m_value.num, "deg");
  856. break;
  857. case CSS_RAD:
  858. text = formatNumber(m_value.num, "rad");
  859. break;
  860. case CSS_GRAD:
  861. text = formatNumber(m_value.num, "grad");
  862. break;
  863. case CSS_MS:
  864. text = formatNumber(m_value.num, "ms");
  865. break;
  866. case CSS_S:
  867. text = formatNumber(m_value.num, "s");
  868. break;
  869. case CSS_HZ:
  870. text = formatNumber(m_value.num, "hz");
  871. break;
  872. case CSS_KHZ:
  873. text = formatNumber(m_value.num, "khz");
  874. break;
  875. case CSS_TURN:
  876. text = formatNumber(m_value.num, "turn");
  877. break;
  878. case CSS_DIMENSION:
  879. // FIXME
  880. break;
  881. case CSS_STRING:
  882. text = quoteCSSStringIfNeeded(m_value.string);
  883. break;
  884. case CSS_URI:
  885. text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")";
  886. break;
  887. case CSS_IDENT:
  888. text = valueOrPropertyName(m_value.ident);
  889. break;
  890. case CSS_ATTR: {
  891. StringBuilder result;
  892. result.reserveCapacity(6 + m_value.string->length());
  893. result.appendLiteral("attr(");
  894. result.append(m_value.string);
  895. result.append(')');
  896. text = result.toString();
  897. break;
  898. }
  899. case CSS_COUNTER_NAME:
  900. text = "counter(" + String(m_value.string) + ')';
  901. break;
  902. case CSS_COUNTER: {
  903. StringBuilder result;
  904. String separator = m_value.counter->separator();
  905. if (separator.isEmpty())
  906. result.appendLiteral("counter(");
  907. else
  908. result.appendLiteral("counters(");
  909. result.append(m_value.counter->identifier());
  910. if (!separator.isEmpty()) {
  911. result.appendLiteral(", ");
  912. result.append(quoteCSSStringIfNeeded(separator));
  913. }
  914. String listStyle = m_value.counter->listStyle();
  915. if (!listStyle.isEmpty()) {
  916. result.appendLiteral(", ");
  917. result.append(listStyle);
  918. }
  919. result.append(')');
  920. text = result.toString();
  921. break;
  922. }
  923. case CSS_RECT:
  924. text = getRectValue()->cssText();
  925. break;
  926. case CSS_QUAD:
  927. text = getQuadValue()->cssText();
  928. break;
  929. case CSS_RGBCOLOR:
  930. case CSS_PARSER_HEXCOLOR: {
  931. RGBA32 rgbColor = m_value.rgbcolor;
  932. if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR)
  933. Color::parseHexColor(m_value.string, rgbColor);
  934. Color color(rgbColor);
  935. Vector<LChar> result;
  936. result.reserveInitialCapacity(32);
  937. bool colorHasAlpha = color.hasAlpha();
  938. if (colorHasAlpha)
  939. result.append("rgba(", 5);
  940. else
  941. result.append("rgb(", 4);
  942. appendNumber(result, static_cast<unsigned char>(color.red()));
  943. result.append(", ", 2);
  944. appendNumber(result, static_cast<unsigned char>(color.green()));
  945. result.append(", ", 2);
  946. appendNumber(result, static_cast<unsigned char>(color.blue()));
  947. if (colorHasAlpha) {
  948. result.append(", ", 2);
  949. NumberToStringBuffer buffer;
  950. const char* alphaString = numberToFixedPrecisionString(color.alpha() / 255.0f, 6, buffer, true);
  951. result.append(alphaString, strlen(alphaString));
  952. }
  953. result.append(')');
  954. text = String::adopt(result);
  955. break;
  956. }
  957. case CSS_PAIR:
  958. text = getPairValue()->cssText();
  959. break;
  960. #if ENABLE(DASHBOARD_SUPPORT)
  961. case CSS_DASHBOARD_REGION: {
  962. StringBuilder result;
  963. for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) {
  964. if (!result.isEmpty())
  965. result.append(' ');
  966. result.appendLiteral("dashboard-region(");
  967. result.append(region->m_label);
  968. if (region->m_isCircle)
  969. result.appendLiteral(" circle");
  970. else if (region->m_isRectangle)
  971. result.appendLiteral(" rectangle");
  972. else
  973. break;
  974. if (region->top()->m_primitiveUnitType == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) {
  975. ASSERT(region->right()->m_primitiveUnitType == CSS_IDENT);
  976. ASSERT(region->bottom()->m_primitiveUnitType == CSS_IDENT);
  977. ASSERT(region->left()->m_primitiveUnitType == CSS_IDENT);
  978. ASSERT(region->right()->getIdent() == CSSValueInvalid);
  979. ASSERT(region->bottom()->getIdent() == CSSValueInvalid);
  980. ASSERT(region->left()->getIdent() == CSSValueInvalid);
  981. } else {
  982. result.append(' ');
  983. result.append(region->top()->cssText());
  984. result.append(' ');
  985. result.append(region->right()->cssText());
  986. result.append(' ');
  987. result.append(region->bottom()->cssText());
  988. result.append(' ');
  989. result.append(region->left()->cssText());
  990. }
  991. result.append(')');
  992. }
  993. text = result.toString();
  994. break;
  995. }
  996. #endif
  997. case CSS_PARSER_OPERATOR: {
  998. char c = static_cast<char>(m_value.ident);
  999. text = String(&c, 1U);
  1000. break;
  1001. }
  1002. case CSS_PARSER_IDENTIFIER:
  1003. text = quoteCSSStringIfNeeded(m_value.string);
  1004. break;
  1005. case CSS_CALC:
  1006. text = m_value.calc->cssText();
  1007. break;
  1008. case CSS_SHAPE:
  1009. text = m_value.shape->cssText();
  1010. break;
  1011. case CSS_VW:
  1012. text = formatNumber(m_value.num, "vw");
  1013. break;
  1014. case CSS_VH:
  1015. text = formatNumber(m_value.num, "vh");
  1016. break;
  1017. case CSS_VMIN:
  1018. text = formatNumber(m_value.num, "vmin");
  1019. break;
  1020. case CSS_VMAX:
  1021. text = formatNumber(m_value.num, "vmax");
  1022. break;
  1023. #if ENABLE(CSS_VARIABLES)
  1024. case CSS_VARIABLE_NAME:
  1025. text = "-webkit-var(" + String(m_value.string) + ')';
  1026. break;
  1027. #endif
  1028. }
  1029. ASSERT(!cssTextCache().contains(this));
  1030. cssTextCache().set(this, text);
  1031. m_hasCachedCSSText = true;
  1032. return text;
  1033. }
  1034. #if ENABLE(CSS_VARIABLES)
  1035. String CSSPrimitiveValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
  1036. {
  1037. if (isVariableName() && variables.contains(m_value.string))
  1038. return variables.get(m_value.string);
  1039. if (CSSCalcValue* calcValue = cssCalcValue())
  1040. return calcValue->customSerializeResolvingVariables(variables);
  1041. if (Pair* pairValue = getPairValue())
  1042. return pairValue->serializeResolvingVariables(variables);
  1043. if (Rect* rectVal = getRectValue())
  1044. return rectVal->serializeResolvingVariables(variables);
  1045. if (Quad* quadVal = getQuadValue())
  1046. return quadVal->serializeResolvingVariables(variables);
  1047. if (CSSBasicShape* shapeValue = getShapeValue())
  1048. return shapeValue->serializeResolvingVariables(variables);
  1049. return customCssText();
  1050. }
  1051. bool CSSPrimitiveValue::hasVariableReference() const
  1052. {
  1053. if (CSSCalcValue* calcValue = cssCalcValue())
  1054. return calcValue->hasVariableReference();
  1055. if (Pair* pairValue = getPairValue())
  1056. return pairValue->hasVariableReference();
  1057. if (Quad* quadValue = getQuadValue())
  1058. return quadValue->hasVariableReference();
  1059. if (Rect* rectValue = getRectValue())
  1060. return rectValue->hasVariableReference();
  1061. if (CSSBasicShape* shapeValue = getShapeValue())
  1062. return shapeValue->hasVariableReference();
  1063. return isVariableName();
  1064. }
  1065. #endif
  1066. void CSSPrimitiveValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const
  1067. {
  1068. if (m_primitiveUnitType == CSS_URI)
  1069. addSubresourceURL(urls, styleSheet->completeURL(m_value.string));
  1070. }
  1071. Length CSSPrimitiveValue::viewportPercentageLength() const
  1072. {
  1073. ASSERT(isViewportPercentageLength());
  1074. Length viewportLength;
  1075. switch (m_primitiveUnitType) {
  1076. case CSS_VW:
  1077. viewportLength = Length(getDoubleValue(), ViewportPercentageWidth);
  1078. break;
  1079. case CSS_VH:
  1080. viewportLength = Length(getDoubleValue(), ViewportPercentageHeight);
  1081. break;
  1082. case CSS_VMIN:
  1083. viewportLength = Length(getDoubleValue(), ViewportPercentageMin);
  1084. break;
  1085. case CSS_VMAX:
  1086. viewportLength = Length(getDoubleValue(), ViewportPercentageMax);
  1087. break;
  1088. default:
  1089. break;
  1090. }
  1091. return viewportLength;
  1092. }
  1093. PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::cloneForCSSOM() const
  1094. {
  1095. RefPtr<CSSPrimitiveValue> result;
  1096. switch (m_primitiveUnitType) {
  1097. case CSS_STRING:
  1098. case CSS_URI:
  1099. case CSS_ATTR:
  1100. case CSS_COUNTER_NAME:
  1101. result = CSSPrimitiveValue::create(m_value.string, static_cast<UnitTypes>(m_primitiveUnitType));
  1102. break;
  1103. case CSS_COUNTER:
  1104. result = CSSPrimitiveValue::create(m_value.counter->cloneForCSSOM());
  1105. break;
  1106. case CSS_RECT:
  1107. result = CSSPrimitiveValue::create(m_value.rect->cloneForCSSOM());
  1108. break;
  1109. case CSS_QUAD:
  1110. result = CSSPrimitiveValue::create(m_value.quad->cloneForCSSOM());
  1111. break;
  1112. case CSS_PAIR:
  1113. // Pair is not exposed to the CSSOM, no need for a deep clone.
  1114. result = CSSPrimitiveValue::create(m_value.pair);
  1115. break;
  1116. #if ENABLE(DASHBOARD_SUPPORT)
  1117. case CSS_DASHBOARD_REGION:
  1118. // DashboardRegion is not exposed to the CSSOM, no need for a deep clone.
  1119. result = CSSPrimitiveValue::create(m_value.region);
  1120. break;
  1121. #endif
  1122. case CSS_CALC:
  1123. // CSSCalcValue is not exposed to the CSSOM, no need for a deep clone.
  1124. result = CSSPrimitiveValue::create(m_value.calc);
  1125. break;
  1126. case CSS_SHAPE:
  1127. // CSSShapeValue is not exposed to the CSSOM, no need for a deep clone.
  1128. result = CSSPrimitiveValue::create(m_value.shape);
  1129. break;
  1130. case CSS_NUMBER:
  1131. case CSS_PARSER_INTEGER:
  1132. case CSS_PERCENTAGE:
  1133. case CSS_EMS:
  1134. case CSS_EXS:
  1135. case CSS_REMS:
  1136. case CSS_CHS:
  1137. case CSS_PX:
  1138. case CSS_CM:
  1139. case CSS_MM:
  1140. case CSS_IN:
  1141. case CSS_PT:
  1142. case CSS_PC:
  1143. case CSS_DEG:
  1144. case CSS_RAD:
  1145. case CSS_GRAD:
  1146. case CSS_MS:
  1147. case CSS_S:
  1148. case CSS_HZ:
  1149. case CSS_KHZ:
  1150. case CSS_TURN:
  1151. case CSS_VW:
  1152. case CSS_VH:
  1153. case CSS_VMIN:
  1154. case CSS_VMAX:
  1155. #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
  1156. case CSS_DPPX:
  1157. case CSS_DPI:
  1158. case CSS_DPCM:
  1159. #endif
  1160. result = CSSPrimitiveValue::create(m_value.num, static_cast<UnitTypes>(m_primitiveUnitType));
  1161. break;
  1162. case CSS_IDENT:
  1163. result = CSSPrimitiveValue::createIdentifier(m_value.ident);
  1164. break;
  1165. case CSS_RGBCOLOR:
  1166. result = CSSPrimitiveValue::createColor(m_value.rgbcolor);
  1167. break;
  1168. case CSS_DIMENSION:
  1169. case CSS_UNKNOWN:
  1170. case CSS_PARSER_OPERATOR:
  1171. case CSS_PARSER_IDENTIFIER:
  1172. case CSS_PARSER_HEXCOLOR:
  1173. ASSERT_NOT_REACHED();
  1174. break;
  1175. }
  1176. if (result)
  1177. result->setCSSOMSafe();
  1178. return result;
  1179. }
  1180. bool CSSPrimitiveValue::equals(const CSSPrimitiveValue& other) const
  1181. {
  1182. if (m_primitiveUnitType != other.m_primitiveUnitType)
  1183. return false;
  1184. switch (m_primitiveUnitType) {
  1185. case CSS_UNKNOWN:
  1186. return false;
  1187. case CSS_NUMBER:
  1188. case CSS_PARSER_INTEGER:
  1189. case CSS_PERCENTAGE:
  1190. case CSS_EMS:
  1191. case CSS_EXS:
  1192. case CSS_REMS:
  1193. case CSS_PX:
  1194. case CSS_CM:
  1195. #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
  1196. case CSS_DPPX:
  1197. case CSS_DPI:
  1198. case CSS_DPCM:
  1199. #endif
  1200. case CSS_MM:
  1201. case CSS_IN:
  1202. case CSS_PT:
  1203. case CSS_PC:
  1204. case CSS_DEG:
  1205. case CSS_RAD:
  1206. case CSS_GRAD:
  1207. case CSS_MS:
  1208. case CSS_S:
  1209. case CSS_HZ:
  1210. case CSS_KHZ:
  1211. case CSS_TURN:
  1212. case CSS_VW:
  1213. case CSS_VH:
  1214. case CSS_VMIN:
  1215. case CSS_DIMENSION:
  1216. return m_value.num == other.m_value.num;
  1217. case CSS_IDENT:
  1218. return valueOrPropertyName(m_value.ident) == valueOrPropertyName(other.m_value.ident);
  1219. case CSS_STRING:
  1220. case CSS_URI:
  1221. case CSS_ATTR:
  1222. case CSS_COUNTER_NAME:
  1223. case CSS_PARSER_IDENTIFIER:
  1224. case CSS_PARSER_HEXCOLOR:
  1225. #if ENABLE(CSS_VARIABLES)
  1226. case CSS_VARIABLE_NAME:
  1227. #endif
  1228. return equal(m_value.string, other.m_value.string);
  1229. case CSS_COUNTER:
  1230. return m_value.counter && other.m_value.counter && m_value.counter->equals(*other.m_value.counter);
  1231. case CSS_RECT:
  1232. return m_value.rect && other.m_value.rect && m_value.rect->equals(*other.m_value.rect);
  1233. case CSS_QUAD:
  1234. return m_value.quad && other.m_value.quad && m_value.quad->equals(*other.m_value.quad);
  1235. case CSS_RGBCOLOR:
  1236. return m_value.rgbcolor == other.m_value.rgbcolor;
  1237. case CSS_PAIR:
  1238. return m_value.pair && other.m_value.pair && m_value.pair->equals(*other.m_value.pair);
  1239. #if ENABLE(DASHBOARD_SUPPORT)
  1240. case CSS_DASHBOARD_REGION: {
  1241. DashboardRegion* region = getDashboardRegionValue();
  1242. DashboardRegion* otherRegion = other.getDashboardRegionValue();
  1243. return region ? otherRegion && region->equals(*otherRegion) : !otherRegion;
  1244. }
  1245. #endif
  1246. case CSS_PARSER_OPERATOR:
  1247. return m_value.ident == other.m_value.ident;
  1248. case CSS_CALC:
  1249. return m_value.calc && other.m_value.calc && m_value.calc->equals(*other.m_value.calc);
  1250. case CSS_SHAPE:
  1251. return m_value.shape && other.m_value.shape && m_value.shape->equals(*other.m_value.shape);
  1252. }
  1253. return false;
  1254. }
  1255. } // namespace WebCore