From 8e580ccd195d2b7ae896803391ef404cb3b41d3b Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 3 May 2015 16:10:15 +0100 Subject: Split out presentational hints handling. --- css/Makefile | 2 +- css/hints.c | 1794 +++++++++++++++++++++++++++++++++++++++++++++ css/hints.h | 48 ++ css/select.c | 1915 ++---------------------------------------------- css/select.h | 6 +- render/box_construct.c | 3 +- 6 files changed, 1914 insertions(+), 1854 deletions(-) create mode 100644 css/hints.c create mode 100644 css/hints.h diff --git a/css/Makefile b/css/Makefile index 1280d57e1..127dbaa32 100644 --- a/css/Makefile +++ b/css/Makefile @@ -1,5 +1,5 @@ # CSS sources -S_CSS := css.c dump.c internal.c select.c utils.c +S_CSS := css.c dump.c internal.c hints.c select.c utils.c S_CSS := $(addprefix css/,$(S_CSS)) diff --git a/css/hints.c b/css/hints.c new file mode 100644 index 000000000..059b42bfa --- /dev/null +++ b/css/hints.c @@ -0,0 +1,1794 @@ +/* + * Copyright 2009 John-Mark Bell + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "utils/nsoption.h" +#include "utils/corestrings.h" +#include "utils/log.h" +#include "utils/nsurl.h" +#include "utils/utils.h" + +#include "css/hints.h" +#include "css/select.h" + +/****************************************************************************** + * Utility functions * + ******************************************************************************/ + +/** + * Determine if a given character is whitespace + * + * \param c Character to consider + * \return true if character is whitespace, false otherwise + */ +static bool isWhitespace(char c) +{ + return c == ' ' || c == '\t' || c == '\f' || c == '\r' || c == '\n'; +} + +/** + * Determine if a given character is a valid hex digit + * + * \param c Character to consider + * \return true if character is a valid hex digit, false otherwise + */ +static bool isHex(char c) +{ + return ('0' <= c && c <= '9') || + ('A' <= (c & ~0x20) && (c & ~0x20) <= 'F'); +} + +/** + * Convert a character representing a hex digit to the corresponding hex value + * + * \param c Character to convert + * \return Hex value represented by character + * + * \note This function assumes an ASCII-compatible character set + */ +static uint8_t charToHex(char c) +{ + /* 0-9 */ + c -= '0'; + + /* A-F */ + if (c > 9) + c -= 'A' - '9' - 1; + + /* a-f */ + if (c > 15) + c -= 'a' - 'A'; + + return c; +} + + +/****************************************************************************** + * Common parsing functions * + ******************************************************************************/ + +/** + * Parse a number string + * + * \param data Data to parse (NUL-terminated) + * \param maybe_negative Negative numbers permitted + * \param real Floating point numbers permitted + * \param value Pointer to location to receive numeric value + * \param consumed Pointer to location to receive number of input + * bytes consumed + * \return true on success, false on invalid input + */ +static bool parse_number(const char *data, bool maybe_negative, bool real, + css_fixed *value, size_t *consumed) +{ + size_t len; + const uint8_t *ptr; + int32_t intpart = 0; + int32_t fracpart = 0; + int32_t pwr = 1; + int sign = 1; + + *consumed = 0; + + len = strlen(data); + ptr = (const uint8_t *) data; + + if (len == 0) + return false; + + /* Skip leading whitespace */ + while (len > 0 && isWhitespace(ptr[0])) { + len--; + ptr++; + } + + if (len == 0) + return false; + + /* Extract sign, if any */ + if (ptr[0] == '+') { + len--; + ptr++; + } else if (ptr[0] == '-' && maybe_negative) { + sign = -1; + len--; + ptr++; + } + + if (len == 0) + return false; + + /* Must have a digit [0,9] */ + if ('0' > ptr[0] || ptr[0] > '9') + return false; + + /* Now extract intpart, assuming base 10 */ + while (len > 0) { + /* Stop on first non-digit */ + if (ptr[0] < '0' || '9' < ptr[0]) + break; + + /* Prevent overflow of 'intpart'; proper clamping below */ + if (intpart < (1 << 22)) { + intpart *= 10; + intpart += ptr[0] - '0'; + } + ptr++; + len--; + } + + /* And fracpart, again, assuming base 10 */ + if (real && len > 1 && ptr[0] == '.' && + ('0' <= ptr[1] && ptr[1] <= '9')) { + ptr++; + len--; + + while (len > 0) { + if (ptr[0] < '0' || '9' < ptr[0]) + break; + + if (pwr < 1000000) { + pwr *= 10; + fracpart *= 10; + fracpart += ptr[0] - '0'; + } + ptr++; + len--; + } + + fracpart = ((1 << 10) * fracpart + pwr/2) / pwr; + if (fracpart >= (1 << 10)) { + intpart++; + fracpart &= (1 << 10) - 1; + } + } + + if (sign > 0) { + /* If the result is larger than we can represent, + * then clamp to the maximum value we can store. */ + if (intpart >= (1 << 21)) { + intpart = (1 << 21) - 1; + fracpart = (1 << 10) - 1; + } + } else { + /* If the negated result is smaller than we can represent + * then clamp to the minimum value we can store. */ + if (intpart >= (1 << 21)) { + intpart = -(1 << 21); + fracpart = 0; + } else { + intpart = -intpart; + if (fracpart) { + fracpart = (1 << 10) - fracpart; + intpart--; + } + } + } + + *value = (intpart << 10) | fracpart; + + *consumed = ptr - (const uint8_t *) data; + + return true; +} + +/** + * Parse a dimension string + * + * \param data Data to parse (NUL-terminated) + * \param strict Whether to enforce strict parsing rules + * \param length Pointer to location to receive dimension's length + * \param unit Pointer to location to receive dimension's unit + * \return true on success, false on invalid input + */ +static bool parse_dimension(const char *data, bool strict, css_fixed *length, + css_unit *unit) +{ + size_t len; + size_t read; + css_fixed value; + + len = strlen(data); + + if (parse_number(data, false, true, &value, &read) == false) + return false; + + if (strict && value < INTTOFIX(1)) + return false; + + *length = value; + + if (len > read && data[read] == '%') + *unit = CSS_UNIT_PCT; + else + *unit = CSS_UNIT_PX; + + return true; +} + +/** + * Mapping of colour name to CSS color + */ +struct colour_map { + const char *name; + css_color color; +}; + +/** + * Name comparator for named colour matching + * + * \param a Name to match + * \param b Colour map entry to consider + * \return 0 on match, + * < 0 if a < b, + * > 0 if b > a. + */ +static int cmp_colour_name(const void *a, const void *b) +{ + const char *aa = a; + const struct colour_map *bb = b; + + return strcasecmp(aa, bb->name); +} + +/** + * Parse a named colour + * + * \param name Name to parse + * \param result Pointer to location to receive css_color + * \return true on success, false on invalid input + */ +static bool parse_named_colour(const char *name, css_color *result) +{ + static const struct colour_map named_colours[] = { + { "aliceblue", 0xfff0f8ff }, + { "antiquewhite", 0xfffaebd7 }, + { "aqua", 0xff00ffff }, + { "aquamarine", 0xff7fffd4 }, + { "azure", 0xfff0ffff }, + { "beige", 0xfff5f5dc }, + { "bisque", 0xffffe4c4 }, + { "black", 0xff000000 }, + { "blanchedalmond", 0xffffebcd }, + { "blue", 0xff0000ff }, + { "blueviolet", 0xff8a2be2 }, + { "brown", 0xffa52a2a }, + { "burlywood", 0xffdeb887 }, + { "cadetblue", 0xff5f9ea0 }, + { "chartreuse", 0xff7fff00 }, + { "chocolate", 0xffd2691e }, + { "coral", 0xffff7f50 }, + { "cornflowerblue", 0xff6495ed }, + { "cornsilk", 0xfffff8dc }, + { "crimson", 0xffdc143c }, + { "cyan", 0xff00ffff }, + { "darkblue", 0xff00008b }, + { "darkcyan", 0xff008b8b }, + { "darkgoldenrod", 0xffb8860b }, + { "darkgray", 0xffa9a9a9 }, + { "darkgreen", 0xff006400 }, + { "darkgrey", 0xffa9a9a9 }, + { "darkkhaki", 0xffbdb76b }, + { "darkmagenta", 0xff8b008b }, + { "darkolivegreen", 0xff556b2f }, + { "darkorange", 0xffff8c00 }, + { "darkorchid", 0xff9932cc }, + { "darkred", 0xff8b0000 }, + { "darksalmon", 0xffe9967a }, + { "darkseagreen", 0xff8fbc8f }, + { "darkslateblue", 0xff483d8b }, + { "darkslategray", 0xff2f4f4f }, + { "darkslategrey", 0xff2f4f4f }, + { "darkturquoise", 0xff00ced1 }, + { "darkviolet", 0xff9400d3 }, + { "deeppink", 0xffff1493 }, + { "deepskyblue", 0xff00bfff }, + { "dimgray", 0xff696969 }, + { "dimgrey", 0xff696969 }, + { "dodgerblue", 0xff1e90ff }, + { "feldspar", 0xffd19275 }, + { "firebrick", 0xffb22222 }, + { "floralwhite", 0xfffffaf0 }, + { "forestgreen", 0xff228b22 }, + { "fuchsia", 0xffff00ff }, + { "gainsboro", 0xffdcdcdc }, + { "ghostwhite", 0xfff8f8ff }, + { "gold", 0xffffd700 }, + { "goldenrod", 0xffdaa520 }, + { "gray", 0xff808080 }, + { "green", 0xff008000 }, + { "greenyellow", 0xffadff2f }, + { "grey", 0xff808080 }, + { "honeydew", 0xfff0fff0 }, + { "hotpink", 0xffff69b4 }, + { "indianred", 0xffcd5c5c }, + { "indigo", 0xff4b0082 }, + { "ivory", 0xfffffff0 }, + { "khaki", 0xfff0e68c }, + { "lavender", 0xffe6e6fa }, + { "lavenderblush", 0xfffff0f5 }, + { "lawngreen", 0xff7cfc00 }, + { "lemonchiffon", 0xfffffacd }, + { "lightblue", 0xffadd8e6 }, + { "lightcoral", 0xfff08080 }, + { "lightcyan", 0xffe0ffff }, + { "lightgoldenrodyellow", 0xfffafad2 }, + { "lightgray", 0xffd3d3d3 }, + { "lightgreen", 0xff90ee90 }, + { "lightgrey", 0xffd3d3d3 }, + { "lightpink", 0xffffb6c1 }, + { "lightsalmon", 0xffffa07a }, + { "lightseagreen", 0xff20b2aa }, + { "lightskyblue", 0xff87cefa }, + { "lightslateblue", 0xff8470ff }, + { "lightslategray", 0xff778899 }, + { "lightslategrey", 0xff778899 }, + { "lightsteelblue", 0xffb0c4de }, + { "lightyellow", 0xffffffe0 }, + { "lime", 0xff00ff00 }, + { "limegreen", 0xff32cd32 }, + { "linen", 0xfffaf0e6 }, + { "magenta", 0xffff00ff }, + { "maroon", 0xff800000 }, + { "mediumaquamarine", 0xff66cdaa }, + { "mediumblue", 0xff0000cd }, + { "mediumorchid", 0xffba55d3 }, + { "mediumpurple", 0xff9370db }, + { "mediumseagreen", 0xff3cb371 }, + { "mediumslateblue", 0xff7b68ee }, + { "mediumspringgreen", 0xff00fa9a }, + { "mediumturquoise", 0xff48d1cc }, + { "mediumvioletred", 0xffc71585 }, + { "midnightblue", 0xff191970 }, + { "mintcream", 0xfff5fffa }, + { "mistyrose", 0xffffe4e1 }, + { "moccasin", 0xffffe4b5 }, + { "navajowhite", 0xffffdead }, + { "navy", 0xff000080 }, + { "oldlace", 0xfffdf5e6 }, + { "olive", 0xff808000 }, + { "olivedrab", 0xff6b8e23 }, + { "orange", 0xffffa500 }, + { "orangered", 0xffff4500 }, + { "orchid", 0xffda70d6 }, + { "palegoldenrod", 0xffeee8aa }, + { "palegreen", 0xff98fb98 }, + { "paleturquoise", 0xffafeeee }, + { "palevioletred", 0xffdb7093 }, + { "papayawhip", 0xffffefd5 }, + { "peachpuff", 0xffffdab9 }, + { "peru", 0xffcd853f }, + { "pink", 0xffffc0cb }, + { "plum", 0xffdda0dd }, + { "powderblue", 0xffb0e0e6 }, + { "purple", 0xff800080 }, + { "red", 0xffff0000 }, + { "rosybrown", 0xffbc8f8f }, + { "royalblue", 0xff4169e1 }, + { "saddlebrown", 0xff8b4513 }, + { "salmon", 0xfffa8072 }, + { "sandybrown", 0xfff4a460 }, + { "seagreen", 0xff2e8b57 }, + { "seashell", 0xfffff5ee }, + { "sienna", 0xffa0522d }, + { "silver", 0xffc0c0c0 }, + { "skyblue", 0xff87ceeb }, + { "slateblue", 0xff6a5acd }, + { "slategray", 0xff708090 }, + { "slategrey", 0xff708090 }, + { "snow", 0xfffffafa }, + { "springgreen", 0xff00ff7f }, + { "steelblue", 0xff4682b4 }, + { "tan", 0xffd2b48c }, + { "teal", 0xff008080 }, + { "thistle", 0xffd8bfd8 }, + { "tomato", 0xffff6347 }, + { "turquoise", 0xff40e0d0 }, + { "violet", 0xffee82ee }, + { "violetred", 0xffd02090 }, + { "wheat", 0xfff5deb3 }, + { "white", 0xffffffff }, + { "whitesmoke", 0xfff5f5f5 }, + { "yellow", 0xffffff00 }, + { "yellowgreen", 0xff9acd32 } + }; + const struct colour_map *entry; + + entry = bsearch(name, named_colours, + sizeof(named_colours) / sizeof(named_colours[0]), + sizeof(named_colours[0]), + cmp_colour_name); + + if (entry != NULL) + *result = entry->color; + + return entry != NULL; +} + +/** + * Parser for colours specified in attribute values. + * + * \param data Data to parse (NUL-terminated) + * \param result Pointer to location to receive resulting css_color + * \return true on success, false on invalid input + */ +bool nscss_parse_colour(const char *data, css_color *result) +{ + size_t len = strlen(data); + uint8_t r, g, b; + + /* 2 */ + if (len == 0) + return false; + + /* 3 */ + if (len == SLEN("transparent") && strcasecmp(data, "transparent") == 0) + return false; + + /* 4 */ + if (parse_named_colour(data, result)) + return true; + + /** \todo Implement HTML5's utterly insane legacy colour parsing */ + + if (data[0] == '#') { + data++; + len--; + } + + if (len == 3 && isHex(data[0]) && isHex(data[1]) && isHex(data[2])) { + r = charToHex(data[0]); + g = charToHex(data[1]); + b = charToHex(data[2]); + + r |= (r << 4); + g |= (g << 4); + b |= (b << 4); + + *result = (0xff << 24) | (r << 16) | (g << 8) | b; + + return true; + } else if (len == 6 && isHex(data[0]) && isHex(data[1]) && + isHex(data[2]) && isHex(data[3]) && isHex(data[4]) && + isHex(data[5])) { + r = (charToHex(data[0]) << 4) | charToHex(data[1]); + g = (charToHex(data[2]) << 4) | charToHex(data[3]); + b = (charToHex(data[4]) << 4) | charToHex(data[5]); + + *result = (0xff << 24) | (r << 16) | (g << 8) | b; + + return true; + } + + return false; +} + +/** + * Parse a font \@size attribute + * + * \param size Data to parse (NUL-terminated) + * \param val Pointer to location to receive enum value + * \param len Pointer to location to receive length + * \param unit Pointer to location to receive unit + * \return True on success, false on failure + */ +static bool parse_font_size(const char *size, uint8_t *val, + css_fixed *len, css_unit *unit) +{ + static const uint8_t size_map[] = { + CSS_FONT_SIZE_XX_SMALL, + CSS_FONT_SIZE_SMALL, + CSS_FONT_SIZE_MEDIUM, + CSS_FONT_SIZE_LARGE, + CSS_FONT_SIZE_X_LARGE, + CSS_FONT_SIZE_XX_LARGE, + CSS_FONT_SIZE_DIMENSION /* xxx-large (see below) */ + }; + + const char *p = size; + char mode; + int value = 0; + + /* Skip whitespace */ + while (*p != '\0' && isWhitespace(*p)) + p++; + + mode = *p; + + /* Skip +/- */ + if (mode == '+' || mode == '-') + p++; + + /* Need at least one digit */ + if (*p < '0' || *p > '9') { + return false; + } + + /* Consume digits, computing value */ + while ('0' <= *p && *p <= '9') { + value = value * 10 + (*p - '0'); + p++; + } + + /* Resolve relative sizes */ + if (mode == '+') + value += 3; + else if (mode == '-') + value = 3 - value; + + /* Clamp to range [1,7] */ + if (value < 1) + value = 1; + else if (value > 7) + value = 7; + + if (value == 7) { + /* Manufacture xxx-large */ + *len = FDIV(FMUL(INTTOFIX(3), INTTOFIX(nsoption_int(font_size))), + F_10); + } else { + /* Len is irrelevant */ + *len = 0; + } + + *unit = CSS_UNIT_PT; + *val = size_map[value - 1]; + + return true; +} + + +/****************************************************************************** + * Presentational hint handlers * + ******************************************************************************/ + +static css_error node_presentational_hint_vertical_align( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_string *name; + dom_string *valign = NULL; + dom_exception err; + + err = dom_node_get_node_name(node, &name); + if (err != DOM_NO_ERR) + return CSS_PROPERTY_NOT_SET; + + if (dom_string_caseless_lwc_isequal(name, corestring_lwc_col) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_thead) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_tbody) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_tfoot) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_tr) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { + err = dom_element_get_attribute(node, + corestring_dom_valign, &valign); + if (err != DOM_NO_ERR || valign == NULL) { + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + if (dom_string_caseless_lwc_isequal(valign, + corestring_lwc_top)) { + hint->status = CSS_VERTICAL_ALIGN_TOP; + } else if (dom_string_caseless_lwc_isequal(valign, + corestring_lwc_middle)) { + hint->status = CSS_VERTICAL_ALIGN_MIDDLE; + } else if (dom_string_caseless_lwc_isequal(valign, + corestring_lwc_bottom)) { + hint->status = CSS_VERTICAL_ALIGN_BOTTOM; + } else if (dom_string_caseless_lwc_isequal(valign, + corestring_lwc_baseline)) { + hint->status = CSS_VERTICAL_ALIGN_BASELINE; + } else { + dom_string_unref(valign); + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(valign); + dom_string_unref(name); + + return CSS_OK; + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_applet) || + dom_string_caseless_lwc_isequal(name, + corestring_lwc_embed) || + dom_string_caseless_lwc_isequal(name, + corestring_lwc_iframe) || + dom_string_caseless_lwc_isequal(name, + corestring_lwc_img) || + dom_string_caseless_lwc_isequal(name, + corestring_lwc_object)) { + /** \todo input[type=image][align=*] - $11.3.3 */ + err = dom_element_get_attribute(node, + corestring_dom_align, &valign); + if (err != DOM_NO_ERR || valign == NULL) { + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + if (dom_string_caseless_lwc_isequal(valign, + corestring_lwc_top)) { + hint->status = CSS_VERTICAL_ALIGN_TOP; + } else if (dom_string_caseless_lwc_isequal(valign, + corestring_lwc_bottom) || + dom_string_caseless_lwc_isequal(valign, + corestring_lwc_baseline)) { + hint->status = CSS_VERTICAL_ALIGN_BASELINE; + } else if (dom_string_caseless_lwc_isequal(valign, + corestring_lwc_texttop)) { + hint->status = CSS_VERTICAL_ALIGN_TEXT_TOP; + } else if (dom_string_caseless_lwc_isequal(valign, + corestring_lwc_absmiddle) || + dom_string_caseless_lwc_isequal(valign, + corestring_lwc_abscenter)) { + hint->status = CSS_VERTICAL_ALIGN_MIDDLE; + } else { + dom_string_unref(valign); + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(valign); + dom_string_unref(name); + + return CSS_OK; + } + + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; +} + +static css_error node_presentational_hint_text_align( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_string *name; + dom_string *align = NULL; + dom_exception err; + + err = dom_node_get_node_name(node, &name); + if (err != DOM_NO_ERR) + return CSS_PROPERTY_NOT_SET; + + if (dom_string_caseless_lwc_isequal(name, corestring_lwc_p) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_h1) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_h2) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_h3) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_h4) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_h5) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_h6)) { + err = dom_element_get_attribute(node, + corestring_dom_align, &align); + if (err != DOM_NO_ERR || align == NULL) { + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_left)) { + hint->status = CSS_TEXT_ALIGN_LEFT; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_center)) { + hint->status = CSS_TEXT_ALIGN_CENTER; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_right)) { + hint->status = CSS_TEXT_ALIGN_RIGHT; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_justify)) { + hint->status = CSS_TEXT_ALIGN_JUSTIFY; + } else { + dom_string_unref(align); + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(align); + dom_string_unref(name); + + return CSS_OK; + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_center)) { + hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER; + + dom_string_unref(name); + + return CSS_OK; + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_caption)) { + err = dom_element_get_attribute(node, + corestring_dom_align, &align); + if (err != DOM_NO_ERR) { + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + if (align == NULL || dom_string_caseless_lwc_isequal(align, + corestring_lwc_center)) { + hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_left)) { + hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_right)) { + hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_justify)) { + hint->status = CSS_TEXT_ALIGN_JUSTIFY; + } else { + dom_string_unref(align); + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + if (align != NULL) + dom_string_unref(align); + dom_string_unref(name); + + return CSS_OK; + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_div) || + dom_string_caseless_lwc_isequal(name, + corestring_lwc_thead) || + dom_string_caseless_lwc_isequal(name, + corestring_lwc_tbody) || + dom_string_caseless_lwc_isequal(name, + corestring_lwc_tfoot) || + dom_string_caseless_lwc_isequal(name, + corestring_lwc_tr) || + dom_string_caseless_lwc_isequal(name, + corestring_lwc_td) || + dom_string_caseless_lwc_isequal(name, + corestring_lwc_th)) { + err = dom_element_get_attribute(node, + corestring_dom_align, &align); + if (err != DOM_NO_ERR || align == NULL) { + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_center)) { + hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_left)) { + hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_right)) { + hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_justify)) { + hint->status = CSS_TEXT_ALIGN_JUSTIFY; + } else { + dom_string_unref(align); + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(align); + dom_string_unref(name); + + return CSS_OK; + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_table)) { + /* Tables usually reset alignment */ + hint->status = CSS_TEXT_ALIGN_INHERIT_IF_NON_MAGIC; + + dom_string_unref(name); + + return CSS_OK; + } else { + dom_string_unref(name); + + return CSS_PROPERTY_NOT_SET; + } + +} + +static css_error node_presentational_hint_padding_trbl( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_string *name; + dom_exception exc; + dom_string *cellpadding = NULL; + css_error result = CSS_PROPERTY_NOT_SET; + + exc = dom_node_get_node_name(node, &name); + if (exc != DOM_NO_ERR) + return CSS_BADPARM; + + if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { + css_qname qs; + dom_node *tablenode = NULL; + qs.ns = NULL; + qs.name = lwc_string_ref(corestring_lwc_table); + if (named_ancestor_node(ctx, node, &qs, + (void *)&tablenode) != CSS_OK) { + /* Didn't find, or had error */ + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + lwc_string_unref(qs.name); + + if (tablenode != NULL) { + exc = dom_element_get_attribute(tablenode, + corestring_dom_cellpadding, + &cellpadding); + if (exc != DOM_NO_ERR) { + dom_string_unref(name); + return CSS_BADPARM; + } + } + /* No need to unref tablenode, named_ancestor_node does not + * return a reffed node to the CSS + */ + } + + dom_string_unref(name); + + if (cellpadding != NULL) { + if (parse_dimension(dom_string_data(cellpadding), false, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->status = CSS_PADDING_SET; + result = CSS_OK; + } + dom_string_unref(cellpadding); + } + + return result; +} + +static css_error node_presentational_hint_margin_rl( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint, + uint32_t property) +{ + dom_string *n; + dom_exception exc; + + exc = dom_node_get_node_name(node, &n); + if (exc != DOM_NO_ERR) + return CSS_BADPARM; + + if (dom_string_caseless_lwc_isequal(n, corestring_lwc_img) || + dom_string_caseless_lwc_isequal(n, corestring_lwc_applet)) { + dom_string_unref(n); + exc = dom_element_get_attribute(node, + corestring_dom_hspace, &n); + if (exc != DOM_NO_ERR) { + return CSS_BADPARM; + } + + if (n == NULL) + return CSS_PROPERTY_NOT_SET; + + if (parse_dimension(dom_string_data(n), false, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->status = CSS_MARGIN_SET; + } else { + dom_string_unref(n); + return CSS_PROPERTY_NOT_SET; + } + dom_string_unref(n); + return CSS_OK; + } else if (dom_string_caseless_lwc_isequal(n, corestring_lwc_table) || + dom_string_caseless_lwc_isequal(n, corestring_lwc_align)) { + dom_string_unref(n); + exc = dom_element_get_attribute(node, + corestring_dom_align, &n); + if (exc != DOM_NO_ERR) { + return CSS_BADPARM; + } + + if (n == NULL) + return CSS_PROPERTY_NOT_SET; + + if (dom_string_caseless_lwc_isequal(n, + corestring_lwc_center) || + dom_string_caseless_lwc_isequal(n, + corestring_lwc_abscenter) || + dom_string_caseless_lwc_isequal(n, + corestring_lwc_middle) || + dom_string_caseless_lwc_isequal(n, + corestring_lwc_absmiddle)) { + hint->status = CSS_MARGIN_AUTO; + } else { + dom_string_unref(n); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(n); + return CSS_OK; + } else if (dom_string_caseless_lwc_isequal(n, corestring_lwc_hr)) { + dom_string_unref(n); + exc = dom_element_get_attribute(node, + corestring_dom_align, &n); + if (exc != DOM_NO_ERR) + return CSS_BADPARM; + + if (n == NULL) + return CSS_PROPERTY_NOT_SET; + + if (dom_string_caseless_lwc_isequal(n, + corestring_lwc_left)) { + if (property == CSS_PROP_MARGIN_LEFT) { + hint->data.length.value = 0; + hint->data.length.unit = CSS_UNIT_PX; + hint->status = CSS_MARGIN_SET; + } else { + hint->status = CSS_MARGIN_AUTO; + } + } else if (dom_string_caseless_lwc_isequal(n, + corestring_lwc_center)) { + hint->status = CSS_MARGIN_AUTO; + } else if (dom_string_caseless_lwc_isequal(n, + corestring_lwc_right)) { + if (property == CSS_PROP_MARGIN_RIGHT) { + hint->data.length.value = 0; + hint->data.length.unit = CSS_UNIT_PX; + hint->status = CSS_MARGIN_SET; + } else { + hint->status = CSS_MARGIN_AUTO; + } + } else { + dom_string_unref(n); + return CSS_PROPERTY_NOT_SET; + } + dom_string_unref(n); + + return CSS_OK; + } + + dom_string_unref(n); + + return CSS_PROPERTY_NOT_SET; +} + +static css_error node_presentational_hint_margin_tb( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_string *name, *vspace = NULL; + dom_exception exc; + + exc = dom_node_get_node_name(node, &name); + if (exc != DOM_NO_ERR) + return CSS_BADPARM; + + if (dom_string_caseless_lwc_isequal(name, corestring_lwc_img) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) { + exc = dom_element_get_attribute(node, corestring_dom_vspace, + &vspace); + if (exc != DOM_NO_ERR) { + dom_string_unref(name); + return CSS_BADPARM; + } + } + + dom_string_unref(name); + + if (vspace == NULL) + return CSS_PROPERTY_NOT_SET; + + if (parse_dimension(dom_string_data(vspace), false, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->status = CSS_MARGIN_SET; + } else { + dom_string_unref(vspace); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(vspace); + + return CSS_OK; +} + +static css_error node_presentational_hint_border_trbl_width( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_string *name; + dom_exception exc; + dom_string *width = NULL; + bool is_table_cell = false; + + exc = dom_node_get_node_name(node, &name); + if (exc != DOM_NO_ERR) + return CSS_BADPARM; + + if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { + css_qname qs; + dom_node *tablenode = NULL; + qs.ns = NULL; + qs.name = lwc_string_ref(corestring_lwc_table); + if (named_ancestor_node(ctx, node, &qs, + (void *)&tablenode) != CSS_OK) { + /* Didn't find, or had error */ + lwc_string_unref(qs.name); + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + lwc_string_unref(qs.name); + if (tablenode != NULL) { + exc = dom_element_get_attribute(tablenode, + corestring_dom_border, &width); + if (exc != DOM_NO_ERR) { + dom_string_unref(name); + return CSS_BADPARM; + } + } + /* No need to unref tablenode, named_ancestor_node does not + * return a reffed node to the CSS + */ + is_table_cell = true; + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_table)) { + exc = dom_element_get_attribute(node, corestring_dom_border, + &width); + if (exc != DOM_NO_ERR) { + dom_string_unref(name); + return CSS_BADPARM; + } + } + + dom_string_unref(name); + + if (width == NULL) + return CSS_PROPERTY_NOT_SET; + + if (parse_dimension(dom_string_data(width), false, + &hint->data.length.value, + &hint->data.length.unit)) { + if (is_table_cell && + INTTOFIX(0) != + hint->data.length.value) { + hint->data.length.value = INTTOFIX(1); + hint->data.length.unit = CSS_UNIT_PX; + } + hint->status = CSS_BORDER_WIDTH_WIDTH; + } else { + dom_string_unref(width); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(width); + + return CSS_OK; +} + +static css_error node_presentational_hint_border_trbl_style( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_string *name; + dom_exception exc; + + exc = dom_node_get_node_name(node, &name); + if (exc != DOM_NO_ERR) + return CSS_BADPARM; + + if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { + css_qname qs; + dom_node *tablenode = NULL; + qs.ns = NULL; + qs.name = lwc_string_ref(corestring_lwc_table); + + if (named_ancestor_node(ctx, node, &qs, + (void *)&tablenode) != CSS_OK) { + /* Didn't find, or had error */ + lwc_string_unref(qs.name); + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + lwc_string_unref(qs.name); + + if (tablenode != NULL) { + bool has_border = false; + + exc = dom_element_has_attribute(tablenode, + corestring_dom_border, + &has_border); + if (exc != DOM_NO_ERR) { + dom_string_unref(name); + return CSS_BADPARM; + } + + if (has_border) { + hint->status = CSS_BORDER_STYLE_INSET; + dom_string_unref(name); + return CSS_OK; + } + } + /* No need to unref tablenode, named_ancestor_node does not + * return a reffed node to the CSS + */ + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_table)) { + bool has_border = false; + + exc = dom_element_has_attribute(node, + corestring_dom_border, + &has_border); + if (exc != DOM_NO_ERR) { + dom_string_unref(name); + return CSS_BADPARM; + } + + if (has_border) { + hint->status = CSS_BORDER_STYLE_OUTSET; + dom_string_unref(name); + return CSS_OK; + } + } + + dom_string_unref(name); + + return CSS_PROPERTY_NOT_SET; +} + +static css_error node_presentational_hint_border_trbl_color( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_string *name; + dom_string *bordercolor = NULL; + dom_exception err; + + err = dom_node_get_node_name(node, &name); + if (err != DOM_NO_ERR) + return CSS_PROPERTY_NOT_SET; + + if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { + css_qname qs; + dom_node *tablenode = NULL; + qs.ns = NULL; + qs.name = lwc_string_ref(corestring_lwc_table); + + if (named_ancestor_node(ctx, node, &qs, + (void *)&tablenode) != CSS_OK) { + /* Didn't find, or had error */ + lwc_string_unref(qs.name); + dom_string_unref(name); + return CSS_PROPERTY_NOT_SET; + } + + lwc_string_unref(qs.name); + + if (tablenode != NULL) { + err = dom_element_get_attribute(node, + corestring_dom_bordercolor, + &bordercolor); + } + /* No need to unref tablenode, named_ancestor_node does not + * return a reffed node to the CSS + */ + + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_table)) { + err = dom_element_get_attribute(node, + corestring_dom_bordercolor, + &bordercolor); + } + + dom_string_unref(name); + + if ((err != DOM_NO_ERR) || (bordercolor == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + if (nscss_parse_colour((const char *)dom_string_data(bordercolor), + &hint->data.color)) { + hint->status = CSS_BORDER_COLOR_COLOR; + dom_string_unref(bordercolor); + return CSS_OK; + } + + dom_string_unref(bordercolor); + return CSS_PROPERTY_NOT_SET; +} + +static css_error node_presentational_hint_border_spacing( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_exception err; + dom_string *node_name = NULL; + dom_string *cellspacing = NULL; + + err = dom_node_get_node_name(node, &node_name); + if ((err != DOM_NO_ERR) || (node_name == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + if (!dom_string_caseless_lwc_isequal(node_name, + corestring_lwc_table)) { + dom_string_unref(node_name); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(node_name); + + err = dom_element_get_attribute(node, + corestring_dom_cellspacing, &cellspacing); + if ((err != DOM_NO_ERR) || (cellspacing == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + + if (parse_dimension((const char *)dom_string_data(cellspacing), + false, + &hint->data.position.h.value, + &hint->data.position.h.unit)) { + + hint->data.position.v = hint->data.position.h; + hint->status = CSS_BORDER_SPACING_SET; + + dom_string_unref(cellspacing); + return CSS_OK; + } + + dom_string_unref(cellspacing); + return CSS_PROPERTY_NOT_SET; +} + +static css_error node_presentational_hint_width( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_string *name; + dom_string *width = NULL; + dom_exception err; + bool textarea = false; + bool input = false; + + err = dom_node_get_node_name(node, &name); + if (err != DOM_NO_ERR) + return CSS_PROPERTY_NOT_SET; + + if (dom_string_caseless_lwc_isequal(name, corestring_lwc_hr) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_iframe) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_img) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_object) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_table) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_th) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) { + err = dom_element_get_attribute(node, + corestring_dom_width, &width); + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_textarea)) { + textarea = true; + err = dom_element_get_attribute(node, + corestring_dom_cols, &width); + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_input)) { + input = true; + err = dom_element_get_attribute(node, + corestring_dom_size, &width); + } + + dom_string_unref(name); + + if ((err != DOM_NO_ERR) || (width == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + if (parse_dimension((const char *)dom_string_data(width), + false, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->status = CSS_WIDTH_SET; + dom_string_unref(width); + + if (textarea) { + hint->data.length.unit = CSS_UNIT_EX; + } + + if (input) { + err = dom_element_get_attribute(node, + corestring_dom_type, &width); + if (err != DOM_NO_ERR) { + return CSS_PROPERTY_NOT_SET; + } + + if ((width == NULL) || + dom_string_caseless_lwc_isequal(width, + corestring_lwc_text) || + dom_string_caseless_lwc_isequal(width, + corestring_lwc_search) || + dom_string_caseless_lwc_isequal(width, + corestring_lwc_file) || + dom_string_caseless_lwc_isequal(width, + corestring_lwc_password)) { + hint->data.length.unit = CSS_UNIT_EX; + } + dom_string_unref(width); + } + + return CSS_OK; + } + + dom_string_unref(width); + return CSS_PROPERTY_NOT_SET; + +} + +static css_error node_presentational_hint_height(nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_string *name; + dom_string *height = NULL; + dom_exception err; + bool textarea = false; + + err = dom_node_get_node_name(node, &name); + if (err != DOM_NO_ERR) + return CSS_PROPERTY_NOT_SET; + + if (dom_string_caseless_lwc_isequal(name, corestring_lwc_iframe) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_th) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_tr) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_img) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_object) || + dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) { + err = dom_element_get_attribute(node, + corestring_dom_height, &height); + } else if (dom_string_caseless_lwc_isequal(name, + corestring_lwc_textarea)) { + textarea = true; + err = dom_element_get_attribute(node, + corestring_dom_rows, &height); + } + + dom_string_unref(name); + + if ((err != DOM_NO_ERR) || (height == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + if (parse_dimension((const char *)dom_string_data(height), + false, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->status = CSS_HEIGHT_SET; + + if (textarea) { + hint->data.length.unit = CSS_UNIT_EM; + } + + dom_string_unref(height); + return CSS_OK; + } + + dom_string_unref(height); + return CSS_PROPERTY_NOT_SET; +} + +static css_error node_presentational_hint_font_size( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_exception err; + dom_string *node_name = NULL; + dom_string *size; + + err = dom_node_get_node_name(node, &node_name); + if ((err != DOM_NO_ERR) || (node_name == NULL)) { + return CSS_NOMEM; + } + + if (!dom_string_caseless_lwc_isequal(node_name, + corestring_lwc_font)) { + dom_string_unref(node_name); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(node_name); + + err = dom_element_get_attribute(node, corestring_dom_size, &size); + if ((err != DOM_NO_ERR) || (size == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + if (parse_font_size((const char *)dom_string_data(size), + &hint->status, + &hint->data.length.value, + &hint->data.length.unit)) { + dom_string_unref(size); + return CSS_OK; + } + + dom_string_unref(size); + return CSS_PROPERTY_NOT_SET; +} + +static css_error node_presentational_hint_float( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_exception err; + dom_string *node_name = NULL; + dom_string *align; + + err = dom_node_get_node_name(node, &node_name); + if ((err != DOM_NO_ERR) || (node_name == NULL)) { + return CSS_NOMEM; + } + + /** \todo input[type=image][align=*] - $11.3.3 */ + if (!dom_string_caseless_lwc_isequal(node_name, + corestring_lwc_table) && + !dom_string_caseless_lwc_isequal(node_name, + corestring_lwc_applet) && + !dom_string_caseless_lwc_isequal(node_name, + corestring_lwc_embed) && + !dom_string_caseless_lwc_isequal(node_name, + corestring_lwc_iframe) && + !dom_string_caseless_lwc_isequal(node_name, + corestring_lwc_img) && + !dom_string_caseless_lwc_isequal(node_name, + corestring_lwc_object)) { + dom_string_unref(node_name); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(node_name); + + err = dom_element_get_attribute(node, corestring_dom_align, &align); + if ((err != DOM_NO_ERR) || (align == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_left)) { + hint->status = CSS_FLOAT_LEFT; + dom_string_unref(align); + return CSS_OK; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_right)) { + hint->status = CSS_FLOAT_RIGHT; + dom_string_unref(align); + return CSS_OK; + } + + dom_string_unref(align); + + return CSS_PROPERTY_NOT_SET; +} + +static css_error node_presentational_hint_color( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + css_error error; + dom_exception err; + dom_string *node_name = NULL; + dom_string *color; + + err = dom_node_get_node_name(node, &node_name); + if ((err != DOM_NO_ERR) || (node_name == NULL)) { + return CSS_NOMEM; + } + + if (dom_string_caseless_lwc_isequal(node_name, corestring_lwc_a)) { + /* find body node */ + css_qname qs; + dom_node *bodynode = NULL; + bool is_visited; + + qs.ns = NULL; + qs.name = lwc_string_ref(corestring_lwc_body); + if (named_ancestor_node(ctx, node, &qs, + (void *)&bodynode) != CSS_OK) { + /* Didn't find, or had error */ + lwc_string_unref(qs.name); + dom_string_unref(node_name); + return CSS_PROPERTY_NOT_SET; + } + + lwc_string_unref(qs.name); + + /* deal with missing body ancestor */ + if (bodynode == NULL) { + dom_string_unref(node_name); + return CSS_BADPARM; + } + + error = node_is_visited(ctx, node, &is_visited); + if (error != CSS_OK) + return error; + + if (is_visited) { + err = dom_element_get_attribute(bodynode, + corestring_dom_vlink, &color); + if ((err != DOM_NO_ERR) || (color == NULL)) { + dom_string_unref(node_name); + return CSS_PROPERTY_NOT_SET; + } + } else { + err = dom_element_get_attribute(bodynode, + corestring_dom_link, &color); + if ((err != DOM_NO_ERR) || (color == NULL)) { + dom_string_unref(node_name); + return CSS_PROPERTY_NOT_SET; + } + } + } else if (dom_string_caseless_lwc_isequal(node_name, + corestring_lwc_body)) { + err = dom_element_get_attribute(node, + corestring_dom_text, &color); + if ((err != DOM_NO_ERR) || (color == NULL)) { + dom_string_unref(node_name); + return CSS_PROPERTY_NOT_SET; + } + } else { + err = dom_element_get_attribute(node, + corestring_dom_color, &color); + if ((err != DOM_NO_ERR) || (color == NULL)) { + dom_string_unref(node_name); + return CSS_PROPERTY_NOT_SET; + } + } + + if (!nscss_parse_colour((const char *)dom_string_data(color), + &hint->data.color)) { + dom_string_unref(color); + dom_string_unref(node_name); + return CSS_PROPERTY_NOT_SET; + } + + hint->status = CSS_COLOR_COLOR; + + dom_string_unref(color); + dom_string_unref(node_name); + + return CSS_OK; +} + +static css_error node_presentational_hint_caption_side( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_exception err; + dom_string *node_name = NULL; + dom_string *align = NULL; + + err = dom_node_get_node_name(node, &node_name); + if ((err != DOM_NO_ERR) || (node_name == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + if (!dom_string_caseless_lwc_isequal(node_name, + corestring_lwc_caption)) { + dom_string_unref(node_name); + return CSS_PROPERTY_NOT_SET; + } + + dom_string_unref(node_name); + + err = dom_element_get_attribute(node, corestring_dom_align, &align); + if ((err != DOM_NO_ERR) || (align == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + if (dom_string_caseless_lwc_isequal(align, corestring_lwc_bottom)) { + hint->status = CSS_CAPTION_SIDE_BOTTOM; + dom_string_unref(align); + return CSS_OK; + } + + dom_string_unref(align); + + return CSS_PROPERTY_NOT_SET; +} + +static css_error node_presentational_hint_background_color( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_exception err; + dom_string *bgcolor; + + err = dom_element_get_attribute(node, + corestring_dom_bgcolor, &bgcolor); + if ((err != DOM_NO_ERR) || (bgcolor == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + if (nscss_parse_colour((const char *)dom_string_data(bgcolor), + &hint->data.color)) { + hint->status = CSS_BACKGROUND_COLOR_COLOR; + dom_string_unref(bgcolor); + return CSS_OK; + } + + dom_string_unref(bgcolor); + + return CSS_PROPERTY_NOT_SET; +} + +static css_error node_presentational_hint_background_image( + nscss_select_ctx *ctx, + dom_node *node, + css_hint *hint) +{ + dom_exception err; + dom_string *atr_val; + nserror error; + nsurl *url; + lwc_string *iurl; + lwc_error lerror; + + err = dom_element_get_attribute(node, + corestring_dom_background, &atr_val); + if ((err != DOM_NO_ERR) || (atr_val == NULL)) { + return CSS_PROPERTY_NOT_SET; + } + + error = nsurl_join(ctx->base_url, + (const char *)dom_string_data(atr_val), &url); + + dom_string_unref(atr_val); + + if (error != NSERROR_OK) { + return CSS_NOMEM; + } + + lerror = lwc_intern_string(nsurl_access(url), + nsurl_length(url), &iurl); + + nsurl_unref(url); + + if (lerror == lwc_error_oom) { + return CSS_NOMEM; + } + + if (lerror == lwc_error_ok) { + hint->data.string = iurl; + hint->status = CSS_BACKGROUND_IMAGE_IMAGE; + return CSS_OK; + } + + return CSS_PROPERTY_NOT_SET; +} + +/* Exported function, documeted in css/hints.h */ +css_error node_presentational_hint(void *pw, void *node, + uint32_t property, css_hint *hint) +{ + + switch (property) { + case CSS_PROP_BACKGROUND_IMAGE: + return node_presentational_hint_background_image(pw, node, hint); + + case CSS_PROP_BACKGROUND_COLOR: + return node_presentational_hint_background_color(pw, node, hint); + case CSS_PROP_CAPTION_SIDE: + return node_presentational_hint_caption_side(pw, node, hint); + + case CSS_PROP_COLOR: + return node_presentational_hint_color(pw, node, hint); + + case CSS_PROP_FLOAT: + return node_presentational_hint_float(pw, node, hint); + + case CSS_PROP_FONT_SIZE: + return node_presentational_hint_font_size(pw, node, hint); + + case CSS_PROP_HEIGHT: + return node_presentational_hint_height(pw, node, hint); + + case CSS_PROP_WIDTH: + return node_presentational_hint_width(pw, node, hint); + + case CSS_PROP_BORDER_SPACING: + return node_presentational_hint_border_spacing(pw, node, hint); + + case CSS_PROP_BORDER_TOP_COLOR : + case CSS_PROP_BORDER_RIGHT_COLOR : + case CSS_PROP_BORDER_BOTTOM_COLOR : + case CSS_PROP_BORDER_LEFT_COLOR : + return node_presentational_hint_border_trbl_color(pw, node, hint); + + case CSS_PROP_BORDER_TOP_STYLE : + case CSS_PROP_BORDER_RIGHT_STYLE : + case CSS_PROP_BORDER_BOTTOM_STYLE : + case CSS_PROP_BORDER_LEFT_STYLE : + return node_presentational_hint_border_trbl_style(pw, node, hint); + + case CSS_PROP_BORDER_TOP_WIDTH : + case CSS_PROP_BORDER_RIGHT_WIDTH : + case CSS_PROP_BORDER_BOTTOM_WIDTH : + case CSS_PROP_BORDER_LEFT_WIDTH : + return node_presentational_hint_border_trbl_width(pw, node, hint); + + case CSS_PROP_MARGIN_TOP : + case CSS_PROP_MARGIN_BOTTOM : + return node_presentational_hint_margin_tb(pw, node, hint); + + case CSS_PROP_MARGIN_RIGHT: + case CSS_PROP_MARGIN_LEFT: + return node_presentational_hint_margin_rl(pw, node, hint, property); + + case CSS_PROP_PADDING_TOP: + case CSS_PROP_PADDING_RIGHT : + case CSS_PROP_PADDING_BOTTOM : + case CSS_PROP_PADDING_LEFT: + return node_presentational_hint_padding_trbl(pw, node, hint); + + case CSS_PROP_TEXT_ALIGN: + return node_presentational_hint_text_align(pw, node, hint); + + case CSS_PROP_VERTICAL_ALIGN: + return node_presentational_hint_vertical_align(pw, node, hint); + } + + return CSS_PROPERTY_NOT_SET; +} + diff --git a/css/hints.h b/css/hints.h new file mode 100644 index 000000000..68d4c1063 --- /dev/null +++ b/css/hints.h @@ -0,0 +1,48 @@ +/* + * Copyright 2009 John-Mark Bell + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef NETSURF_CSS_HINTS_H_ +#define NETSURF_CSS_HINTS_H_ + +#include + +#include "css/css.h" + + + + +/** + * Callback to retrieve presentational hints for a node + * + * \param pw HTML document + * \param node DOM node + * \param property CSS property to retrieve + * \param hint Pointer to hint object to populate + * \return CSS_OK on success, + * CSS_PROPERTY_NOT_SET if there is no hint for the requested property, + * CSS_NOMEM on memory exhaustion. + */ +css_error node_presentational_hint( + void *pw, + void *node, + uint32_t property, + css_hint *hint); + +bool nscss_parse_colour(const char *data, css_color *result); + +#endif diff --git a/css/select.c b/css/select.c index e88d3f61f..a929cf10a 100644 --- a/css/select.c +++ b/css/select.c @@ -17,28 +17,23 @@ */ #include -#include #include #include -#include "content/content_protected.h" #include "content/urldb.h" #include "desktop/system_colour.h" #include "utils/nsoption.h" #include "utils/corestrings.h" #include "utils/log.h" -#include "utils/utils.h" #include "css/internal.h" +#include "css/hints.h" #include "css/select.h" -#include "css/utils.h" static css_error node_name(void *pw, void *node, css_qname *qname); static css_error node_classes(void *pw, void *node, lwc_string ***classes, uint32_t *n_classes); static css_error node_id(void *pw, void *node, lwc_string **id); -static css_error named_ancestor_node(void *pw, void *node, - const css_qname *qname, void **ancestor); static css_error named_parent_node(void *pw, void *node, const css_qname *qname, void **parent); static css_error named_sibling_node(void *pw, void *node, @@ -78,7 +73,6 @@ static css_error node_count_siblings(void *pw, void *node, bool same_name, bool after, int32_t *count); static css_error node_is_empty(void *pw, void *node, bool *match); static css_error node_is_link(void *pw, void *node, bool *match); -static css_error node_is_visited(void *pw, void *node, bool *match); static css_error node_is_hover(void *pw, void *node, bool *match); static css_error node_is_active(void *pw, void *node, bool *match); static css_error node_is_focus(void *pw, void *node, bool *match); @@ -88,8 +82,6 @@ static css_error node_is_checked(void *pw, void *node, bool *match); static css_error node_is_target(void *pw, void *node, bool *match); static css_error node_is_lang(void *pw, void *node, lwc_string *lang, bool *match); -static css_error node_presentational_hint(void *pw, void *node, - uint32_t property, css_hint *hint); static css_error ua_default_for_property(void *pw, uint32_t property, css_hint *hint); static css_error set_libcss_node_data(void *pw, void *node, @@ -97,18 +89,9 @@ static css_error set_libcss_node_data(void *pw, void *node, static css_error get_libcss_node_data(void *pw, void *node, void **libcss_node_data); -static int cmp_colour_name(const void *a, const void *b); -static bool parse_named_colour(const char *data, css_color *result); -static bool parse_dimension(const char *data, bool strict, - css_fixed *length, css_unit *unit); -static bool parse_number(const char *data, bool non_negative, bool real, - css_fixed *value, size_t *consumed); -static bool parse_font_size(const char *size, uint8_t *val, - css_fixed *len, css_unit *unit); +static css_error nscss_compute_font_size(void *pw, const css_hint *parent, + css_hint *size); -static bool isWhitespace(char c); -static bool isHex(char c); -static uint8_t charToHex(char c); /** * Selection callback table for libcss @@ -465,64 +448,6 @@ css_error nscss_compute_font_size(void *pw, const css_hint *parent, return CSS_OK; } -/** - * Parser for colours specified in attribute values. - * - * \param data Data to parse (NUL-terminated) - * \param result Pointer to location to receive resulting css_color - * \return true on success, false on invalid input - */ -bool nscss_parse_colour(const char *data, css_color *result) -{ - size_t len = strlen(data); - uint8_t r, g, b; - - /* 2 */ - if (len == 0) - return false; - - /* 3 */ - if (len == SLEN("transparent") && strcasecmp(data, "transparent") == 0) - return false; - - /* 4 */ - if (parse_named_colour(data, result)) - return true; - - /** \todo Implement HTML5's utterly insane legacy colour parsing */ - - if (data[0] == '#') { - data++; - len--; - } - - if (len == 3 && isHex(data[0]) && isHex(data[1]) && isHex(data[2])) { - r = charToHex(data[0]); - g = charToHex(data[1]); - b = charToHex(data[2]); - - r |= (r << 4); - g |= (g << 4); - b |= (b << 4); - - *result = (0xff << 24) | (r << 16) | (g << 8) | b; - - return true; - } else if (len == 6 && isHex(data[0]) && isHex(data[1]) && - isHex(data[2]) && isHex(data[3]) && isHex(data[4]) && - isHex(data[5])) { - r = (charToHex(data[0]) << 4) | charToHex(data[1]); - g = (charToHex(data[2]) << 4) | charToHex(data[3]); - b = (charToHex(data[4]) << 4) | charToHex(data[5]); - - *result = (0xff << 24) | (r << 16) | (g << 8) | b; - - return true; - } - - return false; -} - /****************************************************************************** * Style selection callbacks * ******************************************************************************/ @@ -1844,1794 +1769,86 @@ css_error node_is_lang(void *pw, void *node, return CSS_OK; } -static css_error -node_presentational_hint_vertical_align(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_string *name; - dom_string *valign = NULL; - dom_exception err; - - err = dom_node_get_node_name(node, &name); - if (err != DOM_NO_ERR) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_col) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_thead) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_tbody) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_tfoot) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_tr) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { - err = dom_element_get_attribute(node, - corestring_dom_valign, &valign); - if (err != DOM_NO_ERR || valign == NULL) { - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - if (dom_string_caseless_lwc_isequal(valign, - corestring_lwc_top)) { - hint->status = CSS_VERTICAL_ALIGN_TOP; - } else if (dom_string_caseless_lwc_isequal(valign, - corestring_lwc_middle)) { - hint->status = CSS_VERTICAL_ALIGN_MIDDLE; - } else if (dom_string_caseless_lwc_isequal(valign, - corestring_lwc_bottom)) { - hint->status = CSS_VERTICAL_ALIGN_BOTTOM; - } else if (dom_string_caseless_lwc_isequal(valign, - corestring_lwc_baseline)) { - hint->status = CSS_VERTICAL_ALIGN_BASELINE; - } else { - dom_string_unref(valign); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(valign); - dom_string_unref(name); - - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_applet) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_embed) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_iframe) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_img) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_object)) { - /** \todo input[type=image][align=*] - $11.3.3 */ - err = dom_element_get_attribute(node, - corestring_dom_align, &valign); - if (err != DOM_NO_ERR || valign == NULL) { - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - if (dom_string_caseless_lwc_isequal(valign, - corestring_lwc_top)) { - hint->status = CSS_VERTICAL_ALIGN_TOP; - } else if (dom_string_caseless_lwc_isequal(valign, - corestring_lwc_bottom) || - dom_string_caseless_lwc_isequal(valign, - corestring_lwc_baseline)) { - hint->status = CSS_VERTICAL_ALIGN_BASELINE; - } else if (dom_string_caseless_lwc_isequal(valign, - corestring_lwc_texttop)) { - hint->status = CSS_VERTICAL_ALIGN_TEXT_TOP; - } else if (dom_string_caseless_lwc_isequal(valign, - corestring_lwc_absmiddle) || - dom_string_caseless_lwc_isequal(valign, - corestring_lwc_abscenter)) { - hint->status = CSS_VERTICAL_ALIGN_MIDDLE; - } else { - dom_string_unref(valign); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(valign); - dom_string_unref(name); - - return CSS_OK; - } - - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; -} - -static css_error -node_presentational_hint_text_align(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +/** + * Callback to retrieve the User-Agent defaults for a CSS property. + * + * \param pw HTML document + * \param property Property to retrieve defaults for + * \param hint Pointer to hint object to populate + * \return CSS_OK on success, + * CSS_INVALID if the property should not have a user-agent default. + */ +css_error ua_default_for_property(void *pw, uint32_t property, css_hint *hint) { - dom_string *name; - dom_string *align = NULL; - dom_exception err; - - err = dom_node_get_node_name(node, &name); - if (err != DOM_NO_ERR) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_p) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h1) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h2) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h3) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h4) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h5) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h6)) { - err = dom_element_get_attribute(node, - corestring_dom_align, &align); - if (err != DOM_NO_ERR || align == NULL) { - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_left)) { - hint->status = CSS_TEXT_ALIGN_LEFT; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_center)) { - hint->status = CSS_TEXT_ALIGN_CENTER; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_right)) { - hint->status = CSS_TEXT_ALIGN_RIGHT; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_justify)) { - hint->status = CSS_TEXT_ALIGN_JUSTIFY; - } else { - dom_string_unref(align); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(align); - dom_string_unref(name); - - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_center)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER; - - dom_string_unref(name); - - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_caption)) { - err = dom_element_get_attribute(node, - corestring_dom_align, &align); - if (err != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - if (align == NULL || dom_string_caseless_lwc_isequal(align, - corestring_lwc_center)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_left)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_right)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_justify)) { - hint->status = CSS_TEXT_ALIGN_JUSTIFY; - } else { - dom_string_unref(align); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - if (align != NULL) - dom_string_unref(align); - dom_string_unref(name); - - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_div) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_thead) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_tbody) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_tfoot) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_tr) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_th)) { - err = dom_element_get_attribute(node, - corestring_dom_align, &align); - if (err != DOM_NO_ERR || align == NULL) { - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_center)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_left)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_right)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_justify)) { - hint->status = CSS_TEXT_ALIGN_JUSTIFY; - } else { - dom_string_unref(align); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; + if (property == CSS_PROP_COLOR) { + hint->data.color = 0xff000000; + hint->status = CSS_COLOR_COLOR; + } else if (property == CSS_PROP_FONT_FAMILY) { + hint->data.strings = NULL; + switch (nsoption_int(font_default)) { + case PLOT_FONT_FAMILY_SANS_SERIF: + hint->status = CSS_FONT_FAMILY_SANS_SERIF; + break; + case PLOT_FONT_FAMILY_SERIF: + hint->status = CSS_FONT_FAMILY_SERIF; + break; + case PLOT_FONT_FAMILY_MONOSPACE: + hint->status = CSS_FONT_FAMILY_MONOSPACE; + break; + case PLOT_FONT_FAMILY_CURSIVE: + hint->status = CSS_FONT_FAMILY_CURSIVE; + break; + case PLOT_FONT_FAMILY_FANTASY: + hint->status = CSS_FONT_FAMILY_FANTASY; + break; } - - dom_string_unref(align); - dom_string_unref(name); - - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_table)) { - /* Tables usually reset alignment */ - hint->status = CSS_TEXT_ALIGN_INHERIT_IF_NON_MAGIC; - - dom_string_unref(name); - - return CSS_OK; + } else if (property == CSS_PROP_QUOTES) { + /** \todo Not exactly useful :) */ + hint->data.strings = NULL; + hint->status = CSS_QUOTES_NONE; + } else if (property == CSS_PROP_VOICE_FAMILY) { + /** \todo Fix this when we have voice-family done */ + hint->data.strings = NULL; + hint->status = 0; } else { - dom_string_unref(name); - - return CSS_PROPERTY_NOT_SET; - } - -} - -static css_error -node_presentational_hint_padding_trbl(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_string *name; - dom_exception exc; - dom_string *cellpadding = NULL; - css_error result = CSS_PROPERTY_NOT_SET; - - exc = dom_node_get_node_name(node, &name); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { - css_qname qs; - dom_node *tablenode = NULL; - qs.ns = NULL; - qs.name = lwc_string_ref(corestring_lwc_table); - if (named_ancestor_node(ctx, node, &qs, - (void *)&tablenode) != CSS_OK) { - /* Didn't find, or had error */ - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - lwc_string_unref(qs.name); - - if (tablenode != NULL) { - exc = dom_element_get_attribute(tablenode, - corestring_dom_cellpadding, - &cellpadding); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } - } - /* No need to unref tablenode, named_ancestor_node does not - * return a reffed node to the CSS - */ + return CSS_INVALID; } - - dom_string_unref(name); - if (cellpadding != NULL) { - if (parse_dimension(dom_string_data(cellpadding), false, - &hint->data.length.value, - &hint->data.length.unit)) { - hint->status = CSS_PADDING_SET; - result = CSS_OK; - } - dom_string_unref(cellpadding); - } - - return result; + return CSS_OK; } -static css_error -node_presentational_hint_margin_rl(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint, - uint32_t property) +css_error set_libcss_node_data(void *pw, void *node, void *libcss_node_data) { - dom_string *n; - dom_exception exc; - - exc = dom_node_get_node_name(node, &n); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (dom_string_caseless_lwc_isequal(n, corestring_lwc_img) || - dom_string_caseless_lwc_isequal(n, corestring_lwc_applet)) { - dom_string_unref(n); - exc = dom_element_get_attribute(node, - corestring_dom_hspace, &n); - if (exc != DOM_NO_ERR) { - return CSS_BADPARM; - } - - if (n == NULL) - return CSS_PROPERTY_NOT_SET; - - if (parse_dimension(dom_string_data(n), false, - &hint->data.length.value, - &hint->data.length.unit)) { - hint->status = CSS_MARGIN_SET; - } else { - dom_string_unref(n); - return CSS_PROPERTY_NOT_SET; - } - dom_string_unref(n); - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(n, corestring_lwc_table) || - dom_string_caseless_lwc_isequal(n, corestring_lwc_align)) { - dom_string_unref(n); - exc = dom_element_get_attribute(node, - corestring_dom_align, &n); - if (exc != DOM_NO_ERR) { - return CSS_BADPARM; - } - - if (n == NULL) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(n, - corestring_lwc_center) || - dom_string_caseless_lwc_isequal(n, - corestring_lwc_abscenter) || - dom_string_caseless_lwc_isequal(n, - corestring_lwc_middle) || - dom_string_caseless_lwc_isequal(n, - corestring_lwc_absmiddle)) { - hint->status = CSS_MARGIN_AUTO; - } else { - dom_string_unref(n); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(n); - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(n, corestring_lwc_hr)) { - dom_string_unref(n); - exc = dom_element_get_attribute(node, - corestring_dom_align, &n); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (n == NULL) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(n, - corestring_lwc_left)) { - if (property == CSS_PROP_MARGIN_LEFT) { - hint->data.length.value = 0; - hint->data.length.unit = CSS_UNIT_PX; - hint->status = CSS_MARGIN_SET; - } else { - hint->status = CSS_MARGIN_AUTO; - } - } else if (dom_string_caseless_lwc_isequal(n, - corestring_lwc_center)) { - hint->status = CSS_MARGIN_AUTO; - } else if (dom_string_caseless_lwc_isequal(n, - corestring_lwc_right)) { - if (property == CSS_PROP_MARGIN_RIGHT) { - hint->data.length.value = 0; - hint->data.length.unit = CSS_UNIT_PX; - hint->status = CSS_MARGIN_SET; - } else { - hint->status = CSS_MARGIN_AUTO; - } - } else { - dom_string_unref(n); - return CSS_PROPERTY_NOT_SET; - } - dom_string_unref(n); - - return CSS_OK; - } - - dom_string_unref(n); - - return CSS_PROPERTY_NOT_SET; -} + dom_node *n = node; + dom_exception err; + void *old_node_data; -static css_error -node_presentational_hint_margin_tb(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_string *name, *vspace = NULL; - dom_exception exc; - - exc = dom_node_get_node_name(node, &name); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_img) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) { - exc = dom_element_get_attribute(node, corestring_dom_vspace, - &vspace); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } - } - - dom_string_unref(name); - - if (vspace == NULL) - return CSS_PROPERTY_NOT_SET; - - if (parse_dimension(dom_string_data(vspace), false, - &hint->data.length.value, - &hint->data.length.unit)) { - hint->status = CSS_MARGIN_SET; - } else { - dom_string_unref(vspace); - return CSS_PROPERTY_NOT_SET; + /* Set this node's node data */ + err = dom_node_set_user_data(n, + corestring_dom___ns_key_libcss_node_data, + libcss_node_data, nscss_dom_user_data_handler, + (void *) &old_node_data); + if (err != DOM_NO_ERR) { + return CSS_NOMEM; } - dom_string_unref(vspace); + assert(old_node_data == NULL); return CSS_OK; } -static css_error -node_presentational_hint_border_trbl_width(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +css_error get_libcss_node_data(void *pw, void *node, void **libcss_node_data) { - dom_string *name; - dom_exception exc; - dom_string *width = NULL; - bool is_table_cell = false; - - exc = dom_node_get_node_name(node, &name); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { - css_qname qs; - dom_node *tablenode = NULL; - qs.ns = NULL; - qs.name = lwc_string_ref(corestring_lwc_table); - if (named_ancestor_node(ctx, node, &qs, - (void *)&tablenode) != CSS_OK) { - /* Didn't find, or had error */ - lwc_string_unref(qs.name); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - lwc_string_unref(qs.name); - if (tablenode != NULL) { - exc = dom_element_get_attribute(tablenode, - corestring_dom_border, &width); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } - } - /* No need to unref tablenode, named_ancestor_node does not - * return a reffed node to the CSS - */ - is_table_cell = true; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_table)) { - exc = dom_element_get_attribute(node, corestring_dom_border, - &width); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } - } - - dom_string_unref(name); - - if (width == NULL) - return CSS_PROPERTY_NOT_SET; - - if (parse_dimension(dom_string_data(width), false, - &hint->data.length.value, - &hint->data.length.unit)) { - if (is_table_cell && - INTTOFIX(0) != - hint->data.length.value) { - hint->data.length.value = INTTOFIX(1); - hint->data.length.unit = CSS_UNIT_PX; - } - hint->status = CSS_BORDER_WIDTH_WIDTH; - } else { - dom_string_unref(width); - return CSS_PROPERTY_NOT_SET; - } + dom_node *n = node; + dom_exception err; - dom_string_unref(width); + /* Get this node's node data */ + err = dom_node_get_user_data(n, + corestring_dom___ns_key_libcss_node_data, + libcss_node_data); + if (err != DOM_NO_ERR) { + return CSS_NOMEM; + } return CSS_OK; } - -static css_error -node_presentational_hint_border_trbl_style(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_string *name; - dom_exception exc; - - exc = dom_node_get_node_name(node, &name); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { - css_qname qs; - dom_node *tablenode = NULL; - qs.ns = NULL; - qs.name = lwc_string_ref(corestring_lwc_table); - - if (named_ancestor_node(ctx, node, &qs, - (void *)&tablenode) != CSS_OK) { - /* Didn't find, or had error */ - lwc_string_unref(qs.name); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - lwc_string_unref(qs.name); - - if (tablenode != NULL) { - bool has_border = false; - - exc = dom_element_has_attribute(tablenode, - corestring_dom_border, - &has_border); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } - - if (has_border) { - hint->status = CSS_BORDER_STYLE_INSET; - dom_string_unref(name); - return CSS_OK; - } - } - /* No need to unref tablenode, named_ancestor_node does not - * return a reffed node to the CSS - */ - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_table)) { - bool has_border = false; - - exc = dom_element_has_attribute(node, - corestring_dom_border, - &has_border); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } - - if (has_border) { - hint->status = CSS_BORDER_STYLE_OUTSET; - dom_string_unref(name); - return CSS_OK; - } - } - - dom_string_unref(name); - - return CSS_PROPERTY_NOT_SET; -} - -static css_error -node_presentational_hint_border_trbl_color(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_string *name; - dom_string *bordercolor = NULL; - dom_exception err; - - err = dom_node_get_node_name(node, &name); - if (err != DOM_NO_ERR) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { - css_qname qs; - dom_node *tablenode = NULL; - qs.ns = NULL; - qs.name = lwc_string_ref(corestring_lwc_table); - - if (named_ancestor_node(ctx, node, &qs, - (void *)&tablenode) != CSS_OK) { - /* Didn't find, or had error */ - lwc_string_unref(qs.name); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - lwc_string_unref(qs.name); - - if (tablenode != NULL) { - err = dom_element_get_attribute(node, - corestring_dom_bordercolor, - &bordercolor); - } - /* No need to unref tablenode, named_ancestor_node does not - * return a reffed node to the CSS - */ - - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_table)) { - err = dom_element_get_attribute(node, - corestring_dom_bordercolor, - &bordercolor); - } - - dom_string_unref(name); - - if ((err != DOM_NO_ERR) || (bordercolor == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (nscss_parse_colour((const char *)dom_string_data(bordercolor), - &hint->data.color)) { - hint->status = CSS_BORDER_COLOR_COLOR; - dom_string_unref(bordercolor); - return CSS_OK; - } - - dom_string_unref(bordercolor); - return CSS_PROPERTY_NOT_SET; -} - -static css_error -node_presentational_hint_border_spacing(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_exception err; - dom_string *node_name = NULL; - dom_string *cellspacing = NULL; - - err = dom_node_get_node_name(node, &node_name); - if ((err != DOM_NO_ERR) || (node_name == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (!dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_table)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(node_name); - - err = dom_element_get_attribute(node, - corestring_dom_cellspacing, &cellspacing); - if ((err != DOM_NO_ERR) || (cellspacing == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - - if (parse_dimension((const char *)dom_string_data(cellspacing), - false, - &hint->data.position.h.value, - &hint->data.position.h.unit)) { - - hint->data.position.v = hint->data.position.h; - hint->status = CSS_BORDER_SPACING_SET; - - dom_string_unref(cellspacing); - return CSS_OK; - } - - dom_string_unref(cellspacing); - return CSS_PROPERTY_NOT_SET; -} - -static css_error -node_presentational_hint_width(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_string *name; - dom_string *width = NULL; - dom_exception err; - bool textarea = false; - bool input = false; - - err = dom_node_get_node_name(node, &name); - if (err != DOM_NO_ERR) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_hr) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_iframe) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_img) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_object) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_table) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) { - err = dom_element_get_attribute(node, - corestring_dom_width, &width); - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_textarea)) { - textarea = true; - err = dom_element_get_attribute(node, - corestring_dom_cols, &width); - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_input)) { - input = true; - err = dom_element_get_attribute(node, - corestring_dom_size, &width); - } - - dom_string_unref(name); - - if ((err != DOM_NO_ERR) || (width == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (parse_dimension((const char *)dom_string_data(width), - false, - &hint->data.length.value, - &hint->data.length.unit)) { - hint->status = CSS_WIDTH_SET; - dom_string_unref(width); - - if (textarea) { - hint->data.length.unit = CSS_UNIT_EX; - } - - if (input) { - err = dom_element_get_attribute(node, - corestring_dom_type, &width); - if (err != DOM_NO_ERR) { - return CSS_PROPERTY_NOT_SET; - } - - if ((width == NULL) || - dom_string_caseless_lwc_isequal(width, - corestring_lwc_text) || - dom_string_caseless_lwc_isequal(width, - corestring_lwc_search) || - dom_string_caseless_lwc_isequal(width, - corestring_lwc_file) || - dom_string_caseless_lwc_isequal(width, - corestring_lwc_password)) { - hint->data.length.unit = CSS_UNIT_EX; - } - dom_string_unref(width); - } - - return CSS_OK; - } - - dom_string_unref(width); - return CSS_PROPERTY_NOT_SET; - -} - -static css_error -node_presentational_hint_height(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_string *name; - dom_string *height = NULL; - dom_exception err; - bool textarea = false; - - err = dom_node_get_node_name(node, &name); - if (err != DOM_NO_ERR) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_iframe) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_tr) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_img) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_object) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) { - err = dom_element_get_attribute(node, - corestring_dom_height, &height); - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_textarea)) { - textarea = true; - err = dom_element_get_attribute(node, - corestring_dom_rows, &height); - } - - dom_string_unref(name); - - if ((err != DOM_NO_ERR) || (height == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (parse_dimension((const char *)dom_string_data(height), - false, - &hint->data.length.value, - &hint->data.length.unit)) { - hint->status = CSS_HEIGHT_SET; - - if (textarea) { - hint->data.length.unit = CSS_UNIT_EM; - } - - dom_string_unref(height); - return CSS_OK; - } - - dom_string_unref(height); - return CSS_PROPERTY_NOT_SET; -} - -static css_error -node_presentational_hint_font_size(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_exception err; - dom_string *node_name = NULL; - dom_string *size; - - err = dom_node_get_node_name(node, &node_name); - if ((err != DOM_NO_ERR) || (node_name == NULL)) { - return CSS_NOMEM; - } - - if (!dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_font)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(node_name); - - err = dom_element_get_attribute(node, corestring_dom_size, &size); - if ((err != DOM_NO_ERR) || (size == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (parse_font_size((const char *)dom_string_data(size), - &hint->status, - &hint->data.length.value, - &hint->data.length.unit)) { - dom_string_unref(size); - return CSS_OK; - } - - dom_string_unref(size); - return CSS_PROPERTY_NOT_SET; -} - -static css_error -node_presentational_hint_float(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_exception err; - dom_string *node_name = NULL; - dom_string *align; - - err = dom_node_get_node_name(node, &node_name); - if ((err != DOM_NO_ERR) || (node_name == NULL)) { - return CSS_NOMEM; - } - - /** \todo input[type=image][align=*] - $11.3.3 */ - if (!dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_table) && - !dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_applet) && - !dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_embed) && - !dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_iframe) && - !dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_img) && - !dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_object)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(node_name); - - err = dom_element_get_attribute(node, corestring_dom_align, &align); - if ((err != DOM_NO_ERR) || (align == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_left)) { - hint->status = CSS_FLOAT_LEFT; - dom_string_unref(align); - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_right)) { - hint->status = CSS_FLOAT_RIGHT; - dom_string_unref(align); - return CSS_OK; - } - - dom_string_unref(align); - - return CSS_PROPERTY_NOT_SET; -} - -static css_error -node_presentational_hint_color(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - css_error error; - dom_exception err; - dom_string *node_name = NULL; - dom_string *color; - - err = dom_node_get_node_name(node, &node_name); - if ((err != DOM_NO_ERR) || (node_name == NULL)) { - return CSS_NOMEM; - } - - if (dom_string_caseless_lwc_isequal(node_name, corestring_lwc_a)) { - /* find body node */ - css_qname qs; - dom_node *bodynode = NULL; - bool is_visited; - - qs.ns = NULL; - qs.name = lwc_string_ref(corestring_lwc_body); - if (named_ancestor_node(ctx, node, &qs, - (void *)&bodynode) != CSS_OK) { - /* Didn't find, or had error */ - lwc_string_unref(qs.name); - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - - lwc_string_unref(qs.name); - - /* deal with missing body ancestor */ - if (bodynode == NULL) { - dom_string_unref(node_name); - return CSS_BADPARM; - } - - error = node_is_visited(ctx, node, &is_visited); - if (error != CSS_OK) - return error; - - if (is_visited) { - err = dom_element_get_attribute(bodynode, - corestring_dom_vlink, &color); - if ((err != DOM_NO_ERR) || (color == NULL)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - } else { - err = dom_element_get_attribute(bodynode, - corestring_dom_link, &color); - if ((err != DOM_NO_ERR) || (color == NULL)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - } - } else if (dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_body)) { - err = dom_element_get_attribute(node, - corestring_dom_text, &color); - if ((err != DOM_NO_ERR) || (color == NULL)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - } else { - err = dom_element_get_attribute(node, - corestring_dom_color, &color); - if ((err != DOM_NO_ERR) || (color == NULL)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - } - - if (!nscss_parse_colour((const char *)dom_string_data(color), - &hint->data.color)) { - dom_string_unref(color); - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - - hint->status = CSS_COLOR_COLOR; - - dom_string_unref(color); - dom_string_unref(node_name); - - return CSS_OK; -} - -static css_error -node_presentational_hint_caption_side(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_exception err; - dom_string *node_name = NULL; - dom_string *align = NULL; - - err = dom_node_get_node_name(node, &node_name); - if ((err != DOM_NO_ERR) || (node_name == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (!dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_caption)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(node_name); - - err = dom_element_get_attribute(node, corestring_dom_align, &align); - if ((err != DOM_NO_ERR) || (align == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (dom_string_caseless_lwc_isequal(align, corestring_lwc_bottom)) { - hint->status = CSS_CAPTION_SIDE_BOTTOM; - dom_string_unref(align); - return CSS_OK; - } - - dom_string_unref(align); - - return CSS_PROPERTY_NOT_SET; -} - -static css_error -node_presentational_hint_background_color(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_exception err; - dom_string *bgcolor; - - err = dom_element_get_attribute(node, - corestring_dom_bgcolor, &bgcolor); - if ((err != DOM_NO_ERR) || (bgcolor == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (nscss_parse_colour((const char *)dom_string_data(bgcolor), - &hint->data.color)) { - hint->status = CSS_BACKGROUND_COLOR_COLOR; - dom_string_unref(bgcolor); - return CSS_OK; - } - - dom_string_unref(bgcolor); - - return CSS_PROPERTY_NOT_SET; -} - -static css_error -node_presentational_hint_background_image(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_exception err; - dom_string *atr_val; - nserror error; - nsurl *url; - lwc_string *iurl; - lwc_error lerror; - - err = dom_element_get_attribute(node, - corestring_dom_background, &atr_val); - if ((err != DOM_NO_ERR) || (atr_val == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - error = nsurl_join(ctx->base_url, - (const char *)dom_string_data(atr_val), &url); - - dom_string_unref(atr_val); - - if (error != NSERROR_OK) { - return CSS_NOMEM; - } - - lerror = lwc_intern_string(nsurl_access(url), - nsurl_length(url), &iurl); - - nsurl_unref(url); - - if (lerror == lwc_error_oom) { - return CSS_NOMEM; - } - - if (lerror == lwc_error_ok) { - hint->data.string = iurl; - hint->status = CSS_BACKGROUND_IMAGE_IMAGE; - return CSS_OK; - } - - return CSS_PROPERTY_NOT_SET; -} - -/** - * Callback to retrieve presentational hints for a node - * - * \param pw HTML document - * \param node DOM node - * \param property CSS property to retrieve - * \param hint Pointer to hint object to populate - * \return CSS_OK on success, - * CSS_PROPERTY_NOT_SET if there is no hint for the requested property, - * CSS_NOMEM on memory exhaustion. - */ -css_error node_presentational_hint(void *pw, void *node, - uint32_t property, css_hint *hint) -{ - - switch (property) { - case CSS_PROP_BACKGROUND_IMAGE: - return node_presentational_hint_background_image(pw, node, hint); - - case CSS_PROP_BACKGROUND_COLOR: - return node_presentational_hint_background_color(pw, node, hint); - case CSS_PROP_CAPTION_SIDE: - return node_presentational_hint_caption_side(pw, node, hint); - - case CSS_PROP_COLOR: - return node_presentational_hint_color(pw, node, hint); - - case CSS_PROP_FLOAT: - return node_presentational_hint_float(pw, node, hint); - - case CSS_PROP_FONT_SIZE: - return node_presentational_hint_font_size(pw, node, hint); - - case CSS_PROP_HEIGHT: - return node_presentational_hint_height(pw, node, hint); - - case CSS_PROP_WIDTH: - return node_presentational_hint_width(pw, node, hint); - - case CSS_PROP_BORDER_SPACING: - return node_presentational_hint_border_spacing(pw, node, hint); - - case CSS_PROP_BORDER_TOP_COLOR : - case CSS_PROP_BORDER_RIGHT_COLOR : - case CSS_PROP_BORDER_BOTTOM_COLOR : - case CSS_PROP_BORDER_LEFT_COLOR : - return node_presentational_hint_border_trbl_color(pw, node, hint); - - case CSS_PROP_BORDER_TOP_STYLE : - case CSS_PROP_BORDER_RIGHT_STYLE : - case CSS_PROP_BORDER_BOTTOM_STYLE : - case CSS_PROP_BORDER_LEFT_STYLE : - return node_presentational_hint_border_trbl_style(pw, node, hint); - - case CSS_PROP_BORDER_TOP_WIDTH : - case CSS_PROP_BORDER_RIGHT_WIDTH : - case CSS_PROP_BORDER_BOTTOM_WIDTH : - case CSS_PROP_BORDER_LEFT_WIDTH : - return node_presentational_hint_border_trbl_width(pw, node, hint); - - case CSS_PROP_MARGIN_TOP : - case CSS_PROP_MARGIN_BOTTOM : - return node_presentational_hint_margin_tb(pw, node, hint); - - case CSS_PROP_MARGIN_RIGHT: - case CSS_PROP_MARGIN_LEFT: - return node_presentational_hint_margin_rl(pw, node, hint, property); - - case CSS_PROP_PADDING_TOP: - case CSS_PROP_PADDING_RIGHT : - case CSS_PROP_PADDING_BOTTOM : - case CSS_PROP_PADDING_LEFT: - return node_presentational_hint_padding_trbl(pw, node, hint); - - case CSS_PROP_TEXT_ALIGN: - return node_presentational_hint_text_align(pw, node, hint); - - case CSS_PROP_VERTICAL_ALIGN: - return node_presentational_hint_vertical_align(pw, node, hint); - } - - return CSS_PROPERTY_NOT_SET; -} - -/** - * Callback to retrieve the User-Agent defaults for a CSS property. - * - * \param pw HTML document - * \param property Property to retrieve defaults for - * \param hint Pointer to hint object to populate - * \return CSS_OK on success, - * CSS_INVALID if the property should not have a user-agent default. - */ -css_error ua_default_for_property(void *pw, uint32_t property, css_hint *hint) -{ - if (property == CSS_PROP_COLOR) { - hint->data.color = 0xff000000; - hint->status = CSS_COLOR_COLOR; - } else if (property == CSS_PROP_FONT_FAMILY) { - hint->data.strings = NULL; - switch (nsoption_int(font_default)) { - case PLOT_FONT_FAMILY_SANS_SERIF: - hint->status = CSS_FONT_FAMILY_SANS_SERIF; - break; - case PLOT_FONT_FAMILY_SERIF: - hint->status = CSS_FONT_FAMILY_SERIF; - break; - case PLOT_FONT_FAMILY_MONOSPACE: - hint->status = CSS_FONT_FAMILY_MONOSPACE; - break; - case PLOT_FONT_FAMILY_CURSIVE: - hint->status = CSS_FONT_FAMILY_CURSIVE; - break; - case PLOT_FONT_FAMILY_FANTASY: - hint->status = CSS_FONT_FAMILY_FANTASY; - break; - } - } else if (property == CSS_PROP_QUOTES) { - /** \todo Not exactly useful :) */ - hint->data.strings = NULL; - hint->status = CSS_QUOTES_NONE; - } else if (property == CSS_PROP_VOICE_FAMILY) { - /** \todo Fix this when we have voice-family done */ - hint->data.strings = NULL; - hint->status = 0; - } else { - return CSS_INVALID; - } - - return CSS_OK; -} - -css_error set_libcss_node_data(void *pw, void *node, void *libcss_node_data) -{ - dom_node *n = node; - dom_exception err; - void *old_node_data; - - /* Set this node's node data */ - err = dom_node_set_user_data(n, - corestring_dom___ns_key_libcss_node_data, - libcss_node_data, nscss_dom_user_data_handler, - (void *) &old_node_data); - if (err != DOM_NO_ERR) { - return CSS_NOMEM; - } - - assert(old_node_data == NULL); - - return CSS_OK; -} - -css_error get_libcss_node_data(void *pw, void *node, void **libcss_node_data) -{ - dom_node *n = node; - dom_exception err; - - /* Get this node's node data */ - err = dom_node_get_user_data(n, - corestring_dom___ns_key_libcss_node_data, - libcss_node_data); - if (err != DOM_NO_ERR) { - return CSS_NOMEM; - } - - return CSS_OK; -} - -/** - * Mapping of colour name to CSS color - */ -struct colour_map { - const char *name; - css_color color; -}; - -/** - * Name comparator for named colour matching - * - * \param a Name to match - * \param b Colour map entry to consider - * \return 0 on match, - * < 0 if a < b, - * > 0 if b > a. - */ -int cmp_colour_name(const void *a, const void *b) -{ - const char *aa = a; - const struct colour_map *bb = b; - - return strcasecmp(aa, bb->name); -} - -/** - * Parse a named colour - * - * \param name Name to parse - * \param result Pointer to location to receive css_color - * \return true on success, false on invalid input - */ -bool parse_named_colour(const char *name, css_color *result) -{ - static const struct colour_map named_colours[] = { - { "aliceblue", 0xfff0f8ff }, - { "antiquewhite", 0xfffaebd7 }, - { "aqua", 0xff00ffff }, - { "aquamarine", 0xff7fffd4 }, - { "azure", 0xfff0ffff }, - { "beige", 0xfff5f5dc }, - { "bisque", 0xffffe4c4 }, - { "black", 0xff000000 }, - { "blanchedalmond", 0xffffebcd }, - { "blue", 0xff0000ff }, - { "blueviolet", 0xff8a2be2 }, - { "brown", 0xffa52a2a }, - { "burlywood", 0xffdeb887 }, - { "cadetblue", 0xff5f9ea0 }, - { "chartreuse", 0xff7fff00 }, - { "chocolate", 0xffd2691e }, - { "coral", 0xffff7f50 }, - { "cornflowerblue", 0xff6495ed }, - { "cornsilk", 0xfffff8dc }, - { "crimson", 0xffdc143c }, - { "cyan", 0xff00ffff }, - { "darkblue", 0xff00008b }, - { "darkcyan", 0xff008b8b }, - { "darkgoldenrod", 0xffb8860b }, - { "darkgray", 0xffa9a9a9 }, - { "darkgreen", 0xff006400 }, - { "darkgrey", 0xffa9a9a9 }, - { "darkkhaki", 0xffbdb76b }, - { "darkmagenta", 0xff8b008b }, - { "darkolivegreen", 0xff556b2f }, - { "darkorange", 0xffff8c00 }, - { "darkorchid", 0xff9932cc }, - { "darkred", 0xff8b0000 }, - { "darksalmon", 0xffe9967a }, - { "darkseagreen", 0xff8fbc8f }, - { "darkslateblue", 0xff483d8b }, - { "darkslategray", 0xff2f4f4f }, - { "darkslategrey", 0xff2f4f4f }, - { "darkturquoise", 0xff00ced1 }, - { "darkviolet", 0xff9400d3 }, - { "deeppink", 0xffff1493 }, - { "deepskyblue", 0xff00bfff }, - { "dimgray", 0xff696969 }, - { "dimgrey", 0xff696969 }, - { "dodgerblue", 0xff1e90ff }, - { "feldspar", 0xffd19275 }, - { "firebrick", 0xffb22222 }, - { "floralwhite", 0xfffffaf0 }, - { "forestgreen", 0xff228b22 }, - { "fuchsia", 0xffff00ff }, - { "gainsboro", 0xffdcdcdc }, - { "ghostwhite", 0xfff8f8ff }, - { "gold", 0xffffd700 }, - { "goldenrod", 0xffdaa520 }, - { "gray", 0xff808080 }, - { "green", 0xff008000 }, - { "greenyellow", 0xffadff2f }, - { "grey", 0xff808080 }, - { "honeydew", 0xfff0fff0 }, - { "hotpink", 0xffff69b4 }, - { "indianred", 0xffcd5c5c }, - { "indigo", 0xff4b0082 }, - { "ivory", 0xfffffff0 }, - { "khaki", 0xfff0e68c }, - { "lavender", 0xffe6e6fa }, - { "lavenderblush", 0xfffff0f5 }, - { "lawngreen", 0xff7cfc00 }, - { "lemonchiffon", 0xfffffacd }, - { "lightblue", 0xffadd8e6 }, - { "lightcoral", 0xfff08080 }, - { "lightcyan", 0xffe0ffff }, - { "lightgoldenrodyellow", 0xfffafad2 }, - { "lightgray", 0xffd3d3d3 }, - { "lightgreen", 0xff90ee90 }, - { "lightgrey", 0xffd3d3d3 }, - { "lightpink", 0xffffb6c1 }, - { "lightsalmon", 0xffffa07a }, - { "lightseagreen", 0xff20b2aa }, - { "lightskyblue", 0xff87cefa }, - { "lightslateblue", 0xff8470ff }, - { "lightslategray", 0xff778899 }, - { "lightslategrey", 0xff778899 }, - { "lightsteelblue", 0xffb0c4de }, - { "lightyellow", 0xffffffe0 }, - { "lime", 0xff00ff00 }, - { "limegreen", 0xff32cd32 }, - { "linen", 0xfffaf0e6 }, - { "magenta", 0xffff00ff }, - { "maroon", 0xff800000 }, - { "mediumaquamarine", 0xff66cdaa }, - { "mediumblue", 0xff0000cd }, - { "mediumorchid", 0xffba55d3 }, - { "mediumpurple", 0xff9370db }, - { "mediumseagreen", 0xff3cb371 }, - { "mediumslateblue", 0xff7b68ee }, - { "mediumspringgreen", 0xff00fa9a }, - { "mediumturquoise", 0xff48d1cc }, - { "mediumvioletred", 0xffc71585 }, - { "midnightblue", 0xff191970 }, - { "mintcream", 0xfff5fffa }, - { "mistyrose", 0xffffe4e1 }, - { "moccasin", 0xffffe4b5 }, - { "navajowhite", 0xffffdead }, - { "navy", 0xff000080 }, - { "oldlace", 0xfffdf5e6 }, - { "olive", 0xff808000 }, - { "olivedrab", 0xff6b8e23 }, - { "orange", 0xffffa500 }, - { "orangered", 0xffff4500 }, - { "orchid", 0xffda70d6 }, - { "palegoldenrod", 0xffeee8aa }, - { "palegreen", 0xff98fb98 }, - { "paleturquoise", 0xffafeeee }, - { "palevioletred", 0xffdb7093 }, - { "papayawhip", 0xffffefd5 }, - { "peachpuff", 0xffffdab9 }, - { "peru", 0xffcd853f }, - { "pink", 0xffffc0cb }, - { "plum", 0xffdda0dd }, - { "powderblue", 0xffb0e0e6 }, - { "purple", 0xff800080 }, - { "red", 0xffff0000 }, - { "rosybrown", 0xffbc8f8f }, - { "royalblue", 0xff4169e1 }, - { "saddlebrown", 0xff8b4513 }, - { "salmon", 0xfffa8072 }, - { "sandybrown", 0xfff4a460 }, - { "seagreen", 0xff2e8b57 }, - { "seashell", 0xfffff5ee }, - { "sienna", 0xffa0522d }, - { "silver", 0xffc0c0c0 }, - { "skyblue", 0xff87ceeb }, - { "slateblue", 0xff6a5acd }, - { "slategray", 0xff708090 }, - { "slategrey", 0xff708090 }, - { "snow", 0xfffffafa }, - { "springgreen", 0xff00ff7f }, - { "steelblue", 0xff4682b4 }, - { "tan", 0xffd2b48c }, - { "teal", 0xff008080 }, - { "thistle", 0xffd8bfd8 }, - { "tomato", 0xffff6347 }, - { "turquoise", 0xff40e0d0 }, - { "violet", 0xffee82ee }, - { "violetred", 0xffd02090 }, - { "wheat", 0xfff5deb3 }, - { "white", 0xffffffff }, - { "whitesmoke", 0xfff5f5f5 }, - { "yellow", 0xffffff00 }, - { "yellowgreen", 0xff9acd32 } - }; - const struct colour_map *entry; - - entry = bsearch(name, named_colours, - sizeof(named_colours) / sizeof(named_colours[0]), - sizeof(named_colours[0]), - cmp_colour_name); - - if (entry != NULL) - *result = entry->color; - - return entry != NULL; -} - -/** - * Parse a dimension string - * - * \param data Data to parse (NUL-terminated) - * \param strict Whether to enforce strict parsing rules - * \param length Pointer to location to receive dimension's length - * \param unit Pointer to location to receive dimension's unit - * \return true on success, false on invalid input - */ -bool parse_dimension(const char *data, bool strict, css_fixed *length, - css_unit *unit) -{ - size_t len; - size_t read; - css_fixed value; - - len = strlen(data); - - if (parse_number(data, false, true, &value, &read) == false) - return false; - - if (strict && value < INTTOFIX(1)) - return false; - - *length = value; - - if (len > read && data[read] == '%') - *unit = CSS_UNIT_PCT; - else - *unit = CSS_UNIT_PX; - - return true; -} - -/** - * Parse a number string - * - * \param data Data to parse (NUL-terminated) - * \param maybe_negative Negative numbers permitted - * \param real Floating point numbers permitted - * \param value Pointer to location to receive numeric value - * \param consumed Pointer to location to receive number of input - * bytes consumed - * \return true on success, false on invalid input - */ -bool parse_number(const char *data, bool maybe_negative, bool real, - css_fixed *value, size_t *consumed) -{ - size_t len; - const uint8_t *ptr; - int32_t intpart = 0; - int32_t fracpart = 0; - int32_t pwr = 1; - int sign = 1; - - *consumed = 0; - - len = strlen(data); - ptr = (const uint8_t *) data; - - if (len == 0) - return false; - - /* Skip leading whitespace */ - while (len > 0 && isWhitespace(ptr[0])) { - len--; - ptr++; - } - - if (len == 0) - return false; - - /* Extract sign, if any */ - if (ptr[0] == '+') { - len--; - ptr++; - } else if (ptr[0] == '-' && maybe_negative) { - sign = -1; - len--; - ptr++; - } - - if (len == 0) - return false; - - /* Must have a digit [0,9] */ - if ('0' > ptr[0] || ptr[0] > '9') - return false; - - /* Now extract intpart, assuming base 10 */ - while (len > 0) { - /* Stop on first non-digit */ - if (ptr[0] < '0' || '9' < ptr[0]) - break; - - /* Prevent overflow of 'intpart'; proper clamping below */ - if (intpart < (1 << 22)) { - intpart *= 10; - intpart += ptr[0] - '0'; - } - ptr++; - len--; - } - - /* And fracpart, again, assuming base 10 */ - if (real && len > 1 && ptr[0] == '.' && - ('0' <= ptr[1] && ptr[1] <= '9')) { - ptr++; - len--; - - while (len > 0) { - if (ptr[0] < '0' || '9' < ptr[0]) - break; - - if (pwr < 1000000) { - pwr *= 10; - fracpart *= 10; - fracpart += ptr[0] - '0'; - } - ptr++; - len--; - } - - fracpart = ((1 << 10) * fracpart + pwr/2) / pwr; - if (fracpart >= (1 << 10)) { - intpart++; - fracpart &= (1 << 10) - 1; - } - } - - if (sign > 0) { - /* If the result is larger than we can represent, - * then clamp to the maximum value we can store. */ - if (intpart >= (1 << 21)) { - intpart = (1 << 21) - 1; - fracpart = (1 << 10) - 1; - } - } else { - /* If the negated result is smaller than we can represent - * then clamp to the minimum value we can store. */ - if (intpart >= (1 << 21)) { - intpart = -(1 << 21); - fracpart = 0; - } else { - intpart = -intpart; - if (fracpart) { - fracpart = (1 << 10) - fracpart; - intpart--; - } - } - } - - *value = (intpart << 10) | fracpart; - - *consumed = ptr - (const uint8_t *) data; - - return true; -} - -/** - * Parse a font \@size attribute - * - * \param size Data to parse (NUL-terminated) - * \param val Pointer to location to receive enum value - * \param len Pointer to location to receive length - * \param unit Pointer to location to receive unit - * \return True on success, false on failure - */ -bool parse_font_size(const char *size, uint8_t *val, - css_fixed *len, css_unit *unit) -{ - static const uint8_t size_map[] = { - CSS_FONT_SIZE_XX_SMALL, - CSS_FONT_SIZE_SMALL, - CSS_FONT_SIZE_MEDIUM, - CSS_FONT_SIZE_LARGE, - CSS_FONT_SIZE_X_LARGE, - CSS_FONT_SIZE_XX_LARGE, - CSS_FONT_SIZE_DIMENSION /* xxx-large (see below) */ - }; - - const char *p = size; - char mode; - int value = 0; - - /* Skip whitespace */ - while (*p != '\0' && isWhitespace(*p)) - p++; - - mode = *p; - - /* Skip +/- */ - if (mode == '+' || mode == '-') - p++; - - /* Need at least one digit */ - if (*p < '0' || *p > '9') { - return false; - } - - /* Consume digits, computing value */ - while ('0' <= *p && *p <= '9') { - value = value * 10 + (*p - '0'); - p++; - } - - /* Resolve relative sizes */ - if (mode == '+') - value += 3; - else if (mode == '-') - value = 3 - value; - - /* Clamp to range [1,7] */ - if (value < 1) - value = 1; - else if (value > 7) - value = 7; - - if (value == 7) { - /* Manufacture xxx-large */ - *len = FDIV(FMUL(INTTOFIX(3), INTTOFIX(nsoption_int(font_size))), - F_10); - } else { - /* Len is irrelevant */ - *len = 0; - } - - *unit = CSS_UNIT_PT; - *val = size_map[value - 1]; - - return true; -} - -/****************************************************************************** - * Utility functions * - ******************************************************************************/ - -/** - * Determine if a given character is whitespace - * - * \param c Character to consider - * \return true if character is whitespace, false otherwise - */ -bool isWhitespace(char c) -{ - return c == ' ' || c == '\t' || c == '\f' || c == '\r' || c == '\n'; -} - -/** - * Determine if a given character is a valid hex digit - * - * \param c Character to consider - * \return true if character is a valid hex digit, false otherwise - */ -bool isHex(char c) -{ - return ('0' <= c && c <= '9') || - ('A' <= (c & ~0x20) && (c & ~0x20) <= 'F'); -} - -/** - * Convert a character representing a hex digit to the corresponding hex value - * - * \param c Character to convert - * \return Hex value represented by character - * - * \note This function assumes an ASCII-compatible character set - */ -uint8_t charToHex(char c) -{ - /* 0-9 */ - c -= '0'; - - /* A-F */ - if (c > 9) - c -= 'A' - '9' - 1; - - /* a-f */ - if (c > 15) - c -= 'a' - 'A'; - - return c; -} - diff --git a/css/select.h b/css/select.h index 13b9e1201..0e0be9578 100644 --- a/css/select.h +++ b/css/select.h @@ -49,9 +49,9 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n, css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx, const css_computed_style *parent); -css_error nscss_compute_font_size(void *pw, const css_hint *parent, - css_hint *size); -bool nscss_parse_colour(const char *data, css_color *result); +css_error named_ancestor_node(void *pw, void *node, + const css_qname *qname, void **ancestor); +css_error node_is_visited(void *pw, void *node, bool *match); #endif diff --git a/render/box_construct.c b/render/box_construct.c index 25686c908..b3fc8f156 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -36,8 +36,9 @@ #include "utils/config.h" #include "content/content_protected.h" #include "css/css.h" -#include "css/utils.h" +#include "css/hints.h" #include "css/select.h" +#include "css/utils.h" #include "utils/nsoption.h" #include "utils/corestrings.h" #include "utils/locale.h" -- cgit v1.2.3 From e6c818822937c89bfa828c10859aaf010f0e2066 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Tue, 19 May 2015 08:56:48 +0100 Subject: Tidy cellpadding hint handling. --- css/hints.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/css/hints.c b/css/hints.c index 059b42bfa..c8f5ebb79 100644 --- a/css/hints.c +++ b/css/hints.c @@ -832,7 +832,6 @@ static css_error node_presentational_hint_padding_trbl( { dom_string *name; dom_exception exc; - dom_string *cellpadding = NULL; css_error result = CSS_PROPERTY_NOT_SET; exc = dom_node_get_node_name(node, &name); @@ -843,6 +842,8 @@ static css_error node_presentational_hint_padding_trbl( dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { css_qname qs; dom_node *tablenode = NULL; + dom_string *cellpadding = NULL; + qs.ns = NULL; qs.name = lwc_string_ref(corestring_lwc_table); if (named_ancestor_node(ctx, node, &qs, @@ -866,20 +867,20 @@ static css_error node_presentational_hint_padding_trbl( /* No need to unref tablenode, named_ancestor_node does not * return a reffed node to the CSS */ - } - - dom_string_unref(name); - if (cellpadding != NULL) { - if (parse_dimension(dom_string_data(cellpadding), false, - &hint->data.length.value, - &hint->data.length.unit)) { - hint->status = CSS_PADDING_SET; - result = CSS_OK; + if (cellpadding != NULL) { + if (parse_dimension(dom_string_data(cellpadding), false, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->status = CSS_PADDING_SET; + result = CSS_OK; + } + dom_string_unref(cellpadding); } - dom_string_unref(cellpadding); } + dom_string_unref(name); + return result; } -- cgit v1.2.3 From ae485432c544e555be74790c1a9f1ee50835eaad Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Tue, 19 May 2015 08:57:16 +0100 Subject: Remove duplicate branch. --- css/hints.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/css/hints.c b/css/hints.c index c8f5ebb79..066212e89 100644 --- a/css/hints.c +++ b/css/hints.c @@ -1578,14 +1578,6 @@ static css_error node_presentational_hint_color( return CSS_PROPERTY_NOT_SET; } } - } else if (dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_body)) { - err = dom_element_get_attribute(node, - corestring_dom_text, &color); - if ((err != DOM_NO_ERR) || (color == NULL)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } } else { err = dom_element_get_attribute(node, corestring_dom_color, &color); -- cgit v1.2.3 From e42afd9b3215e4711c68bc040bb5ceb1b8f17a44 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Wed, 8 Jul 2015 21:55:12 +0100 Subject: Change hints handling to use new libcss API. Collect hints and provide them up front. Note this implementation is minimal effort, and quite inefficient. We can be faster about it by walking the element's attributes, and caching things set on ancestor elements which apply to the current element. (Mostly table, and body stuff.) --- css/hints.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++------------- css/hints.h | 7 +- 2 files changed, 191 insertions(+), 55 deletions(-) diff --git a/css/hints.c b/css/hints.c index 066212e89..a3242c689 100644 --- a/css/hints.c +++ b/css/hints.c @@ -28,6 +28,9 @@ #include "css/hints.h" #include "css/select.h" +#define LOG_STATS +#undef LOG_STATS + /****************************************************************************** * Utility functions * ******************************************************************************/ @@ -1711,77 +1714,209 @@ static css_error node_presentational_hint_background_image( return CSS_PROPERTY_NOT_SET; } +struct css_hint_ctx { + struct css_hint *hints; + uint32_t alloc; + uint32_t len; +}; + +struct css_hint_ctx hint_ctx; + +static void css_hint_destroy(struct css_hint_ctx *hint) +{ + hint->alloc = 0; + hint->len = 0; + free(hint->hints); +} + +static nserror css_hint_extend(struct css_hint_ctx *hint) +{ + uint32_t alloc = (hint->alloc == 0) ? 32 : hint->alloc * 2; + struct css_hint *temp; + + temp = realloc(hint->hints, sizeof(struct css_hint) * alloc); + if (temp != NULL) { + hint->hints = temp; + hint->alloc = alloc; + + return NSERROR_OK; + } + + return NSERROR_NOMEM; +} + +nserror css_hint_init(void) +{ + nserror err; + + err = css_hint_extend(&hint_ctx); + if (err != NSERROR_OK) { + return err; + } + + return NSERROR_OK; +} + +void css_hint_fini(void) +{ + css_hint_destroy(&hint_ctx); +} + + /* Exported function, documeted in css/hints.h */ -css_error node_presentational_hint(void *pw, void *node, - uint32_t property, css_hint *hint) +static inline css_error node_presentational_hint_internal( + void *pw, void *node, struct css_hint_ctx *hints) { + struct css_hint_ctx *ctx = hints; + uint32_t property; + nserror nserr; + css_error err; - switch (property) { - case CSS_PROP_BACKGROUND_IMAGE: - return node_presentational_hint_background_image(pw, node, hint); + ctx->len = 0; - case CSS_PROP_BACKGROUND_COLOR: - return node_presentational_hint_background_color(pw, node, hint); - case CSS_PROP_CAPTION_SIDE: - return node_presentational_hint_caption_side(pw, node, hint); + for (property = 0; property < CSS_N_PROPERTIES; property++) { + css_hint *hint = &(ctx->hints[ctx->len]); - case CSS_PROP_COLOR: - return node_presentational_hint_color(pw, node, hint); + if (ctx->alloc == 0 || ctx->len == ctx->alloc - 1) { + nserr = css_hint_extend(ctx); + if (nserr != NSERROR_OK) { + return NSERROR_NOMEM; + } + } - case CSS_PROP_FLOAT: - return node_presentational_hint_float(pw, node, hint); + switch (property) { + case CSS_PROP_BACKGROUND_IMAGE: + err = node_presentational_hint_background_image( + pw, node, hint); + break; - case CSS_PROP_FONT_SIZE: - return node_presentational_hint_font_size(pw, node, hint); + case CSS_PROP_BACKGROUND_COLOR: + err = node_presentational_hint_background_color( + pw, node, hint); + break; - case CSS_PROP_HEIGHT: - return node_presentational_hint_height(pw, node, hint); + case CSS_PROP_CAPTION_SIDE: + err = node_presentational_hint_caption_side( + pw, node, hint); + break; - case CSS_PROP_WIDTH: - return node_presentational_hint_width(pw, node, hint); + case CSS_PROP_COLOR: + err = node_presentational_hint_color( + pw, node, hint); + break; - case CSS_PROP_BORDER_SPACING: - return node_presentational_hint_border_spacing(pw, node, hint); + case CSS_PROP_FLOAT: + err = node_presentational_hint_float( + pw, node, hint); + break; - case CSS_PROP_BORDER_TOP_COLOR : - case CSS_PROP_BORDER_RIGHT_COLOR : - case CSS_PROP_BORDER_BOTTOM_COLOR : - case CSS_PROP_BORDER_LEFT_COLOR : - return node_presentational_hint_border_trbl_color(pw, node, hint); + case CSS_PROP_FONT_SIZE: + err = node_presentational_hint_font_size( + pw, node, hint); + break; - case CSS_PROP_BORDER_TOP_STYLE : - case CSS_PROP_BORDER_RIGHT_STYLE : - case CSS_PROP_BORDER_BOTTOM_STYLE : - case CSS_PROP_BORDER_LEFT_STYLE : - return node_presentational_hint_border_trbl_style(pw, node, hint); + case CSS_PROP_HEIGHT: + err = node_presentational_hint_height( + pw, node, hint); + break; - case CSS_PROP_BORDER_TOP_WIDTH : - case CSS_PROP_BORDER_RIGHT_WIDTH : - case CSS_PROP_BORDER_BOTTOM_WIDTH : - case CSS_PROP_BORDER_LEFT_WIDTH : - return node_presentational_hint_border_trbl_width(pw, node, hint); + case CSS_PROP_WIDTH: + err = node_presentational_hint_width( + pw, node, hint); + break; - case CSS_PROP_MARGIN_TOP : - case CSS_PROP_MARGIN_BOTTOM : - return node_presentational_hint_margin_tb(pw, node, hint); + case CSS_PROP_BORDER_SPACING: + err = node_presentational_hint_border_spacing( + pw, node, hint); + break; - case CSS_PROP_MARGIN_RIGHT: - case CSS_PROP_MARGIN_LEFT: - return node_presentational_hint_margin_rl(pw, node, hint, property); + case CSS_PROP_BORDER_TOP_COLOR: + case CSS_PROP_BORDER_RIGHT_COLOR: + case CSS_PROP_BORDER_BOTTOM_COLOR: + case CSS_PROP_BORDER_LEFT_COLOR: + err = node_presentational_hint_border_trbl_color( + pw, node, hint); + break; - case CSS_PROP_PADDING_TOP: - case CSS_PROP_PADDING_RIGHT : - case CSS_PROP_PADDING_BOTTOM : - case CSS_PROP_PADDING_LEFT: - return node_presentational_hint_padding_trbl(pw, node, hint); + case CSS_PROP_BORDER_TOP_STYLE: + case CSS_PROP_BORDER_RIGHT_STYLE: + case CSS_PROP_BORDER_BOTTOM_STYLE: + case CSS_PROP_BORDER_LEFT_STYLE: + err = node_presentational_hint_border_trbl_style( + pw, node, hint); + break; - case CSS_PROP_TEXT_ALIGN: - return node_presentational_hint_text_align(pw, node, hint); + case CSS_PROP_BORDER_TOP_WIDTH: + case CSS_PROP_BORDER_RIGHT_WIDTH: + case CSS_PROP_BORDER_BOTTOM_WIDTH: + case CSS_PROP_BORDER_LEFT_WIDTH: + err = node_presentational_hint_border_trbl_width( + pw, node, hint); + break; + + case CSS_PROP_MARGIN_TOP: + case CSS_PROP_MARGIN_BOTTOM: + err = node_presentational_hint_margin_tb( + pw, node, hint); + break; + + case CSS_PROP_MARGIN_RIGHT: + case CSS_PROP_MARGIN_LEFT: + err = node_presentational_hint_margin_rl( + pw, node, hint, property); + break; - case CSS_PROP_VERTICAL_ALIGN: - return node_presentational_hint_vertical_align(pw, node, hint); + case CSS_PROP_PADDING_TOP: + case CSS_PROP_PADDING_RIGHT: + case CSS_PROP_PADDING_BOTTOM: + case CSS_PROP_PADDING_LEFT: + err = node_presentational_hint_padding_trbl( + pw, node, hint); + break; + + case CSS_PROP_TEXT_ALIGN: + err = node_presentational_hint_text_align( + pw, node, hint); + break; + + case CSS_PROP_VERTICAL_ALIGN: + err = node_presentational_hint_vertical_align( + pw, node, hint); + break; + + default: + err = CSS_PROPERTY_NOT_SET; + break; + } + + if (err == CSS_OK) { + hint->prop = property; + ctx->len++; + } } - return CSS_PROPERTY_NOT_SET; + return CSS_OK; +} + + +/* Exported function, documeted in css/hints.h */ +css_error node_presentational_hint(void *pw, void *node, + uint32_t *nhints, css_hint **hints) +{ + css_error err; + + err = node_presentational_hint_internal(pw, node, &hint_ctx); + if (err != CSS_OK) { + return err; + } + +#ifdef LOG_STATS + LOG("Properties with hints: %i", hint_ctx.len); +#endif + + *nhints = hint_ctx.len; + *hints = hint_ctx.hints; + + return CSS_OK; } diff --git a/css/hints.h b/css/hints.h index 68d4c1063..d2b07b578 100644 --- a/css/hints.h +++ b/css/hints.h @@ -23,7 +23,8 @@ #include "css/css.h" - +nserror css_hint_init(void); +void css_hint_fini(void); /** @@ -40,8 +41,8 @@ css_error node_presentational_hint( void *pw, void *node, - uint32_t property, - css_hint *hint); + uint32_t *nhints, + css_hint **hints); bool nscss_parse_colour(const char *data, css_color *result); -- cgit v1.2.3 From 278451463f53ddc4fed2c9a104089f17a8c9158f Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Tue, 2 Feb 2016 15:42:09 +0000 Subject: Rewrite hints handling to be more efficient. Now we only look for hints that are actually possible for the given element. This new way of doing things is made possible by the new LibCSS API for hints. This also makes use of the LibDOM HTMLElement tag type to avoid lots of massive if-else-if ladders of dom_string_caseless_isequal calls. --- css/css.c | 6 + css/hints.c | 1905 ++++++++++++++++++++++++----------------------------------- 2 files changed, 788 insertions(+), 1123 deletions(-) diff --git a/css/css.c b/css/css.c index acbc14a14..66dc6d4ba 100644 --- a/css/css.c +++ b/css/css.c @@ -31,6 +31,7 @@ #include "utils/messages.h" #include "css/css.h" +#include "css/hints.h" #include "css/internal.h" /* Define to trace import fetches */ @@ -806,6 +807,7 @@ static void nscss_fini(void) css_stylesheet_destroy(blank_import); blank_import = NULL; } + css_hint_fini(); } static const content_handler css_content_handler = { @@ -832,6 +834,10 @@ nserror nscss_init(void) if (error != NSERROR_OK) goto error; + error = css_hint_init(); + if (error != NSERROR_OK) + goto error; + return NSERROR_OK; error: diff --git a/css/hints.c b/css/hints.c index a3242c689..c4d1c2910 100644 --- a/css/hints.c +++ b/css/hints.c @@ -578,1324 +578,907 @@ static bool parse_font_size(const char *size, uint8_t *val, } +/****************************************************************************** + * Hint context management * + ******************************************************************************/ + +#define MAX_HINTS_PER_ELEMENT 32 + +struct css_hint_ctx { + struct css_hint *hints; + uint32_t len; +}; + +struct css_hint_ctx hint_ctx; + +nserror css_hint_init(void) +{ + hint_ctx.hints = malloc(sizeof(struct css_hint) * + MAX_HINTS_PER_ELEMENT); + if (hint_ctx.hints == NULL) { + return NSERROR_NOMEM; + } + + return NSERROR_OK; +} + +void css_hint_fini(void) +{ + hint_ctx.len = 0; + free(hint_ctx.hints); +} + +static void css_hint_clean(void) +{ + hint_ctx.len = 0; +} + +static inline struct css_hint * css_hint_advance(struct css_hint *hint) +{ + hint_ctx.len++; + assert(hint_ctx.len < MAX_HINTS_PER_ELEMENT); + + return ++hint; +} + +static void css_hint_get_hints(struct css_hint **hints, uint32_t *nhints) +{ + *hints = hint_ctx.hints; + *nhints = hint_ctx.len; +} + + /****************************************************************************** * Presentational hint handlers * ******************************************************************************/ -static css_error node_presentational_hint_vertical_align( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_table_cell_border_padding( + nscss_select_ctx *ctx, + dom_node *node) { - dom_string *name; - dom_string *valign = NULL; - dom_exception err; + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + css_qname qs; + dom_string *attr = NULL; + dom_node *tablenode = NULL; + dom_exception exc; + + qs.ns = NULL; + qs.name = lwc_string_ref(corestring_lwc_table); + if (named_ancestor_node(ctx, node, &qs, + (void *)&tablenode) != CSS_OK) { + /* Didn't find, or had error */ + lwc_string_unref(qs.name); + return; + } + lwc_string_unref(qs.name); + + if (tablenode == NULL) { + return; + } + /* No need to unref tablenode, named_ancestor_node does not + * return a reffed node to the CSS + */ + + exc = dom_element_get_attribute(tablenode, + corestring_dom_border, &attr); + + if (exc == DOM_NO_ERR && attr != NULL) { + uint32_t hint_prop; + css_hint_length hint_length; + + if (parse_dimension( + dom_string_data(attr), false, + &hint_length.value, + &hint_length.unit) && + INTTOFIX(0) != hint_length.value) { + + for (hint_prop = CSS_PROP_BORDER_TOP_STYLE; + hint_prop <= CSS_PROP_BORDER_LEFT_STYLE; + hint_prop++) { + hint->prop = hint_prop; + hint->status = CSS_BORDER_STYLE_INSET; + hint = css_hint_advance(hint); + } + + for (hint_prop = CSS_PROP_BORDER_TOP_WIDTH; + hint_prop <= CSS_PROP_BORDER_LEFT_WIDTH; + hint_prop++) { + hint->prop = hint_prop; + hint->data.length.value = INTTOFIX(1); + hint->data.length.unit = CSS_UNIT_PX; + hint->status = CSS_BORDER_WIDTH_WIDTH; + hint = css_hint_advance(hint); + } + } + dom_string_unref(attr); + } + + exc = dom_element_get_attribute(tablenode, + corestring_dom_bordercolor, &attr); + + if (exc == DOM_NO_ERR && attr != NULL) { + uint32_t hint_prop; + css_color hint_color; + + if (nscss_parse_colour( + (const char *)dom_string_data(attr), + &hint_color)) { + + for (hint_prop = CSS_PROP_BORDER_TOP_COLOR; + hint_prop <= CSS_PROP_BORDER_LEFT_COLOR; + hint_prop++) { + hint->prop = hint_prop; + hint->data.color = hint_color; + hint->status = CSS_BORDER_COLOR_COLOR; + hint = css_hint_advance(hint); + } + } + dom_string_unref(attr); + } + + exc = dom_element_get_attribute(tablenode, + corestring_dom_cellpadding, &attr); + + if (exc == DOM_NO_ERR && attr != NULL) { + uint32_t hint_prop; + css_hint_length hint_length; - err = dom_node_get_node_name(node, &name); - if (err != DOM_NO_ERR) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_col) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_thead) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_tbody) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_tfoot) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_tr) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { - err = dom_element_get_attribute(node, - corestring_dom_valign, &valign); - if (err != DOM_NO_ERR || valign == NULL) { - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; + if (parse_dimension( + dom_string_data(attr), false, + &hint_length.value, + &hint_length.unit)) { + + for (hint_prop = CSS_PROP_PADDING_TOP; + hint_prop <= CSS_PROP_PADDING_LEFT; + hint_prop++) { + hint->prop = hint_prop; + hint->data.length.value = hint_length.value; + hint->data.length.unit = hint_length.unit; + hint->status = CSS_PADDING_SET; + hint = css_hint_advance(hint); + } } + dom_string_unref(attr); + } +} + +static void css_hint_vertical_align_table_cells( + nscss_select_ctx *ctx, + dom_node *node) +{ + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + dom_string *attr = NULL; + dom_exception err; + + err = dom_element_get_attribute(node, + corestring_dom_valign, &attr); - if (dom_string_caseless_lwc_isequal(valign, + if (err == DOM_NO_ERR && attr != NULL) { + if (dom_string_caseless_lwc_isequal(attr, corestring_lwc_top)) { + hint->prop = CSS_PROP_VERTICAL_ALIGN; hint->status = CSS_VERTICAL_ALIGN_TOP; - } else if (dom_string_caseless_lwc_isequal(valign, + hint = css_hint_advance(hint); + + } else if (dom_string_caseless_lwc_isequal(attr, corestring_lwc_middle)) { + hint->prop = CSS_PROP_VERTICAL_ALIGN; hint->status = CSS_VERTICAL_ALIGN_MIDDLE; - } else if (dom_string_caseless_lwc_isequal(valign, + hint = css_hint_advance(hint); + + } else if (dom_string_caseless_lwc_isequal(attr, corestring_lwc_bottom)) { + hint->prop = CSS_PROP_VERTICAL_ALIGN; hint->status = CSS_VERTICAL_ALIGN_BOTTOM; - } else if (dom_string_caseless_lwc_isequal(valign, + hint = css_hint_advance(hint); + + } else if (dom_string_caseless_lwc_isequal(attr, corestring_lwc_baseline)) { + hint->prop = CSS_PROP_VERTICAL_ALIGN; hint->status = CSS_VERTICAL_ALIGN_BASELINE; - } else { - dom_string_unref(valign); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; + hint = css_hint_advance(hint); } + dom_string_unref(attr); + } +} - dom_string_unref(valign); - dom_string_unref(name); - - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_applet) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_embed) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_iframe) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_img) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_object)) { - /** \todo input[type=image][align=*] - $11.3.3 */ - err = dom_element_get_attribute(node, - corestring_dom_align, &valign); - if (err != DOM_NO_ERR || valign == NULL) { - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } +static void css_hint_vertical_align_replaced( + nscss_select_ctx *ctx, + dom_node *node) +{ + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + dom_string *attr = NULL; + dom_exception err; + + err = dom_element_get_attribute(node, + corestring_dom_valign, &attr); - if (dom_string_caseless_lwc_isequal(valign, + if (err == DOM_NO_ERR && attr != NULL) { + if (dom_string_caseless_lwc_isequal(attr, corestring_lwc_top)) { + hint->prop = CSS_PROP_VERTICAL_ALIGN; hint->status = CSS_VERTICAL_ALIGN_TOP; - } else if (dom_string_caseless_lwc_isequal(valign, + hint = css_hint_advance(hint); + + } else if (dom_string_caseless_lwc_isequal(attr, corestring_lwc_bottom) || - dom_string_caseless_lwc_isequal(valign, + dom_string_caseless_lwc_isequal(attr, corestring_lwc_baseline)) { + hint->prop = CSS_PROP_VERTICAL_ALIGN; hint->status = CSS_VERTICAL_ALIGN_BASELINE; - } else if (dom_string_caseless_lwc_isequal(valign, + hint = css_hint_advance(hint); + + } else if (dom_string_caseless_lwc_isequal(attr, corestring_lwc_texttop)) { + hint->prop = CSS_PROP_VERTICAL_ALIGN; hint->status = CSS_VERTICAL_ALIGN_TEXT_TOP; - } else if (dom_string_caseless_lwc_isequal(valign, + hint = css_hint_advance(hint); + + } else if (dom_string_caseless_lwc_isequal(attr, corestring_lwc_absmiddle) || - dom_string_caseless_lwc_isequal(valign, + dom_string_caseless_lwc_isequal(attr, corestring_lwc_abscenter)) { + hint->prop = CSS_PROP_VERTICAL_ALIGN; hint->status = CSS_VERTICAL_ALIGN_MIDDLE; - } else { - dom_string_unref(valign); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; + hint = css_hint_advance(hint); } - - dom_string_unref(valign); - dom_string_unref(name); - - return CSS_OK; + dom_string_unref(attr); } - - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; } -static css_error node_presentational_hint_text_align( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_text_align_normal( + nscss_select_ctx *ctx, + dom_node *node) { - dom_string *name; + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; dom_string *align = NULL; dom_exception err; - err = dom_node_get_node_name(node, &name); - if (err != DOM_NO_ERR) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_p) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h1) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h2) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h3) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h4) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h5) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_h6)) { - err = dom_element_get_attribute(node, - corestring_dom_align, &align); - if (err != DOM_NO_ERR || align == NULL) { - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - + err = dom_element_get_attribute(node, + corestring_dom_align, &align); + if (err == DOM_NO_ERR && align != NULL) { if (dom_string_caseless_lwc_isequal(align, corestring_lwc_left)) { + hint->prop = CSS_PROP_TEXT_ALIGN; hint->status = CSS_TEXT_ALIGN_LEFT; + hint = css_hint_advance(hint); + } else if (dom_string_caseless_lwc_isequal(align, corestring_lwc_center)) { + hint->prop = CSS_PROP_TEXT_ALIGN; hint->status = CSS_TEXT_ALIGN_CENTER; + hint = css_hint_advance(hint); + } else if (dom_string_caseless_lwc_isequal(align, corestring_lwc_right)) { + hint->prop = CSS_PROP_TEXT_ALIGN; hint->status = CSS_TEXT_ALIGN_RIGHT; + hint = css_hint_advance(hint); + } else if (dom_string_caseless_lwc_isequal(align, corestring_lwc_justify)) { + hint->prop = CSS_PROP_TEXT_ALIGN; hint->status = CSS_TEXT_ALIGN_JUSTIFY; - } else { - dom_string_unref(align); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; + hint = css_hint_advance(hint); } - dom_string_unref(align); - dom_string_unref(name); + } +} - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_center)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER; - - dom_string_unref(name); - - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_caption)) { - err = dom_element_get_attribute(node, - corestring_dom_align, &align); - if (err != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } +static void css_hint_text_align_center( + nscss_select_ctx *ctx, + dom_node *node) +{ + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; - if (align == NULL || dom_string_caseless_lwc_isequal(align, - corestring_lwc_center)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_left)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_right)) { - hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_justify)) { - hint->status = CSS_TEXT_ALIGN_JUSTIFY; - } else { - dom_string_unref(align); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } + hint->prop = CSS_PROP_TEXT_ALIGN; + hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER; + hint = css_hint_advance(hint); +} + +static void css_hint_margin_left_right_align_center( + nscss_select_ctx *ctx, + dom_node *node) +{ + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + dom_string *attr; + dom_exception exc; + + exc = dom_element_get_attribute(node, + corestring_dom_align, &attr); + + if (exc == DOM_NO_ERR && attr != NULL) { + if (dom_string_caseless_lwc_isequal(attr, + corestring_lwc_center) || + dom_string_caseless_lwc_isequal(attr, + corestring_lwc_abscenter) || + dom_string_caseless_lwc_isequal(attr, + corestring_lwc_middle) || + dom_string_caseless_lwc_isequal(attr, + corestring_lwc_absmiddle)) { + hint->prop = CSS_PROP_MARGIN_LEFT; + hint->status = CSS_MARGIN_AUTO; + hint = css_hint_advance(hint); - if (align != NULL) - dom_string_unref(align); - dom_string_unref(name); - - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_div) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_thead) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_tbody) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_tfoot) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_tr) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, - corestring_lwc_th)) { - err = dom_element_get_attribute(node, - corestring_dom_align, &align); - if (err != DOM_NO_ERR || align == NULL) { - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; + hint->prop = CSS_PROP_MARGIN_RIGHT; + hint->status = CSS_MARGIN_AUTO; + hint = css_hint_advance(hint); } + dom_string_unref(attr); + } +} +static void css_hint_text_align_special( + nscss_select_ctx *ctx, + dom_node *node) +{ + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + dom_string *align = NULL; + dom_exception err; + + err = dom_element_get_attribute(node, + corestring_dom_align, &align); + + if (err == DOM_NO_ERR && align != NULL) { if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_center)) { + corestring_lwc_center)) { + hint->prop = CSS_PROP_TEXT_ALIGN; hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER; + hint = css_hint_advance(hint); + } else if (dom_string_caseless_lwc_isequal(align, corestring_lwc_left)) { + hint->prop = CSS_PROP_TEXT_ALIGN; hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT; + hint = css_hint_advance(hint); + } else if (dom_string_caseless_lwc_isequal(align, corestring_lwc_right)) { + hint->prop = CSS_PROP_TEXT_ALIGN; hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT; + hint = css_hint_advance(hint); + } else if (dom_string_caseless_lwc_isequal(align, corestring_lwc_justify)) { + hint->prop = CSS_PROP_TEXT_ALIGN; hint->status = CSS_TEXT_ALIGN_JUSTIFY; - } else { - dom_string_unref(align); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; + hint = css_hint_advance(hint); } - dom_string_unref(align); - dom_string_unref(name); - - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_table)) { - /* Tables usually reset alignment */ - hint->status = CSS_TEXT_ALIGN_INHERIT_IF_NON_MAGIC; - - dom_string_unref(name); - - return CSS_OK; - } else { - dom_string_unref(name); - - return CSS_PROPERTY_NOT_SET; } +} + +static void css_hint_text_align_table_special( + nscss_select_ctx *ctx, + dom_node *node) +{ + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + hint->prop = CSS_PROP_TEXT_ALIGN; + hint->status = CSS_TEXT_ALIGN_INHERIT_IF_NON_MAGIC; + hint = css_hint_advance(hint); } -static css_error node_presentational_hint_padding_trbl( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_margin_hspace_vspace( + nscss_select_ctx *ctx, + dom_node *node) { - dom_string *name; + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + dom_string *attr = NULL; dom_exception exc; - css_error result = CSS_PROPERTY_NOT_SET; - - exc = dom_node_get_node_name(node, &name); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { - css_qname qs; - dom_node *tablenode = NULL; - dom_string *cellpadding = NULL; - - qs.ns = NULL; - qs.name = lwc_string_ref(corestring_lwc_table); - if (named_ancestor_node(ctx, node, &qs, - (void *)&tablenode) != CSS_OK) { - /* Didn't find, or had error */ - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - lwc_string_unref(qs.name); - - if (tablenode != NULL) { - exc = dom_element_get_attribute(tablenode, - corestring_dom_cellpadding, - &cellpadding); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } - } - /* No need to unref tablenode, named_ancestor_node does not - * return a reffed node to the CSS - */ - - if (cellpadding != NULL) { - if (parse_dimension(dom_string_data(cellpadding), false, - &hint->data.length.value, - &hint->data.length.unit)) { - hint->status = CSS_PADDING_SET; - result = CSS_OK; - } - dom_string_unref(cellpadding); + + exc = dom_element_get_attribute(node, + corestring_dom_vspace, &attr); + + if (exc == DOM_NO_ERR && attr != NULL) { + css_hint_length hint_length; + if (parse_dimension( + dom_string_data(attr), false, + &hint_length.value, + &hint_length.unit)) { + hint->prop = CSS_PROP_MARGIN_TOP; + hint->data.length.value = hint_length.value; + hint->data.length.unit = hint_length.unit; + hint->status = CSS_MARGIN_SET; + hint = css_hint_advance(hint); + + hint->prop = CSS_PROP_MARGIN_BOTTOM; + hint->data.length.value = hint_length.value; + hint->data.length.unit = hint_length.unit; + hint->status = CSS_MARGIN_SET; + hint = css_hint_advance(hint); } + dom_string_unref(attr); } - - dom_string_unref(name); - return result; + exc = dom_element_get_attribute(node, + corestring_dom_hspace, &attr); + + if (exc == DOM_NO_ERR && attr != NULL) { + css_hint_length hint_length; + if (parse_dimension( + dom_string_data(attr), false, + &hint_length.value, + &hint_length.unit)) { + hint->prop = CSS_PROP_MARGIN_LEFT; + hint->data.length.value = hint_length.value; + hint->data.length.unit = hint_length.unit; + hint->status = CSS_MARGIN_SET; + hint = css_hint_advance(hint); + + hint->prop = CSS_PROP_MARGIN_RIGHT; + hint->data.length.value = hint_length.value; + hint->data.length.unit = hint_length.unit; + hint->status = CSS_MARGIN_SET; + hint = css_hint_advance(hint); + } + dom_string_unref(attr); + } } -static css_error node_presentational_hint_margin_rl( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint, - uint32_t property) +static void css_hint_margin_left_right_hr( + nscss_select_ctx *ctx, + dom_node *node) { - dom_string *n; + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + dom_string *attr; dom_exception exc; - - exc = dom_node_get_node_name(node, &n); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (dom_string_caseless_lwc_isequal(n, corestring_lwc_img) || - dom_string_caseless_lwc_isequal(n, corestring_lwc_applet)) { - dom_string_unref(n); - exc = dom_element_get_attribute(node, - corestring_dom_hspace, &n); - if (exc != DOM_NO_ERR) { - return CSS_BADPARM; - } - - if (n == NULL) - return CSS_PROPERTY_NOT_SET; - - if (parse_dimension(dom_string_data(n), false, - &hint->data.length.value, - &hint->data.length.unit)) { + + exc = dom_element_get_attribute(node, + corestring_dom_align, &attr); + + if (exc == DOM_NO_ERR && attr != NULL) { + if (dom_string_caseless_lwc_isequal(attr, + corestring_lwc_left)) { + hint->prop = CSS_PROP_MARGIN_LEFT; + hint->data.length.value = 0; + hint->data.length.unit = CSS_UNIT_PX; hint->status = CSS_MARGIN_SET; - } else { - dom_string_unref(n); - return CSS_PROPERTY_NOT_SET; - } - dom_string_unref(n); - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(n, corestring_lwc_table) || - dom_string_caseless_lwc_isequal(n, corestring_lwc_align)) { - dom_string_unref(n); - exc = dom_element_get_attribute(node, - corestring_dom_align, &n); - if (exc != DOM_NO_ERR) { - return CSS_BADPARM; - } - - if (n == NULL) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(n, - corestring_lwc_center) || - dom_string_caseless_lwc_isequal(n, - corestring_lwc_abscenter) || - dom_string_caseless_lwc_isequal(n, - corestring_lwc_middle) || - dom_string_caseless_lwc_isequal(n, - corestring_lwc_absmiddle)) { + hint = css_hint_advance(hint); + + hint->prop = CSS_PROP_MARGIN_RIGHT; hint->status = CSS_MARGIN_AUTO; - } else { - dom_string_unref(n); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(n); - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(n, corestring_lwc_hr)) { - dom_string_unref(n); - exc = dom_element_get_attribute(node, - corestring_dom_align, &n); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (n == NULL) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(n, - corestring_lwc_left)) { - if (property == CSS_PROP_MARGIN_LEFT) { - hint->data.length.value = 0; - hint->data.length.unit = CSS_UNIT_PX; - hint->status = CSS_MARGIN_SET; - } else { - hint->status = CSS_MARGIN_AUTO; - } - } else if (dom_string_caseless_lwc_isequal(n, + hint = css_hint_advance(hint); + + } else if (dom_string_caseless_lwc_isequal(attr, corestring_lwc_center)) { + hint->prop = CSS_PROP_MARGIN_LEFT; hint->status = CSS_MARGIN_AUTO; - } else if (dom_string_caseless_lwc_isequal(n, + hint = css_hint_advance(hint); + + hint->prop = CSS_PROP_MARGIN_RIGHT; + hint->status = CSS_MARGIN_AUTO; + hint = css_hint_advance(hint); + + } else if (dom_string_caseless_lwc_isequal(attr, corestring_lwc_right)) { - if (property == CSS_PROP_MARGIN_RIGHT) { - hint->data.length.value = 0; - hint->data.length.unit = CSS_UNIT_PX; - hint->status = CSS_MARGIN_SET; - } else { - hint->status = CSS_MARGIN_AUTO; - } - } else { - dom_string_unref(n); - return CSS_PROPERTY_NOT_SET; + hint->prop = CSS_PROP_MARGIN_LEFT; + hint->status = CSS_MARGIN_AUTO; + hint = css_hint_advance(hint); + + hint->prop = CSS_PROP_MARGIN_RIGHT; + hint->data.length.value = 0; + hint->data.length.unit = CSS_UNIT_PX; + hint->status = CSS_MARGIN_SET; + hint = css_hint_advance(hint); } - dom_string_unref(n); - - return CSS_OK; + dom_string_unref(attr); } - - dom_string_unref(n); - - return CSS_PROPERTY_NOT_SET; } -static css_error node_presentational_hint_margin_tb( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_table_spacing_border( + nscss_select_ctx *ctx, + dom_node *node) { - dom_string *name, *vspace = NULL; + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; dom_exception exc; - - exc = dom_node_get_node_name(node, &name); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_img) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) { - exc = dom_element_get_attribute(node, corestring_dom_vspace, - &vspace); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } - } - - dom_string_unref(name); - - if (vspace == NULL) - return CSS_PROPERTY_NOT_SET; - - if (parse_dimension(dom_string_data(vspace), false, - &hint->data.length.value, - &hint->data.length.unit)) { - hint->status = CSS_MARGIN_SET; - } else { - dom_string_unref(vspace); - return CSS_PROPERTY_NOT_SET; - } + dom_string *attr = NULL; - dom_string_unref(vspace); + exc = dom_element_get_attribute(node, corestring_dom_border, &attr); - return CSS_OK; -} + if (exc == DOM_NO_ERR && attr != NULL) { + uint32_t hint_prop; + css_hint_length hint_length; -static css_error node_presentational_hint_border_trbl_width( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_string *name; - dom_exception exc; - dom_string *width = NULL; - bool is_table_cell = false; - - exc = dom_node_get_node_name(node, &name); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { - css_qname qs; - dom_node *tablenode = NULL; - qs.ns = NULL; - qs.name = lwc_string_ref(corestring_lwc_table); - if (named_ancestor_node(ctx, node, &qs, - (void *)&tablenode) != CSS_OK) { - /* Didn't find, or had error */ - lwc_string_unref(qs.name); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; + for (hint_prop = CSS_PROP_BORDER_TOP_STYLE; + hint_prop <= CSS_PROP_BORDER_LEFT_STYLE; + hint_prop++) { + hint->prop = hint_prop; + hint->status = CSS_BORDER_STYLE_OUTSET; + hint = css_hint_advance(hint); } - - lwc_string_unref(qs.name); - if (tablenode != NULL) { - exc = dom_element_get_attribute(tablenode, - corestring_dom_border, &width); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; + + if (parse_dimension( + dom_string_data(attr), false, + &hint_length.value, + &hint_length.unit)) { + + for (hint_prop = CSS_PROP_BORDER_TOP_WIDTH; + hint_prop <= CSS_PROP_BORDER_LEFT_WIDTH; + hint_prop++) { + hint->prop = hint_prop; + hint->data.length.value = hint_length.value; + hint->data.length.unit = hint_length.unit; + hint->status = CSS_BORDER_WIDTH_WIDTH; + hint = css_hint_advance(hint); } } - /* No need to unref tablenode, named_ancestor_node does not - * return a reffed node to the CSS - */ - is_table_cell = true; - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_table)) { - exc = dom_element_get_attribute(node, corestring_dom_border, - &width); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } + dom_string_unref(attr); } - - dom_string_unref(name); - - if (width == NULL) - return CSS_PROPERTY_NOT_SET; - - if (parse_dimension(dom_string_data(width), false, - &hint->data.length.value, - &hint->data.length.unit)) { - if (is_table_cell && - INTTOFIX(0) != - hint->data.length.value) { - hint->data.length.value = INTTOFIX(1); - hint->data.length.unit = CSS_UNIT_PX; - } - hint->status = CSS_BORDER_WIDTH_WIDTH; - } else { - dom_string_unref(width); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(width); - - return CSS_OK; -} - -static css_error node_presentational_hint_border_trbl_style( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) -{ - dom_string *name; - dom_exception exc; - exc = dom_node_get_node_name(node, &name); - if (exc != DOM_NO_ERR) - return CSS_BADPARM; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { - css_qname qs; - dom_node *tablenode = NULL; - qs.ns = NULL; - qs.name = lwc_string_ref(corestring_lwc_table); - - if (named_ancestor_node(ctx, node, &qs, - (void *)&tablenode) != CSS_OK) { - /* Didn't find, or had error */ - lwc_string_unref(qs.name); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - lwc_string_unref(qs.name); + exc = dom_element_get_attribute(node, + corestring_dom_bordercolor, &attr); - if (tablenode != NULL) { - bool has_border = false; + if (exc == DOM_NO_ERR && attr != NULL) { + uint32_t hint_prop; + css_color hint_color; - exc = dom_element_has_attribute(tablenode, - corestring_dom_border, - &has_border); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } + if (nscss_parse_colour( + (const char *)dom_string_data(attr), + &hint_color)) { - if (has_border) { - hint->status = CSS_BORDER_STYLE_INSET; - dom_string_unref(name); - return CSS_OK; + for (hint_prop = CSS_PROP_BORDER_TOP_COLOR; + hint_prop <= CSS_PROP_BORDER_LEFT_COLOR; + hint_prop++) { + hint->prop = hint_prop; + hint->data.color = hint_color; + hint->status = CSS_BORDER_COLOR_COLOR; + hint = css_hint_advance(hint); } } - /* No need to unref tablenode, named_ancestor_node does not - * return a reffed node to the CSS - */ - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_table)) { - bool has_border = false; - - exc = dom_element_has_attribute(node, - corestring_dom_border, - &has_border); - if (exc != DOM_NO_ERR) { - dom_string_unref(name); - return CSS_BADPARM; - } + dom_string_unref(attr); + } - if (has_border) { - hint->status = CSS_BORDER_STYLE_OUTSET; - dom_string_unref(name); - return CSS_OK; + exc = dom_element_get_attribute(node, + corestring_dom_cellspacing, &attr); + + if (exc == DOM_NO_ERR && attr != NULL) { + if (parse_dimension( + (const char *)dom_string_data(attr), false, + &hint->data.position.h.value, + &hint->data.position.h.unit)) { + hint->prop = CSS_PROP_BORDER_SPACING; + hint->data.position.v = hint->data.position.h; + hint->status = CSS_BORDER_SPACING_SET; + hint = css_hint_advance(hint); } + dom_string_unref(attr); } - - dom_string_unref(name); - - return CSS_PROPERTY_NOT_SET; } -static css_error node_presentational_hint_border_trbl_color( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_height( + nscss_select_ctx *ctx, + dom_node *node) { - dom_string *name; - dom_string *bordercolor = NULL; + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + dom_string *attr = NULL; dom_exception err; - err = dom_node_get_node_name(node, &name); - if (err != DOM_NO_ERR) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) { - css_qname qs; - dom_node *tablenode = NULL; - qs.ns = NULL; - qs.name = lwc_string_ref(corestring_lwc_table); - - if (named_ancestor_node(ctx, node, &qs, - (void *)&tablenode) != CSS_OK) { - /* Didn't find, or had error */ - lwc_string_unref(qs.name); - dom_string_unref(name); - return CSS_PROPERTY_NOT_SET; - } - - lwc_string_unref(qs.name); - - if (tablenode != NULL) { - err = dom_element_get_attribute(node, - corestring_dom_bordercolor, - &bordercolor); + err = dom_element_get_attribute(node, + corestring_dom_height, &attr); + + if (err == DOM_NO_ERR && attr != NULL) { + if (parse_dimension( + (const char *)dom_string_data(attr), false, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->prop = CSS_PROP_HEIGHT; + hint->status = CSS_HEIGHT_SET; + hint = css_hint_advance(hint); } - /* No need to unref tablenode, named_ancestor_node does not - * return a reffed node to the CSS - */ - - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_table)) { - err = dom_element_get_attribute(node, - corestring_dom_bordercolor, - &bordercolor); - } - - dom_string_unref(name); - - if ((err != DOM_NO_ERR) || (bordercolor == NULL)) { - return CSS_PROPERTY_NOT_SET; + dom_string_unref(attr); } - - if (nscss_parse_colour((const char *)dom_string_data(bordercolor), - &hint->data.color)) { - hint->status = CSS_BORDER_COLOR_COLOR; - dom_string_unref(bordercolor); - return CSS_OK; - } - - dom_string_unref(bordercolor); - return CSS_PROPERTY_NOT_SET; } -static css_error node_presentational_hint_border_spacing( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_width( + nscss_select_ctx *ctx, + dom_node *node) { + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + dom_string *attr = NULL; dom_exception err; - dom_string *node_name = NULL; - dom_string *cellspacing = NULL; - - err = dom_node_get_node_name(node, &node_name); - if ((err != DOM_NO_ERR) || (node_name == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (!dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_table)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(node_name); err = dom_element_get_attribute(node, - corestring_dom_cellspacing, &cellspacing); - if ((err != DOM_NO_ERR) || (cellspacing == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - - if (parse_dimension((const char *)dom_string_data(cellspacing), - false, - &hint->data.position.h.value, - &hint->data.position.h.unit)) { - - hint->data.position.v = hint->data.position.h; - hint->status = CSS_BORDER_SPACING_SET; - - dom_string_unref(cellspacing); - return CSS_OK; + corestring_dom_width, &attr); + + if (err == DOM_NO_ERR && attr != NULL) { + if (parse_dimension( + (const char *)dom_string_data(attr), false, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->prop = CSS_PROP_WIDTH; + hint->status = CSS_WIDTH_SET; + hint = css_hint_advance(hint); + } + dom_string_unref(attr); } - - dom_string_unref(cellspacing); - return CSS_PROPERTY_NOT_SET; } -static css_error node_presentational_hint_width( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_height_width_textarea( + nscss_select_ctx *ctx, + dom_node *node) { - dom_string *name; - dom_string *width = NULL; + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + dom_string *attr = NULL; dom_exception err; - bool textarea = false; - bool input = false; - - err = dom_node_get_node_name(node, &name); - if (err != DOM_NO_ERR) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_hr) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_iframe) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_img) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_object) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_table) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) { - err = dom_element_get_attribute(node, - corestring_dom_width, &width); - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_textarea)) { - textarea = true; - err = dom_element_get_attribute(node, - corestring_dom_cols, &width); - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_input)) { - input = true; - err = dom_element_get_attribute(node, - corestring_dom_size, &width); - } - - dom_string_unref(name); - if ((err != DOM_NO_ERR) || (width == NULL)) { - return CSS_PROPERTY_NOT_SET; + err = dom_element_get_attribute(node, + corestring_dom_rows, &attr); + + if (err == DOM_NO_ERR && attr != NULL) { + if (parse_dimension( + (const char *)dom_string_data(attr), false, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->prop = CSS_PROP_HEIGHT; + hint->data.length.unit = CSS_UNIT_EM; + hint->status = CSS_HEIGHT_SET; + hint = css_hint_advance(hint); + } + dom_string_unref(attr); } - if (parse_dimension((const char *)dom_string_data(width), - false, - &hint->data.length.value, - &hint->data.length.unit)) { - hint->status = CSS_WIDTH_SET; - dom_string_unref(width); - - if (textarea) { + err = dom_element_get_attribute(node, + corestring_dom_cols, &attr); + + if (err == DOM_NO_ERR && attr != NULL) { + if (parse_dimension( + (const char *)dom_string_data(attr), false, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->prop = CSS_PROP_WIDTH; hint->data.length.unit = CSS_UNIT_EX; + hint->status = CSS_WIDTH_SET; + hint = css_hint_advance(hint); } - - if (input) { - err = dom_element_get_attribute(node, - corestring_dom_type, &width); - if (err != DOM_NO_ERR) { - return CSS_PROPERTY_NOT_SET; - } - - if ((width == NULL) || - dom_string_caseless_lwc_isequal(width, - corestring_lwc_text) || - dom_string_caseless_lwc_isequal(width, - corestring_lwc_search) || - dom_string_caseless_lwc_isequal(width, - corestring_lwc_file) || - dom_string_caseless_lwc_isequal(width, - corestring_lwc_password)) { - hint->data.length.unit = CSS_UNIT_EX; - } - dom_string_unref(width); - } - - return CSS_OK; + dom_string_unref(attr); } - - dom_string_unref(width); - return CSS_PROPERTY_NOT_SET; - } -static css_error node_presentational_hint_height(nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_width_input( + nscss_select_ctx *ctx, + dom_node *node) { - dom_string *name; - dom_string *height = NULL; + struct css_hint *hint = &(hint_ctx.hints[hint_ctx.len]); + dom_string *attr = NULL; dom_exception err; - bool textarea = false; - - err = dom_node_get_node_name(node, &name); - if (err != DOM_NO_ERR) - return CSS_PROPERTY_NOT_SET; - - if (dom_string_caseless_lwc_isequal(name, corestring_lwc_iframe) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_td) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_th) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_tr) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_img) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_object) || - dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) { - err = dom_element_get_attribute(node, - corestring_dom_height, &height); - } else if (dom_string_caseless_lwc_isequal(name, - corestring_lwc_textarea)) { - textarea = true; - err = dom_element_get_attribute(node, - corestring_dom_rows, &height); - } - dom_string_unref(name); - - if ((err != DOM_NO_ERR) || (height == NULL)) { - return CSS_PROPERTY_NOT_SET; - } + err = dom_element_get_attribute(node, + corestring_dom_size, &attr); - if (parse_dimension((const char *)dom_string_data(height), - false, - &hint->data.length.value, - &hint->data.length.unit)) { - hint->status = CSS_HEIGHT_SET; + if (err == DOM_NO_ERR && attr != NULL) { + if (parse_dimension( + (const char *)dom_string_data(attr), false, + &hint->data.length.value, + &hint->data.length.unit)) { + dom_string *attr2 = NULL; - if (textarea) { - hint->data.length.unit = CSS_UNIT_EM; + err = dom_element_get_attribute(node, + corestring_dom_type, &attr2); + if (err == DOM_NO_ERR) { + + hint->prop = CSS_PROP_WIDTH; + hint->status = CSS_WIDTH_SET; + + if (attr2 == NULL || + dom_string_caseless_lwc_isequal( + attr2, + corestring_lwc_text) || + dom_string_caseless_lwc_isequal( + attr2, + corestring_lwc_search) || + dom_string_caseless_lwc_isequal( + attr2, + corestring_lwc_password) || + dom_string_caseless_lwc_isequal( + attr2, + corestring_lwc_file)) { + hint->data.length.unit = CSS_UNIT_EX; + } + if (attr2 != NULL) { + dom_string_unref(attr2); + } + hint = css_hint_advance(hint); + } } - - dom_string_unref(height); - return CSS_OK; + dom_string_unref(attr); } - - dom_string_unref(height); - return CSS_PROPERTY_NOT_SET; } -static css_error node_presentational_hint_font_size( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_anchor_color( + nscss_select_ctx *ctx, + dom_node *node) { + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + css_error error; dom_exception err; - dom_string *node_name = NULL; - dom_string *size; + dom_string *color; + dom_node *bodynode = NULL; + + /* find body node */ + css_qname qs; + bool is_visited; - err = dom_node_get_node_name(node, &node_name); - if ((err != DOM_NO_ERR) || (node_name == NULL)) { - return CSS_NOMEM; + qs.ns = NULL; + qs.name = lwc_string_ref(corestring_lwc_body); + if (named_ancestor_node(ctx, node, &qs, + (void *)&bodynode) != CSS_OK) { + /* Didn't find, or had error */ + lwc_string_unref(qs.name); + return ; } + lwc_string_unref(qs.name); - if (!dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_font)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; + if (bodynode == NULL) { + return; } - dom_string_unref(node_name); + error = node_is_visited(ctx, node, &is_visited); + if (error != CSS_OK) + return; - err = dom_element_get_attribute(node, corestring_dom_size, &size); - if ((err != DOM_NO_ERR) || (size == NULL)) { - return CSS_PROPERTY_NOT_SET; + if (is_visited) { + err = dom_element_get_attribute(bodynode, + corestring_dom_vlink, &color); + } else { + err = dom_element_get_attribute(bodynode, + corestring_dom_link, &color); } - if (parse_font_size((const char *)dom_string_data(size), - &hint->status, - &hint->data.length.value, - &hint->data.length.unit)) { - dom_string_unref(size); - return CSS_OK; + if (err == DOM_NO_ERR && color != NULL) { + if (nscss_parse_colour( + (const char *)dom_string_data(color), + &hint->data.color)) { + hint->prop = CSS_PROP_COLOR; + hint->status = CSS_COLOR_COLOR; + hint = css_hint_advance(hint); + } + dom_string_unref(color); } - - dom_string_unref(size); - return CSS_PROPERTY_NOT_SET; } -static css_error node_presentational_hint_float( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_color( + nscss_select_ctx *ctx, + dom_node *node) { + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; dom_exception err; - dom_string *node_name = NULL; - dom_string *align; - - err = dom_node_get_node_name(node, &node_name); - if ((err != DOM_NO_ERR) || (node_name == NULL)) { - return CSS_NOMEM; - } - - /** \todo input[type=image][align=*] - $11.3.3 */ - if (!dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_table) && - !dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_applet) && - !dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_embed) && - !dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_iframe) && - !dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_img) && - !dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_object)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(node_name); + dom_string *color; - err = dom_element_get_attribute(node, corestring_dom_align, &align); - if ((err != DOM_NO_ERR) || (align == NULL)) { - return CSS_PROPERTY_NOT_SET; - } + err = dom_element_get_attribute(node, corestring_dom_color, &color); - if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_left)) { - hint->status = CSS_FLOAT_LEFT; - dom_string_unref(align); - return CSS_OK; - } else if (dom_string_caseless_lwc_isequal(align, - corestring_lwc_right)) { - hint->status = CSS_FLOAT_RIGHT; - dom_string_unref(align); - return CSS_OK; + if (err == DOM_NO_ERR && color != NULL) { + if (nscss_parse_colour( + (const char *)dom_string_data(color), + &hint->data.color)) { + hint->prop = CSS_PROP_COLOR; + hint->status = CSS_COLOR_COLOR; + hint = css_hint_advance(hint); + } + dom_string_unref(color); } - - dom_string_unref(align); - - return CSS_PROPERTY_NOT_SET; } -static css_error node_presentational_hint_color( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_font_size( + nscss_select_ctx *ctx, + dom_node *node) { - css_error error; + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; dom_exception err; - dom_string *node_name = NULL; - dom_string *color; - - err = dom_node_get_node_name(node, &node_name); - if ((err != DOM_NO_ERR) || (node_name == NULL)) { - return CSS_NOMEM; - } + dom_string *size; - if (dom_string_caseless_lwc_isequal(node_name, corestring_lwc_a)) { - /* find body node */ - css_qname qs; - dom_node *bodynode = NULL; - bool is_visited; - - qs.ns = NULL; - qs.name = lwc_string_ref(corestring_lwc_body); - if (named_ancestor_node(ctx, node, &qs, - (void *)&bodynode) != CSS_OK) { - /* Didn't find, or had error */ - lwc_string_unref(qs.name); - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; + err = dom_element_get_attribute(node, corestring_dom_size, &size); + if (err == DOM_NO_ERR && size != NULL) { + if (parse_font_size( + (const char *)dom_string_data(size), + &hint->status, + &hint->data.length.value, + &hint->data.length.unit)) { + hint->prop = CSS_PROP_FONT_SIZE; + hint = css_hint_advance(hint); } - - lwc_string_unref(qs.name); + dom_string_unref(size); + } +} - /* deal with missing body ancestor */ - if (bodynode == NULL) { - dom_string_unref(node_name); - return CSS_BADPARM; - } +static void css_hint_float( + nscss_select_ctx *ctx, + dom_node *node) +{ + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; + dom_exception err; + dom_string *align; - error = node_is_visited(ctx, node, &is_visited); - if (error != CSS_OK) - return error; + err = dom_element_get_attribute(node, corestring_dom_align, &align); + if (err == DOM_NO_ERR && align != NULL) { + if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_left)) { + hint->prop = CSS_PROP_FLOAT; + hint->status = CSS_FLOAT_LEFT; + hint = css_hint_advance(hint); - if (is_visited) { - err = dom_element_get_attribute(bodynode, - corestring_dom_vlink, &color); - if ((err != DOM_NO_ERR) || (color == NULL)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - } else { - err = dom_element_get_attribute(bodynode, - corestring_dom_link, &color); - if ((err != DOM_NO_ERR) || (color == NULL)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - } - } else { - err = dom_element_get_attribute(node, - corestring_dom_color, &color); - if ((err != DOM_NO_ERR) || (color == NULL)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; + } else if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_right)) { + hint->prop = CSS_PROP_FLOAT; + hint->status = CSS_FLOAT_RIGHT; + hint = css_hint_advance(hint); } + dom_string_unref(align); } - - if (!nscss_parse_colour((const char *)dom_string_data(color), - &hint->data.color)) { - dom_string_unref(color); - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - - hint->status = CSS_COLOR_COLOR; - - dom_string_unref(color); - dom_string_unref(node_name); - - return CSS_OK; } -static css_error node_presentational_hint_caption_side( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_caption_side( + nscss_select_ctx *ctx, + dom_node *node) { + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; dom_exception err; - dom_string *node_name = NULL; dom_string *align = NULL; - err = dom_node_get_node_name(node, &node_name); - if ((err != DOM_NO_ERR) || (node_name == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (!dom_string_caseless_lwc_isequal(node_name, - corestring_lwc_caption)) { - dom_string_unref(node_name); - return CSS_PROPERTY_NOT_SET; - } - - dom_string_unref(node_name); - err = dom_element_get_attribute(node, corestring_dom_align, &align); - if ((err != DOM_NO_ERR) || (align == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (dom_string_caseless_lwc_isequal(align, corestring_lwc_bottom)) { - hint->status = CSS_CAPTION_SIDE_BOTTOM; + if (err == DOM_NO_ERR && align != NULL) { + if (dom_string_caseless_lwc_isequal(align, + corestring_lwc_bottom)) { + hint->prop = CSS_PROP_CAPTION_SIDE; + hint->status = CSS_CAPTION_SIDE_BOTTOM; + hint = css_hint_advance(hint); + } dom_string_unref(align); - return CSS_OK; } - - dom_string_unref(align); - - return CSS_PROPERTY_NOT_SET; } -static css_error node_presentational_hint_background_color( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_bg_color( + nscss_select_ctx *ctx, + dom_node *node) { + struct css_hint *hint = &hint_ctx.hints[hint_ctx.len]; dom_exception err; dom_string *bgcolor; err = dom_element_get_attribute(node, corestring_dom_bgcolor, &bgcolor); - if ((err != DOM_NO_ERR) || (bgcolor == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - if (nscss_parse_colour((const char *)dom_string_data(bgcolor), - &hint->data.color)) { - hint->status = CSS_BACKGROUND_COLOR_COLOR; + if (err == DOM_NO_ERR && bgcolor != NULL) { + if (nscss_parse_colour( + (const char *)dom_string_data(bgcolor), + &hint->data.color)) { + hint->prop = CSS_PROP_BACKGROUND_COLOR; + hint->status = CSS_BACKGROUND_COLOR_COLOR; + hint = css_hint_advance(hint); + } dom_string_unref(bgcolor); - return CSS_OK; } - - dom_string_unref(bgcolor); - - return CSS_PROPERTY_NOT_SET; } -static css_error node_presentational_hint_background_image( - nscss_select_ctx *ctx, - dom_node *node, - css_hint *hint) +static void css_hint_bg_image( + nscss_select_ctx *ctx, + dom_node *node) { + struct css_hint *hint = &(hint_ctx.hints[hint_ctx.len]); dom_exception err; - dom_string *atr_val; - nserror error; - nsurl *url; - lwc_string *iurl; - lwc_error lerror; + dom_string *attr; err = dom_element_get_attribute(node, - corestring_dom_background, &atr_val); - if ((err != DOM_NO_ERR) || (atr_val == NULL)) { - return CSS_PROPERTY_NOT_SET; - } - - error = nsurl_join(ctx->base_url, - (const char *)dom_string_data(atr_val), &url); - - dom_string_unref(atr_val); - - if (error != NSERROR_OK) { - return CSS_NOMEM; - } - - lerror = lwc_intern_string(nsurl_access(url), - nsurl_length(url), &iurl); - - nsurl_unref(url); - - if (lerror == lwc_error_oom) { - return CSS_NOMEM; - } - - if (lerror == lwc_error_ok) { - hint->data.string = iurl; - hint->status = CSS_BACKGROUND_IMAGE_IMAGE; - return CSS_OK; - } - - return CSS_PROPERTY_NOT_SET; -} - -struct css_hint_ctx { - struct css_hint *hints; - uint32_t alloc; - uint32_t len; -}; - -struct css_hint_ctx hint_ctx; - -static void css_hint_destroy(struct css_hint_ctx *hint) -{ - hint->alloc = 0; - hint->len = 0; - free(hint->hints); -} - -static nserror css_hint_extend(struct css_hint_ctx *hint) -{ - uint32_t alloc = (hint->alloc == 0) ? 32 : hint->alloc * 2; - struct css_hint *temp; - - temp = realloc(hint->hints, sizeof(struct css_hint) * alloc); - if (temp != NULL) { - hint->hints = temp; - hint->alloc = alloc; - - return NSERROR_OK; - } - - return NSERROR_NOMEM; -} - -nserror css_hint_init(void) -{ - nserror err; - - err = css_hint_extend(&hint_ctx); - if (err != NSERROR_OK) { - return err; - } - - return NSERROR_OK; -} - -void css_hint_fini(void) -{ - css_hint_destroy(&hint_ctx); -} - - -/* Exported function, documeted in css/hints.h */ -static inline css_error node_presentational_hint_internal( - void *pw, void *node, struct css_hint_ctx *hints) -{ - struct css_hint_ctx *ctx = hints; - uint32_t property; - nserror nserr; - css_error err; - - ctx->len = 0; - - for (property = 0; property < CSS_N_PROPERTIES; property++) { - css_hint *hint = &(ctx->hints[ctx->len]); - - if (ctx->alloc == 0 || ctx->len == ctx->alloc - 1) { - nserr = css_hint_extend(ctx); - if (nserr != NSERROR_OK) { - return NSERROR_NOMEM; + corestring_dom_background, &attr); + if (err == DOM_NO_ERR && attr != NULL) { + nsurl *url; + nserror error = nsurl_join(ctx->base_url, + (const char *)dom_string_data(attr), &url); + dom_string_unref(attr); + + if (error != NSERROR_OK) { + lwc_string *iurl; + lwc_error lerror = lwc_intern_string(nsurl_access(url), + nsurl_length(url), &iurl); + nsurl_unref(url); + + if (lerror == lwc_error_ok) { + hint->prop = CSS_PROP_BACKGROUND_IMAGE; + hint->data.string = iurl; + hint->status = CSS_BACKGROUND_IMAGE_IMAGE; + hint = css_hint_advance(hint); } } - - switch (property) { - case CSS_PROP_BACKGROUND_IMAGE: - err = node_presentational_hint_background_image( - pw, node, hint); - break; - - case CSS_PROP_BACKGROUND_COLOR: - err = node_presentational_hint_background_color( - pw, node, hint); - break; - - case CSS_PROP_CAPTION_SIDE: - err = node_presentational_hint_caption_side( - pw, node, hint); - break; - - case CSS_PROP_COLOR: - err = node_presentational_hint_color( - pw, node, hint); - break; - - case CSS_PROP_FLOAT: - err = node_presentational_hint_float( - pw, node, hint); - break; - - case CSS_PROP_FONT_SIZE: - err = node_presentational_hint_font_size( - pw, node, hint); - break; - - case CSS_PROP_HEIGHT: - err = node_presentational_hint_height( - pw, node, hint); - break; - - case CSS_PROP_WIDTH: - err = node_presentational_hint_width( - pw, node, hint); - break; - - case CSS_PROP_BORDER_SPACING: - err = node_presentational_hint_border_spacing( - pw, node, hint); - break; - - case CSS_PROP_BORDER_TOP_COLOR: - case CSS_PROP_BORDER_RIGHT_COLOR: - case CSS_PROP_BORDER_BOTTOM_COLOR: - case CSS_PROP_BORDER_LEFT_COLOR: - err = node_presentational_hint_border_trbl_color( - pw, node, hint); - break; - - case CSS_PROP_BORDER_TOP_STYLE: - case CSS_PROP_BORDER_RIGHT_STYLE: - case CSS_PROP_BORDER_BOTTOM_STYLE: - case CSS_PROP_BORDER_LEFT_STYLE: - err = node_presentational_hint_border_trbl_style( - pw, node, hint); - break; - - case CSS_PROP_BORDER_TOP_WIDTH: - case CSS_PROP_BORDER_RIGHT_WIDTH: - case CSS_PROP_BORDER_BOTTOM_WIDTH: - case CSS_PROP_BORDER_LEFT_WIDTH: - err = node_presentational_hint_border_trbl_width( - pw, node, hint); - break; - - case CSS_PROP_MARGIN_TOP: - case CSS_PROP_MARGIN_BOTTOM: - err = node_presentational_hint_margin_tb( - pw, node, hint); - break; - - case CSS_PROP_MARGIN_RIGHT: - case CSS_PROP_MARGIN_LEFT: - err = node_presentational_hint_margin_rl( - pw, node, hint, property); - break; - - case CSS_PROP_PADDING_TOP: - case CSS_PROP_PADDING_RIGHT: - case CSS_PROP_PADDING_BOTTOM: - case CSS_PROP_PADDING_LEFT: - err = node_presentational_hint_padding_trbl( - pw, node, hint); - break; - - case CSS_PROP_TEXT_ALIGN: - err = node_presentational_hint_text_align( - pw, node, hint); - break; - - case CSS_PROP_VERTICAL_ALIGN: - err = node_presentational_hint_vertical_align( - pw, node, hint); - break; - - default: - err = CSS_PROPERTY_NOT_SET; - break; - } - - if (err == CSS_OK) { - hint->prop = property; - ctx->len++; - } } - - return CSS_OK; } @@ -1903,19 +1486,95 @@ static inline css_error node_presentational_hint_internal( css_error node_presentational_hint(void *pw, void *node, uint32_t *nhints, css_hint **hints) { - css_error err; + dom_exception exc; + dom_html_element_type tag_type; + + css_hint_clean(); - err = node_presentational_hint_internal(pw, node, &hint_ctx); - if (err != CSS_OK) { - return err; + exc = dom_html_element_get_tag_type(node, &tag_type); + if (exc != DOM_NO_ERR) { + tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN; + } + + switch (tag_type) { + case DOM_HTML_ELEMENT_TYPE_TH: + case DOM_HTML_ELEMENT_TYPE_TD: + css_hint_width(pw, node); + css_hint_table_cell_border_padding(pw, node); + case DOM_HTML_ELEMENT_TYPE_TR: + css_hint_height(pw, node); + case DOM_HTML_ELEMENT_TYPE_THEAD: + case DOM_HTML_ELEMENT_TYPE_TBODY: + case DOM_HTML_ELEMENT_TYPE_TFOOT: + css_hint_text_align_special(pw, node); + case DOM_HTML_ELEMENT_TYPE_COL: + css_hint_vertical_align_table_cells(pw, node); + break; + case DOM_HTML_ELEMENT_TYPE_APPLET: + case DOM_HTML_ELEMENT_TYPE_IMG: + css_hint_margin_hspace_vspace(pw, node); + case DOM_HTML_ELEMENT_TYPE_EMBED: + case DOM_HTML_ELEMENT_TYPE_IFRAME: + case DOM_HTML_ELEMENT_TYPE_OBJECT: + css_hint_height(pw, node); + css_hint_width(pw, node); + css_hint_vertical_align_replaced(pw, node); + css_hint_float(pw, node); + break; + case DOM_HTML_ELEMENT_TYPE_P: + case DOM_HTML_ELEMENT_TYPE_H1: + case DOM_HTML_ELEMENT_TYPE_H2: + case DOM_HTML_ELEMENT_TYPE_H3: + case DOM_HTML_ELEMENT_TYPE_H4: + case DOM_HTML_ELEMENT_TYPE_H5: + case DOM_HTML_ELEMENT_TYPE_H6: + css_hint_text_align_normal(pw, node); + break; + case DOM_HTML_ELEMENT_TYPE_CENTER: + css_hint_text_align_center(pw, node); + break; + case DOM_HTML_ELEMENT_TYPE_CAPTION: + css_hint_caption_side(pw, node); + case DOM_HTML_ELEMENT_TYPE_DIV: + css_hint_text_align_special(pw, node); + break; + case DOM_HTML_ELEMENT_TYPE_TABLE: + css_hint_text_align_table_special(pw, node); + css_hint_table_spacing_border(pw, node); + css_hint_float(pw, node); + css_hint_margin_left_right_align_center(pw, node); + css_hint_width(pw, node); + break; + case DOM_HTML_ELEMENT_TYPE_HR: + css_hint_margin_left_right_hr(pw, node); + break; + case DOM_HTML_ELEMENT_TYPE_TEXTAREA: + css_hint_height_width_textarea(pw, node); + break; + case DOM_HTML_ELEMENT_TYPE_INPUT: + css_hint_width_input(pw, node); + break; + case DOM_HTML_ELEMENT_TYPE_A: + css_hint_anchor_color(pw, node); + break; + case DOM_HTML_ELEMENT_TYPE_FONT: + css_hint_font_size(pw, node); + break; + default: + break; + } + + if (tag_type != DOM_HTML_ELEMENT_TYPE__UNKNOWN) { + css_hint_color(pw, node); + css_hint_bg_color(pw, node); + css_hint_bg_image(pw, node); } #ifdef LOG_STATS LOG("Properties with hints: %i", hint_ctx.len); #endif - *nhints = hint_ctx.len; - *hints = hint_ctx.hints; + css_hint_get_hints(hints, nhints); return CSS_OK; } -- cgit v1.2.3