1 
2 /******************************************************************************
3 * MODULE     : font.cpp
4 * DESCRIPTION: fonts
5 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11 
12 #include "font.hpp"
13 #include "gui.hpp"
14 #include "Freetype/tt_file.hpp"
15 #include "iterator.hpp"
16 #include "file.hpp"
17 #include "convert.hpp"
18 
19 RESOURCE_CODE(font);
20 
21 /******************************************************************************
22 * Constructors for fonts
23 ******************************************************************************/
24 
font_rep(string s)25 font_rep::font_rep (string s):
26   rep<font> (s),
27   type      (FONT_TYPE_TEX),
28   spc       (0),
29   extra     (0),
30   last_zoom (0.0),
31   zoomed_fn (NULL),
32   protrusion_maps (-1)
33 {
34 }
35 
font_rep(string s,font fn)36 font_rep::font_rep (string s, font fn):
37   rep<font>    (s),
38   type         (fn->type),
39   size         (fn->size),
40   design_size  (fn->design_size),
41   display_size (fn->display_size),
42   slope        (fn->slope),
43   spc          (fn->spc),
44   extra        (fn->extra),
45   sep          (fn->sep),
46   last_zoom    (0.0),
47   zoomed_fn    (NULL),
48   protrusion_maps (-1)
49 {
50   copy_math_pars (fn);
51 }
52 
53 void
copy_math_pars(font fn)54 font_rep::copy_math_pars (font fn) {
55   y1           = fn->y1;
56   y2           = fn->y2;
57   yx           = fn->yx;
58   yfrac        = fn->yfrac;
59   ysub_lo_base = fn->ysub_lo_base;
60   ysub_hi_lim  = fn->ysub_hi_lim;
61   ysup_lo_lim  = fn->ysup_lo_lim;
62   ysup_lo_base = fn->ysup_lo_base;
63   ysup_hi_lim  = fn->ysup_hi_lim;
64   yshift       = fn->yshift;
65   wpt          = fn->wpt;
66   wfn          = fn->wfn;
67   wline        = fn->wline;
68   wquad        = fn->wquad;
69 }
70 
71 void
draw(renderer ren,string s,SI x,SI y,SI xk,bool ext)72 font_rep::draw (renderer ren, string s, SI x, SI y, SI xk, bool ext) {
73   if (ren->zoomf == 1.0 || !ren->is_screen) {
74     if (ext) draw_fixed (ren, s, x, y, xk);
75     else draw_fixed (ren, s, x, y);
76   }
77   else if (ren->zoomf != last_zoom) {
78     last_zoom= ren->zoomf;
79     zoomed_fn= magnify (ren->zoomf);
80     draw (ren, s, x, y, xk, ext);
81   }
82   else {
83     // FIXME: low level rendering hack
84     SI     old_ox     = ren->ox;
85     SI     old_oy     = ren->oy;
86     SI     old_cx1    = ren->cx1;
87     SI     old_cy1    = ren->cy1;
88     SI     old_cx2    = ren->cx2;
89     SI     old_cy2    = ren->cy2;
90     double old_zoomf  = ren->zoomf;
91     int    old_shrinkf= ren->shrinkf;
92     SI     old_pixel  = ren->pixel;
93     SI     old_thicken= ren->thicken;
94 
95     ren->ox     = (SI) tm_round (old_ox  * old_zoomf);
96     ren->oy     = (SI) tm_round (old_oy  * old_zoomf);
97     //ren->cx1    = (SI) ::floor (old_cx1 * old_zoomf);
98     //ren->cx2    = (SI) ::floor (old_cx2 * old_zoomf);
99     //ren->cy1    = (SI) ::ceil  (old_cy1 * old_zoomf);
100     //ren->cy2    = (SI) ::ceil  (old_cy2 * old_zoomf);
101     ren->cx1    = (SI) tm_round (old_cx1 * old_zoomf);
102     ren->cx2    = (SI) tm_round (old_cx2 * old_zoomf);
103     ren->cy1    = (SI) tm_round (old_cy1 * old_zoomf);
104     ren->cy2    = (SI) tm_round (old_cy2 * old_zoomf);
105     ren->zoomf  = 1.0;
106     ren->shrinkf= std_shrinkf;
107     ren->brushpx= ren->pixel;
108     ren->pixel  = std_shrinkf * PIXEL;
109     ren->thicken= (std_shrinkf >> 1) * PIXEL;
110 
111     SI xx= (SI) tm_round (x * old_zoomf);
112     SI yy= (SI) tm_round (y * old_zoomf);
113     if (ext) {
114       SI kk= (SI) tm_round (xk * old_zoomf);
115       zoomed_fn->draw_fixed (ren, s, xx, yy, kk);
116     }
117     else zoomed_fn->draw_fixed (ren, s, xx, yy);
118 
119     ren->ox     = old_ox;
120     ren->oy     = old_oy;
121     ren->cx1    = old_cx1;
122     ren->cx2    = old_cx2;
123     ren->cy1    = old_cy1;
124     ren->cy2    = old_cy2;
125     ren->zoomf  = old_zoomf;
126     ren->shrinkf= old_shrinkf;
127     ren->brushpx= -1;
128     ren->pixel  = old_pixel;
129     ren->thicken= old_thicken;
130   }
131 }
132 
133 void
draw(renderer ren,string s,SI x,SI y)134 font_rep::draw (renderer ren, string s, SI x, SI y) {
135   draw (ren, s, x, y, 0, false);
136 }
137 
138 void
draw(renderer ren,string s,SI x,SI y,SI xk)139 font_rep::draw (renderer ren, string s, SI x, SI y, SI xk) {
140   draw (ren, s, x, y, xk, true);
141 }
142 
143 void
draw_fixed(renderer ren,string s,SI x,SI y,bool ligf)144 font_rep::draw_fixed (renderer ren, string s, SI x, SI y, bool ligf) {
145   (void) ligf;
146   draw_fixed (ren, s, x, y);
147 }
148 
149 void
draw_fixed(renderer ren,string s,SI x,SI y,SI xk)150 font_rep::draw_fixed (renderer ren, string s, SI x, SI y, SI xk) {
151   STACK_NEW_ARRAY (xpos, SI, N(s)+1);
152   get_xpositions (s, xpos, xk);
153   int i= 0;
154   while (i<N(s)) {
155     int old= i;
156     tm_char_forwards (s, i);
157     draw_fixed (ren, s (old, i), x + xpos[old], y, false);
158   }
159   STACK_DELETE_ARRAY (xpos);
160 }
161 
get_left_slope(string s)162 double font_rep::get_left_slope  (string s) { (void) s; return slope; }
get_right_slope(string s)163 double font_rep::get_right_slope (string s) { (void) s; return slope; }
get_left_correction(string s)164 SI     font_rep::get_left_correction  (string s) { (void) s; return 0; }
get_right_correction(string s)165 SI     font_rep::get_right_correction (string s) { (void) s; return 0; }
166 
167 void
get_extents(string s,metric & ex,bool ligf)168 font_rep::get_extents (string s, metric& ex, bool ligf) {
169   if (ligf) get_extents (s, ex);
170   else get_extents (s, ex, 0);
171 }
172 
173 void
get_extents(string s,metric & ex,SI xk)174 font_rep::get_extents (string s, metric& ex, SI xk) {
175   get_extents (s, ex);
176   STACK_NEW_ARRAY (xpos, SI, N(s)+1);
177   get_xpositions (s, xpos, xk);
178   SI d= xpos[N(s)] - ex->x2;
179   ex->x2 += d;
180   ex->x4 += d - xk;
181   STACK_DELETE_ARRAY (xpos);
182 }
183 
184 void
get_xpositions(string s,SI * xpos)185 font_rep::get_xpositions (string s, SI* xpos) {
186   int i= 0;
187   SI  x= 0;
188   metric ex;
189   while (i < N(s)) {
190     if (s[i] == '<')
191       while ((i < N(s)) && (s[i] != '>')) {
192 	i++;
193 	xpos[i]= x;
194       }
195     i++;
196     get_extents (s (0, i), ex);
197     x= ex->x2;
198     xpos[i]= x;
199   }
200 }
201 
202 void
get_xpositions(string s,SI * xpos,bool ligf)203 font_rep::get_xpositions (string s, SI* xpos, bool ligf) {
204   (void) ligf;
205   get_xpositions (s, xpos);
206 }
207 
208 void
get_xpositions(string s,SI * xpos,SI xk)209 font_rep::get_xpositions (string s, SI* xpos, SI xk) {
210   get_xpositions (s, xpos, false);
211   int n= tm_string_length (s);
212   if (n == 0) return;
213   int i= 0, count= 0;
214   xpos[0]= xk;
215   while (i < N(s)) {
216     SI dx= (2*count + 1) * xk;
217     if (s[i] == '<')
218       while ((i < N(s)) && (s[i] != '>')) {
219 	i++;
220 	xpos[i] += dx;
221       }
222     i++;
223     count++;
224     if (i == N(s)) dx= 2 * count * xk;
225     else dx= (2*count + 1) * xk;
226     xpos[i] += dx;
227   }
228 }
229 
230 void
var_get_extents(string s,metric & ex)231 font_rep::var_get_extents (string s, metric& ex) {
232   bool flag=true;
233   int start=0, end;
234   get_extents ("", ex);
235   while (start<N(s)) {
236     for (end=start; (end<N(s)) && (s[end]!=' '); end++) {}
237     if (start<end) {
238       metric ey;
239       get_extents (s (start, end), ey);
240       if (flag) {
241 	ex->x3= ey->x3+ ex->x2; ex->y3= ey->y3+ ex->x2;
242 	ex->x4= ey->x4; ex->y4= ey->y4;
243 	ex->x2 += ey->x2;
244 	flag= false;
245       }
246       else {
247 	ex->x3= min (ex->x3, ex->x2+ ey->x3);
248 	ex->x4= max (ex->x4, ex->x2+ ey->x4);
249 	ex->y3= min (ex->y3, ey->y3);
250 	ex->y4= max (ex->y4, ey->y4);
251 	ex->x2 += ey->x2;
252       }
253     }
254     for (; (end<N(s)) && (s[end]==' '); end++) ex->x2 += spc->def;
255     start= end;
256   }
257 }
258 
259 void
var_get_xpositions(string s,SI * xpos)260 font_rep::var_get_xpositions (string s, SI* xpos) {
261   (void) s; (void) xpos;
262   FAILED ("not yet implemented");
263 }
264 
265 void
var_draw(renderer ren,string s,SI x,SI y)266 font_rep::var_draw (renderer ren, string s, SI x, SI y) {
267   SI dx=0;
268   int start=0, end;
269   while (start<N(s)) {
270     for (end=start; (end<N(s)) && (s[end]!=' '); end++) {}
271     if (start<end) {
272       metric ex;
273       draw (ren, s (start, end), x+dx, y);
274       get_extents (s (start, end), ex);
275       dx += ex->x2;
276     }
277     for (; (end<N(s)) && (s[end]==' '); end++) dx += spc->def;
278     start= end;
279   }
280 }
281 
282 //bool get_glyph_fatal= true;
283 bool get_glyph_fatal= false;
284 
285 glyph
get_glyph(string s)286 font_rep::get_glyph (string s) {
287   if (get_glyph_fatal) {
288     failed_error << "glyph name: " << s << "\n";
289     FAILED ("no bitmap available");
290   }
291   else cout << "  no bitmap available for " << s << "\n";
292   return glyph (0, 0, 0, 0);
293 }
294 
295 /******************************************************************************
296 * Error font: used to draw unindentified characters
297 ******************************************************************************/
298 
299 struct error_font_rep: font_rep {
300   font fn;
301   error_font_rep (string name, font fn);
302   bool supports (string c);
303   void get_extents (string s, metric& ex);
304   void get_xpositions (string s, SI* xpos);
305   void draw_fixed (renderer ren, string s, SI x, SI y);
306   font magnify (double zoom);
307 };
308 
error_font_rep(string name,font fnb)309 error_font_rep::error_font_rep (string name, font fnb):
310   font_rep (name, fnb), fn (fnb) {}
311 
312 bool
supports(string c)313 error_font_rep::supports (string c) {
314   return true;
315 }
316 
317 void
get_extents(string s,metric & ex)318 error_font_rep::get_extents (string s, metric& ex) {
319   fn->get_extents (s, ex);
320 }
321 
322 void
get_xpositions(string s,SI * xpos)323 error_font_rep::get_xpositions (string s, SI* xpos) {
324   fn->get_xpositions (s, xpos);
325 }
326 
327 void
draw_fixed(renderer ren,string s,SI x,SI y)328 error_font_rep::draw_fixed (renderer ren, string s, SI x, SI y) {
329   ren->set_pencil (red);
330   fn->draw_fixed (ren, s, x, y);
331 }
332 
333 font
magnify(double zoom)334 error_font_rep::magnify (double zoom) {
335   return error_font (fn->magnify (zoom));
336 }
337 
338 font
error_font(font fn)339 error_font (font fn) {
340   string name= "error-" * fn->res_name;
341   return make (font, name, tm_new<error_font_rep> (name, fn));
342 }
343 
344 /******************************************************************************
345 * System dependent fonts
346 ******************************************************************************/
347 
348 #ifndef X11TEXMACS
349 
350 font
x_font(string family,int size,int dpi)351 x_font (string family, int size, int dpi) {
352   (void) family; (void) size; (void) dpi;
353   return font ();
354 }
355 
356 #endif
357 
358 #ifndef QTTEXMACS
359 
360 font
qt_font(string family,int size,int dpi)361 qt_font (string family, int size, int dpi) {
362   (void) family; (void) size; (void) dpi;
363   return font ();
364 }
365 
366 #endif
367 
368 /******************************************************************************
369 * Miscellaneous
370 ******************************************************************************/
371 
372 static hashmap<string,font> larger_font_table;
373 
374 static font
make_rubber_font(font fn)375 make_rubber_font (font fn) {
376   if (starts (fn->res_name, "stix-"))
377     return rubber_stix_font (fn);
378   else if (fn->type == FONT_TYPE_UNICODE)
379     return rubber_unicode_font (fn);
380   else
381     return fn;
382 }
383 
384 font
rubber_font(font base)385 rubber_font (font base) {
386   if (larger_font_table->contains (base->res_name))
387     return larger_font_table (base->res_name);
388   font larger= make_rubber_font (base);
389   larger_font_table (base->res_name)= larger;
390   return larger;
391 }
392 
393 int
script(int sz,int level)394 script (int sz, int level) {
395   int i;
396   if (level<0) level=0;
397   if (level>2) level=2;
398   for (i=0; i<level; i++) sz= (sz*2+2)/3;
399   return sz;
400 }
401 
402 string
default_chinese_font_name()403 default_chinese_font_name () {
404   if (tt_font_exists ("FandolSong-Regular")) return "FandolSong";
405   if (tt_font_exists ("simsun")) return "simsun";
406   if (tt_font_exists ("fireflysung")) return "fireflysung";
407   if (tt_font_exists ("uming")) return "uming";
408   if (tt_font_exists ("儷黑 Pro")) return "lihei";
409   if (tt_font_exists ("华文细黑")) return "heiti";
410   if (tt_font_exists ("SimSun")) return "apple-simsun";
411   return "roman";
412 }
413 
414 string
default_japanese_font_name()415 default_japanese_font_name () {
416   if (tt_font_exists ("ipam")) return (new_fonts? "IPAMincho": "modern");
417   if (tt_font_exists ("sazanami")) return "sazanami";
418   if (tt_font_exists ("ttf-japanese-gothic")) return "ttf-japanese";
419   if (tt_font_exists ("ヒラギノ明朝 ProN W6")) return "kaku";
420   if (tt_font_exists ("MS PGothic")) return "ms-gothic";
421   if (tt_font_exists ("MS PMincho")) return "ms-mincho";
422   return "roman";
423 }
424 
425 string
default_korean_font_name()426 default_korean_font_name () {
427   if (tt_font_exists ("unbatang")) return (new_fonts? "UnBatang": "modern");
428   if (tt_font_exists ("UnBatang")) return (new_fonts? "UnBatang": "modern");
429   if (tt_font_exists ("AppleGothic")) return "apple-gothic";
430   if (tt_font_exists ("Gulim")) return "gulim";
431   return "roman";
432 }
433