File: | backend/dvi/mdvi-lib/font.c |
Warning: | line 214, column 6 Using a fixed address is not portable because that address will probably not be valid in all environments or platforms |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (C) 2000, Matias Atria | |||
3 | * | |||
4 | * This program is free software; you can redistribute it and/or modify | |||
5 | * it under the terms of the GNU General Public License as published by | |||
6 | * the Free Software Foundation; either version 2 of the License, or | |||
7 | * (at your option) any later version. | |||
8 | * | |||
9 | * This program is distributed in the hope that it will be useful, | |||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
12 | * GNU General Public License for more details. | |||
13 | * | |||
14 | * You should have received a copy of the GNU General Public License | |||
15 | * along with this program; if not, write to the Free Software | |||
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
17 | */ | |||
18 | ||||
19 | #include <config.h> | |||
20 | #include <stdlib.h> | |||
21 | ||||
22 | #include "mdvi.h" | |||
23 | #include "private.h" | |||
24 | ||||
25 | static ListHead fontlist; | |||
26 | ||||
27 | extern char *_mdvi_fallback_font; | |||
28 | ||||
29 | extern void vf_free_macros(DviFont *); | |||
30 | ||||
31 | #define finfosearch.info search.info | |||
32 | #define TYPENAME(font)((font)->search.info ? (font)->search.info->name : "none" ) \ | |||
33 | ((font)->finfosearch.info ? (font)->finfosearch.info->name : "none") | |||
34 | ||||
35 | int font_reopen(DviFont *font) | |||
36 | { | |||
37 | if(font->in) | |||
38 | fseek(font->in, (long)0, SEEK_SET0); | |||
39 | else if((font->in = fopenkpse_fopen_trace(font->filename, "rb")) == NULL((void*)0)) { | |||
40 | DEBUG((DBG_FILES, "reopen(%s) -> Error\n", font->filename))__debug ((1 << 2), "reopen(%s) -> Error\n", font-> filename); | |||
41 | return -1; | |||
42 | } | |||
43 | DEBUG((DBG_FILES, "reopen(%s) -> Ok.\n", font->filename))__debug ((1 << 2), "reopen(%s) -> Ok.\n", font->filename ); | |||
44 | return 0; | |||
45 | } | |||
46 | ||||
47 | /* used from context: params and device */ | |||
48 | static int load_font_file(DviParams *params, DviFont *font) | |||
49 | { | |||
50 | int status; | |||
51 | ||||
52 | if(SEARCH_DONE(font->search)((font->search).id < 0)) | |||
53 | return -1; | |||
54 | if(font->in == NULL((void*)0) && font_reopen(font) < 0) | |||
55 | return -1; | |||
56 | DEBUG((DBG_FONTS, "%s: loading %s font from `%s'\n",__debug ((1 << 1), "%s: loading %s font from `%s'\n", font ->fontname, font->search.info->name, font->filename ) | |||
57 | font->fontname,__debug ((1 << 1), "%s: loading %s font from `%s'\n", font ->fontname, font->search.info->name, font->filename ) | |||
58 | font->finfo->name, font->filename))__debug ((1 << 1), "%s: loading %s font from `%s'\n", font ->fontname, font->search.info->name, font->filename ); | |||
59 | do { | |||
60 | status = font->finfosearch.info->load(params, font); | |||
61 | } while(status < 0 && mdvi_font_retry(params, font) == 0); | |||
62 | if(status < 0) | |||
63 | return -1; | |||
64 | if(font->in) { | |||
65 | fclosekpse_fclose_trace(font->in); | |||
66 | font->in = NULL((void*)0); | |||
67 | } | |||
68 | DEBUG((DBG_FONTS, "reload_font(%s) -> %s\n",__debug ((1 << 1), "reload_font(%s) -> %s\n", font-> fontname, status < 0 ? "Error" : "Ok") | |||
69 | font->fontname, status < 0 ? "Error" : "Ok"))__debug ((1 << 1), "reload_font(%s) -> %s\n", font-> fontname, status < 0 ? "Error" : "Ok"); | |||
70 | return 0; | |||
71 | } | |||
72 | ||||
73 | void font_drop_one(DviFontRef *ref) | |||
74 | { | |||
75 | DviFont *font; | |||
76 | ||||
77 | font = ref->ref; | |||
78 | mdvi_free(ref); | |||
79 | /* drop all children */ | |||
80 | for(ref = font->subfonts; ref; ref = ref->next) { | |||
81 | /* just adjust the reference counts */ | |||
82 | ref->ref->links--; | |||
83 | } | |||
84 | if(--font->links == 0) { | |||
85 | /* | |||
86 | * this font doesn't have any more references, but | |||
87 | * we still keep it around in case a virtual font | |||
88 | * requests it. | |||
89 | */ | |||
90 | if(font->in) { | |||
91 | fclosekpse_fclose_trace(font->in); | |||
92 | font->in = NULL((void*)0); | |||
93 | } | |||
94 | if(LIST(font)((List *)(font)) != fontlist.tail) { | |||
95 | /* move it to the end of the list */ | |||
96 | listh_remove(&fontlist, LIST(font)((List *)(font))); | |||
97 | listh_append(&fontlist, LIST(font)((List *)(font))); | |||
98 | } | |||
99 | } | |||
100 | DEBUG((DBG_FONTS, "%s: reference dropped, %d more left\n",__debug ((1 << 1), "%s: reference dropped, %d more left\n" , font->fontname, font->links) | |||
101 | font->fontname, font->links))__debug ((1 << 1), "%s: reference dropped, %d more left\n" , font->fontname, font->links); | |||
102 | } | |||
103 | ||||
104 | void font_drop_chain(DviFontRef *head) | |||
105 | { | |||
106 | DviFontRef *ptr; | |||
107 | ||||
108 | for(; (ptr = head); ) { | |||
109 | head = ptr->next; | |||
110 | font_drop_one(ptr); | |||
111 | } | |||
112 | } | |||
113 | ||||
114 | int font_free_unused(DviDevice *dev) | |||
115 | { | |||
116 | DviFont *font, *next; | |||
117 | int count = 0; | |||
118 | ||||
119 | DEBUG((DBG_FONTS, "destroying unused fonts\n"))__debug ((1 << 1), "destroying unused fonts\n"); | |||
120 | for(font = (DviFont *)fontlist.head; font; font = next) { | |||
121 | DviFontRef *ref; | |||
122 | ||||
123 | next = font->next; | |||
124 | if(font->links) | |||
125 | continue; | |||
126 | count++; | |||
127 | DEBUG((DBG_FONTS, "removing unused %s font `%s'\n",__debug ((1 << 1), "removing unused %s font `%s'\n", (( font)->search.info ? (font)->search.info->name : "none" ), font->fontname) | |||
128 | TYPENAME(font), font->fontname))__debug ((1 << 1), "removing unused %s font `%s'\n", (( font)->search.info ? (font)->search.info->name : "none" ), font->fontname); | |||
129 | listh_remove(&fontlist, LIST(font)((List *)(font))); | |||
130 | if(font->in) | |||
131 | fclosekpse_fclose_trace(font->in); | |||
132 | /* get rid of subfonts (but can't use `drop_chain' here) */ | |||
133 | for(; (ref = font->subfonts); ) { | |||
134 | font->subfonts = ref->next; | |||
135 | mdvi_free(ref); | |||
136 | } | |||
137 | /* remove this font */ | |||
138 | font_reset_font_glyphs(dev, font, MDVI_FONTSEL_GLYPH(1 << 2)); | |||
139 | /* let the font destroy its private data */ | |||
140 | if(font->finfosearch.info->freedata) | |||
141 | font->finfosearch.info->freedata(font); | |||
142 | /* destroy characters */ | |||
143 | if(font->chars) | |||
144 | mdvi_free(font->chars); | |||
145 | mdvi_free(font->fontname); | |||
146 | mdvi_free(font->filename); | |||
147 | mdvi_free(font); | |||
148 | } | |||
149 | DEBUG((DBG_FONTS, "%d unused fonts removed\n", count))__debug ((1 << 1), "%d unused fonts removed\n", count); | |||
150 | return count; | |||
151 | } | |||
152 | ||||
153 | /* used from context: params and device */ | |||
154 | DviFontRef * | |||
155 | font_reference( | |||
156 | DviParams *params, /* rendering parameters */ | |||
157 | Int32 id, /* external id number */ | |||
158 | const char *name, /* font name */ | |||
159 | Int32 sum, /* checksum (from DVI of VF) */ | |||
160 | int hdpi, /* resolution */ | |||
161 | int vdpi, | |||
162 | Int32 scale) /* scaling factor (from DVI or VF) */ | |||
163 | { | |||
164 | DviFont *font; | |||
165 | DviFontRef *ref; | |||
166 | DviFontRef *subfont_ref; | |||
167 | ||||
168 | /* see if there is a font with the same characteristics */ | |||
169 | for(font = (DviFont *)fontlist.head; font; font = font->next) { | |||
170 | if(strcmp(name, font->fontname) == 0 | |||
171 | && (!sum || !font->checksum || font->checksum == sum) | |||
172 | && font->hdpi == hdpi | |||
173 | && font->vdpi == vdpi | |||
174 | && font->scale == scale) | |||
175 | break; | |||
176 | } | |||
177 | /* try to load the font */ | |||
178 | if(font == NULL((void*)0)) { | |||
179 | font = mdvi_add_font(name, sum, hdpi, vdpi, scale); | |||
180 | if(font == NULL((void*)0)) | |||
181 | return NULL((void*)0); | |||
182 | listh_append(&fontlist, LIST(font)((List *)(font))); | |||
183 | } | |||
184 | if(!font->links && !font->chars && load_font_file(params, font) < 0) { | |||
185 | DEBUG((DBG_FONTS, "font_reference(%s) -> Error\n", name))__debug ((1 << 1), "font_reference(%s) -> Error\n", name ); | |||
186 | return NULL((void*)0); | |||
187 | } | |||
188 | ref = xalloc(DviFontRef)(DviFontRef *)mdvi_malloc(sizeof(DviFontRef)); | |||
189 | ref->ref = font; | |||
190 | ||||
191 | font->links++; | |||
192 | for(subfont_ref = font->subfonts; subfont_ref; subfont_ref = subfont_ref->next) { | |||
193 | /* just adjust the reference counts */ | |||
194 | subfont_ref->ref->links++; | |||
195 | } | |||
196 | ||||
197 | ref->fontid = id; | |||
198 | ||||
199 | if(LIST(font)((List *)(font)) != fontlist.head) { | |||
200 | listh_remove(&fontlist, LIST(font)((List *)(font))); | |||
201 | listh_prepend(&fontlist, LIST(font)((List *)(font))); | |||
202 | } | |||
203 | ||||
204 | DEBUG((DBG_FONTS, "font_reference(%s) -> %d links\n",__debug ((1 << 1), "font_reference(%s) -> %d links\n" , font->fontname, font->links) | |||
205 | font->fontname, font->links))__debug ((1 << 1), "font_reference(%s) -> %d links\n" , font->fontname, font->links); | |||
206 | return ref; | |||
207 | } | |||
208 | ||||
209 | void font_transform_glyph(DviOrientation orient, DviGlyph *g) | |||
210 | { | |||
211 | BITMAP *map; | |||
212 | int x, y; | |||
213 | ||||
214 | map = (BITMAP *)g->data; | |||
| ||||
215 | if(MDVI_GLYPH_ISEMPTY(map)((map) == ((void *)1))) | |||
216 | map = NULL((void*)0); | |||
217 | ||||
218 | /* put the glyph in the right orientation */ | |||
219 | switch(orient) { | |||
220 | case MDVI_ORIENT_TBLR: | |||
221 | break; | |||
222 | case MDVI_ORIENT_TBRL: | |||
223 | g->x = g->w - g->x; | |||
224 | if(map) bitmap_flip_horizontally(map); | |||
225 | break; | |||
226 | case MDVI_ORIENT_BTLR: | |||
227 | g->y = g->h - g->y; | |||
228 | if(map) bitmap_flip_vertically(map); | |||
229 | break; | |||
230 | case MDVI_ORIENT_BTRL: | |||
231 | g->x = g->w - g->x; | |||
232 | g->y = g->h - g->y; | |||
233 | if(map) bitmap_flip_diagonally(map); | |||
234 | break; | |||
235 | case MDVI_ORIENT_RP90: | |||
236 | if(map) bitmap_rotate_counter_clockwise(map); | |||
237 | y = g->y; | |||
238 | x = g->w - g->x; | |||
239 | g->x = y; | |||
240 | g->y = x; | |||
241 | SWAPINT(g->w, g->h)({ int _s = g->w; g->w = g->h; g->h = _s; }); | |||
242 | break; | |||
243 | case MDVI_ORIENT_RM90: | |||
244 | if(map) bitmap_rotate_clockwise(map); | |||
245 | y = g->h - g->y; | |||
246 | x = g->x; | |||
247 | g->x = y; | |||
248 | g->y = x; | |||
249 | SWAPINT(g->w, g->h)({ int _s = g->w; g->w = g->h; g->h = _s; }); | |||
250 | break; | |||
251 | case MDVI_ORIENT_IRP90: | |||
252 | if(map) bitmap_flip_rotate_counter_clockwise(map); | |||
253 | y = g->y; | |||
254 | x = g->x; | |||
255 | g->x = y; | |||
256 | g->y = x; | |||
257 | SWAPINT(g->w, g->h)({ int _s = g->w; g->w = g->h; g->h = _s; }); | |||
258 | break; | |||
259 | case MDVI_ORIENT_IRM90: | |||
260 | if(map) bitmap_flip_rotate_clockwise(map); | |||
261 | y = g->h - g->y; | |||
262 | x = g->w - g->x; | |||
263 | g->x = y; | |||
264 | g->y = x; | |||
265 | SWAPINT(g->w, g->h)({ int _s = g->w; g->w = g->h; g->h = _s; }); | |||
266 | break; | |||
267 | } | |||
268 | } | |||
269 | ||||
270 | static int load_one_glyph(DviContext *dvi, DviFont *font, int code) | |||
271 | { | |||
272 | BITMAP *map; | |||
273 | DviFontChar *ch; | |||
274 | int status; | |||
275 | ||||
276 | #ifndef NODEBUG | |||
277 | ch = FONTCHAR(font, code)(((code) < font->loc || (code) > font->hic || !(font )->chars) ? ((void*)0) : &font->chars[(code) - (font )->loc]); | |||
278 | DEBUG((DBG_GLYPHS, "loading glyph code %d in %s (at %u)\n",__debug ((1 << 7), "loading glyph code %d in %s (at %u)\n" , code, font->fontname, ch->offset) | |||
279 | code, font->fontname, ch->offset))__debug ((1 << 7), "loading glyph code %d in %s (at %u)\n" , code, font->fontname, ch->offset); | |||
280 | #endif | |||
281 | if(font->finfosearch.info->getglyph == NULL((void*)0)) { | |||
282 | /* font type does not need to load glyphs (e.g. vf) */ | |||
283 | return 0; | |||
284 | } | |||
285 | ||||
286 | status = font->finfosearch.info->getglyph(&dvi->params, font, code); | |||
287 | if(status < 0) | |||
288 | return -1; | |||
289 | /* get the glyph again (font->chars may have changed) */ | |||
290 | ch = FONTCHAR(font, code)(((code) < font->loc || (code) > font->hic || !(font )->chars) ? ((void*)0) : &font->chars[(code) - (font )->loc]); | |||
291 | #ifndef NODEBUG | |||
292 | map = (BITMAP *)ch->glyph.data; | |||
293 | if(DEBUGGING(BITMAP_DATA)(_mdvi_debug_mask & (1 << 13))) { | |||
294 | DEBUG((DBG_BITMAP_DATA,__debug ((1 << 13), "%s: new %s bitmap for character %d:\n" , font->fontname, ((font)->search.info ? (font)->search .info->name : "none"), code) | |||
295 | "%s: new %s bitmap for character %d:\n",__debug ((1 << 13), "%s: new %s bitmap for character %d:\n" , font->fontname, ((font)->search.info ? (font)->search .info->name : "none"), code) | |||
296 | font->fontname, TYPENAME(font), code))__debug ((1 << 13), "%s: new %s bitmap for character %d:\n" , font->fontname, ((font)->search.info ? (font)->search .info->name : "none"), code); | |||
297 | if(MDVI_GLYPH_ISEMPTY(map)((map) == ((void *)1))) | |||
298 | DEBUG((DBG_BITMAP_DATA, "blank bitmap\n"))__debug ((1 << 13), "blank bitmap\n"); | |||
299 | else | |||
300 | bitmap_print(stderrstderr, map); | |||
301 | } | |||
302 | #endif | |||
303 | /* check if we have to scale it */ | |||
304 | if(!font->finfosearch.info->scalable && font->hdpi != font->vdpi) { | |||
305 | int hs, vs, d; | |||
306 | ||||
307 | /* we scale it ourselves */ | |||
308 | d = Max(font->hdpi, font->vdpi)(((font->hdpi) > (font->vdpi)) ? (font->hdpi) : ( font->vdpi)); | |||
309 | hs = d / font->hdpi; | |||
310 | vs = d / font->vdpi; | |||
311 | if(ch->width && ch->height && (hs > 1 || vs > 1)) { | |||
312 | int h, v; | |||
313 | DviGlyph glyph; | |||
314 | ||||
315 | DEBUG((DBG_FONTS,__debug ((1 << 1), "%s: scaling glyph %d to resolution %dx%d\n" , font->fontname, code, font->hdpi, font->vdpi) | |||
316 | "%s: scaling glyph %d to resolution %dx%d\n",__debug ((1 << 1), "%s: scaling glyph %d to resolution %dx%d\n" , font->fontname, code, font->hdpi, font->vdpi) | |||
317 | font->fontname, code, font->hdpi, font->vdpi))__debug ((1 << 1), "%s: scaling glyph %d to resolution %dx%d\n" , font->fontname, code, font->hdpi, font->vdpi); | |||
318 | h = dvi->params.hshrink; | |||
319 | v = dvi->params.vshrink; | |||
320 | d = dvi->params.density; | |||
321 | dvi->params.hshrink = hs; | |||
322 | dvi->params.vshrink = vs; | |||
323 | dvi->params.density = 50; | |||
324 | /* shrink it */ | |||
325 | font->finfosearch.info->shrink0(dvi, font, ch, &glyph); | |||
326 | /* restore parameters */ | |||
327 | dvi->params.hshrink = h; | |||
328 | dvi->params.vshrink = v; | |||
329 | dvi->params.density = d; | |||
330 | /* update glyph data */ | |||
331 | if(!MDVI_GLYPH_ISEMPTY(ch->glyph.data)((ch->glyph.data) == ((void *)1))) | |||
332 | bitmap_destroy((BITMAP *)ch->glyph.data); | |||
333 | ch->glyph.data = glyph.data; | |||
334 | ch->glyph.x = glyph.x; | |||
335 | ch->glyph.y = glyph.y; | |||
336 | ch->glyph.w = glyph.w; | |||
337 | ch->glyph.h = glyph.h; | |||
338 | } | |||
339 | ||||
340 | } | |||
341 | font_transform_glyph(dvi->params.orientation, &ch->glyph); | |||
342 | ||||
343 | return 0; | |||
344 | } | |||
345 | ||||
346 | DviFontChar *font_get_glyph(DviContext *dvi, DviFont *font, int code) | |||
347 | { | |||
348 | DviFontChar *ch; | |||
349 | ||||
350 | again: | |||
351 | /* if we have not loaded the font yet, do so now */ | |||
352 | if(!font->chars && load_font_file(&dvi->params, font) < 0) | |||
| ||||
353 | return NULL((void*)0); | |||
354 | ||||
355 | /* get the unscaled glyph, maybe loading it from disk */ | |||
356 | ch = FONTCHAR(font, code)(((code) < font->loc || (code) > font->hic || !(font )->chars) ? ((void*)0) : &font->chars[(code) - (font )->loc]); | |||
357 | if(!ch
| |||
358 | return NULL((void*)0); | |||
359 | if(!ch->loaded && load_one_glyph(dvi, font, code) == -1) { | |||
360 | if(font->chars == NULL((void*)0)) { | |||
361 | /* we need to try another font class */ | |||
362 | goto again; | |||
363 | } | |||
364 | return NULL((void*)0); | |||
365 | } | |||
366 | /* yes, we have to do this again */ | |||
367 | ch = FONTCHAR(font, code)(((code) < font->loc || (code) > font->hic || !(font )->chars) ? ((void*)0) : &font->chars[(code) - (font )->loc]); | |||
368 | ||||
369 | /* Got the glyph. If we also have the right scaled glyph, do no more */ | |||
370 | if(!ch->width || !ch->height || | |||
371 | font->finfosearch.info->getglyph == NULL((void*)0) || | |||
372 | (dvi->params.hshrink == 1 && dvi->params.vshrink == 1)) | |||
373 | return ch; | |||
374 | ||||
375 | /* If the glyph is empty, we just need to shrink the box */ | |||
376 | if(ch->missing || MDVI_GLYPH_ISEMPTY(ch->glyph.data)((ch->glyph.data) == ((void *)1))) { | |||
377 | if(MDVI_GLYPH_UNSET(ch->shrunk.data)((ch->shrunk.data) == ((void*)0))) | |||
378 | mdvi_shrink_box(dvi, font, ch, &ch->shrunk); | |||
379 | return ch; | |||
380 | } else if(MDVI_ENABLED(dvi, MDVI_PARAM_ANTIALIASED)((dvi)->params.flags & (1))) { | |||
381 | if(ch->grey.data && | |||
382 | !MDVI_GLYPH_ISEMPTY(ch->grey.data)((ch->grey.data) == ((void *)1)) && | |||
383 | ch->fg == dvi->curr_fg && | |||
384 | ch->bg == dvi->curr_bg) | |||
385 | return ch; | |||
386 | if(ch->grey.data && | |||
387 | !MDVI_GLYPH_ISEMPTY(ch->grey.data)((ch->grey.data) == ((void *)1))) { | |||
388 | if(dvi->device.free_image) | |||
389 | dvi->device.free_image(ch->grey.data); | |||
390 | ch->grey.data = NULL((void*)0); | |||
391 | } | |||
392 | font->finfosearch.info->shrink1(dvi, font, ch, &ch->grey); | |||
393 | } else if(!ch->shrunk.data) | |||
394 | font->finfosearch.info->shrink0(dvi, font, ch, &ch->shrunk); | |||
395 | ||||
396 | return ch; | |||
397 | } | |||
398 | ||||
399 | void font_reset_one_glyph(DviDevice *dev, DviFontChar *ch, int what) | |||
400 | { | |||
401 | if(!glyph_present(ch)((ch) && (ch)->offset)) | |||
402 | return; | |||
403 | if(what & MDVI_FONTSEL_BITMAP(1 << 0)) { | |||
404 | if(MDVI_GLYPH_NONEMPTY(ch->shrunk.data)((ch->shrunk.data) && (ch->shrunk.data) != ((void *)1))) | |||
405 | bitmap_destroy((BITMAP *)ch->shrunk.data); | |||
406 | ch->shrunk.data = NULL((void*)0); | |||
407 | } | |||
408 | if(what & MDVI_FONTSEL_GREY(1 << 1)) { | |||
409 | if(MDVI_GLYPH_NONEMPTY(ch->grey.data)((ch->grey.data) && (ch->grey.data) != ((void * )1))) { | |||
410 | if(dev->free_image) | |||
411 | dev->free_image(ch->grey.data); | |||
412 | } | |||
413 | ch->grey.data = NULL((void*)0); | |||
414 | } | |||
415 | if(what & MDVI_FONTSEL_GLYPH(1 << 2)) { | |||
416 | if(MDVI_GLYPH_NONEMPTY(ch->glyph.data)((ch->glyph.data) && (ch->glyph.data) != ((void *)1))) | |||
417 | bitmap_destroy((BITMAP *)ch->glyph.data); | |||
418 | ch->glyph.data = NULL((void*)0); | |||
419 | ch->loaded = 0; | |||
420 | } | |||
421 | } | |||
422 | ||||
423 | void font_reset_font_glyphs(DviDevice *dev, DviFont *font, int what) | |||
424 | { | |||
425 | int i; | |||
426 | DviFontChar *ch; | |||
427 | ||||
428 | if(what & MDVI_FONTSEL_GLYPH(1 << 2)) | |||
429 | what |= MDVI_FONTSEL_BITMAP(1 << 0)|MDVI_FONTSEL_GREY(1 << 1); | |||
430 | if(font->subfonts) { | |||
431 | DviFontRef *ref; | |||
432 | ||||
433 | for(ref = font->subfonts; ref; ref = ref->next) | |||
434 | font_reset_font_glyphs(dev, ref->ref, what); | |||
435 | } | |||
436 | if(font->in) { | |||
437 | DEBUG((DBG_FILES, "close(%s)\n", font->filename))__debug ((1 << 2), "close(%s)\n", font->filename); | |||
438 | fclosekpse_fclose_trace(font->in); | |||
439 | font->in = NULL((void*)0); | |||
440 | } | |||
441 | if(font->finfosearch.info->getglyph == NULL((void*)0)) | |||
442 | return; | |||
443 | DEBUG((DBG_FONTS, "resetting glyphs in font `%s'\n", font->fontname))__debug ((1 << 1), "resetting glyphs in font `%s'\n", font ->fontname); | |||
444 | for(ch = font->chars, i = font->loc; i <= font->hic; ch++, i++) { | |||
445 | if(glyph_present(ch)((ch) && (ch)->offset)) | |||
446 | font_reset_one_glyph(dev, ch, what); | |||
447 | } | |||
448 | if((what & MDVI_FONTSEL_GLYPH(1 << 2)) && font->finfosearch.info->reset) | |||
449 | font->finfosearch.info->reset(font); | |||
450 | } | |||
451 | ||||
452 | void font_reset_chain_glyphs(DviDevice *dev, DviFontRef *head, int what) | |||
453 | { | |||
454 | DviFontRef *ref; | |||
455 | ||||
456 | for(ref = head; ref; ref = ref->next) | |||
457 | font_reset_font_glyphs(dev, ref->ref, what); | |||
458 | } | |||
459 | ||||
460 | static int compare_refs(const void *p1, const void *p2) | |||
461 | { | |||
462 | return ((*(DviFontRef **)p1)->fontid - (*(DviFontRef **)p2)->fontid); | |||
463 | } | |||
464 | ||||
465 | void font_finish_definitions(DviContext *dvi) | |||
466 | { | |||
467 | int count; | |||
468 | DviFontRef **map, *ref; | |||
469 | ||||
470 | /* first get rid of unused fonts */ | |||
471 | font_free_unused(&dvi->device); | |||
472 | ||||
473 | if(dvi->fonts == NULL((void*)0)) { | |||
474 | mdvi_warning(_("%s: no fonts defined\n")gettext("%s: no fonts defined\n"), dvi->filename); | |||
475 | return; | |||
476 | } | |||
477 | map = xnalloc(DviFontRef *, dvi->nfonts)(DviFontRef * *)mdvi_calloc((dvi->nfonts), sizeof(DviFontRef *)); | |||
478 | for(count = 0, ref = dvi->fonts; ref; ref = ref->next) | |||
479 | map[count++] = ref; | |||
480 | /* sort the array by font id */ | |||
481 | qsort(map, dvi->nfonts, sizeof(DviFontRef *), compare_refs); | |||
482 | dvi->fontmap = map; | |||
483 | } | |||
484 | ||||
485 | DviFontRef *font_find_flat(DviContext *dvi, Int32 id) | |||
486 | { | |||
487 | DviFontRef *ref; | |||
488 | ||||
489 | for(ref = dvi->fonts; ref; ref = ref->next) | |||
490 | if(ref->fontid == id) | |||
491 | break; | |||
492 | return ref; | |||
493 | } | |||
494 | ||||
495 | DviFontRef *font_find_mapped(DviContext *dvi, Int32 id) | |||
496 | { | |||
497 | int lo, hi, n; | |||
498 | DviFontRef **map; | |||
499 | ||||
500 | /* do a binary search */ | |||
501 | lo = 0; hi = dvi->nfonts; | |||
502 | map = dvi->fontmap; | |||
503 | while(lo < hi) { | |||
504 | int sign; | |||
505 | ||||
506 | n = (hi + lo) >> 1; | |||
507 | sign = (map[n]->fontid - id); | |||
508 | if(sign == 0) | |||
509 | break; | |||
510 | else if(sign < 0) | |||
511 | lo = n; | |||
512 | else | |||
513 | hi = n; | |||
514 | } | |||
515 | if(lo >= hi) | |||
516 | return NULL((void*)0); | |||
517 | return map[n]; | |||
518 | } | |||
519 |