Gitweb links:

...log 
http://git.netsurf-browser.org/libcss.git/shortlog/62dc80851eef3e256ef522dd68346672f30b7375
...commit 
http://git.netsurf-browser.org/libcss.git/commit/62dc80851eef3e256ef522dd68346672f30b7375
...tree 
http://git.netsurf-browser.org/libcss.git/tree/62dc80851eef3e256ef522dd68346672f30b7375

The branch, tlsa/calc has been created
        at  62dc80851eef3e256ef522dd68346672f30b7375 (commit)

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=62dc80851eef3e256ef522dd68346672f30b7375
commit 62dc80851eef3e256ef522dd68346672f30b7375
Author: Daniel Silverstone <[email protected]>
Commit: Michael Drake <Michael Drake [email protected]>

    parse: Add calc() parser.
    
    Co-authored-by: Michael Drake <[email protected]>

diff --git a/src/parse/properties/css_property_parser_gen.c 
b/src/parse/properties/css_property_parser_gen.c
index 0e6ce72..838f2b6 100644
--- a/src/parse/properties/css_property_parser_gen.c
+++ b/src/parse/properties/css_property_parser_gen.c
@@ -296,6 +296,16 @@ void output_length_unit(FILE *outputf, struct keyval 
*parseid, struct keyval_lis
        struct keyval *ckv = kvlist->item[0];
        int ident_count;
 
+       fprintf(outputf,
+               "if ((token->type == CSS_TOKEN_IDENT) && "
+               "(lwc_string_caseless_isequal(token->idata, c->strings[CALC], 
&match) == lwc_error_ok && match))"
+               " {\n"
+               "\t\terror = css__parse_calc(c, vector, ctx, result, 
buildOPV(%s, 0, %s /* _CALC */), %s);\n"
+               "\t} else ",
+               parseid->val,
+               ckv->val,
+               ckv->key
+       );
 
        fprintf(outputf,
                "{\n"
diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c
index 0e49853..b1864cb 100644
--- a/src/parse/properties/utils.c
+++ b/src/parse/properties/utils.c
@@ -1334,3 +1334,268 @@ cleanup:
        return error;
 }
 
