~ubuntu-branches/ubuntu/hardy/texmacs/hardy

« back to all changes in this revision

Viewing changes to src/Typeset/Boxes/Composite/math_boxes.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Treinen
  • Date: 2004-04-19 20:34:00 UTC
  • Revision ID: james.westby@ubuntu.com-20040419203400-g4e34ih0315wcn8v
Tags: upstream-1.0.3-R2
ImportĀ upstreamĀ versionĀ 1.0.3-R2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/******************************************************************************
 
3
* MODULE     : math.cpp
 
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
******************************************************************************/
 
13
 
 
14
#include "Boxes/composite.hpp"
 
15
#include "Boxes/construct.hpp"
 
16
#include "Boxes/Composite/italic_correct.hpp"
 
17
 
 
18
/******************************************************************************
 
19
* Miscellaneous routines
 
20
******************************************************************************/
 
21
 
 
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 (); }
 
26
 
 
27
SI
 
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 ()));
 
39
}
 
40
 
 
41
/******************************************************************************
 
42
* Fractions
 
43
******************************************************************************/
 
44
 
 
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);
 
49
};
 
50
 
 
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)
 
54
{
 
55
  // Italic correction does not lead to nicer results,
 
56
  // because right correction is not equilibrated w.r.t. left correction
 
57
 
 
58
  SI bar_y = fn->yfrac;
 
59
  SI bar_w = fn->wline;
 
60
  SI sep   = fn->sep;
 
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;
 
64
  SI d     = sep >> 1;
 
65
 
 
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);
 
69
 
 
70
  italic_correct (b1);
 
71
  italic_correct (b2);
 
72
  position ();
 
73
  italic_restore (b1);
 
74
  italic_restore (b2);
 
75
  x1= min (0, x1);
 
76
  x2= max (w, x2);
 
77
  left_justify ();
 
78
  finalize ();
 
79
}
 
80
 
 
81
int
 
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)) {
 
86
    i= 1-i;
 
87
    if (bs[i]->decoration () && (!force)) return -1;
 
88
  }
 
89
  return i;
 
90
}
 
91
 
 
92
/******************************************************************************
 
93
* Square roots
 
94
******************************************************************************/
 
95
 
 
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);
 
100
};
 
101
 
 
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)
 
105
{
 
106
  right_italic_correct (b1);
 
107
 
 
108
  SI sep  = fn->sep;
 
109
  SI wline= fn->wline;
 
110
  SI dx   = -fn->wquad/36, dy= -fn->wquad/36; // correction
 
111
  SI by   = sqrtb->y2+ dy;
 
112
 
 
113
  insert (b1, 0, 0);
 
114
  if (!nil (b2)) {
 
115
    SI X = - sqrtb->w();
 
116
    SI M = X / 3;
 
117
    SI Y = sqrtb->y1;
 
118
    SI bw= sqrtb->w();
 
119
    SI bh= sqrtb->h();
 
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);
 
123
  }
 
124
  insert (sqrtb, -sqrtb->x2, 0);
 
125
  insert (line_box (decorate_middle (ip), dx, by, b1->x2, by, wline, c), 0, 0);
 
126
  
 
127
  position ();
 
128
  left_justify ();
 
129
  y1 -= wline;
 
130
  y2 += wline;
 
131
  x2 += sep >> 1;
 
132
 
 
133
  right_italic_restore (b1);
 
134
  finalize ();
 
135
}
 
136
 
 
137
int
 
138
sqrt_box_rep::find_child (SI x, SI y, SI delta, bool force) {
 
139
  (void) y;
 
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)) {
 
143
    i= 1-i;
 
144
    if (bs[i]->decoration () && (!force)) return -1;
 
145
  }
 
146
  return i;
 
147
}
 
148
 
 
149
/******************************************************************************
 
150
* Negation boxes
 
151
******************************************************************************/
 
152
 
 
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);
 
157
};
 
158
 
 
159
neg_box_rep::neg_box_rep (path ip, box b, font fn, color c):
 
160
  composite_box_rep (ip)
 
161
{
 
162
  SI wline= fn->wline;
 
163
  SI delta= fn->wquad/6;
 
164
  SI X    = (b->x1 + b->x2) >> 1;
 
165
  SI Y    = (b->y1 + b->y2) >> 1;
 
166
  SI DX, DY;
 
167
 
 
168
  insert (b, 0, 0);
 
169
  if ((3*(b->x2-b->x1)) > (2*(b->y2-b->y1))) {
 
170
    DY= delta + ((b->y2 - b->y1)>>1);
 
171
    DX= DY>>1;
 
172
  }
 
173
  else {
 
174
    DX= delta + ((b->x2 - b->x1)>>1);
 
175
    DY= DX;
 
176
  }
 
177
  insert (line_box (decorate_middle (ip),
 
178
                    X+DX, Y+DY, X-DX, Y-DY, wline, c), 0, 0);
 
179
  
 
180
  italic_correct (b);
 
181
  position ();
 
182
  italic_restore (b);
 
183
  finalize ();
 
184
}
 
185
 
 
186
int
 
