| File: | backend/dvi/mdvi-lib/tfm.c |
| Warning: | line 112, column 14 Access to field 'offset' results in a dereference of a null pointer (loaded from variable 'ch') |
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 | #include <stdarg.h> | |||
| 22 | #include <string.h> | |||
| 23 | #include <sys/stat.h> | |||
| 24 | #include <unistd.h> | |||
| 25 | ||||
| 26 | #include "mdvi.h" | |||
| 27 | #include "private.h" | |||
| 28 | ||||
| 29 | static int tfm_load_font __PROTO((DviParams *, DviFont *))(DviParams *, DviFont *); | |||
| 30 | static int tfm_font_get_glyph __PROTO((DviParams *, DviFont *, int))(DviParams *, DviFont *, int); | |||
| 31 | ||||
| 32 | DviFontInfo tfm_font_info = { | |||
| 33 | "TFM", | |||
| 34 | 0, /* scaling not supported by format */ | |||
| 35 | tfm_load_font, | |||
| 36 | tfm_font_get_glyph, | |||
| 37 | mdvi_shrink_box, | |||
| 38 | mdvi_shrink_box, | |||
| 39 | NULL((void*)0), /* free */ | |||
| 40 | NULL((void*)0), /* reset */ | |||
| 41 | NULL((void*)0), /* lookup */ | |||
| 42 | kpse_tfm_format, | |||
| 43 | NULL((void*)0) | |||
| 44 | }; | |||
| 45 | ||||
| 46 | DviFontInfo ofm_font_info = { | |||
| 47 | "OFM", | |||
| 48 | 0, /* scaling not supported by format */ | |||
| 49 | tfm_load_font, | |||
| 50 | tfm_font_get_glyph, | |||
| 51 | mdvi_shrink_box, | |||
| 52 | mdvi_shrink_box, | |||
| 53 | NULL((void*)0), /* free */ | |||
| 54 | NULL((void*)0), /* reset */ | |||
| 55 | NULL((void*)0), /* lookup */ | |||
| 56 | kpse_ofm_format, | |||
| 57 | NULL((void*)0) | |||
| 58 | }; | |||
| 59 | ||||
| 60 | DviFontInfo afm_font_info = { | |||
| 61 | "AFM", | |||
| 62 | 0, /* scaling not supported by format */ | |||
| 63 | tfm_load_font, | |||
| 64 | tfm_font_get_glyph, | |||
| 65 | mdvi_shrink_box, | |||
| 66 | mdvi_shrink_box, | |||
| 67 | NULL((void*)0), /* free */ | |||
| 68 | NULL((void*)0), /* reset */ | |||
| 69 | NULL((void*)0), /* lookup */ | |||
| 70 | kpse_afm_format, | |||
| 71 | NULL((void*)0) | |||
| 72 | }; | |||
| 73 | ||||
| 74 | #define TYPENAME(font)((font)->search.info ? (font)->search.info : "none") \ | |||
| 75 | ((font)->search.info ? (font)->search.info : "none") | |||
| 76 | ||||
| 77 | /* | |||
| 78 | * Although it does not seem that way, this conversion is independent of the | |||
| 79 | * shrinking factors, within roundoff (that's because `conv' and `vconv' | |||
| 80 | * have already been scaled by hshrink and vshrink, repsectively). We | |||
| 81 | * should really use `dviconv' and `dvivconv', but I'm not so sure those | |||
| 82 | * should be moved to the DviParams structure. | |||
| 83 | */ | |||
| 84 | #define XCONV(x)(int)((params->conv * (x) * params->hshrink) + 0.5) FROUND(params->conv * (x) * params->hshrink)(int)((params->conv * (x) * params->hshrink) + 0.5) | |||
| 85 | #define YCONV(y)(int)((params->vconv * (y) * params->vshrink) + 0.5) FROUND(params->vconv * (y) * params->vshrink)(int)((params->vconv * (y) * params->vshrink) + 0.5) | |||
| 86 | ||||
| 87 | /* this is used quite often in several places, so I made it standalone */ | |||
| 88 | int get_tfm_chars(DviParams *params, DviFont *font, TFMInfo *info, int loaded) | |||
| 89 | { | |||
| 90 | Int32 z, alpha, beta; | |||
| 91 | int n; | |||
| 92 | DviFontChar *ch; | |||
| 93 | TFMChar *ptr; | |||
| 94 | ||||
| 95 | n = info->hic - info->loc + 1; | |||
| 96 | if(n != FONT_GLYPH_COUNT(font)((font)->hic - (font)->loc + 1)) { | |||
| 97 | font->chars = mdvi_realloc(font->chars, | |||
| 98 | n * sizeof(DviFontChar)); | |||
| 99 | } | |||
| 100 | font->loc = info->loc; | |||
| 101 | font->hic = info->hic; | |||
| 102 | ch = font->chars; | |||
| 103 | ptr = info->chars; | |||
| 104 | ||||
| 105 | /* Prepare z, alpha and beta for TFM width computation */ | |||
| 106 | TFMPREPARE(font->scale, z, alpha, beta)do { alpha = 16; z = (font->scale); while(z > 040000000L ) { z >>= 1; alpha <<= 1; } beta = 256 / alpha; alpha *= z; } while(0); | |||
| 107 | ||||
| 108 | /* get the character metrics */ | |||
| 109 | for(n = info->loc; n <= info->hic; ch++, ptr++, n++) { | |||
| 110 | int a, b, c, d; | |||
| 111 | ||||
| 112 | ch->offset = ptr->present; | |||
| ||||
| 113 | if(ch->offset == 0) | |||
| 114 | continue; | |||
| 115 | /* this is what we came here for */ | |||
| 116 | ch->tfmwidth = TFMSCALE(z, ptr->advance, alpha, beta)(((((ptr->advance) >> 24) & 0xff) == 255) ? (((( ((((ptr->advance)) & 0xff) * ((z))) >> 8) + (((( (ptr->advance)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->advance)) >> 16) & 0xff) * ((z))) / (beta) - (alpha) : ((((((((ptr->advance)) & 0xff) * ((z))) >> 8) + (((((ptr->advance)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->advance)) >> 16) & 0xff) * ((z))) / (beta)); | |||
| 117 | /* scale all other TFM units (so they are in DVI units) */ | |||
| 118 | a = TFMSCALE(z, ptr->left, alpha, beta)(((((ptr->left) >> 24) & 0xff) == 255) ? ((((((( (ptr->left)) & 0xff) * ((z))) >> 8) + (((((ptr-> left)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr ->left)) >> 16) & 0xff) * ((z))) / (beta) - (alpha ) : ((((((((ptr->left)) & 0xff) * ((z))) >> 8) + (((((ptr->left)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->left)) >> 16) & 0xff) * ((z))) / ( beta)); | |||
| 119 | b = TFMSCALE(z, ptr->right, alpha, beta)(((((ptr->right) >> 24) & 0xff) == 255) ? (((((( ((ptr->right)) & 0xff) * ((z))) >> 8) + (((((ptr ->right)) >> 8) & 0xff) * ((z)))) >> 8) + ( (((ptr->right)) >> 16) & 0xff) * ((z))) / (beta) - (alpha) : ((((((((ptr->right)) & 0xff) * ((z))) >> 8) + (((((ptr->right)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->right)) >> 16) & 0xff) * ((z))) / (beta)); | |||
| 120 | c = TFMSCALE(z, ptr->height, alpha, beta)(((((ptr->height) >> 24) & 0xff) == 255) ? ((((( (((ptr->height)) & 0xff) * ((z))) >> 8) + (((((ptr ->height)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->height)) >> 16) & 0xff) * ((z))) / (beta ) - (alpha) : ((((((((ptr->height)) & 0xff) * ((z))) >> 8) + (((((ptr->height)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->height)) >> 16) & 0xff) * ((z))) / (beta)); | |||
| 121 | d = TFMSCALE(z, ptr->depth, alpha, beta)(((((ptr->depth) >> 24) & 0xff) == 255) ? (((((( ((ptr->depth)) & 0xff) * ((z))) >> 8) + (((((ptr ->depth)) >> 8) & 0xff) * ((z)))) >> 8) + ( (((ptr->depth)) >> 16) & 0xff) * ((z))) / (beta) - (alpha) : ((((((((ptr->depth)) & 0xff) * ((z))) >> 8) + (((((ptr->depth)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->depth)) >> 16) & 0xff) * ((z))) / (beta)); | |||
| 122 | ||||
| 123 | /* now convert to unscaled pixels */ | |||
| 124 | ch->width = XCONV(b - a)(int)((params->conv * (b - a) * params->hshrink) + 0.5); | |||
| 125 | ch->height = YCONV(c - d)(int)((params->vconv * (c - d) * params->vshrink) + 0.5 ); | |||
| 126 | if(ch->height < 0) ch->height = -ch->height; | |||
| 127 | ch->x = XCONV(a)(int)((params->conv * (a) * params->hshrink) + 0.5); | |||
| 128 | ch->y = YCONV(c)(int)((params->vconv * (c) * params->vshrink) + 0.5); | |||
| 129 | /* | |||
| 130 | * the offset is not used, but we might as well set it to | |||
| 131 | * something meaningful (and it MUST be non-zero) | |||
| 132 | */ | |||
| 133 | ch->flags = 0; | |||
| 134 | ch->code = n; | |||
| 135 | ch->glyph.data = NULL((void*)0); | |||
| 136 | ch->grey.data = NULL((void*)0); | |||
| 137 | ch->shrunk.data = NULL((void*)0); | |||
| 138 | ch->loaded = loaded; | |||
| 139 | } | |||
| 140 | ||||
| 141 | return 0; | |||
| 142 | } | |||
| 143 | ||||
| 144 | /* | |||
| 145 | * We use this function as a last resort to find the character widths in a | |||
| 146 | * font The DVI rendering code can correctly skip over a glyph if it knows | |||
| 147 | * its TFM width, which is what we try to find here. | |||
| 148 | */ | |||
| 149 | static int tfm_load_font(DviParams *params, DviFont *font) | |||
| 150 | { | |||
| 151 | TFMInfo *tfm; | |||
| 152 | int type; | |||
| 153 | ||||
| 154 | switch(font->search.info->kpse_type) { | |||
| ||||
| 155 | case kpse_tfm_format: | |||
| 156 | type = DviFontTFM; | |||
| 157 | break; | |||
| 158 | case kpse_afm_format: | |||
| 159 | type = DviFontAFM; | |||
| 160 | break; | |||
| 161 | case kpse_ofm_format: | |||
| 162 | type = DviFontOFM; | |||
| 163 | break; | |||
| 164 | default: | |||
| 165 | return -1; | |||
| 166 | } | |||
| 167 | ||||
| 168 | /* we don't need this */ | |||
| 169 | if(font->in) { | |||
| 170 | fclosekpse_fclose_trace(font->in); | |||
| 171 | font->in = NULL((void*)0); | |||
| 172 | } | |||
| 173 | tfm = get_font_metrics(font->fontname, type, font->filename); | |||
| 174 | if(tfm == NULL((void*)0)) | |||
| 175 | return -1; | |||
| 176 | ||||
| 177 | if(tfm->checksum && font->checksum && tfm->checksum != font->checksum) { | |||
| 178 | mdvi_warning(_("%s: Checksum mismatch (got %u, expected %u)\n")gettext("%s: Checksum mismatch (got %u, expected %u)\n"), | |||
| 179 | font->fontname, (unsigned)tfm->checksum, | |||
| 180 | (unsigned)font->checksum); | |||
| 181 | } | |||
| 182 | font->checksum = tfm->checksum; | |||
| 183 | font->design = tfm->design; | |||
| 184 | font->loc = 0; | |||
| 185 | font->hic = 0; | |||
| 186 | font->chars = NULL((void*)0); | |||
| 187 | get_tfm_chars(params, font, tfm, 1); | |||
| 188 | ||||
| 189 | /* free everything */ | |||
| 190 | free_font_metrics(tfm); | |||
| 191 | ||||
| 192 | return 0; | |||
| 193 | } | |||
| 194 | ||||
| 195 | static int tfm_font_get_glyph(DviParams *params, DviFont *font, int code) | |||
| 196 | { | |||
| 197 | DviFontChar *ch; | |||
| 198 | ||||
| 199 | ch = FONTCHAR(font, code)(((code) < font->loc || (code) > font->hic || !(font )->chars) ? ((void*)0) : &font->chars[(code) - (font )->loc]); | |||
| 200 | if(!glyph_present(ch)((ch) && (ch)->offset)) | |||
| 201 | return -1; | |||
| 202 | ch->glyph.x = ch->x; | |||
| 203 | ch->glyph.y = ch->y; | |||
| 204 | ch->glyph.w = ch->width; | |||
| 205 | ch->glyph.h = ch->height; | |||
| 206 | /* | |||
| 207 | * This has two purposes: (1) avoid unnecessary calls to this function, | |||
| 208 | * and (2) detect when the glyph data for a TFM font is actually used | |||
| 209 | * (we'll get a SEGV). Any occurrence of that is a bug. | |||
| 210 | */ | |||
| 211 | ch->glyph.data = MDVI_GLYPH_EMPTY((void *)1); | |||
| 212 | ||||
| 213 | return 0; | |||
| 214 | } |