~registry/texmacs/trunk

« back to all changes in this revision

Viewing changes to src/src/Plugins/Metafont/load_tex.cpp

  • Committer: mgubi
  • Date: 2009-06-04 15:13:41 UTC
  • Revision ID: svn-v4:64cb5145-927a-446d-8aed-2fb7b4773692:trunk:2717
Support for X11 TeXmacs.app on Mac

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/******************************************************************************
 
3
* MODULE     : load_tex.cpp
 
4
* DESCRIPTION: simultaneously load pk and tfm file and
 
5
*              generate them if they can't be found.
 
6
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
 
7
*******************************************************************************
 
8
* This software falls under the GNU general public license version 3 or later.
 
9
* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
 
10
* in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
 
11
******************************************************************************/
 
12
 
 
13
#include "load_tex.hpp"
 
14
#include "path.hpp"
 
15
#include "boot.hpp"
 
16
#include "Freetype/tt_file.hpp"
 
17
#include "Freetype/tt_face.hpp"
 
18
#include "timer.hpp"
 
19
#include "data_cache.hpp"
 
20
 
 
21
#ifdef OS_WIN32
 
22
#include <x11/xlib.h>
 
23
#endif
 
24
 
 
25
static int
 
26
mag (double dpi, double size, double dsize) {
 
27
  if ((size>=100) && (dsize<100)) dsize *= 100;
 
28
  if ((dsize>=100) && (size<100))  size *= 100;
 
29
  return (int) (((size * dpi) / dsize) + 0.5);
 
30
}
 
31
 
 
32
/******************************************************************************
 
33
* Loading tfm files
 
34
******************************************************************************/
 
35
 
 
36
bool
 
37
try_tfm (string family, int size, int osize, tex_font_metric& tfm, bool make) {
 
38
  // cout << "Try tfm " << family << size << " (" << osize << ")\n";
 
39
  make= make && get_setting ("MAKETFM") != "false";
 
40
  string name_tfm = family * as_string (osize) * ".tfm";
 
41
  if (tex_font_metric::instances -> contains (name_tfm)) {
 
42
    tfm= tex_font_metric (name_tfm);
 
43
    return true;
 
44
  }
 
45
  string name= family * (size==0? string (""): as_string (size)) * ".tfm";
 
46
  if (DEBUG_STD) cout << "TeXmacs] Try tfm " << name << "\n";
 
47
  url u= resolve_tex (name);
 
48
  if (is_none (u)) {
 
49
    if (exists (url ("$TEXMACS_HOME_PATH/fonts/error", name)))
 
50
      return false;
 
51
    if (make) {
 
52
      system_wait ("Generating font file", name);
 
53
      make_tex_tfm (name);
 
54
      system_wait ("");
 
55
      u= resolve_tex (name);
 
56
      if (is_none (u)) {
 
57
        reset_tfm_path ();
 
58
        u= resolve_tex (name);
 
59
        save_string (url ("$TEXMACS_HOME_PATH/fonts/error", name), "");
 
60
      }
 
61
    }
 
62
    if (is_none (u)) return false;
 
63
  }
 
64
  // cout << "Tfm " << family << osize << " -> " << family << size << "\n";
 
65
  tfm= load_tfm (u, family, osize);
 
66
  if (size != osize)
 
67
    cache_set ("font_cache.scm",
 
68
               "tfm:" * family * as_string (osize), as_string (size));
 
69
  if (size == 0) {
 
70
    size= tfm->size;
 
71
    if (DEBUG_STD) cout << "TeXmacs] Design size = " << size << "\n";
 
72
  }
 
73
  if (size != osize)
 
74
    tfm->header[1]= mag (tfm->header[1], osize, size);
 
75
  return true;
 
76
}
 
77
 
 
78
bool
 
79
load_tex_tfm (string family, int size, int dsize, tex_font_metric& tfm,
 
80
              bool make)
 
