/* * This file is part of LibCSS. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #ifndef css_stylesheet_h_ #define css_stylesheet_h_ #include #include #include #include #include #include #include #include "bytecode/bytecode.h" #include "parse/parse.h" #include "parse/mq.h" #include "select/hash.h" typedef struct css_rule css_rule; typedef struct css_selector css_selector; typedef struct css_style { css_code_t *bytecode; /**< Pointer to bytecode */ uint32_t used; /**< number of code entries used */ uint32_t allocated; /**< number of allocated code entries */ struct css_stylesheet *sheet; /**< containing sheet */ } css_style; typedef enum css_selector_type { CSS_SELECTOR_ELEMENT, CSS_SELECTOR_CLASS, CSS_SELECTOR_ID, CSS_SELECTOR_PSEUDO_CLASS, CSS_SELECTOR_PSEUDO_ELEMENT, CSS_SELECTOR_ATTRIBUTE, CSS_SELECTOR_ATTRIBUTE_EQUAL, CSS_SELECTOR_ATTRIBUTE_DASHMATCH, CSS_SELECTOR_ATTRIBUTE_INCLUDES, CSS_SELECTOR_ATTRIBUTE_PREFIX, CSS_SELECTOR_ATTRIBUTE_SUFFIX, CSS_SELECTOR_ATTRIBUTE_SUBSTRING } css_selector_type; typedef enum css_combinator { CSS_COMBINATOR_NONE, CSS_COMBINATOR_ANCESTOR, CSS_COMBINATOR_PARENT, CSS_COMBINATOR_SIBLING, CSS_COMBINATOR_GENERIC_SIBLING } css_combinator; typedef enum css_selector_detail_value_type { CSS_SELECTOR_DETAIL_VALUE_STRING, CSS_SELECTOR_DETAIL_VALUE_NTH } css_selector_detail_value_type; typedef union css_selector_detail_value { lwc_string *string; /**< Interned string, or NULL */ struct { int32_t a; int32_t b; } nth; /**< Data for x = an + b */ } css_selector_detail_value; typedef struct css_selector_detail { css_qname qname; /**< Interned name */ css_selector_detail_value value; /**< Detail value */ unsigned int type : 4, /**< Type of selector */ comb : 3, /**< Type of combinator */ next : 1, /**< Another selector detail * follows */ value_type : 1, /**< Type of value field */ negate : 1; /**< Detail match is inverted */ } css_selector_detail; struct css_selector { css_selector *combinator; /**< Combining selector */ css_rule *rule; /**< Owning rule */ #define CSS_SPECIFICITY_A 0x01000000 #define CSS_SPECIFICITY_B 0x00010000 #define CSS_SPECIFICITY_C 0x00000100 #define CSS_SPECIFICITY_D 0x00000001 uint32_t specificity; /**< Specificity of selector */ css_selector_detail data; /**< Selector data */ }; typedef enum css_rule_type { CSS_RULE_UNKNOWN, CSS_RULE_SELECTOR, CSS_RULE_CHARSET, CSS_RULE_IMPORT, CSS_RULE_MEDIA, CSS_RULE_FONT_FACE, CSS_RULE_PAGE } css_rule_type; typedef enum css_rule_parent_type { CSS_RULE_PARENT_STYLESHEET, CSS_RULE_PARENT_RULE } css_rule_parent_type; struct css_rule { void *parent; /**< containing rule or owning * stylesheet (defined by ptype) */ css_rule *next; /**< next in list */ css_rule *prev; /**< previous in list */ uint32_t index; /**< index in sheet */ uint16_t items; /**< number of items (selectors) in rule */ uint8_t type; /**< css_rule_type */ uint8_t ptype; /**< css_rule_parent_type */ } _ALIGNED; typedef struct css_rule_selector { css_rule base; css_selector **selectors; css_style *style; } css_rule_selector; typedef struct css_rule_media { css_rule base; css_mq_query *media; css_rule *first_child; css_rule *last_child; } css_rule_media; typedef struct css_rule_font_face { css_rule base; css_font_face *font_face; } css_rule_font_face; typedef struct css_rule_page { css_rule base; css_selector *selector; css_style *style; } css_rule_page; typedef struct css_rule_import { css_rule base; lwc_string *url; css_mq_query *media; css_stylesheet *sheet; } css_rule_import; typedef struct css_rule_charset { css_rule base; lwc_string *encoding; /** \todo use MIB enum? */ } css_rule_charset; struct css_stylesheet { css_selector_hash *selectors; /**< Hashtable of selectors */ uint32_t rule_count; /**< Number of rules in sheet */ css_rule *rule_list; /**< List of rules in sheet */ css_rule *last_rule; /**< Last rule in list */ bool disabled; /**< Whether this sheet is * disabled */ char *url; /**< URL of this sheet */ char *title; /**< Title of this sheet */ css_language_level level; /**< Language level of sheet */ css_parser *parser; /**< Core parser for sheet */ void *parser_frontend; /**< Frontend parser */ lwc_string **propstrings; /**< Property strings, for parser */ bool quirks_allowed; /**< Quirks permitted */ bool quirks_used; /**< Quirks actually used */ bool uses_revert; /**< Uses 'revert' property value */ bool inline_style; /**< Is an inline style */ size_t size; /**< Size, in bytes */ css_import_notification_fn import; /**< Import notification function */ void *import_pw; /**< Private word */ css_url_resolution_fn resolve; /**< URL resolution function */ void *resolve_pw; /**< Private word */ css_color_resolution_fn color; /**< Colour resolution function */ void *color_pw; /**< Private word */ /** System font resolution function */ css_font_resolution_fn font; void *font_pw; /**< Private word */ css_style *cached_style; /**< Cache for style parsing */ lwc_string **string_vector; /**< Bytecode string vector */ uint32_t string_vector_l; /**< The string vector allocated * length in entries */ uint32_t string_vector_c; /**< The number of string * vector entries used */ }; css_error css__stylesheet_style_create(css_stylesheet *sheet, css_style **style); css_error css__stylesheet_style_append(css_style *style, css_code_t code); css_error css__stylesheet_style_vappend(css_style *style, uint32_t style_count, ...); css_error css__stylesheet_style_destroy(css_style *style); css_error css__stylesheet_merge_style(css_style *target, css_style *style); /** Helper function to avoid distinct buildOPV call */ static inline css_error css__stylesheet_style_appendOPV(css_style *style, opcode_t opcode, uint8_t flags, uint16_t value) { if ((flags & (0x7 << 1)) == FLAG_REVERT) { style->sheet->uses_revert = true; } return css__stylesheet_style_append(style, buildOPV(opcode, flags, value)); } /** Helper function to set inherit generic value */ static inline css_error css_stylesheet_style_inherit(css_style *style, opcode_t opcode) { return css__stylesheet_style_append(style, buildOPV(opcode, FLAG_INHERIT, 0)); } /** Helper function to set initial generic value */ static inline css_error css_stylesheet_style_initial(css_style *style, opcode_t opcode) { return css__stylesheet_style_append(style, buildOPV(opcode, FLAG_INITIAL, 0)); } /** Helper function to set inherit generic value */ static inline css_error css_stylesheet_style_revert(css_style *style, opcode_t opcode) { style->sheet->uses_revert = true; return css__stylesheet_style_append(style, buildOPV(opcode, FLAG_REVERT, 0)); } /** Helper function to set initial generic value */ static inline css_error css_stylesheet_style_unset(css_style *style, opcode_t opcode) { return css__stylesheet_style_append(style, buildOPV(opcode, FLAG_UNSET, 0)); } /** Helper function to set initial generic value */ static inline css_error css_stylesheet_style_flag_value(css_style *style, enum flag_value flag_value, opcode_t opcode) { enum flag flag = flag_value << 1; if (flag == FLAG_REVERT) { style->sheet->uses_revert = true; } return css__stylesheet_style_append(style, buildOPV(opcode, flag, 0)); } css_error css__stylesheet_selector_create(css_stylesheet *sheet, css_qname *qname, css_selector **selector); css_error css__stylesheet_selector_destroy(css_stylesheet *sheet, css_selector *selector); css_error css__stylesheet_selector_detail_init(css_stylesheet *sheet, css_selector_type type, css_qname *qname, css_selector_detail_value value, css_selector_detail_value_type value_type, bool negate, css_selector_detail *detail); css_error css__stylesheet_selector_append_specific(css_stylesheet *sheet, css_selector **parent, const css_selector_detail *specific); css_error css__stylesheet_selector_combine(css_stylesheet *sheet, css_combinator type, css_selector *a, css_selector *b); css_error css__stylesheet_rule_create(css_stylesheet *sheet, css_rule_type type, css_rule **rule); css_error css__stylesheet_rule_destroy(css_stylesheet *sheet, css_rule *rule); css_error css__stylesheet_rule_add_selector(css_stylesheet *sheet, css_rule *rule, css_selector *selector); css_error css__stylesheet_rule_append_style(css_stylesheet *sheet, css_rule *rule, css_style *style); css_error css__stylesheet_rule_set_charset(css_stylesheet *sheet, css_rule *rule, lwc_string *charset); css_error css__stylesheet_rule_set_nascent_import(css_stylesheet *sheet, css_rule *rule, lwc_string *url, css_mq_query *media); css_error css__stylesheet_rule_set_media(css_stylesheet *sheet, css_rule *rule, css_mq_query *media); css_error css__stylesheet_rule_set_page_selector(css_stylesheet *sheet, css_rule *rule, css_selector *sel); css_error css__stylesheet_add_rule(css_stylesheet *sheet, css_rule *rule, css_rule *parent); css_error css__stylesheet_remove_rule(css_stylesheet *sheet, css_rule *rule); css_error css__stylesheet_string_get(css_stylesheet *sheet, uint32_t string_number, lwc_string **string); css_error css__stylesheet_string_add(css_stylesheet *sheet, lwc_string *string, uint32_t *string_number); #endif