summaryrefslogtreecommitdiff
path: root/content/handlers/css/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'content/handlers/css/utils.c')
-rw-r--r--content/handlers/css/utils.c144
1 files changed, 136 insertions, 8 deletions
diff --git a/content/handlers/css/utils.c b/content/handlers/css/utils.c
index 5c7cbd9a7..8fe157bd2 100644
--- a/content/handlers/css/utils.c
+++ b/content/handlers/css/utils.c
@@ -27,11 +27,75 @@
/** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
css_fixed nscss_screen_dpi = F_90;
+
+/**
+ * Map viewport-relative length units to either vh or vw.
+ *
+ * Non-viewport-relative units are unchanged.
+ *
+ * \param[in] ctx Length conversion context.
+ * \param[in] unit Unit to map.
+ * \return the mapped unit.
+ */
+static inline css_unit css_utils__fudge_viewport_units(
+ const nscss_len_ctx *ctx,
+ css_unit unit)
+{
+ switch (unit) {
+ case CSS_UNIT_VI:
+ assert(ctx->root_style != NULL);
+ if (css_computed_writing_mode(ctx->root_style) ==
+ CSS_WRITING_MODE_HORIZONTAL_TB) {
+ unit = CSS_UNIT_VW;
+ } else {
+ unit = CSS_UNIT_VH;
+ }
+ break;
+ case CSS_UNIT_VB:
+ assert(ctx->root_style != NULL);
+ if (css_computed_writing_mode(ctx->root_style) ==
+ CSS_WRITING_MODE_HORIZONTAL_TB) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ case CSS_UNIT_VMIN:
+ if (ctx->vh < ctx->vw) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ case CSS_UNIT_VMAX:
+ if (ctx->vh > ctx->vw) {
+ unit = CSS_UNIT_VH;
+ } else {
+ unit = CSS_UNIT_VW;
+ }
+ break;
+ default: break;
+ }
+
+ return unit;
+}
+
/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2pt(css_fixed length, css_unit unit)
+css_fixed nscss_len2pt(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit)
{
/* Length must not be relative */
- assert(unit != CSS_UNIT_EM && unit != CSS_UNIT_EX);
+ assert(unit != CSS_UNIT_EM &&
+ unit != CSS_UNIT_EX &&
+ unit != CSS_UNIT_CAP &&
+ unit != CSS_UNIT_CH &&
+ unit != CSS_UNIT_IC &&
+ unit != CSS_UNIT_REM &&
+ unit != CSS_UNIT_RLH);
+
+ unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) {
/* We assume the screen and any other output has the same dpi */
@@ -45,36 +109,50 @@ css_fixed nscss_len2pt(css_fixed length, css_unit unit)
/* 1in = 25.4mm => 1mm = (72/25.4)pt */
case CSS_UNIT_MM: return FMUL(length,
FDIV(F_72, FLTTOFIX(25.4)));
+ /* 1in = 101.6q => 1mm = (72/101.6)pt */
+ case CSS_UNIT_Q: return FMUL(length,
+ FDIV(F_72, FLTTOFIX(101.6)));
case CSS_UNIT_PT: return length;
/* 1pc = 12pt */
case CSS_UNIT_PC: return FMUL(length, INTTOFIX(12));
+ case CSS_UNIT_VH: return FDIV(FMUL(FDIV((length * ctx->vh), F_100),
+ F_72), nscss_screen_dpi);
+ case CSS_UNIT_VW: return FDIV(FMUL(FDIV((length * ctx->vw), F_100),
+ F_72), nscss_screen_dpi);
default: break;
}
return 0;
}
-
/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2px(css_fixed length, css_unit unit,
+css_fixed nscss_len2px(
+ const nscss_len_ctx *ctx,
+ css_fixed length,
+ css_unit unit,
const css_computed_style *style)
{
/* We assume the screen and any other output has the same dpi */
css_fixed px_per_unit;
- assert(style != NULL || (unit != CSS_UNIT_EM && unit != CSS_UNIT_EX));
+ unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) {
case CSS_UNIT_EM:
case CSS_UNIT_EX:
+ case CSS_UNIT_CAP:
+ case CSS_UNIT_CH:
+ case CSS_UNIT_IC:
{
css_fixed font_size = 0;
css_unit font_unit = CSS_UNIT_PT;
+ assert(style != NULL);
+
css_computed_font_size(style, &font_size, &font_unit);
/* Convert to points */
- font_size = nscss_len2pt(font_size, font_unit);
+ font_size = nscss_len2pt(ctx, font_size, font_unit);
/* Clamp to configured minimum */
if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
@@ -85,9 +163,22 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
* 1in = 72pt => 1pt = (DPI/72)px */
px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
- /* Scale ex units: we use a fixed ratio of 1ex = 0.6em */
- if (unit == CSS_UNIT_EX)
+ /* Scale non-em units to em. We have fixed ratios. */
+ 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:
@@ -105,6 +196,10 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_MM:
px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(25.4));
break;
+ /* 1in = 101.6q => 1q = (DPI/101.6)px */
+ case CSS_UNIT_Q:
+ px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(101.6));
+ break;
/* 1in = 72pt => 1pt = (DPI/72)px */
case CSS_UNIT_PT:
px_per_unit = FDIV(nscss_screen_dpi, F_72);
@@ -113,6 +208,39 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_PC:
px_per_unit = FDIV(nscss_screen_dpi, INTTOFIX(6));
break;
+ case CSS_UNIT_REM:
+ {
+ css_fixed font_size = 0;
+ css_unit font_unit = CSS_UNIT_PT;
+
+ assert(ctx->root_style != NULL);
+
+ css_computed_font_size(ctx->root_style,
+ &font_size, &font_unit);
+
+ /* Convert to points */
+ font_size = nscss_len2pt(ctx, font_size, font_unit);
+
+ /* Clamp to configured minimum */
+ if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
+ font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
+ }
+
+ /* Convert to pixels (manually, to maximise precision)
+ * 1in = 72pt => 1pt = (DPI/72)px */
+ px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
+ break;
+ }
+ /* 1rlh = <user_font_size>pt => 1rlh = (DPI/user_font_size)px */
+ case CSS_UNIT_RLH:
+ px_per_unit = FDIV(nscss_screen_dpi, FDIV(
+ INTTOFIX(nsoption_int(font_size)),
+ INTTOFIX(10)));
+ break;
+ case CSS_UNIT_VH:
+ return TRUNCATEFIX((FDIV((length * ctx->vh), F_100) + F_0_5));
+ case CSS_UNIT_VW:
+ return TRUNCATEFIX((FDIV((length * ctx->vw), F_100) + F_0_5));
default:
px_per_unit = 0;
break;