summaryrefslogtreecommitdiff
path: root/Docs/ideas/css-engine.txt
blob: fb35e628ee5b553c0e9ff9a9bc16b9b94eea31ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
CSS engine
==========

Requirements
------------

 + Parse stylesheets conforming to the forward compatible CSS grammar
   (Note that in the short term, the semantic analysis stage only need
    support CSS2.1)
 + Stylesheet management/merging (i.e. multiple stylesheets may be added 
   to a single engine context and thus affect style selection)
 + Be able to select a style for a DOM node based upon the current stylesheets
   in the engine context.
 + Implemented as a standalone, reusable, library -- ideally MIT licensed.

Suggested API
-------------

struct css_context;
struct css_style;
struct css_stylesheet;

typedef struct css_context css_context;
typedef struct css_style css_style;
typedef struct css_stylesheet css_stylesheet;

typedef enum css_error {
	CSS_OK,
	CSS_NOMEM,
	/* etc */
} css_error;

typedef enum css_origin {
	CSS_ORIGIN_UA,
	CSS_ORIGIN_AUTHOR,
	CSS_ORIGIN_USER
} css_origin;

#define CSS_MEDIA_SCREEN (1<<0)
#define CSS_MEDIA_PRINT  (1<<1)
/* etc */
#define CSS_MEDIA_ALL    (0xffffffff)

#define CSS_PSEUDO_CLASS_NONE    (0)
#define CSS_PSEUDO_CLASS_LINK    (1<<0)
#define CSS_PSEUDO_CLASS_VISITED (1<<1)
#define CSS_PSEUDO_CLASS_HOVER   (1<<2)
#define CSS_PSEUDO_CLASS_ACTIVE  (1<<3)
#define CSS_PSEUDO_CLASS_FOCUS   (1<<4)

typedef enum css_property {
	CSS_BACKGROUND_ATTACHMENT,
	/* etc */
} css_property;

typedef struct css_value {
	css_property property;

	union {
		css_background_attachment background_attachment;
		/* etc */
	} value;
} css_value;

typedef css_error (*css_import_handler)(void *pw, const char *url,
		css_stylesheet *sheet);

/* Initialise library */
css_error css_init(void);
/* Finalise library */
css_error css_fini(void);

/* Create a stylesheet associated with the given URL,
 * specifying the sheet's origin, the media type(s) it applies to and 
 * a callback routine for fetching imported sheets */
css_stylesheet *css_stylesheet_create(const char *url, 
		css_origin origin, uint32_t media,
		css_import_handler import_callback, void *pw);
/* Destroy a stylesheet */
void css_stylesheet_destroy(css_stylesheet *sheet);

/* Append data to a stylesheet, parsing progressively */
css_error css_stylesheet_append_data(css_stylesheet *sheet,
		const uint8_t *data, size_t len);
/* Tell stylesheet parser that there's no more data (will complete parsing) */
css_error css_stylesheet_data_done(css_stylesheet *sheet);

/* Retrieve the URL associated with a stylesheet */
const char *css_stylesheet_get_url(css_stylesheet *sheet);
/* Retrieve the origin of a stylesheet */
css_origin css_stylesheet_get_origin(css_stylesheet *sheet);
/* Retrieve the media type(s) applicable to a stylesheet */
uint32_t css_stylesheet_get_media(css_stylesheet *sheet);

/* Create a selection context */
css_context *css_context_create(void);
/* Destroy a selection context */
void css_context_destroy(css_context *context);

/* Append a top-level stylesheet to a selection context */
css_error css_context_append_sheet(css_context *context,
		css_stylesheet *sheet);
/* Insert a top-level stylesheet into a selection context, at the given index */
css_error css_context_insert_sheet(css_context *context, 
		css_stylesheet *sheet, uint32_t index);
/* Remove a top-level stylesheet from a selection context */
css_error css_context_remove_sheet(css_context *context, 
		css_stylesheet *sheet);

/* Retrieve the total number of sheets in a selection context 
 * (includes imported sheets) */
uint32_t css_context_count_sheets(css_context *context);
/* Get a stylesheet from a selection context given an index [0, count) */
const css_stylesheet *css_context_get_sheet(css_context *context, 
		uint32_t index);

/* Select a style for a given DOM node with the given pseudo classes active
 * and media type.
 *
 * If the document language contains non-CSS presentational hints (e.g. HTML
 * presentational attributes etc), then these are passed in through 
 * property_list and treated as if they were encountered at the start of the
 * author stylesheet with a specificity of 0. */
css_style *css_style_select(css_context *context,
		<dom_node_type> *node, uint32_t pseudo_classes, uint32_t media,
		css_value **property_list, uint32_t property_list_length);
/* Destroy a selected style */
void css_style_destroy(css_style *style);

/* Retrieve a property value from a style */
css_value *css_value_get(css_style *style, css_property property);
/* Destroy a property value */
void css_value_destroy(css_value *value);

Memory management
-----------------

 + Stylesheets are owned by their creator. Selection contexts reference them.
 + Selection contexts are owned by the client.
 + Selected styles are owned by the client.
 + Property values are owned by the client.

 Therefore, the only difficulty lies within the handling of stylesheets 
 inserted into a selection context. The client code must ensure that a
 stylesheet is destroyed after it has been removed from any selection
 contexts which are using it.

DOM node types & tree traversal
-------------------------------

 This is currently undecided. Either the CSS engine is tied to a DOM 
 implementation (and makes API calls directly), or it's more generic and
 performs API calls through a vtable provided by the client.

Imported stylesheets
--------------------

 Imported stylesheets are handled by the CSS engine creating an appropriate
 css_stylesheet object for the imported sheet and then asking the client
 to fetch the data and append it to the sheet. The imported sheet is then 
 stored in the sheet that imported it. This effectively creates a tree of
 stylesheets beneath the initial top-level sheet created by the client.