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 <assert.h>
  9.  
  10. #include "bytecode/bytecode.h"
  11. #include "bytecode/opcodes.h"
  12. #include "select/properties/properties.h"
  13. #include "select/propget.h"
  14. #include "select/propset.h"
  15. #include "utils/utils.h"
  16.  
  17. #include "select/properties/helpers.h"
  18.  
  19. /* Useful helpers */
  20.  
  21. css_unit css__to_css_unit(uint32_t u)
  22. {
  23.         switch (u) {
  24.         case UNIT_PX: return CSS_UNIT_PX;
  25.         case UNIT_EX: return CSS_UNIT_EX;
  26.         case UNIT_EM: return CSS_UNIT_EM;
  27.         case UNIT_IN: return CSS_UNIT_IN;
  28.         case UNIT_CM: return CSS_UNIT_CM;
  29.         case UNIT_MM: return CSS_UNIT_MM;
  30.         case UNIT_PT: return CSS_UNIT_PT;
  31.         case UNIT_PC: return CSS_UNIT_PC;
  32.         case UNIT_PCT: return CSS_UNIT_PCT;
  33.         case UNIT_DEG: return CSS_UNIT_DEG;
  34.         case UNIT_GRAD: return CSS_UNIT_GRAD;
  35.         case UNIT_RAD: return CSS_UNIT_RAD;
  36.         case UNIT_MS: return CSS_UNIT_MS;
  37.         case UNIT_S: return CSS_UNIT_S;
  38.         case UNIT_HZ: return CSS_UNIT_HZ;
  39.         case UNIT_KHZ: return CSS_UNIT_KHZ;
  40.         }
  41.  
  42.         return 0;
  43. }
  44.  
  45. /******************************************************************************
  46.  * Utilities below here                                                       *
  47.  ******************************************************************************/
  48. css_error css__cascade_bg_border_color(uint32_t opv, css_style *style,
  49.                 css_select_state *state,
  50.                 css_error (*fun)(css_computed_style *, uint8_t, css_color))
  51. {
  52.         uint16_t value = CSS_BACKGROUND_COLOR_INHERIT;
  53.         css_color color = 0;
  54.  
  55.         assert(CSS_BACKGROUND_COLOR_INHERIT ==
  56.                (enum css_background_color_e)CSS_BORDER_COLOR_INHERIT);
  57.         assert(CSS_BACKGROUND_COLOR_COLOR ==
  58.                (enum css_background_color_e)CSS_BORDER_COLOR_COLOR);
  59.         assert(CSS_BACKGROUND_COLOR_CURRENT_COLOR ==
  60.                (enum css_background_color_e)CSS_BORDER_COLOR_CURRENT_COLOR);
  61.  
  62.         if (isInherit(opv) == false) {
  63.                 switch (getValue(opv)) {
  64.                 case BACKGROUND_COLOR_TRANSPARENT:
  65.                         value = CSS_BACKGROUND_COLOR_COLOR;
  66.                         break;
  67.                 case BACKGROUND_COLOR_CURRENT_COLOR:
  68.                         value = CSS_BACKGROUND_COLOR_CURRENT_COLOR;
  69.                         break;
  70.                 case BACKGROUND_COLOR_SET:
  71.                         value = CSS_BACKGROUND_COLOR_COLOR;
  72.                         color = *((css_color *) style->bytecode);
  73.                         advance_bytecode(style, sizeof(color));
  74.                         break;
  75.                 }
  76.         }
  77.  
  78.         if (css__outranks_existing(getOpcode(opv), isImportant(opv), state,
  79.                         isInherit(opv))) {
  80.                 return fun(state->computed, value, color);
  81.         }
  82.  
  83.         return CSS_OK;
  84. }
  85.  
  86. css_error css__cascade_uri_none(uint32_t opv, css_style *style,
  87.                 css_select_state *state,
  88.                 css_error (*fun)(css_computed_style *, uint8_t,
  89.                                 lwc_string *))
  90. {
  91.         uint16_t value = CSS_BACKGROUND_IMAGE_INHERIT;
  92.         lwc_string *uri = NULL;
  93.  
  94.         if (isInherit(opv) == false) {
  95.                 switch (getValue(opv)) {
  96.                 case BACKGROUND_IMAGE_NONE:
  97.                         value = CSS_BACKGROUND_IMAGE_NONE;
  98.                         break;
  99.                 case BACKGROUND_IMAGE_URI:
  100.                         value = CSS_BACKGROUND_IMAGE_IMAGE;
  101.                         css__stylesheet_string_get(style->sheet, *((css_code_t *) style->bytecode), &uri);
  102.                         advance_bytecode(style, sizeof(css_code_t));
  103.                         break;
  104.                 }
  105.         }
  106.  
  107.         /** \todo lose fun != NULL once all properties have set routines */
  108.         if (fun != NULL && css__outranks_existing(getOpcode(opv),
  109.                         isImportant(opv), state, isInherit(opv))) {
  110.                 return fun(state->computed, value, uri);
  111.         }
  112.  
  113.         return CSS_OK;
  114. }
  115.  
  116. css_error css__cascade_border_style(uint32_t opv, css_style *style,
  117.                 css_select_state *state,
  118.                 css_error (*fun)(css_computed_style *, uint8_t))
  119. {
  120.         uint16_t value = CSS_BORDER_STYLE_INHERIT;
  121.  
  122.         UNUSED(style);
  123.  
  124.         if (isInherit(opv) == false) {
  125.                 switch (getValue(opv)) {
  126.                 case BORDER_STYLE_NONE:
  127.                         value = CSS_BORDER_STYLE_NONE;
  128.                         break;
  129.                 case BORDER_STYLE_HIDDEN:
  130.                         value = CSS_BORDER_STYLE_HIDDEN;
  131.                         break;
  132.                 case BORDER_STYLE_DOTTED:
  133.                         value = CSS_BORDER_STYLE_DOTTED;
  134.                         break;
  135.                 case BORDER_STYLE_DASHED:
  136.                         value = CSS_BORDER_STYLE_DASHED;
  137.                         break;
  138.                 case BORDER_STYLE_SOLID:
  139.                         value = CSS_BORDER_STYLE_SOLID;
  140.                         break;
  141.                 case BORDER_STYLE_DOUBLE:
  142.                         value = CSS_BORDER_STYLE_DOUBLE;
  143.                         break;
  144.                 case BORDER_STYLE_GROOVE:
  145.                         value = CSS_BORDER_STYLE_GROOVE;
  146.                         break;
  147.                 case BORDER_STYLE_RIDGE:
  148.                         value = CSS_BORDER_STYLE_RIDGE;
  149.                         break;
  150.                 case BORDER_STYLE_INSET:
  151.                         value = CSS_BORDER_STYLE_INSET;
  152.                         break;
  153.                 case BORDER_STYLE_OUTSET:
  154.                         value = CSS_BORDER_STYLE_OUTSET;
  155.                         break;
  156.                 }
  157.         }
  158.  
  159.         if (css__outranks_existing(getOpcode(opv), isImportant(opv), state,
  160.                         isInherit(opv))) {
  161.                 return fun(state->computed, value);
  162.         }
  163.  
  164.         return CSS_OK;
  165. }
  166.  
  167. css_error css__cascade_border_width(uint32_t opv, css_style *style,
  168.                 css_select_state *state,
  169.                 css_error (*fun)(css_computed_style *, uint8_t, css_fixed,
  170.                                 css_unit))
  171. {
  172.         uint16_t value = CSS_BORDER_WIDTH_INHERIT;
  173.         css_fixed length = 0;
  174.         uint32_t unit = UNIT_PX;
  175.  
  176.         if (isInherit(opv) == false) {
  177.                 switch (getValue(opv)) {
  178.                 case BORDER_WIDTH_SET:
  179.                         value = CSS_BORDER_WIDTH_WIDTH;
  180.                         length = *((css_fixed *) style->bytecode);
  181.                         advance_bytecode(style, sizeof(length));
  182.                         unit = *((uint32_t *) style->bytecode);
  183.                         advance_bytecode(style, sizeof(unit));
  184.                         break;
  185.                 case BORDER_WIDTH_THIN:
  186.                         value = CSS_BORDER_WIDTH_THIN;
  187.                         break;
  188.                 case BORDER_WIDTH_MEDIUM:
  189.                         value = CSS_BORDER_WIDTH_MEDIUM;
  190.                         break;
  191.                 case BORDER_WIDTH_THICK:
  192.                         value = CSS_BORDER_WIDTH_THICK;
  193.                         break;
  194.                 }
  195.         }
  196.  
  197.         unit = css__to_css_unit(unit);
  198.  
  199.         if (css__outranks_existing(getOpcode(opv), isImportant(opv), state,
  200.                         isInherit(opv))) {
  201.                 return fun(state->computed, value, length, unit);
  202.         }
  203.  
  204.         return CSS_OK;
  205. }
  206.  
  207. css_error css__cascade_length_auto(uint32_t opv, css_style *style,
  208.                 css_select_state *state,
  209.                 css_error (*fun)(css_computed_style *, uint8_t, css_fixed,
  210.                                 css_unit))
  211. {
  212.         uint16_t value = CSS_BOTTOM_INHERIT;
  213.         css_fixed length = 0;
  214.         uint32_t unit = UNIT_PX;
  215.  
  216.         if (isInherit(opv) == false) {
  217.                 switch (getValue(opv)) {
  218.                 case BOTTOM_SET:
  219.                         value = CSS_BOTTOM_SET;
  220.                         length = *((css_fixed *) style->bytecode);
  221.                         advance_bytecode(style, sizeof(length));
  222.                         unit = *((uint32_t *) style->bytecode);
  223.                         advance_bytecode(style, sizeof(unit));
  224.                         break;
  225.                 case BOTTOM_AUTO:
  226.                         value = CSS_BOTTOM_AUTO;
  227.                         break;
  228.                 }
  229.         }
  230.  
  231.         unit = css__to_css_unit(unit);
  232.  
  233.         if (css__outranks_existing(getOpcode(opv), isImportant(opv), state,
  234.                         isInherit(opv))) {
  235.                 return fun(state->computed, value, length, unit);
  236.         }
  237.  
  238.         return CSS_OK;
  239. }
  240.  
  241. css_error css__cascade_length_normal(uint32_t opv, css_style *style,
  242.                 css_select_state *state,
  243.                 css_error (*fun)(css_computed_style *, uint8_t, css_fixed,
  244.                                 css_unit))
  245. {
  246.         uint16_t value = CSS_LETTER_SPACING_INHERIT;
  247.         css_fixed length = 0;
  248.         uint32_t unit = UNIT_PX;
  249.  
  250.         if (isInherit(opv) == false) {
  251.                 switch (getValue(opv)) {
  252.                 case LETTER_SPACING_SET:
  253.                         value = CSS_LETTER_SPACING_SET;
  254.                         length = *((css_fixed *) style->bytecode);
  255.                         advance_bytecode(style, sizeof(length));
  256.                         unit = *((uint32_t *) style->bytecode);
  257.                         advance_bytecode(style, sizeof(unit));
  258.                         break;
  259.                 case LETTER_SPACING_NORMAL:
  260.                         value = CSS_LETTER_SPACING_NORMAL;
  261.                         break;
  262.                 }
  263.         }
  264.  
  265.         unit = css__to_css_unit(unit);
  266.  
  267.         if (css__outranks_existing(getOpcode(opv), isImportant(opv), state,
  268.                         isInherit(opv))) {
  269.                 return fun(state->computed, value, length, unit);
  270.         }
  271.  
  272.         return CSS_OK;
  273. }
  274.  
  275. css_error css__cascade_length_none(uint32_t opv, css_style *style,
  276.                 css_select_state *state,
  277.                 css_error (*fun)(css_computed_style *, uint8_t, css_fixed,
  278.                                 css_unit))
  279. {
  280.         uint16_t value = CSS_MAX_HEIGHT_INHERIT;
  281.         css_fixed length = 0;
  282.         uint32_t unit = UNIT_PX;
  283.  
  284.         if (isInherit(opv) == false) {
  285.                 switch (getValue(opv)) {
  286.                 case MAX_HEIGHT_SET:
  287.                         value = CSS_MAX_HEIGHT_SET;
  288.                         length = *((css_fixed *) style->bytecode);
  289.                         advance_bytecode(style, sizeof(length));
  290.                         unit = *((uint32_t *) style->bytecode);
  291.                         advance_bytecode(style, sizeof(unit));
  292.                         break;
  293.                 case MAX_HEIGHT_NONE:
  294.                         value = CSS_MAX_HEIGHT_NONE;
  295.                         break;
  296.                 }
  297.         }
  298.  
  299.         unit = css__to_css_unit(unit);
  300.  
  301.         if (css__outranks_existing(getOpcode(opv), isImportant(opv), state,
  302.                         isInherit(opv))) {
  303.                 return fun(state->computed, value, length, unit);
  304.         }
  305.  
  306.         return CSS_OK;
  307. }
  308.  
  309. css_error css__cascade_length(uint32_t opv, css_style *style,
  310.                 css_select_state *state,
  311.                 css_error (*fun)(css_computed_style *, uint8_t, css_fixed,
  312.                                 css_unit))
  313. {
  314.         uint16_t value = CSS_MIN_HEIGHT_INHERIT;
  315.         css_fixed length = 0;
  316.         uint32_t unit = UNIT_PX;
  317.  
  318.         if (isInherit(opv) == false) {
  319.                 value = CSS_MIN_HEIGHT_SET;
  320.                 length = *((css_fixed *) style->bytecode);
  321.                 advance_bytecode(style, sizeof(length));
  322.                 unit = *((uint32_t *) style->bytecode);
  323.                 advance_bytecode(style, sizeof(unit));
  324.         }
  325.  
  326.         unit = css__to_css_unit(unit);
  327.  
  328.         /** \todo lose fun != NULL once all properties have set routines */
  329.         if (fun != NULL && css__outranks_existing(getOpcode(opv),
  330.                         isImportant(opv), state, isInherit(opv))) {
  331.                 return fun(state->computed, value, length, unit);
  332.         }
  333.  
  334.         return CSS_OK;
  335. }
  336.  
  337. css_error css__cascade_number(uint32_t opv, css_style *style,
  338.                 css_select_state *state,
  339.                 css_error (*fun)(css_computed_style *, uint8_t, css_fixed))
  340. {
  341.         uint16_t value = 0;
  342.         css_fixed length = 0;
  343.  
  344.         /** \todo values */
  345.  
  346.         if (isInherit(opv) == false) {
  347.                 value = 0;
  348.                 length = *((css_fixed *) style->bytecode);
  349.                 advance_bytecode(style, sizeof(length));
  350.         }
  351.  
  352.         /** \todo lose fun != NULL once all properties have set routines */
  353.         if (fun != NULL && css__outranks_existing(getOpcode(opv),
  354.                         isImportant(opv), state, isInherit(opv))) {
  355.                 return fun(state->computed, value, length);
  356.         }
  357.  
  358.         return CSS_OK;
  359. }
  360.  
  361. css_error css__cascade_page_break_after_before_inside(uint32_t opv,
  362.                 css_style *style, css_select_state *state,
  363.                 css_error (*fun)(css_computed_style *, uint8_t))
  364. {
  365.         uint16_t value = CSS_PAGE_BREAK_AFTER_INHERIT;
  366.  
  367.         UNUSED(style);
  368.  
  369.         if (isInherit(opv) == false) {
  370.                 switch (getValue(opv)) {
  371.                 case PAGE_BREAK_AFTER_AUTO:
  372.                         value = CSS_PAGE_BREAK_AFTER_AUTO;
  373.                         break;
  374.                 case PAGE_BREAK_AFTER_ALWAYS:
  375.                         value = CSS_PAGE_BREAK_AFTER_ALWAYS;
  376.                         break;
  377.                 case PAGE_BREAK_AFTER_AVOID:
  378.                         value = CSS_PAGE_BREAK_AFTER_AVOID;
  379.                         break;
  380.                 case PAGE_BREAK_AFTER_LEFT:
  381.                         value = CSS_PAGE_BREAK_AFTER_LEFT;
  382.                         break;
  383.                 case PAGE_BREAK_AFTER_RIGHT:
  384.                         value = CSS_PAGE_BREAK_AFTER_RIGHT;
  385.                         break;
  386.                 }
  387.         }
  388.  
  389.         /** \todo lose fun != NULL */
  390.         if (fun != NULL && css__outranks_existing(getOpcode(opv),
  391.                         isImportant(opv), state, isInherit(opv))) {
  392.                 return fun(state->computed, value);
  393.         }
  394.  
  395.         return CSS_OK;
  396. }
  397.  
  398. css_error css__cascade_counter_increment_reset(uint32_t opv, css_style *style,
  399.                 css_select_state *state,
  400.                 css_error (*fun)(css_computed_style *, uint8_t,
  401.                                 css_computed_counter *))
  402. {
  403.         uint16_t value = CSS_COUNTER_INCREMENT_INHERIT;
  404.         css_computed_counter *counters = NULL;
  405.         uint32_t n_counters = 0;
  406.  
  407.         if (isInherit(opv) == false) {
  408.                 switch (getValue(opv)) {
  409.                 case COUNTER_INCREMENT_NAMED:
  410.                 {
  411.                         uint32_t v = getValue(opv);
  412.  
  413.                         while (v != COUNTER_INCREMENT_NONE) {
  414.                                 css_computed_counter *temp;
  415.                                 lwc_string *name;
  416.                                 css_fixed val = 0;
  417.  
  418.                                 css__stylesheet_string_get(style->sheet, *((css_code_t *) style->bytecode), &name);
  419.                                 advance_bytecode(style, sizeof(css_code_t));
  420.  
  421.                                 val = *((css_fixed *) style->bytecode);
  422.                                 advance_bytecode(style, sizeof(css_code_t));
  423.  
  424.                                 temp = state->computed->alloc(counters,
  425.                                                 (n_counters + 1) *
  426.                                                 sizeof(css_computed_counter),
  427.                                                 state->computed->pw);
  428.                                 if (temp == NULL) {
  429.                                         if (counters != NULL) {
  430.                                                 state->computed->alloc(counters,
  431.                                                         0, state->computed->pw);
  432.                                         }
  433.                                         return CSS_NOMEM;
  434.                                 }
  435.  
  436.                                 counters = temp;
  437.  
  438.                                 counters[n_counters].name = name;
  439.                                 counters[n_counters].value = val;
  440.  
  441.                                 n_counters++;
  442.  
  443.                                 v = *((uint32_t *) style->bytecode);
  444.                                 advance_bytecode(style, sizeof(css_code_t));
  445.                         }
  446.                 }
  447.                         break;
  448.                 case COUNTER_INCREMENT_NONE:
  449.                         value = CSS_COUNTER_INCREMENT_NONE;
  450.                         break;
  451.                 }
  452.         }
  453.  
  454.         /* If we have some counters, terminate the array with a blank entry */
  455.         if (n_counters > 0) {
  456.                 css_computed_counter *temp;
  457.  
  458.                 temp = state->computed->alloc(counters,
  459.                                 (n_counters + 1) * sizeof(css_computed_counter),
  460.                                 state->computed->pw);
  461.                 if (temp == NULL) {
  462.                         state->computed->alloc(counters, 0, state->computed->pw);
  463.                         return CSS_NOMEM;
  464.                 }
  465.  
  466.                 counters = temp;
  467.  
  468.                 counters[n_counters].name = NULL;
  469.                 counters[n_counters].value = 0;
  470.         }
  471.  
  472.         if (css__outranks_existing(getOpcode(opv), isImportant(opv), state,
  473.                         isInherit(opv))) {
  474.                 css_error error;
  475.  
  476.                 error = fun(state->computed, value, counters);
  477.                 if (error != CSS_OK && n_counters > 0)
  478.                         state->computed->alloc(counters, 0, state->computed->pw);
  479.  
  480.                 return error;
  481.         } else if (n_counters > 0) {
  482.                 state->computed->alloc(counters, 0, state->computed->pw);
  483.         }
  484.  
  485.         return CSS_OK;
  486. }
  487.  
  488.