81
{
 
82
  //cout << "Load TeX tfm " << family << size << " (dsize= " << dsize << ")\n";
 
83
  if (try_tfm (family, size, size, tfm, make))
 
84
    return true;
 
85
  if (size > 333)
 
86
    return load_tex_tfm (family, (size+50)/100, dsize, tfm, make);
 
87
  if (get_font_type () == 3) {
 
88
    if ((size > 14) && try_tfm (family, 17, size, tfm, make)) return true;
 
89
    if ((size > 12) && try_tfm (family, 12, size, tfm, make)) return true;
 
90
    if ((size > 10) && try_tfm (family, 10, size, tfm, make)) return true;
 
91
    if ((size <  5) && try_tfm (family,  5, size, tfm, make)) return true;
 
92
    if ((size <  6) && try_tfm (family,  6, size, tfm, make)) return true;
 
93
    if ((size <  7) && try_tfm (family,  7, size, tfm, make)) return true;
 
94
    if ((size <  8) && try_tfm (family,  8, size, tfm, make)) return true;
 
95
    if ((size <  9) && try_tfm (family,  9, size, tfm, make)) return true;
 
96
    if ((size <  9) && try_tfm (family,  7, size, tfm, make)) return true;
 
97
    if (try_tfm (family, 10, size, tfm, make)) return true;
 
98
    if ((size > 14) && try_tfm (family, 1700, size, tfm, make)) return true;
 
99
    if ((size > 12) && try_tfm (family, 1200, size, tfm, make)) return true;
 
100
    if ((size < 5) && try_tfm (family, 500, size, tfm, make)) return true;
 
101
    if ((size < 9) && try_tfm (family, 700, size, tfm, make)) return true;
 
102
    if (try_tfm (family, 1000, size, tfm, make)) return true;
 
103
  }
 
104
  if (get_font_type () == 2) {
 
105
    SI delta= (size<10? 1: -1);
 
106
    if (try_tfm (family, size + delta, size, tfm, make)) return true;
 
107
    if (try_tfm (family, size - delta, size, tfm, make)) return true;
 
108
    if (try_tfm (family, size + 2*delta, size, tfm, make)) return true;
 
109
    if (try_tfm (family, size - 2*delta, size, tfm, make)) return true;
 
110
    if (try_tfm (family, 100 * size, size, tfm, make)) return true;
 
111
    if (try_tfm (family, 100 * (size + delta), size, tfm, make)) return true;
 
112
    if (try_tfm (family, 100 * (size - delta), size, tfm, make)) return true;
 
113
    if (try_tfm (family, 100 * (size + 2*delta), size, tfm, make)) return true;
 
114
    if (try_tfm (family, 100 * (size - 2*delta), size, tfm, make)) return true;
 
115
  }
 
116
  if (dsize != size)
 
117
    if (try_tfm (family, dsize, size, tfm, make))
 
118
      return true;
 
119
  if ((dsize != 10) && (size != 10))
 
120
    if (try_tfm (family, 10, size, tfm, make))
 
121
      return true;
 
122
  return false;
 
123
}
 
124
 
 
125
bool
 
126
load_tex_tfm (string family, int size, int dsize, tex_font_metric& tfm) {
 
127
  string var= "tfm:" * family * as_string (size);
 
128
  if (is_cached ("font_cache.scm", var))
 
129
    if (try_tfm (family, as_int (cache_get ("font_cache.scm", var)->label),
 
130
                 size, tfm, false))
 
131
      return true;
 
132
  if (get_font_type () >= 2 && get_setting ("MAKETFM") != "false")
 
133
    if (load_tex_tfm (family, size ,dsize, tfm, false))
 
134
      return true;
 
135
  return load_tex_tfm (family, size ,dsize, tfm, true);
 
136
}
 
137
 
 
138
/******************************************************************************
 
139
* PK font glyphs with lazy parsing
 
140
******************************************************************************/
 
141
 
 
142
static glyph error_glyph;
 
143
 
 
144
struct pk_font_glyphs_rep: public font_glyphs_rep {
 
145
  pk_loader* pkl;
 
146
  int bc, ec;
 
147
  glyph* fng; // definitions of the characters
 
148
 
 
149
  pk_font_glyphs_rep (string name, pk_loader*);
 
150
  glyph& get (int char_code);
 
151
};
 
152
 
 
153
pk_font_glyphs_rep::pk_font_glyphs_rep(string name, pk_loader* pkl2)
 
