Back to index

texmacs  1.0.7.15
virtual_font.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : virtual_font.cpp
00004 * DESCRIPTION: fonts consisting of extra symbols which can be generated
00005 *              automatically from a defining tree
00006 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00007 *******************************************************************************
00008 * This software falls under the GNU general public license version 3 or later.
00009 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00010 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00011 ******************************************************************************/
00012 
00013 #include "font.hpp"
00014 #include "translator.hpp"
00015 #include "analyze.hpp"
00016 
00017 /******************************************************************************
00018 * The virtual font class
00019 ******************************************************************************/
00020 
00021 struct virtual_font_rep: font_rep {
00022   font         base_fn;
00023   translator   virt;
00024   int          size, dpi;
00025   int          last;
00026   font_metric  fnm;
00027   font_glyphs  fng;
00028   double       unit;
00029 
00030   virtual_font_rep (string name, font base, string vname, int size, int dpi);
00031   glyph compile (scheme_tree t, metric& ex);
00032   int   get_char (string s, font_metric& fnm, font_glyphs& fng);
00033   glyph get_glyph (string s);
00034 
00035   void get_extents (string s, metric& ex);
00036   void draw (renderer ren, string s, SI x, SI y);
00037 };
00038 
00039 virtual_font_rep::virtual_font_rep (
00040   string name, font base, string vname, int size2, int dpi2):
00041     font_rep (name, base), base_fn (base),
00042     virt (load_translator (vname)), size (size2), dpi (dpi2),
00043     last (N(virt->virt_def)),
00044     fnm (std_font_metric (name, tm_new_array<metric> (last), 0, last-1)),
00045     fng (std_font_glyphs (name, tm_new_array<glyph> (last), 0, last-1))
00046 {
00047   copy_math_pars (base_fn);
00048   unit= ((size*dpi)/72)*PIXEL;
00049 }
00050 
00051 /******************************************************************************
00052 * Compilation of virtual characters
00053 ******************************************************************************/
00054 
00055 static void
00056 outer_fit (metric& ex, metric& ey, SI x, SI y) {
00057   ex->x1= min (ex->x1, x+ ey->x1);
00058   ex->y1= min (ex->y1, y+ ey->y1);
00059   ex->x2= max (ex->x2, x+ ey->x2);
00060   ex->y2= max (ex->y2, y+ ey->y2);
00061   ex->x3= min (ex->x3, x+ ey->x3);
00062   ex->y3= min (ex->y3, y+ ey->y3);
00063   ex->x4= max (ex->x4, x+ ey->x4);
00064   ex->y4= max (ex->y4, y+ ey->y4);
00065 }
00066 
00067 glyph
00068 virtual_font_rep::compile (scheme_tree t, metric& ex) {
00069   // cout << "Compile " << t << "\n";
00070 
00071   if (is_atomic (t)) {
00072     string r= t->label;
00073     if (N(r)>1) r= "<" * r * ">";
00074     base_fn->get_extents (r, ex);
00075     return base_fn->get_glyph (r);
00076   }
00077 
00078   if (is_func (t, TUPLE, 3) &&
00079       (is_double (t[0])) && (is_double (t[1])))
00080     {
00081       SI x= (SI) (as_double (t[0]) * unit);
00082       SI y= (SI) (as_double (t[1]) * unit);
00083       glyph gl= compile (t[2], ex);
00084       ex->x1 += x; ex->y1 += y;
00085       ex->x2 += x; ex->y2 += y;
00086       ex->x3 += x - PIXEL; ex->y3 += y + PIXEL;
00087       ex->x4 += x - PIXEL; ex->y4 += y + PIXEL;
00088       return move (gl, x, y);
00089     }
00090 
00091   if (is_tuple (t, "join")) {
00092     int i, n= N(t);
00093     glyph gl1= compile (t[1], ex);
00094     for (i=2; i<n; i++) {
00095       metric ey;
00096       glyph gl2= compile (t[i], ey);
00097       outer_fit (ex, ey, 0, 0);
00098       gl1= join (gl1, gl2);
00099     }
00100     return gl1;
00101   }
00102 
00103   if (is_tuple (t, "glue", 2)) {
00104     metric ey;
00105     glyph gl1= compile (t[1], ex);
00106     glyph gl2= compile (t[2], ey);
00107     SI dx= ex->x2- ((base_fn->wpt*28)>>4);
00108     outer_fit (ex, ey, dx, 0);
00109     return join (gl1, move (gl2, dx, 0));
00110   }
00111 
00112   if (is_tuple (t, "glue*", 2)) {
00113     metric ey;
00114     glyph gl1= compile (t[1], ex);
00115     glyph gl2= compile (t[2], ey);
00116     SI dx= ex->x2;
00117     outer_fit (ex, ey, dx, 0);
00118     return join (gl1, move (gl2, dx, 0));
00119   }
00120 
00121   if (is_tuple (t, "add", 2)) {
00122     metric ey;
00123     glyph gl1= compile (t[1], ex);
00124     glyph gl2= compile (t[2], ey);
00125     SI dx= ((ex->x1+ ex->x2- ey->x1- ey->x2) >> 1);
00126     outer_fit (ex, ey, dx, 0);
00127     return join (gl1, move (gl2, dx, 0));
00128   }
00129 
00130   if (is_tuple (t, "enlarge")) {
00131     glyph gl= compile (t[1], ex);
00132     if (N(t)>2) ex->x1 -= (SI) (as_double (t[2]) * unit);
00133     if (N(t)>3) ex->x2 += (SI) (as_double (t[3]) * unit);
00134     if (N(t)>4) ex->y1 -= (SI) (as_double (t[4]) * unit);
00135     if (N(t)>5) ex->y2 += (SI) (as_double (t[5]) * unit);
00136     return gl;
00137   }
00138 
00139   if (is_tuple (t, "clip")) {
00140     glyph gl= compile (t[1], ex);
00141     if (N(t)>2 && t[2]!="*") ex->x1= ex->x3= (SI) (as_double (t[2]) * unit);
00142     if (N(t)>3 && t[3]!="*") ex->x2= ex->x4= (SI) (as_double (t[3]) * unit);
00143     if (N(t)>4 && t[4]!="*") ex->y1= ex->y3= (SI) (as_double (t[4]) * unit);
00144     if (N(t)>5 && t[5]!="*") ex->y2= ex->y4= (SI) (as_double (t[5]) * unit);
00145     return clip (gl, ex->x3, ex->y3, ex->x4, ex->y4);
00146   }
00147 
00148   if (is_tuple (t, "hor-flip", 1))
00149     return hor_flip (compile (t[1], ex));
00150 
00151   if (is_tuple (t, "ver-flip", 1))
00152     return ver_flip (compile (t[1], ex));
00153 
00154   if (is_tuple (t, "rot-left", 1)) {
00155     metric ey;
00156     glyph gl= pos_rotate (compile (t[1], ey));
00157     ex->x1= 0;
00158     ex->y1= 0;
00159     ex->x2= ey->y2- ey->y1;
00160     ex->y2= ey->x2- ey->x1;
00161     ex->x3= ey->y2- ey->y4;
00162     ex->y3= ey->x3- ey->x1;
00163     ex->x4= ey->y2- ey->y3;
00164     ex->y4= ey->x4- ey->x1;
00165     return move (gl, ey->y2, -ey->x1);
00166   }
00167 
00168   if (is_tuple (t, "rot-right", 1)) {
00169     metric ey;
00170     glyph gl= pos_rotate (pos_rotate (pos_rotate (compile (t[1], ey))));
00171     ex->x1= 0;
00172     ex->y1= 0;
00173     ex->x2= ey->y2- ey->y1;
00174     ex->y2= ey->x2- ex->x1;
00175     ex->x3= ey->y3- ey->y1;
00176     ex->y3= ey->x2- ey->x4;
00177     ex->x4= ey->y4- ey->y1;
00178     ex->y4= ey->x2- ey->x3;
00179     return move (gl, -ey->y1, ey->x2);
00180   }
00181 
00182   if (is_tuple (t, "hor-extend", 3) || is_tuple (t, "hor-extend", 4)) {
00183     glyph gl= compile (t[1], ex);
00184     int pos= (int) (as_double (t[2]) * gl->width);
00185     SI  add= (SI)  (as_double (t[3]) * unit);
00186     if (is_tuple (t, "hor-extend", 4))
00187       add= (SI)  (as_double (t[3]) * as_double (t[4]) * unit);
00188     int by = add / PIXEL;
00189     if (pos < 0) pos= 0;
00190     if (pos >= gl->width) pos= gl->width-1;
00191     ex->x2 += add;
00192     ex->x4 += by * PIXEL;
00193     return hor_extend (gl, pos, by);
00194   }
00195 
00196   if (is_tuple (t, "ver-extend", 3) || is_tuple (t, "ver-extend", 4)) {
00197     glyph gl= compile (t[1], ex);
00198     int pos= (int) (as_double (t[2]) * gl->height);
00199     SI  add= (SI)  (as_double (t[3]) * unit);
00200     if (is_tuple (t, "ver-extend", 4))
00201       add= (SI)  (as_double (t[3]) * as_double (t[4]) * unit);
00202     int by = add / PIXEL;
00203     if (pos < 0) pos= 0;
00204     if (pos >= gl->height) pos= gl->height-1;
00205     ex->y1 -= add;
00206     ex->y3 -= by * PIXEL;
00207     return ver_extend (gl, pos, by);
00208   }
00209 
00210   cerr << "TeXmacs] The defining tree is " << t << "\n";
00211   FAILED ("invalid virtual character");
00212   return glyph ();
00213 }
00214 
00215 /******************************************************************************
00216 * Getting extents and drawing strings
00217 ******************************************************************************/
00218 
00219 static tree
00220 subst_sharp (tree t, string by) {
00221   if (is_atomic (t)) {
00222     int i;
00223     string s= t->label;
00224     i= search_forwards ("#", s);
00225     if (i == -1) return s;
00226     else return s(0,i) * by * s(i+1,N(s));
00227   }
00228   else {
00229     int i, n= N(t);
00230     tree r (t, n);
00231     for (i=0; i<n; i++)
00232       r[i]= subst_sharp (t[i], by);
00233     return r;
00234   }
00235 }
00236 
00237 static void
00238 make_char_font (string name, font_metric& cfnm, font_glyphs& cfng) {
00239   cfnm= std_font_metric (name, tm_new_array<metric> (1), 0, 0);
00240   cfng= std_font_glyphs (name, tm_new_array<glyph> (1), 0, 0);
00241 }
00242 
00243 /******************************************************************************
00244 * Getting extents and drawing strings
00245 ******************************************************************************/
00246 
00247 int
00248 virtual_font_rep::get_char (string s, font_metric& cfnm, font_glyphs& cfng) {
00249   int c= ((N(s)==0)? -1: ((QN) s[0]));
00250   if ((c<0) || (c>=last)) return -1;
00251   if (N(s)==1) {
00252     cfnm= fnm;
00253     cfng= fng;
00254     if (is_nil (fng->get(c)))
00255       fng->get(c)= compile (virt->virt_def[c], fnm->get(c));
00256     return c;
00257   }
00258   else {
00259     make_char_font (res_name * s, cfnm, cfng);
00260     tree t= subst_sharp (virt->virt_def[c], s(1,N(s)));
00261     if (is_nil (cfng->get(0)))
00262       cfng->get(0)= compile (t, cfnm->get(0));
00263     return 0;
00264   }
00265 }
00266 
00267 void
00268 virtual_font_rep::get_extents (string s, metric& ex) {
00269   font_metric cfnm;
00270   font_glyphs cfng;
00271   int c= get_char (s, cfnm, cfng);
00272   if (c == -1) {
00273     ex->y1= y1; ex->y2= y2;
00274     ex->x1= ex->x2= ex->x3= ex->x4= ex->y3= ex->y4= 0;
00275   }
00276   else {
00277     metric_struct* ey= cfnm->get(c);
00278     ex->x1= ey->x1; ex->y1= ey->y1;
00279     ex->x2= ey->x2; ex->y2= ey->y2;
00280     ex->x3= ey->x3; ex->y3= ey->y3;
00281     ex->x4= ey->x4; ex->y4= ey->y4;
00282   }
00283 }
00284 
00285 void
00286 virtual_font_rep::draw (renderer ren, string s, SI x, SI y) {
00287   font_metric cfnm;
00288   font_glyphs cfng;
00289   int c= get_char (s, cfnm, cfng);
00290   if (c != -1) ren->draw (c, cfng, x, y);
00291 }
00292 
00293 glyph
00294 virtual_font_rep::get_glyph (string s) {
00295   font_metric cfnm;
00296   font_glyphs cfng;
00297   int c= get_char (s, cfnm, cfng);
00298   if (c == -1) return font_rep::get_glyph (s);
00299   else return cfng->get(c);
00300 }
00301 
00302 /******************************************************************************
00303 * User interface
00304 ******************************************************************************/
00305 
00306 font
00307 virtual_font (font base, string name, int size, int dpi) {
00308   string full_name=
00309     base->res_name * "#virtual-" *
00310     name * as_string (size) * "@" * as_string (dpi);
00311   return make (font, full_name,
00312     tm_new<virtual_font_rep> (full_name, base, name, size, dpi));
00313 }