summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/parse/Makefile2
-rw-r--r--src/parse/font_face.c413
-rw-r--r--src/parse/font_face.h22
-rw-r--r--src/parse/language.c42
-rw-r--r--src/parse/properties/utils.c45
-rw-r--r--src/parse/properties/utils.h14
-rw-r--r--src/parse/propstrings.c10
-rw-r--r--src/parse/propstrings.h5
-rw-r--r--src/select/Makefile2
-rw-r--r--src/select/font_face.c251
-rw-r--r--src/select/font_face.h53
-rw-r--r--src/select/select.c329
-rw-r--r--src/stylesheet.c26
-rw-r--r--src/stylesheet.h2
14 files changed, 1169 insertions, 47 deletions
diff --git a/src/parse/Makefile b/src/parse/Makefile
index a7548a8..3d1df42 100644
--- a/src/parse/Makefile
+++ b/src/parse/Makefile
@@ -1,4 +1,4 @@
# Sources
-DIR_SOURCES := parse.c language.c important.c propstrings.c
+DIR_SOURCES := parse.c language.c important.c propstrings.c font_face.c
include build/makefiles/Makefile.subdir
diff --git a/src/parse/font_face.c b/src/parse/font_face.c
new file mode 100644
index 0000000..14a715d
--- /dev/null
+++ b/src/parse/font_face.c
@@ -0,0 +1,413 @@
+/*
+ * This file is part of LibCSS.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2011 Things Made Out Of Other Things Ltd.
+ * Written by James Montgomerie <jamie@th.ingsmadeoutofotherthin.gs>
+ */
+
+#include "parse/font_face.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "parse/propstrings.h"
+#include "parse/properties/utils.h"
+#include "select/font_face.h"
+
+static bool font_rule_font_family_reserved(css_language *c,
+ const css_token *ident)
+{
+ bool match;
+
+ return (lwc_string_caseless_isequal(ident->idata, c->strings[SERIF],
+ &match) == lwc_error_ok && match) ||
+ (lwc_string_caseless_isequal(ident->idata,
+ c->strings[SANS_SERIF], &match) == lwc_error_ok &&
+ match) ||
+ (lwc_string_caseless_isequal(ident->idata, c->strings[CURSIVE],
+ &match) == lwc_error_ok && match) ||
+ (lwc_string_caseless_isequal(ident->idata, c->strings[FANTASY],
+ &match) == lwc_error_ok && match) ||
+ (lwc_string_caseless_isequal(ident->idata,
+ c->strings[MONOSPACE], &match) == lwc_error_ok &&
+ match) ||
+ (lwc_string_caseless_isequal(ident->idata, c->strings[INHERIT],
+ &match) == lwc_error_ok && match) ||
+ (lwc_string_caseless_isequal(ident->idata, c->strings[INITIAL],
+ &match) == lwc_error_ok && match) ||
+ (lwc_string_caseless_isequal(ident->idata, c->strings[DEFAULT],
+ &match) == lwc_error_ok && match);
+}
+
+static css_error font_face_parse_font_family(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_font_face *font_face)
+{
+ css_error error;
+ lwc_string *string;
+
+ error = css__ident_list_or_string_to_string(c, vector, ctx,
+ font_rule_font_family_reserved, &string);
+ if (error != CSS_OK)
+ return error;
+
+ css__font_face_set_font_family(font_face, string);
+
+ lwc_string_unref(string);
+
+ return CSS_OK;
+}
+
+static css_error font_face_src_parse_format(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_font_face_format *format)
+{
+ bool match;
+ const css_token *token;
+
+ *format = CSS_FONT_FACE_FORMAT_UNSPECIFIED;
+
+ /* 'format(' STRING [ ',' STRING ]* ')'
+ *
+ * 'format(' already consumed
+ */
+
+ do {
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || token->type != CSS_TOKEN_STRING)
+ return CSS_INVALID;
+
+ if (lwc_string_isequal(token->idata,
+ c->strings[WOFF], &match) == lwc_error_ok &&
+ match) {
+ *format |= CSS_FONT_FACE_FORMAT_WOFF;
+ } else if ((lwc_string_isequal(token->idata,
+ c->strings[TRUETYPE], &match) == lwc_error_ok &&
+ match) ||
+ (lwc_string_isequal(token->idata,
+ c->strings[OPENTYPE], &match) == lwc_error_ok &&
+ match)) {
+ *format |= CSS_FONT_FACE_FORMAT_OPENTYPE;
+ } else if (lwc_string_isequal(token->idata,
+ c->strings[EMBEDDED_OPENTYPE],
+ &match) == lwc_error_ok && match) {
+ *format |= CSS_FONT_FACE_FORMAT_EMBEDDED_OPENTYPE;
+ } else if (lwc_string_isequal(token->idata,
+ c->strings[SVG], &match) == lwc_error_ok &&
+ match) {
+ *format |= CSS_FONT_FACE_FORMAT_SVG;
+ } else {
+ /* The spec gives a list of possible strings, which
+ * hints that unknown strings should be parse errors,
+ * but it also talks about "unknown font formats",
+ * so we treat any string we don't know not as a parse
+ * error, but as indicating an "unknown font format".
+ */
+ *format |= CSS_FONT_FACE_FORMAT_UNKNOWN;
+ }
+
+ consumeWhitespace(vector, ctx);
+ token = parserutils_vector_iterate(vector, ctx);
+ } while (token != NULL && tokenIsChar(token, ','));
+
+ if (token == NULL || tokenIsChar(token, ')') == false)
+ return CSS_INVALID;
+
+ return CSS_OK;
+}
+
+static css_error font_face_src_parse_spec_or_name(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ lwc_string **location,
+ css_font_face_location_type *location_type,
+ css_font_face_format *format)
+{
+ const css_token *token;
+ css_error error;
+ bool match;
+
+ /* spec-or-name ::= font-face-spec | font-face-name
+ * font-face-spec ::= URI [ 'format(' STRING [ ',' STRING ]* ')' ]?
+ * font-face-name ::= 'local(' ident-list-or-string ')'
+ * ident-list-or-string ::= IDENT IDENT* | STRING
+ */
+
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL)
+ return CSS_INVALID;
+
+ if (token->type == CSS_TOKEN_URI) {
+ error = c->sheet->resolve(c->sheet->resolve_pw,
+ c->sheet->url, token->idata,
+ location);
+ if (error != CSS_OK)
+ return error;
+
+ *location_type = CSS_FONT_FACE_LOCATION_TYPE_URI;
+
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token != NULL && token->type == CSS_TOKEN_FUNCTION &&
+ lwc_string_caseless_isequal(token->idata,
+ c->strings[FORMAT], &match) == lwc_error_ok &&
+ match) {
+ parserutils_vector_iterate(vector, ctx);
+
+ error = font_face_src_parse_format(c, vector, ctx,
+ format);
+ if (error != CSS_OK) {
+ lwc_string_unref(*location);
+ return error;
+ }
+ }
+ } else if (token->type == CSS_TOKEN_FUNCTION &&
+ lwc_string_caseless_isequal(token->idata,
+ c->strings[LOCAL],
+ &match) == lwc_error_ok && match) {
+ consumeWhitespace(vector, ctx);
+
+ error = css__ident_list_or_string_to_string(
+ c, vector, ctx, NULL, location);
+ if (error != CSS_OK)
+ return error;
+
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || tokenIsChar(token, ')') == false) {
+ lwc_string_unref(*location);
+ return CSS_INVALID;
+ }
+
+ *location_type = CSS_FONT_FACE_LOCATION_TYPE_LOCAL;
+ } else {
+ return CSS_INVALID;
+ }
+
+ return CSS_OK;
+}
+
+static css_error font_face_parse_src(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_font_face *font_face)
+{
+ int orig_ctx = *ctx;
+ css_error error = CSS_OK;
+ const css_token *token;
+ css_font_face_src *srcs = NULL, *new_srcs = NULL;
+ uint32_t n_srcs = 0;
+
+ /* src ::= spec-or-name [ ',' spec-or-name ]*
+ * spec-or-name ::= font-face-spec | font-face-name
+ * font-face-spec ::= URI [ 'format(' STRING [ ',' STRING ]* ')' ]?
+ * font-face-name ::= 'local(' ident-list-or-string ')'
+ * ident-list-or-string ::= IDENT IDENT* | STRING
+ */
+
+ /* Create one css_font_face_src for each consecutive location and
+ * [potentially] type pair in the comma-separated list
+ */
+ do {
+ lwc_string *location;
+ css_font_face_location_type location_type =
+ CSS_FONT_FACE_LOCATION_TYPE_UNSPECIFIED;
+ css_font_face_format format =
+ CSS_FONT_FACE_FORMAT_UNSPECIFIED;
+
+ error = font_face_src_parse_spec_or_name(c, vector, ctx,
+ &location, &location_type, &format);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ /* This will be inefficient if there are a lot of locations -
+ * probably not a problem in practice.
+ */
+ new_srcs = c->alloc(srcs,
+ (n_srcs + 1) * sizeof(css_font_face_src),
+ c->pw);
+ if (new_srcs == NULL) {
+ error = CSS_NOMEM;
+ goto cleanup;
+ }
+ srcs = new_srcs;
+
+ srcs[n_srcs].location = location;
+ srcs[n_srcs].bits[0] = format << 2 | location_type;
+
+ ++n_srcs;
+
+ consumeWhitespace(vector, ctx);
+ token = parserutils_vector_iterate(vector, ctx);
+ } while (token != NULL && tokenIsChar(token, ','));
+
+ error = css__font_face_set_srcs(font_face, srcs, n_srcs);
+
+cleanup:
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ if (srcs != NULL)
+ c->alloc(srcs, 0, c->pw);
+ }
+
+ return error;
+}
+
+static css_error font_face_parse_font_style(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_font_face *font_face)
+{
+ int orig_ctx = *ctx;
+ css_error error = CSS_OK;
+ const css_token *token;
+ enum css_font_style_e style = 0;
+ bool match;
+
+ /* IDENT(normal, italic, oblique) */
+
+ token = parserutils_vector_iterate(vector, ctx);
+ if ((token == NULL) || ((token->type != CSS_TOKEN_IDENT))) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ if ((lwc_string_caseless_isequal(token->idata,
+ c->strings[NORMAL], &match) == lwc_error_ok && match)) {
+ style = CSS_FONT_STYLE_NORMAL;
+ } else if ((lwc_string_caseless_isequal(token->idata,
+ c->strings[ITALIC], &match) == lwc_error_ok && match)) {
+ style = CSS_FONT_STYLE_ITALIC;
+ } else if ((lwc_string_caseless_isequal(token->idata,
+ c->strings[OBLIQUE], &match) == lwc_error_ok &&
+ match)) {
+ style = CSS_FONT_STYLE_OBLIQUE;
+ } else {
+ error = CSS_INVALID;
+ }
+
+ if (error == CSS_OK) {
+ font_face->bits[0] = (font_face->bits[0] & 0xfc) | style;
+ } else {
+ *ctx = orig_ctx;
+ }
+
+ return error;
+}
+
+static css_error font_face_parse_font_weight(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_font_face *font_face)
+{
+ int orig_ctx = *ctx;
+ css_error error = CSS_OK;
+ const css_token *token;
+ enum css_font_weight_e weight = 0;
+ bool match;
+
+ /* NUMBER (100, 200, 300, 400, 500, 600, 700, 800, 900) |
+ * IDENT (normal, bold) */
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || (token->type != CSS_TOKEN_IDENT &&
+ token->type != CSS_TOKEN_NUMBER)) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ if (token->type == CSS_TOKEN_NUMBER) {
+ size_t consumed = 0;
+ css_fixed num = css__number_from_lwc_string(token->idata,
+ true, &consumed);
+ /* Invalid if there are trailing characters */
+ if (consumed != lwc_string_length(token->idata)) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ switch (FIXTOINT(num)) {
+ case 100: weight = CSS_FONT_WEIGHT_100; break;
+ case 200: weight = CSS_FONT_WEIGHT_200; break;
+ case 300: weight = CSS_FONT_WEIGHT_300; break;
+ case 400: weight = CSS_FONT_WEIGHT_400; break;
+ case 500: weight = CSS_FONT_WEIGHT_500; break;
+ case 600: weight = CSS_FONT_WEIGHT_600; break;
+ case 700: weight = CSS_FONT_WEIGHT_700; break;
+ case 800: weight = CSS_FONT_WEIGHT_800; break;
+ case 900: weight = CSS_FONT_WEIGHT_900; break;
+ default: error = CSS_INVALID;
+ }
+ } else if ((lwc_string_caseless_isequal(token->idata,
+ c->strings[NORMAL], &match) == lwc_error_ok && match)) {
+ weight = CSS_FONT_WEIGHT_NORMAL;
+ } else if ((lwc_string_caseless_isequal(token->idata,
+ c->strings[BOLD], &match) == lwc_error_ok && match)) {
+ weight = CSS_FONT_WEIGHT_BOLD;
+ } else {
+ error = CSS_INVALID;
+ }
+
+ if (error == CSS_OK) {
+ font_face->bits[0] = (font_face->bits[0] & 0xc3) |
+ (weight << 2);
+ } else {
+ *ctx = orig_ctx;
+ }
+
+ return error;
+}
+
+/**
+ * Parse a descriptor in an @font-face rule
+ *
+ * \param c Parsing context
+ * \param descriptor Token for this descriptor
+ * \param vector Vector of tokens to process
+ * \param ctx Pointer to vector iteration context
+ * \param rule Rule to process descriptor into
+ * \return CSS_OK on success,
+ * CSS_BADPARM on bad parameters,
+ * CSS_INVALID on invalid syntax,
+ * CSS_NOMEM on memory exhaustion
+ */
+css_error css__parse_font_descriptor(css_language *c,
+ const css_token *descriptor, const parserutils_vector *vector,
+ int *ctx, css_rule_font_face *rule)
+{
+ css_font_face *font_face = rule->font_face;
+ css_error error;
+ bool match;
+
+ if (font_face == NULL) {
+ error = css__font_face_create(c->sheet->alloc,
+ c->sheet->pw, &font_face);
+ if (error != CSS_OK) {
+ return error;
+ }
+
+ rule->font_face = font_face;
+ }
+
+ if (lwc_string_caseless_isequal(descriptor->idata,
+ c->strings[FONT_FAMILY], &match) == lwc_error_ok &&
+ match) {
+ return font_face_parse_font_family(c, vector, ctx, font_face);
+ } else if (lwc_string_caseless_isequal(descriptor->idata,
+ c->strings[SRC], &match) == lwc_error_ok && match) {
+ return font_face_parse_src(c, vector, ctx, font_face);
+ } else if (lwc_string_caseless_isequal(descriptor->idata,
+ c->strings[FONT_STYLE], &match) == lwc_error_ok &&
+ match) {
+ return font_face_parse_font_style(c, vector, ctx, font_face);
+ } else if (lwc_string_caseless_isequal(descriptor->idata,
+ c->strings[FONT_WEIGHT], &match) == lwc_error_ok &&
+ match) {
+ return font_face_parse_font_weight(c, vector, ctx, font_face);
+ }
+
+ return CSS_INVALID;
+}
+
diff --git a/src/parse/font_face.h b/src/parse/font_face.h
new file mode 100644
index 0000000..435380e
--- /dev/null
+++ b/src/parse/font_face.h
@@ -0,0 +1,22 @@
+/*
+ * This file is part of LibCSS.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2011 Things Made Out Of Other Things Ltd.
+ * Written by James Montgomerie <jamie@th.ingsmadeoutofotherthin.gs>
+ */
+
+#ifndef css_parse_font_face_h_
+#define css_parse_font_face_h_
+
+#include <parserutils/utils/vector.h>
+
+#include "stylesheet.h"
+#include "lex/lex.h"
+#include "parse/language.h"
+
+css_error css__parse_font_descriptor(css_language *c,
+ const css_token *descriptor, const parserutils_vector *vector,
+ int *ctx, struct css_rule_font_face *rule);
+
+#endif
diff --git a/src/parse/language.c b/src/parse/language.c
index 0436c22..a5fce0e 100644
--- a/src/parse/language.c
+++ b/src/parse/language.c
@@ -12,6 +12,7 @@
#include "stylesheet.h"
#include "lex/lex.h"
+#include "parse/font_face.h"
#include "parse/important.h"
#include "parse/language.h"
#include "parse/parse.h"
@@ -558,6 +559,26 @@ css_error handleStartAtRule(css_language *c, const parserutils_vector *vector)
* so no need to destroy it */
c->state = HAD_RULE;
+ } else if (lwc_string_caseless_isequal(atkeyword->idata,
+ c->strings[FONT_FACE], &match) == lwc_error_ok &&
+ match) {
+ error = css__stylesheet_rule_create(c->sheet,
+ CSS_RULE_FONT_FACE, &rule);
+ if (error != CSS_OK)
+ return error;
+
+ consumeWhitespace(vector, &ctx);
+
+ error = css__stylesheet_add_rule(c->sheet, rule, NULL);
+ if (error != CSS_OK) {
+ css__stylesheet_rule_destroy(c->sheet, rule);
+ return error;
+ }
+
+ /* Rule is now owned by the sheet,
+ * so no need to destroy it */
+
+ c->state = HAD_RULE;
} else if (lwc_string_caseless_isequal(atkeyword->idata, c->strings[PAGE],
&match) == lwc_error_ok && match) {
const css_token *token;
@@ -693,9 +714,9 @@ css_error handleBlockContent(css_language *c, const parserutils_vector *vector)
context_entry *entry;
css_rule *rule;
- /* In CSS 2.1, block content comprises either declarations (if the
- * current block is associated with @page or a selector), or rulesets
- * (if the current block is associated with @media). */
+ /* Block content comprises either declarations (if the current block is
+ * associated with @page, @font-face or a selector), or rulesets (if the
+ * current block is associated with @media). */
entry = parserutils_stack_get_current(c->context);
if (entry == NULL || entry->data == NULL)
@@ -704,7 +725,8 @@ css_error handleBlockContent(css_language *c, const parserutils_vector *vector)
rule = entry->data;
if (rule == NULL || (rule->type != CSS_RULE_SELECTOR &&
rule->type != CSS_RULE_PAGE &&
- rule->type != CSS_RULE_MEDIA))
+ rule->type != CSS_RULE_MEDIA &&
+ rule->type != CSS_RULE_FONT_FACE))
return CSS_INVALID;
if (rule->type == CSS_RULE_MEDIA) {
@@ -729,6 +751,7 @@ css_error handleDeclaration(css_language *c, const parserutils_vector *vector)
/* Locations where declarations are permitted:
*
* + In @page
+ * + In @font-face
* + In ruleset
*/
entry = parserutils_stack_get_current(c->context);
@@ -737,7 +760,8 @@ css_error handleDeclaration(css_language *c, const parserutils_vector *vector)
rule = entry->data;
if (rule == NULL || (rule->type != CSS_RULE_SELECTOR &&
- rule->type != CSS_RULE_PAGE))
+ rule->type != CSS_RULE_PAGE &&
+ rule->type != CSS_RULE_FONT_FACE))
return CSS_INVALID;
/* Strip any leading whitespace (can happen if in nested block) */
@@ -759,7 +783,13 @@ css_error handleDeclaration(css_language *c, const parserutils_vector *vector)
consumeWhitespace(vector, &ctx);
- error = parseProperty(c, ident, vector, &ctx, rule);
+ if (rule->type == CSS_RULE_FONT_FACE) {
+ css_rule_font_face * ff_rule = (css_rule_font_face *) rule;
+ error = css__parse_font_descriptor(
+ c, ident, vector, &ctx, ff_rule);
+ } else {
+ error = parseProperty(c, ident, vector, &ctx, rule);
+ }
if (error != CSS_OK)
return error;
diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c
index bf7e212..4eca6fc 100644
--- a/src/parse/properties/utils.c
+++ b/src/parse/properties/utils.c
@@ -1044,6 +1044,45 @@ css_error css__parse_unit_keyword(const char *ptr, size_t len, css_unit *unit)
}
/**
+ * Create a string from a list of IDENT/S tokens if the next token is IDENT
+ * or references the next token's string if it is a STRING
+ *
+ * \param c Parsing context
+ * \param vector Vector containing tokens
+ * \param ctx Vector iteration context
+ * \param reserved Callback to determine if an identifier is reserved
+ * \param result Pointer to location to receive resulting string
+ * \return CSS_OK on success, appropriate error otherwise.
+ *
+ * Post condition: \a *ctx is updated with the next token to process
+ * If the input is invalid, then \a *ctx remains unchanged.
+ *
+ * The resulting string's reference is passed to the caller
+ */
+css_error css__ident_list_or_string_to_string(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ bool (*reserved)(css_language *c, const css_token *ident),
+ lwc_string **result)
+{
+ const css_token *token;
+
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token == NULL)
+ return CSS_INVALID;
+
+ if (token->type == CSS_TOKEN_STRING) {
+ token = parserutils_vector_iterate(vector, ctx);
+ *result = lwc_string_ref(token->idata);
+ return CSS_OK;
+ } else if(token->type == CSS_TOKEN_IDENT) {
+ return css__ident_list_to_string(c, vector, ctx, reserved,
+ result);
+ }
+
+ return CSS_INVALID;
+}
+
+/**
* Create a string from a list of IDENT/S tokens
*
* \param c Parsing context
@@ -1058,7 +1097,7 @@ css_error css__parse_unit_keyword(const char *ptr, size_t len, css_unit *unit)
*
* The resulting string's reference is passed to the caller
*/
-static css_error ident_list_to_string(css_language *c,
+css_error css__ident_list_to_string(css_language *c,
const parserutils_vector *vector, int *ctx,
bool (*reserved)(css_language *c, const css_token *ident),
lwc_string **result)
@@ -1084,7 +1123,7 @@ static css_error ident_list_to_string(css_language *c,
token->type == CSS_TOKEN_S)) {
if (token->type == CSS_TOKEN_IDENT) {
/* IDENT -- if reserved, reject style */
- if (reserved(c, token)) {
+ if (reserved != NULL && reserved(c, token)) {
error = CSS_INVALID;
goto cleanup;
}
@@ -1175,7 +1214,7 @@ css_error css__comma_list_to_style(css_language *c,
*ctx = prev_ctx;
- error = ident_list_to_string(c, vector, ctx,
+ error = css__ident_list_to_string(c, vector, ctx,
reserved, &str);
if (error != CSS_OK)
goto cleanup;
diff --git a/src/parse/properties/utils.h b/src/parse/properties/utils.h
index ab045bd..be903ee 100644
--- a/src/parse/properties/utils.h
+++ b/src/parse/properties/utils.h
@@ -181,10 +181,22 @@ css_error css__parse_unit_specifier(css_language *c,
css_error css__parse_unit_keyword(const char *ptr, size_t len,
css_unit *unit);
+css_error css__ident_list_or_string_to_string(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ bool (*reserved)(css_language *c, const css_token *ident),
+ lwc_string **result);
+
+css_error css__ident_list_to_string(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ bool (*reserved)(css_language *c, const css_token *ident),
+ lwc_string **result);
+
css_error css__comma_list_to_style(css_language *c,
const parserutils_vector *vector, int *ctx,
bool (*reserved)(css_language *c, const css_token *ident),
- css_code_t (*get_value)(css_language *c, const css_token *token, bool first),
+ css_code_t (*get_value)(css_language *c,
+ const css_token *token,
+ bool first),
css_style *result);
#endif
diff --git a/src/parse/propstrings.c b/src/parse/propstrings.c
index bf1fcd0..dea8816 100644
--- a/src/parse/propstrings.c
+++ b/src/parse/propstrings.c
@@ -30,6 +30,7 @@ const stringmap_entry stringmap[LAST_KNOWN] = {
{ "import", SLEN("import") },
{ "media", SLEN("media") },
{ "namespace", SLEN("namespace") },
+ { "font-face", SLEN("font-face") },
{ "page", SLEN("page") },
{ "aural", SLEN("aural") },
@@ -372,6 +373,15 @@ const stringmap_entry stringmap[LAST_KNOWN] = {
{ "currentColor", SLEN("currentColor") },
{ "odd", SLEN("odd") },
{ "even", SLEN("even") },
+ { "src", SLEN("src") },
+ { "local", SLEN("local") },
+ { "initial", SLEN("initial") },
+ { "format", SLEN("format") },
+ { "woff", SLEN("woff") },
+ { "truetype", SLEN("truetype") },
+ { "opentype", SLEN("opentype") },
+ { "embedded-opentype", SLEN("embedded-opentype") },
+ { "svg", SLEN("svg") },
{ "aliceblue", SLEN("aliceblue") },
{ "antiquewhite", SLEN("antiquewhite") },
diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h
index 7c7b693..16affcd 100644
--- a/src/parse/propstrings.h
+++ b/src/parse/propstrings.h
@@ -15,7 +15,7 @@ enum {
UNIVERSAL,
/* At-rules */
- CHARSET, LIBCSS_IMPORT, MEDIA, NAMESPACE, PAGE,
+ CHARSET, LIBCSS_IMPORT, MEDIA, NAMESPACE, FONT_FACE, PAGE,
/* Media types */
AURAL, BRAILLE, EMBOSSED, HANDHELD, PRINT, PROJECTION,
@@ -88,7 +88,8 @@ enum {
W_RESIZE, LIBCSS_TEXT, WAIT, HELP, PROGRESS, SERIF, SANS_SERIF, CURSIVE,
FANTASY, MONOSPACE, MALE, FEMALE, CHILD, MIX, UNDERLINE, OVERLINE,
LINE_THROUGH, BLINK, RGB, RGBA, HSL, HSLA, LIBCSS_LEFT, LIBCSS_CENTER,
- LIBCSS_RIGHT, CURRENTCOLOR, ODD, EVEN,
+ LIBCSS_RIGHT, CURRENTCOLOR, ODD, EVEN, SRC, LOCAL, INITIAL,
+ FORMAT, WOFF, TRUETYPE, OPENTYPE, EMBEDDED_OPENTYPE, SVG,
/* Named colours */
FIRST_COLOUR,
diff --git a/src/select/Makefile b/src/select/Makefile
index db1c4e6..b99eab3 100644
--- a/src/select/Makefile
+++ b/src/select/Makefile
@@ -1,4 +1,4 @@
# Sources
-DIR_SOURCES := computed.c dispatch.c hash.c select.c
+DIR_SOURCES := computed.c dispatch.c hash.c select.c font_face.c
include build/makefiles/Makefile.subdir
diff --git a/src/select/font_face.c b/src/select/font_face.c
new file mode 100644
index 0000000..ae24827
--- /dev/null
+++ b/src/select/font_face.c
@@ -0,0 +1,251 @@
+/*
+ * This file is part of LibCSS.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2011 Things Made Out Of Other Things Ltd.
+ * Written by James Montgomerie <jamie@th.ingsmadeoutofotherthin.gs>
+ */
+
+#include <string.h>
+
+#include "select/font_face.h"
+
+static void font_faces_srcs_destroy(css_font_face *font_face)
+{
+ uint32_t i;
+ css_font_face_src *srcs = font_face->srcs;
+
+ for (i = 0; i < font_face->n_srcs; ++i) {
+ if (srcs[i].location != NULL) {
+ lwc_string_unref(srcs[i].location);
+ }
+ }
+
+ font_face->alloc(srcs, 0, font_face->pw);
+ font_face->srcs = NULL;
+}
+
+/**
+ * Create a font-face
+ *
+ * \param alloc Memory (de)allocation function
+ * \param pw Pointer to client-specific data
+ * \param result Pointer to location to receive result
+ * \return CSS_OK on success,
+ * CSS_NOMEM on memory exhaustion,
+ * CSS_BADPARM on bad parameters.
+ */
+css_error css__font_face_create(css_allocator_fn alloc, void *pw,
+ css_font_face **result)
+{
+ css_font_face *f;
+
+ if (alloc == NULL || result == NULL)
+ return CSS_BADPARM;
+
+ f = alloc(NULL, sizeof(css_font_face), pw);
+ if (f == NULL)
+ return CSS_NOMEM;
+
+ memset(f, 0, sizeof(css_font_face));
+
+ f->alloc = alloc;
+ f->pw = pw;
+
+ *result = f;
+
+ return CSS_OK;
+}
+
+/**
+ * Destroy a font-face
+ *
+ * \param font_face Font-face to destroy
+ * \return CSS_OK on success, appropriate error otherwise
+ */
+css_error css__font_face_destroy(css_font_face *font_face)
+{
+ if (font_face == NULL)
+ return CSS_BADPARM;
+
+ if (font_face->font_family != NULL)
+ lwc_string_unref(font_face->font_family);
+
+ if (font_face->srcs != NULL)
+ font_faces_srcs_destroy(font_face);
+
+ font_face->alloc(font_face, 0, font_face->pw);
+
+ return CSS_OK;
+}
+
+
+/**
+ * Set a font-face's font-family name
+ *
+ * \param font_face The font-face
+ * \param font_family Font-family name
+ * \param result Pointer to location to receive result
+ * \return CSS_OK on success,
+ * CSS_BADPARM on bad parameters.
+ */
+css_error css__font_face_set_font_family(css_font_face *font_face,
+ lwc_string *font_family)
+{
+ if (font_face == NULL || font_family == NULL)
+ return CSS_BADPARM;
+
+ if (font_face->font_family != NULL)
+ lwc_string_unref(font_face->font_family);
+
+ font_face->font_family = lwc_string_ref(font_family);
+
+ return CSS_OK;
+}
+
+/**
+ * Get a font-face's font-family name
+ *
+ * \param font_face The font-face
+ * \param result Pointer to location to receive result
+ * \return CSS_OK on success,
+ * CSS_BADPARM on bad parameters.
+ */
+css_error css_font_face_get_font_family(const css_font_face *font_face,
+ lwc_string **font_family)
+{
+ if (font_face == NULL || font_family == NULL)
+ return CSS_BADPARM;
+
+ *font_family = font_face->font_family;
+
+ return CSS_OK;
+}
+
+/**
+ * Get the style of font for a font-face.
+ *
+ * \param src The font-face
+ * \return The style, as a css_font_style_e
+ */
+uint8_t css_font_face_font_style(const css_font_face *font_face)
+{
+ return font_face->bits[0] & 0x3;
+}
+
+/**
+ * Get the weight of font for a font-face.
+ *
+ * \param src The font-face
+ * \return The style, as a css_font_weight_e
+ */
+uint8_t css_font_face_font_weight(const css_font_face *font_face)
+{
+ return (font_face->bits[0] >> 2) & 0xf;
+}
+
+/**
+ * Get the number of potential src locations for a font-face
+ *
+ * \param font_face The font-face
+ * \param count Pointer to location to receive result
+ * \return CSS_OK on success,
+ * CSS_BADPARM on bad parameters.
+ */
+css_error css_font_face_count_srcs(const css_font_face *font_face,
+ uint32_t *count)
+{
+ if (font_face == NULL || count == NULL)
+ return CSS_BADPARM;
+
+ *count = font_face->n_srcs;
+ return CSS_OK;
+}
+
+/**
+ * Get a specific src location from a font-face
+ *
+ * \param font_face The font-face
+ * \param index The index for the wanted src.
+ * \param count Pointer to location to receive result
+ * \return CSS_OK on success,
+ * CSS_BADPARM on bad parameters.
+ */
+css_error css_font_face_get_src(const css_font_face *font_face,
+ uint32_t index, const css_font_face_src **src)
+{
+ if (font_face == NULL || src == NULL || index >= font_face->n_srcs)
+ return CSS_BADPARM;
+
+ *src = &(font_face->srcs[index]);
+
+ return CSS_OK;
+}
+
+/**
+ * Get the location for a font-face src.
+ *
+ * \param font_face The font-face
+ * \param count Pointer to location to receive result
+ * \return CSS_OK on success,
+ * CSS_BADPARM on bad parameters.
+ *
+ * \note The type of location (local or URL) can be gathered from
+ * css_font_face_src_location_type, and the format of font (if specified)
+ * from css_font_face_src_format.
+ */
+css_error css_font_face_src_get_location(const css_font_face_src *src,
+ lwc_string **location)
+{
+ if (src == NULL || location == NULL)
+ return CSS_BADPARM;
+
+ *location = src->location;
+
+ return CSS_OK;
+}
+
+/**
+ * Get the location type for a font-face src.
+ *
+ * \param src The font-face src
+ * \return The location type
+ */
+css_font_face_location_type css_font_face_src_location_type(
+ const css_font_face_src *src)
+{
+ return src->bits[0] & 0x3;
+}
+
+/**
+ * Get the format of font for a font-face src.
+ *
+ * \param src The font-face src
+ * \return The format, if specified
+ */
+css_font_face_format css_font_face_src_format(const css_font_face_src *src)
+{
+ return (src->bits[0] >> 2) & 0x1f;
+}
+
+/**
+ * Set a font-faces array of srcs.
+ *
+ * \param font_face The font-face
+ * \param srcs The array of css_font_face_srcs
+ * \param n_srcs The count of css_font_face_srcs in the array
+ * \return The format, if specified
+ */
+css_error css__font_face_set_srcs(css_font_face *font_face,
+ css_font_face_src *srcs, uint32_t n_srcs)
+{
+ if (font_face->srcs != NULL)
+ font_faces_srcs_destroy(font_face);
+
+ font_face->srcs = srcs;
+ font_face->n_srcs = n_srcs;
+
+ return CSS_OK;
+}
+
+
diff --git a/src/select/font_face.h b/src/select/font_face.h
new file mode 100644
index 0000000..3572de8
--- /dev/null
+++ b/src/select/font_face.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of LibCSS.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2011 Things Made Out Of Other Things Ltd.
+ * Written by James Montgomerie <jamie@th.ingsmadeoutofotherthin.gs>
+ */
+
+#ifndef css_select_font_face_h_
+#define css_select_font_face_h_
+
+#include <libcss/font_face.h>
+
+
+struct css_font_face_src {
+ lwc_string *location;
+ /*
+ * Bit allocations:
+ *
+ * 76543210
+ * 1 _fffffll format | location type
+ */
+ uint8_t bits[1];
+};
+
+struct css_font_face {
+ lwc_string *font_family;
+ css_font_face_src *srcs;
+ uint32_t n_srcs;
+
+ /*
+ * Bit allocations:
+ *
+ * 76543210
+ * 1 __wwwwss font-weight | font-style
+ */
+ uint8_t bits[1];
+
+ css_allocator_fn alloc;
+ void *pw;
+};
+
+css_error css__font_face_create(css_allocator_fn alloc, void *pw,
+ css_font_face **result);
+css_error css__font_face_destroy(css_font_face *font_face);
+
+css_error css__font_face_set_font_family(css_font_face *font_face,
+ lwc_string *font_family);
+
+css_error css__font_face_set_srcs(css_font_face *font_face,
+ css_font_face_src *srcs, uint32_t n_srcs);
+
+#endif
diff --git a/src/select/select.c b/src/select/select.c
index 7baac03..4243140 100644
--- a/src/select/select.c
+++ b/src/select/select.c
@@ -8,6 +8,8 @@
#include <assert.h>
#include <string.h>
+#include <libwapcaplet/libwapcaplet.h>
+
#include <libcss/select.h>
#include "bytecode/bytecode.h"
@@ -17,6 +19,7 @@
#include "select/dispatch.h"
#include "select/hash.h"
#include "select/propset.h"
+#include "select/font_face.h"
#include "select/select.h"
#include "utils/parserutilserror.h"
#include "utils/utils.h"
@@ -74,6 +77,27 @@ struct css_select_ctx {
lwc_string *after;
};
+/**
+ * Container for selected font faces
+ */
+typedef struct css_select_font_faces_list {
+ const css_font_face **font_faces;
+ size_t count;
+} css_select_font_faces_list;
+
+/**
+ * Font face selection state
+ */
+typedef struct css_select_font_faces_state {
+ lwc_string *font_family;
+ uint64_t media;
+
+ css_select_font_faces_list ua_font_faces;
+ css_select_font_faces_list user_font_faces;
+ css_select_font_faces_list author_font_faces;
+} css_select_font_faces_state;
+
+
static css_error set_hint(css_select_state *state, uint32_t prop);
static css_error set_initial(css_select_state *state,
uint32_t prop, css_pseudo_element pseudo,
@@ -104,6 +128,11 @@ static css_error match_detail(css_select_ctx *ctx, void *node,
bool *match, css_pseudo_element *pseudo_element);
static css_error cascade_style(const css_style *style, css_select_state *state);
+static css_error select_font_faces_from_sheet(css_select_ctx *ctx,
+ const css_stylesheet *sheet,
+ css_origin origin,
+ css_select_font_faces_state *state);
+
#ifdef DEBUG_CHAIN_MATCHING
static void dump_chain(const css_selector *selector);
#endif
@@ -558,6 +587,144 @@ css_error css_select_results_destroy(css_select_results *results)
return CSS_OK;
}
+/**
+ * Search a selection context for defined font faces
+ *
+ * \param ctx Selection context
+ * \param media Currently active media types
+ * \param font_family Font family to search for
+ * \param result Pointer to location to receive result
+ * \return CSS_OK on success, appropriate error otherwise.
+ */
+css_error css_select_font_faces(css_select_ctx *ctx,
+ uint64_t media, lwc_string *font_family,
+ css_select_font_faces_results **result)
+{
+ uint32_t i;
+ css_error error;
+ css_select_font_faces_state state;
+ uint32_t n_font_faces;
+
+ if (ctx == NULL || font_family == NULL || result == NULL)
+ return CSS_BADPARM;
+
+ memset(&state, 0, sizeof(css_select_font_faces_state));
+ state.font_family = font_family;
+ state.media = media;
+
+ /* Iterate through the top-level stylesheets, selecting font-faces
+ * from those which apply to our current media requirements and
+ * are not disabled */
+ for (i = 0; i < ctx->n_sheets; i++) {
+ const css_select_sheet s = ctx->sheets[i];
+
+ if ((s.media & media) != 0 &&
+ s.sheet->disabled == false) {
+ error = select_font_faces_from_sheet(ctx, s.sheet,
+ s.origin, &state);
+ if (error != CSS_OK)
+ goto cleanup;
+ }
+ }
+
+ n_font_faces = state.ua_font_faces.count +
+ state.user_font_faces.count +
+ state.author_font_faces.count;
+
+
+ if (n_font_faces > 0) {
+ /* We found some matching faces. Make a results structure with
+ * the font faces in priority order. */
+ css_select_font_faces_results *results;
+
+ results = ctx->alloc(NULL,
+ sizeof(css_select_font_faces_results),
+ ctx->pw);
+ if (results == NULL) {
+ error = CSS_NOMEM;
+ goto cleanup;
+ }
+
+ results->alloc = ctx->alloc;
+ results->pw = ctx->pw;
+
+ results->font_faces = ctx->alloc(NULL,
+ n_font_faces * sizeof(css_font_face *),
+ ctx->pw);
+ if (results->font_faces == NULL) {
+ ctx->alloc(results, 0, ctx->pw);
+ error = CSS_NOMEM;
+ goto cleanup;
+ }
+
+ results->n_font_faces = n_font_faces;
+
+ i = 0;
+ if (state.ua_font_faces.count != 0) {
+ memcpy(results->font_faces,
+ state.ua_font_faces.font_faces,
+ sizeof(css_font_face *) *
+ state.ua_font_faces.count);
+
+ i += state.ua_font_faces.count;
+ }
+
+ if (state.user_font_faces.count != 0) {
+ memcpy(results->font_faces + i,
+ state.user_font_faces.font_faces,
+ sizeof(css_font_face *) *
+ state.user_font_faces.count);
+ i += state.user_font_faces.count;
+ }
+
+ if (state.author_font_faces.count != 0) {
+ memcpy(results->font_faces + i,
+ state.author_font_faces.font_faces,
+ sizeof(css_font_face *) *
+ state.author_font_faces.count);
+ }
+
+ *result = results;
+ }
+
+ error = CSS_OK;
+
+cleanup:
+ if (state.ua_font_faces.count != 0)
+ ctx->alloc(state.ua_font_faces.font_faces, 0, ctx->pw);
+
+ if (state.user_font_faces.count != 0)
+ ctx->alloc(state.user_font_faces.font_faces, 0, ctx->pw);
+
+ if (state.author_font_faces.count != 0)
+ ctx->alloc(state.author_font_faces.font_faces, 0, ctx->pw);
+
+ return error;
+}
+
+/**
+ * Destroy a font-face result set
+ *
+ * \param results Result set to destroy
+ * \return CSS_OK on success, appropriate error otherwise
+ */
+css_error css_select_font_faces_results_destroy(
+ css_select_font_faces_results *results)
+{
+ if (results == NULL)
+ return CSS_BADPARM;
+
+ if (results->font_faces != NULL) {
+ /* Don't destroy the individual css_font_faces, they're owned
+ by their respective sheets */
+ results->alloc(results->font_faces, 0, results->pw);
+ }
+
+ results->alloc(results, 0, results->pw);
+
+ return CSS_OK;
+}
+
/******************************************************************************
* Selection engine internals below here *
******************************************************************************/
@@ -870,13 +1037,14 @@ css_error set_initial(css_select_state *state,
return CSS_OK;
}
+#define IMPORT_STACK_SIZE 256
+
css_error select_from_sheet(css_select_ctx *ctx, const css_stylesheet *sheet,
css_origin origin, css_select_state *state)
{
const css_stylesheet *s = sheet;
const css_rule *rule = s->rule_list;
uint32_t sp = 0;
-#define IMPORT_STACK_SIZE 256
const css_rule *import_stack[IMPORT_STACK_SIZE];
do {
@@ -894,7 +1062,8 @@ css_error select_from_sheet(css_select_ctx *ctx, const css_stylesheet *sheet,
if (import->sheet != NULL &&
(import->media & state->media) != 0) {
/* It's applicable, so process it */
- assert(sp < IMPORT_STACK_SIZE - 1);
+ if (sp >= IMPORT_STACK_SIZE)
+ return CSS_NOMEM;
import_stack[sp++] = rule;
@@ -930,6 +1099,144 @@ css_error select_from_sheet(css_select_ctx *ctx, const css_stylesheet *sheet,
return CSS_OK;
}
+static inline bool _rule_applies_to_media(const css_rule *rule, uint64_t media)
+{
+ bool applies = true;
+ const css_rule *ancestor = rule;
+
+ while (ancestor != NULL) {
+ const css_rule_media *m = (const css_rule_media *) ancestor;
+
+ if (ancestor->type == CSS_RULE_MEDIA &&
+ (m->media & media) == 0) {
+ applies = false;
+ break;
+ }
+
+ if (ancestor->ptype != CSS_RULE_PARENT_STYLESHEET)
+ ancestor = ancestor->parent;
+ else
+ ancestor = NULL;
+ }
+
+ return applies;
+}
+
+static css_error _select_font_face_from_rule(css_select_ctx *ctx,
+ const css_rule_font_face *rule, css_origin origin,
+ css_select_font_faces_state *state)
+{
+ if (_rule_applies_to_media((const css_rule *) rule, state->media)) {
+ bool correct_family = false;
+
+ if (lwc_string_isequal(
+ rule->font_face->font_family,
+ state->font_family,
+ &correct_family) == lwc_error_ok &&
+ correct_family) {
+ css_select_font_faces_list *faces = NULL;
+ const css_font_face **new_faces;
+ uint32_t index;
+ size_t new_size;
+
+ switch (origin) {
+ case CSS_ORIGIN_UA:
+ faces = &state->ua_font_faces;
+ break;
+ case CSS_ORIGIN_USER:
+ faces = &state->user_font_faces;
+ break;
+ case CSS_ORIGIN_AUTHOR:
+ faces = &state->author_font_faces;
+ break;
+ }
+
+ index = faces->count++;
+ new_size = faces->count * sizeof(css_font_face *);
+
+ new_faces = ctx->alloc(faces->font_faces,
+ new_size, ctx->pw);
+ if (new_faces == NULL) {
+ faces->count = 0;
+ return CSS_NOMEM;
+ }
+ faces->font_faces = new_faces;
+
+ faces->font_faces[index] = rule->font_face;
+ }
+ }
+
+ return CSS_OK;
+}
+
+static css_error select_font_faces_from_sheet(css_select_ctx *ctx,
+ const css_stylesheet *sheet,
+ css_origin origin,
+ css_select_font_faces_state *state)
+{
+ const css_stylesheet *s = sheet;
+ const css_rule *rule = s->rule_list;
+ uint32_t sp = 0;
+ const css_rule *import_stack[IMPORT_STACK_SIZE];
+
+ do {
+ /* Find first non-charset rule, if we're at the list head */
+ if (rule == s->rule_list) {
+ while (rule != NULL && rule->type == CSS_RULE_CHARSET)
+ rule = rule->next;
+ }
+
+ if (rule != NULL && rule->type == CSS_RULE_IMPORT) {
+ /* Current rule is an import */
+ const css_rule_import *import =
+ (const css_rule_import *) rule;
+
+ if (import->sheet != NULL &&
+ (import->media & state->media) != 0) {
+ /* It's applicable, so process it */
+ if (sp >= IMPORT_STACK_SIZE)
+ return CSS_NOMEM;
+
+ import_stack[sp++] = rule;
+
+ s = import->sheet;
+ rule = s->rule_list;
+ } else {
+ /* Not applicable; skip over it */
+ rule = rule->next;
+ }
+ } else if (rule != NULL && rule->type == CSS_RULE_FONT_FACE) {
+ css_error error;
+
+ error = _select_font_face_from_rule(
+ ctx,
+ (const css_rule_font_face *) rule,
+ origin,
+ state);
+
+ if (error != CSS_OK)
+ return error;
+
+ rule = rule->next;
+ } else if (rule == NULL) {
+ /* Find next sheet to process */
+ if (sp > 0) {
+ sp--;
+ rule = import_stack[sp]->next;
+ s = import_stack[sp]->parent;
+ } else {
+ s = NULL;
+ }
+ } else {
+ rule = rule->next;
+ }
+ } while (s != NULL);
+
+ return CSS_OK;
+}
+
+#undef IMPORT_STACK_SIZE
+
static inline bool _selectors_pending(const css_selector **node,
const css_selector **id, const css_selector ***classes,
uint32_t n_classes, const css_selector **univ)
@@ -1063,8 +1370,6 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx,
while (_selectors_pending(node_selectors, id_selectors,
class_selectors, n_classes, univ_selectors)) {
const css_selector *selector;
- css_rule *rule, *parent;
- bool process = true;
/* Selectors must be matched in ascending order of specificity
* and rule index. (c.f. css__outranks_existing())
@@ -1077,21 +1382,7 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx,
/* Ignore any selectors contained in rules which are a child
* of an @media block that doesn't match the current media
* requirements. */
- for (rule = selector->rule; rule != NULL; rule = parent) {
- if (rule->type == CSS_RULE_MEDIA &&
- (((css_rule_media *) rule)->media &
- state->media) == 0) {
- process = false;
- break;
- }
-
- if (rule->ptype != CSS_RULE_PARENT_STYLESHEET)
- parent = rule->parent;
- else
- parent = NULL;
- }
-
- if (process) {
+ if (_rule_applies_to_media(selector->rule, state->media)) {
error = match_selector_chain(ctx, selector, state);
if (error != CSS_OK)
goto cleanup;
diff --git a/src/stylesheet.c b/src/stylesheet.c
index f8dedac..e37a00a 100644
--- a/src/stylesheet.c
+++ b/src/stylesheet.c
@@ -15,6 +15,7 @@
#include "utils/parserutilserror.h"
#include "utils/utils.h"
#include "select/dispatch.h"
+#include "select/font_face.h"
static css_error _add_selectors(css_stylesheet *sheet, css_rule *rule);
static css_error _remove_selectors(css_stylesheet *sheet, css_rule *rule);
@@ -261,7 +262,7 @@ css_error css_stylesheet_create(const css_stylesheet_params *params,
*/
css_error css_stylesheet_destroy(css_stylesheet *sheet)
{
- uint32_t string_index;
+ uint32_t index;
css_rule *r, *s;
if (sheet == NULL)
@@ -296,17 +297,17 @@ css_error css_stylesheet_destroy(css_stylesheet *sheet)
css__stylesheet_style_destroy(sheet->cached_style);
/* destroy string vector */
- for (string_index = 0;
- string_index < sheet->string_vector_c;
- string_index++) {
- lwc_string_unref(sheet->string_vector[string_index]);
+ for (index = 0;
+ index < sheet->string_vector_c;
+ index++) {
+ lwc_string_unref(sheet->string_vector[index]);
}
if (sheet->string_vector != NULL)
sheet->alloc(sheet->string_vector, 0, sheet->pw);
css__propstrings_unref();
-
+
sheet->alloc(sheet, 0, sheet->pw);
return CSS_OK;
@@ -625,7 +626,7 @@ css_error css_stylesheet_size(css_stylesheet *sheet, size_t *size)
bytes += hash_size;
}
-
+
*size = bytes;
return CSS_OK;
@@ -1194,10 +1195,10 @@ css_error css__stylesheet_rule_destroy(css_stylesheet *sheet, css_rule *rule)
break;
case CSS_RULE_FONT_FACE:
{
- css_rule_font_face *font_face = (css_rule_font_face *) rule;
+ css_rule_font_face *font_face_r = (css_rule_font_face *) rule;
- if (font_face->style != NULL)
- css__stylesheet_style_destroy(font_face->style);
+ if (font_face_r->font_face != NULL)
+ css__font_face_destroy(font_face_r->font_face);
}
break;
case CSS_RULE_PAGE:
@@ -1705,8 +1706,8 @@ size_t _rule_size(const css_rule *r)
bytes += sizeof(css_rule_font_face);
- if (rf->style != NULL)
- bytes += (rf->style->used * sizeof(css_code_t));
+ if (rf->font_face != NULL)
+ bytes += sizeof(css_font_face);
} else if (r->type == CSS_RULE_PAGE) {
const css_rule_page *rp = (const css_rule_page *) r;
const css_selector *s = rp->selector;
@@ -1731,4 +1732,3 @@ size_t _rule_size(const css_rule *r)
return bytes;
}
-
diff --git a/src/stylesheet.h b/src/stylesheet.h
index 0f6deed..d48d0a9 100644
--- a/src/stylesheet.h
+++ b/src/stylesheet.h
@@ -141,7 +141,7 @@ typedef struct css_rule_media {
typedef struct css_rule_font_face {
css_rule base;
- css_style *style;
+ css_font_face *font_face;
} css_rule_font_face;
typedef struct css_rule_page {