Back to index

texmacs  1.0.7.15
tex_rubber_font.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : tex_rubber_font.cpp
00004 * DESCRIPTION: TeX rubber fonts
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "font.hpp"
00013 #include "translator.hpp"
00014 #include "Metafont/load_tex.hpp"
00015 
00016 /******************************************************************************
00017 * TeX rubber fonts
00018 ******************************************************************************/
00019 
00020 struct tex_rubber_font_rep: font_rep {
00021   string           family;
00022   int              dpi;
00023   int              dsize;
00024   translator       ext;
00025   tex_font_metric  tfm;
00026   font_glyphs      pk;
00027   double           unit;
00028 
00029   tex_rubber_font_rep (string name, string trl_name,
00030                      string family, int size, int dpi, int dsize);
00031   void get_extents (int c, metric& ex);
00032   void get_partial_extents (int c, metric& ex);
00033   void get_extents (string s, metric& ex);
00034   void draw (renderer ren, int c, SI x, SI& y, SI& real_y);
00035   void draw (renderer ren, string s, SI x, SI y);
00036 
00037   double get_left_slope (string s);
00038   double get_right_slope (string s);
00039   SI     get_right_correction (string s);
00040 };
00041 
00042 struct tex_dummy_rubber_font_rep: font_rep {
00043   font base_fn;
00044   tex_dummy_rubber_font_rep (string name, font base_fn);
00045   void get_extents (string s, metric& ex);
00046   void draw (renderer ren, string s, SI x, SI y);
00047 };
00048 
00049 /******************************************************************************
00050 * The implementation of TeX rubber fonts
00051 ******************************************************************************/
00052 
00053 #define conv(x) ((SI) (((double) (x))*unit))
00054 
00055 tex_rubber_font_rep::tex_rubber_font_rep (string name,
00056   string trl_name, string family2, int size2, int dpi2, int dsize2):
00057     font_rep (name), dsize (dsize2), ext (load_translator (trl_name))
00058 {
00059   load_tex (family2, size2, dpi2, dsize, tfm, pk);
00060 
00061   family       = family2;
00062   size         = size2;
00063   dpi          = dpi2;
00064   design_size  = tfm->design_size () >> 12;
00065   display_size = (((design_size*dpi)/72)*PIXEL) >> 8;
00066   unit         = ((double) display_size) / ((double) (1<<20));
00067   slope        = tfm->slope ();
00068   spc->def     = conv (tfm->spc ());
00069   spc->min     = spc->def - conv (tfm->spc_shrink ());
00070   spc->max     = spc->def + conv (tfm->spc_stretch ());
00071   extra        = conv (tfm->spc_extra ());
00072   extra->min   = extra->min >> 1;
00073   extra->max   = extra->min << 1;
00074   sep          = ((((dpi*PIXEL)/72)*design_size) >> 8) / 10;
00075 
00076   y1           = conv (-262080);
00077   y2           = y1+ display_size;
00078   yx           = conv (tfm->x_height ());
00079   yfrac        = yx >> 1;
00080   ysub_lo_base = -yx/3;
00081   ysub_hi_lim  = (5*yx)/6;
00082   ysup_lo_lim  = yx/2;
00083   ysup_lo_base = (5*yx)/6;
00084   ysup_hi_lim  = yx;
00085   yshift       = yx/6;
00086 
00087   wpt          = (dpi*PIXEL)/72;
00088   wfn          = (wpt*design_size) >> 8;
00089   wline        = wfn/20;
00090   wquad        = conv (tfm->spc_quad ());
00091 }
00092 
00093 font
00094 tex_rubber_font (string trl_name,
00095                string family, int size, int dpi, int dsize) {
00096   string name= "tex-rubber:"*family * as_string (size) * "@" * as_string(dpi);
00097   return make (font, name,
00098     tm_new<tex_rubber_font_rep> (name, trl_name, family, size, dpi, dsize));
00099 }
00100 
00101 /******************************************************************************
00102 * Drawing rubber boxes and computing extents
00103 ******************************************************************************/
00104 
00105 void
00106 tex_rubber_font_rep::get_extents (int c, metric& ex) {
00107   glyph gl= pk->get (c);
00108   if (is_nil (gl))
00109     ex->x1= ex->y1= ex->x2= ex->y2= ex->x3= ex->y3= ex->x4= ex->y4= 0;
00110   else {
00111     ex->x1=  0;
00112     ex->y1= -conv (tfm->d(c));
00113     ex->x2=  conv (tfm->w(c));
00114     ex->y2=  conv (tfm->h(c));
00115     ex->x3= -((int) gl->xoff) * PIXEL;
00116     ex->x4=  ((int) (gl->width- gl->xoff)) * PIXEL;
00117     ex->y3=  ((int) (gl->yoff- gl->height)) * PIXEL;
00118     ex->y4=  ((int) gl->yoff) * PIXEL;
00119 
00120     ex->x3 -= 2*PIXEL; ex->x4 += 2*PIXEL;
00121     ex->y3 -= 2*PIXEL; ex->y4 += 3*PIXEL;
00122   }
00123 }
00124 
00125 void
00126 tex_rubber_font_rep::get_partial_extents (int c, metric& ex) {
00127   metric ey;
00128   get_extents (c, ey);
00129   ex->x1= min (ex->x1, ey->x1); ex->y1 -= (ey->y2-ey->y1);
00130   ex->x2= max (ex->x2, ey->x2);
00131   ex->x3= min (ex->x3, ey->x3); ex->y3= min (ex->y3, ex->y1+ (ey->y3-ey->y1));
00132   ex->x4= max (ex->x4, ey->x4); ex->y4= max (ex->y4, ex->y1+ (ey->y4-ey->y1));
00133 }
00134 
00135 void
00136 tex_rubber_font_rep::get_extents (string s, metric& ex) {
00137   ASSERT ((N(s)>=2) && (s[0]=='<') && (s[N(s)-1]=='>'),
00138          "invalid rubber character");
00139 
00140   // determining base character and serial number
00141   int i;
00142   for (i=N(s)-1; i>0; i--) if (s[i]=='-') break;
00143   string r= s (0, i) * ">";
00144   QN pre_c= ext->dict[r];
00145   int n= as_int (s (i+1, N(s)-1));
00146   if ((pre_c<tfm->bc) || (pre_c>tfm->ec)) {
00147     ex->x1= ex->y1= ex->x2= ex->y2= ex->x3= ex->y3= ex->x4= ex->y4= 0;
00148     return;
00149   }
00150 
00151   // get extents
00152   QN c= tfm->nth_in_list (pre_c, n);
00153   if (tfm->tag (c) != 3) get_extents (c, ex);
00154   else {
00155     int i, nr_rep= n- tfm->list_len (pre_c);
00156 
00157     ex->x1= ex->x3= ex->y3= PLUS_INFINITY;
00158     ex->x2= ex->x4= ex->y4= MINUS_INFINITY;
00159     ex->y1= ex->y2= 0;
00160 
00161     if (tfm->top (c)!=0) get_partial_extents (tfm->top (c), ex);
00162     if ((tfm->rep (c)!=0) && (tfm->mid (c)!=0))
00163       for (i=0; i<nr_rep; i++) get_partial_extents (tfm->rep (c), ex);
00164     if (tfm->mid (c)!=0) get_partial_extents (tfm->mid (c), ex);
00165     if (tfm->rep (c)!=0)
00166       for (i=0; i<nr_rep; i++) get_partial_extents (tfm->rep (c), ex);
00167     if (tfm->bot (c)!=0) get_partial_extents (tfm->bot (c), ex);
00168   }
00169 
00170   if ((N(s) >= 7) && (s(0,5) == "<big-") && (n == 2)) {
00171     // correction for very big operators
00172     ex->y1 += ex->y2;
00173     ex->y2  = 0;
00174   }
00175   else {
00176     // correction for large delimiters
00177     int j;
00178     for (j=1; j<N(s); j++) if (s[j]=='-') break;
00179     if (j==N(s)) return; else j++;
00180     switch (s[j]) {
00181     case 'r':
00182       if ((N(s) >= j+6) && (s(j+1,j+6) == "angle")) {
00183        ex->x1= ex->x3- sep;
00184        ex->x2= ex->x4+ sep;
00185        break;
00186       }
00187     case ']':
00188     case '|':
00189       ex->x1= ex->x3- sep;
00190       ex->x2= ex->x4+ (3*sep/2);
00191       break;
00192     case 's':
00193       break;
00194     default:
00195       ex->x1= ex->x3- sep;
00196       ex->x2= ex->x4+ sep;
00197     }
00198   }
00199 }
00200 
00201 void
00202 tex_rubber_font_rep::draw (renderer ren, int c, SI x, SI& y, SI& real_y) {
00203   ren->draw (c, pk, x, y);
00204   SI delta  = conv (tfm->h (c)+ tfm->d (c));
00205   SI pixel  = PIXEL * ren->sfactor;
00206   y        -= pixel * (delta/pixel);
00207   real_y   -= delta;
00208   while (y >= real_y + pixel) y -= pixel;
00209 }
00210 
00211 void
00212 tex_rubber_font_rep::draw (renderer ren, string s, SI x, SI y) {
00213   metric ex;
00214   get_extents (s, ex);
00215 
00216   // determining base character and serial number
00217   int i;
00218   for (i=N(s)-1; i>0; i--) if (s[i]=='-') break;
00219   string r= s (0, i) * ">";
00220   QN pre_c= ext->dict[r];
00221   int n= as_int (s (i+1, N(s)-1));
00222 
00223   // draw the character
00224   if ((pre_c<tfm->bc) || (pre_c>tfm->ec)) return;
00225   QN c = tfm->nth_in_list (pre_c, n);
00226 
00227   if (tfm->tag (c) != 3) ren->draw (c, pk, x, y);
00228   else {
00229     int i;
00230     int nr_rep= n- tfm->list_len (pre_c);
00231 
00232     SI real_y= y; // may be necessary to round y
00233                   // using SI temp= x; decode (temp, y); encode (temp, y);
00234     if (tfm->top (c)!=0) draw (ren, tfm->top (c), x, y, real_y);
00235     if (tfm->rep (c)!=0)
00236       for (i=0; i<nr_rep; i++)
00237        draw (ren, tfm->rep (c), x, y, real_y);
00238     if (tfm->mid (c)!=0) draw (ren, tfm->mid (c), x, y, real_y);
00239     if ((tfm->rep (c)!=0) && (tfm->mid (c)!=0))
00240       for (i=0; i<nr_rep; i++)
00241        draw (ren, tfm->rep (c), x, y, real_y);
00242     if (tfm->bot (c)!=0) draw (ren, tfm->bot (c), x, y, real_y);
00243   }
00244 }
00245 
00246 /******************************************************************************
00247 * Metric properties of rubber boxes
00248 ******************************************************************************/
00249 
00250 double
00251 tex_rubber_font_rep::get_left_slope (string s) {
00252   if ((N(s)>=5) && (s(0,5)=="<big-") && (get_right_correction(s)!=0))
00253     return 0.25;
00254   return slope;
00255 }
00256 
00257 double
00258 tex_rubber_font_rep::get_right_slope (string s) {
00259   if ((N(s)>=5) && (s(0,5)=="<big-") && (get_right_correction(s)!=0))
00260     return 0.25;
00261   return slope;
00262 }
00263 
00264 SI
00265 tex_rubber_font_rep::get_right_correction (string s) {
00266   if ((N(s)>=5) && (s(0,5)=="<big-")) {
00267     int i;
00268     for (i=N(s)-1; i>0; i--) if (s[i]=='-') break;
00269     string r= s (0, i) * ">";
00270     QN  pre_c= ext->dict[r];
00271     int n    = as_int (s (i+1, N(s)-1));
00272     QN  c    = tfm->nth_in_list (pre_c, n);
00273     return conv (tfm->i (c));
00274   }
00275   return 0;
00276 }
00277 
00278 #undef conv
00279 
00280 /******************************************************************************
00281 * The implementation of TeX dummy rubber fonts for \left. \right. and \big.
00282 ******************************************************************************/
00283 
00284 tex_dummy_rubber_font_rep::tex_dummy_rubber_font_rep (string name, font fn):
00285   font_rep (name), base_fn (fn) {}
00286 
00287 void
00288 tex_dummy_rubber_font_rep::get_extents (string s, metric& ex) {
00289   string r= s;
00290   if (s(0,8) == "<large-.") r= "<left-(" * s (8, N(s));
00291   if (s(0,7) == "<left-.") r= "<left-(" * s (7, N(s));
00292   if (s(0,6) == "<mid-.") r= "<left-(" * s (6, N(s));
00293   if (s(0,8) == "<right-.") r= "<left-(" * s (8, N(s));
00294   if (s(0,6) == "<big-.") r= "<big-sum" * s (6, N(s));
00295   base_fn->get_extents (r, ex);
00296   ex->x1= ex->x2= ex->x3= ex->x4= 0;
00297 }
00298 
00299 void
00300 tex_dummy_rubber_font_rep::draw (renderer ren, string s, SI x, SI y) {
00301   (void) ren; (void) s; (void) x; (void) y;
00302 }
00303 
00304 font
00305 tex_dummy_rubber_font (font base_fn) {
00306   string name= "tex-dummy(" * base_fn->res_name * ")";
00307   return make (font, name, tm_new<tex_dummy_rubber_font_rep> (name, base_fn));
00308 }