NetSurf
utils.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004 James Bursa <james@netsurf-browser.org>
3  * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
4  *
5  * This file is part of NetSurf, http://www.netsurf-browser.org/
6  *
7  * NetSurf is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License.
10  *
11  * NetSurf is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <assert.h>
21 
22 #include "utils/nsoption.h"
23 #include "utils/log.h"
24 
25 #include "css/utils.h"
26 
27 /** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
28 css_fixed nscss_screen_dpi = F_90;
29 
30 /** Medium screen density for device viewing distance. */
32 
33 /**
34  * Map viewport-relative length units to either vh or vw.
35  *
36  * Non-viewport-relative units are unchanged.
37  *
38  * \param[in] ctx Length conversion context.
39  * \param[in] unit Unit to map.
40  * \return the mapped unit.
41  */
42 static inline css_unit css_utils__fudge_viewport_units(
43  const nscss_len_ctx *ctx,
44  css_unit unit)
45 {
46  switch (unit) {
47  case CSS_UNIT_VI:
48  assert(ctx->root_style != NULL);
49  if (css_computed_writing_mode(ctx->root_style) ==
50  CSS_WRITING_MODE_HORIZONTAL_TB) {
51  unit = CSS_UNIT_VW;
52  } else {
53  unit = CSS_UNIT_VH;
54  }
55  break;
56  case CSS_UNIT_VB:
57  assert(ctx->root_style != NULL);
58  if (css_computed_writing_mode(ctx->root_style) ==
59  CSS_WRITING_MODE_HORIZONTAL_TB) {
60  unit = CSS_UNIT_VH;
61  } else {
62  unit = CSS_UNIT_VW;
63  }
64  break;
65  case CSS_UNIT_VMIN:
66  if (ctx->vh < ctx->vw) {
67  unit = CSS_UNIT_VH;
68  } else {
69  unit = CSS_UNIT_VW;
70  }
71  break;
72  case CSS_UNIT_VMAX:
73  if (ctx->vh > ctx->vw) {
74  unit = CSS_UNIT_VH;
75  } else {
76  unit = CSS_UNIT_VW;
77  }
78  break;
79  default: break;
80  }
81 
82  return unit;
83 }
84 
85 /* exported interface documented in content/handlers/css/utils.h */
86 css_fixed nscss_len2pt(
87  const nscss_len_ctx *ctx,
88  css_fixed length,
89  css_unit unit)
90 {
91  /* Length must not be relative */
92  assert(unit != CSS_UNIT_EM &&
93  unit != CSS_UNIT_EX &&
94  unit != CSS_UNIT_CAP &&
95  unit != CSS_UNIT_CH &&
96  unit != CSS_UNIT_IC &&
97  unit != CSS_UNIT_REM &&
98  unit != CSS_UNIT_RLH);
99 
100  unit = css_utils__fudge_viewport_units(ctx, unit);
101 
102  switch (unit) {
103  /* We assume the screen and any other output has the same dpi */
104  /* 1in = DPIpx => 1px = (72/DPI)pt */
105  case CSS_UNIT_PX: return FDIV(FMUL(length, F_72), F_96);
106  /* 1in = 72pt */
107  case CSS_UNIT_IN: return FMUL(length, F_72);
108  /* 1in = 2.54cm => 1cm = (72/2.54)pt */
109  case CSS_UNIT_CM: return FMUL(length,
110  FDIV(F_72, FLTTOFIX(2.54)));
111  /* 1in = 25.4mm => 1mm = (72/25.4)pt */
112  case CSS_UNIT_MM: return FMUL(length,
113  FDIV(F_72, FLTTOFIX(25.4)));
114  /* 1in = 101.6q => 1mm = (72/101.6)pt */
115  case CSS_UNIT_Q: return FMUL(length,
116  FDIV(F_72, FLTTOFIX(101.6)));
117  case CSS_UNIT_PT: return length;
118  /* 1pc = 12pt */
119  case CSS_UNIT_PC: return FMUL(length, INTTOFIX(12));
120  case CSS_UNIT_VH: return FDIV(FMUL(FDIV(FMUL(length, ctx->vh), F_100), F_72), F_96);
121  case CSS_UNIT_VW: return FDIV(FMUL(FDIV(FMUL(length,ctx->vw), F_100), F_72), F_96);
122  default: break;
123  }
124 
125  return 0;
126 }
127 
128 /* exported interface documented in content/handlers/css/utils.h */
129 css_fixed nscss_len2px(
130  const nscss_len_ctx *ctx,
131  css_fixed length,
132  css_unit unit,
133  const css_computed_style *style)
134 {
135  /* We assume the screen and any other output has the same dpi */
136  css_fixed px_per_unit;
137 
138  unit = css_utils__fudge_viewport_units(ctx, unit);
139 
140  switch (unit) {
141  case CSS_UNIT_EM:
142  case CSS_UNIT_EX:
143  case CSS_UNIT_CAP:
144  case CSS_UNIT_CH:
145  case CSS_UNIT_IC:
146  {
147  css_fixed font_size = 0;
148  css_unit font_unit = CSS_UNIT_PT;
149 
150  assert(style != NULL);
151 
152  css_computed_font_size(style, &font_size, &font_unit);
153 
154  /* Convert to points */
155  font_size = nscss_len2pt(ctx, font_size, font_unit);
156 
157  /* Clamp to configured minimum */
158  if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
159  font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
160  }
161 
162  /* Convert to pixels (manually, to maximise precision)
163  * 1in = 72pt => 1pt = (DPI/72)px */
164  px_per_unit = FDIV(FMUL(font_size, F_96), F_72);
165 
166  /* Scale non-em units to em. We have fixed ratios. */
167  switch (unit) {
168  case CSS_UNIT_EX:
169  px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.6));
170  break;
171  case CSS_UNIT_CAP:
172  px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.9));
173  break;
174  case CSS_UNIT_CH:
175  px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.4));
176  break;
177  case CSS_UNIT_IC:
178  px_per_unit = FMUL(px_per_unit, FLTTOFIX(1.1));
179  break;
180  default: break;
181  }
182  }
183  break;
184  case CSS_UNIT_PX:
185  px_per_unit = F_1;
186  break;
187  /* 1in = 96 CSS pixels */
188  case CSS_UNIT_IN:
189  px_per_unit = F_96;
190  break;
191  /* 1in = 2.54cm => 1cm = (DPI/2.54)px */
192  case CSS_UNIT_CM:
193  px_per_unit = FDIV(F_96, FLTTOFIX(2.54));
194  break;
195  /* 1in = 25.4mm => 1mm = (DPI/25.4)px */
196  case CSS_UNIT_MM:
197  px_per_unit = FDIV(F_96, FLTTOFIX(25.4));
198  break;
199  /* 1in = 101.6q => 1q = (DPI/101.6)px */
200  case CSS_UNIT_Q:
201  px_per_unit = FDIV(F_96, FLTTOFIX(101.6));
202  break;
203  /* 1in = 72pt => 1pt = (DPI/72)px */
204  case CSS_UNIT_PT:
205  px_per_unit = FDIV(F_96, F_72);
206  break;
207  /* 1pc = 12pt => 1in = 6pc => 1pc = (DPI/6)px */
208  case CSS_UNIT_PC:
209  px_per_unit = FDIV(F_96, INTTOFIX(6));
210  break;
211  case CSS_UNIT_REM:
212  {
213  css_fixed font_size = 0;
214  css_unit font_unit = CSS_UNIT_PT;
215 
216  assert(ctx->root_style != NULL);
217 
218  css_computed_font_size(ctx->root_style,
219  &font_size, &font_unit);
220 
221  /* Convert to points */
222  font_size = nscss_len2pt(ctx, font_size, font_unit);
223 
224  /* Clamp to configured minimum */
225  if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
226  font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
227  }
228 
229  /* Convert to pixels (manually, to maximise precision)
230  * 1in = 72pt => 1pt = (DPI/72)px */
231  px_per_unit = FDIV(FMUL(font_size, F_96), F_72);
232  break;
233  }
234  /* 1rlh = <user_font_size>pt => 1rlh = (DPI/user_font_size)px */
235  case CSS_UNIT_RLH:
236  px_per_unit = FDIV(F_96, FDIV(
237  INTTOFIX(nsoption_int(font_size)),
238  INTTOFIX(10)));
239  break;
240  case CSS_UNIT_VH:
241  px_per_unit = FDIV(ctx->vh, F_100);
242  break;
243  case CSS_UNIT_VW:
244  px_per_unit = FDIV(ctx->vw, F_100);
245  break;
246  default:
247  px_per_unit = 0;
248  break;
249  }
250 
251  px_per_unit = nscss_pixels_css_to_physical(px_per_unit);
252 
253  /* Ensure we round px_per_unit to the nearest whole number of pixels:
254  * the use of FIXTOINT() below will truncate. */
255  px_per_unit += F_0_5;
256 
257  /* Calculate total number of pixels */
258  return FMUL(length, TRUNCATEFIX(px_per_unit));
259 }
css_fixed nscss_len2pt(const nscss_len_ctx *ctx, css_fixed length, css_unit unit)
Convert an absolute CSS length to points.
Definition: utils.c:86
Length conversion context data.
Definition: utils.h:35
#define nsoption_int(OPTION)
Get the value of an integer option.
Definition: nsoption.h:279
Option reading and saving interface.
static css_unit css_utils__fudge_viewport_units(const nscss_len_ctx *ctx, css_unit unit)
Map viewport-relative length units to either vh or vw.
Definition: utils.c:42
const css_computed_style * root_style
Computed style for the document root element.
Definition: utils.h:50
css_fixed nscss_screen_dpi
Screen DPI in fixed point units: defaults to 90, which RISC OS uses.
Definition: utils.c:28
int vh
Viewport height in px.
Definition: utils.h:45
static css_fixed nscss_pixels_css_to_physical(css_fixed css_pixels)
Convert css pixels to physical pixels.
Definition: utils.h:88
int vw
Viewport width in px.
Definition: utils.h:40
css_fixed nscss_len2px(const nscss_len_ctx *ctx, css_fixed length, css_unit unit, const css_computed_style *style)
Convert a CSS length to pixels.
Definition: utils.c:129
css_fixed nscss_baseline_pixel_density
Medium screen density for device viewing distance.
Definition: utils.c:31