summaryrefslogtreecommitdiff
path: root/src/select/mq.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/select/mq.h')
-rw-r--r--src/select/mq.h226
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;
}