Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of LibCSS
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
  6.  */
  7.  
  8. #include <string.h>
  9.  
  10. #include "select/computed.h"
  11. #include "select/dispatch.h"
  12. #include "select/propget.h"
  13. #include "select/propset.h"
  14. #include "utils/utils.h"
  15.  
  16. static css_error compute_absolute_color(css_computed_style *style,
  17.                 uint8_t (*get)(const css_computed_style *style,
  18.                                 css_color *color),
  19.                 css_error (*set)(css_computed_style *style,
  20.                                 uint8_t type, css_color color));
  21. static css_error compute_border_colors(css_computed_style *style);
  22.  
  23. static css_error compute_absolute_border_width(css_computed_style *style,
  24.                 const css_hint_length *ex_size);
  25. static css_error compute_absolute_border_side_width(css_computed_style *style,
  26.                 const css_hint_length *ex_size,
  27.                 uint8_t (*get)(const css_computed_style *style,
  28.                                 css_fixed *len, css_unit *unit),
  29.                 css_error (*set)(css_computed_style *style, uint8_t type,
  30.                                 css_fixed len, css_unit unit));
  31. static css_error compute_absolute_sides(css_computed_style *style,
  32.                 const css_hint_length *ex_size);
  33. static css_error compute_absolute_clip(css_computed_style *style,
  34.                 const css_hint_length *ex_size);
  35. static css_error compute_absolute_line_height(css_computed_style *style,
  36.                 const css_hint_length *ex_size);
  37. static css_error compute_absolute_margins(css_computed_style *style,
  38.                 const css_hint_length *ex_size);
  39. static css_error compute_absolute_padding(css_computed_style *style,
  40.                 const css_hint_length *ex_size);
  41. static css_error compute_absolute_vertical_align(css_computed_style *style,
  42.                 const css_hint_length *ex_size);
  43. static css_error compute_absolute_length(css_computed_style *style,
  44.                 const css_hint_length *ex_size,
  45.                 uint8_t (*get)(const css_computed_style *style,
  46.                                 css_fixed *len, css_unit *unit),
  47.                 css_error (*set)(css_computed_style *style, uint8_t type,
  48.                                 css_fixed len, css_unit unit));
  49. static css_error compute_absolute_length_auto(css_computed_style *style,
  50.                 const css_hint_length *ex_size,
  51.                 uint8_t (*get)(const css_computed_style *style,
  52.                                 css_fixed *len, css_unit *unit),
  53.                 css_error (*set)(css_computed_style *style, uint8_t type,
  54.                                 css_fixed len, css_unit unit));
  55. static css_error compute_absolute_length_none(css_computed_style *style,
  56.                 const css_hint_length *ex_size,
  57.                 uint8_t (*get)(const css_computed_style *style,
  58.                                 css_fixed *len, css_unit *unit),
  59.                 css_error (*set)(css_computed_style *style, uint8_t type,
  60.                                 css_fixed len, css_unit unit));
  61. static css_error compute_absolute_length_normal(css_computed_style *style,
  62.                 const css_hint_length *ex_size,
  63.                 uint8_t (*get)(const css_computed_style *style,
  64.                                 css_fixed *len, css_unit *unit),
  65.                 css_error (*set)(css_computed_style *style, uint8_t type,
  66.                                 css_fixed len, css_unit unit));
  67. static css_error compute_absolute_length_pair(css_computed_style *style,
  68.                 const css_hint_length *ex_size,
  69.                 uint8_t (*get)(const css_computed_style *style,
  70.                                 css_fixed *len1, css_unit *unit1,
  71.                                 css_fixed *len2, css_unit *unit2),
  72.                 css_error (*set)(css_computed_style *style, uint8_t type,
  73.                                 css_fixed len1, css_unit unit1,
  74.                                 css_fixed len2, css_unit unit2));
  75.  
  76.  
  77. /**
  78.  * Create a computed style
  79.  *
  80.  * \param alloc   Memory (de)allocation function
  81.  * \param pw      Pointer to client-specific data
  82.  * \param result  Pointer to location to receive result
  83.  * \return CSS_OK on success,
  84.  *         CSS_NOMEM on memory exhaustion,
  85.  *         CSS_BADPARM on bad parameters.
  86.  */
  87. css_error css_computed_style_create(css_allocator_fn alloc, void *pw,
  88.                 css_computed_style **result)
  89. {
  90.         css_computed_style *s;
  91.  
  92.         if (alloc == NULL || result == NULL)
  93.                 return CSS_BADPARM;
  94.  
  95.         s = alloc(NULL, sizeof(css_computed_style), pw);
  96.         if (s == NULL)
  97.                 return CSS_NOMEM;
  98.  
  99.         memset(s, 0, sizeof(css_computed_style));
  100.  
  101.         s->alloc = alloc;
  102.         s->pw = pw;
  103.  
  104.         *result = s;
  105.  
  106.         return CSS_OK;
  107. }
  108.  
  109. /**
  110.  * Destroy a computed style
  111.  *
  112.  * \param style  Style to destroy
  113.  * \return CSS_OK on success, appropriate error otherwise
  114.  */
  115. css_error css_computed_style_destroy(css_computed_style *style)
  116. {
  117.         if (style == NULL)
  118.                 return CSS_BADPARM;
  119.  
  120.         if (style->uncommon != NULL) {
  121.                 if (style->uncommon->counter_increment != NULL) {
  122.                         css_computed_counter *c;
  123.  
  124.                         for (c = style->uncommon->counter_increment;
  125.                                         c->name != NULL; c++) {
  126.                                 lwc_string_unref(c->name);
  127.                         }
  128.  
  129.                         style->alloc(style->uncommon->counter_increment, 0,
  130.                                         style->pw);
  131.                 }
  132.  
  133.                 if (style->uncommon->counter_reset != NULL) {
  134.                         css_computed_counter *c;
  135.  
  136.                         for (c = style->uncommon->counter_reset;
  137.                                         c->name != NULL; c++) {
  138.                                 lwc_string_unref(c->name);
  139.                         }
  140.  
  141.                         style->alloc(style->uncommon->counter_reset, 0,
  142.                                         style->pw);
  143.                 }
  144.        
  145.                 if (style->uncommon->cursor != NULL) {
  146.                         lwc_string **s;
  147.  
  148.                         for (s = style->uncommon->cursor; *s != NULL; s++) {
  149.                                 lwc_string_unref(*s);
  150.                         }
  151.  
  152.                         style->alloc(style->uncommon->cursor, 0, style->pw);
  153.                 }
  154.  
  155.                 if (style->uncommon->content != NULL) {
  156.                         css_computed_content_item *c;
  157.  
  158.                         for (c = style->uncommon->content;
  159.                                         c->type != CSS_COMPUTED_CONTENT_NONE;
  160.                                         c++) {
  161.                                 switch (c->type) {
  162.                                 case CSS_COMPUTED_CONTENT_STRING:
  163.                                         lwc_string_unref(c->data.string);
  164.                                         break;
  165.                                 case CSS_COMPUTED_CONTENT_URI:
  166.                                         lwc_string_unref(c->data.uri);
  167.                                         break;
  168.                                 case CSS_COMPUTED_CONTENT_ATTR:
  169.                                         lwc_string_unref(c->data.attr);
  170.                                         break;
  171.                                 case CSS_COMPUTED_CONTENT_COUNTER:
  172.                                         lwc_string_unref(c->data.counter.name);
  173.                                         break;
  174.                                 case CSS_COMPUTED_CONTENT_COUNTERS:
  175.                                         lwc_string_unref(c->data.counters.name);
  176.                                         lwc_string_unref(c->data.counters.sep);
  177.                                         break;
  178.                                 default:
  179.                                         break;
  180.                                 }
  181.                         }
  182.  
  183.                         style->alloc(style->uncommon->content, 0, style->pw);
  184.                 }
  185.  
  186.                 style->alloc(style->uncommon, 0, style->pw);
  187.         }
  188.  
  189.         if (style->page != NULL) {
  190.                 style->alloc(style->page, 0, style->pw);
  191.         }
  192.  
  193.         if (style->aural != NULL) {
  194.                 style->alloc(style->aural, 0, style->pw);
  195.         }
  196.  
  197.         if (style->font_family != NULL) {
  198.                 lwc_string **s;
  199.  
  200.                 for (s = style->font_family; *s != NULL; s++) {
  201.                         lwc_string_unref(*s);
  202.                 }
  203.  
  204.                 style->alloc(style->font_family, 0, style->pw);
  205.         }
  206.  
  207.         if (style->quotes != NULL) {
  208.                 lwc_string **s;
  209.  
  210.                 for (s = style->quotes; *s != NULL; s++) {
  211.                         lwc_string_unref(*s);
  212.                 }
  213.  
  214.                 style->alloc(style->quotes, 0, style->pw);
  215.         }
  216.  
  217.         if (style->list_style_image != NULL)
  218.                 lwc_string_unref(style->list_style_image);
  219.  
  220.         if (style->background_image != NULL)
  221.                 lwc_string_unref(style->background_image);
  222.  
  223.         style->alloc(style, 0, style->pw);
  224.  
  225.         return CSS_OK;
  226. }
  227.  
  228. /**
  229.  * Populate a blank computed style with Initial values
  230.  *
  231.  * \param style    Computed style to populate
  232.  * \param handler  Dispatch table of handler functions
  233.  * \param pw       Client-specific private data for handler functions
  234.  * \return CSS_OK on success.
  235.  */
  236. css_error css_computed_style_initialise(css_computed_style *style,
  237.                 css_select_handler *handler, void *pw)
  238. {
  239.         css_select_state state;
  240.         uint32_t i;
  241.         css_error error;
  242.  
  243.         if (style == NULL)
  244.                 return CSS_BADPARM;
  245.  
  246.         state.node = NULL;
  247.         state.media = CSS_MEDIA_ALL;
  248.         state.results = NULL;
  249.         state.computed = style;
  250.         state.handler = handler;
  251.         state.pw = pw;
  252.  
  253.         for (i = 0; i < CSS_N_PROPERTIES; i++) {
  254.                 /* No need to initialise anything other than the normal
  255.                  * properties -- the others are handled by the accessors */
  256.                 if (prop_dispatch[i].inherited == false &&
  257.                                 prop_dispatch[i].group == GROUP_NORMAL) {
  258.                         error = prop_dispatch[i].initial(&state);
  259.                         if (error != CSS_OK)
  260.                                 return error;
  261.                 }
  262.         }
  263.  
  264.         return CSS_OK;
  265. }
  266.  
  267. /**
  268.  * Compose two computed styles
  269.  *
  270.  * \param parent             Parent style
  271.  * \param child              Child style
  272.  * \param compute_font_size  Function to compute an absolute font size
  273.  * \param pw                 Client data for compute_font_size
  274.  * \param result             Pointer to style to compose into
  275.  * \return CSS_OK on success, appropriate error otherwise.
  276.  *
  277.  * \pre \a parent is a fully composed style (thus has no inherited properties)
  278.  *
  279.  * \note \a child and \a result may point at the same object
  280.  */
  281. css_error css_computed_style_compose(const css_computed_style *parent,
  282.                 const css_computed_style *child,
  283.                 css_error (*compute_font_size)(void *pw,
  284.                         const css_hint *parent, css_hint *size),
  285.                 void *pw,
  286.                 css_computed_style *result)
  287. {
  288.         css_error error = CSS_OK;
  289.         size_t i;
  290.  
  291.         /* Iterate through the properties */
  292.         for (i = 0; i < CSS_N_PROPERTIES; i++) {
  293.                 /* Skip any in extension blocks if the block does not exist */ 
  294.                 if (prop_dispatch[i].group == GROUP_UNCOMMON &&
  295.                                 parent->uncommon == NULL &&
  296.                                 child->uncommon == NULL)
  297.                         continue;
  298.  
  299.                 if (prop_dispatch[i].group == GROUP_PAGE &&
  300.                                 parent->page == NULL && child->page == NULL)
  301.                         continue;
  302.  
  303.                 if (prop_dispatch[i].group == GROUP_AURAL &&
  304.                                 parent->aural == NULL && child->aural == NULL)
  305.                         continue;
  306.  
  307.                 /* Compose the property */
  308.                 error = prop_dispatch[i].compose(parent, child, result);
  309.                 if (error != CSS_OK)
  310.                         break;
  311.         }
  312.  
  313.         /* Finally, compute absolute values for everything */
  314.         return css__compute_absolute_values(parent, result, compute_font_size, pw);
  315. }
  316.  
  317. /******************************************************************************
  318.  * Property accessors                                                         *
  319.  ******************************************************************************/
  320.  
  321.  
  322. #define CSS_LETTER_SPACING_INDEX 0
  323. #define CSS_LETTER_SPACING_SHIFT 2
  324. #define CSS_LETTER_SPACING_MASK  0xfc
  325. uint8_t css_computed_letter_spacing(
  326.                 const css_computed_style *style,
  327.                 css_fixed *length, css_unit *unit)
  328. {
  329.         if (style->uncommon != NULL) {
  330.                 uint8_t bits = style->uncommon->bits[CSS_LETTER_SPACING_INDEX];
  331.                 bits &= CSS_LETTER_SPACING_MASK;
  332.                 bits >>= CSS_LETTER_SPACING_SHIFT;
  333.  
  334.                 /* 6bits: uuuutt : unit | type */
  335.  
  336.                 if ((bits & 3) == CSS_LETTER_SPACING_SET) {
  337.                         *length = style->uncommon->letter_spacing;
  338.                         *unit = (css_unit) (bits >> 2);
  339.                 }
  340.  
  341.                 return (bits & 3);
  342.         }
  343.  
  344.         return CSS_LETTER_SPACING_NORMAL;
  345. }
  346. #undef CSS_LETTER_SPACING_MASK
  347. #undef CSS_LETTER_SPACING_SHIFT
  348. #undef CSS_LETTER_SPACING_INDEX
  349.  
  350. #define CSS_OUTLINE_COLOR_INDEX 0
  351. #define CSS_OUTLINE_COLOR_SHIFT 0
  352. #define CSS_OUTLINE_COLOR_MASK  0x3
  353. uint8_t css_computed_outline_color(
  354.                 const css_computed_style *style, css_color *color)
  355. {
  356.         if (style->uncommon != NULL) {
  357.                 uint8_t bits = style->uncommon->bits[CSS_OUTLINE_COLOR_INDEX];
  358.                 bits &= CSS_OUTLINE_COLOR_MASK;
  359.                 bits >>= CSS_OUTLINE_COLOR_SHIFT;
  360.  
  361.                 /* 2bits: tt : type */
  362.  
  363.                 if ((bits & 3) == CSS_OUTLINE_COLOR_COLOR) {
  364.                         *color = style->uncommon->outline_color;
  365.                 }
  366.  
  367.                 return (bits & 3);
  368.         }
  369.  
  370.         return CSS_OUTLINE_COLOR_INVERT;
  371. }
  372. #undef CSS_OUTLINE_COLOR_MASK
  373. #undef CSS_OUTLINE_COLOR_SHIFT
  374. #undef CSS_OUTLINE_COLOR_INDEX
  375.  
  376. #define CSS_OUTLINE_WIDTH_INDEX 1
  377. #define CSS_OUTLINE_WIDTH_SHIFT 1
  378. #define CSS_OUTLINE_WIDTH_MASK  0xfe
  379. uint8_t css_computed_outline_width(
  380.                 const css_computed_style *style,
  381.                 css_fixed *length, css_unit *unit)
  382. {
  383.         if (style->uncommon != NULL) {
  384.                 uint8_t bits = style->uncommon->bits[CSS_OUTLINE_WIDTH_INDEX];
  385.                 bits &= CSS_OUTLINE_WIDTH_MASK;
  386.                 bits >>= CSS_OUTLINE_WIDTH_SHIFT;
  387.  
  388.                 /* 7bits: uuuuttt : unit | type */
  389.  
  390.                 if ((bits & 7) == CSS_OUTLINE_WIDTH_WIDTH) {
  391.                         *length = style->uncommon->outline_width;
  392.                         *unit = (css_unit) (bits >> 3);
  393.                 }
  394.  
  395.                 return (bits & 7);
  396.         }
  397.  
  398.         *length = INTTOFIX(2);
  399.         *unit = CSS_UNIT_PX;
  400.  
  401.         return CSS_OUTLINE_WIDTH_WIDTH;
  402. }
  403. #undef CSS_OUTLINE_WIDTH_MASK
  404. #undef CSS_OUTLINE_WIDTH_SHIFT
  405. #undef CSS_OUTLINE_WIDTH_INDEX
  406.  
  407. #define CSS_BORDER_SPACING_INDEX 1
  408. #define CSS_BORDER_SPACING_SHIFT 0
  409. #define CSS_BORDER_SPACING_MASK  0x1
  410. #define CSS_BORDER_SPACING_INDEX1 2
  411. #define CSS_BORDER_SPACING_SHIFT1 0
  412. #define CSS_BORDER_SPACING_MASK1 0xff
  413. uint8_t css_computed_border_spacing(
  414.                 const css_computed_style *style,
  415.                 css_fixed *hlength, css_unit *hunit,
  416.                 css_fixed *vlength, css_unit *vunit)
  417. {
  418.         if (style->uncommon != NULL) {
  419.                 uint8_t bits = style->uncommon->bits[CSS_BORDER_SPACING_INDEX];
  420.                 bits &= CSS_BORDER_SPACING_MASK;
  421.                 bits >>= CSS_BORDER_SPACING_SHIFT;
  422.  
  423.                 /* 1 bit: type */
  424.                 if (bits == CSS_BORDER_SPACING_SET) {
  425.                         uint8_t bits1 =
  426.                                 style->uncommon->bits[CSS_BORDER_SPACING_INDEX1];
  427.                         bits1 &= CSS_BORDER_SPACING_MASK1;
  428.                         bits1 >>= CSS_BORDER_SPACING_SHIFT1;
  429.  
  430.                         /* 8bits: hhhhvvvv : hunit | vunit */
  431.  
  432.                         *hlength = style->uncommon->border_spacing[0];
  433.                         *hunit = (css_unit) (bits1 >> 4);
  434.  
  435.                         *vlength = style->uncommon->border_spacing[1];
  436.                         *vunit = (css_unit) (bits1 & 0xf);
  437.                 }
  438.  
  439.                 return bits;
  440.         } else {
  441.                 *hlength = *vlength = 0;
  442.                 *hunit = *vunit = CSS_UNIT_PX;
  443.         }
  444.  
  445.         return CSS_BORDER_SPACING_SET;
  446. }
  447. #undef CSS_BORDER_SPACING_MASK1
  448. #undef CSS_BORDER_SPACING_SHIFT1
  449. #undef CSS_BORDER_SPACING_INDEX1
  450. #undef CSS_BORDER_SPACING_MASK
  451. #undef CSS_BORDER_SPACING_SHIFT
  452. #undef CSS_BORDER_SPACING_INDEX
  453.  
  454. #define CSS_WORD_SPACING_INDEX 3
  455. #define CSS_WORD_SPACING_SHIFT 2
  456. #define CSS_WORD_SPACING_MASK  0xfc
  457. uint8_t css_computed_word_spacing(
  458.                 const css_computed_style *style,
  459.                 css_fixed *length, css_unit *unit)
  460. {
  461.         if (style->uncommon != NULL) {
  462.                 uint8_t bits = style->uncommon->bits[CSS_WORD_SPACING_INDEX];
  463.                 bits &= CSS_WORD_SPACING_MASK;
  464.                 bits >>= CSS_WORD_SPACING_SHIFT;
  465.  
  466.                 /* 6bits: uuuutt : unit | type */
  467.  
  468.                 if ((bits & 3) == CSS_WORD_SPACING_SET) {
  469.                         *length = style->uncommon->word_spacing;
  470.                         *unit = (css_unit) (bits >> 2);
  471.                 }
  472.  
  473.                 return (bits & 3);
  474.         }
  475.  
  476.         return CSS_WORD_SPACING_NORMAL;
  477. }
  478. #undef CSS_WORD_SPACING_MASK
  479. #undef CSS_WORD_SPACING_SHIFT
  480. #undef CSS_WORD_SPACING_INDEX
  481.  
  482. #define CSS_COUNTER_INCREMENT_INDEX 3
  483. #define CSS_COUNTER_INCREMENT_SHIFT 1
  484. #define CSS_COUNTER_INCREMENT_MASK  0x2
  485. uint8_t css_computed_counter_increment(
  486.                 const css_computed_style *style,
  487.                 const css_computed_counter **counters)
  488. {
  489.         if (style->uncommon != NULL) {
  490.                 uint8_t bits =
  491.                         style->uncommon->bits[CSS_COUNTER_INCREMENT_INDEX];
  492.                 bits &= CSS_COUNTER_INCREMENT_MASK;
  493.                 bits >>= CSS_COUNTER_INCREMENT_SHIFT;
  494.  
  495.                 /* 1bit: type */
  496.                 *counters = style->uncommon->counter_increment;
  497.  
  498.                 return bits;
  499.         }
  500.  
  501.         return CSS_COUNTER_INCREMENT_NONE;
  502. }
  503. #undef CSS_COUNTER_INCREMENT_MASK
  504. #undef CSS_COUNTER_INCREMENT_SHIFT
  505. #undef CSS_COUNTER_INCREMENT_INDEX
  506.  
  507. #define CSS_COUNTER_RESET_INDEX 3
  508. #define CSS_COUNTER_RESET_SHIFT 0
  509. #define CSS_COUNTER_RESET_MASK  0x1
  510. uint8_t css_computed_counter_reset(
  511.                 const css_computed_style *style,
  512.                 const css_computed_counter **counters)
  513. {
  514.         if (style->uncommon != NULL) {
  515.                 uint8_t bits = style->uncommon->bits[CSS_COUNTER_RESET_INDEX];
  516.                 bits &= CSS_COUNTER_RESET_MASK;
  517.                 bits >>= CSS_COUNTER_RESET_SHIFT;
  518.  
  519.                 /* 1bit: type */
  520.                 *counters = style->uncommon->counter_reset;
  521.  
  522.                 return bits;
  523.         }
  524.  
  525.         return CSS_COUNTER_RESET_NONE;
  526. }
  527. #undef CSS_COUNTER_RESET_MASK
  528. #undef CSS_COUNTER_RESET_SHIFT
  529. #undef CSS_COUNTER_RESET_INDEX
  530.  
  531. #define CSS_CURSOR_INDEX 4
  532. #define CSS_CURSOR_SHIFT 3
  533. #define CSS_CURSOR_MASK  0xf8
  534. uint8_t css_computed_cursor(
  535.                 const css_computed_style *style,
  536.                 lwc_string ***urls)
  537. {
  538.         if (style->uncommon != NULL) {
  539.                 uint8_t bits = style->uncommon->bits[CSS_CURSOR_INDEX];
  540.                 bits &= CSS_CURSOR_MASK;
  541.                 bits >>= CSS_CURSOR_SHIFT;
  542.  
  543.                 /* 5bits: type */
  544.                 *urls = style->uncommon->cursor;
  545.  
  546.                 return bits;
  547.         }
  548.  
  549.         return CSS_CURSOR_AUTO;
  550. }
  551. #undef CSS_CURSOR_MASK
  552. #undef CSS_CURSOR_SHIFT
  553. #undef CSS_CURSOR_INDEX
  554.  
  555. #define CSS_CLIP_INDEX 7
  556. #define CSS_CLIP_SHIFT 2
  557. #define CSS_CLIP_MASK  0xfc
  558. #define CSS_CLIP_INDEX1 5
  559. #define CSS_CLIP_SHIFT1 0
  560. #define CSS_CLIP_MASK1 0xff
  561. #define CSS_CLIP_INDEX2 6
  562. #define CSS_CLIP_SHIFT2 0
  563. #define CSS_CLIP_MASK2 0xff
  564. uint8_t css_computed_clip(
  565.                 const css_computed_style *style,
  566.                 css_computed_clip_rect *rect)
  567. {
  568.         if (style->uncommon != NULL) {
  569.                 uint8_t bits = style->uncommon->bits[CSS_CLIP_INDEX];
  570.                 bits &= CSS_CLIP_MASK;
  571.                 bits >>= CSS_CLIP_SHIFT;
  572.  
  573.                 /* 6bits: trblyy : top | right | bottom | left | type */
  574.                 if ((bits & 0x3) == CSS_CLIP_RECT) {
  575.                         uint8_t bits1;
  576.  
  577.                         rect->left_auto = (bits & 0x4);
  578.                         rect->bottom_auto = (bits & 0x8);
  579.                         rect->right_auto = (bits & 0x10);
  580.                         rect->top_auto = (bits & 0x20);
  581.  
  582.                         if (rect->top_auto == false ||
  583.                                         rect->right_auto == false) {
  584.                                 /* 8bits: ttttrrrr : top | right */
  585.                                 bits1 = style->uncommon->bits[CSS_CLIP_INDEX1];
  586.                                 bits1 &= CSS_CLIP_MASK1;
  587.                                 bits1 >>= CSS_CLIP_SHIFT1;
  588.                         } else {
  589.                                 bits1 = 0;
  590.                         }
  591.  
  592.                         rect->top = style->uncommon->clip[0];
  593.                         rect->tunit = (css_unit) (bits1 >> 4);
  594.  
  595.                         rect->right = style->uncommon->clip[1];
  596.                         rect->runit = (css_unit) (bits1 & 0xf);
  597.  
  598.                         if (rect->bottom_auto == false ||
  599.                                         rect->left_auto == false) {
  600.                                 /* 8bits: bbbbllll : bottom | left */
  601.                                 bits1 = style->uncommon->bits[CSS_CLIP_INDEX2];
  602.                                 bits1 &= CSS_CLIP_MASK2;
  603.                                 bits1 >>= CSS_CLIP_SHIFT2;
  604.                         } else {
  605.                                 bits1 = 0;
  606.                         }
  607.  
  608.                         rect->bottom = style->uncommon->clip[2];
  609.                         rect->bunit = (css_unit) (bits1 >> 4);
  610.  
  611.                         rect->left = style->uncommon->clip[3];
  612.                         rect->lunit = (css_unit) (bits1 & 0xf);
  613.                 }
  614.  
  615.                 return (bits & 0x3);
  616.         }
  617.  
  618.         return CSS_CLIP_AUTO;
  619. }
  620. #undef CSS_CLIP_MASK2
  621. #undef CSS_CLIP_SHIFT2
  622. #undef CSS_CLIP_INDEX2
  623. #undef CSS_CLIP_MASK1
  624. #undef CSS_CLIP_SHIFT1
  625. #undef CSS_CLIP_INDEX1
  626. #undef CSS_CLIP_MASK
  627. #undef CSS_CLIP_SHIFT
  628. #undef CSS_CLIP_INDEX
  629.  
  630. #define CSS_CONTENT_INDEX 7
  631. #define CSS_CONTENT_SHIFT 0
  632. #define CSS_CONTENT_MASK  0x3
  633. uint8_t css_computed_content(
  634.                 const css_computed_style *style,
  635.                 const css_computed_content_item **content)
  636. {
  637.         if (style->uncommon != NULL) {
  638.                 uint8_t bits = style->uncommon->bits[CSS_CONTENT_INDEX];
  639.                 bits &= CSS_CONTENT_MASK;
  640.                 bits >>= CSS_CONTENT_SHIFT;
  641.  
  642.                 /* 2bits: type */
  643.                 *content = style->uncommon->content;
  644.  
  645.                 return bits;
  646.         }
  647.  
  648.         return CSS_CONTENT_NORMAL;
  649. }
  650. #undef CSS_CONTENT_MASK
  651. #undef CSS_CONTENT_SHIFT
  652. #undef CSS_CONTENT_INDEX
  653.  
  654. #define CSS_VERTICAL_ALIGN_INDEX 0
  655. #define CSS_VERTICAL_ALIGN_SHIFT 0
  656. #define CSS_VERTICAL_ALIGN_MASK  0xff
  657. uint8_t css_computed_vertical_align(
  658.                 const css_computed_style *style,
  659.                 css_fixed *length, css_unit *unit)
  660. {
  661.         uint8_t bits = style->bits[CSS_VERTICAL_ALIGN_INDEX];
  662.         bits &= CSS_VERTICAL_ALIGN_MASK;
  663.         bits >>= CSS_VERTICAL_ALIGN_SHIFT;
  664.  
  665.         /* 8bits: uuuutttt : units | type */
  666.         if ((bits & 0xf) == CSS_VERTICAL_ALIGN_SET) {
  667.                 *length = style->vertical_align;
  668.                 *unit = (css_unit) (bits >> 4);
  669.         }
  670.  
  671.         return (bits & 0xf);
  672. }
  673. #undef CSS_VERTICAL_ALIGN_MASK
  674. #undef CSS_VERTICAL_ALIGN_SHIFT
  675. #undef CSS_VERTICAL_ALIGN_INDEX
  676.  
  677. #define CSS_FONT_SIZE_INDEX 1
  678. #define CSS_FONT_SIZE_SHIFT 0
  679. #define CSS_FONT_SIZE_MASK  0xff
  680. uint8_t css_computed_font_size(
  681.                 const css_computed_style *style,
  682.                 css_fixed *length, css_unit *unit)
  683. {
  684.         uint8_t bits = style->bits[CSS_FONT_SIZE_INDEX];
  685.         bits &= CSS_FONT_SIZE_MASK;
  686.         bits >>= CSS_FONT_SIZE_SHIFT;
  687.  
  688.         /* 8bits: uuuutttt : units | type */
  689.         if ((bits & 0xf) == CSS_FONT_SIZE_DIMENSION) {
  690.                 *length = style->font_size;
  691.                 *unit = (css_unit) (bits >> 4);
  692.         }
  693.  
  694.         return (bits & 0xf);
  695. }
  696. #undef CSS_FONT_SIZE_MASK
  697. #undef CSS_FONT_SIZE_SHIFT
  698. #undef CSS_FONT_SIZE_INDEX
  699.  
  700. #define CSS_BORDER_TOP_WIDTH_INDEX 2
  701. #define CSS_BORDER_TOP_WIDTH_SHIFT 1
  702. #define CSS_BORDER_TOP_WIDTH_MASK  0xfe
  703. uint8_t css_computed_border_top_width(
  704.                 const css_computed_style *style,
  705.                 css_fixed *length, css_unit *unit)
  706. {
  707.         uint8_t bits = style->bits[CSS_BORDER_TOP_WIDTH_INDEX];
  708.         bits &= CSS_BORDER_TOP_WIDTH_MASK;
  709.         bits >>= CSS_BORDER_TOP_WIDTH_SHIFT;
  710.  
  711.         /* 7bits: uuuuttt : units | type */
  712.         if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) {
  713.                 *length = style->border_width[0];
  714.                 *unit = (css_unit) (bits >> 3);
  715.         }
  716.  
  717.         return (bits & 0x7);
  718. }
  719. #undef CSS_BORDER_TOP_WIDTH_MASK
  720. #undef CSS_BORDER_TOP_WIDTH_SHIFT
  721. #undef CSS_BORDER_TOP_WIDTH_INDEX
  722.  
  723. #define CSS_BORDER_RIGHT_WIDTH_INDEX 3
  724. #define CSS_BORDER_RIGHT_WIDTH_SHIFT 1
  725. #define CSS_BORDER_RIGHT_WIDTH_MASK  0xfe
  726. uint8_t css_computed_border_right_width(
  727.                 const css_computed_style *style,
  728.                 css_fixed *length, css_unit *unit)
  729. {
  730.         uint8_t bits = style->bits[CSS_BORDER_RIGHT_WIDTH_INDEX];
  731.         bits &= CSS_BORDER_RIGHT_WIDTH_MASK;
  732.         bits >>= CSS_BORDER_RIGHT_WIDTH_SHIFT;
  733.  
  734.         /* 7bits: uuuuttt : units | type */
  735.         if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) {
  736.                 *length = style->border_width[1];
  737.                 *unit = (css_unit) (bits >> 3);
  738.         }
  739.  
  740.         return (bits & 0x7);
  741. }
  742. #undef CSS_BORDER_RIGHT_WIDTH_MASK
  743. #undef CSS_BORDER_RIGHT_WIDTH_SHIFT
  744. #undef CSS_BORDER_RIGHT_WIDTH_INDEX
  745.  
  746. #define CSS_BORDER_BOTTOM_WIDTH_INDEX 4
  747. #define CSS_BORDER_BOTTOM_WIDTH_SHIFT 1
  748. #define CSS_BORDER_BOTTOM_WIDTH_MASK  0xfe
  749. uint8_t css_computed_border_bottom_width(
  750.                 const css_computed_style *style,
  751.                 css_fixed *length, css_unit *unit)
  752. {
  753.         uint8_t bits = style->bits[CSS_BORDER_BOTTOM_WIDTH_INDEX];
  754.         bits &= CSS_BORDER_BOTTOM_WIDTH_MASK;
  755.         bits >>= CSS_BORDER_BOTTOM_WIDTH_SHIFT;
  756.  
  757.         /* 7bits: uuuuttt : units | type */
  758.         if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) {
  759.                 *length = style->border_width[2];
  760.                 *unit = (css_unit) (bits >> 3);
  761.         }
  762.  
  763.         return (bits & 0x7);
  764. }
  765. #undef CSS_BORDER_BOTTOM_WIDTH_MASK
  766. #undef CSS_BORDER_BOTTOM_WIDTH_SHIFT
  767. #undef CSS_BORDER_BOTTOM_WIDTH_INDEX
  768.  
  769. #define CSS_BORDER_LEFT_WIDTH_INDEX 5
  770. #define CSS_BORDER_LEFT_WIDTH_SHIFT 1
  771. #define CSS_BORDER_LEFT_WIDTH_MASK  0xfe
  772. uint8_t css_computed_border_left_width(
  773.                 const css_computed_style *style,
  774.                 css_fixed *length, css_unit *unit)
  775. {
  776.         uint8_t bits = style->bits[CSS_BORDER_LEFT_WIDTH_INDEX];
  777.         bits &= CSS_BORDER_LEFT_WIDTH_MASK;
  778.         bits >>= CSS_BORDER_LEFT_WIDTH_SHIFT;
  779.  
  780.         /* 7bits: uuuuttt : units | type */
  781.         if ((bits & 0x7) == CSS_BORDER_WIDTH_WIDTH) {
  782.                 *length = style->border_width[3];
  783.                 *unit = (css_unit) (bits >> 3);
  784.         }
  785.  
  786.         return (bits & 0x7);
  787. }
  788. #undef CSS_BORDER_LEFT_WIDTH_MASK
  789. #undef CSS_BORDER_LEFT_WIDTH_SHIFT
  790. #undef CSS_BORDER_LEFT_WIDTH_INDEX
  791.  
  792. #define CSS_BACKGROUND_IMAGE_INDEX 2
  793. #define CSS_BACKGROUND_IMAGE_SHIFT 0
  794. #define CSS_BACKGROUND_IMAGE_MASK  0x1
  795. uint8_t css_computed_background_image(
  796.                 const css_computed_style *style,
  797.                 lwc_string **url)
  798. {
  799.         uint8_t bits = style->bits[CSS_BACKGROUND_IMAGE_INDEX];
  800.         bits &= CSS_BACKGROUND_IMAGE_MASK;
  801.         bits >>= CSS_BACKGROUND_IMAGE_SHIFT;
  802.  
  803.         /* 1bit: type */
  804.         *url = style->background_image;
  805.  
  806.         return bits;
  807. }
  808. #undef CSS_BACKGROUND_IMAGE_MASK
  809. #undef CSS_BACKGROUND_IMAGE_SHIFT
  810. #undef CSS_BACKGROUND_IMAGE_INDEX
  811.  
  812. #define CSS_COLOR_INDEX 3
  813. #define CSS_COLOR_SHIFT 0
  814. #define CSS_COLOR_MASK  0x1
  815. uint8_t css_computed_color(
  816.                 const css_computed_style *style,
  817.                 css_color *color)
  818. {
  819.         uint8_t bits = style->bits[CSS_COLOR_INDEX];
  820.         bits &= CSS_COLOR_MASK;
  821.         bits >>= CSS_COLOR_SHIFT;
  822.  
  823.         /* 1bit: type */
  824.         *color = style->color;
  825.  
  826.         return bits;
  827. }
  828. #undef CSS_COLOR_MASK
  829. #undef CSS_COLOR_SHIFT
  830. #undef CSS_COLOR_INDEX
  831.  
  832. #define CSS_LIST_STYLE_IMAGE_INDEX 4
  833. #define CSS_LIST_STYLE_IMAGE_SHIFT 0
  834. #define CSS_LIST_STYLE_IMAGE_MASK  0x1
  835. uint8_t css_computed_list_style_image(
  836.                 const css_computed_style *style,
  837.                 lwc_string **url)
  838. {
  839.         uint8_t bits = style->bits[CSS_LIST_STYLE_IMAGE_INDEX];
  840.         bits &= CSS_LIST_STYLE_IMAGE_MASK;
  841.         bits >>= CSS_LIST_STYLE_IMAGE_SHIFT;
  842.  
  843.         /* 1bit: type */
  844.         *url = style->list_style_image;
  845.  
  846.         return bits;
  847. }
  848. #undef CSS_LIST_STYLE_IMAGE_MASK
  849. #undef CSS_LIST_STYLE_IMAGE_SHIFT
  850. #undef CSS_LIST_STYLE_IMAGE_INDEX
  851.  
  852. #define CSS_QUOTES_INDEX 5
  853. #define CSS_QUOTES_SHIFT 0
  854. #define CSS_QUOTES_MASK  0x1
  855. uint8_t css_computed_quotes(
  856.                 const css_computed_style *style,
  857.                 lwc_string ***quotes)
  858. {
  859.         uint8_t bits = style->bits[CSS_QUOTES_INDEX];
  860.         bits &= CSS_QUOTES_MASK;
  861.         bits >>= CSS_QUOTES_SHIFT;
  862.  
  863.         /* 1bit: type */
  864.         *quotes = style->quotes;
  865.  
  866.         return bits;
  867. }
  868. #undef CSS_QUOTES_MASK
  869. #undef CSS_QUOTES_SHIFT
  870. #undef CSS_QUOTES_INDEX
  871.  
  872. #define CSS_TOP_INDEX 6
  873. #define CSS_TOP_SHIFT 2
  874. #define CSS_TOP_MASK  0xfc
  875. #define CSS_RIGHT_INDEX 7
  876. #define CSS_RIGHT_SHIFT 2
  877. #define CSS_RIGHT_MASK  0xfc
  878. #define CSS_BOTTOM_INDEX 8
  879. #define CSS_BOTTOM_SHIFT 2
  880. #define CSS_BOTTOM_MASK  0xfc
  881. #define CSS_LEFT_INDEX 9
  882. #define CSS_LEFT_SHIFT 2
  883. #define CSS_LEFT_MASK  0xfc
  884. uint8_t css_computed_top(
  885.                 const css_computed_style *style,
  886.                 css_fixed *length, css_unit *unit)
  887. {
  888.         uint8_t bits = style->bits[CSS_TOP_INDEX];
  889.         bits &= CSS_TOP_MASK;
  890.         bits >>= CSS_TOP_SHIFT;
  891.  
  892.         /* Fix up, based on computed position */
  893.         if (css_computed_position(style) == CSS_POSITION_STATIC) {
  894.                 /* Static -> auto */
  895.                 bits = CSS_TOP_AUTO;
  896.         } else if (css_computed_position(style) == CSS_POSITION_RELATIVE) {
  897.                 /* Relative -> follow $9.4.3 */
  898.                 uint8_t bottom = style->bits[CSS_BOTTOM_INDEX];
  899.                 bottom &= CSS_BOTTOM_MASK;
  900.                 bottom >>= CSS_BOTTOM_SHIFT;
  901.  
  902.                 if ((bits & 0x3) == CSS_TOP_AUTO &&
  903.                                 (bottom & 0x3) == CSS_BOTTOM_AUTO) {
  904.                         /* Both auto => 0px */
  905.                         *length = 0;
  906.                         *unit = CSS_UNIT_PX;
  907.                 } else if ((bits & 0x3) == CSS_TOP_AUTO) {
  908.                         /* Top is auto => -bottom */
  909.                         *length = -style->bottom;
  910.                         *unit = (css_unit) (bottom >> 2);
  911.                 } else {
  912.                         *length = style->top;
  913.                         *unit = (css_unit) (bits >> 2);
  914.                 }
  915.  
  916.                 bits = CSS_TOP_SET;
  917.         } else if ((bits & 0x3) == CSS_TOP_SET) {
  918.                 *length = style->top;
  919.                 *unit = (css_unit) (bits >> 2);
  920.         }
  921.  
  922.         /* 6bits: uuuutt : units | type */
  923.         return (bits & 0x3);
  924. }
  925.  
  926. uint8_t css_computed_right(
  927.                 const css_computed_style *style,
  928.                 css_fixed *length, css_unit *unit)
  929. {
  930.         uint8_t bits = style->bits[CSS_RIGHT_INDEX];
  931.         bits &= CSS_RIGHT_MASK;
  932.         bits >>= CSS_RIGHT_SHIFT;
  933.  
  934.         /* Fix up, based on computed position */
  935.         if (css_computed_position(style) == CSS_POSITION_STATIC) {
  936.                 /* Static -> auto */
  937.                 bits = CSS_RIGHT_AUTO;
  938.         } else if (css_computed_position(style) == CSS_POSITION_RELATIVE) {
  939.                 /* Relative -> follow $9.4.3 */
  940.                 uint8_t left = style->bits[CSS_LEFT_INDEX];
  941.                 left &= CSS_LEFT_MASK;
  942.                 left >>= CSS_LEFT_SHIFT;
  943.  
  944.                 if ((bits & 0x3) == CSS_RIGHT_AUTO &&
  945.                                 (left & 0x3) == CSS_LEFT_AUTO) {
  946.                         /* Both auto => 0px */
  947.                         *length = 0;
  948.                         *unit = CSS_UNIT_PX;
  949.                 } else if ((bits & 0x3) == CSS_RIGHT_AUTO) {
  950.                         /* Right is auto => -left */
  951.                         *length = -style->left;
  952.                         *unit = (css_unit) (left >> 2);
  953.                 } else {
  954.                         /** \todo Consider containing block's direction
  955.                          * if overconstrained */
  956.                         *length = style->right;
  957.                         *unit = (css_unit) (bits >> 2);
  958.                 }
  959.  
  960.                 bits = CSS_RIGHT_SET;
  961.         } else if ((bits & 0x3) == CSS_RIGHT_SET) {
  962.                 *length = style->right;
  963.                 *unit = (css_unit) (bits >> 2);
  964.         }
  965.  
  966.         /* 6bits: uuuutt : units | type */
  967.         return (bits & 0x3);
  968. }
  969.  
  970. uint8_t css_computed_bottom(
  971.                 const css_computed_style *style,
  972.                 css_fixed *length, css_unit *unit)
  973. {
  974.         uint8_t bits = style->bits[CSS_BOTTOM_INDEX];
  975.         bits &= CSS_BOTTOM_MASK;
  976.         bits >>= CSS_BOTTOM_SHIFT;
  977.  
  978.         /* Fix up, based on computed position */
  979.         if (css_computed_position(style) == CSS_POSITION_STATIC) {
  980.                 /* Static -> auto */
  981.                 bits = CSS_BOTTOM_AUTO;
  982.         } else if (css_computed_position(style) == CSS_POSITION_RELATIVE) {
  983.                 /* Relative -> follow $9.4.3 */
  984.                 uint8_t top = style->bits[CSS_TOP_INDEX];
  985.                 top &= CSS_TOP_MASK;
  986.                 top >>= CSS_TOP_SHIFT;
  987.  
  988.                 if ((bits & 0x3) == CSS_BOTTOM_AUTO &&
  989.                                 (top & 0x3) == CSS_TOP_AUTO) {
  990.                         /* Both auto => 0px */
  991.                         *length = 0;
  992.                         *unit = CSS_UNIT_PX;
  993.                 } else if ((bits & 0x3) == CSS_BOTTOM_AUTO ||
  994.                                 (top & 0x3) != CSS_TOP_AUTO) {
  995.                         /* Bottom is auto or top is not auto => -top */
  996.                         *length = -style->top;
  997.                         *unit = (css_unit) (top >> 2);
  998.                 } else {
  999.                         *length = style->bottom;
  1000.                         *unit = (css_unit) (bits >> 2);
  1001.                 }
  1002.  
  1003.                 bits = CSS_BOTTOM_SET;
  1004.         } else if ((bits & 0x3) == CSS_BOTTOM_SET) {
  1005.                 *length = style->bottom;
  1006.                 *unit = (css_unit) (bits >> 2);
  1007.         }
  1008.  
  1009.         /* 6bits: uuuutt : units | type */
  1010.         return (bits & 0x3);
  1011. }
  1012.  
  1013. uint8_t css_computed_left(
  1014.                 const css_computed_style *style,
  1015.                 css_fixed *length, css_unit *unit)
  1016. {
  1017.         uint8_t bits = style->bits[CSS_LEFT_INDEX];
  1018.         bits &= CSS_LEFT_MASK;
  1019.         bits >>= CSS_LEFT_SHIFT;
  1020.  
  1021.         /* Fix up, based on computed position */
  1022.         if (css_computed_position(style) == CSS_POSITION_STATIC) {
  1023.                 /* Static -> auto */
  1024.                 bits = CSS_LEFT_AUTO;
  1025.         } else if (css_computed_position(style) == CSS_POSITION_RELATIVE) {
  1026.                 /* Relative -> follow $9.4.3 */
  1027.                 uint8_t right = style->bits[CSS_RIGHT_INDEX];
  1028.                 right &= CSS_RIGHT_MASK;
  1029.                 right >>= CSS_RIGHT_SHIFT;
  1030.  
  1031.                 if ((bits & 0x3) == CSS_LEFT_AUTO &&
  1032.                                 (right & 0x3) == CSS_RIGHT_AUTO) {
  1033.                         /* Both auto => 0px */
  1034.                         *length = 0;
  1035.                         *unit = CSS_UNIT_PX;
  1036.                 } else if ((bits & 0x3) == CSS_LEFT_AUTO) {
  1037.                         /* Left is auto => -right */
  1038.                         *length = -style->right;
  1039.                         *unit = (css_unit) (right >> 2);
  1040.                 } else {
  1041.                         /** \todo Consider containing block's direction
  1042.                          * if overconstrained */
  1043.                         *length = style->left;
  1044.                         *unit = (css_unit) (bits >> 2);
  1045.                 }
  1046.  
  1047.                 bits = CSS_LEFT_SET;
  1048.         } else if ((bits & 0x3) == CSS_LEFT_SET) {
  1049.                 *length = style->left;
  1050.                 *unit = (css_unit) (bits >> 2);
  1051.         }
  1052.  
  1053.         /* 6bits: uuuutt : units | type */
  1054.         return (bits & 0x3);
  1055. }
  1056. #undef CSS_LEFT_MASK
  1057. #undef CSS_LEFT_SHIFT
  1058. #undef CSS_LEFT_INDEX
  1059. #undef CSS_BOTTOM_MASK
  1060. #undef CSS_BOTTOM_SHIFT
  1061. #undef CSS_BOTTOM_INDEX
  1062. #undef CSS_RIGHT_MASK
  1063. #undef CSS_RIGHT_SHIFT
  1064. #undef CSS_RIGHT_INDEX
  1065. #undef CSS_TOP_MASK
  1066. #undef CSS_TOP_SHIFT
  1067. #undef CSS_TOP_INDEX
  1068.  
  1069. #define CSS_BORDER_TOP_COLOR_INDEX 6
  1070. #define CSS_BORDER_TOP_COLOR_SHIFT 0
  1071. #define CSS_BORDER_TOP_COLOR_MASK  0x3
  1072. uint8_t css_computed_border_top_color(
  1073.                 const css_computed_style *style,
  1074.                 css_color *color)
  1075. {
  1076.         uint8_t bits = style->bits[CSS_BORDER_TOP_COLOR_INDEX];
  1077.         bits &= CSS_BORDER_TOP_COLOR_MASK;
  1078.         bits >>= CSS_BORDER_TOP_COLOR_SHIFT;
  1079.  
  1080.         /* 2bits: type */
  1081.         *color = style->border_color[0];
  1082.  
  1083.         return bits;
  1084. }
  1085. #undef CSS_BORDER_TOP_COLOR_MASK
  1086. #undef CSS_BORDER_TOP_COLOR_SHIFT
  1087. #undef CSS_BORDER_TOP_COLOR_INDEX
  1088.  
  1089. #define CSS_BORDER_RIGHT_COLOR_INDEX 7
  1090. #define CSS_BORDER_RIGHT_COLOR_SHIFT 0
  1091. #define CSS_BORDER_RIGHT_COLOR_MASK  0x3
  1092. uint8_t css_computed_border_right_color(
  1093.                 const css_computed_style *style,
  1094.                 css_color *color)
  1095. {
  1096.         uint8_t bits = style->bits[CSS_BORDER_RIGHT_COLOR_INDEX];
  1097.         bits &= CSS_BORDER_RIGHT_COLOR_MASK;
  1098.         bits >>= CSS_BORDER_RIGHT_COLOR_SHIFT;
  1099.  
  1100.         /* 2bits: type */
  1101.         *color = style->border_color[1];
  1102.  
  1103.         return bits;
  1104. }
  1105. #undef CSS_BORDER_RIGHT_COLOR_MASK
  1106. #undef CSS_BORDER_RIGHT_COLOR_SHIFT
  1107. #undef CSS_BORDER_RIGHT_COLOR_INDEX
  1108.  
  1109. #define CSS_BORDER_BOTTOM_COLOR_INDEX 8
  1110. #define CSS_BORDER_BOTTOM_COLOR_SHIFT 0
  1111. #define CSS_BORDER_BOTTOM_COLOR_MASK  0x3
  1112. uint8_t css_computed_border_bottom_color(
  1113.                 const css_computed_style *style,
  1114.                 css_color *color)
  1115. {
  1116.         uint8_t bits = style->bits[CSS_BORDER_BOTTOM_COLOR_INDEX];
  1117.         bits &= CSS_BORDER_BOTTOM_COLOR_MASK;
  1118.         bits >>= CSS_BORDER_BOTTOM_COLOR_SHIFT;
  1119.  
  1120.         /* 2bits: type */
  1121.         *color = style->border_color[2];
  1122.  
  1123.         return bits;
  1124. }
  1125. #undef CSS_BORDER_BOTTOM_COLOR_MASK
  1126. #undef CSS_BORDER_BOTTOM_COLOR_SHIFT
  1127. #undef CSS_BORDER_BOTTOM_COLOR_INDEX
  1128.  
  1129. #define CSS_BORDER_LEFT_COLOR_INDEX 9
  1130. #define CSS_BORDER_LEFT_COLOR_SHIFT 0
  1131. #define CSS_BORDER_LEFT_COLOR_MASK  0x3
  1132. uint8_t css_computed_border_left_color(
  1133.                 const css_computed_style *style,
  1134.                 css_color *color)
  1135. {
  1136.         uint8_t bits = style->bits[CSS_BORDER_LEFT_COLOR_INDEX];
  1137.         bits &= CSS_BORDER_LEFT_COLOR_MASK;
  1138.         bits >>= CSS_BORDER_LEFT_COLOR_SHIFT;
  1139.  
  1140.         /* 2bits: type */
  1141.         *color = style->border_color[3];
  1142.  
  1143.         return bits;
  1144. }
  1145. #undef CSS_BORDER_LEFT_COLOR_MASK
  1146. #undef CSS_BORDER_LEFT_COLOR_SHIFT
  1147. #undef CSS_BORDER_LEFT_COLOR_INDEX
  1148.  
  1149. #define CSS_HEIGHT_INDEX 10
  1150. #define CSS_HEIGHT_SHIFT 2
  1151. #define CSS_HEIGHT_MASK  0xfc
  1152. uint8_t css_computed_height(
  1153.                 const css_computed_style *style,
  1154.                 css_fixed *length, css_unit *unit)
  1155. {
  1156.         uint8_t bits = style->bits[CSS_HEIGHT_INDEX];
  1157.         bits &= CSS_HEIGHT_MASK;
  1158.         bits >>= CSS_HEIGHT_SHIFT;
  1159.  
  1160.         /* 6bits: uuuutt : units | type */
  1161.         if ((bits & 0x3) == CSS_HEIGHT_SET) {
  1162.                 *length = style->height;
  1163.                 *unit = (css_unit) (bits >> 2);
  1164.         }
  1165.  
  1166.         return (bits & 0x3);
  1167. }
  1168. #undef CSS_HEIGHT_MASK
  1169. #undef CSS_HEIGHT_SHIFT
  1170. #undef CSS_HEIGHT_INDEX
  1171.  
  1172. #define CSS_LINE_HEIGHT_INDEX 11
  1173. #define CSS_LINE_HEIGHT_SHIFT 2
  1174. #define CSS_LINE_HEIGHT_MASK  0xfc
  1175. uint8_t css_computed_line_height(
  1176.                 const css_computed_style *style,
  1177.                 css_fixed *length, css_unit *unit)
  1178. {
  1179.         uint8_t bits = style->bits[CSS_LINE_HEIGHT_INDEX];
  1180.         bits &= CSS_LINE_HEIGHT_MASK;
  1181.         bits >>= CSS_LINE_HEIGHT_SHIFT;
  1182.  
  1183.         /* 6bits: uuuutt : units | type */
  1184.         if ((bits & 0x3) == CSS_LINE_HEIGHT_NUMBER ||
  1185.                         (bits & 0x3) == CSS_LINE_HEIGHT_DIMENSION) {
  1186.                 *length = style->line_height;
  1187.         }
  1188.  
  1189.         if ((bits & 0x3) == CSS_LINE_HEIGHT_DIMENSION) {
  1190.                 *unit = (css_unit) (bits >> 2);
  1191.         }
  1192.  
  1193.         return (bits & 0x3);
  1194. }
  1195. #undef CSS_LINE_HEIGHT_MASK
  1196. #undef CSS_LINE_HEIGHT_SHIFT
  1197. #undef CSS_LINE_HEIGHT_INDEX
  1198.  
  1199. #define CSS_BACKGROUND_COLOR_INDEX 10
  1200. #define CSS_BACKGROUND_COLOR_SHIFT 0
  1201. #define CSS_BACKGROUND_COLOR_MASK  0x3
  1202. uint8_t css_computed_background_color(
  1203.                 const css_computed_style *style,
  1204.                 css_color *color)
  1205. {
  1206.         uint8_t bits = style->bits[CSS_BACKGROUND_COLOR_INDEX];
  1207.         bits &= CSS_BACKGROUND_COLOR_MASK;
  1208.         bits >>= CSS_BACKGROUND_COLOR_SHIFT;
  1209.  
  1210.         /* 2bits: type */
  1211.         *color = style->background_color;
  1212.  
  1213.         return bits;
  1214. }
  1215. #undef CSS_BACKGROUND_COLOR_MASK
  1216. #undef CSS_BACKGROUND_COLOR_SHIFT
  1217. #undef CSS_BACKGROUND_COLOR_INDEX
  1218.  
  1219. #define CSS_Z_INDEX_INDEX 11
  1220. #define CSS_Z_INDEX_SHIFT 0
  1221. #define CSS_Z_INDEX_MASK  0x3
  1222. uint8_t css_computed_z_index(
  1223.                 const css_computed_style *style,
  1224.                 int32_t *z_index)
  1225. {
  1226.         uint8_t bits = style->bits[CSS_Z_INDEX_INDEX];
  1227.         bits &= CSS_Z_INDEX_MASK;
  1228.         bits >>= CSS_Z_INDEX_SHIFT;
  1229.  
  1230.         /* 2bits: type */
  1231.         *z_index = style->z_index;
  1232.  
  1233.         return bits;
  1234. }
  1235. #undef CSS_Z_INDEX_MASK
  1236. #undef CSS_Z_INDEX_SHIFT
  1237. #undef CSS_Z_INDEX_INDEX
  1238.  
  1239. #define CSS_MARGIN_TOP_INDEX 12
  1240. #define CSS_MARGIN_TOP_SHIFT 2
  1241. #define CSS_MARGIN_TOP_MASK  0xfc
  1242. uint8_t css_computed_margin_top(
  1243.                 const css_computed_style *style,
  1244.                 css_fixed *length, css_unit *unit)
  1245. {
  1246.         uint8_t bits = style->bits[CSS_MARGIN_TOP_INDEX];
  1247.         bits &= CSS_MARGIN_TOP_MASK;
  1248.         bits >>= CSS_MARGIN_TOP_SHIFT;
  1249.  
  1250.         /* 6bits: uuuutt : units | type */
  1251.         if ((bits & 0x3) == CSS_MARGIN_SET) {
  1252.                 *length = style->margin[0];
  1253.                 *unit = (css_unit) (bits >> 2);
  1254.         }
  1255.  
  1256.         return (bits & 0x3);
  1257. }
  1258. #undef CSS_MARGIN_TOP_MASK
  1259. #undef CSS_MARGIN_TOP_SHIFT
  1260. #undef CSS_MARGIN_TOP_INDEX
  1261.  
  1262. #define CSS_MARGIN_RIGHT_INDEX 13
  1263. #define CSS_MARGIN_RIGHT_SHIFT 2
  1264. #define CSS_MARGIN_RIGHT_MASK  0xfc
  1265. uint8_t css_computed_margin_right(
  1266.                 const css_computed_style *style,
  1267.                 css_fixed *length, css_unit *unit)
  1268. {
  1269.         uint8_t bits = style->bits[CSS_MARGIN_RIGHT_INDEX];
  1270.         bits &= CSS_MARGIN_RIGHT_MASK;
  1271.         bits >>= CSS_MARGIN_RIGHT_SHIFT;
  1272.  
  1273.         /* 6bits: uuuutt : units | type */
  1274.         if ((bits & 0x3) == CSS_MARGIN_SET) {
  1275.                 *length = style->margin[1];
  1276.                 *unit = (css_unit) (bits >> 2);
  1277.         }
  1278.  
  1279.         return (bits & 0x3);
  1280. }
  1281. #undef CSS_MARGIN_RIGHT_MASK
  1282. #undef CSS_MARGIN_RIGHT_SHIFT
  1283. #undef CSS_MARGIN_RIGHT_INDEX
  1284.  
  1285. #define CSS_MARGIN_BOTTOM_INDEX 14
  1286. #define CSS_MARGIN_BOTTOM_SHIFT 2
  1287. #define CSS_MARGIN_BOTTOM_MASK  0xfc
  1288. uint8_t css_computed_margin_bottom(
  1289.                 const css_computed_style *style,
  1290.                 css_fixed *length, css_unit *unit)
  1291. {
  1292.         uint8_t bits = style->bits[CSS_MARGIN_BOTTOM_INDEX];
  1293.         bits &= CSS_MARGIN_BOTTOM_MASK;
  1294.         bits >>= CSS_MARGIN_BOTTOM_SHIFT;
  1295.  
  1296.         /* 6bits: uuuutt : units | type */
  1297.         if ((bits & 0x3) == CSS_MARGIN_SET) {
  1298.                 *length = style->margin[2];
  1299.                 *unit = (css_unit) (bits >> 2);
  1300.         }
  1301.  
  1302.         return (bits & 0x3);
  1303. }
  1304. #undef CSS_MARGIN_BOTTOM_MASK
  1305. #undef CSS_MARGIN_BOTTOM_SHIFT
  1306. #undef CSS_MARGIN_BOTTOM_INDEX
  1307.  
  1308. #define CSS_MARGIN_LEFT_INDEX 15
  1309. #define CSS_MARGIN_LEFT_SHIFT 2
  1310. #define CSS_MARGIN_LEFT_MASK  0xfc
  1311. uint8_t css_computed_margin_left(
  1312.                 const css_computed_style *style,
  1313.                 css_fixed *length, css_unit *unit)
  1314. {
  1315.         uint8_t bits = style->bits[CSS_MARGIN_LEFT_INDEX];
  1316.         bits &= CSS_MARGIN_LEFT_MASK;
  1317.         bits >>= CSS_MARGIN_LEFT_SHIFT;
  1318.  
  1319.         /* 6bits: uuuutt : units | type */
  1320.         if ((bits & 0x3) == CSS_MARGIN_SET) {
  1321.                 *length = style->margin[3];
  1322.                 *unit = (css_unit) (bits >> 2);
  1323.         }
  1324.  
  1325.         return (bits & 0x3);
  1326. }
  1327. #undef CSS_MARGIN_LEFT_MASK
  1328. #undef CSS_MARGIN_LEFT_SHIFT
  1329. #undef CSS_MARGIN_LEFT_INDEX
  1330.  
  1331. #define CSS_BACKGROUND_ATTACHMENT_INDEX 12
  1332. #define CSS_BACKGROUND_ATTACHMENT_SHIFT 0
  1333. #define CSS_BACKGROUND_ATTACHMENT_MASK  0x3
  1334. uint8_t css_computed_background_attachment(
  1335.                 const css_computed_style *style)
  1336. {
  1337.         uint8_t bits = style->bits[CSS_BACKGROUND_ATTACHMENT_INDEX];
  1338.         bits &= CSS_BACKGROUND_ATTACHMENT_MASK;
  1339.         bits >>= CSS_BACKGROUND_ATTACHMENT_SHIFT;
  1340.  
  1341.         /* 2bits: type */
  1342.         return bits;
  1343. }
  1344. #undef CSS_BACKGROUND_ATTACHMENT_MASK
  1345. #undef CSS_BACKGROUND_ATTACHMENT_SHIFT
  1346. #undef CSS_BACKGROUND_ATTACHMENT_INDEX
  1347.  
  1348. #define CSS_BORDER_COLLAPSE_INDEX 13
  1349. #define CSS_BORDER_COLLAPSE_SHIFT 0
  1350. #define CSS_BORDER_COLLAPSE_MASK  0x3
  1351. uint8_t css_computed_border_collapse(
  1352.                 const css_computed_style *style)
  1353. {
  1354.         uint8_t bits = style->bits[CSS_BORDER_COLLAPSE_INDEX];
  1355.         bits &= CSS_BORDER_COLLAPSE_MASK;
  1356.         bits >>= CSS_BORDER_COLLAPSE_SHIFT;
  1357.  
  1358.         /* 2bits: type */
  1359.         return bits;
  1360. }
  1361. #undef CSS_BORDER_COLLAPSE_MASK
  1362. #undef CSS_BORDER_COLLAPSE_SHIFT
  1363. #undef CSS_BORDER_COLLAPSE_INDEX
  1364.  
  1365. #define CSS_CAPTION_SIDE_INDEX 14
  1366. #define CSS_CAPTION_SIDE_SHIFT 0
  1367. #define CSS_CAPTION_SIDE_MASK  0x3
  1368. uint8_t css_computed_caption_side(
  1369.                 const css_computed_style *style)
  1370. {
  1371.         uint8_t bits = style->bits[CSS_CAPTION_SIDE_INDEX];
  1372.         bits &= CSS_CAPTION_SIDE_MASK;
  1373.         bits >>= CSS_CAPTION_SIDE_SHIFT;
  1374.  
  1375.         /* 2bits: type */
  1376.         return bits;
  1377. }
  1378. #undef CSS_CAPTION_SIDE_MASK
  1379. #undef CSS_CAPTION_SIDE_SHIFT
  1380. #undef CSS_CAPTION_SIDE_INDEX
  1381.  
  1382. #define CSS_DIRECTION_INDEX 15
  1383. #define CSS_DIRECTION_SHIFT 0
  1384. #define CSS_DIRECTION_MASK  0x3
  1385. uint8_t css_computed_direction(
  1386.                 const css_computed_style *style)
  1387. {
  1388.         uint8_t bits = style->bits[CSS_DIRECTION_INDEX];
  1389.         bits &= CSS_DIRECTION_MASK;
  1390.         bits >>= CSS_DIRECTION_SHIFT;
  1391.  
  1392.         /* 2bits: type */
  1393.         return bits;
  1394. }
  1395. #undef CSS_DIRECTION_MASK
  1396. #undef CSS_DIRECTION_SHIFT
  1397. #undef CSS_DIRECTION_INDEX
  1398.  
  1399. #define CSS_MAX_HEIGHT_INDEX 16
  1400. #define CSS_MAX_HEIGHT_SHIFT 2
  1401. #define CSS_MAX_HEIGHT_MASK  0xfc
  1402. uint8_t css_computed_max_height(
  1403.                 const css_computed_style *style,
  1404.                 css_fixed *length, css_unit *unit)
  1405. {
  1406.         uint8_t bits = style->bits[CSS_MAX_HEIGHT_INDEX];
  1407.         bits &= CSS_MAX_HEIGHT_MASK;
  1408.         bits >>= CSS_MAX_HEIGHT_SHIFT;
  1409.  
  1410.         /* 6bits: uuuutt : units | type */
  1411.         if ((bits & 0x3) == CSS_MAX_HEIGHT_SET) {
  1412.                 *length = style->max_height;
  1413.                 *unit = (css_unit) (bits >> 2);
  1414.         }
  1415.  
  1416.         return (bits & 0x3);
  1417. }
  1418. #undef CSS_MAX_HEIGHT_MASK
  1419. #undef CSS_MAX_HEIGHT_SHIFT
  1420. #undef CSS_MAX_HEIGHT_INDEX
  1421.  
  1422. #define CSS_MAX_WIDTH_INDEX 17
  1423. #define CSS_MAX_WIDTH_SHIFT 2
  1424. #define CSS_MAX_WIDTH_MASK  0xfc
  1425. uint8_t css_computed_max_width(
  1426.                 const css_computed_style *style,
  1427.                 css_fixed *length, css_unit *unit)
  1428. {
  1429.         uint8_t bits = style->bits[CSS_MAX_WIDTH_INDEX];
  1430.         bits &= CSS_MAX_WIDTH_MASK;
  1431.         bits >>= CSS_MAX_WIDTH_SHIFT;
  1432.  
  1433.         /* 6bits: uuuutt : units | type */
  1434.         if ((bits & 0x3) == CSS_MAX_WIDTH_SET) {
  1435.                 *length = style->max_width;
  1436.                 *unit = (css_unit) (bits >> 2);
  1437.         }
  1438.  
  1439.         return (bits & 0x3);
  1440. }
  1441. #undef CSS_MAX_WIDTH_MASK
  1442. #undef CSS_MAX_WIDTH_SHIFT
  1443. #undef CSS_MAX_WIDTH_INDEX
  1444.  
  1445. #define CSS_WIDTH_INDEX 18
  1446. #define CSS_WIDTH_SHIFT 2
  1447. #define CSS_WIDTH_MASK  0xfc
  1448. uint8_t css_computed_width(
  1449.                 const css_computed_style *style,
  1450.                 css_fixed *length, css_unit *unit)
  1451. {
  1452.         uint8_t bits = style->bits[CSS_WIDTH_INDEX];
  1453.         bits &= CSS_WIDTH_MASK;
  1454.         bits >>= CSS_WIDTH_SHIFT;
  1455.  
  1456.         /* 6bits: uuuutt : units | type */
  1457.         if ((bits & 0x3) == CSS_WIDTH_SET) {
  1458.                 *length = style->width;
  1459.                 *unit = (css_unit) (bits >> 2);
  1460.         }
  1461.  
  1462.         return (bits & 0x3);
  1463. }
  1464. #undef CSS_WIDTH_MASK
  1465. #undef CSS_WIDTH_SHIFT
  1466. #undef CSS_WIDTH_INDEX
  1467.  
  1468. #define CSS_EMPTY_CELLS_INDEX 16
  1469. #define CSS_EMPTY_CELLS_SHIFT 0
  1470. #define CSS_EMPTY_CELLS_MASK  0x3
  1471. uint8_t css_computed_empty_cells(
  1472.                 const css_computed_style *style)
  1473. {
  1474.         uint8_t bits = style->bits[CSS_EMPTY_CELLS_INDEX];
  1475.         bits &= CSS_EMPTY_CELLS_MASK;
  1476.         bits >>= CSS_EMPTY_CELLS_SHIFT;
  1477.  
  1478.         /* 2bits: type */
  1479.         return bits;
  1480. }
  1481. #undef CSS_EMPTY_CELLS_MASK
  1482. #undef CSS_EMPTY_CELLS_SHIFT
  1483. #undef CSS_EMPTY_CELLS_INDEX
  1484.  
  1485. #define CSS_FLOAT_INDEX 17
  1486. #define CSS_FLOAT_SHIFT 0
  1487. #define CSS_FLOAT_MASK  0x3
  1488. uint8_t css_computed_float(
  1489.                 const css_computed_style *style)
  1490. {
  1491.         uint8_t bits = style->bits[CSS_FLOAT_INDEX];
  1492.         bits &= CSS_FLOAT_MASK;
  1493.         bits >>= CSS_FLOAT_SHIFT;
  1494.  
  1495.         /* Fix up as per $9.7:2 */
  1496.         if (css_computed_position(style) == CSS_POSITION_ABSOLUTE ||
  1497.                         css_computed_position(style) == CSS_POSITION_FIXED)
  1498.                 return CSS_FLOAT_NONE;
  1499.  
  1500.         /* 2bits: type */
  1501.         return bits;
  1502. }
  1503. #undef CSS_FLOAT_MASK
  1504. #undef CSS_FLOAT_SHIFT
  1505. #undef CSS_FLOAT_INDEX
  1506.  
  1507. #define CSS_FONT_STYLE_INDEX 18
  1508. #define CSS_FONT_STYLE_SHIFT 0
  1509. #define CSS_FONT_STYLE_MASK  0x3
  1510. uint8_t css_computed_font_style(
  1511.                 const css_computed_style *style)
  1512. {
  1513.         uint8_t bits = style->bits[CSS_FONT_STYLE_INDEX];
  1514.         bits &= CSS_FONT_STYLE_MASK;
  1515.         bits >>= CSS_FONT_STYLE_SHIFT;
  1516.  
  1517.         /* 2bits: type */
  1518.         return bits;
  1519. }
  1520. #undef CSS_FONT_STYLE_MASK
  1521. #undef CSS_FONT_STYLE_SHIFT
  1522. #undef CSS_FONT_STYLE_INDEX
  1523.  
  1524. #define CSS_MIN_HEIGHT_INDEX 19
  1525. #define CSS_MIN_HEIGHT_SHIFT 3
  1526. #define CSS_MIN_HEIGHT_MASK  0xf8
  1527. uint8_t css_computed_min_height(
  1528.                 const css_computed_style *style,
  1529.                 css_fixed *length, css_unit *unit)
  1530. {
  1531.         uint8_t bits = style->bits[CSS_MIN_HEIGHT_INDEX];
  1532.         bits &= CSS_MIN_HEIGHT_MASK;
  1533.         bits >>= CSS_MIN_HEIGHT_SHIFT;
  1534.  
  1535.         /* 5bits: uuuut : units | type */
  1536.         if ((bits & 0x1) == CSS_MIN_HEIGHT_SET) {
  1537.                 *length = style->min_height;
  1538.                 *unit = (css_unit) (bits >> 1);
  1539.         }
  1540.  
  1541.         return (bits & 0x1);
  1542. }
  1543. #undef CSS_MIN_HEIGHT_MASK
  1544. #undef CSS_MIN_HEIGHT_SHIFT
  1545. #undef CSS_MIN_HEIGHT_INDEX
  1546.  
  1547. #define CSS_MIN_WIDTH_INDEX 20
  1548. #define CSS_MIN_WIDTH_SHIFT 3
  1549. #define CSS_MIN_WIDTH_MASK  0xf8
  1550. uint8_t css_computed_min_width(
  1551.                 const css_computed_style *style,
  1552.                 css_fixed *length, css_unit *unit)
  1553. {
  1554.         uint8_t bits = style->bits[CSS_MIN_WIDTH_INDEX];
  1555.         bits &= CSS_MIN_WIDTH_MASK;
  1556.         bits >>= CSS_MIN_WIDTH_SHIFT;
  1557.  
  1558.         /* 5bits: uuuut : units | type */
  1559.         if ((bits & 0x1) == CSS_MIN_WIDTH_SET) {
  1560.                 *length = style->min_width;
  1561.                 *unit = (css_unit) (bits >> 1);
  1562.         }
  1563.  
  1564.         return (bits & 0x1);
  1565. }
  1566. #undef CSS_MIN_WIDTH_MASK
  1567. #undef CSS_MIN_WIDTH_SHIFT
  1568. #undef CSS_MIN_WIDTH_INDEX
  1569.  
  1570. #define CSS_BACKGROUND_REPEAT_INDEX 19
  1571. #define CSS_BACKGROUND_REPEAT_SHIFT 0
  1572. #define CSS_BACKGROUND_REPEAT_MASK  0x7
  1573. uint8_t css_computed_background_repeat(
  1574.                 const css_computed_style *style)
  1575. {
  1576.         uint8_t bits = style->bits[CSS_BACKGROUND_REPEAT_INDEX];
  1577.         bits &= CSS_BACKGROUND_REPEAT_MASK;
  1578.         bits >>= CSS_BACKGROUND_REPEAT_SHIFT;
  1579.  
  1580.         /* 3bits: type */
  1581.         return bits;
  1582. }
  1583. #undef CSS_BACKGROUND_REPEAT_MASK
  1584. #undef CSS_BACKGROUND_REPEAT_SHIFT
  1585. #undef CSS_BACKGROUND_REPEAT_INDEX
  1586.  
  1587. #define CSS_CLEAR_INDEX 20
  1588. #define CSS_CLEAR_SHIFT 0
  1589. #define CSS_CLEAR_MASK  0x7
  1590. uint8_t css_computed_clear(
  1591.                 const css_computed_style *style)
  1592. {
  1593.         uint8_t bits = style->bits[CSS_CLEAR_INDEX];
  1594.         bits &= CSS_CLEAR_MASK;
  1595.         bits >>= CSS_CLEAR_SHIFT;
  1596.  
  1597.         /* 3bits: type */
  1598.         return bits;
  1599. }
  1600. #undef CSS_CLEAR_MASK
  1601. #undef CSS_CLEAR_SHIFT
  1602. #undef CSS_CLEAR_INDEX
  1603.  
  1604. #define CSS_PADDING_TOP_INDEX 21
  1605. #define CSS_PADDING_TOP_SHIFT 3
  1606. #define CSS_PADDING_TOP_MASK  0xf8
  1607. uint8_t css_computed_padding_top(
  1608.                 const css_computed_style *style,
  1609.                 css_fixed *length, css_unit *unit)
  1610. {
  1611.         uint8_t bits = style->bits[CSS_PADDING_TOP_INDEX];
  1612.         bits &= CSS_PADDING_TOP_MASK;
  1613.         bits >>= CSS_PADDING_TOP_SHIFT;
  1614.  
  1615.         /* 5bits: uuuut : units | type */
  1616.         if ((bits & 0x1) == CSS_PADDING_SET) {
  1617.                 *length = style->padding[0];
  1618.                 *unit = (css_unit) (bits >> 1);
  1619.         }
  1620.  
  1621.         return (bits & 0x1);
  1622. }
  1623. #undef CSS_PADDING_TOP_MASK
  1624. #undef CSS_PADDING_TOP_SHIFT
  1625. #undef CSS_PADDING_TOP_INDEX
  1626.  
  1627. #define CSS_PADDING_RIGHT_INDEX 22
  1628. #define CSS_PADDING_RIGHT_SHIFT 3
  1629. #define CSS_PADDING_RIGHT_MASK  0xf8
  1630. uint8_t css_computed_padding_right(
  1631.                 const css_computed_style *style,
  1632.                 css_fixed *length, css_unit *unit)
  1633. {
  1634.         uint8_t bits = style->bits[CSS_PADDING_RIGHT_INDEX];
  1635.         bits &= CSS_PADDING_RIGHT_MASK;
  1636.         bits >>= CSS_PADDING_RIGHT_SHIFT;
  1637.  
  1638.         /* 5bits: uuuut : units | type */
  1639.         if ((bits & 0x1) == CSS_PADDING_SET) {
  1640.                 *length = style->padding[1];
  1641.                 *unit = (css_unit) (bits >> 1);
  1642.         }
  1643.  
  1644.         return (bits & 0x1);
  1645. }
  1646. #undef CSS_PADDING_RIGHT_MASK
  1647. #undef CSS_PADDING_RIGHT_SHIFT
  1648. #undef CSS_PADDING_RIGHT_INDEX
  1649.  
  1650. #define CSS_PADDING_BOTTOM_INDEX 23
  1651. #define CSS_PADDING_BOTTOM_SHIFT 3
  1652. #define CSS_PADDING_BOTTOM_MASK  0xf8
  1653. uint8_t css_computed_padding_bottom(
  1654.                 const css_computed_style *style,
  1655.                 css_fixed *length, css_unit *unit)
  1656. {
  1657.         uint8_t bits = style->bits[CSS_PADDING_BOTTOM_INDEX];
  1658.         bits &= CSS_PADDING_BOTTOM_MASK;
  1659.         bits >>= CSS_PADDING_BOTTOM_SHIFT;
  1660.  
  1661.         /* 5bits: uuuut : units | type */
  1662.         if ((bits & 0x1) == CSS_PADDING_SET) {
  1663.                 *length = style->padding[2];
  1664.                 *unit = (css_unit) (bits >> 1);
  1665.         }
  1666.  
  1667.         return (bits & 0x1);
  1668. }
  1669. #undef CSS_PADDING_BOTTOM_MASK
  1670. #undef CSS_PADDING_BOTTOM_SHIFT
  1671. #undef CSS_PADDING_BOTTOM_INDEX
  1672.  
  1673. #define CSS_PADDING_LEFT_INDEX 24
  1674. #define CSS_PADDING_LEFT_SHIFT 3
  1675. #define CSS_PADDING_LEFT_MASK  0xf8
  1676. uint8_t css_computed_padding_left(
  1677.                 const css_computed_style *style,
  1678.                 css_fixed *length, css_unit *unit)
  1679. {
  1680.         uint8_t bits = style->bits[CSS_PADDING_LEFT_INDEX];
  1681.         bits &= CSS_PADDING_LEFT_MASK;
  1682.         bits >>= CSS_PADDING_LEFT_SHIFT;
  1683.  
  1684.         /* 5bits: uuuut : units | type */
  1685.         if ((bits & 0x1) == CSS_PADDING_SET) {
  1686.                 *length = style->padding[3];
  1687.                 *unit = (css_unit) (bits >> 1);
  1688.         }
  1689.  
  1690.         return (bits & 0x1);
  1691. }
  1692. #undef CSS_PADDING_LEFT_MASK
  1693. #undef CSS_PADDING_LEFT_SHIFT
  1694. #undef CSS_PADDING_LEFT_INDEX
  1695.  
  1696. #define CSS_OVERFLOW_INDEX 21
  1697. #define CSS_OVERFLOW_SHIFT 0
  1698. #define CSS_OVERFLOW_MASK  0x7
  1699. uint8_t css_computed_overflow(
  1700.                 const css_computed_style *style)
  1701. {
  1702.         uint8_t bits = style->bits[CSS_OVERFLOW_INDEX];
  1703.         bits &= CSS_OVERFLOW_MASK;
  1704.         bits >>= CSS_OVERFLOW_SHIFT;
  1705.  
  1706.         /* 3bits: type */
  1707.         return bits;
  1708. }
  1709. #undef CSS_OVERFLOW_MASK
  1710. #undef CSS_OVERFLOW_SHIFT
  1711. #undef CSS_OVERFLOW_INDEX
  1712.  
  1713. #define CSS_POSITION_INDEX 22
  1714. #define CSS_POSITION_SHIFT 0
  1715. #define CSS_POSITION_MASK  0x7
  1716. uint8_t css_computed_position(
  1717.                 const css_computed_style *style)
  1718. {
  1719.         uint8_t bits = style->bits[CSS_POSITION_INDEX];
  1720.         bits &= CSS_POSITION_MASK;
  1721.         bits >>= CSS_POSITION_SHIFT;
  1722.  
  1723.         /* 3bits: type */
  1724.         return bits;
  1725. }
  1726. #undef CSS_POSITION_MASK
  1727. #undef CSS_POSITION_SHIFT
  1728. #undef CSS_POSITION_INDEX
  1729.  
  1730. #define CSS_OPACITY_INDEX 23
  1731. #define CSS_OPACITY_SHIFT 2
  1732. #define CSS_OPACITY_MASK  0x04
  1733. uint8_t css_computed_opacity(
  1734.                 const css_computed_style *style,
  1735.                 css_fixed *opacity)
  1736. {
  1737.         uint8_t bits = style->bits[CSS_OPACITY_INDEX];
  1738.         bits &= CSS_OPACITY_MASK;
  1739.         bits >>= CSS_OPACITY_SHIFT;
  1740.  
  1741.         /* 1bit: t : type */
  1742.         if ((bits & 0x1) == CSS_OPACITY_SET) {
  1743.                 *opacity = style->opacity;
  1744.         }
  1745.  
  1746.         return (bits & 0x1);
  1747. }
  1748. #undef CSS_OPACITY_MASK
  1749. #undef CSS_OPACITY_SHIFT
  1750. #undef CSS_OPACITY_INDEX
  1751.  
  1752. #define CSS_TEXT_TRANSFORM_INDEX 24
  1753. #define CSS_TEXT_TRANSFORM_SHIFT 0
  1754. #define CSS_TEXT_TRANSFORM_MASK  0x7
  1755. uint8_t css_computed_text_transform(
  1756.                 const css_computed_style *style)
  1757. {
  1758.         uint8_t bits = style->bits[CSS_TEXT_TRANSFORM_INDEX];
  1759.         bits &= CSS_TEXT_TRANSFORM_MASK;
  1760.         bits >>= CSS_TEXT_TRANSFORM_SHIFT;
  1761.  
  1762.         /* 3bits: type */
  1763.         return bits;
  1764. }
  1765. #undef CSS_TEXT_TRANSFORM_MASK
  1766. #undef CSS_TEXT_TRANSFORM_SHIFT
  1767. #undef CSS_TEXT_TRANSFORM_INDEX
  1768.  
  1769. #define CSS_TEXT_INDENT_INDEX 25
  1770. #define CSS_TEXT_INDENT_SHIFT 3
  1771. #define CSS_TEXT_INDENT_MASK  0xf8
  1772. uint8_t css_computed_text_indent(
  1773.                 const css_computed_style *style,
  1774.                 css_fixed *length, css_unit *unit)
  1775. {
  1776.         uint8_t bits = style->bits[CSS_TEXT_INDENT_INDEX];
  1777.         bits &= CSS_TEXT_INDENT_MASK;
  1778.         bits >>= CSS_TEXT_INDENT_SHIFT;
  1779.  
  1780.         /* 5bits: uuuut : units | type */
  1781.         if ((bits & 0x1) == CSS_TEXT_INDENT_SET) {
  1782.                 *length = style->text_indent;
  1783.                 *unit = (css_unit) (bits >> 1);
  1784.         }
  1785.  
  1786.         return (bits & 0x1);
  1787. }
  1788. #undef CSS_TEXT_INDENT_MASK
  1789. #undef CSS_TEXT_INDENT_SHIFT
  1790. #undef CSS_TEXT_INDENT_INDEX
  1791.  
  1792. #define CSS_WHITE_SPACE_INDEX 25
  1793. #define CSS_WHITE_SPACE_SHIFT 0
  1794. #define CSS_WHITE_SPACE_MASK  0x7
  1795. uint8_t css_computed_white_space(
  1796.                 const css_computed_style *style)
  1797. {
  1798.         uint8_t bits = style->bits[CSS_WHITE_SPACE_INDEX];
  1799.         bits &= CSS_WHITE_SPACE_MASK;
  1800.         bits >>= CSS_WHITE_SPACE_SHIFT;
  1801.  
  1802.         /* 3bits: type */
  1803.         return bits;
  1804. }
  1805. #undef CSS_WHITE_SPACE_MASK
  1806. #undef CSS_WHITE_SPACE_SHIFT
  1807. #undef CSS_WHITE_SPACE_INDEX
  1808.  
  1809. #define CSS_BACKGROUND_POSITION_INDEX 27
  1810. #define CSS_BACKGROUND_POSITION_SHIFT 7
  1811. #define CSS_BACKGROUND_POSITION_MASK  0x80
  1812. #define CSS_BACKGROUND_POSITION_INDEX1 26
  1813. #define CSS_BACKGROUND_POSITION_SHIFT1 0
  1814. #define CSS_BACKGROUND_POSITION_MASK1 0xff
  1815. uint8_t css_computed_background_position(
  1816.                 const css_computed_style *style,
  1817.                 css_fixed *hlength, css_unit *hunit,
  1818.                 css_fixed *vlength, css_unit *vunit)
  1819. {
  1820.         uint8_t bits = style->bits[CSS_BACKGROUND_POSITION_INDEX];
  1821.         bits &= CSS_BACKGROUND_POSITION_MASK;
  1822.         bits >>= CSS_BACKGROUND_POSITION_SHIFT;
  1823.  
  1824.         /* 1bit: type */
  1825.         if (bits == CSS_BACKGROUND_POSITION_SET) {
  1826.                 uint8_t bits1 = style->bits[CSS_BACKGROUND_POSITION_INDEX1];
  1827.                 bits1 &= CSS_BACKGROUND_POSITION_MASK1;
  1828.                 bits1 >>= CSS_BACKGROUND_POSITION_SHIFT1;
  1829.  
  1830.                 /* 8bits: hhhhvvvv : hunit | vunit */
  1831.                 *hlength = style->background_position[0];
  1832.                 *hunit = (css_unit) (bits1 >> 4);
  1833.  
  1834.                 *vlength = style->background_position[1];
  1835.                 *vunit = (css_unit) (bits1 & 0xf);
  1836.         }
  1837.  
  1838.         return bits;
  1839. }
  1840. #undef CSS_BACKGROUND_POSITION_MASK1
  1841. #undef CSS_BACKGROUND_POSITION_SHIFT1
  1842. #undef CSS_BACKGROUND_POSITION_INDEX1
  1843. #undef CSS_BACKGROUND_POSITION_MASK
  1844. #undef CSS_BACKGROUND_POSITION_SHIFT
  1845. #undef CSS_BACKGROUND_POSITION_INDEX
  1846.  
  1847. #define CSS_DISPLAY_INDEX 27
  1848. #define CSS_DISPLAY_SHIFT 2
  1849. #define CSS_DISPLAY_MASK  0x7c
  1850. uint8_t css_computed_display(
  1851.                 const css_computed_style *style, bool root)
  1852. {
  1853.         uint8_t position;
  1854.         uint8_t bits = style->bits[CSS_DISPLAY_INDEX];
  1855.         bits &= CSS_DISPLAY_MASK;
  1856.         bits >>= CSS_DISPLAY_SHIFT;
  1857.  
  1858.         /* Return computed display as per $9.7 */
  1859.         position = css_computed_position(style);
  1860.  
  1861.         /* 5bits: type */
  1862.         if (bits == CSS_DISPLAY_NONE)
  1863.                 return bits; /* 1. */
  1864.  
  1865.         if ((position == CSS_POSITION_ABSOLUTE ||
  1866.                         position == CSS_POSITION_FIXED) /* 2. */ ||
  1867.                         css_computed_float(style) != CSS_FLOAT_NONE /* 3. */ ||
  1868.                         root /* 4. */) {
  1869.                 if (bits == CSS_DISPLAY_INLINE_TABLE) {
  1870.                         return CSS_DISPLAY_TABLE;
  1871.                 } else if (bits == CSS_DISPLAY_INLINE ||
  1872.                                 bits == CSS_DISPLAY_RUN_IN ||
  1873.                                 bits == CSS_DISPLAY_TABLE_ROW_GROUP ||
  1874.                                 bits == CSS_DISPLAY_TABLE_COLUMN ||
  1875.                                 bits == CSS_DISPLAY_TABLE_COLUMN_GROUP ||
  1876.                                 bits == CSS_DISPLAY_TABLE_HEADER_GROUP ||
  1877.                                 bits == CSS_DISPLAY_TABLE_FOOTER_GROUP ||
  1878.                                 bits == CSS_DISPLAY_TABLE_ROW ||
  1879.                                 bits == CSS_DISPLAY_TABLE_CELL ||
  1880.                                 bits == CSS_DISPLAY_TABLE_CAPTION ||
  1881.                                 bits == CSS_DISPLAY_INLINE_BLOCK) {
  1882.                         return CSS_DISPLAY_BLOCK;
  1883.                 }
  1884.         }
  1885.  
  1886.         /* 5. */
  1887.         return bits;
  1888. }
  1889.  
  1890. uint8_t css_computed_display_static(
  1891.                 const css_computed_style *style)
  1892. {
  1893.         uint8_t bits = style->bits[CSS_DISPLAY_INDEX];
  1894.         bits &= CSS_DISPLAY_MASK;
  1895.         bits >>= CSS_DISPLAY_SHIFT;
  1896.  
  1897.         /* 5bits: type */
  1898.         return bits;
  1899. }
  1900.  
  1901. #undef CSS_DISPLAY_MASK
  1902. #undef CSS_DISPLAY_SHIFT
  1903. #undef CSS_DISPLAY_INDEX
  1904.  
  1905. #define CSS_FONT_VARIANT_INDEX 27
  1906. #define CSS_FONT_VARIANT_SHIFT 0
  1907. #define CSS_FONT_VARIANT_MASK  0x3
  1908. uint8_t css_computed_font_variant(
  1909.                 const css_computed_style *style)
  1910. {
  1911.         uint8_t bits = style->bits[CSS_FONT_VARIANT_INDEX];
  1912.         bits &= CSS_FONT_VARIANT_MASK;
  1913.         bits >>= CSS_FONT_VARIANT_SHIFT;
  1914.  
  1915.         /* 2bits: type */
  1916.         return bits;
  1917. }
  1918. #undef CSS_FONT_VARIANT_MASK
  1919. #undef CSS_FONT_VARIANT_SHIFT
  1920. #undef CSS_FONT_VARIANT_INDEX
  1921.  
  1922. #define CSS_TEXT_DECORATION_INDEX 28
  1923. #define CSS_TEXT_DECORATION_SHIFT 3
  1924. #define CSS_TEXT_DECORATION_MASK  0xf8
  1925. uint8_t css_computed_text_decoration(
  1926.                 const css_computed_style *style)
  1927. {
  1928.         uint8_t bits = style->bits[CSS_TEXT_DECORATION_INDEX];
  1929.         bits &= CSS_TEXT_DECORATION_MASK;
  1930.         bits >>= CSS_TEXT_DECORATION_SHIFT;
  1931.  
  1932.         /* 5bits: type */
  1933.         return bits;
  1934. }
  1935. #undef CSS_TEXT_DECORATION_MASK
  1936. #undef CSS_TEXT_DECORATION_SHIFT
  1937. #undef CSS_TEXT_DECORATION_INDEX
  1938.  
  1939. #define CSS_FONT_FAMILY_INDEX 28
  1940. #define CSS_FONT_FAMILY_SHIFT 0
  1941. #define CSS_FONT_FAMILY_MASK  0x7
  1942. uint8_t css_computed_font_family(
  1943.                 const css_computed_style *style,
  1944.                 lwc_string ***names)
  1945. {
  1946.         uint8_t bits = style->bits[CSS_FONT_FAMILY_INDEX];
  1947.         bits &= CSS_FONT_FAMILY_MASK;
  1948.         bits >>= CSS_FONT_FAMILY_SHIFT;
  1949.  
  1950.         /* 3bits: type */
  1951.         *names = style->font_family;
  1952.  
  1953.         return bits;
  1954. }
  1955. #undef CSS_FONT_FAMILY_MASK
  1956. #undef CSS_FONT_FAMILY_SHIFT
  1957. #undef CSS_FONT_FAMILY_INDEX
  1958.  
  1959. #define CSS_BORDER_TOP_STYLE_INDEX 29
  1960. #define CSS_BORDER_TOP_STYLE_SHIFT 4
  1961. #define CSS_BORDER_TOP_STYLE_MASK  0xf0
  1962. uint8_t css_computed_border_top_style(
  1963.                 const css_computed_style *style)
  1964. {
  1965.         uint8_t bits = style->bits[CSS_BORDER_TOP_STYLE_INDEX];
  1966.         bits &= CSS_BORDER_TOP_STYLE_MASK;
  1967.         bits >>= CSS_BORDER_TOP_STYLE_SHIFT;
  1968.  
  1969.         /* 4bits: type */
  1970.         return bits;
  1971. }
  1972. #undef CSS_BORDER_TOP_STYLE_MASK
  1973. #undef CSS_BORDER_TOP_STYLE_SHIFT
  1974. #undef CSS_BORDER_TOP_STYLE_INDEX
  1975.  
  1976. #define CSS_BORDER_RIGHT_STYLE_INDEX 29
  1977. #define CSS_BORDER_RIGHT_STYLE_SHIFT 0
  1978. #define CSS_BORDER_RIGHT_STYLE_MASK  0xf
  1979. uint8_t css_computed_border_right_style(
  1980.                 const css_computed_style *style)
  1981. {
  1982.         uint8_t bits = style->bits[CSS_BORDER_RIGHT_STYLE_INDEX];
  1983.         bits &= CSS_BORDER_RIGHT_STYLE_MASK;
  1984.         bits >>= CSS_BORDER_RIGHT_STYLE_SHIFT;
  1985.  
  1986.         /* 4bits: type */
  1987.         return bits;
  1988. }
  1989. #undef CSS_BORDER_RIGHT_STYLE_MASK
  1990. #undef CSS_BORDER_RIGHT_STYLE_SHIFT
  1991. #undef CSS_BORDER_RIGHT_STYLE_INDEX
  1992.  
  1993. #define CSS_BORDER_BOTTOM_STYLE_INDEX 30
  1994. #define CSS_BORDER_BOTTOM_STYLE_SHIFT 4
  1995. #define CSS_BORDER_BOTTOM_STYLE_MASK  0xf0
  1996. uint8_t css_computed_border_bottom_style(
  1997.                 const css_computed_style *style)
  1998. {
  1999.         uint8_t bits = style->bits[CSS_BORDER_BOTTOM_STYLE_INDEX];
  2000.         bits &= CSS_BORDER_BOTTOM_STYLE_MASK;
  2001.         bits >>= CSS_BORDER_BOTTOM_STYLE_SHIFT;
  2002.  
  2003.         /* 4bits: type */
  2004.         return bits;
  2005. }
  2006. #undef CSS_BORDER_BOTTOM_STYLE_MASK
  2007. #undef CSS_BORDER_BOTTOM_STYLE_SHIFT
  2008. #undef CSS_BORDER_BOTTOM_STYLE_INDEX
  2009.  
  2010. #define CSS_BORDER_LEFT_STYLE_INDEX 30
  2011. #define CSS_BORDER_LEFT_STYLE_SHIFT 0
  2012. #define CSS_BORDER_LEFT_STYLE_MASK  0xf
  2013. uint8_t css_computed_border_left_style(
  2014.                 const css_computed_style *style)
  2015. {
  2016.         uint8_t bits = style->bits[CSS_BORDER_LEFT_STYLE_INDEX];
  2017.         bits &= CSS_BORDER_LEFT_STYLE_MASK;
  2018.         bits >>= CSS_BORDER_LEFT_STYLE_SHIFT;
  2019.  
  2020.         /* 4bits: type */
  2021.         return bits;
  2022. }
  2023. #undef CSS_BORDER_LEFT_STYLE_MASK
  2024. #undef CSS_BORDER_LEFT_STYLE_SHIFT
  2025. #undef CSS_BORDER_LEFT_STYLE_INDEX
  2026.  
  2027. #define CSS_FONT_WEIGHT_INDEX 31
  2028. #define CSS_FONT_WEIGHT_SHIFT 4
  2029. #define CSS_FONT_WEIGHT_MASK  0xf0
  2030. uint8_t css_computed_font_weight(
  2031.                 const css_computed_style *style)
  2032. {
  2033.         uint8_t bits = style->bits[CSS_FONT_WEIGHT_INDEX];
  2034.         bits &= CSS_FONT_WEIGHT_MASK;
  2035.         bits >>= CSS_FONT_WEIGHT_SHIFT;
  2036.  
  2037.         /* 4bits: type */
  2038.         return bits;
  2039. }
  2040. #undef CSS_FONT_WEIGHT_MASK
  2041. #undef CSS_FONT_WEIGHT_SHIFT
  2042. #undef CSS_FONT_WEIGHT_INDEX
  2043.  
  2044. #define CSS_LIST_STYLE_TYPE_INDEX 31
  2045. #define CSS_LIST_STYLE_TYPE_SHIFT 0
  2046. #define CSS_LIST_STYLE_TYPE_MASK  0xf
  2047. uint8_t css_computed_list_style_type(
  2048.                 const css_computed_style *style)
  2049. {
  2050.         uint8_t bits = style->bits[CSS_LIST_STYLE_TYPE_INDEX];
  2051.         bits &= CSS_LIST_STYLE_TYPE_MASK;
  2052.         bits >>= CSS_LIST_STYLE_TYPE_SHIFT;
  2053.  
  2054.         /* 4bits: type */
  2055.         return bits;
  2056. }
  2057. #undef CSS_LIST_STYLE_TYPE_MASK
  2058. #undef CSS_LIST_STYLE_TYPE_SHIFT
  2059. #undef CSS_LIST_STYLE_TYPE_INDEX
  2060.  
  2061. #define CSS_OUTLINE_STYLE_INDEX 32
  2062. #define CSS_OUTLINE_STYLE_SHIFT 4
  2063. #define CSS_OUTLINE_STYLE_MASK  0xf0
  2064. uint8_t css_computed_outline_style(
  2065.                 const css_computed_style *style)
  2066. {
  2067.         uint8_t bits = style->bits[CSS_OUTLINE_STYLE_INDEX];
  2068.         bits &= CSS_OUTLINE_STYLE_MASK;
  2069.         bits >>= CSS_OUTLINE_STYLE_SHIFT;
  2070.  
  2071.         /* 4bits: type */
  2072.         return bits;
  2073. }
  2074. #undef CSS_OUTLINE_STYLE_MASK
  2075. #undef CSS_OUTLINE_STYLE_SHIFT
  2076. #undef CSS_OUTLINE_STYLE_INDEX
  2077.  
  2078. #define CSS_TABLE_LAYOUT_INDEX 32
  2079. #define CSS_TABLE_LAYOUT_SHIFT 2
  2080. #define CSS_TABLE_LAYOUT_MASK  0xc
  2081. uint8_t css_computed_table_layout(
  2082.                 const css_computed_style *style)
  2083. {
  2084.         uint8_t bits = style->bits[CSS_TABLE_LAYOUT_INDEX];
  2085.         bits &= CSS_TABLE_LAYOUT_MASK;
  2086.         bits >>= CSS_TABLE_LAYOUT_SHIFT;
  2087.  
  2088.         /* 2bits: type */
  2089.         return bits;
  2090. }
  2091. #undef CSS_TABLE_LAYOUT_MASK
  2092. #undef CSS_TABLE_LAYOUT_SHIFT
  2093. #undef CSS_TABLE_LAYOUT_INDEX
  2094.  
  2095. #define CSS_UNICODE_BIDI_INDEX 32
  2096. #define CSS_UNICODE_BIDI_SHIFT 0
  2097. #define CSS_UNICODE_BIDI_MASK  0x3
  2098. uint8_t css_computed_unicode_bidi(
  2099.                 const css_computed_style *style)
  2100. {
  2101.         uint8_t bits = style->bits[CSS_UNICODE_BIDI_INDEX];
  2102.         bits &= CSS_UNICODE_BIDI_MASK;
  2103.         bits >>= CSS_UNICODE_BIDI_SHIFT;
  2104.  
  2105.         /* 2bits: type */
  2106.         return bits;
  2107. }
  2108. #undef CSS_UNICODE_BIDI_MASK
  2109. #undef CSS_UNICODE_BIDI_SHIFT
  2110. #undef CSS_UNICODE_BIDI_INDEX
  2111.  
  2112. #define CSS_VISIBILITY_INDEX 33
  2113. #define CSS_VISIBILITY_SHIFT 6
  2114. #define CSS_VISIBILITY_MASK  0xc0
  2115. uint8_t css_computed_visibility(
  2116.                 const css_computed_style *style)
  2117. {
  2118.         uint8_t bits = style->bits[CSS_VISIBILITY_INDEX];
  2119.         bits &= CSS_VISIBILITY_MASK;
  2120.         bits >>= CSS_VISIBILITY_SHIFT;
  2121.  
  2122.         /* 2bits: type */
  2123.         return bits;
  2124. }
  2125. #undef CSS_VISIBILITY_MASK
  2126. #undef CSS_VISIBILITY_SHIFT
  2127. #undef CSS_VISIBILITY_INDEX
  2128.  
  2129. #define CSS_LIST_STYLE_POSITION_INDEX 33
  2130. #define CSS_LIST_STYLE_POSITION_SHIFT 4
  2131. #define CSS_LIST_STYLE_POSITION_MASK  0x30
  2132. uint8_t css_computed_list_style_position(
  2133.                 const css_computed_style *style)
  2134. {
  2135.         uint8_t bits = style->bits[CSS_LIST_STYLE_POSITION_INDEX];
  2136.         bits &= CSS_LIST_STYLE_POSITION_MASK;
  2137.         bits >>= CSS_LIST_STYLE_POSITION_SHIFT;
  2138.  
  2139.         /* 2bits: type */
  2140.         return bits;
  2141. }
  2142. #undef CSS_LIST_STYLE_POSITION_MASK
  2143. #undef CSS_LIST_STYLE_POSITION_SHIFT
  2144. #undef CSS_LIST_STYLE_POSITION_INDEX
  2145.  
  2146. #define CSS_TEXT_ALIGN_INDEX 33
  2147. #define CSS_TEXT_ALIGN_SHIFT 0
  2148. #define CSS_TEXT_ALIGN_MASK  0xf
  2149. uint8_t css_computed_text_align(
  2150.                 const css_computed_style *style)
  2151. {
  2152.         uint8_t bits = style->bits[CSS_TEXT_ALIGN_INDEX];
  2153.         bits &= CSS_TEXT_ALIGN_MASK;
  2154.         bits >>= CSS_TEXT_ALIGN_SHIFT;
  2155.  
  2156.         /* 4bits: type */
  2157.         return bits;
  2158. }
  2159. #undef CSS_TEXT_ALIGN_MASK
  2160. #undef CSS_TEXT_ALIGN_SHIFT
  2161. #undef CSS_TEXT_ALIGN_INDEX
  2162.  
  2163. #define CSS_PAGE_BREAK_AFTER_INDEX 0
  2164. #define CSS_PAGE_BREAK_AFTER_SHIFT 0
  2165. #define CSS_PAGE_BREAK_AFTER_MASK 0x7
  2166. uint8_t css_computed_page_break_after(
  2167.                 const css_computed_style *style)
  2168. {
  2169.         if (style->page != NULL) {
  2170.                 uint8_t bits = style->page->bits[CSS_PAGE_BREAK_AFTER_INDEX];
  2171.                 bits &= CSS_PAGE_BREAK_AFTER_MASK;
  2172.                 bits >>= CSS_PAGE_BREAK_AFTER_SHIFT;
  2173.        
  2174.                 /* 3bits: type */
  2175.                 return bits;
  2176.         }
  2177.    
  2178.         return CSS_PAGE_BREAK_AFTER_AUTO;
  2179. }
  2180. #undef CSS_PAGE_BREAK_AFTER_MASK
  2181. #undef CSS_PAGE_BREAK_AFTER_SHIFT
  2182. #undef CSS_PAGE_BREAK_AFTER_INDEX
  2183.  
  2184. #define CSS_PAGE_BREAK_BEFORE_INDEX 0
  2185. #define CSS_PAGE_BREAK_BEFORE_SHIFT 3
  2186. #define CSS_PAGE_BREAK_BEFORE_MASK 0x38
  2187. uint8_t css_computed_page_break_before(
  2188.                 const css_computed_style *style)
  2189. {
  2190.         if (style->page != NULL) {
  2191.                 uint8_t bits = style->page->bits[CSS_PAGE_BREAK_BEFORE_INDEX];
  2192.                 bits &= CSS_PAGE_BREAK_BEFORE_MASK;
  2193.                 bits >>= CSS_PAGE_BREAK_BEFORE_SHIFT;
  2194.        
  2195.                 /* 3bits: type */
  2196.                 return bits;
  2197.         }
  2198.    
  2199.         return CSS_PAGE_BREAK_BEFORE_AUTO;
  2200. }
  2201. #undef CSS_PAGE_BREAK_BEFORE_MASK
  2202. #undef CSS_PAGE_BREAK_BEFORE_SHIFT
  2203. #undef CSS_PAGE_BREAK_BEFORE_INDEX
  2204.    
  2205. #define CSS_PAGE_BREAK_INSIDE_INDEX 0
  2206. #define CSS_PAGE_BREAK_INSIDE_SHIFT 6
  2207. #define CSS_PAGE_BREAK_INSIDE_MASK 0xc0
  2208. uint8_t css_computed_page_break_inside(
  2209.             const css_computed_style *style)
  2210. {
  2211.         if (style->page != NULL) {
  2212.                 uint8_t bits = style->page->bits[CSS_PAGE_BREAK_INSIDE_INDEX];
  2213.                 bits &= CSS_PAGE_BREAK_INSIDE_MASK;
  2214.                 bits >>= CSS_PAGE_BREAK_INSIDE_SHIFT;
  2215.        
  2216.                 /* 2bits: type */
  2217.                 return bits;
  2218.         }
  2219.    
  2220.         return CSS_PAGE_BREAK_INSIDE_AUTO;
  2221. }
  2222. #undef CSS_PAGE_BREAK_INSIDE_MASK
  2223. #undef CSS_PAGE_BREAK_INSIDE_SHIFT
  2224. #undef CSS_PAGE_BREAK_INSIDE_INDEX
  2225.  
  2226. #define CSS_ORPHANS_INDEX 1
  2227. #define CSS_ORPHANS_SHIFT 0
  2228. #define CSS_ORPHANS_MASK  0x1
  2229. uint8_t css_computed_orphans(
  2230.                 const css_computed_style *style,
  2231.                 int32_t *orphans)
  2232. {
  2233.         if (style->page != NULL) {
  2234.                 uint8_t bits = style->page->bits[CSS_ORPHANS_INDEX];
  2235.                 bits &= CSS_ORPHANS_MASK;
  2236.                 bits >>= CSS_ORPHANS_SHIFT;
  2237.  
  2238.                 *orphans = FIXTOINT(style->page->orphans);;
  2239.  
  2240.                 /* 1bit: type */
  2241.                 return bits;
  2242.         }
  2243.  
  2244.         /* Use initial value */
  2245.         *orphans = 2;
  2246.  
  2247.         return CSS_ORPHANS_SET;
  2248. }
  2249. #undef CSS_ORPHANS_MASK
  2250. #undef CSS_ORPHANS_SHIFT
  2251. #undef CSS_ORPHANS_INDEX
  2252.  
  2253. #define CSS_WIDOWS_INDEX 1
  2254. #define CSS_WIDOWS_SHIFT 1
  2255. #define CSS_WIDOWS_MASK  0x2
  2256. uint8_t css_computed_widows(
  2257.                 const css_computed_style *style,
  2258.                 int32_t *widows)
  2259. {
  2260.         if (style->page != NULL) {
  2261.                 uint8_t bits = style->page->bits[CSS_WIDOWS_INDEX];
  2262.                 bits &= CSS_WIDOWS_MASK;
  2263.                 bits >>= CSS_WIDOWS_SHIFT;
  2264.  
  2265.                 *widows = FIXTOINT(style->page->widows);
  2266.  
  2267.                 /* 1bit: type */
  2268.                 return bits;
  2269.         }
  2270.  
  2271.         /* Use initial value */
  2272.         *widows = 2;
  2273.  
  2274.         return CSS_WIDOWS_SET;
  2275. }
  2276. #undef CSS_WIDOWS_MASK
  2277. #undef CSS_WIDOWS_SHIFT
  2278. #undef CSS_WIDOWS_INDEX
  2279.  
  2280.  
  2281. /******************************************************************************
  2282.  * Library internals                                                          *
  2283.  ******************************************************************************/
  2284.  
  2285. /**
  2286.  * Compute the absolute values of a style
  2287.  *
  2288.  * \param parent             Parent style, or NULL for tree root
  2289.  * \param style              Computed style to process
  2290.  * \param compute_font_size  Callback to calculate an absolute font-size
  2291.  * \param pw                 Private word for callback
  2292.  * \return CSS_OK on success.
  2293.  */
  2294. css_error css__compute_absolute_values(const css_computed_style *parent,
  2295.                 css_computed_style *style,
  2296.                 css_error (*compute_font_size)(void *pw,
  2297.                         const css_hint *parent, css_hint *size),
  2298.                 void *pw)
  2299. {
  2300.         css_hint psize, size, ex_size;
  2301.         css_error error;
  2302.  
  2303.         /* Ensure font-size is absolute */
  2304.         if (parent != NULL) {
  2305.                 psize.status = get_font_size(parent,
  2306.                                 &psize.data.length.value,
  2307.                                 &psize.data.length.unit);
  2308.         }
  2309.  
  2310.         size.status = get_font_size(style,
  2311.                         &size.data.length.value,
  2312.                         &size.data.length.unit);
  2313.  
  2314.         error = compute_font_size(pw, parent != NULL ? &psize : NULL, &size);
  2315.         if (error != CSS_OK)
  2316.                 return error;
  2317.  
  2318.         error = set_font_size(style, size.status,
  2319.                         size.data.length.value,
  2320.                         size.data.length.unit);
  2321.         if (error != CSS_OK)
  2322.                 return error;
  2323.  
  2324.         /* Compute the size of an ex unit */
  2325.         ex_size.status = CSS_FONT_SIZE_DIMENSION;
  2326.         ex_size.data.length.value = INTTOFIX(1);
  2327.         ex_size.data.length.unit = CSS_UNIT_EX;
  2328.         error = compute_font_size(pw, &size, &ex_size);
  2329.         if (error != CSS_OK)
  2330.                 return error;
  2331.  
  2332.         /* Convert ex size into ems */
  2333.         if (size.data.length.value != 0)
  2334.                 ex_size.data.length.value = FDIV(ex_size.data.length.value,
  2335.                                         size.data.length.value);
  2336.         else
  2337.                 ex_size.data.length.value = 0;
  2338.         ex_size.data.length.unit = CSS_UNIT_EM;
  2339.  
  2340.         /* Fix up background-position */
  2341.         error = compute_absolute_length_pair(style, &ex_size.data.length,
  2342.                         get_background_position,
  2343.                         set_background_position);
  2344.         if (error != CSS_OK)
  2345.                 return error;
  2346.  
  2347.         /* Fix up background-color */
  2348.         error = compute_absolute_color(style,
  2349.                         get_background_color,
  2350.                         set_background_color);
  2351.         if (error != CSS_OK)
  2352.                 return error;
  2353.  
  2354.         /* Fix up border-{top,right,bottom,left}-color */
  2355.         error = compute_border_colors(style);
  2356.         if (error != CSS_OK)
  2357.                 return error;
  2358.  
  2359.         /* Fix up border-{top,right,bottom,left}-width */
  2360.         error = compute_absolute_border_width(style, &ex_size.data.length);
  2361.         if (error != CSS_OK)
  2362.                 return error;
  2363.  
  2364.         /* Fix up sides */
  2365.         error = compute_absolute_sides(style, &ex_size.data.length);
  2366.         if (error != CSS_OK)
  2367.                 return error;
  2368.  
  2369.         /* Fix up height */
  2370.         error = compute_absolute_length_auto(style, &ex_size.data.length,
  2371.                         get_height, set_height);
  2372.         if (error != CSS_OK)
  2373.                 return error;
  2374.  
  2375.         /* Fix up line-height (must be before vertical-align) */
  2376.         error = compute_absolute_line_height(style, &ex_size.data.length);
  2377.         if (error != CSS_OK)
  2378.                 return error;
  2379.  
  2380.         /* Fix up margins */
  2381.         error = compute_absolute_margins(style, &ex_size.data.length);
  2382.         if (error != CSS_OK)
  2383.                 return error;
  2384.  
  2385.         /* Fix up max-height */
  2386.         error = compute_absolute_length_none(style, &ex_size.data.length,
  2387.                         get_max_height, set_max_height);
  2388.         if (error != CSS_OK)
  2389.                 return error;
  2390.  
  2391.         /* Fix up max-width */
  2392.         error = compute_absolute_length_none(style, &ex_size.data.length,
  2393.                         get_max_width, set_max_width);
  2394.         if (error != CSS_OK)
  2395.                 return error;
  2396.  
  2397.         /* Fix up min-height */
  2398.         error = compute_absolute_length(style, &ex_size.data.length,
  2399.                         get_min_height, set_min_height);
  2400.         if (error != CSS_OK)
  2401.                 return error;
  2402.  
  2403.         /* Fix up min-width */
  2404.         error = compute_absolute_length(style, &ex_size.data.length,
  2405.                         get_min_width, set_min_width);
  2406.         if (error != CSS_OK)
  2407.                 return error;
  2408.  
  2409.         /* Fix up padding */
  2410.         error = compute_absolute_padding(style, &ex_size.data.length);
  2411.         if (error != CSS_OK)
  2412.                 return error;
  2413.  
  2414.         /* Fix up text-indent */
  2415.         error = compute_absolute_length(style, &ex_size.data.length,
  2416.                         get_text_indent, set_text_indent);
  2417.         if (error != CSS_OK)
  2418.                 return error;
  2419.  
  2420.         /* Fix up vertical-align */
  2421.         error = compute_absolute_vertical_align(style, &ex_size.data.length);
  2422.         if (error != CSS_OK)
  2423.                 return error;
  2424.  
  2425.         /* Fix up width */
  2426.         error = compute_absolute_length_auto(style, &ex_size.data.length,
  2427.                         get_width, set_width);
  2428.         if (error != CSS_OK)
  2429.                 return error;
  2430.  
  2431.         /* Uncommon properties */
  2432.         if (style->uncommon != NULL) {
  2433.                 /* Fix up border-spacing */
  2434.                 error = compute_absolute_length_pair(style,
  2435.                                 &ex_size.data.length,
  2436.                                 get_border_spacing,
  2437.                                 set_border_spacing);
  2438.                 if (error != CSS_OK)
  2439.                         return error;
  2440.  
  2441.                 /* Fix up clip */
  2442.                 error = compute_absolute_clip(style, &ex_size.data.length);
  2443.                 if (error != CSS_OK)
  2444.                         return error;
  2445.  
  2446.                 /* Fix up letter-spacing */
  2447.                 error = compute_absolute_length_normal(style,
  2448.                                 &ex_size.data.length,
  2449.                                 get_letter_spacing,
  2450.                                 set_letter_spacing);
  2451.                 if (error != CSS_OK)
  2452.                         return error;
  2453.  
  2454.                 /* Fix up outline-color */
  2455.                 error = compute_absolute_color(style,
  2456.                                 get_outline_color,
  2457.                                 set_outline_color);
  2458.                 if (error != CSS_OK)
  2459.                         return error;
  2460.  
  2461.                 /* Fix up outline-width */
  2462.                 error = compute_absolute_border_side_width(style,
  2463.                                 &ex_size.data.length,
  2464.                                 get_outline_width,
  2465.                                 set_outline_width);
  2466.                 if (error != CSS_OK)
  2467.                         return error;
  2468.  
  2469.                 /* Fix up word spacing */
  2470.                 error = compute_absolute_length_normal(style,
  2471.                                 &ex_size.data.length,
  2472.                                 get_word_spacing,
  2473.                                 set_word_spacing);
  2474.                 if (error != CSS_OK)
  2475.                         return error;
  2476.         }
  2477.  
  2478.         return CSS_OK;
  2479. }
  2480.  
  2481. /******************************************************************************
  2482.  * Absolute value calculators
  2483.  ******************************************************************************/
  2484.  
  2485. /**
  2486.  * Compute colour values, replacing any set to currentColor with
  2487.  * the computed value of color.
  2488.  *
  2489.  * \param style  The style to process
  2490.  * \param get    Accessor for colour value
  2491.  * \param set    Mutator for colour value
  2492.  * \return CSS_OK on success
  2493.  */
  2494. css_error compute_absolute_color(css_computed_style *style,
  2495.                 uint8_t (*get)(const css_computed_style *style,
  2496.                                 css_color *color),
  2497.                 css_error (*set)(css_computed_style *style,
  2498.                                 uint8_t type, css_color color))
  2499. {
  2500.         css_color color;
  2501.         css_error error = CSS_OK;
  2502.  
  2503.         if (get(style, &color) == CSS_BACKGROUND_COLOR_CURRENT_COLOR) {
  2504.                 css_color computed_color;
  2505.  
  2506.                 css_computed_color(style, &computed_color);
  2507.  
  2508.                 error = set(style, CSS_BACKGROUND_COLOR_COLOR, computed_color);
  2509.         }
  2510.  
  2511.         return error;
  2512. }
  2513.  
  2514. /**
  2515.  * Compute border colours, replacing any set to currentColor with
  2516.  * the computed value of color.
  2517.  *
  2518.  * \param style  The style to process
  2519.  * \return CSS_OK on success
  2520.  */
  2521. css_error compute_border_colors(css_computed_style *style)
  2522. {
  2523.         css_color color, bcol;
  2524.         css_error error;
  2525.  
  2526.         css_computed_color(style, &color);
  2527.  
  2528.         if (get_border_top_color(style, &bcol) == CSS_BORDER_COLOR_CURRENT_COLOR) {
  2529.                 error = set_border_top_color(style,
  2530.                                 CSS_BORDER_COLOR_COLOR, color);
  2531.                 if (error != CSS_OK)
  2532.                         return error;
  2533.         }
  2534.  
  2535.         if (get_border_right_color(style, &bcol) == CSS_BORDER_COLOR_CURRENT_COLOR) {
  2536.                 error = set_border_right_color(style,
  2537.                                 CSS_BORDER_COLOR_COLOR, color);
  2538.                 if (error != CSS_OK)
  2539.                         return error;
  2540.         }
  2541.  
  2542.         if (get_border_bottom_color(style, &bcol) == CSS_BORDER_COLOR_CURRENT_COLOR) {
  2543.                 error = set_border_bottom_color(style,
  2544.                                 CSS_BORDER_COLOR_COLOR, color);
  2545.                 if (error != CSS_OK)
  2546.                         return error;
  2547.         }
  2548.  
  2549.         if (get_border_left_color(style, &bcol) == CSS_BORDER_COLOR_CURRENT_COLOR) {
  2550.                 error = set_border_left_color(style,
  2551.                                 CSS_BORDER_COLOR_COLOR, color);
  2552.                 if (error != CSS_OK)
  2553.                         return error;
  2554.         }
  2555.  
  2556.         return CSS_OK;
  2557. }
  2558.  
  2559. /**
  2560.  * Compute absolute border widths
  2561.  *
  2562.  * \param style      Style to process
  2563.  * \param ex_size    Ex size in ems
  2564.  * \return CSS_OK on success
  2565.  */
  2566. css_error compute_absolute_border_width(css_computed_style *style,
  2567.                 const css_hint_length *ex_size)
  2568. {
  2569.         css_error error;
  2570.  
  2571.         error = compute_absolute_border_side_width(style, ex_size,
  2572.                         get_border_top_width,
  2573.                         set_border_top_width);
  2574.         if (error != CSS_OK)
  2575.                 return error;
  2576.  
  2577.         error = compute_absolute_border_side_width(style, ex_size,
  2578.                         get_border_right_width,
  2579.                         set_border_right_width);
  2580.         if (error != CSS_OK)
  2581.                 return error;
  2582.  
  2583.         error = compute_absolute_border_side_width(style, ex_size,
  2584.                         get_border_bottom_width,
  2585.                         set_border_bottom_width);
  2586.         if (error != CSS_OK)
  2587.                 return error;
  2588.  
  2589.         error = compute_absolute_border_side_width(style, ex_size,
  2590.                         get_border_left_width,
  2591.                         set_border_left_width);
  2592.         if (error != CSS_OK)
  2593.                 return error;
  2594.  
  2595.         return CSS_OK;
  2596. }
  2597.  
  2598. /**
  2599.  * Compute an absolute border side width
  2600.  *
  2601.  * \param style      Style to process
  2602.  * \param ex_size    Ex size, in ems
  2603.  * \param get        Function to read length
  2604.  * \param set        Function to write length
  2605.  * \return CSS_OK on success
  2606.  */
  2607. css_error compute_absolute_border_side_width(css_computed_style *style,
  2608.                 const css_hint_length *ex_size,
  2609.                 uint8_t (*get)(const css_computed_style *style,
  2610.                                 css_fixed *len, css_unit *unit),
  2611.                 css_error (*set)(css_computed_style *style, uint8_t type,
  2612.                                 css_fixed len, css_unit unit))
  2613. {
  2614.         css_fixed length;
  2615.         css_unit unit;
  2616.         uint8_t type;
  2617.  
  2618.         type = get(style, &length, &unit);
  2619.         if (type == CSS_BORDER_WIDTH_THIN) {
  2620.                 length = INTTOFIX(1);
  2621.                 unit = CSS_UNIT_PX;
  2622.         } else if (type == CSS_BORDER_WIDTH_MEDIUM) {
  2623.                 length = INTTOFIX(2);
  2624.                 unit = CSS_UNIT_PX;
  2625.         } else if (type == CSS_BORDER_WIDTH_THICK) {
  2626.                 length = INTTOFIX(4);
  2627.                 unit = CSS_UNIT_PX;
  2628.         }
  2629.  
  2630.         if (unit == CSS_UNIT_EX) {
  2631.                 length = FMUL(length, ex_size->value);
  2632.                 unit = ex_size->unit;
  2633.         }
  2634.  
  2635.         return set(style, CSS_BORDER_WIDTH_WIDTH, length, unit);
  2636. }
  2637.  
  2638. /**
  2639.  * Compute absolute clip
  2640.  *
  2641.  * \param style      Style to process
  2642.  * \param ex_size    Ex size in ems
  2643.  * \return CSS_OK on success
  2644.  */
  2645. css_error compute_absolute_clip(css_computed_style *style,
  2646.                 const css_hint_length *ex_size)
  2647. {
  2648.         css_computed_clip_rect rect = { 0, 0, 0, 0, CSS_UNIT_PX, CSS_UNIT_PX,
  2649.                         CSS_UNIT_PX, CSS_UNIT_PX, false, false, false, false };
  2650.         css_error error;
  2651.  
  2652.         if (get_clip(style, &rect) == CSS_CLIP_RECT) {
  2653.                 if (rect.top_auto == false) {
  2654.                         if (rect.tunit == CSS_UNIT_EX) {
  2655.                                 rect.top = FMUL(rect.top, ex_size->value);
  2656.                                 rect.tunit = ex_size->unit;
  2657.                         }
  2658.                 }
  2659.  
  2660.                 if (rect.right_auto == false) {
  2661.                         if (rect.runit == CSS_UNIT_EX) {
  2662.                                 rect.right = FMUL(rect.right, ex_size->value);
  2663.                                 rect.runit = ex_size->unit;
  2664.                         }
  2665.                 }
  2666.  
  2667.                 if (rect.bottom_auto == false) {
  2668.                         if (rect.bunit == CSS_UNIT_EX) {
  2669.                                 rect.bottom = FMUL(rect.bottom, ex_size->value);
  2670.                                 rect.bunit = ex_size->unit;
  2671.                         }
  2672.                 }
  2673.  
  2674.                 if (rect.left_auto == false) {
  2675.                         if (rect.lunit == CSS_UNIT_EX) {
  2676.                                 rect.left = FMUL(rect.left, ex_size->value);
  2677.                                 rect.lunit = ex_size->unit;
  2678.                         }
  2679.                 }
  2680.  
  2681.                 error = set_clip(style, CSS_CLIP_RECT, &rect);
  2682.                 if (error != CSS_OK)
  2683.                         return error;
  2684.         }
  2685.  
  2686.         return CSS_OK;
  2687. }
  2688.  
  2689. /**
  2690.  * Compute absolute line-height
  2691.  *
  2692.  * \param style      Style to process
  2693.  * \param ex_size    Ex size, in ems
  2694.  * \return CSS_OK on success
  2695.  */
  2696. css_error compute_absolute_line_height(css_computed_style *style,
  2697.                 const css_hint_length *ex_size)
  2698. {
  2699.         css_fixed length = 0;
  2700.         css_unit unit = CSS_UNIT_PX;
  2701.         uint8_t type;
  2702.         css_error error;
  2703.  
  2704.         type = get_line_height(style, &length, &unit);
  2705.  
  2706.         if (type == CSS_LINE_HEIGHT_DIMENSION) {
  2707.                 if (unit == CSS_UNIT_EX) {
  2708.                         length = FMUL(length, ex_size->value);
  2709.                         unit = ex_size->unit;
  2710.                 }
  2711.  
  2712.                 error = set_line_height(style, type, length, unit);
  2713.                 if (error != CSS_OK)
  2714.                         return error;
  2715.         }
  2716.  
  2717.         return CSS_OK;
  2718. }
  2719.  
  2720. /**
  2721.  * Compute the absolute values of {top,right,bottom,left}
  2722.  *
  2723.  * \param style      Style to process
  2724.  * \param ex_size    Ex size, in ems
  2725.  * \return CSS_OK on success
  2726.  */
  2727. css_error compute_absolute_sides(css_computed_style *style,
  2728.                 const css_hint_length *ex_size)
  2729. {
  2730.         css_error error;
  2731.  
  2732.         /* Calculate absolute lengths for sides */
  2733.         error = compute_absolute_length_auto(style, ex_size, get_top, set_top);
  2734.         if (error != CSS_OK)
  2735.                 return error;
  2736.  
  2737.         error = compute_absolute_length_auto(style, ex_size,
  2738.                         get_right, set_right);
  2739.         if (error != CSS_OK)
  2740.                 return error;
  2741.  
  2742.         error = compute_absolute_length_auto(style, ex_size,
  2743.                         get_bottom, set_bottom);
  2744.         if (error != CSS_OK)
  2745.                 return error;
  2746.  
  2747.         error = compute_absolute_length_auto(style, ex_size,
  2748.                         get_left, set_left);
  2749.         if (error != CSS_OK)
  2750.                 return error;
  2751.  
  2752.         return CSS_OK;
  2753. }
  2754.  
  2755. /**
  2756.  * Compute absolute margins
  2757.  *
  2758.  * \param style      Style to process
  2759.  * \param ex_size    Ex size, in ems
  2760.  * \return CSS_OK on success
  2761.  */
  2762. css_error compute_absolute_margins(css_computed_style *style,
  2763.                 const css_hint_length *ex_size)
  2764. {
  2765.         css_error error;
  2766.  
  2767.         error = compute_absolute_length_auto(style, ex_size,
  2768.                         get_margin_top, set_margin_top);
  2769.         if (error != CSS_OK)
  2770.                 return error;
  2771.  
  2772.         error = compute_absolute_length_auto(style, ex_size,
  2773.                         get_margin_right, set_margin_right);
  2774.         if (error != CSS_OK)
  2775.                 return error;
  2776.  
  2777.         error = compute_absolute_length_auto(style, ex_size,
  2778.                         get_margin_bottom, set_margin_bottom);
  2779.         if (error != CSS_OK)
  2780.                 return error;
  2781.  
  2782.         error = compute_absolute_length_auto(style, ex_size,
  2783.                         get_margin_left, set_margin_left);
  2784.         if (error != CSS_OK)
  2785.                 return error;
  2786.        
  2787.         return CSS_OK;
  2788. }
  2789.  
  2790. /**
  2791.  * Compute absolute padding
  2792.  *
  2793.  * \param style      Style to process
  2794.  * \param ex_size    Ex size, in ems
  2795.  * \return CSS_OK on success
  2796.  */
  2797. css_error compute_absolute_padding(css_computed_style *style,
  2798.                 const css_hint_length *ex_size)
  2799. {
  2800.         css_error error;
  2801.  
  2802.         error = compute_absolute_length(style, ex_size,
  2803.                         get_padding_top, set_padding_top);
  2804.         if (error != CSS_OK)
  2805.                 return error;
  2806.  
  2807.         error = compute_absolute_length(style, ex_size,
  2808.                         get_padding_right, set_padding_right);
  2809.         if (error != CSS_OK)
  2810.                 return error;
  2811.  
  2812.         error = compute_absolute_length(style, ex_size,
  2813.                         get_padding_bottom, set_padding_bottom);
  2814.         if (error != CSS_OK)
  2815.                 return error;
  2816.  
  2817.         error = compute_absolute_length(style, ex_size,
  2818.                         get_padding_left, set_padding_left);
  2819.         if (error != CSS_OK)
  2820.                 return error;
  2821.        
  2822.         return CSS_OK;
  2823. }
  2824.  
  2825. /**
  2826.  * Compute absolute vertical-align
  2827.  *
  2828.  * \param style      Style to process
  2829.  * \param ex_size    Ex size, in ems
  2830.  * \return CSS_OK on success
  2831.  */
  2832. css_error compute_absolute_vertical_align(css_computed_style *style,
  2833.                 const css_hint_length *ex_size)
  2834. {
  2835.         css_fixed length = 0;
  2836.         css_unit unit = CSS_UNIT_PX;
  2837.         uint8_t type;
  2838.         css_error error;
  2839.  
  2840.         type = get_vertical_align(style, &length, &unit);
  2841.  
  2842.         if (type == CSS_VERTICAL_ALIGN_SET) {
  2843.                 if (unit == CSS_UNIT_EX) {
  2844.                         length = FMUL(length, ex_size->value);
  2845.                         unit = ex_size->unit;
  2846.                 }
  2847.  
  2848.                 error = set_vertical_align(style, type, length, unit);
  2849.                 if (error != CSS_OK)
  2850.                         return error;
  2851.         }
  2852.  
  2853.         return CSS_OK;
  2854. }
  2855.  
  2856. /**
  2857.  * Compute the absolute value of length
  2858.  *
  2859.  * \param style      Style to process
  2860.  * \param ex_size    Ex size, in ems
  2861.  * \param get        Function to read length
  2862.  * \param set        Function to write length
  2863.  * \return CSS_OK on success
  2864.  */
  2865. css_error compute_absolute_length(css_computed_style *style,
  2866.                 const css_hint_length *ex_size,
  2867.                 uint8_t (*get)(const css_computed_style *style,
  2868.                                 css_fixed *len, css_unit *unit),
  2869.                 css_error (*set)(css_computed_style *style, uint8_t type,
  2870.                                 css_fixed len, css_unit unit))
  2871. {
  2872.         css_fixed length;
  2873.         css_unit unit;
  2874.         uint8_t type;
  2875.  
  2876.         type = get(style, &length, &unit);
  2877.  
  2878.         if (unit == CSS_UNIT_EX) {
  2879.                 length = FMUL(length, ex_size->value);
  2880.                 unit = ex_size->unit;
  2881.         }
  2882.  
  2883.         return set(style, type, length, unit);
  2884. }
  2885.  
  2886. /**
  2887.  * Compute the absolute value of length or auto
  2888.  *
  2889.  * \param style      Style to process
  2890.  * \param ex_size    Ex size, in ems
  2891.  * \param get        Function to read length
  2892.  * \param set        Function to write length
  2893.  * \return CSS_OK on success
  2894.  */
  2895. css_error compute_absolute_length_auto(css_computed_style *style,
  2896.                 const css_hint_length *ex_size,
  2897.                 uint8_t (*get)(const css_computed_style *style,
  2898.                                 css_fixed *len, css_unit *unit),
  2899.                 css_error (*set)(css_computed_style *style, uint8_t type,
  2900.                                 css_fixed len, css_unit unit))
  2901. {
  2902.         css_fixed length;
  2903.         css_unit unit;
  2904.         uint8_t type;
  2905.  
  2906.         type = get(style, &length, &unit);
  2907.         if (type != CSS_BOTTOM_AUTO) {
  2908.                 if (unit == CSS_UNIT_EX) {
  2909.                         length = FMUL(length, ex_size->value);
  2910.                         unit = ex_size->unit;
  2911.                 }
  2912.  
  2913.                 return set(style, CSS_BOTTOM_SET, length, unit);
  2914.         }
  2915.  
  2916.         return set(style, CSS_BOTTOM_AUTO, 0, CSS_UNIT_PX);
  2917. }
  2918.  
  2919. /**
  2920.  * Compute the absolute value of length or none
  2921.  *
  2922.  * \param style      Style to process
  2923.  * \param ex_size    Ex size, in ems
  2924.  * \param get        Function to read length
  2925.  * \param set        Function to write length
  2926.  * \return CSS_OK on success
  2927.  */
  2928. css_error compute_absolute_length_none(css_computed_style *style,
  2929.                 const css_hint_length *ex_size,
  2930.                 uint8_t (*get)(const css_computed_style *style,
  2931.                                 css_fixed *len, css_unit *unit),
  2932.                 css_error (*set)(css_computed_style *style, uint8_t type,
  2933.                                 css_fixed len, css_unit unit))
  2934. {
  2935.         css_fixed length;
  2936.         css_unit unit;
  2937.         uint8_t type;
  2938.  
  2939.         type = get(style, &length, &unit);
  2940.         if (type != CSS_MAX_HEIGHT_NONE) {
  2941.                 if (unit == CSS_UNIT_EX) {
  2942.                         length = FMUL(length, ex_size->value);
  2943.                         unit = ex_size->unit;
  2944.                 }
  2945.  
  2946.                 return set(style, CSS_MAX_HEIGHT_SET, length, unit);
  2947.         }
  2948.  
  2949.         return set(style, CSS_MAX_HEIGHT_NONE, 0, CSS_UNIT_PX);
  2950. }
  2951.  
  2952. /**
  2953.  * Compute the absolute value of length or normal
  2954.  *
  2955.  * \param style      Style to process
  2956.  * \param ex_size    Ex size, in ems
  2957.  * \param get        Function to read length
  2958.  * \param set        Function to write length
  2959.  * \return CSS_OK on success
  2960.  */
  2961. css_error compute_absolute_length_normal(css_computed_style *style,
  2962.                 const css_hint_length *ex_size,
  2963.                 uint8_t (*get)(const css_computed_style *style,
  2964.                                 css_fixed *len, css_unit *unit),
  2965.                 css_error (*set)(css_computed_style *style, uint8_t type,
  2966.                                 css_fixed len, css_unit unit))
  2967. {
  2968.         css_fixed length;
  2969.         css_unit unit;
  2970.         uint8_t type;
  2971.  
  2972.         type = get(style, &length, &unit);
  2973.         if (type != CSS_LETTER_SPACING_NORMAL) {
  2974.                 if (unit == CSS_UNIT_EX) {
  2975.                         length = FMUL(length, ex_size->value);
  2976.                         unit = ex_size->unit;
  2977.                 }
  2978.  
  2979.                 return set(style, CSS_LETTER_SPACING_SET, length, unit);
  2980.         }
  2981.  
  2982.         return set(style, CSS_LETTER_SPACING_NORMAL, 0, CSS_UNIT_PX);
  2983. }
  2984.  
  2985. /**
  2986.  * Compute the absolute value of length pair
  2987.  *
  2988.  * \param style      Style to process
  2989.  * \param ex_size    Ex size, in ems
  2990.  * \param get        Function to read length
  2991.  * \param set        Function to write length
  2992.  * \return CSS_OK on success
  2993.  */
  2994. css_error compute_absolute_length_pair(css_computed_style *style,
  2995.                 const css_hint_length *ex_size,
  2996.                 uint8_t (*get)(const css_computed_style *style,
  2997.                                 css_fixed *len1, css_unit *unit1,
  2998.                                 css_fixed *len2, css_unit *unit2),
  2999.                 css_error (*set)(css_computed_style *style, uint8_t type,
  3000.                                 css_fixed len1, css_unit unit1,
  3001.                                 css_fixed len2, css_unit unit2))
  3002. {
  3003.         css_fixed length1, length2;
  3004.         css_unit unit1, unit2;
  3005.         uint8_t type;
  3006.  
  3007.         type = get(style, &length1, &unit1, &length2, &unit2);
  3008.  
  3009.         if (unit1 == CSS_UNIT_EX) {
  3010.                 length1 = FMUL(length1, ex_size->value);
  3011.                 unit1 = ex_size->unit;
  3012.         }
  3013.  
  3014.         if (unit2 == CSS_UNIT_EX) {
  3015.                 length2 = FMUL(length2, ex_size->value);
  3016.                 unit2 = ex_size->unit;
  3017.         }
  3018.  
  3019.         return set(style, type, length1, unit1, length2, unit2);
  3020. }
  3021.  
  3022.