187
neg_box_rep::find_child (SI x, SI y, SI delta, bool force) {
 
188
  (void) y;
 
189
  if (outside (x, delta, x1, x2) && (is_accessible (ip) || force)) return -1;
 
190
  if (bs[0]->decoration () && (!force)) return -1;
 
191
  return 0;
 
192
}
 
193
 
 
194
/******************************************************************************
 
195
* Tree boxes
 
196
******************************************************************************/
 
197
 
 
198
struct tree_box_rep: public composite_box_rep {
 
199
  SI  border;
 
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);
 
203
};
 
204
 
 
205
tree_box_rep::tree_box_rep (path ip, array<box> bs, font fn, color line_c):
 
206
  composite_box_rep (ip)
 
207
{
 
208
  SI sep   = fn->sep;
 
209
  SI hsep  = 2*fn->spc->def;
 
210
  SI vsep  = 4*fn->spc->def;
 
211
  SI line_w= fn->wline;
 
212
 
 
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);
 
216
  w += (n-2)*hsep;
 
217
  cw = w;
 
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;
 
220
 
 
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;
 
224
    SI y_i= up- h;
 
225
    insert (bs[i], x_i, y_i);
 
226
    x += bs[i]->w()+ hsep;
 
227
  }
 
228
 
 
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;
 
232
    SI bm = w>>1;
 
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;
 
239
  }
 
240
 
 
241
  position ();
 
242
  border= up+ (vsep>>1);
 
243
  finalize ();
 
244
}
 
245
 
 
246
int
 
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;
 
249
  int i=0;
 
250
  if (y < border) {
 
251
    int j, d=MAX_SI;
 
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);
 
256
          i= j;
 
257
        }
 
258
  }
 
259
  if (bs[i]->decoration () && (!force)) return -1;
 
260
  return i;
 
261
}
 
262
 
 
263
/******************************************************************************
 
264
* wide hats, tildas, etc...
 
265
******************************************************************************/
 
266
 
 
267
struct wide_box_rep: public composite_box_rep {
 
268
  box ref;
 
269
  SI  dw, dh, dd;
 
270
  bool above;
 
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 ();
 
276
 
 
277
  SI left_correction () {
 
278
    return ref->left_correction (); }
 
279
  SI right_correction () {
 
280
    if (above) {
 
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);
 
284
      return rc; }
 
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 () {
 
293
    if (above) {
 
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);
 
297
      return rc; }
 
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) {
 
304
    if (!above)
 
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) {
 
310
    if (above)
 
311
      return min (ref->sup_hi_lim (level) + dh, box_rep::sup_hi_lim (level));
 
312
    return ref->sup_hi_lim (level); }
 
313
};
 
314
 
 
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)
 
318
{
 
319
  SI X, Y, dx;
 
320
  SI hw= max (ref->w(), hi->w()) >> 1;
 
321
  SI m = (ref->x1 + ref->x2) >> 1;
 
322
  insert (ref, 0, 0);
 
323
  if (above) {
 
324
    Y= ref->y2;
 
325
    X= ((SI) (ref->right_slope () * Y)) + m;
 
326
    insert (hi, X- ((hi->x1 + hi->x2)>>1), Y+ sep);
 
327
  }
 
328
  else {
 
329
    Y= ref->y1 - hi->y2;
 
330
    X= ((SI) (ref->right_slope () * (Y - sep))) + m;
 
331
    insert (hi, X- ((hi->x1 + hi->x2)>>1), Y- sep);
 
332
  }
 
333
  position ();
 
334
  dx= x1;
 
335
  left_justify ();
 
336
 
 
337
  dh= hi->y2+ sep;
 
338
  dw= (SI) (dh * ref->right_slope ());
 
339
  dd= fn->sep;
 
340
  x1= m- hw- dx;
 
341
  x2= m+ hw- dx;
 
342
  if (!above) y1 += fn->sep - sep;
 
343
  finalize ();
 
344
}
 
345
 
 
346
int
 
347
wide_box_rep::find_child (SI x, SI y, SI delta, bool force) {
 
348
  (void) y;
 
349
  if (outside (x, delta, x1, x2) && (is_accessible (ip) || force)) return -1;
 
350
  if (bs[0]->decoration () && (!force)) return -1;
 
351
  return 0;
 
352
}
 
353
 
 
354
double
 
355
wide_box_rep::left_slope () {
 
356
  return ref->left_slope ();
 
357
}
 
358
 
 
359
double
 
360
wide_box_rep::right_slope () {
 
361
  return ref->right_slope ();
 
362
}
 
363
 
 
364
/******************************************************************************
 
365
* box construction routines
 
366
******************************************************************************/
 
367
 
 
368
box
 
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);
 
371
}
 
372
 
 
373
box
 
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);
 
376
}
 
377
 
 
378
box
 
379
neg_box (path ip, box b, font fn, color c) {
 
380
  return new neg_box_rep (ip, b, fn, c);
 
381
}
 
382
 
 
383
box
 
384
tree_box (path ip, array<box> bs, font fn, color line_c) {
 
385
  return new tree_box_rep (ip, bs, fn, line_c);
 
386
}
 
387
 
 
388
box
 
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);
 
391
}