154
  :font_glyphs_rep (name), pkl (pkl2)
 
155
{
 
156
  if (pkl) {
 
157
    fng = pkl->load_pk ();
 
158
    bc = pkl->tfm->bc;
 
159
    ec = pkl->tfm->ec;
 
160
  }
 
161
  else {
 
162
    fng = 0;
 
163
    bc = 0;
 
164
    ec = -1;
 
165
  }
 
166
}
 
167
 
 
168
glyph&
 
169
pk_font_glyphs_rep::get(int c)
 
170
{
 
171
  if ((c<bc) || (c>ec)) return error_glyph;
 
172
  if (pkl && !pkl->unpacked[c-bc]) {
 
173
    pkl->input_pos = pkl->char_pos[c-bc];
 
174
    pkl->flagbyte  = pkl->char_flag[c-bc];
 
175
    pkl->unpack(fng[c-bc]);
 
176
 
 
177
    pkl->unpacked[c-bc] = true;
 
178
  }
 
179
  return fng [c-bc];
 
180
}
 
181
 
 
182
/******************************************************************************
 
183
* Loading pk files
 
184
******************************************************************************/
 
185
 
 
186
bool
 
187
try_pk (string family, int size, int dpi, int dsize,
 
188
        tex_font_metric& tfm, font_glyphs& pk)
 
189
{
 
190
  // cout << "Try pk " << family << size << " at " << dpi << " dpi\n";
 
191
#ifdef USE_FREETYPE
 
192
  if (get_font_type () > 0) {
 
193
    // Substitute by True Type font ?
 
194
    int tt_size= size<333? size: (size+50)/100;
 
195
    int tt_dpi = size<333? dpi : (size * dpi) / (100 * tt_size);
 
196
    string tt_name= tt_find_name (family, tt_size);
 
197
    if (tt_name != "") {
 
198
      if (font_glyphs::instances -> contains (tt_name))
 
199
        pk= font_glyphs (tt_name);
 
200
      else pk= tt_font_glyphs (tt_name, tt_size, tt_dpi);
 
201
      return true;
 
202
    }
 
203
  }
 
204
#endif // USE_FREETYPE
 
205
 
 
206
  // Open regular pk font
 
207
  string name_pk= family * as_string (size) * "." * as_string (dpi) * "pk";
 
208
  if (font_glyphs::instances -> contains (name_pk)) {
 
209
    pk = font_glyphs (name_pk);
 
210
    return true;
 
211
  }
 
212
  if (dsize == 0) {
 
213
    int old_size= size;
 
214
    size= tfm->size;
 
215
    dpi = mag (dpi, old_size, size);
 
216
  }
 
217
  string size_name (dsize==0? string (""): as_string (size));
 
218
  string name (family * size_name * "." * as_string (dpi) * "pk");
 
219
  if (DEBUG_STD) cout << "TeXmacs] Open pk " << name << "\n";
 
220
  url u= resolve_tex (name);
 
221
  if (is_none (u)) {
 
222
    if (exists (url ("$TEXMACS_HOME_PATH/fonts/error", name)))
 
223
      return false;
 
224
    if (get_setting ("MAKEPK") != "false") {
 
225
      system_wait ("Generating font file", name);
 
226
      make_tex_pk (family * size_name, dpi, as_int (get_setting ("DPI")));
 
227
      system_wait ("");
 
228
      u= resolve_tex (name);
 
229
      if (is_none (u)) {
 
230
        reset_pk_path ();
 
231
        u= resolve_tex (name);
 
232
      }
 
233
    }
 
234
    if (is_none (u)) {
 
235
      save_string (url ("$TEXMACS_HOME_PATH/fonts/error", name), "");
 
236
      return false;
 
237
    }
 
238
  }
 
239
  pk = font_glyphs (tm_new<pk_font_glyphs_rep> (name_pk,
 
240
                                            tm_new<pk_loader> (u, tfm, dpi)));
 
241
  return true;
 
242
}
 
243
 
 
244
bool
 
