diff options
Diffstat (limited to 'src/select/mq.h')
-rw-r--r-- | src/select/mq.h | 226 |
1 files changed, 93 insertions, 133 deletions
diff --git a/src/select/mq.h b/src/select/mq.h index 9a97b7d..89da2c5 100644 --- a/src/select/mq.h +++ b/src/select/mq.h @@ -9,115 +9,15 @@ #ifndef css_select_mq_h_ #define css_select_mq_h_ -#include "select/properties/properties.h" -#include "select/properties/helpers.h" - -static inline css_fixed css_len2px( - css_fixed length, - css_unit unit, - const css_media *media) -{ - css_fixed px_per_unit; - - switch (unit) { - case CSS_UNIT_VI: - /* TODO: Assumes writing mode. */ - unit = CSS_UNIT_VW; - break; - case CSS_UNIT_VB: - /* TODO: Assumes writing mode. */ - unit = CSS_UNIT_VH; - break; - case CSS_UNIT_VMIN: - unit = (media->height < media->width) ? - CSS_UNIT_VH : CSS_UNIT_VW; - break; - case CSS_UNIT_VMAX: - unit = (media->width > media->height) ? - CSS_UNIT_VH : CSS_UNIT_VW; - break; - default: - break; - } - - switch (unit) { - case CSS_UNIT_EM: - case CSS_UNIT_EX: - case CSS_UNIT_CAP: - case CSS_UNIT_CH: - case CSS_UNIT_IC: - { - px_per_unit = FDIV(FMUL(media->client_font_size, F_96), F_72); - - /* TODO: Handling these as fixed ratios of CSS_UNIT_EM. */ - switch (unit) { - case CSS_UNIT_EX: - px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.6)); - break; - case CSS_UNIT_CAP: - px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.9)); - break; - case CSS_UNIT_CH: - px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.4)); - break; - case CSS_UNIT_IC: - px_per_unit = FMUL(px_per_unit, FLTTOFIX(1.1)); - break; - default: - break; - } - } - break; - case CSS_UNIT_PX: - return length; - case CSS_UNIT_IN: - px_per_unit = F_96; - break; - case CSS_UNIT_CM: - px_per_unit = FDIV(F_96, FLTTOFIX(2.54)); - break; - case CSS_UNIT_MM: - px_per_unit = FDIV(F_96, FLTTOFIX(25.4)); - break; - case CSS_UNIT_Q: - px_per_unit = FDIV(F_96, FLTTOFIX(101.6)); - break; - case CSS_UNIT_PT: - px_per_unit = FDIV(F_96, F_72); - break; - case CSS_UNIT_PC: - px_per_unit = FDIV(F_96, INTTOFIX(6)); - break; - case CSS_UNIT_REM: - px_per_unit = FDIV(FMUL(media->client_font_size, F_96), F_72); - break; - case CSS_UNIT_RLH: - px_per_unit = media->client_line_height; - break; - case CSS_UNIT_VH: - px_per_unit = FDIV(media->height, F_100); - break; - case CSS_UNIT_VW: - px_per_unit = FDIV(media->width, F_100); - break; - default: - px_per_unit = 0; - break; - } - - /* Ensure we round px_per_unit to the nearest whole number of pixels: - * the use of FIXTOINT() below will truncate. */ - px_per_unit += F_0_5; - - /* Calculate total number of pixels */ - return FMUL(length, TRUNCATEFIX(px_per_unit)); -} +#include "select/helpers.h" +#include "select/strings.h" +#include "select/unit.h" static inline bool mq_match_feature_range_length_op1( css_mq_feature_op op, const css_mq_value *value, const css_fixed client_len, - const css_media *media) + const css_unit_ctx *unit_ctx) { css_fixed v; @@ -126,9 +26,9 @@ static inline bool mq_match_feature_range_length_op1( } if (value->data.dim.unit != UNIT_PX) { - v = css_len2px(value->data.dim.len, - css__to_css_unit(value->data.dim.unit), - media); + v = css_unit_len2px_mq(unit_ctx, + value->data.dim.len, + css__to_css_unit(value->data.dim.unit)); } else { v = value->data.dim.len; } @@ -149,7 +49,7 @@ static inline bool mq_match_feature_range_length_op2( css_mq_feature_op op, const css_mq_value *value, const css_fixed client_len, - const css_media *media) + const css_unit_ctx *unit_ctx) { css_fixed v; @@ -161,9 +61,9 @@ static inline bool mq_match_feature_range_length_op2( } if (value->data.dim.unit != UNIT_PX) { - v = css_len2px(value->data.dim.len, - css__to_css_unit(value->data.dim.unit), - media); + v = css_unit_len2px_mq(unit_ctx, + value->data.dim.len, + css__to_css_unit(value->data.dim.unit)); } else { v = value->data.dim.len; } @@ -179,34 +79,79 @@ static inline bool mq_match_feature_range_length_op2( } } +static inline bool mq_match_feature_eq_ident_op1( + css_mq_feature_op op, + const css_mq_value *value, + const lwc_string *client_value) +{ + bool is_match; + + if (value->type != CSS_MQ_VALUE_TYPE_IDENT) { + return false; + } + + if (value->data.ident == NULL || client_value == NULL) { + return false; + } + + switch (op) { + case CSS_MQ_FEATURE_OP_EQ: + return (lwc_string_isequal(value->data.ident, + client_value, &is_match) == lwc_error_ok) && + is_match; + default: + return false; + } +} + /** * Match media query features. * - * \param[in] feat Condition to match. - * \param[in] media Current media spec, to check against feat. + * \param[in] feat Condition to match. + * \param[in] unit_ctx Current unit conversion context. + * \param[in] media Current media spec, to check against feat. * \return true if condition matches, otherwise false. */ static inline bool mq_match_feature( const css_mq_feature *feat, - const css_media *media) + const css_unit_ctx *unit_ctx, + const css_media *media, + const css_select_strings *str) { + bool match; + /* TODO: Use interned string for comparison. */ - if (strcmp(lwc_string_data(feat->name), "width") == 0) { + if (lwc_string_isequal(feat->name, + str->width, &match) == lwc_error_ok && + match == true) { if (!mq_match_feature_range_length_op1(feat->op, &feat->value, - media->width, media)) { + media->width, unit_ctx)) { return false; } return mq_match_feature_range_length_op2(feat->op2, - &feat->value2, media->width, media); + &feat->value2, media->width, unit_ctx); - } else if (strcmp(lwc_string_data(feat->name), "height") == 0) { + } else if (lwc_string_isequal(feat->name, + str->height, &match) == lwc_error_ok && + match == true) { if (!mq_match_feature_range_length_op1(feat->op, &feat->value, - media->height, media)) { + media->height, unit_ctx)) { return false; } return mq_match_feature_range_length_op2(feat->op2, - &feat->value2, media->height, media); + &feat->value2, media->height, unit_ctx); + + } else if (lwc_string_isequal(feat->name, + str->prefers_color_scheme, &match) == lwc_error_ok && + match == true) { + if (mq_match_feature_eq_ident_op1(feat->op, &feat->value, + media->prefers_color_scheme) || + feat->op == CSS_MQ_FEATURE_OP_BOOL) { + return true; + } + + return false; } /* TODO: Look at other feature names. */ @@ -217,13 +162,16 @@ static inline bool mq_match_feature( /** * Match media query conditions. * - * \param[in] cond Condition to match. - * \param[in] media Current media spec, to check against cond. + * \param[in] cond Condition to match. + * \param[in] unit_ctx Current unit conversion context. + * \param[in] media Current media spec, to check against cond. * \return true if condition matches, otherwise false. */ static inline bool mq_match_condition( const css_mq_cond *cond, - const css_media *media) + const css_unit_ctx *unit_ctx, + const css_media *media, + const css_select_strings *str) { bool matched = !cond->op; @@ -231,11 +179,13 @@ static inline bool mq_match_condition( bool part_matched; if (cond->parts[i]->type == CSS_MQ_FEATURE) { part_matched = mq_match_feature( - cond->parts[i]->data.feat, media); + cond->parts[i]->data.feat, + unit_ctx, media, str); } else { assert(cond->parts[i]->type == CSS_MQ_COND); part_matched = mq_match_condition( - cond->parts[i]->data.cond, media); + cond->parts[i]->data.cond, + unit_ctx, media, str); } if (cond->op) { @@ -262,19 +212,23 @@ static inline bool mq_match_condition( * If anything in the list matches, the list matches. If none match * it doesn't match. * - * \param[in] m Media query list. - * \param[in] media Current media spec, to check against m. + * \param[in] m Media query list. + * \param[in] unit_ctx Current unit conversion context. + * \param[in] media Current media spec, to check against m. * \return true if media query list matches media */ static inline bool mq__list_match( const css_mq_query *m, - const css_media *media) + const css_unit_ctx *unit_ctx, + const css_media *media, + const css_select_strings *str) { for (; m != NULL; m = m->next) { /* Check type */ if (!!(m->type & media->type) != m->negate_type) { if (m->cond == NULL || - mq_match_condition(m->cond, media)) { + mq_match_condition(m->cond, + unit_ctx, media, str)) { /* We have a match, no need to look further. */ return true; } @@ -287,11 +241,16 @@ static inline bool mq__list_match( /** * Test whether the rule applies for current media. * - * \param rule Rule to test - * \param media Current media spec + * \param rule Rule to test + * \param unit_ctx Current unit conversion context. + * \param media Current media spec * \return true iff chain's rule applies for media */ -static inline bool mq_rule_good_for_media(const css_rule *rule, const css_media *media) +static inline bool mq_rule_good_for_media( + const css_rule *rule, + const css_unit_ctx *unit_ctx, + const css_media *media, + const css_select_strings *str) { bool applies = true; const css_rule *ancestor = rule; @@ -300,7 +259,8 @@ static inline bool mq_rule_good_for_media(const css_rule *rule, const css_media const css_rule_media *m = (const css_rule_media *) ancestor; if (ancestor->type == CSS_RULE_MEDIA) { - applies = mq__list_match(m->media, media); + applies = mq__list_match(m->media, + unit_ctx, media, str); if (applies == false) { break; } |