+/******************************************************************************/
+
+/* CALC
+ *
+ * calc( <calc-sum> )
+ *
+ * where
+ * <calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]*
+ *
+ * where
+ * <calc-product> = <calc-value> [ '*' <calc-value> | '/' <number> ]*
+ *
+ * where
+ * <calc-value> = <number> | <dimension> | <percentage> | ( <calc-sum> )
+ *
+ *
+ * calc(10px + (4rem / 2)) =>
+ *   U 10 px
+ *   U 4 rem
+ *   N 2
+ *   /
+ *   +
+ *   =
+ */
+
+static css_error
+css__parse_calc_sum(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_style *result,
+               uint32_t unit);
+
+static css_error
+css__parse_calc_value(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_style *result,
+               uint32_t default_unit)
+{
+       css_error error;
+       int orig_ctx = *ctx;
+       const css_token *token;
+
+       token = parserutils_vector_iterate(vector, ctx);
+       if (tokenIsChar(token, '(')) {
+               error = css__parse_calc_sum(c, vector, ctx, result, 
default_unit);
+               if (error != CSS_OK) {
+                       return error;
+               }
+
+               token = parserutils_vector_peek(vector, *ctx);
+               if (!tokenIsChar(token, ')')) {
+                       return CSS_INVALID;
+               }
+
+       } else switch (token->type) {
+       case CSS_TOKEN_NUMBER:    /* Fall through */
+       case CSS_TOKEN_DIMENSION: /* Fall through */
+       case CSS_TOKEN_PERCENTAGE:
+       {
+               css_fixed length = 0;
+               uint32_t unit = 0;
+               *ctx = orig_ctx;
+
+               error = css__parse_unit_specifier(c, vector, ctx, default_unit, 
&length, &unit);
+               if (error != CSS_OK) {
+                       *ctx = orig_ctx;
+                       return error;
+               }
+
+               error = css__stylesheet_style_vappend(result, 3, (css_code_t) 
'U', length, unit);
+       }
+               break;
+
+       default:
+               error = CSS_INVALID;
+               break;
+       }
+
+       return error;
+}
+
+/* Both this, and css_parse_calc_sum must stop when it encounters a 
close-paren.
+ * If it hasn't had any useful tokens before that, it's an error.  It does not
+ * need to restore ctx before returning an error but it does need to ensure 
that
+ * the close paren has not been consumed
+ */
+static css_error
+css__parse_calc_product(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_style *result,
+               uint32_t unit)
+{
+       css_error error = CSS_OK;
+       const css_token *token;
+       bool multiplication;
+
+
+       /* First parse a value */
+       error = css__parse_calc_value(c, vector, ctx, result, unit);
+       if (error != CSS_OK) {
+               return error;
+       }
+
+       do {
+               /* What is our next token? */
+               token = parserutils_vector_peek(vector, *ctx);
+               if (token == NULL) {
+                       error = CSS_INVALID;
+                       break;
+               } else if (tokenIsChar(token, ')'))
+                       break;
+               else if (tokenIsChar(token, '*'))
+                       multiplication = true;
+               else if (tokenIsChar(token, '/'))
+                       multiplication = false;
+               else {
+                       error = CSS_INVALID;
+                       break;
+               }
+               /* Consume that * or / now */
+               token = parserutils_vector_iterate(vector, ctx);
+
+               if (multiplication) {
+                       /* parse another value */
+                       error = css__parse_calc_value(c, vector, ctx, result, 
unit);
+                       if (error != CSS_OK)
+                               break;
+               } else {
+                       css_fixed num;
+                       size_t consumed;
+
+                       token = parserutils_vector_iterate(vector, ctx);
+                       if (token->type != CSS_TOKEN_NUMBER) {
+                               error = CSS_INVALID;
+                               break;
+                       }
+                       num = css__number_from_lwc_string(token->idata, false, 
&consumed);
+                       if (consumed != lwc_string_length(token->idata)) {
+                               error = CSS_INVALID;
+                               break;
+                       }
+
+                       error = css__stylesheet_style_append(result, 
(css_code_t) 'N');
+                       if (error != CSS_OK)
+                               break;
+                       error = css__stylesheet_style_append(result, 
(css_code_t) num);
+                       if (error != CSS_OK)
+                               break;
+               }
+
+               /* emit the multiplication/division operator */
+               error = css__stylesheet_style_append(result, (css_code_t) 
(multiplication ? '*' : '/'));
+       } while (1);
+       /* We've fallen off, either we had an error or we're left with ')' */
+       return error;
+}
+
+
+css_error
+css__parse_calc_sum(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_style *result,
+               uint32_t unit)
+{
+       css_error error = CSS_OK;
+       const css_token *token;
+       bool addition;
+
+
+       /* First parse a product */
+       error = css__parse_calc_product(c, vector, ctx, result, unit);
+       if (error != CSS_OK) {
+               return error;
+       }
+
+       do {
+               /* What is our next token? */
+               token = parserutils_vector_peek(vector, *ctx);
+               if (token == NULL) {
+                       error = CSS_INVALID;
+                       break;
+               } else if (tokenIsChar(token, ')'))
+                       break;
+               else if (tokenIsChar(token, '+'))
+                       addition = true;
+               else if (tokenIsChar(token, '-'))
+                       addition = false;
+               else {
+                       error = CSS_INVALID;
+                       break;
+               }
+               /* Consume that + or - now */
+               token = parserutils_vector_iterate(vector, ctx);
+
+               /* parse another product */
+               error = css__parse_calc_product(c, vector, ctx, result, unit);
+               if (error != CSS_OK)
+                       break;
+
+               /* emit the addition/subtraction operator */
+               error = css__stylesheet_style_append(result, (css_code_t) 
(addition ? '+' : '-'));
+       } while (1);
+       /* We've fallen off, either we had an error or we're left with ')' */
+       return error;
+}
+
+/* Documented in utils.h */
+css_error css__parse_calc(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_style *result,
+               css_code_t property,
+               uint32_t unit)
+{
+       int orig_ctx = *ctx;
+       const css_token *token;
+       css_error error = CSS_OK;
+       css_style *calc_style = NULL;
+
+       token = parserutils_vector_iterate(vector, ctx);
+       if (token == NULL) {
+               *ctx = orig_ctx;
+               return CSS_INVALID;
+       }
+
+       if (!tokenIsChar(token, '(')) {
+               /* If we don't get an open-paren, give up now */
+               *ctx = orig_ctx;
+               return CSS_INVALID;
+       }
+
+       error = css__stylesheet_style_create(c->sheet, &calc_style);
+       if (error != CSS_OK)
+               goto cleanup;
+
+       error = css__stylesheet_style_append(calc_style, property);
+       if (error != CSS_OK)
+               goto cleanup;
+
+       error = css__parse_calc_sum(c, vector, ctx, calc_style, unit);
+       if (error != CSS_OK)
+               goto cleanup;
+
+       token = parserutils_vector_iterate(vector, ctx);
+       if (!tokenIsChar(token, ')')) {
+               /* If we don't get a close-paren, give up now */
+               error = CSS_INVALID;
+               goto cleanup;
+       }
+
+       /* Append the indicator that the calc is finished */
+       error = css__stylesheet_style_append(calc_style, (css_code_t) '=');
+       if (error != CSS_OK)
+               goto cleanup;
+
+       /* TODO: Once we're OK to do so, merge the style */
+       (void)result;
+       /* error = css__stylesheet_style_merge_style(result, calc_style); */
+
+cleanup:
+       css__stylesheet_style_destroy(calc_style);
+       if (error != CSS_OK) {
+               *ctx = orig_ctx;
+       }
+
+       return error;
+}
\ No newline at end of file
diff --git a/src/parse/properties/utils.h b/src/parse/properties/utils.h
index e4c97c7..e5331d2 100644
--- a/src/parse/properties/utils.h
+++ b/src/parse/properties/utils.h
@@ -199,4 +199,28 @@ css_error css__comma_list_to_style(css_language *c,
                                bool first),
                css_style *result);
 