245
load_tex_pk (string family, int size, int dpi, int dsize,
 
246
             tex_font_metric& tfm, font_glyphs& pk) {
 
247
  if (try_pk (family, size, dpi, dsize, tfm, pk)) return true;
 
248
  if ((dsize != size) && (dsize != 0))
 
249
    if (try_pk (family, dsize, mag (dpi, size, dsize), dsize, tfm, pk))
 
250
      return true;
 
251
  if ((dsize != 10) && (size != 10))
 
252
    if (try_pk (family, 10, mag (dpi, size, 10), dsize, tfm, pk))
 
253
      return true;
 
254
  if (size > 333) {
 
255
    int sz= (size+50)/100;
 
256
    return load_tex_pk (family, sz, mag (dpi, size, sz), dsize, tfm, pk);
 
257
  }
 
258
  return false;
 
259
}
 
260
 
 
261
/******************************************************************************
 
262
* Loading tfm and pk files
 
263
******************************************************************************/
 
264
 
 
265
static void
 
266
rubber_status (glyph& gl, int st) {
 
267
  gl -> status |= st;
 
268
  gl -> yoff    = 0;
 
269
}
 
270
 
 
271
static void
 
272
rubber_fix (tex_font_metric tfm, font_glyphs& pk) {
 
273
  // This routine is used so as to correct the anti-aliasing of
 
274
  // rubber TeX characters (in the vertical direction).
 
275
  register int c;
 
276
  for (c=tfm->bc; c<=tfm->ec; c++) {
 
277
    if (tfm->tag (c)==3) {
 
278
      if (tfm->bot(c)!=0) rubber_status (pk->get (tfm->bot (c)), 1);
 
279
      if (tfm->top(c)!=0) rubber_status (pk->get (tfm->top (c)), 2);
 
280
      if (tfm->mid(c)!=0) rubber_status (pk->get (tfm->mid (c)), 3);
 
281
      if (tfm->rep(c)!=0) rubber_status (pk->get (tfm->rep (c)), 3);
 
282
    }
 
283
  }
 
284
}
 
285
 
 
286
void
 
287
load_tex (string family, int size, int dpi, int dsize,
 
288
          tex_font_metric& tfm, font_glyphs& pk)
 
289
{
 
290
  bench_start ("load tex font");
 
291
  if (DEBUG_VERBOSE)
 
292
    cout << "TeXmacs] loading " << family << size
 
293
         << " at " << dpi << " dpi\n";
 
294
  if (load_tex_tfm (family, size, dsize, tfm) &&
 
295
      load_tex_pk (family, size, dpi, dsize, tfm, pk))
 
296
    {
 
297
      bench_cumul ("load tex font");
 
298
      rubber_fix (tfm, pk);
 
299
      return;
 
300
    }
 
301
  if (DEBUG_VERBOSE) {
 
302
    cout << "TeXmacs] font " << family << size
 
303
         << " at " << dpi << " dpi not found\n";
 
304
    cout << "TeXmacs] loading ecrm" << size
 
305
         << " at " << dpi << " dpi instead\n";
 
306
  }
 
307
  if (load_tex_tfm ("ecrm", size, 10, tfm) &&
 
308
      load_tex_pk ("ecrm", size, dpi, 10, tfm, pk))
 
309
    {
 
310
      bench_cumul ("load tex font");
 
311
      return;
 
312
    }
 
313
#ifdef OS_WIN32
 
314
  else {
 
315
    string name= family * as_string (size) * "@" * as_string (dpi);
 
316
    cerr << "\n\nCould not open font " << name << "\nLoading default" << LF;
 
317
    cout << "Could not load font...\nLoading default" << LF;
 
318
    XNoTexWarn();
 
319
    if (load_tex_tfm ("ecrm", 10, 10, tfm) &&
 
320
        load_tex_pk ("ecrm", 10, 600, 10, tfm, pk))
 
321
      {
 
322
        bench_cumul ("load tex font");
 
323
        return;
 
324
      }
 
325
  }
 
326
#endif
 
327
  string name= family * as_string (size) * "@" * as_string (dpi);
 
328
  cerr << "\n\nI could not open " << name << "\n";
 
329
  FAILED ("Tex seems not to be installed properly");
 
330
  bench_cumul ("load tex font");
 
331
}