2
/******************************************************************************
4
* DESCRIPTION: Boxes for mathematical typesetting:
5
* fractions, roots, negations, limits and scripts
6
* COPYRIGHT : (C) 1999 Joris van der Hoeven
7
*******************************************************************************
8
* This software falls under the GNU general public license and comes WITHOUT
9
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
10
* If you don't have this file, write to the Free Software Foundation, Inc.,
11
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
12
******************************************************************************/
14
#include "Boxes/composite.hpp"
15
#include "Boxes/construct.hpp"
16
#include "Boxes/Composite/italic_correct.hpp"
18
/******************************************************************************
19
* Miscellaneous routines
20
******************************************************************************/
22
inline void left_italic_correct (box b) { b->x1 -= b->left_correction (); }
23
inline void left_italic_restore (box b) { b->x1 += b->left_correction (); }
24
inline void right_italic_correct (box b) { b->x2 += b->right_correction (); }
25
inline void right_italic_restore (box b) { b->x2 -= b->right_correction (); }
28
italic_correction (box L, box R) {
29
double slope_L= L->right_slope ();
30
double slope_R= R->left_slope ();
31
if (slope_L == slope_R) return 0;
32
if (slope_L * slope_R == 0.0)
33
return L->right_correction () + R->left_correction ();
34
double M= (slope_L <= slope_R? slope_R: slope_L);
35
if (M<0) M= (slope_L >= slope_R? slope_R: slope_L);
36
double factor= (slope_R- slope_L) / M;
37
if (factor < 0) factor= -factor;
38
return (SI) (factor * (L->right_correction () + R->left_correction ()));
41
/******************************************************************************
43
******************************************************************************/
45
struct frac_box_rep: public composite_box_rep {
46
frac_box_rep (path ip, box b1, box b2, font fn, font sfn, color c);
47
operator tree () { return tree (TUPLE, "frac", bs[0], bs[1]); }
48
int find_child (SI x, SI y, SI delta, bool force);
51
frac_box_rep::frac_box_rep (
52
path ip, box b1, box b2, font fn, font sfn, color c):
53
composite_box_rep (ip)
55
// Italic correction does not lead to nicer results,
56
// because right correction is not equilibrated w.r.t. left correction
61
SI b1_y = min (b1->y1, sfn->y1);
62
SI b2_y = max (b2->y2, sfn->y2);
63
SI w = max (b1->w (), b2->w()) + 2*sep;
66
insert (b1, (w>>1) - (b1->x2>>1), bar_y+ sep+ (bar_w>>1)- b1_y);
67
insert (b2, (w>>1) - (b2->x2>>1), bar_y- sep- (bar_w>>1)- b2_y);
68
insert (line_box (decorate_middle (ip), d, 0, w-d, 0, bar_w, c), 0, bar_y);
82
frac_box_rep::find_child (SI x, SI y, SI delta, bool force) {
83
if (outside (x, delta, x1, x2) && (is_accessible (ip) || force)) return -1;
84
int i= (y >= sy(2))? 0: 1;
85
if (bs[i]->decoration () && (!force)) {
87
if (bs[i]->decoration () && (!force)) return -1;
92
/******************************************************************************
94
******************************************************************************/
96
struct sqrt_box_rep: public composite_box_rep {
97
sqrt_box_rep (path ip, box b1, box b2, box sqrtb, font fn, color c);
98
operator tree () { return tree (TUPLE, "sqrt", bs[0]); }
99
int find_child (SI x, SI y, SI delta, bool force);
102
sqrt_box_rep::sqrt_box_rep (
103
path ip, box b1, box b2, box sqrtb, font fn, color c):
104
composite_box_rep (ip)
106
right_italic_correct (b1);
110
SI dx = -fn->wquad/36, dy= -fn->wquad/36; // correction
111
SI by = sqrtb->y2+ dy;
120
if (bh < 3*bw) Y += bh >> 1;
121
else Y += (bw*3) >> 1;
122
insert (b2, min (X, M- b2->x2), Y- b2->y1+ sep);
124
insert (sqrtb, -sqrtb->x2, 0);
125
insert (line_box (decorate_middle (ip), dx, by, b1->x2, by, wline, c), 0, 0);
133
right_italic_restore (b1);
138
sqrt_box_rep::find_child (SI x, SI y, SI delta, bool force) {
140
if (outside (x, delta, x1, x2) && (is_accessible (ip) || force)) return -1;
141
int i= ((N(bs)==3) || (x>sx(0)) || ((x>=sx(0)) && (delta>=0)))? 0: 1;
142
if (bs[i]->decoration () && (!force)) {
144
if (bs[i]->decoration () && (!force)) return -1;
149
/******************************************************************************
151
******************************************************************************/
153
struct neg_box_rep: public composite_box_rep {
154
neg_box_rep (path ip, box b1, font fn, color c);
155
operator tree () { return tree (TUPLE, "neg", bs[0]); }
156
int find_child (SI x, SI y, SI delta, bool force);
159
neg_box_rep::neg_box_rep (path ip, box b, font fn, color c):
160
composite_box_rep (ip)
163
SI delta= fn->wquad/6;
164
SI X = (b->x1 + b->x2) >> 1;
165
SI Y = (b->y1 + b->y2) >> 1;
169
if ((3*(b->x2-b->x1)) > (2*(b->y2-b->y1))) {
170
DY= delta + ((b->y2 - b->y1)>>1);
174
DX= delta + ((b->x2 - b->x1)>>1);
177
insert (line_box (decorate_middle (ip),
178
X+DX, Y+DY, X-DX, Y-DY, wline, c), 0, 0);
187
neg_box_rep::find_child (SI x, SI y, SI delta, bool force) {
189
if (outside (x, delta, x1, x2) && (is_accessible (ip) || force)) return -1;
190
if (bs[0]->decoration () && (!force)) return -1;
194
/******************************************************************************
196
******************************************************************************/
198
struct tree_box_rep: public composite_box_rep {
200
tree_box_rep (path ip, array<box> bs, font fn, color line_c);
201
operator tree () { return "tree box"; }
202
int find_child (SI x, SI y, SI delta, bool force);
205
tree_box_rep::tree_box_rep (path ip, array<box> bs, font fn, color line_c):
206
composite_box_rep (ip)
209
SI hsep = 2*fn->spc->def;
210
SI vsep = 4*fn->spc->def;
211
SI line_w= fn->wline;
213
int i, n= N(bs), cw, w= 0, h= MIN_SI, x, x_0, up;
214
for (i=1; i<n; i++) w += bs[i]->w();
215
for (i=1; i<n; i++) h = max (h, max (bs[i]->y2, fn->y2) + sep);
218
x_0= 0; if (bs[0]->w()>w) { x_0= (bs[0]->w()-w)>>1; w= bs[0]->w(); }
219
up= min (bs[0]->y1, fn->y1) - sep - vsep;
221
insert (bs[0], (w>>1)- ((bs[0]->x1+bs[0]->x2)>>1), 0);
222
for (x=x_0, i=1; i<n; i++) {
223
SI x_i= x- bs[i]->x1;
225
insert (bs[i], x_i, y_i);
226
x += bs[i]->w()+ hsep;
229
for (x=x_0, i=1; i<n; i++) {
230
SI x_i= x + (bs[i]->w()>>1);
231
SI y_i= up + max (bs[i]->y2, fn->y2) + sep - h;
233
SI bw = min (bs[0]->w(), cw>>1);
234
SI bx = bm + ((2*i-n) * bw) / (2*n-2);
235
SI by = min (bs[0]->y1, fn->y1) - sep;
236
insert (line_box (decorate_middle (ip),
237
bx, by, x_i, y_i, line_w, line_c), 0, 0);
238
x += bs[i]->w()+ hsep;
242
border= up+ (vsep>>1);
247
tree_box_rep::find_child (SI x, SI y, SI delta, bool force) {
248
if (outside (x, delta, x1, x2) && (is_accessible (ip) || force)) return -1;
252
for (j=1; j<((N(bs)+1)>>1); j++)
253
if (distance (j, x, y, delta)< d)
254
if (bs[j]->accessible () || force) {
255
d= distance (j, x, y, delta);
259
if (bs[i]->decoration () && (!force)) return -1;
263
/******************************************************************************
264
* wide hats, tildas, etc...
265
******************************************************************************/
267
struct wide_box_rep: public composite_box_rep {
271
wide_box_rep (path ip, box ref, box hi, font fn, SI sep, bool above);
272
operator tree () { return tree (TUPLE, "wide", bs[0]); }
273
int find_child (SI x, SI y, SI delta, bool force);
274
double left_slope ();
275
double right_slope ();
277
SI left_correction () {
278
return ref->left_correction (); }
279
SI right_correction () {
281
SI rc= ref->right_correction () + dw;
282
if (sx4 (1) >= (sx2 (1) - (dd>>1))) // corrects buggy extents wide chars
283
rc= max (rc, sx2(1)- x2+ dd);
285
return ref->right_correction (); }
286
SI lsub_correction () {
287
return ref->lsub_correction (); }
288
SI lsup_correction () {
289
return ref->lsup_correction (); }
290
SI rsub_correction () {
291
return ref->rsub_correction (); }
292
SI rsup_correction () {
294
SI rc= ref->rsup_correction () + dw;
295
if (sx4 (1) >= (sx2 (1) - (dd>>1))) // corrects buggy extents wide chars
296
rc= max (rc, sx2(1)- x2+ dd);
298
return ref->rsub_correction (); }
299
SI sub_lo_base (int level) {
300
return ref->sub_lo_base (level); }
301
SI sub_hi_lim (int level) {
302
return ref->sub_hi_lim (level); }
303
SI sup_lo_lim (int level) {
305
return max (ref->sup_lo_lim (level) - dh, box_rep::sup_lo_lim (level));
306
return ref->sup_lo_lim (level); }
307
SI sup_lo_base (int level) {
308
return ref->sup_lo_base (level); }
309
SI sup_hi_lim (int level) {
311
return min (ref->sup_hi_lim (level) + dh, box_rep::sup_hi_lim (level));
312
return ref->sup_hi_lim (level); }
315
wide_box_rep::wide_box_rep (
316
path ip, box ref2, box hi, font fn, SI sep, bool above2):
317
composite_box_rep (ip), ref (ref2), above (above2)
320
SI hw= max (ref->w(), hi->w()) >> 1;
321
SI m = (ref->x1 + ref->x2) >> 1;
325
X= ((SI) (ref->right_slope () * Y)) + m;
326
insert (hi, X- ((hi->x1 + hi->x2)>>1), Y+ sep);
330
X= ((SI) (ref->right_slope () * (Y - sep))) + m;
331
insert (hi, X- ((hi->x1 + hi->x2)>>1), Y- sep);
338
dw= (SI) (dh * ref->right_slope ());
342
if (!above) y1 += fn->sep - sep;
347
wide_box_rep::find_child (SI x, SI y, SI delta, bool force) {
349
if (outside (x, delta, x1, x2) && (is_accessible (ip) || force)) return -1;
350
if (bs[0]->decoration () && (!force)) return -1;
355
wide_box_rep::left_slope () {
356
return ref->left_slope ();
360
wide_box_rep::right_slope () {
361
return ref->right_slope ();
364
/******************************************************************************
365
* box construction routines
366
******************************************************************************/
369
frac_box (path ip, box b1, box b2, font fn, font sfn, color c) {
370
return new frac_box_rep (ip, b1, b2, fn, sfn, c);
374
sqrt_box (path ip, box b1, box b2, box sqrtb, font fn, color c) {
375
return new sqrt_box_rep (ip, b1, b2, sqrtb, fn, c);
379
neg_box (path ip, box b, font fn, color c) {
380
return new neg_box_rep (ip, b, fn, c);
384
tree_box (path ip, array<box> bs, font fn, color line_c) {
385
return new tree_box_rep (ip, bs, fn, line_c);
389
wide_box (path ip, box ref, box hi, font fn, SI sep, bool above) {
390
return new wide_box_rep (ip, ref, hi, fn, sep, above);