1 
2 /******************************************************************************
3 * MODULE     : rubber.cpp
4 * DESCRIPTION: boxes whose dimensions are (partially) set by the user.
5 *                - empty and plain boxes
6 *                - parenthesis boxes
7 *                - overline and underline like boxes
8 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
9 *******************************************************************************
10 * This software falls under the GNU general public license version 3 or later.
11 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
12 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
13 ******************************************************************************/
14 
15 #include "boxes.hpp"
16 
17 /*****************************************************************************/
18 // Bracket types from  ../math-mode/math-macros.hpp
19 /*****************************************************************************/
20 
21 #define Lbracket        1011
22 #define Lcrochet        1012
23 #define Langular        1013
24 #define Laccolade       1014
25 #define Rbracket        1021
26 #define Rcrochet        1022
27 #define Rangular        1023
28 #define Raccolade       1024
29 #define Voidbr          1030
30 #define Absolute        1031
31 
32 /*****************************************************************************/
33 // Empty boxes
34 /*****************************************************************************/
35 
36 struct empty_box_rep: public box_rep {
empty_box_repempty_box_rep37   empty_box_rep (path ip, int x1b, int y1b, int x2b, int y2b): box_rep (ip) {
38     x3=x4=y3=y4=0; x1= x1b; y1=y1b; x2=x2b; y2=y2b; }
operator treeempty_box_rep39   operator tree () { return "empty"; }
displayempty_box_rep40   void display (renderer ren) { (void) ren; }
41 };
42 
43 struct dummy_box_rep: public box_rep {
dummy_box_repdummy_box_rep44   dummy_box_rep (path ip, int x1b, int y1b, int x2b, int y2b): box_rep (ip) {
45     x3=x4=y3=y4=0; x1= x1b; y1=y1b; x2=x2b; y2=y2b; }
operator treedummy_box_rep46   operator tree () { return "dummy"; }
displaydummy_box_rep47   void display (renderer ren) { (void) ren; }
find_box_pathdummy_box_rep48   path find_box_path (SI x, SI y, SI delta, bool force, bool& found) {
49     bool dummy; found= false;
50     return box_rep::find_box_path (x, y, delta, force, dummy); }
51 };
52 
53 struct marker_box_rep: public box_rep {
54   int pos;
55   box ref;
marker_box_repmarker_box_rep56   marker_box_rep (path ip2, int x1b, int y1b, int x2b, int y2b, box ref2):
57     box_rep (is_accessible (ip2)? ip2->next: ip2),
58     pos (is_accessible (ip2)? ip2->item: 0), ref (ref2) {
59       x3= x4= y3= y4= 0; x1= x1b; y1= y1b; x2= x2b; y2= y2b; }
operator treemarker_box_rep60   operator tree () { return "marker"; }
displaymarker_box_rep61   void display (renderer ren) { (void) ren; }
find_box_pathmarker_box_rep62   path find_box_path (SI x, SI y, SI delta, bool force) {
63     (void) x; (void) y; (void) delta; (void) force; return path (0); }
find_lipmarker_box_rep64   path find_lip () {
65     return is_accessible (ip)? descend (ip, pos): ip; }
find_ripmarker_box_rep66   path find_rip () {
67     return is_accessible (ip)? descend (ip, pos): ip; }
find_right_box_pathmarker_box_rep68   path find_right_box_path () {
69     return path (0); }
find_box_pathmarker_box_rep70   path find_box_path (path p, bool& found) {
71     found= !is_nil (p) && is_accessible (ip);
72     return path (0); }
find_tree_pathmarker_box_rep73   path find_tree_path (path bp) {
74     if (is_accessible (ip)) return reverse (descend (ip, pos));
75     else return reverse (descend_decode (ip, 0)); }
find_cursormarker_box_rep76   cursor find_cursor (path bp) {
77     (void) bp; return cursor (0, 0, 0, y1, y2); }
find_selectionmarker_box_rep78   selection find_selection (path lbp, path rbp) {
79     return selection (rectangles (),
80 		      find_tree_path (lbp), find_tree_path (rbp)); }
sub_lo_basemarker_box_rep81   SI sub_lo_base (int level) { return min (y1, ref->sub_lo_base (level)); }
sub_hi_limmarker_box_rep82   SI sub_hi_lim (int level) { return ref->sub_hi_lim (level); }
sup_lo_limmarker_box_rep83   SI sup_lo_lim (int level) { return ref->sup_lo_lim (level); }
sup_lo_basemarker_box_rep84   SI sup_lo_base (int level) { return ref->sup_lo_base (level); }
sup_hi_limmarker_box_rep85   SI sup_hi_lim (int level) { return max (y2, ref->sup_hi_lim (level)); }
86 };
87 
88 /*****************************************************************************/
89 // Brackets
90 /*****************************************************************************/
91 
92 struct bracket_box_rep: public box_rep {
93   int br_type;
94   pencil pen;
95 
96   bracket_box_rep (path ip, int br_type2, pencil pen, SI y1b, SI y2b);
operator treebracket_box_rep97   operator tree () { return "bracket"; }
98   void display (renderer ren);
99 };
100 
101 SI
bracket_width(int br_type,SI height,SI penw)102 bracket_width (int br_type, SI height, SI penw) {
103   switch (br_type) {
104   case Lbracket:
105   case Rbracket:
106   case Lcrochet:
107   case Rcrochet:
108   case Laccolade:
109   case Raccolade:
110   case Langular:
111   case Rangular:
112     {
113       SI ref_size  = penw/2;
114       double factor= sqrt (((double) height) / ((double) ref_size));
115       if (factor<2) factor=2;
116       factor=factor*1.412;
117       return (2*penw) + ((SI) (((double) height)/factor));
118     }
119   case Absolute:
120     return 2*penw;
121   case Voidbr:
122   default:
123     return 0;
124   }
125 }
126 
bracket_box_rep(path ip,int br_type2,pencil pen2,SI y1b,SI y2b)127 bracket_box_rep::bracket_box_rep (path ip, int br_type2, pencil pen2,
128 				  SI y1b, SI y2b): box_rep (ip) {
129   br_type = br_type2;
130   pen     = pen2;
131   x1 = x3 = 0;
132   x2 = x4 = bracket_width (br_type, y2b- y1b, pen->get_width ());
133   y1 = y3 = y1b;
134   y2 = y4 = y2b;
135 }
136 
137 void
draw_bracket(renderer ren,int br_type,SI x,SI y,SI w,SI h,pencil pen)138 draw_bracket (renderer ren, int br_type, SI x, SI y, SI w, SI h, pencil pen) {
139   SI lw= pen->get_width ();
140   x+=lw; w-=2*lw;
141   y+=lw; h-=2*lw;
142   ren->set_pencil (pen);
143   switch (br_type) {
144   case Lbracket:
145     {
146       int i;
147       SI ww= (SI) (((double) w) / (1.0- sqrt (0.5)));
148       SI hh= (SI) (((double) h) / sqrt (2.0));
149       SI ox= x+ ww;
150       SI oy= y+ (h>>1);
151       ren->set_pencil (pen->set_width (ren->pixel));
152       for (i=0; i<lw; i+=ren->pixel)
153 	ren->arc (ox-ww+i, oy-hh, ox+ww-i, oy+hh, 135<<6, 90<<6);
154     }
155     break;
156   case Rbracket:
157     {
158       int i;
159       SI ww= (SI) (((double) w) / (1.0- sqrt (0.5)));
160       SI hh= (SI) (((double) h) / sqrt (2.0));
161       SI ox= x+ w- ww;
162       SI oy= y+ (h>>1);
163       ren->set_pencil (pen->set_width (ren->pixel));
164       for (i=0; i<lw; i+=ren->pixel)
165 	ren->arc (ox-ww+i, oy-hh, ox+ww-i, oy+hh, -(45<<6), 90<<6);
166     }
167     break;
168   case Lcrochet:
169     ren->line (x, y, x, y+h);
170     ren->line (x, y, x+w, y);
171     ren->line (x, y+h, x+w, y+h);
172     break;
173   case Rcrochet:
174     ren->line (x+w, y, x+w, y+h);
175     ren->line (x, y, x+w, y);
176     ren->line (x, y+h, x+w, y+h);
177     break;
178   case Laccolade:
179   case Raccolade:
180     {
181       SI d = w>>1;
182       SI ox= x+ (w>>1);
183       SI oy= y+ (h>>1);
184       // SI xx= x+ w;
185       SI yy= y+ h;
186       ren->line (ox, y+d-PIXEL, ox, oy-d);
187       ren->line (ox, oy+d-PIXEL, ox, yy-d);
188       if (br_type==Laccolade) {
189 	ren->arc (ox, yy-w, ox+w, yy, 90<<6, 90<<6);
190 	ren->arc (ox-w, oy, ox, oy+w, 270<<6, 90<<6);
191 	ren->arc (ox-w, oy-w, ox, oy, 0, 90<<6);
192 	ren->arc (ox, y, ox+w, y+w, 180<<6, 90<<6);
193       }
194       else {
195 	ren->arc (ox-w, yy-w, ox, yy, 0, 90<<6);
196 	ren->arc (ox, oy, ox+w, oy+w, 180<<6, 90<<6);
197 	ren->arc (ox, oy-w, ox+w, oy, 90<<6, 90<<6);
198 	ren->arc (ox-w, y, ox, y+w, 270<<6, 90<<6);
199       }
200     }
201     break;
202   case Langular:
203     ren->line (x, y+(h>>1), x+w, y);
204     ren->line (x, y+(h>>1), x+w, y+h);
205     break;
206   case Rangular:
207     ren->line (x+w, y+(h>>1), x, y);
208     ren->line (x+w, y+(h>>1), x, y+h);
209     break;
210   case Absolute:
211     ren->line (x, y, x, y+h);
212     break;
213   }
214 }
215 
216 void
display(renderer ren)217 bracket_box_rep::display (renderer ren) {
218   draw_bracket (ren, br_type, 0, y1, x2, y2-y1, pen);
219 }
220 
221 /*****************************************************************************/
222 // box construction routines
223 /*****************************************************************************/
224 
225 box
empty_box(path ip,int x1,int y1,int x2,int y2)226 empty_box (path ip, int x1, int y1, int x2, int y2) {
227   return tm_new<empty_box_rep> (ip, x1, y1, x2, y2);
228 }
229 
230 box
dummy_box(path ip,int x1,int y1,int x2,int y2)231 dummy_box (path ip, int x1, int y1, int x2, int y2) {
232   return tm_new<dummy_box_rep> (ip, x1, y1, x2, y2);
233 }
234 
235 box
marker_box(path ip,int x1,int y1,int x2,int y2,box ref)236 marker_box (path ip, int x1, int y1, int x2, int y2, box ref) {
237   return tm_new<marker_box_rep> (ip, x1, y1, x2, y2, ref);
238 }
239 
240 box
bracket_box(path ip,int br_type,pencil pen,SI y1,SI y2)241 bracket_box (path ip, int br_type, pencil pen, SI y1, SI y2) {
242   return tm_new<bracket_box_rep> (ip, br_type, pen, y1, y2);
243 }
244