]> git.donarmstrong.com Git - lilypond.git/blob - lily/afm.cc
* buildscripts/mf-to-table.py (base): add DesignSize comment.
[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--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include <string.h>
11
12 #include "warn.hh"              // error ()
13 #include "libc-extension.hh"
14 #include "afm.hh"
15 #include "stencil.hh"
16 #include "dimensions.hh"
17
18 Adobe_font_metric::Adobe_font_metric (AFM_Font_info * fi)
19 {
20   checksum_ = 0;
21   font_inf_ = fi;
22
23   design_size_ = 1.0;
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,
46                              unsigned int checksum,
47                              Real design_size)
48 {
49   Adobe_font_metric * fm = new Adobe_font_metric (fi);
50   fm->checksum_ = checksum;
51   fm->design_size_ = design_size;
52   return fm->self_scm ();    
53 }
54
55
56 AFM_CharMetricInfo const *
57 Adobe_font_metric::find_ascii_metric (int a) const
58 {
59   if (ascii_to_metric_idx_[a] >=0)
60     {
61       int code = ascii_to_metric_idx_[a];
62       if (code>=0)
63         {
64           return font_inf_->cmi + code;
65         }
66     }
67
68   return 0;
69 }
70
71
72
73 AFM_CharMetricInfo const *
74 Adobe_font_metric::find_char_metric (String nm) const
75 {
76   int idx = name_to_index (nm);
77   if (idx >= 0)
78     return font_inf_->cmi+ idx;
79   else
80     return 0;
81 }
82
83 int
84 Adobe_font_metric::name_to_index (String nm)const 
85 {
86   std::map<String,int>::const_iterator ai = name_to_metric_dict_.find (nm);
87   
88   if (ai == name_to_metric_dict_.end ())
89     return -1;
90   else
91     return (*ai).second; 
92 }
93
94 int
95 Adobe_font_metric::count () const
96 {
97   return font_inf_->numOfChars ;
98 }
99
100 Box
101 Adobe_font_metric::get_ascii_char (int code) const
102 {
103   AFM_CharMetricInfo const
104     * c =  find_ascii_metric (code);
105   Box b (Interval (0,0),Interval (0,0));
106   if (c)
107     b = afm_bbox_to_box (c->charBBox);                  
108
109   return b;
110 }
111
112
113 Box
114 Adobe_font_metric::get_indexed_char (int code) const
115 {
116   if (code>= 0)
117     return afm_bbox_to_box (font_inf_->cmi[code].charBBox);
118   else
119     return   Box (Interval (0,0),Interval (0,0));
120 }
121
122 SCM
123 read_afm_file (String nm)
124 {
125   FILE *f = fopen (nm.to_str0 () , "r");
126   char s[2048] = "";
127   char *check_key = "Comment TfmCheckSum";
128   char *size_key = "Comment DesignSize";
129
130   unsigned int cs = 0;
131   Real ds = 1.0;
132   
133   /* Assume check_key in first 10 lines */
134   for (int i = 0; i < 10; i++)
135     {
136       fgets (s, sizeof (s), f);
137       if (strncmp (s, check_key, strlen (check_key)) == 0)
138         {
139           sscanf (s + strlen (check_key), "%ud", &cs);
140         }
141       else if (strncmp (s, size_key, strlen (size_key)) == 0)
142         {
143           sscanf (s + strlen (size_key), "%lf", &ds);
144         }
145     }
146   
147   rewind (f);
148     
149   AFM_Font_info * fi;
150   int ok = AFM_parseFile (f, &fi, ~1);
151
152   if (ok)
153     {
154       error (_f ("Error parsing AFM file: `%s'", nm.to_str0 ()));
155       exit (2);
156     }
157   fclose (f);
158
159   return Adobe_font_metric::make_afm (fi, cs, ds);
160 }
161
162
163 /*
164   actually, AFMs will be printers point, usually, but our .py script dumps
165   real points.
166  */
167 Box
168 afm_bbox_to_box (AFM_BBox bb)
169 {
170   return Box (Interval (bb.llx, bb.urx)* (1/1000.0) PT,
171               Interval (bb.lly, bb.ury)* (1/1000.0) PT);
172
173 }
174
175 Offset
176 Adobe_font_metric::get_indexed_wxwy (int k)const
177 {
178   AFM_CharMetricInfo const *mi = font_inf_->cmi+ k;
179   return 1/1000.0 PT * Offset (mi->wx, mi->wy); 
180 }
181
182
183
184 Adobe_font_metric::~Adobe_font_metric ()
185 {
186   AFM_free (font_inf_);
187 }
188
189 /*
190   return a stencil, without fontification 
191  */
192 Stencil
193 Adobe_font_metric::find_by_name (String s) const
194 {
195   AFM_CharMetricInfo const *cm = find_char_metric (s);
196
197   if (!cm)
198     {
199       /*
200         Why don't we return empty?
201        */
202       
203       Stencil m;
204       m.set_empty (false);
205       return m;
206     }
207   
208   SCM at = (scm_list_n (ly_symbol2scm ("char"),
209                       scm_int2num (cm->code),
210                       SCM_UNDEFINED));
211   
212   //  at= fontify_atom ((Font_metric*)this, at);
213   Box b = afm_bbox_to_box (cm->charBBox);
214
215   return Stencil (b, at);
216 }