StyleValue.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
  4. * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/ByteBuffer.h>
  9. #include <LibGfx/Palette.h>
  10. #include <LibWeb/CSS/Serialize.h>
  11. #include <LibWeb/CSS/StyleValue.h>
  12. #include <LibWeb/DOM/Document.h>
  13. #include <LibWeb/HTML/BrowsingContext.h>
  14. #include <LibWeb/Loader/LoadRequest.h>
  15. #include <LibWeb/Loader/ResourceLoader.h>
  16. #include <LibWeb/Page/Page.h>
  17. namespace Web::CSS {
  18. StyleValue::StyleValue(Type type)
  19. : m_type(type)
  20. {
  21. }
  22. StyleValue::~StyleValue()
  23. {
  24. }
  25. BackgroundStyleValue const& StyleValue::as_background() const
  26. {
  27. VERIFY(is_background());
  28. return static_cast<BackgroundStyleValue const&>(*this);
  29. }
  30. BackgroundRepeatStyleValue const& StyleValue::as_background_repeat() const
  31. {
  32. VERIFY(is_background_repeat());
  33. return static_cast<BackgroundRepeatStyleValue const&>(*this);
  34. }
  35. BackgroundSizeStyleValue const& StyleValue::as_background_size() const
  36. {
  37. VERIFY(is_background_size());
  38. return static_cast<BackgroundSizeStyleValue const&>(*this);
  39. }
  40. BorderStyleValue const& StyleValue::as_border() const
  41. {
  42. VERIFY(is_border());
  43. return static_cast<BorderStyleValue const&>(*this);
  44. }
  45. BorderRadiusStyleValue const& StyleValue::as_border_radius() const
  46. {
  47. VERIFY(is_border_radius());
  48. return static_cast<BorderRadiusStyleValue const&>(*this);
  49. }
  50. BoxShadowStyleValue const& StyleValue::as_box_shadow() const
  51. {
  52. VERIFY(is_box_shadow());
  53. return static_cast<BoxShadowStyleValue const&>(*this);
  54. }
  55. CalculatedStyleValue const& StyleValue::as_calculated() const
  56. {
  57. VERIFY(is_calculated());
  58. return static_cast<CalculatedStyleValue const&>(*this);
  59. }
  60. ColorStyleValue const& StyleValue::as_color() const
  61. {
  62. VERIFY(is_color());
  63. return static_cast<ColorStyleValue const&>(*this);
  64. }
  65. FlexStyleValue const& StyleValue::as_flex() const
  66. {
  67. VERIFY(is_flex());
  68. return static_cast<FlexStyleValue const&>(*this);
  69. }
  70. FlexFlowStyleValue const& StyleValue::as_flex_flow() const
  71. {
  72. VERIFY(is_flex_flow());
  73. return static_cast<FlexFlowStyleValue const&>(*this);
  74. }
  75. FontStyleValue const& StyleValue::as_font() const
  76. {
  77. VERIFY(is_font());
  78. return static_cast<FontStyleValue const&>(*this);
  79. }
  80. IdentifierStyleValue const& StyleValue::as_identifier() const
  81. {
  82. VERIFY(is_identifier());
  83. return static_cast<IdentifierStyleValue const&>(*this);
  84. }
  85. ImageStyleValue const& StyleValue::as_image() const
  86. {
  87. VERIFY(is_image());
  88. return static_cast<ImageStyleValue const&>(*this);
  89. }
  90. InheritStyleValue const& StyleValue::as_inherit() const
  91. {
  92. VERIFY(is_inherit());
  93. return static_cast<InheritStyleValue const&>(*this);
  94. }
  95. InitialStyleValue const& StyleValue::as_initial() const
  96. {
  97. VERIFY(is_initial());
  98. return static_cast<InitialStyleValue const&>(*this);
  99. }
  100. LengthStyleValue const& StyleValue::as_length() const
  101. {
  102. VERIFY(is_length());
  103. return static_cast<LengthStyleValue const&>(*this);
  104. }
  105. ListStyleStyleValue const& StyleValue::as_list_style() const
  106. {
  107. VERIFY(is_list_style());
  108. return static_cast<ListStyleStyleValue const&>(*this);
  109. }
  110. NumericStyleValue const& StyleValue::as_numeric() const
  111. {
  112. VERIFY(is_numeric());
  113. return static_cast<NumericStyleValue const&>(*this);
  114. }
  115. OverflowStyleValue const& StyleValue::as_overflow() const
  116. {
  117. VERIFY(is_overflow());
  118. return static_cast<OverflowStyleValue const&>(*this);
  119. }
  120. PercentageStyleValue const& StyleValue::as_percentage() const
  121. {
  122. VERIFY(is_percentage());
  123. return static_cast<PercentageStyleValue const&>(*this);
  124. }
  125. PositionStyleValue const& StyleValue::as_position() const
  126. {
  127. VERIFY(is_position());
  128. return static_cast<PositionStyleValue const&>(*this);
  129. }
  130. StringStyleValue const& StyleValue::as_string() const
  131. {
  132. VERIFY(is_string());
  133. return static_cast<StringStyleValue const&>(*this);
  134. }
  135. TextDecorationStyleValue const& StyleValue::as_text_decoration() const
  136. {
  137. VERIFY(is_text_decoration());
  138. return static_cast<TextDecorationStyleValue const&>(*this);
  139. }
  140. TransformationStyleValue const& StyleValue::as_transformation() const
  141. {
  142. VERIFY(is_transformation());
  143. return static_cast<TransformationStyleValue const&>(*this);
  144. }
  145. UnresolvedStyleValue const& StyleValue::as_unresolved() const
  146. {
  147. VERIFY(is_unresolved());
  148. return static_cast<UnresolvedStyleValue const&>(*this);
  149. }
  150. UnsetStyleValue const& StyleValue::as_unset() const
  151. {
  152. VERIFY(is_unset());
  153. return static_cast<UnsetStyleValue const&>(*this);
  154. }
  155. StyleValueList const& StyleValue::as_value_list() const
  156. {
  157. VERIFY(is_value_list());
  158. return static_cast<StyleValueList const&>(*this);
  159. }
  160. BackgroundStyleValue::BackgroundStyleValue(
  161. NonnullRefPtr<StyleValue> color,
  162. NonnullRefPtr<StyleValue> image,
  163. NonnullRefPtr<StyleValue> position,
  164. NonnullRefPtr<StyleValue> size,
  165. NonnullRefPtr<StyleValue> repeat,
  166. NonnullRefPtr<StyleValue> attachment,
  167. NonnullRefPtr<StyleValue> origin,
  168. NonnullRefPtr<StyleValue> clip)
  169. : StyleValue(Type::Background)
  170. , m_color(color)
  171. , m_image(image)
  172. , m_position(position)
  173. , m_size(size)
  174. , m_repeat(repeat)
  175. , m_attachment(attachment)
  176. , m_origin(origin)
  177. , m_clip(clip)
  178. {
  179. auto layer_count = [](auto style_value) -> size_t {
  180. if (style_value->is_value_list())
  181. return style_value->as_value_list().size();
  182. else
  183. return 1;
  184. };
  185. m_layer_count = max(layer_count(m_image), layer_count(m_position));
  186. m_layer_count = max(m_layer_count, layer_count(m_size));
  187. m_layer_count = max(m_layer_count, layer_count(m_repeat));
  188. m_layer_count = max(m_layer_count, layer_count(m_attachment));
  189. m_layer_count = max(m_layer_count, layer_count(m_origin));
  190. m_layer_count = max(m_layer_count, layer_count(m_clip));
  191. VERIFY(!m_color->is_value_list());
  192. }
  193. String BackgroundStyleValue::to_string() const
  194. {
  195. if (m_layer_count == 1) {
  196. return String::formatted("{} {} {} {} {} {} {} {}", m_color->to_string(), m_image->to_string(), m_position->to_string(), m_size->to_string(), m_repeat->to_string(), m_attachment->to_string(), m_origin->to_string(), m_clip->to_string());
  197. }
  198. auto get_layer_value_string = [](NonnullRefPtr<StyleValue> const& style_value, size_t index) {
  199. if (style_value->is_value_list())
  200. return style_value->as_value_list().value_at(index, true)->to_string();
  201. return style_value->to_string();
  202. };
  203. StringBuilder builder;
  204. for (size_t i = 0; i < m_layer_count; i++) {
  205. if (i)
  206. builder.append(", ");
  207. if (i == m_layer_count - 1)
  208. builder.appendff("{} ", m_color->to_string());
  209. builder.appendff("{} {} {} {} {} {} {}", get_layer_value_string(m_image, i), get_layer_value_string(m_position, i), get_layer_value_string(m_size, i), get_layer_value_string(m_repeat, i), get_layer_value_string(m_attachment, i), get_layer_value_string(m_origin, i), get_layer_value_string(m_clip, i));
  210. }
  211. return builder.to_string();
  212. }
  213. String BackgroundRepeatStyleValue::to_string() const
  214. {
  215. return String::formatted("{} {}", CSS::to_string(m_repeat_x), CSS::to_string(m_repeat_y));
  216. }
  217. String BackgroundSizeStyleValue::to_string() const
  218. {
  219. return String::formatted("{} {}", m_size_x.to_string(), m_size_y.to_string());
  220. }
  221. String BorderStyleValue::to_string() const
  222. {
  223. return String::formatted("{} {} {}", m_border_width->to_string(), m_border_style->to_string(), m_border_color->to_string());
  224. }
  225. String BorderRadiusStyleValue::to_string() const
  226. {
  227. return String::formatted("{} / {}", m_horizontal_radius.to_string(), m_vertical_radius.to_string());
  228. }
  229. String BoxShadowStyleValue::to_string() const
  230. {
  231. return String::formatted("{} {} {} {}", m_offset_x.to_string(), m_offset_y.to_string(), m_blur_radius.to_string(), m_color.to_string());
  232. }
  233. static float resolve_calc_value(CalculatedStyleValue::CalcValue const& calc_value, Layout::Node const& layout_node);
  234. static float resolve_calc_number_value(CalculatedStyleValue::CalcNumberValue const&);
  235. static float resolve_calc_product(NonnullOwnPtr<CalculatedStyleValue::CalcProduct> const& calc_product, Layout::Node const& layout_node);
  236. static float resolve_calc_sum(NonnullOwnPtr<CalculatedStyleValue::CalcSum> const& calc_sum, Layout::Node const& layout_node);
  237. static float resolve_calc_number_sum(NonnullOwnPtr<CalculatedStyleValue::CalcNumberSum> const&);
  238. static float resolve_calc_number_product(NonnullOwnPtr<CalculatedStyleValue::CalcNumberProduct> const&);
  239. Optional<Length> CalculatedStyleValue::resolve_length(Layout::Node const& layout_node) const
  240. {
  241. auto length = resolve_calc_sum(m_expression, layout_node);
  242. return Length::make_px(length);
  243. }
  244. static float resolve_calc_value(CalculatedStyleValue::CalcValue const& calc_value, Layout::Node const& layout_node)
  245. {
  246. return calc_value.value.visit(
  247. [](float value) { return value; },
  248. [&](Length const& length) {
  249. return length.resolved_or_zero(layout_node).to_px(layout_node);
  250. },
  251. [&](NonnullOwnPtr<CalculatedStyleValue::CalcSum> const& calc_sum) {
  252. return resolve_calc_sum(calc_sum, layout_node);
  253. },
  254. [](auto&) {
  255. VERIFY_NOT_REACHED();
  256. return 0.0f;
  257. });
  258. }
  259. static float resolve_calc_number_product(NonnullOwnPtr<CalculatedStyleValue::CalcNumberProduct> const& calc_number_product)
  260. {
  261. auto value = resolve_calc_number_value(calc_number_product->first_calc_number_value);
  262. for (auto& additional_number_value : calc_number_product->zero_or_more_additional_calc_number_values) {
  263. auto additional_value = resolve_calc_number_value(additional_number_value.value);
  264. if (additional_number_value.op == CalculatedStyleValue::ProductOperation::Multiply)
  265. value *= additional_value;
  266. else if (additional_number_value.op == CalculatedStyleValue::ProductOperation::Divide)
  267. value /= additional_value;
  268. else
  269. VERIFY_NOT_REACHED();
  270. }
  271. return value;
  272. }
  273. static float resolve_calc_number_sum(NonnullOwnPtr<CalculatedStyleValue::CalcNumberSum> const& calc_number_sum)
  274. {
  275. auto value = resolve_calc_number_product(calc_number_sum->first_calc_number_product);
  276. for (auto& additional_product : calc_number_sum->zero_or_more_additional_calc_number_products) {
  277. auto additional_value = resolve_calc_number_product(additional_product.value);
  278. if (additional_product.op == CSS::CalculatedStyleValue::SumOperation::Add)
  279. value += additional_value;
  280. else if (additional_product.op == CSS::CalculatedStyleValue::SumOperation::Subtract)
  281. value -= additional_value;
  282. else
  283. VERIFY_NOT_REACHED();
  284. }
  285. return value;
  286. }
  287. static float resolve_calc_number_value(CalculatedStyleValue::CalcNumberValue const& number_value)
  288. {
  289. return number_value.value.visit(
  290. [](float number) { return number; },
  291. [](NonnullOwnPtr<CalculatedStyleValue::CalcNumberSum> const& calc_number_sum) {
  292. return resolve_calc_number_sum(calc_number_sum);
  293. });
  294. }
  295. static float resolve_calc_product(NonnullOwnPtr<CalculatedStyleValue::CalcProduct> const& calc_product, Layout::Node const& layout_node)
  296. {
  297. auto value = resolve_calc_value(calc_product->first_calc_value, layout_node);
  298. for (auto& additional_value : calc_product->zero_or_more_additional_calc_values) {
  299. additional_value.value.visit(
  300. [&](CalculatedStyleValue::CalcValue const& calc_value) {
  301. if (additional_value.op != CalculatedStyleValue::ProductOperation::Multiply)
  302. VERIFY_NOT_REACHED();
  303. auto resolved_value = resolve_calc_value(calc_value, layout_node);
  304. value *= resolved_value;
  305. },
  306. [&](CalculatedStyleValue::CalcNumberValue const& calc_number_value) {
  307. if (additional_value.op != CalculatedStyleValue::ProductOperation::Divide)
  308. VERIFY_NOT_REACHED();
  309. auto resolved_calc_number_value = resolve_calc_number_value(calc_number_value);
  310. value /= resolved_calc_number_value;
  311. });
  312. }
  313. return value;
  314. }
  315. static float resolve_calc_sum(NonnullOwnPtr<CalculatedStyleValue::CalcSum> const& calc_sum, Layout::Node const& layout_node)
  316. {
  317. auto value = resolve_calc_product(calc_sum->first_calc_product, layout_node);
  318. for (auto& additional_product : calc_sum->zero_or_more_additional_calc_products) {
  319. auto additional_value = resolve_calc_product(additional_product.value, layout_node);
  320. if (additional_product.op == CalculatedStyleValue::SumOperation::Add)
  321. value += additional_value;
  322. else if (additional_product.op == CalculatedStyleValue::SumOperation::Subtract)
  323. value -= additional_value;
  324. else
  325. VERIFY_NOT_REACHED();
  326. }
  327. return value;
  328. }
  329. static bool is_number(CalculatedStyleValue::ResolvedType type)
  330. {
  331. return type == CalculatedStyleValue::ResolvedType::Number || type == CalculatedStyleValue::ResolvedType::Integer;
  332. }
  333. static bool is_dimension(CalculatedStyleValue::ResolvedType type)
  334. {
  335. return type != CalculatedStyleValue::ResolvedType::Number
  336. && type != CalculatedStyleValue::ResolvedType::Integer
  337. && type != CalculatedStyleValue::ResolvedType::Percentage;
  338. }
  339. template<typename SumWithOperator>
  340. static Optional<CalculatedStyleValue::ResolvedType> resolve_sum_type(CalculatedStyleValue::ResolvedType first_type, NonnullOwnPtrVector<SumWithOperator> const& zero_or_more_additional_products)
  341. {
  342. auto type = first_type;
  343. for (auto const& product : zero_or_more_additional_products) {
  344. auto maybe_product_type = product.resolved_type();
  345. if (!maybe_product_type.has_value())
  346. return {};
  347. auto product_type = maybe_product_type.value();
  348. // At + or -, check that both sides have the same type, or that one side is a <number> and the other is an <integer>.
  349. // If both sides are the same type, resolve to that type.
  350. if (product_type == type)
  351. continue;
  352. // If one side is a <number> and the other is an <integer>, resolve to <number>.
  353. if (is_number(type) && is_number(product_type)) {
  354. type = CalculatedStyleValue::ResolvedType::Number;
  355. continue;
  356. }
  357. // FIXME: calc() handles <percentage> by allowing them to pretend to be whatever <dimension> type is allowed at this location.
  358. // Since we can't easily check what that type is, we just allow <percentage> to combine with any other <dimension> type.
  359. if (type == CalculatedStyleValue::ResolvedType::Percentage && is_dimension(product_type)) {
  360. type = product_type;
  361. continue;
  362. }
  363. if (is_dimension(type) && product_type == CalculatedStyleValue::ResolvedType::Percentage)
  364. continue;
  365. return {};
  366. }
  367. return type;
  368. }
  369. Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcSum::resolved_type() const
  370. {
  371. auto maybe_type = first_calc_product->resolved_type();
  372. if (!maybe_type.has_value())
  373. return {};
  374. auto type = maybe_type.value();
  375. return resolve_sum_type(type, zero_or_more_additional_calc_products);
  376. }
  377. Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcNumberSum::resolved_type() const
  378. {
  379. auto maybe_type = first_calc_number_product->resolved_type();
  380. if (!maybe_type.has_value())
  381. return {};
  382. auto type = maybe_type.value();
  383. return resolve_sum_type(type, zero_or_more_additional_calc_number_products);
  384. }
  385. template<typename ProductWithOperator>
  386. static Optional<CalculatedStyleValue::ResolvedType> resolve_product_type(CalculatedStyleValue::ResolvedType first_type, NonnullOwnPtrVector<ProductWithOperator> const& zero_or_more_additional_values)
  387. {
  388. auto type = first_type;
  389. for (auto const& value : zero_or_more_additional_values) {
  390. auto maybe_value_type = value.resolved_type();
  391. if (!maybe_value_type.has_value())
  392. return {};
  393. auto value_type = maybe_value_type.value();
  394. if (value.op == CalculatedStyleValue::ProductOperation::Multiply) {
  395. // At *, check that at least one side is <number>.
  396. if (!(is_number(type) || is_number(value_type)))
  397. return {};
  398. // If both sides are <integer>, resolve to <integer>.
  399. if (type == CalculatedStyleValue::ResolvedType::Integer && value_type == CalculatedStyleValue::ResolvedType::Integer) {
  400. type = CalculatedStyleValue::ResolvedType::Integer;
  401. } else {
  402. // Otherwise, resolve to the type of the other side.
  403. if (is_number(type))
  404. type = value_type;
  405. }
  406. continue;
  407. } else {
  408. VERIFY(value.op == CalculatedStyleValue::ProductOperation::Divide);
  409. // At /, check that the right side is <number>.
  410. if (!is_number(value_type))
  411. return {};
  412. // If the left side is <integer>, resolve to <number>.
  413. if (type == CalculatedStyleValue::ResolvedType::Integer) {
  414. type = CalculatedStyleValue::ResolvedType::Number;
  415. } else {
  416. // Otherwise, resolve to the type of the left side.
  417. }
  418. // FIXME: Division by zero makes the whole calc() expression invalid.
  419. }
  420. }
  421. return type;
  422. }
  423. Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcProduct::resolved_type() const
  424. {
  425. auto maybe_type = first_calc_value.resolved_type();
  426. if (!maybe_type.has_value())
  427. return {};
  428. auto type = maybe_type.value();
  429. return resolve_product_type(type, zero_or_more_additional_calc_values);
  430. }
  431. Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcSumPartWithOperator::resolved_type() const
  432. {
  433. return value->resolved_type();
  434. }
  435. Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcNumberProduct::resolved_type() const
  436. {
  437. auto maybe_type = first_calc_number_value.resolved_type();
  438. if (!maybe_type.has_value())
  439. return {};
  440. auto type = maybe_type.value();
  441. return resolve_product_type(type, zero_or_more_additional_calc_number_values);
  442. }
  443. Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcNumberProductPartWithOperator::resolved_type() const
  444. {
  445. return value.resolved_type();
  446. }
  447. Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcNumberSumPartWithOperator::resolved_type() const
  448. {
  449. return value->resolved_type();
  450. }
  451. Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcProductPartWithOperator::resolved_type() const
  452. {
  453. return value.visit(
  454. [](CalcValue const& calc_value) {
  455. return calc_value.resolved_type();
  456. },
  457. [](CalcNumberValue const& calc_number_value) {
  458. return calc_number_value.resolved_type();
  459. });
  460. }
  461. Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcValue::resolved_type() const
  462. {
  463. return value.visit(
  464. [](float) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Number }; },
  465. [](Length const&) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Length }; },
  466. [](NonnullOwnPtr<CalcSum> const& sum) { return sum->resolved_type(); });
  467. }
  468. Optional<CalculatedStyleValue::ResolvedType> CalculatedStyleValue::CalcNumberValue::resolved_type() const
  469. {
  470. return value.visit(
  471. [](float) -> Optional<CalculatedStyleValue::ResolvedType> { return { ResolvedType::Number }; },
  472. [](NonnullOwnPtr<CalcNumberSum> const& sum) { return sum->resolved_type(); });
  473. }
  474. // https://www.w3.org/TR/css-color-4/#serializing-sRGB-values
  475. String ColorStyleValue::to_string() const
  476. {
  477. if (m_color.alpha() == 1)
  478. return String::formatted("rgb({}, {}, {})", m_color.red(), m_color.green(), m_color.blue());
  479. return String::formatted("rgba({}, {}, {}, {})", m_color.red(), m_color.green(), m_color.blue(), (float)(m_color.alpha()) / 255.0f);
  480. }
  481. String CombinedBorderRadiusStyleValue::to_string() const
  482. {
  483. return String::formatted("{} {} {} {} / {} {} {} {}", m_top_left->horizontal_radius().to_string(), m_top_right->horizontal_radius().to_string(), m_bottom_right->horizontal_radius().to_string(), m_bottom_left->horizontal_radius().to_string(), m_top_left->vertical_radius().to_string(), m_top_right->vertical_radius().to_string(), m_bottom_right->vertical_radius().to_string(), m_bottom_left->vertical_radius().to_string());
  484. }
  485. String FlexStyleValue::to_string() const
  486. {
  487. return String::formatted("{} {} {}", m_grow->to_string(), m_shrink->to_string(), m_basis->to_string());
  488. }
  489. String FlexFlowStyleValue::to_string() const
  490. {
  491. return String::formatted("{} {}", m_flex_direction->to_string(), m_flex_wrap->to_string());
  492. }
  493. String FontStyleValue::to_string() const
  494. {
  495. return String::formatted("{} {} {} / {} {}", m_font_style->to_string(), m_font_weight->to_string(), m_font_size->to_string(), m_line_height->to_string(), m_font_families->to_string());
  496. }
  497. String IdentifierStyleValue::to_string() const
  498. {
  499. return CSS::string_from_value_id(m_id);
  500. }
  501. bool IdentifierStyleValue::has_color() const
  502. {
  503. switch (m_id) {
  504. case ValueID::Currentcolor:
  505. case ValueID::LibwebLink:
  506. case ValueID::LibwebPaletteActiveLink:
  507. case ValueID::LibwebPaletteActiveWindowBorder1:
  508. case ValueID::LibwebPaletteActiveWindowBorder2:
  509. case ValueID::LibwebPaletteActiveWindowTitle:
  510. case ValueID::LibwebPaletteBase:
  511. case ValueID::LibwebPaletteBaseText:
  512. case ValueID::LibwebPaletteButton:
  513. case ValueID::LibwebPaletteButtonText:
  514. case ValueID::LibwebPaletteDesktopBackground:
  515. case ValueID::LibwebPaletteFocusOutline:
  516. case ValueID::LibwebPaletteHighlightWindowBorder1:
  517. case ValueID::LibwebPaletteHighlightWindowBorder2:
  518. case ValueID::LibwebPaletteHighlightWindowTitle:
  519. case ValueID::LibwebPaletteHoverHighlight:
  520. case ValueID::LibwebPaletteInactiveSelection:
  521. case ValueID::LibwebPaletteInactiveSelectionText:
  522. case ValueID::LibwebPaletteInactiveWindowBorder1:
  523. case ValueID::LibwebPaletteInactiveWindowBorder2:
  524. case ValueID::LibwebPaletteInactiveWindowTitle:
  525. case ValueID::LibwebPaletteLink:
  526. case ValueID::LibwebPaletteMenuBase:
  527. case ValueID::LibwebPaletteMenuBaseText:
  528. case ValueID::LibwebPaletteMenuSelection:
  529. case ValueID::LibwebPaletteMenuSelectionText:
  530. case ValueID::LibwebPaletteMenuStripe:
  531. case ValueID::LibwebPaletteMovingWindowBorder1:
  532. case ValueID::LibwebPaletteMovingWindowBorder2:
  533. case ValueID::LibwebPaletteMovingWindowTitle:
  534. case ValueID::LibwebPaletteRubberBandBorder:
  535. case ValueID::LibwebPaletteRubberBandFill:
  536. case ValueID::LibwebPaletteRuler:
  537. case ValueID::LibwebPaletteRulerActiveText:
  538. case ValueID::LibwebPaletteRulerBorder:
  539. case ValueID::LibwebPaletteRulerInactiveText:
  540. case ValueID::LibwebPaletteSelection:
  541. case ValueID::LibwebPaletteSelectionText:
  542. case ValueID::LibwebPaletteSyntaxComment:
  543. case ValueID::LibwebPaletteSyntaxControlKeyword:
  544. case ValueID::LibwebPaletteSyntaxIdentifier:
  545. case ValueID::LibwebPaletteSyntaxKeyword:
  546. case ValueID::LibwebPaletteSyntaxNumber:
  547. case ValueID::LibwebPaletteSyntaxOperator:
  548. case ValueID::LibwebPaletteSyntaxPreprocessorStatement:
  549. case ValueID::LibwebPaletteSyntaxPreprocessorValue:
  550. case ValueID::LibwebPaletteSyntaxPunctuation:
  551. case ValueID::LibwebPaletteSyntaxString:
  552. case ValueID::LibwebPaletteSyntaxType:
  553. case ValueID::LibwebPaletteTextCursor:
  554. case ValueID::LibwebPaletteThreedHighlight:
  555. case ValueID::LibwebPaletteThreedShadow1:
  556. case ValueID::LibwebPaletteThreedShadow2:
  557. case ValueID::LibwebPaletteVisitedLink:
  558. case ValueID::LibwebPaletteWindow:
  559. case ValueID::LibwebPaletteWindowText:
  560. return true;
  561. default:
  562. return false;
  563. }
  564. }
  565. Color IdentifierStyleValue::to_color(Layout::NodeWithStyle const& node) const
  566. {
  567. if (id() == CSS::ValueID::Currentcolor) {
  568. if (!node.has_style())
  569. return Color::Black;
  570. return node.computed_values().color();
  571. }
  572. auto& document = node.document();
  573. if (id() == CSS::ValueID::LibwebLink)
  574. return document.link_color();
  575. VERIFY(document.page());
  576. auto palette = document.page()->palette();
  577. switch (id()) {
  578. case CSS::ValueID::LibwebPaletteDesktopBackground:
  579. return palette.color(ColorRole::DesktopBackground);
  580. case CSS::ValueID::LibwebPaletteActiveWindowBorder1:
  581. return palette.color(ColorRole::ActiveWindowBorder1);
  582. case CSS::ValueID::LibwebPaletteActiveWindowBorder2:
  583. return palette.color(ColorRole::ActiveWindowBorder2);
  584. case CSS::ValueID::LibwebPaletteActiveWindowTitle:
  585. return palette.color(ColorRole::ActiveWindowTitle);
  586. case CSS::ValueID::LibwebPaletteInactiveWindowBorder1:
  587. return palette.color(ColorRole::InactiveWindowBorder1);
  588. case CSS::ValueID::LibwebPaletteInactiveWindowBorder2:
  589. return palette.color(ColorRole::InactiveWindowBorder2);
  590. case CSS::ValueID::LibwebPaletteInactiveWindowTitle:
  591. return palette.color(ColorRole::InactiveWindowTitle);
  592. case CSS::ValueID::LibwebPaletteMovingWindowBorder1:
  593. return palette.color(ColorRole::MovingWindowBorder1);
  594. case CSS::ValueID::LibwebPaletteMovingWindowBorder2:
  595. return palette.color(ColorRole::MovingWindowBorder2);
  596. case CSS::ValueID::LibwebPaletteMovingWindowTitle:
  597. return palette.color(ColorRole::MovingWindowTitle);
  598. case CSS::ValueID::LibwebPaletteHighlightWindowBorder1:
  599. return palette.color(ColorRole::HighlightWindowBorder1);
  600. case CSS::ValueID::LibwebPaletteHighlightWindowBorder2:
  601. return palette.color(ColorRole::HighlightWindowBorder2);
  602. case CSS::ValueID::LibwebPaletteHighlightWindowTitle:
  603. return palette.color(ColorRole::HighlightWindowTitle);
  604. case CSS::ValueID::LibwebPaletteMenuStripe:
  605. return palette.color(ColorRole::MenuStripe);
  606. case CSS::ValueID::LibwebPaletteMenuBase:
  607. return palette.color(ColorRole::MenuBase);
  608. case CSS::ValueID::LibwebPaletteMenuBaseText:
  609. return palette.color(ColorRole::MenuBaseText);
  610. case CSS::ValueID::LibwebPaletteMenuSelection:
  611. return palette.color(ColorRole::MenuSelection);
  612. case CSS::ValueID::LibwebPaletteMenuSelectionText:
  613. return palette.color(ColorRole::MenuSelectionText);
  614. case CSS::ValueID::LibwebPaletteWindow:
  615. return palette.color(ColorRole::Window);
  616. case CSS::ValueID::LibwebPaletteWindowText:
  617. return palette.color(ColorRole::WindowText);
  618. case CSS::ValueID::LibwebPaletteButton:
  619. return palette.color(ColorRole::Button);
  620. case CSS::ValueID::LibwebPaletteButtonText:
  621. return palette.color(ColorRole::ButtonText);
  622. case CSS::ValueID::LibwebPaletteBase:
  623. return palette.color(ColorRole::Base);
  624. case CSS::ValueID::LibwebPaletteBaseText:
  625. return palette.color(ColorRole::BaseText);
  626. case CSS::ValueID::LibwebPaletteThreedHighlight:
  627. return palette.color(ColorRole::ThreedHighlight);
  628. case CSS::ValueID::LibwebPaletteThreedShadow1:
  629. return palette.color(ColorRole::ThreedShadow1);
  630. case CSS::ValueID::LibwebPaletteThreedShadow2:
  631. return palette.color(ColorRole::ThreedShadow2);
  632. case CSS::ValueID::LibwebPaletteHoverHighlight:
  633. return palette.color(ColorRole::HoverHighlight);
  634. case CSS::ValueID::LibwebPaletteSelection:
  635. return palette.color(ColorRole::Selection);
  636. case CSS::ValueID::LibwebPaletteSelectionText:
  637. return palette.color(ColorRole::SelectionText);
  638. case CSS::ValueID::LibwebPaletteInactiveSelection:
  639. return palette.color(ColorRole::InactiveSelection);
  640. case CSS::ValueID::LibwebPaletteInactiveSelectionText:
  641. return palette.color(ColorRole::InactiveSelectionText);
  642. case CSS::ValueID::LibwebPaletteRubberBandFill:
  643. return palette.color(ColorRole::RubberBandFill);
  644. case CSS::ValueID::LibwebPaletteRubberBandBorder:
  645. return palette.color(ColorRole::RubberBandBorder);
  646. case CSS::ValueID::LibwebPaletteLink:
  647. return palette.color(ColorRole::Link);
  648. case CSS::ValueID::LibwebPaletteActiveLink:
  649. return palette.color(ColorRole::ActiveLink);
  650. case CSS::ValueID::LibwebPaletteVisitedLink:
  651. return palette.color(ColorRole::VisitedLink);
  652. case CSS::ValueID::LibwebPaletteRuler:
  653. return palette.color(ColorRole::Ruler);
  654. case CSS::ValueID::LibwebPaletteRulerBorder:
  655. return palette.color(ColorRole::RulerBorder);
  656. case CSS::ValueID::LibwebPaletteRulerActiveText:
  657. return palette.color(ColorRole::RulerActiveText);
  658. case CSS::ValueID::LibwebPaletteRulerInactiveText:
  659. return palette.color(ColorRole::RulerInactiveText);
  660. case CSS::ValueID::LibwebPaletteTextCursor:
  661. return palette.color(ColorRole::TextCursor);
  662. case CSS::ValueID::LibwebPaletteFocusOutline:
  663. return palette.color(ColorRole::FocusOutline);
  664. case CSS::ValueID::LibwebPaletteSyntaxComment:
  665. return palette.color(ColorRole::SyntaxComment);
  666. case CSS::ValueID::LibwebPaletteSyntaxNumber:
  667. return palette.color(ColorRole::SyntaxNumber);
  668. case CSS::ValueID::LibwebPaletteSyntaxString:
  669. return palette.color(ColorRole::SyntaxString);
  670. case CSS::ValueID::LibwebPaletteSyntaxType:
  671. return palette.color(ColorRole::SyntaxType);
  672. case CSS::ValueID::LibwebPaletteSyntaxPunctuation:
  673. return palette.color(ColorRole::SyntaxPunctuation);
  674. case CSS::ValueID::LibwebPaletteSyntaxOperator:
  675. return palette.color(ColorRole::SyntaxOperator);
  676. case CSS::ValueID::LibwebPaletteSyntaxKeyword:
  677. return palette.color(ColorRole::SyntaxKeyword);
  678. case CSS::ValueID::LibwebPaletteSyntaxControlKeyword:
  679. return palette.color(ColorRole::SyntaxControlKeyword);
  680. case CSS::ValueID::LibwebPaletteSyntaxIdentifier:
  681. return palette.color(ColorRole::SyntaxIdentifier);
  682. case CSS::ValueID::LibwebPaletteSyntaxPreprocessorStatement:
  683. return palette.color(ColorRole::SyntaxPreprocessorStatement);
  684. case CSS::ValueID::LibwebPaletteSyntaxPreprocessorValue:
  685. return palette.color(ColorRole::SyntaxPreprocessorValue);
  686. default:
  687. return {};
  688. }
  689. }
  690. ImageStyleValue::ImageStyleValue(AK::URL const& url)
  691. : StyleValue(Type::Image)
  692. , m_url(url)
  693. {
  694. }
  695. void ImageStyleValue::load_bitmap(DOM::Document& document)
  696. {
  697. if (m_bitmap)
  698. return;
  699. m_document = &document;
  700. auto request = LoadRequest::create_for_url_on_page(m_url, document.page());
  701. set_resource(ResourceLoader::the().load_resource(Resource::Type::Image, request));
  702. }
  703. void ImageStyleValue::resource_did_load()
  704. {
  705. if (!m_document)
  706. return;
  707. m_bitmap = resource()->bitmap();
  708. // FIXME: Do less than a full repaint if possible?
  709. if (m_document && m_document->browsing_context())
  710. m_document->browsing_context()->set_needs_display({});
  711. }
  712. String ImageStyleValue::to_string() const
  713. {
  714. return serialize_a_url(m_url.to_string());
  715. }
  716. String ListStyleStyleValue::to_string() const
  717. {
  718. return String::formatted("{} {} {}", m_position->to_string(), m_image->to_string(), m_style_type->to_string());
  719. }
  720. String NumericStyleValue::to_string() const
  721. {
  722. return m_value.visit(
  723. [](float value) {
  724. return String::formatted("{}", value);
  725. },
  726. [](i64 value) {
  727. return String::formatted("{}", value);
  728. });
  729. }
  730. String OverflowStyleValue::to_string() const
  731. {
  732. return String::formatted("{} {}", m_overflow_x->to_string(), m_overflow_y->to_string());
  733. }
  734. String PercentageStyleValue::to_string() const
  735. {
  736. return m_percentage.to_string();
  737. }
  738. String PositionStyleValue::to_string() const
  739. {
  740. auto to_string = [](PositionEdge edge) {
  741. switch (edge) {
  742. case PositionEdge::Left:
  743. return "left";
  744. case PositionEdge::Right:
  745. return "right";
  746. case PositionEdge::Top:
  747. return "top";
  748. case PositionEdge::Bottom:
  749. return "bottom";
  750. }
  751. VERIFY_NOT_REACHED();
  752. };
  753. return String::formatted("{} {} {} {}", to_string(m_edge_x), m_offset_x.to_string(), to_string(m_edge_y), m_offset_y.to_string());
  754. }
  755. String TextDecorationStyleValue::to_string() const
  756. {
  757. return String::formatted("{} {} {}", m_line->to_string(), m_style->to_string(), m_color->to_string());
  758. }
  759. String TransformationStyleValue::to_string() const
  760. {
  761. StringBuilder builder;
  762. switch (m_transform_function) {
  763. case TransformFunction::TranslateY:
  764. builder.append("translateY");
  765. break;
  766. default:
  767. VERIFY_NOT_REACHED();
  768. }
  769. builder.append('(');
  770. builder.join(", ", m_values);
  771. builder.append(')');
  772. return builder.to_string();
  773. }
  774. String UnresolvedStyleValue::to_string() const
  775. {
  776. StringBuilder builder;
  777. for (auto& value : m_values)
  778. builder.append(value.to_string());
  779. return builder.to_string();
  780. }
  781. String StyleValueList::to_string() const
  782. {
  783. String separator = "";
  784. switch (m_separator) {
  785. case Separator::Space:
  786. separator = " ";
  787. break;
  788. case Separator::Comma:
  789. separator = ", ";
  790. break;
  791. default:
  792. VERIFY_NOT_REACHED();
  793. }
  794. return String::join(separator, m_values);
  795. }
  796. }