summaryrefslogtreecommitdiff
path: root/css/css.c
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-07-23 23:05:34 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-07-23 23:05:34 +0000
commitddeadd1c02880367ad786b113d352a519f45ec73 (patch)
tree00b8b46ee1a3fc84e5492c2183dfaa8192d261f9 /css/css.c
parentb20949a35025b23da1bf0ac6003f4575eb94281d (diff)
downloadnetsurf-ddeadd1c02880367ad786b113d352a519f45ec73.tar.gz
netsurf-ddeadd1c02880367ad786b113d352a519f45ec73.tar.bz2
Merge LibCSS port to trunk.
svn path=/trunk/netsurf/; revision=8752
Diffstat (limited to 'css/css.c')
-rw-r--r--css/css.c3446
1 files changed, 234 insertions, 3212 deletions
diff --git a/css/css.c b/css/css.c
index b035323d4..dbb4f53be 100644
--- a/css/css.c
+++ b/css/css.c
@@ -1,7 +1,5 @@
/*
- * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
- * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -18,3313 +16,337 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * CSS handling (implementation).
- *
- * See CSS 2.1 chapter 5 for the terms used here.
- *
- * CSS style sheets are stored as a hash table mapping selectors to styles.
- * Selectors are hashed by the <em>type selector</em> of the last <em>simple
- * selector</em> in the selector. The <em>universal selector</em> is hashed to
- * chain 0.
- *
- * A <em>simple selector</em> is a struct css_selector with type
- * CSS_SELECTOR_ELEMENT. The data field is the <em>type selector</em>, or 0 for
- * the <em>universal selector</em>. Any <em>attribute selectors</em>, <em>ID
- * selectors</em>, or <em>pseudo-classes</em> form a linked list of
- * css_selector hanging from detail.
- *
- * A <em>selector</em> is a linked list by the combiner field of these simple
- * selectors, in reverse order that they appear in the concrete syntax. The last
- * simple selector is first, then the previous one is linked at combiner and has
- * relationship comb to the last, etc.
- *
- * Selectors are then linked in each hash chain by next, in order of increasing
- * specificity.
- *
- * As an example, the stylesheet
- * \code
- * th { [1] }
- * div#id1 > h4.class1 { [2] }
- * center * { [3] } \endcode
- *
- * would result in a struct css_stylesheet (content::data.css.css) like this
- * \dot
- * digraph example {
- * node [shape=record, fontname=Helvetica, fontsize=9];
- * edge [fontname=Helvetica, fontsize=9];
- * css -> n0 [label="rule[0]"];
- * css -> n2 [label="rule[29]"];
- *
- * n0 [label="css_selector\ntype CSS_SELECTOR_ELEMENT\ldata 0\lcomb CSS_COMB_ANCESTOR\lspecificity 2\l"];
- * n0 -> n1 [label="combiner"];
- * n0 -> n0style [label="style"]; n0style [label="[3]"];
- *
- * n1 [label="css_selector\ntype CSS_SELECTOR_ELEMENT\ldata \"center\"\lcomb CSS_COMB_NONE\lspecificity 1\l"];
- *
- * n2 [label="css_selector\ntype CSS_SELECTOR_ELEMENT\ldata \"th\"\lcomb CSS_COMB_NONE\lspecificity 1\l"];
- * n2 -> n3 [label="next"];
- * n2 -> n2style [label="style"]; n2style [label="[1]"];
- *
- * n3 [label="css_selector\ntype CSS_SELECTOR_ELEMENT\ldata \"h4\"\lcomb CSS_COMB_PARENT\lspecificity 0x10102\l"];
- * n3 -> n4 [label="detail"];
- * n3 -> n5 [label="combiner"];
- * n3 -> n3style [label="style"]; n3style [label="[2]"];
- *
- * n4 [label="css_selector\ntype CSS_SELECTOR_CLASS\ldata \"class1\"\lcomb CSS_COMB_NONE\lspecificity 0x100\l"];
- *
- * n5 [label="css_selector\ntype CSS_SELECTOR_ELEMENT\ldata \"div\"\lcomb CSS_COMB_NONE\lspecificity 0x10001\l"];
- * n5 -> n6 [label="detail"];
- *
- * n6 [label="css_selector\ntype CSS_SELECTOR_ID\ldata \"#id1\"\lcomb CSS_COMB_NONE\lspecificity 0x10000\l"];
- * }
- * \enddot
- *
- * (any fields not shown are 0). In this example the first two rules happen to
- * have hashed to the same value.
- */
-
-#define _GNU_SOURCE /* for strndup */
#include <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <math.h>
-#include <limits.h>
-#define CSS_INTERNALS
-#include "utils/config.h"
+
+#include <libwapcaplet/libwapcaplet.h>
+
#include "content/content.h"
#include "content/fetch.h"
#include "content/fetchcache.h"
#include "css/css.h"
-#include "css/parser.h"
+#include "css/internal.h"
#include "desktop/gui.h"
-#include "desktop/options.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/talloc.h"
-#include "utils/url.h"
-#include "utils/utils.h"
-
-/* Define this to debug the working stylesheet */
-#undef DEBUG_WORKING_STYLESHEET
-struct css_working_stylesheet {
- struct css_selector **rule[HASH_SIZE];
-};
+#include "render/html.h"
-
-static void css_deep_free_style(struct css_style *style);
-static void css_atimport_callback(content_msg msg, struct content *css,
+static void nscss_import(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data);
-static bool css_working_list_imports(struct content **import,
- unsigned int import_count,
- struct content ***css, unsigned int *css_count);
-static bool css_working_merge_chains(
- struct css_working_stylesheet *working_stylesheet,
- struct content **css, unsigned int css_count,
- unsigned int chain,
- struct css_selector **rule);
-static bool css_match_rule(struct css_selector *rule, xmlNode *element);
-static bool css_match_detail(const struct css_selector *detail,
- xmlNode *element);
-static bool css_match_first_child(const struct css_selector *detail,
- xmlNode *element);
-static void css_dump_length(FILE *stream,
- const struct css_length * const length);
-static void css_dump_selector(const struct css_selector *r);
-#ifdef DEBUG_WORKING_STYLESHEET
-static void css_dump_working_stylesheet(
- const struct css_working_stylesheet *ws);
-#endif
-static void css_importance_reset(struct css_importance *i);
-
-/** Default style for a document. These are the 'Initial values' from the
- * spec. */
-const struct css_style css_base_style = {
- CSS_BACKGROUND_ATTACHMENT_SCROLL,
- 0xffffff,
- { CSS_BACKGROUND_IMAGE_NONE, 0 },
- { { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } },
- { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } } },
- CSS_BACKGROUND_REPEAT_REPEAT,
- { { 0x000000, { CSS_BORDER_WIDTH_LENGTH,
- { 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE },
- { 0x000000, { CSS_BORDER_WIDTH_LENGTH,
- { 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE },
- { 0x000000, { CSS_BORDER_WIDTH_LENGTH,
- { 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE },
- { 0x000000, { CSS_BORDER_WIDTH_LENGTH,
- { 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE } },
- CSS_BORDER_COLLAPSE_SEPARATE,
- { CSS_BORDER_SPACING_LENGTH,
- { 0, CSS_UNIT_PX }, { 0, CSS_UNIT_PX } },
- CSS_CAPTION_SIDE_TOP,
- CSS_CLEAR_NONE,
- { CSS_CLIP_AUTO, { { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } },
- { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } },
- { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } },
- { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } } } },
- 0x000000,
- { CSS_CONTENT_NORMAL, 0 },
- { CSS_COUNTER_RESET_NONE, 0 },
- { CSS_COUNTER_INCREMENT_NONE, 0 },
- CSS_CURSOR_AUTO,
- CSS_DIRECTION_LTR,
- CSS_DISPLAY_BLOCK,
- CSS_EMPTY_CELLS_SHOW,
- CSS_FLOAT_NONE,
- CSS_FONT_FAMILY_SANS_SERIF,
- { CSS_FONT_SIZE_LENGTH, { { 10, CSS_UNIT_PT } } },
- CSS_FONT_STYLE_NORMAL,
- CSS_FONT_VARIANT_NORMAL,
- CSS_FONT_WEIGHT_NORMAL,
- { CSS_HEIGHT_AUTO, { { 1, CSS_UNIT_EM } } },
- { CSS_LETTER_SPACING_NORMAL, { 0, CSS_UNIT_PX } },
- { CSS_LINE_HEIGHT_ABSOLUTE, { 1.33 } },
- { CSS_LIST_STYLE_IMAGE_NONE, 0 },
- CSS_LIST_STYLE_POSITION_OUTSIDE,
- CSS_LIST_STYLE_TYPE_DISC,
- { { CSS_MARGIN_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_MARGIN_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_MARGIN_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_MARGIN_LENGTH, { { 0, CSS_UNIT_PX } } } },
- { CSS_MAX_HEIGHT_NONE, { { 0, CSS_UNIT_PX } } },
- { CSS_MAX_WIDTH_NONE, { { 0, CSS_UNIT_PX } } },
- { CSS_MIN_HEIGHT_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_MIN_WIDTH_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_ORPHANS_INTEGER, 2 },
- { { CSS_OUTLINE_COLOR_INVERT, 0x000000 },
- { CSS_BORDER_WIDTH_LENGTH, { 2, CSS_UNIT_PX } },
- CSS_BORDER_STYLE_NONE },
- CSS_OVERFLOW_VISIBLE,
- { { CSS_PADDING_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_PADDING_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_PADDING_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_PADDING_LENGTH, { { 0, CSS_UNIT_PX } } } },
- CSS_PAGE_BREAK_AFTER_AUTO,
- CSS_PAGE_BREAK_BEFORE_AUTO,
- CSS_PAGE_BREAK_INSIDE_AUTO,
- { { CSS_POS_AUTO, { { 0, CSS_UNIT_PX } } },
- { CSS_POS_AUTO, { { 0, CSS_UNIT_PX } } },
- { CSS_POS_AUTO, { { 0, CSS_UNIT_PX } } },
- { CSS_POS_AUTO, { { 0, CSS_UNIT_PX } } } },
- CSS_POSITION_STATIC,
- CSS_TABLE_LAYOUT_AUTO,
- CSS_TEXT_ALIGN_LEFT,
- CSS_TEXT_DECORATION_NONE,
- { CSS_TEXT_INDENT_LENGTH, { { 0, CSS_UNIT_EM } } },
- CSS_TEXT_TRANSFORM_NONE,
- CSS_UNICODE_BIDI_NORMAL,
- { CSS_VERTICAL_ALIGN_BASELINE, { { 0, CSS_UNIT_PX } } },
- CSS_VISIBILITY_VISIBLE,
- CSS_WHITE_SPACE_NORMAL,
- { CSS_WIDOWS_INTEGER, 2 },
- { CSS_WIDTH_AUTO, { { 1, CSS_UNIT_EM } } },
- { CSS_WORD_SPACING_NORMAL, { 0, CSS_UNIT_PX } },
- { CSS_Z_INDEX_AUTO, 0 }
-};
-
-/** Style with no values set. */
-const struct css_style css_empty_style = {
- CSS_BACKGROUND_ATTACHMENT_NOT_SET,
- CSS_COLOR_NOT_SET,
- { CSS_BACKGROUND_IMAGE_NOT_SET, 0 },
- { { CSS_BACKGROUND_POSITION_NOT_SET, { 0.0 } },
- { CSS_BACKGROUND_POSITION_NOT_SET, { 0.0 } } },
- CSS_BACKGROUND_REPEAT_NOT_SET,
- { { CSS_COLOR_NOT_SET, { CSS_BORDER_WIDTH_NOT_SET,
- { 0, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NOT_SET },
- { CSS_COLOR_NOT_SET, { CSS_BORDER_WIDTH_NOT_SET,
- { 0, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NOT_SET },
- { CSS_COLOR_NOT_SET, { CSS_BORDER_WIDTH_NOT_SET,
- { 0, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NOT_SET },
- { CSS_COLOR_NOT_SET, { CSS_BORDER_WIDTH_NOT_SET,
- { 0, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NOT_SET } },
- CSS_BORDER_COLLAPSE_NOT_SET,
- { CSS_BORDER_SPACING_NOT_SET,
- { 0, CSS_UNIT_PX }, { 0, CSS_UNIT_PX } },
- CSS_CAPTION_SIDE_NOT_SET,
- CSS_CLEAR_NOT_SET,
- { CSS_CLIP_NOT_SET, { { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } },
- { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } },
- { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } },
- { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } } } },
- CSS_COLOR_NOT_SET,
- { CSS_CONTENT_NOT_SET, 0 },
- { CSS_COUNTER_RESET_NOT_SET, 0 },
- { CSS_COUNTER_INCREMENT_NOT_SET, 0 },
- CSS_CURSOR_NOT_SET,
- CSS_DIRECTION_NOT_SET,
- CSS_DISPLAY_NOT_SET,
- CSS_EMPTY_CELLS_NOT_SET,
- CSS_FLOAT_NOT_SET,
- CSS_FONT_FAMILY_NOT_SET,
- { CSS_FONT_SIZE_NOT_SET, { { 1, CSS_UNIT_PT } } },
- CSS_FONT_STYLE_NOT_SET,
- CSS_FONT_VARIANT_NOT_SET,
- CSS_FONT_WEIGHT_NOT_SET,
- { CSS_HEIGHT_NOT_SET, { { 1, CSS_UNIT_EM } } },
- { CSS_LETTER_SPACING_NOT_SET, { 0, CSS_UNIT_PX } },
- { CSS_LINE_HEIGHT_NOT_SET, { 1.33 } },
- { CSS_LIST_STYLE_IMAGE_NOT_SET, 0 },
- CSS_LIST_STYLE_POSITION_NOT_SET,
- CSS_LIST_STYLE_TYPE_NOT_SET,
- { { CSS_MARGIN_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_MARGIN_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_MARGIN_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_MARGIN_NOT_SET, { { 0, CSS_UNIT_PX } } } },
- { CSS_MAX_HEIGHT_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_MAX_WIDTH_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_MIN_HEIGHT_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_MIN_WIDTH_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_ORPHANS_NOT_SET, 0 },
- { { CSS_OUTLINE_COLOR_NOT_SET, CSS_COLOR_NOT_SET },
- { CSS_BORDER_WIDTH_NOT_SET, { 0, CSS_UNIT_PX } },
- CSS_BORDER_STYLE_NOT_SET },
- CSS_OVERFLOW_NOT_SET,
- { { CSS_PADDING_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_PADDING_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_PADDING_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_PADDING_NOT_SET, { { 0, CSS_UNIT_PX } } } },
- CSS_PAGE_BREAK_AFTER_NOT_SET,
- CSS_PAGE_BREAK_BEFORE_NOT_SET,
- CSS_PAGE_BREAK_INSIDE_NOT_SET,
- { { CSS_POS_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_POS_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_POS_NOT_SET, { { 0, CSS_UNIT_PX } } },
- { CSS_POS_NOT_SET, { { 0, CSS_UNIT_PX } } } },
- CSS_POSITION_NOT_SET,
- CSS_TABLE_LAYOUT_NOT_SET,
- CSS_TEXT_ALIGN_NOT_SET,
- CSS_TEXT_DECORATION_NOT_SET,
- { CSS_TEXT_INDENT_NOT_SET, { { 0, CSS_UNIT_EM } } },
- CSS_TEXT_TRANSFORM_NOT_SET,
- CSS_UNICODE_BIDI_NOT_SET,
- { CSS_VERTICAL_ALIGN_NOT_SET, { { 0, CSS_UNIT_PX } } },
- CSS_VISIBILITY_NOT_SET,
- CSS_WHITE_SPACE_NOT_SET,
- { CSS_WIDOWS_NOT_SET, 0 },
- { CSS_WIDTH_NOT_SET, { { 1, CSS_UNIT_EM } } },
- { CSS_WORD_SPACING_NOT_SET, { 0, CSS_UNIT_PX } },
- { CSS_Z_INDEX_NOT_SET, 0 }
-};
-
-/** Default style for an element. These should be INHERIT if 'Inherited' is yes,
- * and the 'Initial value' otherwise. */
-const struct css_style css_blank_style = {
- CSS_BACKGROUND_ATTACHMENT_SCROLL,
- NS_TRANSPARENT,
- { CSS_BACKGROUND_IMAGE_NONE, 0 },
- { { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } },
- { CSS_BACKGROUND_POSITION_PERCENT, { 0.0 } } },
- CSS_BACKGROUND_REPEAT_REPEAT,
- { { 0x000000, { CSS_BORDER_WIDTH_LENGTH,
- { 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE },
- { 0x000000, { CSS_BORDER_WIDTH_LENGTH,
- { 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE },
- { 0x000000, { CSS_BORDER_WIDTH_LENGTH,
- { 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE },
- { 0x000000, { CSS_BORDER_WIDTH_LENGTH,
- { 2, CSS_UNIT_PX } }, CSS_BORDER_STYLE_NONE } },
- CSS_BORDER_COLLAPSE_INHERIT,
- { CSS_BORDER_SPACING_INHERIT,
- { 0, CSS_UNIT_PX }, { 0, CSS_UNIT_PX } },
- CSS_CAPTION_SIDE_INHERIT,
- CSS_CLEAR_NONE,
- { CSS_CLIP_AUTO, { { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } },
- { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } },
- { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } },
- { CSS_CLIP_RECT_AUTO, { 0, CSS_UNIT_PX } } } },
- CSS_COLOR_INHERIT,
- { CSS_CONTENT_NORMAL, 0 },
- { CSS_COUNTER_RESET_NONE, 0 },
- { CSS_COUNTER_INCREMENT_NONE, 0 },
- CSS_CURSOR_INHERIT,
- CSS_DIRECTION_INHERIT,
- CSS_DISPLAY_INLINE,
- CSS_EMPTY_CELLS_INHERIT,
- CSS_FLOAT_NONE,
- CSS_FONT_FAMILY_INHERIT,
- { CSS_FONT_SIZE_INHERIT, { { 1, CSS_UNIT_EM } } },
- CSS_FONT_STYLE_INHERIT,
- CSS_FONT_VARIANT_INHERIT,
- CSS_FONT_WEIGHT_INHERIT,
- { CSS_HEIGHT_AUTO, { { 1, CSS_UNIT_EM } } },
- { CSS_LETTER_SPACING_INHERIT, { 0, CSS_UNIT_PX } },
- { CSS_LINE_HEIGHT_INHERIT, { 1.33 } },
- { CSS_LIST_STYLE_IMAGE_INHERIT, 0 },
- CSS_LIST_STYLE_POSITION_INHERIT,
- CSS_LIST_STYLE_TYPE_INHERIT,
- { { CSS_MARGIN_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_MARGIN_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_MARGIN_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_MARGIN_LENGTH, { { 0, CSS_UNIT_PX } } } },
- { CSS_MAX_HEIGHT_NONE, { { 0, CSS_UNIT_PX } } },
- { CSS_MAX_WIDTH_NONE, { { 0, CSS_UNIT_PX } } },
- { CSS_MIN_HEIGHT_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_MIN_WIDTH_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_ORPHANS_INHERIT, 0 },
- { { CSS_OUTLINE_COLOR_INVERT, 0x000000 },
- { CSS_BORDER_WIDTH_LENGTH, { 2, CSS_UNIT_PX } },
- CSS_BORDER_STYLE_NONE },
- CSS_OVERFLOW_VISIBLE,
- { { CSS_PADDING_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_PADDING_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_PADDING_LENGTH, { { 0, CSS_UNIT_PX } } },
- { CSS_PADDING_LENGTH, { { 0, CSS_UNIT_PX } } } },
- CSS_PAGE_BREAK_AFTER_AUTO,
- CSS_PAGE_BREAK_BEFORE_AUTO,
- CSS_PAGE_BREAK_INSIDE_INHERIT,
- { { CSS_POS_AUTO, { { 0, CSS_UNIT_PX } } },
- { CSS_POS_AUTO, { { 0, CSS_UNIT_PX } } },
- { CSS_POS_AUTO, { { 0, CSS_UNIT_PX } } },
- { CSS_POS_AUTO, { { 0, CSS_UNIT_PX } } } },
- CSS_POSITION_STATIC,
- CSS_TABLE_LAYOUT_AUTO,
- CSS_TEXT_ALIGN_INHERIT,
- CSS_TEXT_DECORATION_NONE,
- { CSS_TEXT_INDENT_INHERIT, { { 0, CSS_UNIT_EM } } },
- CSS_TEXT_TRANSFORM_INHERIT,
- CSS_UNICODE_BIDI_NORMAL,
- { CSS_VERTICAL_ALIGN_BASELINE, { { 0, CSS_UNIT_PX } } },
- CSS_VISIBILITY_INHERIT,
- CSS_WHITE_SPACE_INHERIT,
- { CSS_WIDOWS_INHERIT, 0 },
- { CSS_WIDTH_AUTO, { { 1, CSS_UNIT_EM } } },
- { CSS_WORD_SPACING_INHERIT, { 0, CSS_UNIT_PX } },
- { CSS_Z_INDEX_AUTO, 0 }
-};
-
-/** Dots per inch for the display device.
- *
- * This is the number of pixels per inch of the display device.
- * This variable should be treated as constant during the runtime of
- * the program unless the core can be persuaded to re-layout fully
- * on change.
- *
- * We default to 90.0 because RISC OS defaults to 90.0 dpi.
- */
-float css_screen_dpi = 90.0;
-
-/**
- * Convert a CONTENT_CSS for use.
- */
-
-bool css_convert(struct content *c, int width, int height)
-{
- unsigned char *source_data;
- unsigned char *current, *end, *token_text;
- unsigned int i;
- int token;
- void *parser;
- struct css_parser_params param = {false, c, 0, false, false, false};
- struct css_parser_token token_data;
- union content_msg_data msg_data;
-
- /* css_parser_Trace(stderr, "CSS: "); */
-
- c->data.css.css = malloc(sizeof *c->data.css.css);
- parser = css_parser_Alloc(malloc);
- source_data = (unsigned char *) talloc_realloc(c, c->source_data, char,
- c->source_size + 10);
-
- if (!c->data.css.css || !parser || !source_data) {
- free(c->data.css.css);
- css_parser_Free(parser, free);
-
- msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
- }
-
- for (i = 0; i != HASH_SIZE; i++)
- c->data.css.css->rule[i] = 0;
- c->data.css.import_count = 0;
- c->data.css.import_content = 0;
- c->data.css.origin = CSS_ORIGIN_UA;
- c->active = 0;
- c->source_data = (char *) source_data;
-
- for (i = 0; i != 10; i++)
- source_data[c->source_size + i] = 0;
-
- current = source_data;
- end = source_data + c->source_size;
- while (current < end
- && (token = css_tokenise(&current, end + 10,
- &token_text))) {
- token_data.text = (char *) token_text;
- token_data.length = current - token_text;
- css_parser_(parser, token, token_data, &param);
- if (param.syntax_error) {
- LOG(("syntax error near offset %li (%s)",
- (unsigned long) (token_text - source_data),
- c->url));
- param.syntax_error = false;
- } else if (param.memory_error) {
- LOG(("out of memory"));
- break;
- }
- }
-
- css_parser_(parser, 0, token_data, &param);
- css_parser_Free(parser, free);
-
- if (param.memory_error) {
- msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
- }
-
- /*css_dump_stylesheet(c->data.css.css);*/
-
- /* complete fetch of any imported stylesheets */
- while (c->active != 0) {
- fetch_poll();
- gui_multitask();
- }
-
- c->status = CONTENT_STATUS_DONE;
- return true;
-}
-
-
-/**
- * Destroy a CONTENT_CSS and free all resources it owns.
- */
-
-void css_destroy(struct content *c)
-{
- unsigned int i;
- struct css_selector *r;
-
- if (c->data.css.css) {
- for (i = 0; i != HASH_SIZE; i++) {
- for (r = c->data.css.css->rule[i]; r != 0;
- r = r->next) {
- css_deep_free_style(r->style);
- }
- css_free_selector(c->data.css.css->rule[i]);
- }
- free(c->data.css.css);
- }
-
- /* imported stylesheets */
- for (i = 0; i != c->data.css.import_count; i++)
- if (c->data.css.import_content[i] != 0) {
- content_remove_user(c->data.css.import_content[i],
- css_atimport_callback, (intptr_t) c, i);
- }
- free(c->data.css.import_content);
-}
-
-
-/**
- * Set the origin of a stylesheet.
- *
- * \param c content of type CONTENT_CSS
- * \param origin new origin
- *
- * This may only be called once per stylesheet.
- */
-
-void css_set_origin(struct content *c, css_origin origin)
-{
- unsigned int chain, i;
- unsigned long specificity = 0;
- struct css_selector *selector;
-
- assert(c->type == CONTENT_CSS);
-
- if (origin == c->data.css.origin)
- return;
-
- switch (origin)
- {
- case CSS_ORIGIN_AUTHOR: specificity = CSS_SPECIFICITY_AUTHOR; break;
- case CSS_ORIGIN_USER: specificity = CSS_SPECIFICITY_USER; break;
- case CSS_ORIGIN_UA: specificity = CSS_SPECIFICITY_UA; break;
- }
-
- for (chain = 0; chain != HASH_SIZE; chain++)
- for (selector = c->data.css.css->rule[chain];
- selector;
- selector = selector->next)
- selector->specificity += specificity;
- c->data.css.origin = origin;
-
- for (i = 0; i != c->data.css.import_count; i++)
- if (c->data.css.import_content[i])
- css_set_origin(c->data.css.import_content[i], origin);
-}
-
-
-/**
- * Duplicate a CSS style struct.
- *
- * \param style The style to duplicate
- * \return The duplicate style, or NULL if out of memory.
- */
-
-struct css_style *css_duplicate_style(const struct css_style * const style)
-{
- struct css_style *dup;
-
- assert(style);
-
- /* create duplicated style */
- dup = malloc(sizeof (struct css_style));
- if (!dup)
- return NULL;
-
- /* copy all style information into duplicate style */
- memcpy(dup, style, sizeof(struct css_style));
-
- return dup;
-}
-
-
-/**
- * Free a CSS style.
- *
- * \param style The style to free
- */
-
-void css_free_style(struct css_style *style)
-{
- assert(style);
-
- free(style);
-}
-
-
-/**
- * Free a CSS style, deleting all alloced elements.
- *
- * \param style The style to free
- */
-
-void css_deep_free_style(struct css_style *style)
-{
- assert(style);
-
- if (style->background_image.type == CSS_BACKGROUND_IMAGE_URI)
- free(style->background_image.uri);
-
- if (style->list_style_image.type == CSS_LIST_STYLE_IMAGE_URI)
- free(style->list_style_image.uri);
-
- if (style->content.type == CSS_CONTENT_INTERPRET)
- css_deep_free_content(style->content.content);
-
- if (style->counter_reset.type == CSS_COUNTER_RESET_INTERPRET)
- css_deep_free_counter_control(style->counter_reset.data);
-
- if (style->counter_increment.type == CSS_COUNTER_INCREMENT_INTERPRET)
- css_deep_free_counter_control(style->counter_increment.data);
-
- free(style);
-}
-
-
-/**
- * Free all auto-generated content data.
- *
- * \param content the auto-generated content data to free
- */
-
-void css_deep_free_content(struct css_content *content)
-{
- struct css_content *next;
-
- while (content) {
- next = content->next;
- switch (content->type) {
- case CSS_CONTENT_STRING:
- free(content->data.string);
- break;
- case CSS_CONTENT_URI:
- free(content->data.uri);
- break;
- case CSS_CONTENT_COUNTER:
- free(content->data.counter.name);
- free(content->data.counter.separator);
- break;
- case CSS_CONTENT_ATTR:
- free(content->data.attr);
- break;
- case CSS_CONTENT_OPEN_QUOTE:
- case CSS_CONTENT_CLOSE_QUOTE:
- case CSS_CONTENT_NO_OPEN_QUOTE:
- case CSS_CONTENT_NO_CLOSE_QUOTE:
- break;
- }
- free(content);
- content = next;
- }
-}
-
/**
- * Free all counter control data.
+ * Allocation callback for libcss
*
- * \param counter the counter control data to free
+ * \param ptr Pointer to reallocate, or NULL for new allocation
+ * \param size Number of bytes requires
+ * \param pw Allocation context
+ * \return Pointer to allocated block, or NULL on failure
*/
-
-void css_deep_free_counter_control(struct css_counter_control *control)
-{
- struct css_counter_control *next;
-
- while (control) {
- next = control->next;
- free(control->name);
- free(control);
- control = next;
- }
-}
-
-
-/**
- * Create a new struct css_node.
- *
- * \param stylesheet content of type CONTENT_CSS
- * \param type type of node
- * \param data string for data, not copied
- * \param data_length length of data
- * \return allocated node, or 0 if memory exhausted
- *
- * Used by the parser.
- */
-
-struct css_node * css_new_node(struct content *stylesheet,
- css_node_type type,
- const char *data, unsigned int data_length)
-{
- struct css_node *node = malloc(sizeof *node);
- if (!node)
- return 0;
- node->type = type;
- node->data = data;
- node->data_length = data_length;
- node->value = 0;
- node->next = 0;
- node->comb = CSS_COMB_NONE;
- node->style = 0;
- node->specificity = 0;
- node->stylesheet = stylesheet;
-
- return node;
-}
-
-
-/**
- * Free a struct css_node recursively.
- *
- * \param node css_node to free
- *
- * Used by the parser.
- */
-
-void css_free_node(struct css_node *node)
+static void *myrealloc(void *ptr, size_t size, void *pw)
{
- if (!node)
- return;
- if (node->value)
- css_free_node(node->value);
- if (node->next)
- css_free_node(node->next);
- free(node);
+ return realloc(ptr, size);
}
-
/**
- * Create a new struct css_selector.
+ * Initialise a CSS content
*
- * \param type type of selector
- * \param data string for data, not copied
- * \param data_length length of data
- * \return allocated selector, or 0 if memory exhausted
+ * \param c Content to initialise
+ * \param parent Parent content, or NULL if top-level
+ * \param params Content-Type parameters
+ * \return true on success, false on failure
*/
-
-struct css_selector * css_new_selector(css_selector_type type,
- const char *data, unsigned int data_length)
+bool nscss_create(struct content *c, struct content *parent,
+ const char *params[])
{
- struct css_selector *node = malloc(sizeof *node);
- if (!node)
- return 0;
- node->type = type;
- node->data = data;
- node->data_length = data_length;
- node->data2 = 0;
- node->detail = 0;
- node->combiner = 0;
- node->next = 0;
- node->comb = CSS_COMB_NONE;
- node->style = 0;
- node->specificity = 0;
- return node;
-}
+ css_origin origin = CSS_ORIGIN_AUTHOR;
+ css_media_type media = CSS_MEDIA_ALL;
+ lwc_context *dict = NULL;
+ bool quirks = true;
+ css_error error;
+ /** \todo extract charset from params */
+ /** \todo what happens about the allocator? */
-/**
- * Free a struct css_selector recursively.
- *
- * \param node css_selector to free
- */
+ if (parent != NULL) {
+ assert(parent->type == CONTENT_HTML ||
+ parent->type == CONTENT_CSS);
-void css_free_selector(struct css_selector *node)
-{
- if (!node)
- return;
- if (node->detail)
- css_free_selector(node->detail);
- if (node->combiner)
- css_free_selector(node->combiner);
- if (node->next)
- css_free_selector(node->next);
- free(node);
-}
-
-
-/**
- * Process an \@import rule.
- */
+ if (parent->type == CONTENT_HTML) {
+ assert(parent->data.html.dict != NULL);
-void css_atimport(struct content *c, struct css_node *node)
-{
- const char *s;
- char *t, *url, *url1;
- bool string = false, screen = true;
- unsigned int i;
- struct content **import_content;
- url_func_result res;
+ if (c == parent->data.html.
+ stylesheet_content[STYLESHEET_BASE] ||
+ c == parent->data.html.
+ stylesheet_content[STYLESHEET_QUIRKS] ||
+ c == parent->data.html.
+ stylesheet_content[STYLESHEET_ADBLOCK])
+ origin = CSS_ORIGIN_UA;
- LOG(("@import rule"));
+ /** \todo media types */
- import_content = realloc(c->data.css.import_content,
- (c->data.css.import_count + 1) *
- sizeof(*c->data.css.import_content));
- if (!import_content) {
- /** \todo report to user */
- return;
- }
- c->data.css.import_content = import_content;
+ quirks = (parent->data.html.quirks !=
+ BINDING_QUIRKS_MODE_NONE);
- /* uri(...) or "..." */
- switch (node->type) {
- case CSS_NODE_URI:
- LOG(("URI '%.*s'", node->data_length, node->data));
- for (s = node->data + 4;
- *s == ' ' || *s == '\t' || *s == '\r' ||
- *s == '\n' || *s == '\f';
- s++)
- ;
- if (*s == '\'' || *s == '"') {
- string = true;
- s++;
- }
- url = strndup(s, node->data_length - (s - node->data));
- if (!url) {
- /** \todo report to user */
- return;
- }
- for (t = url + strlen(url) - 2;
- *t == ' ' || *t == '\t' || *t == '\r' ||
- *t == '\n' || *t == '\f';
- t--)
- ;
- if (string)
- *t = 0;
- else
- *(t + 1) = 0;
- break;
- case CSS_NODE_STRING:
- LOG(("STRING '%.*s'", node->data_length, node->data));
- url = strndup(node->data, node->data_length);
- if (!url) {
- /** \todo report to user */
- return;
- }
- break;
- default:
- return;
- }
+ dict = parent->data.html.dict;
+ } else {
+ assert(parent->data.css.sheet != NULL);
+ assert(parent->data.css.dict != NULL);
- /* media not specified, 'screen', or 'all' */
- for (node = node->next; node != 0; node = node->next) {
- screen = false;
- if (node->type != CSS_NODE_IDENT) {
- free(url);
- return;
- }
- LOG(("medium '%s'", node->data));
- if ((node->data_length == 6 &&
- strncmp(node->data, "screen", 6) == 0) ||
- (node->data_length == 3 &&
- strncmp(node->data, "all", 3) == 0)) {
- screen = true;
- break;
- }
- node = node->next;
- if (node == 0 || node->type != CSS_NODE_COMMA) {
- free(url);
- return;
- }
- }
- if (!screen) {
- free(url);
- return;
- }
-
- /* Make URL absolute */
- res = url_join(url, c->url, &url1);
- if (res != URL_FUNC_OK) {
- free(url);
- return;
- }
-
- /* Destroy raw url data */
- free(url);
-
- /* URL must be normalized */
- res = url_normalize(url1, &url);
- if (res != URL_FUNC_OK) {
- free(url1);
- return;
- }
-
- /* Destroy non-normalized data */
- free(url1);
-
- /* start the fetch */
- c->data.css.import_count++;
- i = c->data.css.import_count - 1;
- c->data.css.import_content[i] = fetchcache(url,
- css_atimport_callback, (intptr_t) c, i,
- c->width, c->height, true, 0, 0, false, false);
- if (c->data.css.import_content[i]) {
- c->active++;
- fetchcache_go(c->data.css.import_content[i], c->url,
- css_atimport_callback, (intptr_t) c, i,
- c->width, c->height,
- 0, 0, false, c);
- }
-
- free(url);
-}
-
-
-/**
- * Fetchcache callback for imported stylesheets.
- */
-
-void css_atimport_callback(content_msg msg, struct content *css,
- intptr_t p1, intptr_t p2, union content_msg_data data)
-{
- struct content *c = (struct content *) p1;
- unsigned int i = p2;
-
- switch (msg) {
- case CONTENT_MSG_LOADING:
- if (css->type != CONTENT_CSS) {
- content_remove_user(css, css_atimport_callback,
- (intptr_t) c, i);
- if (!css->user_list->next) {
- /* We were only user and we don't
- * want this content, so stop it
- * fetching and mark it as having
- * an error so it gets removed from
- * the cache next time
- * content_clean() gets called */
- fetch_abort(css->fetch);
- css->fetch = 0;
- css->status = CONTENT_STATUS_ERROR;
- }
- c->data.css.import_content[i] = 0;
- c->active--;
- content_add_error(c, "NotCSS", 0);
- }
- break;
-
- case CONTENT_MSG_READY:
- break;
-
- case CONTENT_MSG_DONE:
- LOG(("got imported stylesheet '%s'", css->url));
- /*css_dump_stylesheet(css->data.css);*/
- c->active--;
- break;
-
- case CONTENT_MSG_AUTH:
- case CONTENT_MSG_SSL:
- /* todo: handle AUTH and SSL */
- case CONTENT_MSG_LAUNCH:
- /* Fall through */
- case CONTENT_MSG_ERROR:
- /* The stylesheet we were fetching may have been
- * redirected, in that case, the object pointers
- * will differ, so ensure that the object that's
- * in error is still in use by us before invalidating
- * the pointer */
- if (c->data.css.import_content[i] == css) {
- c->data.css.import_content[i] = 0;
- c->active--;
- content_add_error(c, "?", 0);
- }
- break;
-
- case CONTENT_MSG_STATUS:
- break;
-
- case CONTENT_MSG_NEWPTR:
- c->data.css.import_content[i] = css;
- break;
-
- default:
- assert(0);
- }
-}
-
-
-/**
- * Prepare a working stylesheet with pre-sorted lists of selectors from an
- * array of stylesheets.
- *
- * \param stylesheet_content array of contents of type CONTENT_CSS (each may
- * be 0)
- * \param stylesheet_count number of entries in css
- * \return working stylesheet, or 0 on memory exhaustion
- *
- * See CSS 2.1 6.4.
- */
-
-struct css_working_stylesheet *css_make_working_stylesheet(
- struct content **stylesheet_content,
- unsigned int stylesheet_count)
-{
- struct content **css = 0;
- unsigned int css_count = 0;
- struct css_working_stylesheet *working_stylesheet;
- unsigned int chain;
- struct css_selector **rule_scratch;
-
- working_stylesheet = talloc(0, struct css_working_stylesheet);
- if (!working_stylesheet)
- return 0;
+ error = css_stylesheet_get_origin(
+ parent->data.css.sheet, &origin);
+ if (error != CSS_OK)
+ return false;
- /* make a complete list of stylesheets involved by walking @imports */
- css_working_list_imports(stylesheet_content, stylesheet_count,
- &css, &css_count);
+ error = css_stylesheet_quirks_allowed(
+ parent->data.css.sheet, &quirks);
+ if (error != CSS_OK)
+ return false;
- rule_scratch = talloc_array(working_stylesheet, struct css_selector *,
- css_count);
- if (!rule_scratch) {
- free(css);
- talloc_free(working_stylesheet);
- return 0;
- }
+ /** \todo media types */
- /* merge the corresponding sorted hash chains from each stylesheet */
- for (chain = 0; chain != HASH_SIZE; chain++) {
- if (!css_working_merge_chains(working_stylesheet, css,
- css_count, chain, rule_scratch)) {
- free(css);
- talloc_free(working_stylesheet);
- return 0;
+ dict = parent->data.css.dict;
}
}
- free(css);
- talloc_free(rule_scratch);
-
-#ifdef DEBUG_WORKING_STYLESHEET
- css_dump_working_stylesheet(working_stylesheet);
-#endif
-
- return working_stylesheet;
-}
-
-
-/**
- * Recursively make a list of stylesheets and their imports.
- *
- * \param import array of contents of type CONTENT_CSS
- * \param import_count number of elements in import
- * \param css pointer to array of contents for result
- * \param css_count number of elements used so far in *css
- */
+ if (dict == NULL) {
+ lwc_error lerror = lwc_create_context(myrealloc, NULL, &dict);
-bool css_working_list_imports(struct content **import,
- unsigned int import_count,
- struct content ***css, unsigned int *css_count)
-{
- unsigned int i, j;
- struct content **css2;
- for (i = 0; i != import_count; i++) {
- if (!import[i])
- continue;
- /* search for import[i] in css[0..css_count) */
- for (j = 0; j != *css_count && (*css)[j] != import[i]; j++)
- ;
- if (j != *css_count)
- /* we've seen this stylesheet already */
- continue;
- /* recurse into imports of import[i] */
- if (!css_working_list_imports(import[i]->data.css.
- import_content,
- import[i]->data.css.import_count,
- css, css_count))
+ if (lerror != lwc_error_ok)
return false;
- css2 = realloc(*css, sizeof *css * (*css_count + 1));
- if (!css2)
- return false;
- *css = css2;
- (*css)[*css_count] = import[i];
- (*css_count)++;
}
- return true;
-}
-
-
-/**
- * Merge hash chains of rules into an array of pointers ordered by specificity.
- *
- * \param working_stylesheet working stylesheet to add array to
- * \param css array of contents of type CONTENT_CSS
- * \param css_count number of elements in css
- * \param chain hash chain index to merge
- * \param rule scratch array of css_selector with css_count entries
- * \return true on success, false if memory exhausted
- */
-bool css_working_merge_chains(struct css_working_stylesheet *working_stylesheet,
- struct content **css, unsigned int css_count,
- unsigned int chain,
- struct css_selector **rule)
-{
- unsigned int sheet, rules, rules_done = 0;
- struct css_selector *selector;
- unsigned int best = 0;
- unsigned long min;
-
- /* count total rules */
- rules = 0;
- for (sheet = 0; sheet != css_count; sheet++)
- for (selector = css[sheet]->data.css.css->rule[chain];
- selector;
- selector = selector->next)
- rules++;
- working_stylesheet->rule[chain] = talloc_array(working_stylesheet,
- struct css_selector *, rules + 1);
- if (!working_stylesheet->rule[chain])
+ c->data.css.dict = lwc_context_ref(dict);
+ c->data.css.import_count = 0;
+ c->data.css.imports = NULL;
+
+ error = css_stylesheet_create(CSS_LEVEL_21, NULL,
+ c->url, NULL, origin, media, quirks, false,
+ c->data.css.dict,
+ myrealloc, NULL,
+ nscss_resolve_url, NULL,
+ &c->data.css.sheet);
+ if (error != CSS_OK) {
+ lwc_context_unref(c->data.css.dict);
+ c->data.css.dict = NULL;
return false;
-
- /* mergesort by specificity (increasing) */
- for (sheet = 0; sheet != css_count; sheet++) {
- rule[sheet] = 0;
- rule[sheet] = css[sheet]->data.css.css->rule[chain];
}
- for (; rules_done != rules; rules_done++) {
- /* find rule with lowest specificity */
- min = ULONG_MAX;
- for (sheet = 0; sheet != css_count; sheet++) {
- if (rule[sheet] && rule[sheet]->specificity < min) {
- min = rule[sheet]->specificity;
- best = sheet;
- }
- }
- assert(min != ULONG_MAX);
- working_stylesheet->rule[chain][rules_done] = rule[best];
- rule[best] = rule[best]->next;
- }
- assert(rules_done == rules);
- working_stylesheet->rule[chain][rules] = 0;
return true;
}
-
/**
- * Find the style which applies to an element.
- *
- * \param working_stylesheet working stylesheet
- * \param element element in xml tree to match
- * \param style style to update
- * \pram author updated to indicate properties with author level css
- * importance
+ * Process CSS source data
*
- * The style is updated with any rules that match the element.
+ * \param c Content structure
+ * \param data Data to process
+ * \param size Number of bytes to process
+ * \return true on success, false on failure
*/
-
-void css_get_style(struct css_working_stylesheet *working_stylesheet,
- xmlNode *element, struct css_style *style,
- struct css_importance *author)
+bool nscss_process_data(struct content *c, char *data, unsigned int size)
{
- unsigned int hash, rule_0 = 0, rule_h = 0;
- struct css_selector *rule;
- css_importance_reset(author); /* initialise to sub-author level */
-
- hash = css_hash((const char *) element->name,
- strlen((const char *) element->name));
+ css_error error;
- /* merge sort rules from special hash chain 0 (universal selector) and
- * rules from hash chain for element name */
- while (working_stylesheet->rule[0] &&
- working_stylesheet->rule[0][rule_0] &&
- working_stylesheet->rule[hash] &&
- working_stylesheet->rule[hash][rule_h]) {
- if (working_stylesheet->rule[0][rule_0]->specificity <
- working_stylesheet->rule[hash][rule_h]->
- specificity) {
- rule = working_stylesheet->rule[0][rule_0];
- rule_0++;
- } else {
- rule = working_stylesheet->rule[hash][rule_h];
- rule_h++;
- }
- if (css_match_rule(rule, element))
- css_merge(style, rule->style, rule->specificity,
- author);
- }
-
- /* remaining rules from hash chain 0 */
- while (working_stylesheet->rule[0] &&
- working_stylesheet->rule[0][rule_0]) {
- rule = working_stylesheet->rule[0][rule_0];
- rule_0++;
- if (css_match_rule(rule, element))
- css_merge(style, rule->style, rule->specificity,
- author);
- }
+ error = css_stylesheet_append_data(c->data.css.sheet,
+ (const uint8_t *) data, size);
- /* remaining rules from hash chain for element name */
- while (working_stylesheet->rule[hash] &&
- working_stylesheet->rule[hash][rule_h]) {
- rule = working_stylesheet->rule[hash][rule_h];
- rule_h++;
- if (css_match_rule(rule, element))
- css_merge(style, rule->style, rule->specificity,
- author);
- }
+ return (error == CSS_OK || error == CSS_NEEDDATA);
}
-
/**
- * Determine if a rule applies to an element.
- */
-
-bool css_match_rule(struct css_selector *rule, xmlNode *element)
-{
- struct css_selector *detail;
- xmlNode *anc, *prev;
-
- assert(element->type == XML_ELEMENT_NODE);
-
- if (rule->data && (rule->data_length !=
- strlen((const char *) element->name) ||
- strncasecmp(rule->data, (const char *) element->name,
- rule->data_length) != 0))
- return false;
-
- for (detail = rule->detail; detail; detail = detail->next) {
- if (!css_match_detail(detail, element))
- return false;
- }
-
- if (!rule->combiner)
- return true;
-
- switch (rule->comb) {
- case CSS_COMB_ANCESTOR:
- for (anc = element->parent; anc; anc = anc->parent)
- if (anc->type == XML_ELEMENT_NODE &&
- css_match_rule(rule->combiner, anc))
- return true;
- break;
-
- case CSS_COMB_PRECEDED:
- for (prev = element->prev;
- prev && prev->type != XML_ELEMENT_NODE;
- prev = prev->prev)
- ;
- if (!prev)
- return false;
- return css_match_rule(rule->combiner, prev);
- break;
-
- case CSS_COMB_PARENT:
- for (anc = element->parent;
- anc && anc->type != XML_ELEMENT_NODE;
- anc = anc->parent)
- ;
- if (!anc)
- return false;
- return css_match_rule(rule->combiner, anc);
- break;
-
- default:
- assert(0);
- }
-
- return false;
-}
-
-
-/**
- * Determine if a selector detail matches an element.
+ * Convert a CSS content ready for use
*
- * \param detail a css_selector of type other than CSS_SELECTOR_ELEMENT
- * \param element element in xml tree to match
- * \return true if the selector matches the element
+ * \param c Content to convert
+ * \param w Width of area content will be displayed in
+ * \param h Height of area content will be displayed in
+ * \return true on success, false on failure
*/
-
-bool css_match_detail(const struct css_selector *detail,
- xmlNode *element)
+bool nscss_convert(struct content *c, int w, int h)
{
- bool match = false;
- char *s = 0;
- char *space, *word;
- size_t length;
-
- switch (detail->type) {
- case CSS_SELECTOR_ID:
- s = (char *) xmlGetProp(element,
- (const xmlChar *) "id");
- /* case sensitive, according to HTML4.01 */
- if (s && strlen(s) == detail->data_length &&
- strncmp(detail->data, s,
- detail->data_length) == 0)
- match = true;
- break;
-
- case CSS_SELECTOR_CLASS:
- s = (char *) xmlGetProp(element,
- (const xmlChar *) "class");
- if (!s)
- break;
- word = s;
- do {
- space = strchr(word, ' ');
- if (space)
- length = space - word;
- else
- length = strlen(word);
- /* case sensitive, according to HTML4.01 */
- if (length == detail->data_length &&
- strncmp(word, detail->data,
- length) == 0) {
- match = true;
- break;
- }
- word = space + 1;
- } while (space);
- break;
-
- case CSS_SELECTOR_ATTRIB:
- /* matches if an attribute is present */
- word = strndup(detail->data, detail->data_length);
- if (!word) {
- /** \todo report to user */
- return false;
- }
- s = (char *) xmlGetProp(element,
- (const xmlChar *) word);
- free(word);
- if (s)
- match = true;
- break;
-
- case CSS_SELECTOR_ATTRIB_EQ:
- /* matches if an attribute has a certain value*/
- word = strndup(detail->data, detail->data_length);
- if (!word) {
- /** \todo report to user */
- return false;
- }
- s = (char *) xmlGetProp(element,
- (const xmlChar *) word);
- free(word);
- if (s && strlen(s) == detail->data2_length &&
- strncasecmp(detail->data2, s,
- detail->data2_length) == 0)
- match = true;
- break;
+ css_error error;
- case CSS_SELECTOR_ATTRIB_INC:
- /* matches if one of the space separated words
- * in the attribute is equal */
- word = strndup(detail->data,
- detail->data_length);
- if (!word) {
- /** \todo report to user */
- return false;
- }
- s = (char *) xmlGetProp(element,
- (const xmlChar *) word);
- free(word);
- if (!s)
- break;
- word = s;
- do {
- space = strchr(word, ' ');
- if (space)
- length = space - word;
- else
- length = strlen(word);
- if (length == detail->data2_length &&
- strncasecmp(word, detail->data2,
- length) == 0) {
- match = true;
- break;
- }
- word = space + 1;
- } while (space);
- break;
-
- case CSS_SELECTOR_ATTRIB_DM:
- /* matches if a prefix up to a hyphen matches */
- word = strndup(detail->data,
- detail->data_length);
- if (!word) {
- /** \todo report to user */
- return false;
- }
- s = (char *) xmlGetProp(element,
- (const xmlChar *) word);
- free(word);
- if (!s)
- break;
- length = detail->data2_length;
- if (strncasecmp(detail->data2, s, length) == 0 &&
- (s[length] == '-' || s[length] == 0))
- match = true;
- break;
-
- case CSS_SELECTOR_ATTRIB_PRE:
- /* matches if the attribute begins with a certain
- * value (CSS3) */
- word = strndup(detail->data, detail->data_length);
- if (!word) {
- /** \todo report to user */
- return false;
- }
- s = (char *)xmlGetProp(element,
- (const xmlChar *) word);
- free(word);
- if (s && strncasecmp(detail->data2, s,
- detail->data2_length) == 0)
- match = true;
- break;
+ error = css_stylesheet_data_done(c->data.css.sheet);
- case CSS_SELECTOR_ATTRIB_SUF:
- /* matches if the attribute ends with a certain
- * value (CSS3) */
- word = strndup(detail->data, detail->data_length);
- if (!word) {
- /** \todo report to user */
- return false;
- }
- s = (char *)xmlGetProp(element,
- (const xmlChar *) word);
- free(word);
- if (!s)
- break;
- length = strlen(s);
- if (detail->data2_length <= length) {
- word = s + (length - detail->data2_length);
- if (s && strncasecmp(detail->data2, word,
- detail->data2_length) == 0)
- match = true;
- }
- break;
-
- case CSS_SELECTOR_ATTRIB_SUB:
- /* matches if the attribute contains a certain
- * value (CSS3) */
- word = strndup(detail->data, detail->data_length);
- if (!word) {
- /** \todo report to user */
- return false;
- }
- s = (char *)xmlGetProp(element,
- (const xmlChar *) word);
- free(word);
- if (!s)
- break;
- /* case insensitive strstr follows */
- /* space -> last possible start position */
- /* word -> start of string to search */
- space = s + (strlen(s) - detail->data2_length);
- word = s;
- while (word <= space) {
- if (strncasecmp(detail->data2, word,
- detail->data2_length) == 0) {
- match = true;
- break;
- }
- word++;
- }
- break;
-
- case CSS_SELECTOR_PSEUDO:
- if (detail->data_length == 11 &&
- strncasecmp(detail->data,
- "first-child", 11) == 0) {
- match = css_match_first_child(detail,
- element);
- }
- break;
-
- default:
- assert(0);
- }
-
- if (s)
- xmlFree(s);
-
- return match;
-}
-
-
-/**
- * Handle :first-child pseudo-class.
- *
- * \param detail a css_selector of type other than CSS_SELECTOR_ELEMENT
- * \param element element in xml tree to match
- * \return true if the selector matches the element
- */
-
-bool css_match_first_child(const struct css_selector *detail,
- xmlNode *element)
-{
- xmlNode *prev;
-
- for (prev = element->prev; prev && prev->type != XML_ELEMENT_NODE;
- prev = prev->prev)
- ;
-
- if (!prev)
- return true;
-
- return false;
-}
-
-
-/**
- * Parse a stand-alone CSS property list.
- *
- * \param c parent content
- * \param style css_style to update
- * \param str property list, as found in HTML style attributes
- */
-
-void css_parse_property_list(struct content *c, struct css_style * style,
- char * str)
-{
- unsigned char *source_data;
- unsigned char *current, *end, *token_text;
- size_t length;
- unsigned int i;
- int token;
- void *parser;
- struct css_parser_params param = {true, c, 0, false, false, false};
- struct css_parser_token token_data;
- const struct css_parser_token token_start = { "{", 1 };
- const struct css_parser_token token_end = { "}", 1 };
-
- length = strlen(str);
-
- parser = css_parser_Alloc(malloc);
- source_data = malloc(length + 10);
-
- if (!parser || !source_data) {
- free(parser);
- css_parser_Free(parser, free);
- return;
- }
-
- strcpy((char *) source_data, str);
- for (i = 0; i != 10; i++)
- source_data[length + i] = 0;
-
- css_parser_(parser, LBRACE, token_start, &param);
-
- current = source_data;
- end = source_data + strlen(str);
- while (current < end
- && (token = css_tokenise(&current, end + 10,
- &token_text))) {
- token_data.text = (char *) token_text;
- token_data.length = current - token_text;
- css_parser_(parser, token, token_data, &param);
- if (param.syntax_error) {
- LOG(("syntax error near offset %li",
- (unsigned long) (token_text - source_data)));
- param.syntax_error = false;
- } else if (param.memory_error) {
- LOG(("out of memory"));
- break;
- }
- }
- css_parser_(parser, RBRACE, token_end, &param);
- css_parser_(parser, 0, token_data, &param);
-
- css_parser_Free(parser, free);
-
- if (param.memory_error) {
- css_free_node(param.declaration);
- return;
- }
-
- css_add_declarations(style, param.declaration);
-
- css_free_node(param.declaration);
-
- free(source_data);
-}
-
-
-/**
- * Dump a css_style to stderr in CSS-like syntax.
- */
-
-void css_dump_style(FILE *stream, const struct css_style * const style)
-{
- unsigned int i;
- fprintf(stream, "{ ");
-
-#define DUMP_COLOR(z, s) \
- if (style->z != CSS_COLOR_NOT_SET) { \
- if (style->z == NS_TRANSPARENT) \
- fprintf(stream, s ": transparent; "); \
- else if (style->z == CSS_COLOR_NONE) \
- fprintf(stream, s ": none; "); \
- else \
- fprintf(stream, s ": #%.6x; ", style->z); \
- }
-
-#define DUMP_KEYWORD(z, s, n) \
- if (style->z != css_empty_style.z) \
- fprintf(stream, s ": %s; ", n[style->z]);
-
- DUMP_COLOR(background_color, "background-color");
- if (style->background_attachment !=
- css_empty_style.background_attachment ||
- style->background_image.type !=
- css_empty_style.background_image.type ||
- style->background_position.horz.pos !=
- css_empty_style.background_position.horz.pos ||
- style->background_position.vert.pos !=
- css_empty_style.background_position.vert.pos ||
- style->background_repeat !=
- css_empty_style.background_repeat) {
- fprintf(stream, "background:");
- switch (style->background_image.type) {
- case CSS_BACKGROUND_IMAGE_NONE:
- fprintf(stream, " none");
- break;
- case CSS_BACKGROUND_IMAGE_INHERIT:
- fprintf(stream, " inherit");
- break;
- case CSS_BACKGROUND_IMAGE_URI:
- fprintf(stream, " (%p) \"%s\"",
- style->background_image.uri,
- style->background_image.uri);
- break;
- case CSS_BACKGROUND_IMAGE_NOT_SET:
- ;
- break;
- default:
- fprintf(stream, " UNKNOWN");
- break;
- }
-
- if (style->background_repeat ==
- CSS_BACKGROUND_REPEAT_UNKNOWN)
- fprintf(stream, " UNKNOWN");
- else if (style->background_repeat ==
- CSS_BACKGROUND_REPEAT_NOT_SET)
- ;
- else
- fprintf(stream, " %s",
- css_background_repeat_name[
- style->background_repeat]);
-
- if (style->background_attachment ==
- CSS_BACKGROUND_ATTACHMENT_UNKNOWN)
- fprintf(stream, " UNKNOWN");
- else if (style->background_attachment == CSS_BACKGROUND_ATTACHMENT_NOT_SET)
- ;
- else
- fprintf(stream, " %s",
- css_background_attachment_name[
- style->background_attachment]);
-
- switch (style->background_position.horz.pos) {
- case CSS_BACKGROUND_POSITION_LENGTH:
- fprintf(stream, " ");
- css_dump_length(stream, &style->background_position.
- horz.value.length);
- break;
- case CSS_BACKGROUND_POSITION_PERCENT:
- fprintf(stream, " %g%%",
- style->background_position.
- horz.value.percent);
- break;
- case CSS_BACKGROUND_POSITION_INHERIT:
- fprintf(stream, " inherit");
- break;
- case CSS_BACKGROUND_POSITION_NOT_SET:
- break;
- default:
- fprintf(stream, " UNKNOWN");
- break;
- }
- switch (style->background_position.vert.pos) {
- case CSS_BACKGROUND_POSITION_LENGTH:
- fprintf(stream, " ");
- css_dump_length(stream, &style->background_position.
- vert.value.length);
- break;
- case CSS_BACKGROUND_POSITION_PERCENT:
- fprintf(stream, " %g%%",
- style->background_position.
- vert.value.percent);
- break;
- case CSS_BACKGROUND_POSITION_INHERIT:
- fprintf(stream, " inherit");
- break;
- case CSS_BACKGROUND_POSITION_NOT_SET:
- break;
- default:
- fprintf(stream, " UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
- for (i = 0; i != 4; i++) {
- if (style->border[i].color != CSS_COLOR_NOT_SET ||
- style->border[i].width.width !=
- CSS_BORDER_WIDTH_NOT_SET ||
- style->border[i].style !=
- CSS_BORDER_STYLE_NOT_SET) {
- fprintf(stream, "border-");
- switch (i) {
- case TOP:
- fprintf(stream, "top:");
- break;
- case RIGHT:
- fprintf(stream, "right:");
- break;
- case BOTTOM:
- fprintf(stream, "bottom:");
- break;
- case LEFT:
- fprintf(stream, "left:");
- break;
- }
- switch (style->border[i].width.width) {
- case CSS_BORDER_WIDTH_INHERIT:
- fprintf(stream, " inherit");
- break;
- case CSS_BORDER_WIDTH_LENGTH:
- fprintf(stream, " ");
- css_dump_length(stream,
- &style->border[i].width.value);
- break;
- case CSS_BORDER_WIDTH_NOT_SET:
- break;
- default:
- fprintf(stream, " UNKNOWN");
- break;
- }
-
- if (style->border[i].style ==
- CSS_BORDER_STYLE_UNKNOWN)
- fprintf(stream, " UNKNOWN");
- else if (style->border[i].style ==
- CSS_BORDER_STYLE_NOT_SET)
- ;
- else
- fprintf(stream, " %s",
- css_border_style_name[
- style->border[i].style]);
-
- if (style->border[i].color == NS_TRANSPARENT)
- fprintf(stream, " transparent");
- else if (style->border[i].color == CSS_COLOR_NONE)
- fprintf(stream, " none");
- else if (style->border[i].color == CSS_COLOR_INHERIT)
- fprintf(stream, " inherit");
- else if (style->border[i].color == CSS_COLOR_NOT_SET)
- ;
- else
- fprintf(stream, " #%.6x",
- style->border[i].color);
- fprintf(stream, "; ");
- }
- }
- DUMP_KEYWORD(border_collapse, "border-collapse",
- css_border_collapse_name);
- if (style->border_spacing.border_spacing !=
- CSS_BORDER_SPACING_NOT_SET) {
- fprintf(stream, "border-spacing: ");
- css_dump_length(stream, &style->border_spacing.horz);
- fprintf(stream, " ");
- css_dump_length(stream, &style->border_spacing.vert);
- fprintf(stream, "; ");
- }
-
- DUMP_KEYWORD(caption_side, "caption-side", css_caption_side_name);
- DUMP_KEYWORD(clear, "clear", css_clear_name);
-
- if (style->clip.clip != CSS_CLIP_NOT_SET) {
- fprintf(stream, "clip: ");
- switch (style->clip.clip) {
- case CSS_CLIP_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_CLIP_AUTO:
- fprintf(stream, "auto");
- break;
- case CSS_CLIP_RECT:
- fprintf(stream, "rect(");
- for (i = 0; i != 4; i++) {
- switch (style->clip.rect[i].rect) {
- case CSS_CLIP_RECT_AUTO:
- fprintf(stream, "auto");
- break;
- case CSS_CLIP_RECT_LENGTH:
- css_dump_length(stream,
- &style->clip.rect[i].value);
- break;
- }
- if (i != 3)
- fprintf(stream, ", ");
- }
- fprintf(stream, ")");
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
- DUMP_COLOR(color, "color");
- DUMP_KEYWORD(cursor, "cursor", css_cursor_name);
- DUMP_KEYWORD(direction, "direction", css_direction_name);
- DUMP_KEYWORD(display, "display", css_display_name);
- DUMP_KEYWORD(empty_cells, "empty-cells", css_empty_cells_name);
- DUMP_KEYWORD(float_, "float", css_float_name);
-
- if (style->font_style != CSS_FONT_STYLE_NOT_SET ||
- style->font_weight != CSS_FONT_WEIGHT_NOT_SET ||
- style->font_size.size != CSS_FONT_SIZE_NOT_SET ||
- style->line_height.size != CSS_LINE_HEIGHT_NOT_SET ||
- style->font_family != CSS_FONT_FAMILY_NOT_SET ||
- style->font_variant != CSS_FONT_VARIANT_NOT_SET) {
- fprintf(stream, "font:");
-
- if (style->font_style == CSS_FONT_STYLE_UNKNOWN)
- fprintf(stream, " UNKNOWN");
- else if (style->font_style == CSS_FONT_STYLE_NOT_SET)
- ;
- else
- fprintf(stream, " %s",
- css_font_style_name[style->font_style]);
-
- if (style->font_weight == CSS_FONT_WEIGHT_UNKNOWN)
- fprintf(stream, " UNKNOWN");
- else if (style->font_weight == CSS_FONT_WEIGHT_NOT_SET)
- ;
- else
- fprintf(stream, " %s",
- css_font_weight_name[style->font_weight]);
-
- switch (style->font_size.size) {
- case CSS_FONT_SIZE_ABSOLUTE:
- fprintf(stream, " [%g]",
- style->font_size.value.absolute);
- break;
- case CSS_FONT_SIZE_LENGTH:
- fprintf(stream, " ");
- css_dump_length(stream, &style->font_size.value.length);
- break;
- case CSS_FONT_SIZE_PERCENT:
- fprintf(stream, " %g%%",
- style->font_size.value.percent);
- break;
- case CSS_FONT_SIZE_INHERIT:
- fprintf(stream, " inherit");
- break;
- case CSS_FONT_SIZE_NOT_SET:
- break;
- default:
- fprintf(stream, " UNKNOWN");
- break;
- }
- switch (style->line_height.size) {
- case CSS_LINE_HEIGHT_ABSOLUTE:
- fprintf(stream, "/[%g]",
- style->line_height.value.absolute);
- break;
- case CSS_LINE_HEIGHT_LENGTH:
- fprintf(stream, "/");
- css_dump_length(stream,
- &style->line_height.value.length);
- break;
- case CSS_LINE_HEIGHT_PERCENT:
- fprintf(stream, "/%g%%",
- style->line_height.value.percent);
- break;
- case CSS_LINE_HEIGHT_INHERIT:
- fprintf(stream, "/inherit");
- break;
- case CSS_LINE_HEIGHT_NOT_SET:
- break;
- default:
- fprintf(stream, "/UNKNOWN");
- break;
- }
- if (style->font_family == CSS_FONT_FAMILY_UNKNOWN)
- fprintf(stream, " UNKNOWN");
- else if (style->font_family == CSS_FONT_FAMILY_NOT_SET)
- ;
- else
- fprintf(stream, " %s",
- css_font_family_name[style->font_family]);
-
- if (style->font_variant == CSS_FONT_VARIANT_UNKNOWN)
- fprintf(stream, " UNKNOWN");
- else if (style->font_variant == CSS_FONT_VARIANT_NOT_SET)
- ;
- else
- fprintf(stream, " %s",
- css_font_variant_name[style->font_variant]);
- fprintf(stream, "; ");
- }
-
- if (style->height.height != CSS_HEIGHT_NOT_SET) {
- fprintf(stream, "height: ");
- switch (style->height.height) {
- case CSS_HEIGHT_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_HEIGHT_AUTO:
- fprintf(stream, "auto");
- break;
- case CSS_HEIGHT_LENGTH:
- css_dump_length(stream, &style->height.value.length);
- break;
- case CSS_HEIGHT_PERCENT:
- fprintf(stream, "%g%%",
- style->height.value.percent);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- if (style->letter_spacing.letter_spacing !=
- CSS_LETTER_SPACING_NOT_SET) {
- fprintf(stream, "letter-spacing: ");
- switch (style->letter_spacing.letter_spacing) {
- case CSS_LETTER_SPACING_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_LETTER_SPACING_NORMAL:
- fprintf(stream, "normal");
- break;
- case CSS_LETTER_SPACING_LENGTH:
- css_dump_length(stream, &style->letter_spacing.length);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- if (style->list_style_type != CSS_LIST_STYLE_TYPE_NOT_SET ||
- style->list_style_position !=
- CSS_LIST_STYLE_POSITION_NOT_SET ||
- style->list_style_image.type !=
- CSS_LIST_STYLE_IMAGE_NOT_SET) {
- fprintf(stream, "list-style:");
-
- if (style->list_style_type == CSS_LIST_STYLE_TYPE_UNKNOWN)
- fprintf(stream, " UNKNOWN");
- else if (style->list_style_type == CSS_LIST_STYLE_TYPE_NOT_SET)
- ;
- else
- fprintf(stream, " %s",
- css_list_style_type_name[
- style->list_style_type]);
-
- if (style->list_style_position ==
- CSS_LIST_STYLE_POSITION_UNKNOWN)
- fprintf(stream, " UNKNOWN");
- else if (style->list_style_position ==
- CSS_LIST_STYLE_POSITION_NOT_SET)
- ;
- else
- fprintf(stream, " %s",
- css_list_style_position_name[
- style->list_style_position]);
-
- switch (style->list_style_image.type) {
- case CSS_LIST_STYLE_IMAGE_INHERIT:
- fprintf(stream, " inherit");
- break;
- case CSS_LIST_STYLE_IMAGE_NONE:
- fprintf(stream, " none");
- break;
- case CSS_LIST_STYLE_IMAGE_URI:
- fprintf(stream, " url('%s')",
- style->list_style_image.uri);
- break;
- case CSS_LIST_STYLE_IMAGE_NOT_SET:
- break;
- default:
- fprintf(stream, " UNKNOWN");
- }
- fprintf(stream, "; ");
- }
-
- if (style->margin[0].margin != CSS_MARGIN_NOT_SET ||
- style->margin[1].margin != CSS_MARGIN_NOT_SET ||
- style->margin[2].margin != CSS_MARGIN_NOT_SET ||
- style->margin[3].margin != CSS_MARGIN_NOT_SET) {
- fprintf(stream, "margin:");
- for (i = 0; i != 4; i++) {
- switch (style->margin[i].margin) {
- case CSS_MARGIN_INHERIT:
- fprintf(stream, " inherit");
- break;
- case CSS_MARGIN_LENGTH:
- fprintf(stream, " ");
- css_dump_length(stream,
- &style->margin[i].value.length);
- break;
- case CSS_MARGIN_PERCENT:
- fprintf(stream, " %g%%",
- style->margin[i].value.percent);
- break;
- case CSS_MARGIN_AUTO:
- fprintf(stream, " auto");
- break;
- case CSS_MARGIN_NOT_SET:
- fprintf(stream, " .");
- break;
- default:
- fprintf(stream, " UNKNOWN");
- break;
- }
- }
- fprintf(stream, "; ");
- }
-
- if (style->max_height.max_height != CSS_MAX_HEIGHT_NOT_SET) {
- fprintf(stream, "max-height: ");
- switch (style->max_height.max_height) {
- case CSS_MAX_HEIGHT_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_MAX_HEIGHT_NONE:
- fprintf(stream, "none");
- break;
- case CSS_MAX_HEIGHT_LENGTH:
- css_dump_length(stream,
- &style->max_height.value.length);
- break;
- case CSS_MAX_HEIGHT_PERCENT:
- fprintf(stream, "%g%%",
- style->max_height.value.percent);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- if (style->max_width.max_width != CSS_MAX_WIDTH_NOT_SET) {
- fprintf(stream, "max-width: ");
- switch (style->max_width.max_width) {
- case CSS_MAX_WIDTH_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_MAX_WIDTH_NONE:
- fprintf(stream, "none");
- break;
- case CSS_MAX_WIDTH_LENGTH:
- css_dump_length(stream, &style->max_width.value.length);
- break;
- case CSS_MAX_WIDTH_PERCENT:
- fprintf(stream, "%g%%",
- style->max_width.value.percent);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- if (style->min_height.min_height != CSS_MIN_HEIGHT_NOT_SET) {
- fprintf(stream, "min-height: ");
- switch (style->min_height.min_height) {
- case CSS_MIN_HEIGHT_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_MIN_HEIGHT_LENGTH:
- css_dump_length(stream,
- &style->min_height.value.length);
- break;
- case CSS_MIN_HEIGHT_PERCENT:
- fprintf(stream, "%g%%",
- style->min_height.value.percent);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- if (style->min_width.min_width != CSS_MIN_WIDTH_NOT_SET) {
- fprintf(stream, "min-width: ");
- switch (style->min_width.min_width) {
- case CSS_MIN_WIDTH_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_MIN_WIDTH_LENGTH:
- css_dump_length(stream, &style->min_width.value.length);
- break;
- case CSS_MIN_WIDTH_PERCENT:
- fprintf(stream, "%g%%",
- style->min_width.value.percent);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
+ /* Process pending imports */
+ while (error == CSS_IMPORTS_PENDING) {
+ struct content **imports;
+ uint32_t i;
+ lwc_string *uri;
+ uint64_t media;
+ css_stylesheet *sheet;
+ char *temp_url;
+
+ error = css_stylesheet_next_pending_import(c->data.css.sheet,
+ &uri, &media);
+ if (error != CSS_OK && error != CSS_INVALID) {
+ c->status = CONTENT_STATUS_ERROR;
+ return false;
}
- fprintf(stream, "; ");
- }
- if (style->orphans.orphans != CSS_ORPHANS_NOT_SET) {
- fprintf(stream, "orphans: ");
- switch (style->orphans.orphans) {
- case CSS_ORPHANS_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_ORPHANS_INTEGER:
- fprintf(stream, "%d",
- style->orphans.value);
- break;
- default:
- fprintf(stream, "UNKNOWN");
+ /* Give up if there are no more imports */
+ if (error == CSS_INVALID) {
+ error = CSS_OK;
break;
}
- fprintf(stream, "; ");
- }
- if (style->outline.color.color != CSS_OUTLINE_COLOR_NOT_SET ||
- style->outline.width.width != CSS_BORDER_WIDTH_NOT_SET ||
- style->outline.style != CSS_BORDER_STYLE_NOT_SET) {
- fprintf(stream, "outline:");
- switch (style->outline.color.color) {
- case CSS_OUTLINE_COLOR_INHERIT:
- fprintf(stream, " inherit");
- break;
- case CSS_OUTLINE_COLOR_INVERT:
- fprintf(stream, " invert");
- break;
- case CSS_OUTLINE_COLOR_COLOR:
- if (style->outline.color.value == NS_TRANSPARENT)
- fprintf(stream, " transparent");
- else if (style->outline.color.value == CSS_COLOR_NONE)
- fprintf(stream, " none");
- else if (style->outline.color.value == CSS_COLOR_INHERIT)
- fprintf(stream, " inherit");
- else if (style->outline.color.value == CSS_COLOR_NOT_SET)
- fprintf(stream, " .");
- else
- fprintf(stream, " #%.6x", style->outline.color.value);
- break;
- case CSS_OUTLINE_COLOR_NOT_SET:
- break;
- default:
- fprintf(stream, " UNKNOWN");
- break;
+ /* Copy URI and ensure it's NUL terminated */
+ temp_url = malloc(lwc_string_length(uri) + 1);
+ if (temp_url == NULL) {
+ c->status = CONTENT_STATUS_ERROR;
+ return false;
}
+ memcpy(temp_url, lwc_string_data(uri), lwc_string_length(uri));
+ temp_url[lwc_string_length(uri)] = '\0';
- if (style->outline.style == CSS_BORDER_STYLE_UNKNOWN)
- fprintf(stream, " UNKNOWN");
- else if (style->outline.style == CSS_BORDER_STYLE_NOT_SET)
- ;
- else
- fprintf(stream, " %s",
- css_border_style_name[style->outline.style]);
-
- switch (style->outline.width.width) {
- case CSS_BORDER_WIDTH_INHERIT:
- fprintf(stream, " inherit");
- break;
- case CSS_BORDER_WIDTH_LENGTH:
- fprintf(stream, " ");
- css_dump_length(stream, &style->outline.width.value);
- break;
- case CSS_BORDER_WIDTH_NOT_SET:
- break;
- default:
- fprintf(stream, " UNKNOWN");
- break;
+ /* Increase space in table */
+ imports = realloc(c->data.css.imports,
+ (c->data.css.import_count + 1) *
+ sizeof(struct content *));
+ if (imports == NULL) {
+ c->status = CONTENT_STATUS_ERROR;
+ return false;
}
- fprintf(stream, "; ");
- }
-
- DUMP_KEYWORD(overflow, "overflow", css_overflow_name);
-
- if (style->padding[0].padding != CSS_PADDING_NOT_SET ||
- style->padding[1].padding != CSS_PADDING_NOT_SET ||
- style->padding[2].padding != CSS_PADDING_NOT_SET ||
- style->padding[3].padding != CSS_PADDING_NOT_SET) {
- fprintf(stream, "padding:");
- for (i = 0; i != 4; i++) {
- switch (style->padding[i].padding) {
- case CSS_PADDING_INHERIT:
- fprintf(stream, " inherit");
- break;
- case CSS_PADDING_LENGTH:
- fprintf(stream, " ");
- css_dump_length(stream,
- &style->padding[i].value.length);
- break;
- case CSS_PADDING_PERCENT:
- fprintf(stream, " %g%%",
- style->padding[i].value.percent);
- break;
- case CSS_PADDING_NOT_SET:
- fprintf(stream, " .");
- break;
- default:
- fprintf(stream, " UNKNOWN");
- break;
- }
+ c->data.css.imports = imports;
+
+ /* Create content */
+ i = c->data.css.import_count;
+ c->data.css.imports[c->data.css.import_count++] =
+ fetchcache(temp_url,
+ nscss_import, (intptr_t) c, i,
+ c->width, c->height, true, NULL, NULL,
+ false, false);
+ if (c->data.css.imports[i] == NULL) {
+ free(temp_url);
+ c->status = CONTENT_STATUS_ERROR;
+ return false;
}
- fprintf(stream, "; ");
- }
-
- DUMP_KEYWORD(page_break_after, "page-break-after",
- css_page_break_after_name);
- DUMP_KEYWORD(page_break_before, "page-break-before",
- css_page_break_before_name);
- DUMP_KEYWORD(page_break_inside, "page-break-inside",
- css_page_break_inside_name);
- for (i = 0; i != 4; i++) {
- if (style->pos[i].pos != CSS_POS_NOT_SET) {
- switch (i) {
- case TOP:
- fprintf(stream, "top: ");
- break;
- case RIGHT:
- fprintf(stream, "right: ");
- break;
- case BOTTOM:
- fprintf(stream, "bottom: ");
- break;
- case LEFT:
- fprintf(stream, "left: ");
- break;
- }
- switch (style->pos[i].pos) {
- case CSS_POS_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_POS_AUTO:
- fprintf(stream, "auto");
- break;
- case CSS_POS_PERCENT:
- fprintf(stream, "%g%%",
- style->pos[i].value.percent);
- break;
- case CSS_POS_LENGTH:
- css_dump_length(stream,
- &style->pos[i].value.length);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
+ /* Fetch content */
+ c->active++;
+ fetchcache_go(c->data.css.imports[i], c->url,
+ nscss_import, (intptr_t) c, i,
+ c->width, c->height, NULL, NULL, false, c);
+
+ free(temp_url);
+
+ /* Wait for import to fetch + convert */
+ while (c->active > 0) {
+ fetch_poll();
+ gui_multitask();
+ }
+
+ if (c->data.css.imports[i] != NULL) {
+ sheet = c->data.css.imports[i]->data.css.sheet;
+ c->data.css.imports[i]->data.css.sheet = NULL;
+ } else {
+ error = css_stylesheet_create(CSS_LEVEL_DEFAULT,
+ NULL, "", NULL, CSS_ORIGIN_AUTHOR,
+ media, false, false, c->data.css.dict,
+ myrealloc, NULL,
+ nscss_resolve_url, NULL,
+ &sheet);
+ if (error != CSS_OK) {
+ c->status = CONTENT_STATUS_ERROR;
+ return false;
}
- fprintf(stream, "; ");
- }
- }
- DUMP_KEYWORD(position, "position", css_position_name);
-
- DUMP_KEYWORD(table_layout, "table-layout", css_table_layout_name);
- DUMP_KEYWORD(text_align, "text-align", css_text_align_name);
-
- if (style->text_decoration != CSS_TEXT_DECORATION_NOT_SET) {
- fprintf(stream, "text-decoration:");
- if (style->text_decoration == CSS_TEXT_DECORATION_NONE)
- fprintf(stream, " none");
- if (style->text_decoration == CSS_TEXT_DECORATION_INHERIT)
- fprintf(stream, " inherit");
- if (style->text_decoration & CSS_TEXT_DECORATION_UNDERLINE)
- fprintf(stream, " underline");
- if (style->text_decoration & CSS_TEXT_DECORATION_OVERLINE)
- fprintf(stream, " overline");
- if (style->text_decoration & CSS_TEXT_DECORATION_LINE_THROUGH)
- fprintf(stream, " line-through");
- if (style->text_decoration & CSS_TEXT_DECORATION_BLINK)
- fprintf(stream, " blink");
- fprintf(stream, "; ");
- }
-
- if (style->text_indent.size != CSS_TEXT_INDENT_NOT_SET) {
- fprintf(stream, "text-indent: ");
- switch (style->text_indent.size) {
- case CSS_TEXT_INDENT_LENGTH:
- css_dump_length(stream,
- &style->text_indent.value.length);
- break;
- case CSS_TEXT_INDENT_PERCENT:
- fprintf(stream, "%g%%",
- style->text_indent.value.percent);
- break;
- case CSS_TEXT_INDENT_INHERIT:
- fprintf(stream, "inherit");
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- DUMP_KEYWORD(text_transform, "text-transform", css_text_transform_name);
-
- DUMP_KEYWORD(unicode_bidi, "unicode-bidi", css_unicode_bidi_name);
-
- if (style->vertical_align.type != CSS_VERTICAL_ALIGN_NOT_SET) {
- fprintf(stream, "vertical-align: ");
- switch (style->vertical_align.type) {
- case CSS_VERTICAL_ALIGN_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_VERTICAL_ALIGN_BASELINE:
- fprintf(stream, "baseline");
- break;
- case CSS_VERTICAL_ALIGN_SUB:
- fprintf(stream, "sub");
- break;
- case CSS_VERTICAL_ALIGN_SUPER:
- fprintf(stream, "super");
- break;
- case CSS_VERTICAL_ALIGN_TOP:
- fprintf(stream, "top");
- break;
- case CSS_VERTICAL_ALIGN_TEXT_TOP:
- fprintf(stream, "text-top");
- break;
- case CSS_VERTICAL_ALIGN_MIDDLE:
- fprintf(stream, "middle");
- break;
- case CSS_VERTICAL_ALIGN_BOTTOM:
- fprintf(stream, "bottom");
- break;
- case CSS_VERTICAL_ALIGN_TEXT_BOTTOM:
- fprintf(stream, "text-bottom");
- break;
- case CSS_VERTICAL_ALIGN_LENGTH:
- css_dump_length(stream,
- &style->vertical_align.value.length);
- break;
- case CSS_VERTICAL_ALIGN_PERCENT:
- fprintf(stream, "%g%%",
- style->vertical_align.value.percent);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- DUMP_KEYWORD(visibility, "visibility", css_visibility_name);
- DUMP_KEYWORD(white_space, "white-space", css_white_space_name);
-
- if (style->widows.widows != CSS_WIDOWS_NOT_SET) {
- fprintf(stream, "widows: ");
- switch (style->widows.widows) {
- case CSS_WIDOWS_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_WIDOWS_INTEGER:
- fprintf(stream, "%d",
- style->widows.value);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- if (style->width.width != CSS_WIDTH_NOT_SET) {
- fprintf(stream, "width: ");
- switch (style->width.width) {
- case CSS_WIDTH_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_WIDTH_AUTO:
- fprintf(stream, "auto");
- break;
- case CSS_WIDTH_LENGTH:
- css_dump_length(stream, &style->width.value.length);
- break;
- case CSS_WIDTH_PERCENT:
- fprintf(stream, "%g%%", style->width.value.percent);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- if (style->word_spacing.word_spacing != CSS_WORD_SPACING_NOT_SET) {
- fprintf(stream, "word-spacing: ");
- switch (style->word_spacing.word_spacing) {
- case CSS_WORD_SPACING_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_WORD_SPACING_NORMAL:
- fprintf(stream, "normal");
- break;
- case CSS_WORD_SPACING_LENGTH:
- css_dump_length(stream, &style->word_spacing.length);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- if (style->z_index.z_index != CSS_Z_INDEX_NOT_SET) {
- fprintf(stream, "z-index: ");
- switch (style->z_index.z_index) {
- case CSS_Z_INDEX_INHERIT:
- fprintf(stream, "inherit");
- break;
- case CSS_Z_INDEX_AUTO:
- fprintf(stream, "auto");
- break;
- case CSS_Z_INDEX_INTEGER:
- fprintf(stream, "%d",
- style->z_index.value);
- break;
- default:
- fprintf(stream, "UNKNOWN");
- break;
- }
- fprintf(stream, "; ");
- }
-
- fprintf(stream, "}");
-}
-
-
-/**
- * Dump a css_length to the given stream
- */
-
-void css_dump_length(FILE *stream, const struct css_length * const length)
-{
- if (fabs(length->value) < 0.0001)
- fprintf(stream, "0");
- else
- fprintf(stream, "%g%s", length->value,
- css_unit_name[length->unit]);
-}
-
-#ifdef DEBUG_WORKING_STYLESHEET
-/**
- * Dump a complete css_working_stylesheet to stderr in CSS syntax.
- */
-
-void css_dump_working_stylesheet(const struct css_working_stylesheet *ws)
-{
- unsigned int i, j;
-
- for (i = 0; i != HASH_SIZE; i++) {
- /*fprintf(stderr, "hash %i:\n", i);*/
- for (j = 0; ws->rule[i][j]; j++) {
- css_dump_selector(ws->rule[i][j]);
- fprintf(stderr, " <%lx> ", ws->rule[i][j]->specificity);
- css_dump_style(ws->rule[i][j]->style);
- fprintf(stderr, "\n");
- }
- }
-}
-#endif
-
-/**
- * Set all members to false
- */
-void css_importance_reset(struct css_importance *i) {
- int j;
- i->background_color = false;
- i->background_image = false;
- i->border_spacing = false;
- i->color = false;
- i->height = false;
- i->width = false;
-
- /**< top, right, bottom, left */
- for (j = 0; j < 4; j++) {
- i->border_color[j] = false;
- i->border_style[j] = false;
- i->border_width[j] = false;
- i->margin[j] = false;
- i->padding[j] = false;
- }
-}
-
-/**
- * Dump a complete css_stylesheet to stderr in CSS syntax.
- */
-
-void css_dump_stylesheet(const struct css_stylesheet * stylesheet)
-{
- unsigned int i;
- struct css_selector *r;
- for (i = 0; i != HASH_SIZE; i++) {
- /*fprintf(stderr, "hash %i:\n", i);*/
- for (r = stylesheet->rule[i]; r != 0; r = r->next) {
- css_dump_selector(r);
- fprintf(stderr, " <%lx> ", r->specificity);
- css_dump_style(stderr, r->style);
- fprintf(stderr, "\n");
- }
- }
-}
-
-
-/**
- * Dump a css_selector to stderr in CSS syntax.
- */
-
-void css_dump_selector(const struct css_selector *r)
-{
- struct css_selector *m;
-
- if (r->combiner)
- css_dump_selector(r->combiner);
-
- switch (r->comb) {
- case CSS_COMB_NONE: break;
- case CSS_COMB_ANCESTOR: fprintf(stderr, " "); break;
- case CSS_COMB_PARENT: fprintf(stderr, " > "); break;
- case CSS_COMB_PRECEDED: fprintf(stderr, " + "); break;
- }
-
- if (r->data)
- fprintf(stderr, "%.*s", r->data_length, r->data);
- else
- fprintf(stderr, "*");
-
- for (m = r->detail; m; m = m->next) {
- switch (m->type) {
- case CSS_SELECTOR_ID:
- fprintf(stderr, "#%.*s",
- m->data_length, m->data);
- break;
- case CSS_SELECTOR_CLASS:
- fprintf(stderr, ".%.*s",
- m->data_length, m->data);
- break;
- case CSS_SELECTOR_ATTRIB:
- fprintf(stderr, "[%.*s]",
- m->data_length, m->data);
- break;
- case CSS_SELECTOR_ATTRIB_EQ:
- fprintf(stderr, "[%.*s=%.*s]",
- m->data_length, m->data,
- m->data2_length, m->data2);
- break;
- case CSS_SELECTOR_ATTRIB_INC:
- fprintf(stderr, "[%.*s~=%.*s]",
- m->data_length, m->data,
- m->data2_length, m->data2);
- break;
- case CSS_SELECTOR_ATTRIB_DM:
- fprintf(stderr, "[%.*s|=%.*s]",
- m->data_length, m->data,
- m->data2_length, m->data2);
- break;
- case CSS_SELECTOR_ATTRIB_PRE:
- fprintf(stderr, "[%.*s^=%.*s]",
- m->data_length, m->data,
- m->data2_length, m->data2);
- break;
- case CSS_SELECTOR_ATTRIB_SUF:
- fprintf(stderr, "[%.*s$=%.*s]",
- m->data_length, m->data,
- m->data2_length, m->data2);
- break;
- case CSS_SELECTOR_ATTRIB_SUB:
- fprintf(stderr, "[%.*s*=%.*s]",
- m->data_length, m->data,
- m->data2_length, m->data2);
- break;
- case CSS_SELECTOR_PSEUDO:
- fprintf(stderr, ":%.*s",
- m->data_length, m->data);
- break;
- default:
- fprintf(stderr, "(unexpected detail)");
}
- }
-}
-
-/**
- * Cascade styles.
- *
- * \param style css_style to modify
- * \param apply css_style to cascade onto style
- * \param author updated to indicate which properties have greater
- * than author level CSS importance. (NULL if
- * importance isn't required.)
- *
- * Attributes which have the value 'inherit' or 'unset' in apply are
- * unchanged in style.
- * Other attributes are copied to style, calculating percentages relative to
- * style where applicable.
- */
-
-void css_cascade(struct css_style * const style,
- const struct css_style * const apply,
- struct css_importance * const author)
-{
- unsigned int i;
- float f;
-
- if (apply->background_attachment !=
- CSS_BACKGROUND_ATTACHMENT_INHERIT &&
- apply->background_attachment !=
- CSS_BACKGROUND_ATTACHMENT_NOT_SET)
- style->background_attachment = apply->background_attachment;
- if (apply->background_color != CSS_COLOR_INHERIT &&
- apply->background_color != CSS_COLOR_NOT_SET)
- style->background_color = apply->background_color;
- if (apply->background_image.type != CSS_BACKGROUND_IMAGE_INHERIT &&
- apply->background_image.type !=
- CSS_BACKGROUND_IMAGE_NOT_SET)
- style->background_image = apply->background_image;
- if (apply->background_repeat != CSS_BACKGROUND_REPEAT_INHERIT &&
- apply->background_repeat !=
- CSS_BACKGROUND_REPEAT_NOT_SET)
- style->background_repeat = apply->background_repeat;
- if (apply->border_collapse != CSS_BORDER_COLLAPSE_INHERIT &&
- apply->border_collapse != CSS_BORDER_COLLAPSE_NOT_SET)
- style->border_collapse = apply->border_collapse;
- if (apply->border_spacing.border_spacing !=
- CSS_BORDER_SPACING_INHERIT &&
- apply->border_spacing.border_spacing !=
- CSS_BORDER_SPACING_NOT_SET)
- style->border_spacing = apply->border_spacing;
- if (apply->caption_side != CSS_CAPTION_SIDE_INHERIT &&
- apply->caption_side != CSS_CAPTION_SIDE_NOT_SET)
- style->caption_side = apply->caption_side;
- if (apply->clear != CSS_CLEAR_INHERIT &&
- apply->clear != CSS_CLEAR_NOT_SET)
- style->clear = apply->clear;
- if (apply->color != CSS_COLOR_INHERIT &&
- apply->color != CSS_COLOR_NOT_SET)
- style->color = apply->color;
- if (apply->content.type != CSS_CONTENT_INHERIT &&
- apply->content.type != CSS_CONTENT_NOT_SET)
- style->content = apply->content;
- if (apply->counter_reset.type != CSS_COUNTER_RESET_INHERIT &&
- apply->counter_reset.type != CSS_COUNTER_RESET_NOT_SET)
- style->counter_reset = apply->counter_reset;
- if (apply->counter_increment.type != CSS_COUNTER_INCREMENT_INHERIT &&
- apply->counter_increment.type != CSS_COUNTER_INCREMENT_NOT_SET)
- style->counter_increment = apply->counter_increment;
- if (apply->cursor != CSS_CURSOR_INHERIT &&
- apply->cursor != CSS_CURSOR_NOT_SET)
- style->cursor = apply->cursor;
- if (apply->direction != CSS_DIRECTION_INHERIT &&
- apply->direction != CSS_DIRECTION_NOT_SET)
- style->direction = apply->direction;
- if (apply->display != CSS_DISPLAY_INHERIT &&
- apply->display != CSS_DISPLAY_NOT_SET)
- style->display = apply->display;
- if (apply->empty_cells != CSS_EMPTY_CELLS_INHERIT &&
- apply->empty_cells != CSS_EMPTY_CELLS_NOT_SET)
- style->empty_cells = apply->empty_cells;
- if (apply->float_ != CSS_FLOAT_INHERIT &&
- apply->float_ != CSS_FLOAT_NOT_SET)
- style->float_ = apply->float_;
- if (apply->font_family != CSS_FONT_FAMILY_INHERIT &&
- apply->font_family != CSS_FONT_FAMILY_NOT_SET)
- style->font_family = apply->font_family;
- if (apply->font_style != CSS_FONT_STYLE_INHERIT &&
- apply->font_style != CSS_FONT_STYLE_NOT_SET)
- style->font_style = apply->font_style;
- if (apply->font_variant != CSS_FONT_VARIANT_INHERIT &&
- apply->font_variant != CSS_FONT_VARIANT_NOT_SET)
- style->font_variant = apply->font_variant;
- if (apply->font_weight != CSS_FONT_WEIGHT_INHERIT &&
- apply->font_weight != CSS_FONT_WEIGHT_NOT_SET)
- style->font_weight = apply->font_weight;
- if (apply->height.height != CSS_HEIGHT_INHERIT &&
- apply->height.height != CSS_HEIGHT_NOT_SET)
- style->height = apply->height;
- if (apply->letter_spacing.letter_spacing !=
- CSS_LETTER_SPACING_INHERIT &&
- apply->letter_spacing.letter_spacing !=
- CSS_LETTER_SPACING_NOT_SET)
- style->letter_spacing = apply->letter_spacing;
- if (apply->line_height.size != CSS_LINE_HEIGHT_INHERIT &&
- apply->line_height.size != CSS_LINE_HEIGHT_NOT_SET)
- style->line_height = apply->line_height;
- if (apply->list_style_image.type != CSS_LIST_STYLE_IMAGE_INHERIT &&
- apply->list_style_image.type !=
- CSS_LIST_STYLE_IMAGE_NOT_SET)
- style->list_style_image = apply->list_style_image;
- if (apply->list_style_position != CSS_LIST_STYLE_POSITION_INHERIT &&
- apply->list_style_position !=
- CSS_LIST_STYLE_POSITION_NOT_SET)
- style->list_style_position = apply->list_style_position;
- if (apply->list_style_type != CSS_LIST_STYLE_TYPE_INHERIT &&
- apply->list_style_type != CSS_LIST_STYLE_TYPE_NOT_SET)
- style->list_style_type = apply->list_style_type;
- if (apply->max_height.max_height != CSS_MAX_HEIGHT_INHERIT &&
- apply->max_height.max_height != CSS_MAX_HEIGHT_NOT_SET)
- style->max_height = apply->max_height;
- if (apply->max_width.max_width != CSS_MAX_WIDTH_INHERIT &&
- apply->max_width.max_width != CSS_MAX_WIDTH_NOT_SET)
- style->max_width = apply->max_width;
- if (apply->min_height.min_height != CSS_MIN_HEIGHT_INHERIT &&
- apply->min_height.min_height != CSS_MIN_HEIGHT_NOT_SET)
- style->min_height = apply->min_height;
- if (apply->min_width.min_width != CSS_MIN_WIDTH_INHERIT &&
- apply->min_width.min_width != CSS_MIN_WIDTH_NOT_SET)
- style->min_width = apply->min_width;
- if (apply->orphans.orphans != CSS_ORPHANS_INHERIT &&
- apply->orphans.orphans != CSS_ORPHANS_NOT_SET)
- style->orphans = apply->orphans;
- if (apply->overflow != CSS_OVERFLOW_INHERIT &&
- apply->overflow != CSS_OVERFLOW_NOT_SET)
- style->overflow = apply->overflow;
- if (apply->page_break_after != CSS_PAGE_BREAK_AFTER_INHERIT &&
- apply->page_break_after !=
- CSS_PAGE_BREAK_AFTER_NOT_SET)
- style->page_break_after = apply->page_break_after;
- if (apply->page_break_before != CSS_PAGE_BREAK_BEFORE_INHERIT &&
- apply->page_break_before !=
- CSS_PAGE_BREAK_BEFORE_NOT_SET)
- style->page_break_before = apply->page_break_before;
- if (apply->page_break_inside != CSS_PAGE_BREAK_INSIDE_INHERIT &&
- apply->page_break_inside !=
- CSS_PAGE_BREAK_INSIDE_NOT_SET)
- style->page_break_inside = apply->page_break_inside;
- if (apply->position != CSS_POSITION_INHERIT &&
- apply->position != CSS_POSITION_NOT_SET)
- style->position = apply->position;
- if (apply->table_layout != CSS_TABLE_LAYOUT_INHERIT &&
- apply->table_layout != CSS_TABLE_LAYOUT_NOT_SET)
- style->table_layout = apply->table_layout;
- if (apply->text_align != CSS_TEXT_ALIGN_INHERIT &&
- apply->text_align != CSS_TEXT_ALIGN_NOT_SET)
- style->text_align = apply->text_align;
- /* text-decoration: approximate CSS 2.1 by inheriting into inline elements */
- if (apply->text_decoration != CSS_TEXT_DECORATION_INHERIT &&
- apply->text_decoration != CSS_TEXT_DECORATION_NOT_SET)
- style->text_decoration = apply->text_decoration;
- if (apply->text_indent.size != CSS_TEXT_INDENT_INHERIT &&
- apply->text_indent.size != CSS_TEXT_INDENT_NOT_SET)
- style->text_indent = apply->text_indent;
- if (apply->text_transform != CSS_TEXT_TRANSFORM_INHERIT &&
- apply->text_transform != CSS_TEXT_TRANSFORM_NOT_SET)
- style->text_transform = apply->text_transform;
- if (apply->unicode_bidi != CSS_UNICODE_BIDI_INHERIT &&
- apply->unicode_bidi != CSS_UNICODE_BIDI_NOT_SET)
- style->unicode_bidi = apply->unicode_bidi;
- if (apply->vertical_align.type != CSS_VERTICAL_ALIGN_INHERIT &&
- apply->vertical_align.type !=
- CSS_VERTICAL_ALIGN_NOT_SET)
- style->vertical_align = apply->vertical_align;
- if (apply->visibility != CSS_VISIBILITY_INHERIT &&
- apply->visibility != CSS_VISIBILITY_NOT_SET)
- style->visibility = apply->visibility;
- if (apply->white_space != CSS_WHITE_SPACE_INHERIT &&
- apply->white_space != CSS_WHITE_SPACE_NOT_SET)
- style->white_space = apply->white_space;
- if (apply->widows.widows != CSS_WIDOWS_INHERIT &&
- apply->widows.widows != CSS_WIDOWS_NOT_SET)
- style->widows = apply->widows;
- if (apply->width.width != CSS_WIDTH_INHERIT &&
- apply->width.width != CSS_WIDTH_NOT_SET)
- style->width = apply->width;
- if (apply->word_spacing.word_spacing != CSS_WORD_SPACING_INHERIT &&
- apply->word_spacing.word_spacing !=
- CSS_WORD_SPACING_NOT_SET)
- style->word_spacing = apply->word_spacing;
- if (apply->z_index.z_index != CSS_Z_INDEX_INHERIT &&
- apply->z_index.z_index != CSS_Z_INDEX_NOT_SET)
- style->z_index = apply->z_index;
-
-
- /* clip */
- if (apply->clip.clip != CSS_CLIP_INHERIT &&
- apply->clip.clip != CSS_CLIP_NOT_SET) {
- for (i = 0; i != 4; i++) {
- style->clip.rect[i] = apply->clip.rect[i];
+ error = css_stylesheet_register_import(
+ c->data.css.sheet, sheet);
+ if (error != CSS_OK) {
+ c->status = CONTENT_STATUS_ERROR;
+ return false;
}
- }
-
-
- /* background-position */
- if (apply->background_position.horz.pos !=
- CSS_BACKGROUND_POSITION_INHERIT &&
- apply->background_position.horz.pos !=
- CSS_BACKGROUND_POSITION_NOT_SET) {
- style->background_position.horz =
- apply->background_position.horz;
- }
- if (apply->background_position.vert.pos !=
- CSS_BACKGROUND_POSITION_INHERIT &&
- apply->background_position.vert.pos !=
- CSS_BACKGROUND_POSITION_NOT_SET) {
- style->background_position.vert =
- apply->background_position.vert;
- }
-
- /* font-size */
- f = apply->font_size.value.percent / 100;
- switch (apply->font_size.size) {
- case CSS_FONT_SIZE_ABSOLUTE:
- style->font_size = apply->font_size;
- break;
- case CSS_FONT_SIZE_LENGTH:
- switch (apply->font_size.value.length.unit) {
- case CSS_UNIT_EM:
- f = apply->font_size.value.length.value;
- break;
- case CSS_UNIT_EX:
- f = apply->font_size.value.length.value * 0.6 /*?*/;
- break;
- default:
- style->font_size = apply->font_size;
- }
- if ((apply->font_size.value.length.unit != CSS_UNIT_EM) &&
- (apply->font_size.value.length.unit != CSS_UNIT_EX))
- break;
- /* drop through if EM or EX */
- case CSS_FONT_SIZE_PERCENT:
- switch (style->font_size.size) {
- case CSS_FONT_SIZE_ABSOLUTE:
- style->font_size.value.absolute *= f;
- break;
- case CSS_FONT_SIZE_LENGTH:
- style->font_size.value.length.value *= f;
- break;
- default:
- die("attempting percentage of unknown font-size");
- }
- break;
- case CSS_FONT_SIZE_INHERIT:
- case CSS_FONT_SIZE_NOT_SET:
- default: /* leave unchanged */
- break;
- }
- /* outline */
- if (apply->outline.color.color != CSS_OUTLINE_COLOR_INHERIT &&
- apply->outline.color.color !=
- CSS_OUTLINE_COLOR_NOT_SET)
- style->outline.color = apply->outline.color;
- if (apply->outline.width.width != CSS_BORDER_WIDTH_INHERIT &&
- apply->outline.width.width != CSS_BORDER_WIDTH_NOT_SET)
- style->outline.width = apply->outline.width;
- if (apply->outline.style != CSS_BORDER_STYLE_INHERIT &&
- apply->outline.style != CSS_BORDER_STYLE_NOT_SET)
- style->outline.style = apply->outline.style;
-
- /* borders, margins, padding and box position */
- for (i = 0; i != 4; i++) {
- if (apply->border[i].color != CSS_COLOR_INHERIT &&
- apply->border[i].color != CSS_COLOR_NOT_SET)
- style->border[i].color = apply->border[i].color;
- if (apply->border[i].width.width !=
- CSS_BORDER_WIDTH_INHERIT &&
- apply->border[i].width.width !=
- CSS_BORDER_WIDTH_NOT_SET)
- style->border[i].width = apply->border[i].width;
- if (apply->border[i].style != CSS_BORDER_STYLE_INHERIT &&
- apply->border[i].style !=
- CSS_BORDER_STYLE_NOT_SET)
- style->border[i].style = apply->border[i].style;
-
- if (apply->margin[i].margin != CSS_MARGIN_INHERIT &&
- apply->margin[i].margin != CSS_MARGIN_NOT_SET)
- style->margin[i] = apply->margin[i];
-
- if (apply->padding[i].padding != CSS_PADDING_INHERIT &&
- apply->padding[i].padding !=
- CSS_PADDING_NOT_SET)
- style->padding[i] = apply->padding[i];
-
- if (apply->pos[i].pos != CSS_POS_INHERIT &&
- apply->pos[i].pos != CSS_POS_NOT_SET)
- style->pos[i] = apply->pos[i];
+ error = CSS_IMPORTS_PENDING;
}
- /* Set author level CSS importance (used for HTML style attribute) */
- if (author) {
- if (apply->background_color != CSS_COLOR_NOT_SET)
- author->background_color = true;
- if (apply->background_image.type !=
- CSS_BACKGROUND_IMAGE_NOT_SET)
- author->background_image = true;
- if (apply->border_spacing.border_spacing !=
- CSS_BORDER_SPACING_NOT_SET)
- author->border_spacing = true;
- if (apply->color != CSS_COLOR_NOT_SET)
- author->color = true;
- if (apply->height.height != CSS_HEIGHT_NOT_SET)
- author->height = true;
- if (apply->width.width != CSS_WIDTH_NOT_SET)
- author->width = true;
-
- for (i = 0; i != 4; i++) {
- if (apply->border[i].color != CSS_COLOR_NOT_SET)
- author->border_color[i] = true;
- if (apply->border[i].width.width !=
- CSS_BORDER_WIDTH_NOT_SET)
- author->border_width[i] = true;
- if (apply->border[i].style != CSS_BORDER_STYLE_NOT_SET)
- author->border_style[i] = true;
+ c->status = CONTENT_STATUS_DONE;
- if (apply->margin[i].margin != CSS_MARGIN_NOT_SET)
- author->margin[i] = true;
+ /* Filthy hack to stop this content being reused
+ * when whatever is using it has finished with it. */
+ c->fresh = false;
- if (apply->padding[i].padding != CSS_PADDING_NOT_SET)
- author->padding[i] = true;
- }
- }
+ return error == CSS_OK;
}
-
/**
- * Merge styles.
+ * Clean up a CSS content
*
- * \param style css_style to modify
- * \param apply css_style to merge onto style
- * \param specificity specificity of current CSS rule
- * \param author updated to indicate which properties have greater than
- * author level CSS importance
- *
- * Attributes which have the value 'unset' in apply are unchanged in style.
- * Other attributes are copied to style, overwriting it.
+ * \param c Content to clean up
*/
-
-void css_merge(struct css_style * const style,
- const struct css_style * const apply,
- const unsigned long specificity,
- struct css_importance * const author)
+void nscss_destroy(struct content *c)
{
- unsigned int i;
+ uint32_t i;
- if (apply->background_attachment != CSS_BACKGROUND_ATTACHMENT_NOT_SET)
- style->background_attachment = apply->background_attachment;
- if (apply->background_color != CSS_COLOR_NOT_SET) {
- style->background_color = apply->background_color;
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->background_color = true;
- }
- if (apply->background_image.type != CSS_BACKGROUND_IMAGE_NOT_SET) {
- style->background_image = apply->background_image;
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->background_image = true;
- }
- if (apply->background_repeat != CSS_BACKGROUND_REPEAT_NOT_SET)
- style->background_repeat = apply->background_repeat;
- if (apply->border_collapse != CSS_BORDER_COLLAPSE_NOT_SET)
- style->border_collapse = apply->border_collapse;
- if (apply->border_spacing.border_spacing != CSS_BORDER_SPACING_NOT_SET){
- style->border_spacing = apply->border_spacing;
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->border_spacing = true;
- }
- if (apply->caption_side != CSS_CAPTION_SIDE_NOT_SET)
- style->caption_side = apply->caption_side;
- if (apply->clear != CSS_CLEAR_NOT_SET)
- style->clear = apply->clear;
- if (apply->color != CSS_COLOR_NOT_SET) {
- style->color = apply->color;
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->color = true;
- }
- if (apply->content.type != CSS_CONTENT_NOT_SET)
- style->content = apply->content;
- if (apply->counter_reset.type != CSS_COUNTER_RESET_NOT_SET)
- style->counter_reset = apply->counter_reset;
- if (apply->counter_increment.type != CSS_COUNTER_INCREMENT_NOT_SET)
- style->counter_increment = apply->counter_increment;
- if (apply->cursor != CSS_CURSOR_NOT_SET)
- style->cursor = apply->cursor;
- if (apply->direction != CSS_DIRECTION_NOT_SET)
- style->direction = apply->direction;
- if (apply->display != CSS_DISPLAY_NOT_SET)
- style->display = apply->display;
- if (apply->empty_cells != CSS_EMPTY_CELLS_NOT_SET)
- style->empty_cells = apply->empty_cells;
- if (apply->float_ != CSS_FLOAT_NOT_SET)
- style->float_ = apply->float_;
- if (apply->font_family != CSS_FONT_FAMILY_NOT_SET)
- style->font_family = apply->font_family;
- if (apply->font_size.size != CSS_FONT_SIZE_NOT_SET)
- style->font_size = apply->font_size;
- if (apply->font_style != CSS_FONT_STYLE_NOT_SET)
- style->font_style = apply->font_style;
- if (apply->font_variant != CSS_FONT_VARIANT_NOT_SET)
- style->font_variant = apply->font_variant;
- if (apply->font_weight != CSS_FONT_WEIGHT_NOT_SET)
- style->font_weight = apply->font_weight;
- if (apply->height.height != CSS_HEIGHT_NOT_SET) {
- style->height = apply->height;
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->height = true;
- }
- if (apply->letter_spacing.letter_spacing != CSS_LETTER_SPACING_NOT_SET)
- style->letter_spacing = apply->letter_spacing;
- if (apply->line_height.size != CSS_LINE_HEIGHT_NOT_SET)
- style->line_height = apply->line_height;
- if (apply->list_style_image.type != CSS_LIST_STYLE_IMAGE_NOT_SET)
- style->list_style_image = apply->list_style_image;
- if (apply->list_style_position != CSS_LIST_STYLE_POSITION_NOT_SET)
- style->list_style_position = apply->list_style_position;
- if (apply->list_style_type != CSS_LIST_STYLE_TYPE_NOT_SET)
- style->list_style_type = apply->list_style_type;
- if (apply->max_height.max_height != CSS_MAX_HEIGHT_NOT_SET)
- style->max_height = apply->max_height;
- if (apply->max_width.max_width != CSS_MAX_WIDTH_NOT_SET)
- style->max_width = apply->max_width;
- if (apply->min_height.min_height != CSS_MIN_HEIGHT_NOT_SET)
- style->min_height = apply->min_height;
- if (apply->min_width.min_width != CSS_MIN_WIDTH_NOT_SET)
- style->min_width = apply->min_width;
- if (apply->orphans.orphans != CSS_ORPHANS_NOT_SET)
- style->orphans = apply->orphans;
- if (apply->overflow != CSS_OVERFLOW_NOT_SET)
- style->overflow = apply->overflow;
- if (apply->page_break_after != CSS_PAGE_BREAK_AFTER_NOT_SET)
- style->page_break_after = apply->page_break_after;
- if (apply->page_break_before != CSS_PAGE_BREAK_BEFORE_NOT_SET)
- style->page_break_before = apply->page_break_before;
- if (apply->page_break_inside != CSS_PAGE_BREAK_INSIDE_NOT_SET)
- style->page_break_inside = apply->page_break_inside;
- if (apply->position != CSS_POSITION_NOT_SET)
- style->position = apply->position;
- if (apply->table_layout != CSS_TABLE_LAYOUT_NOT_SET)
- style->table_layout = apply->table_layout;
- if (apply->text_align != CSS_TEXT_ALIGN_NOT_SET)
- style->text_align = apply->text_align;
- /* text-decoration: approximate CSS 2.1 by inheriting into inline elements */
- if (apply->text_decoration != CSS_TEXT_DECORATION_NOT_SET)
- style->text_decoration = apply->text_decoration;
- if (apply->text_indent.size != CSS_TEXT_INDENT_NOT_SET)
- style->text_indent = apply->text_indent;
- if (apply->text_transform != CSS_TEXT_TRANSFORM_NOT_SET)
- style->text_transform = apply->text_transform;
- if (apply->unicode_bidi != CSS_UNICODE_BIDI_NOT_SET)
- style->unicode_bidi = apply->unicode_bidi;
- if (apply->vertical_align.type != CSS_VERTICAL_ALIGN_NOT_SET)
- style->vertical_align = apply->vertical_align;
- if (apply->visibility != CSS_VISIBILITY_NOT_SET)
- style->visibility = apply->visibility;
- if (apply->white_space != CSS_WHITE_SPACE_NOT_SET)
- style->white_space = apply->white_space;
- if (apply->widows.widows != CSS_WIDOWS_NOT_SET)
- style->widows = apply->widows;
- if (apply->width.width != CSS_WIDTH_NOT_SET) {
- style->width = apply->width;
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->width = true;
- }
- if (apply->word_spacing.word_spacing != CSS_WORD_SPACING_NOT_SET)
- style->word_spacing = apply->word_spacing;
- if (apply->z_index.z_index != CSS_Z_INDEX_NOT_SET)
- style->z_index = apply->z_index;
-
-
- /* clip */
- if (apply->clip.clip != CSS_CLIP_NOT_SET) {
- for (i = 0; i != 4; i++) {
- style->clip.rect[i] = apply->clip.rect[i];
+ for (i = 0; i < c->data.css.import_count; i++) {
+ if (c->data.css.imports[i] != NULL) {
+ content_remove_user(c->data.css.imports[i],
+ nscss_import, (uintptr_t) c, i);
}
+ c->data.css.imports[i] = NULL;
}
- /* background-position */
- if (apply->background_position.horz.pos !=
- CSS_BACKGROUND_POSITION_NOT_SET) {
- style->background_position.horz =
- apply->background_position.horz;
- }
- if (apply->background_position.vert.pos !=
- CSS_BACKGROUND_POSITION_NOT_SET) {
- style->background_position.vert =
- apply->background_position.vert;
- }
-
- /* outline */
- if (apply->outline.color.color != CSS_OUTLINE_COLOR_NOT_SET)
- style->outline.color = apply->outline.color;
- if (apply->outline.width.width != CSS_BORDER_WIDTH_NOT_SET)
- style->outline.width = apply->outline.width;
- if (apply->outline.style != CSS_BORDER_STYLE_NOT_SET)
- style->outline.style = apply->outline.style;
+ free(c->data.css.imports);
- /* borders, margins, padding and box position */
- for (i = 0; i != 4; i++) {
- if (apply->border[i].color != CSS_COLOR_NOT_SET) {
- style->border[i].color = apply->border[i].color;
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->border_color[i] = true;
- }
- if (apply->border[i].width.width != CSS_BORDER_WIDTH_NOT_SET) {
- style->border[i].width = apply->border[i].width;
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->border_width[i] = true;
- }
- if (apply->border[i].style != CSS_BORDER_STYLE_NOT_SET) {
- style->border[i].style = apply->border[i].style;
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->border_style[i] = true;
- }
-
- if (apply->margin[i].margin != CSS_MARGIN_NOT_SET) {
- style->margin[i] = apply->margin[i];
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->margin[i] = true;
- }
-
- if (apply->padding[i].padding != CSS_PADDING_NOT_SET) {
- style->padding[i] = apply->padding[i];
- if (specificity >= CSS_SPECIFICITY_AUTHOR)
- author->padding[i] = true;
- }
-
- if (apply->pos[i].pos != CSS_POS_NOT_SET)
- style->pos[i] = apply->pos[i];
+ if (c->data.css.sheet != NULL) {
+ css_stylesheet_destroy(c->data.css.sheet);
+ c->data.css.sheet = NULL;
}
-}
-
-
-/**
- * Calculate a hash for an element name.
- *
- * The hash is case-insensitive.
- */
-
-unsigned int css_hash(const char *s, int length)
-{
- int i;
- unsigned int z = 0;
- if (s == 0)
- return 0;
- for (i = 0; i != length; i++)
- z += s[i] & 0x1f; /* lower 5 bits, case insensitive */
- return (z % (HASH_SIZE - 1)) + 1;
-}
-
-/**
- * Convert a struct css_length to pixels.
- *
- * \param length css_length to convert
- * \param style css_style applying to length. may be 0 if the length's
- * unit is em or ex
- * \return length in pixels
- *
- * If a length's unit is em or ex, the returned length is subject to the
- * configured option_font_min_size.
- */
-
-float css_len2px(const struct css_length *length,
- const struct css_style *style)
-{
- struct css_length font;
- font.unit = CSS_UNIT_PT;
-
- assert(!((length->unit == CSS_UNIT_EM || length->unit == CSS_UNIT_EX) &&
- style == 0));
- switch (length->unit) {
- case CSS_UNIT_EM:
- if ((font.value = css_len2pt(&style->
- font_size.value.length, style)) <
- option_font_min_size / 10) {
- /* min font size is greater than given length so
- * use min font size for conversion to px */
- font.value = option_font_min_size / 10;
- return length->value * css_len2px(&font, style);
- } else
- /* use given length for conversion to px */
- return length->value * css_len2px(&style->
- font_size.value.length, 0);
- case CSS_UNIT_EX:
- if ((font.value = css_len2pt(&style->
- font_size.value.length, style)) <
- option_font_min_size / 10) {
- /* min font size is greater than given length so
- * use min font size for conversion to px */
- font.value = option_font_min_size / 10;
- return length->value * css_len2px(&font,
- style) * 0.6;
- } else
- /* use given length for conversion to px */
- return length->value * css_len2px(&style->
- font_size.value.length, 0) *
- 0.6;
- case CSS_UNIT_PX: return length->value;
- /* We assume the screen and any other output has the same dpi */
- case CSS_UNIT_IN: return length->value * css_screen_dpi;
- case CSS_UNIT_CM: return length->value * css_screen_dpi / 2.54;
- case CSS_UNIT_MM: return length->value * css_screen_dpi / 25.4;
- /* 1pt = 1in/72 */
- case CSS_UNIT_PT: return length->value * css_screen_dpi / 72;
- /* 1pc = 1pt * 12 */
- case CSS_UNIT_PC: return length->value * css_screen_dpi / 6;
- default: break;
- }
- return 0;
-}
-
-/**
- * Convert a struct css_length to points.
- *
- * \param length css_length to convert
- * \param style css_style applying to length. may be 0 if the length's
- * unit is em or ex
- * \return length in points
- */
-
-float css_len2pt(const struct css_length *length,
- const struct css_style *style)
-{
- assert(!((length->unit == CSS_UNIT_EM || length->unit == CSS_UNIT_EX) &&
- style == 0));
- switch (length->unit) {
- case CSS_UNIT_EM:
- return length->value *
- css_len2pt(&style->font_size.value.length, 0);
- case CSS_UNIT_EX:
- return length->value *
- css_len2pt(&style->font_size.value.length, 0) *
- 0.6;
- /* We assume the screen and any other output has the same dpi */
- case CSS_UNIT_PX: return length->value * 72 / css_screen_dpi;
- /* 1pt = 1in/72 */
- case CSS_UNIT_IN: return length->value * 72;
- case CSS_UNIT_CM: return length->value * 28.452756;
- case CSS_UNIT_MM: return length->value * 2.8452756;
- case CSS_UNIT_PT: return length->value;
- /* 1pc = 1pt * 12 */
- case CSS_UNIT_PC: return length->value * 12.0;
- default: break;
+ if (c->data.css.dict != NULL) {
+ lwc_context_unref(c->data.css.dict);
+ c->data.css.dict = NULL;
}
- return 0;
}
/**
- * Return the most 'eyecatching' border.
+ * Fetchcache handler for imported stylesheets
*
- * \return the most eyecatching border, favoured towards test2
+ * \param msg Message type
+ * \param c Content being fetched
+ * \param p1 Parent content
+ * \param p2 Index into parent's imported stylesheet array
+ * \param data Message data
*/
-
-struct css_border *css_eyecatching_border(struct css_border *test1,
- struct css_style *style1, struct css_border *test2,
- struct css_style *style2)
+void nscss_import(content_msg msg, struct content *c,
+ intptr_t p1, intptr_t p2, union content_msg_data data)
{
- float width1, width2;
- int impact = 0;
-
- assert(test1);
- assert(style1);
- assert(test2);
- assert(style2);
+ struct content *parent = (struct content *) p1;
+ uint32_t i = (uint32_t) p2;
- /* hidden border styles always win, none always loses */
- if ((test1->style == CSS_BORDER_STYLE_HIDDEN) ||
- (test2->style == CSS_BORDER_STYLE_NONE))
- return test1;
- if ((test2->style == CSS_BORDER_STYLE_HIDDEN) ||
- (test1->style == CSS_BORDER_STYLE_NONE))
- return test2;
-
- /* the widest border wins */
- width1 = css_len2px(&test1->width.value, style1);
- width2 = css_len2px(&test2->width.value, style2);
- if (width1 > width2)
- return test1;
- if (width2 > width1)
- return test2;
+ switch (msg) {
+ case CONTENT_MSG_LOADING:
+ if (c->type != CONTENT_CSS) {
+ content_remove_user(c, nscss_import, p1, p2);
+ if (c->user_list->next == NULL) {
+ fetch_abort(c->fetch);
+ c->fetch = NULL;
+ c->status = CONTENT_STATUS_ERROR;
+ }
- /* the closest to a solid line wins */
- switch (test1->style) {
- case CSS_BORDER_STYLE_DOUBLE:
- impact++;
- case CSS_BORDER_STYLE_SOLID:
- impact++;
- case CSS_BORDER_STYLE_DASHED:
- impact++;
- case CSS_BORDER_STYLE_DOTTED:
- impact++;
- case CSS_BORDER_STYLE_RIDGE:
- impact++;
- case CSS_BORDER_STYLE_OUTSET:
- impact++;
- case CSS_BORDER_STYLE_GROOVE:
- impact++;
- case CSS_BORDER_STYLE_INSET:
- impact++;
- default:
- break;
+ parent->data.css.imports[i] = NULL;
+ parent->active--;
+ content_add_error(parent, "NotCSS", 0);
+ }
+ break;
+ case CONTENT_MSG_READY:
+ break;
+ case CONTENT_MSG_DONE:
+ parent->active--;
+ break;
+ case CONTENT_MSG_AUTH:
+ case CONTENT_MSG_SSL:
+ case CONTENT_MSG_LAUNCH:
+ case CONTENT_MSG_ERROR:
+ if (parent->data.css.imports[i] == c) {
+ parent->data.css.imports[i] = NULL;
+ parent->active--;
+ }
+ break;
+ case CONTENT_MSG_STATUS:
+ break;
+ case CONTENT_MSG_NEWPTR:
+ parent->data.css.imports[i] = c;
+ break;
+ default:
+ assert(0);
}
- switch (test2->style) {
- case CSS_BORDER_STYLE_DOUBLE:
- impact--;
- case CSS_BORDER_STYLE_SOLID:
- impact--;
- case CSS_BORDER_STYLE_DASHED:
- impact--;
- case CSS_BORDER_STYLE_DOTTED:
- impact--;
- case CSS_BORDER_STYLE_RIDGE:
- impact--;
- case CSS_BORDER_STYLE_OUTSET:
- impact--;
- case CSS_BORDER_STYLE_GROOVE:
- impact--;
- case CSS_BORDER_STYLE_INSET:
- impact--;
- default:
- break;
- }
- if (impact > 0)
- return test1;
- return test2;
}
-