+/**
+ * Parse a CSS calc() invocation
+ *
+ * Calc can generate a number of kinds of units, so we have to tell the
+ * parser the kind of unit we're aiming for (e.g. UNIT_PX, UNIT_ANGLE, etc.)
+ *
+ * \param[in] c        Parsing context
+ * \param[in] vector   Vector of tokens to process
+ * \param[in] ctx      Pointer to vector iteration context
+ * \param[in] result   Pointer to location to receive resulting style
+ * \param[in] property The CSS property we are calculating for
+ * \param[in] unit     The kind of unit which we want to come out of this 
calc()
+ * \return CSS_OK on success,
+ *         CSS_NOMEM on memory exhaustion,
+           CSS_INVALID if the input is not valid
+ *
+ * Post condition: \a *ctx is updated with the next token to process
+ *                 If the input is invalid, then \a *ctx remains unchanged.
+ */
+css_error css__parse_calc(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_style *result,
+               css_code_t property,
+               uint32_t unit);
 #endif
diff --git a/src/parse/propstrings.c b/src/parse/propstrings.c
index 3c9401b..0156ea4 100644
--- a/src/parse/propstrings.c
+++ b/src/parse/propstrings.c
@@ -443,6 +443,7 @@ const stringmap_entry stringmap[LAST_KNOWN] = {
        { "or", SLEN("or") },
        { "only", SLEN("only") },
        { "infinite", SLEN("infinite") },
+       { "calc", SLEN("calc") },
 
        { "aliceblue", SLEN("aliceblue") },
        { "antiquewhite", SLEN("antiquewhite") },
diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h
index 24b681b..c5dd113 100644
--- a/src/parse/propstrings.h
+++ b/src/parse/propstrings.h
@@ -101,7 +101,7 @@ enum {
        AVOID_PAGE, AVOID_COLUMN, BALANCE, HORIZONTAL_TB, VERTICAL_RL,
        VERTICAL_LR, CONTENT_BOX, BORDER_BOX, STRETCH, INLINE_FLEX, FLEX_START,
        FLEX_END, SPACE_BETWEEN, SPACE_AROUND, SPACE_EVENLY, ROW, ROW_REVERSE,
-       COLUMN_REVERSE, WRAP_STRING, WRAP_REVERSE, AND, OR, ONLY, INFINITE,
+       COLUMN_REVERSE, WRAP_STRING, WRAP_REVERSE, AND, OR, ONLY, INFINITE, 
CALC,
 
        /* Named colours */
        FIRST_COLOUR,


-----------------------------------------------------------------------


-- 
Cascading Style Sheets library
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to