Back to index

texmacs  1.0.7.15
load_tex.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : load_tex.cpp
00004 * DESCRIPTION: simultaneously load pk and tfm file and
00005 *              generate them if they can't be found.
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 "load_tex.hpp"
00014 #include "path.hpp"
00015 #include "boot.hpp"
00016 #include "Freetype/tt_file.hpp"
00017 #include "timer.hpp"
00018 #include "data_cache.hpp"
00019 
00020 #ifdef OS_WIN32
00021 #include <x11/xlib.h>
00022 #endif
00023 
00024 static int
00025 mag (double dpi, double size, double dsize) {
00026   if ((size>=100) && (dsize<100)) dsize *= 100;
00027   if ((dsize>=100) && (size<100))  size *= 100;
00028   return (int) (((size * dpi) / dsize) + 0.5);
00029 }
00030 
00031 /******************************************************************************
00032 * Loading tfm files
00033 ******************************************************************************/
00034 
00035 bool
00036 try_tfm (string family, int size, int osize, tex_font_metric& tfm, bool make) {
00037   // cout << "Try tfm " << family << size << " (" << osize << ")\n";
00038   make= make && get_setting ("MAKETFM") != "false";
00039   string name_tfm = family * as_string (osize) * ".tfm";
00040   if (tex_font_metric::instances -> contains (name_tfm)) {
00041     tfm= tex_font_metric (name_tfm);
00042     return true;
00043   }
00044   string name= family * (size==0? string (""): as_string (size)) * ".tfm";
00045   if (DEBUG_STD) cout << "TeXmacs] Try tfm " << name << "\n";
00046   url u= resolve_tex (name);
00047   if (is_none (u)) {
00048     if (exists (url ("$TEXMACS_HOME_PATH/fonts/error", name)))
00049       return false;
00050     if (make) {
00051       system_wait ("Generating font file", name);
00052       make_tex_tfm (name);
00053       system_wait ("");
00054       u= resolve_tex (name);
00055       if (is_none (u)) {
00056        reset_tfm_path ();
00057        u= resolve_tex (name);
00058        save_string (url ("$TEXMACS_HOME_PATH/fonts/error", name), "");
00059       }
00060     }
00061     if (is_none (u)) return false;
00062   }
00063   // cout << "Tfm " << family << osize << " -> " << family << size << "\n";
00064   tfm= load_tfm (u, family, osize);
00065   if (size != osize)
00066     cache_set ("font_cache.scm",
00067               "tfm:" * family * as_string (osize), as_string (size));
00068   if (size == 0) {
00069     size= tfm->size;
00070     if (DEBUG_STD) cout << "TeXmacs] Design size = " << size << "\n";
00071   }
00072   if (size != osize)
00073     tfm->header[1]= mag (tfm->header[1], osize, size);
00074   return true;
00075 }
00076 
00077 bool
00078 load_tex_tfm (string family, int size, int dsize, tex_font_metric& tfm,
00079              bool make)
00080 {
00081   //cout << "Load TeX tfm " << family << size << " (dsize= " << dsize << ")\n";
00082   if (try_tfm (family, size, size, tfm, make))
00083     return true;
00084   if (size > 333)
00085     return load_tex_tfm (family, (size+50)/100, dsize, tfm, make);
00086   if (false) { // NOTE: only use Type 1 fonts
00087     if ((size > 14) && try_tfm (family, 17, size, tfm, make)) return true;
00088     if ((size > 12) && try_tfm (family, 12, size, tfm, make)) return true;
00089     if ((size > 10) && try_tfm (family, 10, size, tfm, make)) return true;
00090     if ((size <  5) && try_tfm (family,  5, size, tfm, make)) return true;
00091     if ((size <  6) && try_tfm (family,  6, size, tfm, make)) return true;
00092     if ((size <  7) && try_tfm (family,  7, size, tfm, make)) return true;
00093     if ((size <  8) && try_tfm (family,  8, size, tfm, make)) return true;
00094     if ((size <  9) && try_tfm (family,  9, size, tfm, make)) return true;
00095     if ((size <  9) && try_tfm (family,  7, size, tfm, make)) return true;
00096     if (try_tfm (family, 10, size, tfm, make)) return true;
00097     if ((size > 14) && try_tfm (family, 1700, size, tfm, make)) return true;
00098     if ((size > 12) && try_tfm (family, 1200, size, tfm, make)) return true;
00099     if ((size < 5) && try_tfm (family, 500, size, tfm, make)) return true;
00100     if ((size < 9) && try_tfm (family, 700, size, tfm, make)) return true;
00101     if (try_tfm (family, 1000, size, tfm, make)) return true;
00102   }
00103   if (true) { // NOTE: first search for type 1, then use Metafont
00104     SI delta= (size<10? 1: -1);
00105     if (try_tfm (family, size + delta, size, tfm, make)) return true;
00106     if (try_tfm (family, size - delta, size, tfm, make)) return true;
00107     if (try_tfm (family, size + 2*delta, size, tfm, make)) return true;
00108     if (try_tfm (family, size - 2*delta, size, tfm, make)) return true;
00109     if (try_tfm (family, 100 * size, size, tfm, make)) return true;
00110     if (try_tfm (family, 100 * (size + delta), size, tfm, make)) return true;
00111     if (try_tfm (family, 100 * (size - delta), size, tfm, make)) return true;
00112     if (try_tfm (family, 100 * (size + 2*delta), size, tfm, make)) return true;
00113     if (try_tfm (family, 100 * (size - 2*delta), size, tfm, make)) return true;
00114   }
00115   if (dsize != size)
00116     if (try_tfm (family, dsize, size, tfm, make))
00117       return true;
00118   if ((dsize != 10) && (size != 10))
00119     if (try_tfm (family, 10, size, tfm, make))
00120       return true;
00121   return false;
00122 }
00123 
00124 bool
00125 load_tex_tfm (string family, int size, int dsize, tex_font_metric& tfm) {
00126   string var= "tfm:" * family * as_string (size);
00127   if (is_cached ("font_cache.scm", var))
00128     if (try_tfm (family, as_int (cache_get ("font_cache.scm", var)->label),
00129                size, tfm, false))
00130       return true;
00131   if (get_setting ("MAKETFM") != "false")
00132     if (load_tex_tfm (family, size ,dsize, tfm, false))
00133       return true;
00134   return load_tex_tfm (family, size ,dsize, tfm, true);
00135 }
00136 
00137 /******************************************************************************
00138 * PK font glyphs with lazy parsing
00139 ******************************************************************************/
00140 
00141 static glyph error_glyph;
00142 
00143 struct pk_font_glyphs_rep: public font_glyphs_rep {
00144   pk_loader* pkl;
00145   int bc, ec;
00146   glyph* fng; // definitions of the characters
00147 
00148   pk_font_glyphs_rep (string name, pk_loader*);
00149   glyph& get (int char_code);
00150 };
00151 
00152 pk_font_glyphs_rep::pk_font_glyphs_rep(string name, pk_loader* pkl2)
00153   :font_glyphs_rep (name), pkl (pkl2)
00154 {
00155   if (pkl) {
00156     fng = pkl->load_pk ();
00157     bc = pkl->tfm->bc;
00158     ec = pkl->tfm->ec;
00159   }
00160   else {
00161     fng = 0;
00162     bc = 0;
00163     ec = -1;
00164   }
00165 }
00166 
00167 glyph&
00168 pk_font_glyphs_rep::get(int c)
00169 {
00170   if ((c<bc) || (c>ec)) return error_glyph;
00171   if (pkl && !pkl->unpacked[c-bc]) {
00172     pkl->input_pos = pkl->char_pos[c-bc];
00173     pkl->flagbyte  = pkl->char_flag[c-bc];
00174     pkl->unpack(fng[c-bc]);
00175 
00176     pkl->unpacked[c-bc] = true;
00177   }
00178   return fng [c-bc];
00179 }
00180 
00181 /******************************************************************************
00182 * Loading pk files
00183 ******************************************************************************/
00184 
00185 bool
00186 try_pk (string family, int size, int dpi, int dsize,
00187        tex_font_metric& tfm, font_glyphs& pk)
00188 {
00189   // cout << "Try pk " << family << size << " at " << dpi << " dpi\n";
00190 #ifdef USE_FREETYPE
00191   // Substitute by True Type font ?
00192   int tt_size= size<333? size: (size+50)/100;
00193   int tt_dpi = size<333? dpi : (size * dpi) / (100 * tt_size);
00194   string tt_name= tt_find_name (family, tt_size);
00195   if (tt_name != "") {
00196     if (font_glyphs::instances -> contains (tt_name))
00197       pk= font_glyphs (tt_name);
00198     else pk= tt_font_glyphs (tt_name, tt_size, tt_dpi);
00199     return true;
00200   }
00201 #endif // USE_FREETYPE
00202 
00203   // Open regular pk font
00204   string name_pk= family * as_string (size) * "." * as_string (dpi) * "pk";
00205   if (font_glyphs::instances -> contains (name_pk)) {
00206     pk = font_glyphs (name_pk);
00207     return true;
00208   }
00209   if (dsize == 0) {
00210     int old_size= size;
00211     size= tfm->size;
00212     dpi = mag (dpi, old_size, size);
00213   }
00214   string size_name (dsize==0? string (""): as_string (size));
00215   string name (family * size_name * "." * as_string (dpi) * "pk");
00216   if (DEBUG_STD) cout << "TeXmacs] Open pk " << name << "\n";
00217   url u= resolve_tex (name);
00218   if (is_none (u)) {
00219     if (exists (url ("$TEXMACS_HOME_PATH/fonts/error", name)))
00220       return false;
00221     if (get_setting ("MAKEPK") != "false") {
00222       system_wait ("Generating font file", name);
00223       make_tex_pk (family * size_name, dpi, as_int (get_setting ("DPI")));
00224       system_wait ("");
00225       u= resolve_tex (name);
00226       if (is_none (u)) {
00227        reset_pk_path ();
00228        u= resolve_tex (name);
00229       }
00230     }
00231     if (is_none (u)) {
00232       save_string (url ("$TEXMACS_HOME_PATH/fonts/error", name), "");
00233       return false;
00234     }
00235   }
00236   pk = font_glyphs (tm_new<pk_font_glyphs_rep> (name_pk,
00237                                        tm_new<pk_loader> (u, tfm, dpi)));
00238   return true;
00239 }
00240 
00241 bool
00242 load_tex_pk (string family, int size, int dpi, int dsize,
00243             tex_font_metric& tfm, font_glyphs& pk) {
00244   if (try_pk (family, size, dpi, dsize, tfm, pk)) return true;
00245   if ((dsize != size) && (dsize != 0))
00246     if (try_pk (family, dsize, mag (dpi, size, dsize), dsize, tfm, pk))
00247       return true;
00248   if ((dsize != 10) && (size != 10))
00249     if (try_pk (family, 10, mag (dpi, size, 10), dsize, tfm, pk))
00250       return true;
00251   if (size > 333) {
00252     int sz= (size+50)/100;
00253     return load_tex_pk (family, sz, mag (dpi, size, sz), dsize, tfm, pk);
00254   }
00255   return false;
00256 }
00257 
00258 /******************************************************************************
00259 * Loading tfm and pk files
00260 ******************************************************************************/
00261 
00262 static void
00263 rubber_status (glyph& gl, int st) {
00264   gl -> status |= st;
00265   gl -> yoff    = 0;
00266 }
00267 
00268 static void
00269 rubber_fix (tex_font_metric tfm, font_glyphs& pk) {
00270   // This routine is used so as to correct the anti-aliasing of
00271   // rubber TeX characters (in the vertical direction).
00272   register int c;
00273   for (c=tfm->bc; c<=tfm->ec; c++) {
00274     if (tfm->tag (c)==3) {
00275       if (tfm->bot(c)!=0) rubber_status (pk->get (tfm->bot (c)), 1);
00276       if (tfm->top(c)!=0) rubber_status (pk->get (tfm->top (c)), 2);
00277       if (tfm->mid(c)!=0) rubber_status (pk->get (tfm->mid (c)), 3);
00278       if (tfm->rep(c)!=0) rubber_status (pk->get (tfm->rep (c)), 3);
00279     }
00280   }
00281 }
00282 
00283 void
00284 load_tex (string family, int size, int dpi, int dsize,
00285          tex_font_metric& tfm, font_glyphs& pk)
00286 {
00287   bench_start ("load tex font");
00288   if (DEBUG_VERBOSE)
00289     cout << "TeXmacs] loading " << family << size
00290         << " at " << dpi << " dpi\n";
00291   if (load_tex_tfm (family, size, dsize, tfm) &&
00292       load_tex_pk (family, size, dpi, dsize, tfm, pk))
00293     {
00294       bench_cumul ("load tex font");
00295       rubber_fix (tfm, pk);
00296       return;
00297     }
00298   if (DEBUG_VERBOSE) {
00299     cout << "TeXmacs] font " << family << size
00300          << " at " << dpi << " dpi not found\n";
00301     cout << "TeXmacs] loading ecrm" << size
00302         << " at " << dpi << " dpi instead\n";
00303   }
00304   if (load_tex_tfm ("ecrm", size, 10, tfm) &&
00305       load_tex_pk ("ecrm", size, dpi, 10, tfm, pk))
00306     {
00307       bench_cumul ("load tex font");
00308       return;
00309     }
00310 #ifdef OS_WIN32
00311   else {
00312     string name= family * as_string (size) * "@" * as_string (dpi);
00313     cerr << "\n\nCould not open font " << name << "\nLoading default" << LF;
00314     cout << "Could not load font...\nLoading default" << LF;
00315     XNoTexWarn();
00316     if (load_tex_tfm ("ecrm", 10, 10, tfm) &&
00317        load_tex_pk ("ecrm", 10, 600, 10, tfm, pk))
00318       {
00319        bench_cumul ("load tex font");
00320        return;
00321       }
00322   }
00323 #endif
00324   string name= family * as_string (size) * "@" * as_string (dpi);
00325   cerr << "\n\nI could not open " << name << "\n";
00326   FAILED ("Tex seems not to be installed properly");
00327   bench_cumul ("load tex font");
00328 }