]> git.donarmstrong.com Git - lilypond.git/blob - lily/afm.cc
*** empty log message ***
[lilypond.git] / lily / afm.cc
1 /*   
2   afm.cc --  implement Adobe_font_metric
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 2000--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #ifndef _GNU_SOURCE // we want memmem
11 #define _GNU_SOURCE
12 #endif
13 #include <string.h>
14 #include "libc-extension.hh"
15 #include "afm.hh"
16 #include "warn.hh"
17 #include "molecule.hh"
18 #include "dimensions.hh"
19
20 Adobe_font_metric::Adobe_font_metric (AFM_Font_info * fi)
21 {
22   checksum_ = 0;
23   font_inf_ = fi;
24
25   for (int i= 256  >? fi->numOfChars; i--;)
26     ascii_to_metric_idx_.push (-1);
27   
28   for (int i=0; i < fi->numOfChars; i++)
29     {
30       AFM_CharMetricInfo * c = fi->cmi + i;
31
32       /*
33         Some TeX afm files contain code = -1. We don't know why, let's
34         ignore it.
35         
36        */
37       if (c->code >= 0)
38         ascii_to_metric_idx_[c->code] = i;
39       name_to_metric_dict_[c->name] = i;
40     }
41 }
42
43
44 SCM
45 Adobe_font_metric::make_afm (AFM_Font_info *fi, unsigned int checksum)
46 {
47   Adobe_font_metric * fm = new Adobe_font_metric (fi);
48   fm->checksum_ = checksum;
49   return fm->self_scm ();    
50 }
51
52
53 AFM_CharMetricInfo const *
54 Adobe_font_metric::find_ascii_metric (int a , bool warn) const
55 {
56   if (ascii_to_metric_idx_[a] >=0)
57     {
58       int code = ascii_to_metric_idx_[a];
59       if (code>=0)
60         {
61           return font_inf_->cmi + code;
62         }
63     }
64   else if (warn)
65     {
66       warning (_f ("can't find character number: %d", a));
67     }
68
69   return 0;
70 }
71
72 AFM_CharMetricInfo const *
73 Adobe_font_metric::find_char_metric (String nm, bool warn) const
74 {
75   std::map<String,int>::const_iterator ai = name_to_metric_dict_.find (nm);
76   
77   if (ai == name_to_metric_dict_.end ())
78     {
79       if (warn)
80         {
81           warning (_f ("can't find character called: `%s'", nm.to_str0 ()));
82         }
83       return 0;
84     }
85   else
86     return font_inf_->cmi + (*ai).second;
87 }
88
89 int
90 Adobe_font_metric::count () const
91 {
92   return font_inf_->numOfChars ;
93 }
94
95 Box
96 Adobe_font_metric::get_char (int code) const
97 {
98   AFM_CharMetricInfo const
99     * c =  find_ascii_metric (code,false);
100   Box b (Interval (0,0),Interval (0,0));
101   if (c)
102     b = afm_bbox_to_box (c->charBBox);                  
103
104   return b;
105 }
106
107 SCM
108 read_afm_file (String nm)
109 {
110   FILE *f = fopen (nm.to_str0 () , "r");
111   char s[2048];
112   char *check_key = "Comment TfmCheckSum";
113
114   unsigned int cs = 0;
115
116 #if 0
117   fread (s, sizeof (s), sizeof (*s), f);
118   if (char const* p = (char const *)
119       memmem (s, sizeof (s), check_key, strlen (check_key)))
120     sscanf (p + strlen (check_key), "%ud", &cs);
121 #else
122   s[0] = 0;
123   /* Assume check_key in first 10 lines */
124   for (int i = 0; i < 10; i++)
125     {
126       fgets (s, sizeof (s), f);
127       if (strncmp (s, check_key, strlen (check_key)) == 0)
128         {
129           sscanf (s + strlen (check_key), "%ud", &cs);
130           break;
131         }
132     }
133 #endif
134   
135   rewind (f);
136     
137   AFM_Font_info * fi;
138   int ok = AFM_parseFile (f, &fi, ~1);
139
140   if (ok)
141     {
142       error (_f ("Error parsing AFM file: `%s'", nm.to_str0 ()));
143       exit (2);
144     }
145   fclose (f);
146
147   return Adobe_font_metric::make_afm (fi, cs);
148 }
149
150
151 /*
152   actually, AFMs will be printers point, usually, but our .py script dumps
153   real points.
154  */
155 Box
156 afm_bbox_to_box (AFM_BBox bb)
157 {
158   return Box (Interval (bb.llx, bb.urx)* (1/1000.0) PT,
159               Interval (bb.lly, bb.ury)* (1/1000.0) PT);
160
161 }
162   
163
164 Adobe_font_metric::~Adobe_font_metric ()
165 {
166   AFM_free (font_inf_);
167 }
168
169 /*
170   return a molecule, without fontification 
171  */
172 Molecule
173 Adobe_font_metric::find_by_name (String s) const
174 {
175   AFM_CharMetricInfo const *cm = find_char_metric (s, false);
176
177   if (!cm)
178     {
179       /*
180         Why don't we return empty?
181        */
182       
183       Molecule m;
184       m.set_empty (false);
185       return m;
186     }
187   
188   SCM at = (scm_list_n (ly_symbol2scm ("char"),
189                       scm_int2num (cm->code),
190                       SCM_UNDEFINED));
191   
192   //  at= fontify_atom ((Font_metric*)this, at);
193   Box b = afm_bbox_to_box (cm->charBBox);
194
195   return Molecule (b, at);
196 }