1 
2 /******************************************************************************
3 * MODULE     : evaluate_length.cpp
4 * DESCRIPTION: evaluation of lengths
5 * COPYRIGHT  : (C) 2006  Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11 
12 #include "evaluate_main.hpp"
13 #include "vars.hpp"
14 #include "analyze.hpp"
15 #include "font.hpp"
16 #include "gui.hpp"
17 
18 /******************************************************************************
19 * Length arithmetic
20 ******************************************************************************/
21 
22 bool
is_length(string s)23 is_length (string s) {
24   int i;
25   for (i=0; (i<N(s)) && ((s[i]<'a') || (s[i]>'z')); i++) {}
26   return is_double (s (0, i)) && is_locase_alpha (s (i, N(s)));
27 }
28 
29 bool
is_length(tree t)30 is_length (tree t) {
31   return is_atomic (t) && is_length (t->label);
32 }
33 
34 bool
is_anylen(tree t)35 is_anylen (tree t) {
36   return
37     (is_func (t, TMLEN) && ((N(t) == 1) || (N(t) == 3))) ||
38     (is_atomic (t) && is_length (t->label)) ||
39     is_func (t, MACRO, 1);
40 }
41 
42 tree
tmlen_plus(tree t1,tree t2)43 tmlen_plus (tree t1, tree t2) {
44   if ((N(t1) == 1) && (N(t2) == 1))
45     return tree (TMLEN, as_string (as_double (t1[0]) + as_double (t2[0])));
46   if (N(t1) == 1) t1= tree (TMLEN, t1[0], t1[0], t1[0]);
47   if (N(t2) == 1) t2= tree (TMLEN, t2[0], t2[0], t2[0]);
48   tree _min= as_string (as_double (t1[0]) + as_double (t2[0]));
49   tree _def= as_string (as_double (t1[1]) + as_double (t2[1]));
50   tree _max= as_string (as_double (t1[2]) + as_double (t2[2]));
51   return tree (TMLEN, _min, _def, _max);
52 }
53 
54 tree
tmlen_times(double sc,tree t)55 tmlen_times (double sc, tree t) {
56   if (N(t) == 1) return tree (TMLEN, as_string (sc * as_double (t[0])));
57   tree _min= as_string (sc * as_double (t[0]));
58   tree _def= as_string (sc * as_double (t[1]));
59   tree _max= as_string (sc * as_double (t[2]));
60   return tree (TMLEN, _min, _def, _max);
61 }
62 
63 tree
tmlen_over(tree t1,tree t2)64 tmlen_over (tree t1, tree t2) {
65   t1= t1[N(t1)==1? 0: 1];
66   t2= t2[N(t2)==1? 0: 1];
67   return as_string (as_double (t1) / as_double (t2));
68 }
69 
70 /******************************************************************************
71 * Decoding lengths
72 ******************************************************************************/
73 
74 tree
as_tmlen(tree t)75 as_tmlen (tree t) {
76   if (is_func (t, TMLEN)) {
77     if (is_double (t[0])) return t;
78     if (N(t) < 3) return as_tmlen (t[0]);
79     tree _min= as_tmlen (t[0]);
80     tree _def= as_tmlen (t[1]);
81     tree _max= as_tmlen (t[2]);
82     _min= _min[N(_min) == 3? 1: 0];
83     _def= _def[N(_def) == 3? 1: 0];
84     _max= _max[N(_max) == 3? 1: 0];
85     return tree (TMLEN, _min, _def, _max);
86   }
87   else if (is_atomic (t)) {
88     string s= t->label;
89     int start= 0, i, n=N(s);
90     while ((start+1<n) && (s[start]=='-') && (s[start+1]=='-')) start += 2;
91     for (i=start; (i<n) && ((s[i]<'a') || (s[i]>'z')); i++) {}
92     string s1= s (start, i);
93     string s2= s (i, n);
94     if (!(is_double (s1) && is_locase_alpha (s2))) return tree (TMLEN, "0");
95     return tmlen_times (as_double (s1),
96 			as_tmlen (evaluate (compound (s2 * "-length"))));
97   }
98   else if (is_func (t, MACRO, 1))
99     return as_tmlen (evaluate (t[0]));
100   else return tree (TMLEN, "0");
101 }
102 
103 SI
as_length(string l)104 as_length (string l) {
105   tree r= as_tmlen (l);
106   string s= r[N(r)==1? 0: 1]->label;
107   return (SI) (as_double (s));
108 }
109 
110 SI
as_length(tree t)111 as_length (tree t) {
112   tree r= as_tmlen (t);
113   string s= r[N(r)==1? 0: 1]->label;
114   return (SI) (as_double (s));
115 }
116 
117 /******************************************************************************
118 * Get environment variables
119 ******************************************************************************/
120 
std_inch()121 inline SI std_inch () {
122   return (SI) ((double) as_int (std_env [DPI]) * PIXEL); }
std_zoom()123 inline double std_zoom () {
124   return as_double (std_env [ZOOM_FACTOR]); }
std_dpi()125 inline int std_dpi () {
126   return as_int (std_env [DPI]); }
std_magnification()127 inline double std_magnification () {
128   return as_double (std_env [MAGNIFICATION]); }
std_font_base_size()129 inline int std_font_base_size () {
130   return as_int (std_env [FONT_BASE_SIZE]); }
std_font_size()131 inline double std_font_size () {
132   return as_double (std_env [FONT_SIZE]); }
std_math_level()133 inline int std_math_level () {
134   return as_int (std_env [MATH_LEVEL]); }
135 
std_mode()136 inline int std_mode () {
137   string s= as_string (std_env [MODE]);
138   if (s == "text") return 1;
139   else if (s == "math") return 2;
140   else if (s == "prog") return 3;
141   else return 0; }
142 
143 font
std_fn()144 std_fn () {
145   int fs= (int) ((std_font_base_size () + 0.5) * std_font_size ());
146   switch (std_mode ()) {
147   case 0:
148   case 1:
149     return smart_font (as_string (std_env [FONT]),
150                        as_string (std_env [FONT_FAMILY]),
151                        as_string (std_env [FONT_SERIES]),
152                        as_string (std_env [FONT_SHAPE]),
153                        script (fs, std_math_level ()),
154                        (int) (std_magnification () * std_dpi ()));
155   case 2:
156     return smart_font (as_string (std_env [MATH_FONT]),
157                        as_string (std_env [MATH_FONT_FAMILY]),
158                        as_string (std_env [MATH_FONT_SERIES]),
159                        as_string (std_env [MATH_FONT_SHAPE]),
160                        as_string (std_env [FONT]),
161                        as_string (std_env [FONT_FAMILY]),
162                        as_string (std_env [FONT_SERIES]),
163                        "mathitalic",
164                        script (fs, std_math_level ()),
165                        (int) (std_magnification () * std_dpi ()));
166   case 3:
167     return smart_font (as_string (std_env [PROG_FONT]),
168                        as_string (std_env [PROG_FONT_FAMILY]),
169                        as_string (std_env [PROG_FONT_SERIES]),
170                        as_string (std_env [PROG_FONT_SHAPE]),
171                        as_string (std_env [FONT]),
172                        as_string (std_env [FONT_FAMILY]) * "-tt",
173                        as_string (std_env [FONT_SERIES]),
174                        as_string (std_env [FONT_SHAPE]),
175                        script (fs, std_math_level ()),
176                        (int) (std_magnification () * std_dpi ()));
177   default:
178     return get_default_font ();
179   }
180 }
181 
182 /******************************************************************************
183 * Universal length units
184 ******************************************************************************/
185 
evaluate_cm_length()186 tree evaluate_cm_length () {
187   return tree (TMLEN, as_string (std_inch() / 2.54)); }
evaluate_mm_length()188 tree evaluate_mm_length () {
189   return tree (TMLEN, as_string (std_inch() / 25.4)); }
evaluate_in_length()190 tree evaluate_in_length () {
191   return tree (TMLEN, as_string (std_inch())); }
evaluate_pt_length()192 tree evaluate_pt_length () {
193   return tree (TMLEN, as_string (std_inch() / 72.27)); }
evaluate_bp_length()194 tree evaluate_bp_length () {
195   return tree (TMLEN, as_string (std_inch() / 72.0)); }
evaluate_dd_length()196 tree evaluate_dd_length () {
197   return tree (TMLEN, as_string (0.376 * std_inch() / 25.4)); }
evaluate_pc_length()198 tree evaluate_pc_length () {
199   return tree (TMLEN, as_string (12.0 * std_inch() / 72.27)); }
evaluate_cc_length()200 tree evaluate_cc_length () {
201   return tree (TMLEN, as_string (4.531 * std_inch() / 25.4)); }
202 
203 /******************************************************************************
204 * Environment-dependent length units
205 ******************************************************************************/
206 
207 tree
evaluate_fs_length()208 evaluate_fs_length () {
209   double fs= (std_font_base_size () * std_magnification () *
210 	      std_inch () * std_font_size ()) / 72.0;
211   return tree (TMLEN, as_string (fs));
212 }
213 
214 tree
evaluate_fbs_length()215 evaluate_fbs_length () {
216   double fbs= (std_font_base_size () * std_magnification () *
217 	       std_inch ()) / 72.0;
218   return tree (TMLEN, as_string (fbs));
219 }
220 
evaluate_em_length()221 tree evaluate_em_length () {
222   return tree (TMLEN, as_string (std_fn()->wquad)); }
evaluate_ln_length()223 tree evaluate_ln_length () {
224   return tree (TMLEN, as_string (std_fn()->wline)); }
evaluate_sep_length()225 tree evaluate_sep_length () {
226   return tree (TMLEN, as_string (std_fn()->sep)); }
evaluate_yfrac_length()227 tree evaluate_yfrac_length () {
228   return tree (TMLEN, as_string (std_fn()->yfrac)); }
evaluate_ex_length()229 tree evaluate_ex_length () {
230   return tree (TMLEN, as_string (std_fn()->yx)); }
231 
232 tree
evaluate_fn_length()233 evaluate_fn_length () {
234   double fs= (std_font_base_size () * std_magnification () *
235 	      std_inch () * std_font_size ()) / 72.0;
236   return tree (TMLEN, as_string (0.5*fs), as_string (fs), as_string (1.5*fs));
237 }
238 
239 tree
evaluate_fns_length()240 evaluate_fns_length () {
241   double fs= (std_font_base_size () * std_magnification () *
242 	      std_inch () * std_font_size ()) / 72.0;
243   return tree (TMLEN, "0", "0", as_string (fs));
244 }
245 
246 static space
as_vspace(tree t)247 as_vspace (tree t) {
248   tree r= as_tmlen (t);
249   if (N(r) == 1)
250     return space ((SI) (as_double (r[0]->label)));
251   else {
252     SI _min= (SI) as_double (r[0]->label);
253     SI _def= (SI) as_double (r[1]->label);
254     SI _max= (SI) as_double (r[2]->label);
255     double flexibility= as_double (std_env [PAGE_FLEXIBILITY]);
256     return space (_def + ((SI) (flexibility * (_min - _def))),
257 		  _def,
258 		  _def + ((SI) (flexibility * (_max - _def))));
259   }
260 }
261 
262 tree
evaluate_bls_length()263 evaluate_bls_length () {
264   double fs= (std_font_base_size () * std_magnification () *
265 	      std_inch () * std_font_size ()) / 72.0;
266   return tmlen_plus (tree (TMLEN, as_string (fs)),
267 		     tree (as_vspace (std_env [PAR_SEP])));
268 }
269 
270 tree
evaluate_fnbot_length()271 evaluate_fnbot_length () {
272   return tree (TMLEN, as_string (std_fn()->y1));
273 }
274 
275 tree
evaluate_fntop_length()276 evaluate_fntop_length () {
277   return tree (TMLEN, as_string (std_fn()->y2));
278 }
279 
280 tree
evaluate_spc_length()281 evaluate_spc_length () {
282   space spc= std_fn()->spc;
283   return tree (TMLEN,
284 	       as_string (spc->min),
285 	       as_string (spc->def),
286 	       as_string (spc->max));
287 }
288 
289 tree
evaluate_xspc_length()290 evaluate_xspc_length () {
291   space spc= std_fn()->extra;
292   return tree (TMLEN,
293 	       as_string (spc->min),
294 	       as_string (spc->def),
295 	       as_string (spc->max));
296 }
297 
298 tree
evaluate_par_length()299 evaluate_par_length () {
300   /*
301   SI width, d1, d2, d3, d4, d5, d6, d7;
302   get_page_pars (width, d1, d2, d3, d4, d5, d6, d7);
303   width -= (get_length (PAR_LEFT) + get_length (PAR_RIGHT));
304   return tree (TMLEN, as_string (width));
305   */
306   return tree (TMLEN, as_string (15 * std_inch() / 2.54)); // 15cm
307 }
308 
309 tree
evaluate_pag_length()310 evaluate_pag_length () {
311   /*
312   SI d1, height, d2, d3, d4, d5, d6, d7;
313   get_page_pars (d1, height, d2, d3, d4, d5, d6, d7);
314   return tree (TMLEN, as_string (height));
315   */
316   return tree (TMLEN, as_string (23 * std_inch() / 2.54)); // 23cm
317 }
318 
evaluate_tmpt_length()319 tree evaluate_tmpt_length () {
320   return tree (TMLEN, "1"); }
evaluate_px_length()321 tree evaluate_px_length () {
322   int px= (int) tm_round ((std_shrinkf * PIXEL) / std_zoom ());
323   return tree (TMLEN, as_string (px)); }
324 
325 tree
evaluate_gw_length()326 evaluate_gw_length () {
327   //return tree (TMLEN, as_string (gw));
328   return tree (TMLEN, as_string (10 * std_inch() / 2.54)); // 10cm
329 }
330 
331 tree
evaluate_gh_length()332 evaluate_gh_length () {
333   //return tree (TMLEN, as_string (gh));
334   return tree (TMLEN, as_string (6 * std_inch() / 2.54)); // 6cm
335 }
336 
337 tree
evaluate_gu_length()338 evaluate_gu_length () {
339   // FIXME: not yet implemented
340   return evaluate_cm_length ();
341   //point p0= fr (point (0.0, 0.0));
342   //point p1= fr (point (1.0, 0.0));
343   //return tree (TMLEN, as_string (norm (p1 - p0)));
344 }
345 
evaluate_msec_length()346 tree evaluate_msec_length () { return tree (TMLEN, "1"); }
evaluate_sec_length()347 tree evaluate_sec_length () { return tree (TMLEN, "1000"); }
evaluate_min_length()348 tree evaluate_min_length () { return tree (TMLEN, "60000"); }
evaluate_hr_length()349 tree evaluate_hr_length () { return tree (TMLEN, "3600000"); }
350