1 /* fontmap.c */
2
3 /************************************************************************
4
5 Part of the dvipng distribution
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation, either version 3 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this program. If not, see
19 <http://www.gnu.org/licenses/>.
20
21 Copyright (C) 2002-2015 Jan-�ke Larsson
22
23 ************************************************************************/
24
25 #include "dvipng.h"
26
27 static struct filemmap psfont_mmap;
28 #ifdef HAVE_FT2
29 static struct filemmap ttfont_mmap;
30 #endif
31 static struct psfontmap *psfontmap=NULL;
32
newword(char ** buffer,char * end)33 static char* newword(char** buffer, char* end)
34 {
35 char *word,*pos=*buffer;
36
37 while(pos<end && *pos!=' ' && *pos!='\t' && *pos!='"') pos++;
38 if ((word=malloc(pos-*buffer+1))==NULL)
39 Fatal("cannot malloc space for string");
40 strncpy(word,*buffer,pos-*buffer);
41 word[pos-*buffer]='\0';
42 *buffer=pos;
43 return(word);
44 }
45
copyword(char * orig)46 char* copyword(char* orig)
47 {
48 char *word;
49
50 if (orig==NULL)
51 return(NULL);
52 if ((word=malloc(strlen(orig)+1))==NULL)
53 Fatal("cannot malloc space for string");
54 strcpy(word,orig);
55 return(word);
56 }
57
find_format(const char * name)58 static char* find_format(const char* name)
59 {
60 /* Cater for both new (first case) and old (second case) kpathsea */
61 char* format =
62 kpse_find_file(name,kpse_fontmap_format,false);
63
64 if (format==NULL)
65 format = kpse_find_file(name,kpse_dvips_config_format,false);
66 return(format);
67 }
68
InitPSFontMap(void)69 void InitPSFontMap(void)
70 {
71 char* psfont_name=NULL;
72 /* Prefer ps2pk.map, fonts are present more often */
73 psfont_name=find_format("ps2pk.map");
74 if (psfont_name==NULL)
75 psfont_name=find_format("psfonts.map");
76 if (psfont_name==NULL) {
77 Warning("cannot find ps2pk.map, nor psfonts.map");
78 } else {
79 DEBUG_PRINT(DEBUG_FT,
80 ("\n OPEN PSFONT MAP:\t'%s'", psfont_name));
81 if (MmapFile(psfont_name,&psfont_mmap)) {
82 Warning("psfonts map %s could not be opened", psfont_name);
83 }
84 free(psfont_name);
85 }
86 #ifdef HAVE_FT2
87 psfont_name=find_format("ttfonts.map");
88 if (psfont_name!=NULL) {
89 DEBUG_PRINT(DEBUG_FT,("\n OPEN TTFONT MAP:\t'%s'", psfont_name));
90 if (MmapFile(psfont_name,&ttfont_mmap)) {
91 Warning("ttfonts map %s could not be opened", psfont_name);
92 }
93 free(psfont_name);
94 }
95 #endif
96 }
97
NewPSFont(struct psfontmap * copyfrom)98 struct psfontmap *NewPSFont(struct psfontmap* copyfrom)
99 {
100 struct psfontmap *newentry=NULL;
101 if ((newentry=malloc(sizeof(struct psfontmap)))==NULL)
102 Fatal("cannot malloc psfontmap space");
103 if (copyfrom!=NULL) {
104 newentry->line = copyfrom->line;
105 newentry->tfmname = copyword(copyfrom->tfmname);
106 newentry->psfile = copyword(copyfrom->psfile);
107 newentry->encname = copyword(copyfrom->encname);
108 newentry->encoding = copyfrom->encoding;
109 #ifdef HAVE_FT2
110 newentry->ft_transformp = copyfrom->ft_transformp;
111 newentry->subfont = copyfrom->subfont;
112 #endif
113 newentry->end = copyfrom->end;
114 } else {
115 newentry->line = NULL;
116 newentry->tfmname = NULL;
117 newentry->psfile = NULL;
118 newentry->encname = NULL;
119 newentry->encoding = NULL;
120 #ifdef HAVE_FT2
121 newentry->ft_transformp = NULL;
122 newentry->subfont = NULL;
123 #endif
124 newentry->end = NULL;
125 }
126 newentry->next=psfontmap;
127 psfontmap=newentry;
128 return(newentry);
129 }
130
SearchPSFontMap(char * fontname,struct filemmap * search_mmap)131 static struct psfontmap *SearchPSFontMap(char* fontname,
132 struct filemmap* search_mmap)
133 {
134 static char *pos=NULL,*end=NULL;
135 static struct filemmap* searching_mmap=NULL;
136 struct psfontmap *entry=NULL;
137
138 if (pos==end && search_mmap!=searching_mmap) {
139 searching_mmap=search_mmap;
140 pos=searching_mmap->data;
141 end=searching_mmap->data+searching_mmap->size;
142 }
143 while(pos<end && (entry==NULL || strcmp(entry->tfmname,fontname)!=0)) {
144 while(pos < end
145 && (*pos=='\r' || *pos=='\n' || *pos==' ' || *pos=='\t'
146 || *pos=='%' || *pos=='*' || *pos==';' || *pos=='#')) {
147 while(pos < end && *pos!='\r' && *pos!='\n') pos++; /* skip comments/empty rows */
148 pos++;
149 }
150 if (pos < end) {
151 entry=NewPSFont(NULL);
152 entry->line = pos;
153 /* skip <something and quoted entries */
154 while(pos < end && (*pos=='<' || *pos=='"')) {
155 if (*pos=='<')
156 while(pos < end && *pos!=' ' && *pos!='\t') pos++;
157 else
158 while(pos < end && *pos!='"') pos++;
159 while(pos < end && (*pos==' ' || *pos=='\t')) pos++;
160 }
161 /* first word is font name */
162 entry->tfmname = newword(&pos,end);
163 while(pos < end && *pos!='\r' && *pos!='\n') pos++;
164 entry->end = pos;
165 }
166 pos++;
167 }
168 if (entry!=NULL && strcmp(entry->tfmname,fontname)!=0)
169 entry=NULL;
170 return(entry);
171 }
172
ClearPSFontMap(void)173 void ClearPSFontMap(void)
174 {
175 struct psfontmap *entry;
176
177 while(psfontmap!=NULL) {
178 entry=psfontmap;
179 psfontmap=psfontmap->next;
180 free(entry->tfmname);
181 if (entry->psfile!=NULL)
182 free(entry->psfile);
183 if (entry->encname!=NULL)
184 free(entry->encname);
185 free(entry);
186 }
187 UnMmapFile(&psfont_mmap);
188 #ifdef HAVE_FT2
189 UnMmapFile(&ttfont_mmap);
190 #endif
191 }
192
ReadPSFontMap(struct psfontmap * entry)193 static void ReadPSFontMap(struct psfontmap *entry)
194 {
195 char *pos,*end,*psname;
196 int nameno = 0;
197
198 DEBUG_PRINT(DEBUG_FT,("\n PSFONTMAP: %s ",entry->tfmname));
199 pos=entry->line;
200 end=entry->end;
201 while(pos < end) {
202 if (*pos=='<') { /* filename follows */
203 pos++;
204 if (pos<end && *pos=='<') { /* <<download.font */
205 pos++;
206 entry->psfile = newword((char**)&pos,end);
207 DEBUG_PRINT(DEBUG_FT,("<%s ",entry->psfile));
208 } else if (pos<end && *pos=='[') { /* <[encoding.file */
209 pos++;
210 entry->encname = newword((char**)&pos,end);
211 DEBUG_PRINT(DEBUG_FT,("<[%s ",entry->encname));
212 } else { /* <some.file */
213 char* word =newword((char**)&pos,end);
214 if (strncmp(word+strlen(word)-4,".enc",4)==0) {/* <some.enc */
215 entry->encname=word;
216 DEBUG_PRINT(DEBUG_FT,("<[%s ",entry->encname));
217 } else { /* <font */
218 entry->psfile=word;
219 DEBUG_PRINT(DEBUG_FT,("<%s ",entry->psfile));
220 }
221 }
222 } else if (*pos=='"') { /* PS code: reencoding/tranformation exists */
223 char *word;
224 double cxx=1.0,cxy=0.0;
225 pos++;
226 DEBUG_PRINT(DEBUG_FT,("\""));
227 while(pos < end && *pos!='"') {
228 word=newword((char**)&pos,end);
229 while(pos < end && (*pos==' ' || *pos=='\t')) pos++;
230 if (pos+10<end && strncmp(pos,"ExtendFont",10)==0) {
231 cxx=strtod(word,NULL);
232 pos+=10;
233 DEBUG_PRINT(DEBUG_FT,("%f ExtendFont ",cxx));
234 } else if (pos+9<end && strncmp(pos,"SlantFont",9)==0) {
235 pos+=9;
236 cxy=strtod(word,NULL);
237 DEBUG_PRINT(DEBUG_FT,("%f SlantFont ",cxy));
238 } else if (pos+12<end && strncmp(pos,"ReEncodeFont",12)==0) {
239 pos+=12;
240 DEBUG_PRINT(DEBUG_FT,("%s ReEncodeFont ",word));
241 } else {
242 DEBUG_PRINT(DEBUG_FT,("(?:%s) ",word));
243 }
244 free(word);
245 }
246 #ifdef HAVE_FT2
247 entry->ft_transformp=&(entry->ft_transform);
248 entry->ft_transform.xx=(FT_Fixed)(cxx*0x10000);
249 entry->ft_transform.xy=(FT_Fixed)(cxy*0x10000);
250 entry->ft_transform.yx=0;
251 entry->ft_transform.yy=0x10000;
252 #endif
253 DEBUG_PRINT(DEBUG_FT,("\" "));
254 pos++;
255 } else { /* bare word */
256 switch (++nameno) {
257 case 1: /* first word is tfmname and perhaps psname, NOT psfile */
258 while(pos<end && *pos!=' ' && *pos!='\t') pos++;
259 psname=entry->tfmname;
260 break;
261 case 2: /* second word is psname, NOT psfile */
262 psname = newword((char**)&pos,end);
263 DEBUG_PRINT(DEBUG_FT,("(%s) ",psname));
264 free(psname);
265 break;
266 case 3: /* third word is encoding */
267 entry->encname = newword((char**)&pos,end);
268 DEBUG_PRINT(DEBUG_FT,("<[%s ",entry->encname));
269 break;
270 default:
271 while(pos<end && *pos!=' ' && *pos!='\t') pos++;
272 Warning("more than three bare words in font map entry");
273 }
274 }
275 while(pos < end && (*pos==' ' || *pos=='\t')) pos++;
276 }
277 if (entry->psfile==NULL) {
278 /* No psfile-name given, use tfmname */
279 entry->psfile=copyword(entry->tfmname);
280 DEBUG_PRINT(DEBUG_FT,(" <%s ",entry->psfile));
281 }
282 if (entry->encname!=NULL
283 && (entry->encoding=FindEncoding(entry->encname))==NULL)
284 Warning("unable to load font encoding '%s' for %s",
285 entry->encname,entry->tfmname);
286 }
287
288
FindPSFontMap(char * fontname)289 struct psfontmap* FindPSFontMap(char* fontname)
290 {
291 struct psfontmap *entry;
292 static struct filemmap* search_mmap_p=&psfont_mmap;
293
294 entry=psfontmap;
295 while(entry!=NULL && strcmp(entry->tfmname,fontname)!=0)
296 entry=entry->next;
297 if(entry==NULL) {
298 entry=SearchPSFontMap(fontname,search_mmap_p);
299 #ifdef HAVE_FT2
300 if(entry==NULL && search_mmap_p!=&ttfont_mmap) {
301 search_mmap_p=&ttfont_mmap;
302 entry=SearchPSFontMap(fontname,search_mmap_p);
303 }
304 }
305 if(entry==NULL) {
306 struct psfontmap* entry_subfont=NULL;
307 entry=psfontmap;
308 while(entry!=NULL && strcmp(entry->tfmname,fontname)!=0) {
309 while(entry!=NULL && strchr(entry->tfmname,'@')==NULL)
310 entry=entry->next;
311 if (entry!=NULL) {
312 entry_subfont=FindSubFont(entry,fontname);
313 if (entry_subfont!=NULL)
314 entry=entry_subfont;
315 else
316 entry=entry->next;
317 }
318 }
319 #endif
320 }
321 if (entry!=NULL && entry->psfile==NULL)
322 ReadPSFontMap(entry);
323 if (entry!=NULL && entry->encname!=NULL && entry->encoding==NULL)
324 /* Encoding given but it cannot be found. Unusable font */
325 return(NULL);
326 return(entry);
327 }
328