| 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 |