| 1 | /* FIG : Facility for Interactive Generation of figures |
|---|
| 2 | * Copyright (c) 1985 by Supoj Sutanthavibul |
|---|
| 3 | * Copyright (c) 1992 by Brian V. Smith |
|---|
| 4 | * |
|---|
| 5 | * "Permission to use, copy, modify, distribute, and sell this software and its |
|---|
| 6 | * documentation for any purpose is hereby granted without fee, provided that |
|---|
| 7 | * the above copyright notice appear in all copies and that both the copyright |
|---|
| 8 | * notice and this permission notice appear in supporting documentation. |
|---|
| 9 | * No representations are made about the suitability of this software for |
|---|
| 10 | * any purpose. It is provided "as is" without express or implied warranty." |
|---|
| 11 | * |
|---|
| 12 | * This software has been widely modified for usage inside ARB. |
|---|
| 13 | */ |
|---|
| 14 | |
|---|
| 15 | #include "aw_xfont.hxx" |
|---|
| 16 | #include "aw_root.hxx" |
|---|
| 17 | |
|---|
| 18 | #include <arbdb.h> |
|---|
| 19 | |
|---|
| 20 | #include <cctype> |
|---|
| 21 | |
|---|
| 22 | // -------------------------------------------------------------------------------- |
|---|
| 23 | |
|---|
| 24 | #define FONT_EXAMINE_MAX 5000 |
|---|
| 25 | #define KNOWN_ISO_VERSIONS 3 |
|---|
| 26 | |
|---|
| 27 | #if !defined(DEVEL_RELEASE) |
|---|
| 28 | // #define DUMP_FONT_LOOKUP |
|---|
| 29 | // #define DUMP_FONT_DETAILS |
|---|
| 30 | #endif |
|---|
| 31 | |
|---|
| 32 | // -------------------------------------------------------------------------------- |
|---|
| 33 | |
|---|
| 34 | typedef XFontStruct *PIX_FONT; |
|---|
| 35 | |
|---|
| 36 | static bool openwinfonts; |
|---|
| 37 | static bool is_scalable[AW_NUM_FONTS]; // whether the font is scalable |
|---|
| 38 | |
|---|
| 39 | // defines the preferred xfontsel-'rgstry' values (most wanted first) |
|---|
| 40 | |
|---|
| 41 | #define PREFER_ISO10646 |
|---|
| 42 | |
|---|
| 43 | #if defined(DEVEL_RALF) |
|---|
| 44 | #if defined(PREFER_ISO10646) |
|---|
| 45 | // #warning current iso setting: prefer ISO10646 (this is recommended) |
|---|
| 46 | #else |
|---|
| 47 | #warning current iso setting: prefer ISO8859 |
|---|
| 48 | #endif // PREFER_ISO10646 |
|---|
| 49 | #endif // DEVEL_RALF |
|---|
| 50 | |
|---|
| 51 | #if defined(PREFER_ISO10646) |
|---|
| 52 | static const char *known_iso_versions[KNOWN_ISO_VERSIONS] = { "ISO10646", "ISO8859", "*" }; |
|---|
| 53 | #else |
|---|
| 54 | static const char *known_iso_versions[KNOWN_ISO_VERSIONS] = { "ISO8859", "ISO10646", "*" }; |
|---|
| 55 | #endif |
|---|
| 56 | |
|---|
| 57 | static struct _xfstruct x_fontinfo[] = { |
|---|
| 58 | { "-adobe-times-medium-r-*--", "Times", NULp }, // #0 |
|---|
| 59 | { "-adobe-times-medium-i-*--", "Times I", NULp }, // #1 |
|---|
| 60 | { "-adobe-times-bold-r-*--", "Times B", NULp }, // #2 |
|---|
| 61 | { "-adobe-times-bold-i-*--", "Times IB", NULp }, // #3 |
|---|
| 62 | { "-schumacher-clean-medium-r-*--", "Schumacher", NULp }, // closest to Avant-Garde |
|---|
| 63 | { "-schumacher-clean-medium-i-*--", "Schumacher I", NULp }, // #5 |
|---|
| 64 | { "-schumacher-clean-bold-r-*--", "Schumacher B", NULp }, // #6 |
|---|
| 65 | { "-schumacher-clean-bold-i-*--", "Schumacher IB", NULp }, // #7 |
|---|
| 66 | { "-*-urw bookman l-medium-r-*--", "Bookman", NULp }, // closest to Bookman |
|---|
| 67 | { "-*-urw bookman l-medium-i-*--", "Bookman I", NULp }, // #9 |
|---|
| 68 | { "-*-urw bookman l-bold-r-*--", "Bookman B", NULp }, // #10 |
|---|
| 69 | { "-*-urw bookman l-bold-i-*--", "Bookman IB", NULp }, // #11 |
|---|
| 70 | { "-adobe-courier-medium-r-*--", "Courier", NULp }, // #12 |
|---|
| 71 | { "-adobe-courier-medium-o-*--", "Courier I", NULp }, // #13 |
|---|
| 72 | { "-adobe-courier-bold-r-*--", "Courier B", NULp }, // #14 |
|---|
| 73 | { "-adobe-courier-bold-o-*--", "Courier IB", NULp }, // #15 |
|---|
| 74 | { "-adobe-helvetica-medium-r-*--", "Helvetica", NULp }, // #16 |
|---|
| 75 | { "-adobe-helvetica-medium-o-*--", "Helvetica I", NULp }, // #17 |
|---|
| 76 | { "-adobe-helvetica-bold-r-*--", "Helvetica B", NULp }, // #18 |
|---|
| 77 | { "-adobe-helvetica-bold-o-*--", "Helvetica IB", NULp }, // #19 |
|---|
| 78 | { "-*-liberation sans narrow-medium-r-*--", "Liberation", NULp }, // closest to Helv-nar. |
|---|
| 79 | { "-*-liberation sans narrow-medium-o-*--", "Liberation I", NULp }, // #21 |
|---|
| 80 | { "-*-liberation sans narrow-bold-r-*--", "Liberation B", NULp }, // #22 |
|---|
| 81 | { "-*-liberation sans narrow-bold-o-*--", "Liberation IB", NULp }, // #23 |
|---|
| 82 | { "-adobe-new century schoolbook-medium-r-*--", "Schoolbook", NULp }, // #24 |
|---|
| 83 | { "-adobe-new century schoolbook-medium-i-*--", "Schoolbook I", NULp }, // #25 |
|---|
| 84 | { "-adobe-new century schoolbook-bold-r-*--", "Schoolbook B", NULp }, // #26 |
|---|
| 85 | { "-adobe-new century schoolbook-bold-i-*--", "Schoolbook IB", NULp }, // #27 |
|---|
| 86 | { "-*-lucidabright-medium-r-*--", "LucidaBr", NULp }, // closest to Palatino |
|---|
| 87 | { "-*-lucidabright-medium-i-*--", "LucidaBr I", NULp }, // #29 |
|---|
| 88 | { "-*-lucidabright-demibold-r-*--", "LucidaBr B", NULp }, // #30 |
|---|
| 89 | { "-*-lucidabright-demibold-i-*--", "LucidaBr IB", NULp }, // #31 |
|---|
| 90 | { "-*-symbol-medium-r-*--", "Symbol", NULp }, // #32 |
|---|
| 91 | { "-*-zapfchancery-medium-i-*--", "zapfchancery", NULp }, // #33 |
|---|
| 92 | { "-*-zapfdingbats-*-*-*--", "zapfdingbats", NULp }, // #34 |
|---|
| 93 | |
|---|
| 94 | // below here are fonts not defined in xfig! |
|---|
| 95 | // on export, they will be mapped to xfig fonts |
|---|
| 96 | // (according to ps_fontinfo.xfontnum, i.e. the number behind the postscript fontname below) |
|---|
| 97 | |
|---|
| 98 | { "-*-lucida-medium-r-*-*-", "Lucida", NULp }, // #35 |
|---|
| 99 | { "-*-lucida-medium-i-*-*-", "Lucida I", NULp }, // #36 |
|---|
| 100 | { "-*-lucida-bold-r-*-*-", "Lucida B", NULp }, // #37 |
|---|
| 101 | { "-*-lucida-bold-i-*-*-", "Lucida IB", NULp }, // #38 |
|---|
| 102 | { "-*-lucidatypewriter-medium-r-*-*-", "Lucida mono", NULp }, // #39 |
|---|
| 103 | { "-*-lucidatypewriter-bold-r-*-*-", "Lucida mono B", NULp }, // #40 |
|---|
| 104 | |
|---|
| 105 | { "-*-screen-medium-r-*-*-", "Screen", NULp }, // #41 |
|---|
| 106 | { "-*-screen-bold-r-*-*-", "Screen B", NULp }, // #42 |
|---|
| 107 | { "-*-clean-medium-r-*-*-", "Clean", NULp }, // #43 |
|---|
| 108 | { "-*-clean-bold-r-*-*-", "Clean B", NULp }, // #44 |
|---|
| 109 | { "-*-terminal-medium-r-*-*-", "Terminal", NULp }, // #45 |
|---|
| 110 | { "-*-terminal-bold-r-*-*-", "Terminal B", NULp }, // #46 |
|---|
| 111 | |
|---|
| 112 | { "-*-dustismo-medium-r-*-*-", "Dustismo", NULp }, // #47 |
|---|
| 113 | { "-*-dustismo-bold-r-*-*-", "Dustismo B", NULp }, // #48 |
|---|
| 114 | { "-*-utopia-medium-r-*-*-", "Utopia", NULp }, // #49 |
|---|
| 115 | { "-*-utopia-bold-r-*-*-", "Utopia B", NULp }, // #50 |
|---|
| 116 | { "-*-dejavu sans-medium-r-*-*-", "Dejavu", NULp }, // #51 |
|---|
| 117 | { "-*-dejavu sans-bold-r-*-*-", "Dejavu B", NULp }, // #52 |
|---|
| 118 | |
|---|
| 119 | { "-*-fixed-medium-r-*-*-", "Fixed", NULp }, // #53 |
|---|
| 120 | { "-*-fixed-bold-r-*-*-", "Fixed B", NULp }, // #54 |
|---|
| 121 | { "-*-dejavu sans mono-medium-r-*-*-", "Dejavu mono", NULp }, // #55 |
|---|
| 122 | { "-*-dejavu sans mono-bold-r-*-*-", "Dejavu mono B", NULp }, // #56 |
|---|
| 123 | { "-*-luxi mono-medium-r-*-*-", "Luxi mono", NULp }, // #57 |
|---|
| 124 | { "-*-luxi mono-bold-r-*-*-", "Luxi mono B", NULp }, // #58 |
|---|
| 125 | { "-*-nimbus mono l-medium-r-*-*-", "Nimbus mono", NULp }, // #59 |
|---|
| 126 | { "-*-nimbus mono l-bold-r-*-*-", "Nimbus mono B", NULp }, // #60 |
|---|
| 127 | { "-*-latin modern typewriter-medium-r-*-*-", "Latin mono", NULp }, // #61 |
|---|
| 128 | { "-*-latin modern typewriter-bold-r-*-*-", "Latin mono B", NULp }, // #62 |
|---|
| 129 | |
|---|
| 130 | { "-*-terminus-medium-r-*-*-", "Terminus", NULp }, // #63 |
|---|
| 131 | { "-*-terminus-bold-r-*-*-", "Terminus B", NULp }, // #64 |
|---|
| 132 | { "-sony-fixed-medium-r-*-*-", "SonyFixed", NULp }, // #65 |
|---|
| 133 | { "-sony-fixed-bold-r-*-*-", "SonyFixed B", NULp }, // #66 |
|---|
| 134 | { "-mutt-clearlyu-medium-r-*-*-", "MuttClearlyu", NULp }, // #67 |
|---|
| 135 | }; |
|---|
| 136 | |
|---|
| 137 | static struct _fstruct ps_fontinfo[] = { |
|---|
| 138 | // map window fonts to postscript fonts |
|---|
| 139 | // negative values indicate monospaced fonts |
|---|
| 140 | { "Default", -1 }, |
|---|
| 141 | { "Times-Roman", 0 }, |
|---|
| 142 | { "Times-Italic", 1 }, |
|---|
| 143 | { "Times-Bold", 2 }, |
|---|
| 144 | { "Times-BoldItalic", 3 }, |
|---|
| 145 | { "AvantGarde-Book", 4 }, |
|---|
| 146 | { "AvantGarde-BookOblique", 5 }, |
|---|
| 147 | { "AvantGarde-Demi", 6 }, |
|---|
| 148 | { "AvantGarde-DemiOblique", 7 }, |
|---|
| 149 | { "Bookman-Light", 8 }, |
|---|
| 150 | { "Bookman-LightItalic", 9 }, |
|---|
| 151 | { "Bookman-Demi", 10 }, |
|---|
| 152 | { "Bookman-DemiItalic", 11 }, |
|---|
| 153 | { "Courier", -12 }, |
|---|
| 154 | { "Courier-Oblique", -13 }, |
|---|
| 155 | { "Courier-Bold", -14 }, |
|---|
| 156 | { "Courier-BoldOblique", -15 }, |
|---|
| 157 | { "Helvetica", 16 }, |
|---|
| 158 | { "Helvetica-Oblique", 17 }, |
|---|
| 159 | { "Helvetica-Bold", 18 }, |
|---|
| 160 | { "Helvetica-BoldOblique", 19 }, |
|---|
| 161 | { "Helvetica-Narrow", 20 }, |
|---|
| 162 | { "Helvetica-Narrow-Oblique", 21 }, |
|---|
| 163 | { "Helvetica-Narrow-Bold", 22 }, |
|---|
| 164 | { "Helvetica-Narrow-BoldOblique", 23 }, |
|---|
| 165 | { "NewCenturySchlbk-Roman", 24 }, |
|---|
| 166 | { "NewCenturySchlbk-Italic", 25 }, |
|---|
| 167 | { "NewCenturySchlbk-Bold", 26 }, |
|---|
| 168 | { "NewCenturySchlbk-BoldItalic", 27 }, |
|---|
| 169 | { "Palatino-Roman", 28 }, |
|---|
| 170 | { "Palatino-Italic", 29 }, |
|---|
| 171 | { "Palatino-Bold", 30 }, |
|---|
| 172 | { "Palatino-BoldItalic", 31 }, |
|---|
| 173 | { "Symbol", 32 }, |
|---|
| 174 | { "ZapfChancery-MediumItalic", 33 }, |
|---|
| 175 | { "ZapfDingbats", 34 }, |
|---|
| 176 | |
|---|
| 177 | // non xfig-fonts below. |
|---|
| 178 | // Need to be mapped to best matching xfig font using a font number between 0 and AW_NUM_FONTS_XFIG-1 |
|---|
| 179 | |
|---|
| 180 | { "LucidaSans", 16 }, |
|---|
| 181 | { "LucidaSans-Italic", 17 }, |
|---|
| 182 | { "LucidaSans-Bold", 18 }, |
|---|
| 183 | { "LucidaSans-BoldItalic", 19 }, |
|---|
| 184 | { "LucidaSansTypewriter", -12 }, |
|---|
| 185 | { "LucidaSansTypewriter-Bold", -14 }, |
|---|
| 186 | |
|---|
| 187 | { "Screen", -16 }, |
|---|
| 188 | { "Screen-Bold", -18 }, |
|---|
| 189 | { "Clean", -12 }, |
|---|
| 190 | { "Clean-Bold", -14 }, |
|---|
| 191 | { "Terminal", -12 }, |
|---|
| 192 | { "Terminal-Bold", -14 }, |
|---|
| 193 | |
|---|
| 194 | { "AvantGarde-Book", 4 }, |
|---|
| 195 | { "AvantGarde-Demi", 6 }, |
|---|
| 196 | { "Palatino-Roman", 28 }, |
|---|
| 197 | { "Palatino-Bold", 30 }, |
|---|
| 198 | { "AvantGarde-Book", 4 }, |
|---|
| 199 | { "AvantGarde-Demi", 6 }, |
|---|
| 200 | |
|---|
| 201 | { "Courier", -12 }, |
|---|
| 202 | { "Courier-Bold", -14 }, |
|---|
| 203 | { "Courier", -12 }, |
|---|
| 204 | { "Courier-Bold", -14 }, |
|---|
| 205 | { "Courier", -12 }, |
|---|
| 206 | { "Courier-Bold", -14 }, |
|---|
| 207 | { "Courier", -12 }, |
|---|
| 208 | { "Courier-Bold", -14 }, |
|---|
| 209 | { "Courier", -12 }, |
|---|
| 210 | { "Courier-Bold", -14 }, |
|---|
| 211 | |
|---|
| 212 | { "Courier", -12 }, |
|---|
| 213 | { "Courier-Bold", -14 }, |
|---|
| 214 | { "Courier", -12 }, |
|---|
| 215 | { "Courier-Bold", -14 }, |
|---|
| 216 | { "Times-Roman", 0 }, |
|---|
| 217 | }; |
|---|
| 218 | |
|---|
| 219 | STATIC_ASSERT(ARRAY_ELEMS(x_fontinfo) == AW_NUM_FONTS); |
|---|
| 220 | STATIC_ASSERT(ARRAY_ELEMS(ps_fontinfo) == AW_NUM_FONTS+1); |
|---|
| 221 | |
|---|
| 222 | #if defined(ASSERTION_USED) |
|---|
| 223 | static void check_ps_fontinfo_valid() { |
|---|
| 224 | // check all fonts do translate into valid xfig fonts: |
|---|
| 225 | for (int f = 0; f<AW_NUM_FONTS; ++f) { |
|---|
| 226 | int xfig_fontnr = AW_font_2_xfig(f); |
|---|
| 227 | if (xfig_fontnr<0) xfig_fontnr = -xfig_fontnr; |
|---|
| 228 | aw_assert(xfig_fontnr >= 0); |
|---|
| 229 | aw_assert(xfig_fontnr < AW_NUM_FONTS_XFIG); |
|---|
| 230 | } |
|---|
| 231 | |
|---|
| 232 | // check for unique font-specs and unique font-shortnames: |
|---|
| 233 | for (int f1 = 0; f1<AW_NUM_FONTS; ++f1) { |
|---|
| 234 | const _xfstruct& x1 = x_fontinfo[f1]; |
|---|
| 235 | for (int f2 = f1+1; f2<AW_NUM_FONTS; ++f2) { |
|---|
| 236 | const _xfstruct& x2 = x_fontinfo[f2]; |
|---|
| 237 | |
|---|
| 238 | aw_assert(strcmp(x1.templat, x2.templat) != 0); |
|---|
| 239 | aw_assert(strcmp(x1.description, x2.description) != 0); |
|---|
| 240 | } |
|---|
| 241 | } |
|---|
| 242 | } |
|---|
| 243 | #endif |
|---|
| 244 | |
|---|
| 245 | |
|---|
| 246 | #define FONT_STRING_PARTS 14 |
|---|
| 247 | |
|---|
| 248 | static const char *parseFontString(const char *fontname, int *minus_position) { |
|---|
| 249 | const char *error = NULp; |
|---|
| 250 | const char *minus = strchr(fontname, '-'); |
|---|
| 251 | int count = 0; |
|---|
| 252 | |
|---|
| 253 | for (; minus; minus = strchr(minus+1, '-'), ++count) { |
|---|
| 254 | if (count >= FONT_STRING_PARTS) { error = "too many '-'"; break; } |
|---|
| 255 | minus_position[count] = minus-fontname; |
|---|
| 256 | } |
|---|
| 257 | if (count != FONT_STRING_PARTS) error = "expected 14 '-'"; |
|---|
| 258 | |
|---|
| 259 | return error; |
|---|
| 260 | } |
|---|
| 261 | static char *getParsedFontPart(const char *fontname, int *minus_position, int idx) { |
|---|
| 262 | aw_assert(idx >= 0 && idx<FONT_STRING_PARTS); |
|---|
| 263 | |
|---|
| 264 | int startpos = minus_position[idx]+1; // behind minus |
|---|
| 265 | int endpos = (idx == (FONT_STRING_PARTS-1) ? strlen(fontname) : minus_position[idx+1])-1; // in front of minus/string-end |
|---|
| 266 | int length = endpos-startpos+1; // excluding minus |
|---|
| 267 | char *result = new char[length+1]; |
|---|
| 268 | |
|---|
| 269 | memcpy(result, fontname+startpos, length); |
|---|
| 270 | result[length] = 0; |
|---|
| 271 | |
|---|
| 272 | return result; |
|---|
| 273 | } |
|---|
| 274 | |
|---|
| 275 | // parse the point size of font 'name' |
|---|
| 276 | // e.g. -adobe-courier-bold-o-normal--10-100-75-75-m-60-ISO8859-1 |
|---|
| 277 | |
|---|
| 278 | static int parsesize(const char *fontname) { |
|---|
| 279 | int pos[14]; |
|---|
| 280 | int size; |
|---|
| 281 | const char *error = parseFontString(fontname, pos); |
|---|
| 282 | |
|---|
| 283 | if (!error) { |
|---|
| 284 | char *sizeString = getParsedFontPart(fontname, pos, 6); |
|---|
| 285 | size = atoi(sizeString); |
|---|
| 286 | if (size == 0 && strcmp(sizeString, "0") != 0) { |
|---|
| 287 | error = GBS_global_string("Can't parse size (from '%s')", sizeString); |
|---|
| 288 | } |
|---|
| 289 | delete [] sizeString; |
|---|
| 290 | } |
|---|
| 291 | |
|---|
| 292 | if (error) { |
|---|
| 293 | fprintf(stderr, "Error parsing size info from '%s' (%s)\n", fontname, error); |
|---|
| 294 | return 0; |
|---|
| 295 | } |
|---|
| 296 | |
|---|
| 297 | return size; |
|---|
| 298 | } |
|---|
| 299 | |
|---|
| 300 | void aw_root_init_font(Display *display) { |
|---|
| 301 | static bool initialized = false; |
|---|
| 302 | if (initialized) return; |
|---|
| 303 | |
|---|
| 304 | initialized = true; |
|---|
| 305 | |
|---|
| 306 | #if defined(ASSERTION_USED) |
|---|
| 307 | check_ps_fontinfo_valid(); |
|---|
| 308 | #endif |
|---|
| 309 | |
|---|
| 310 | /* Now initialize the font structure for the X fonts corresponding to the |
|---|
| 311 | * Postscript fonts for the canvas. OpenWindows can use any LaserWriter |
|---|
| 312 | * fonts at any size, so we don't need to load anything if we are using |
|---|
| 313 | * it. |
|---|
| 314 | */ |
|---|
| 315 | |
|---|
| 316 | // check for OpenWindow-style fonts, otherwise check for scalable font |
|---|
| 317 | openwinfonts = false; |
|---|
| 318 | { |
|---|
| 319 | char **fontlist; |
|---|
| 320 | int count; |
|---|
| 321 | |
|---|
| 322 | // first look for OpenWindow style font names (e.g. times-roman) |
|---|
| 323 | if ((fontlist = XListFonts(display, ps_fontinfo[1].name, 1, &count))) { |
|---|
| 324 | openwinfonts = true; |
|---|
| 325 | for (int f = 0; f<AW_NUM_FONTS; f++) { // copy the OpenWindow font names ( = postscript fontnames?) |
|---|
| 326 | x_fontinfo[f].templat = ps_fontinfo[f+1].name; |
|---|
| 327 | is_scalable[f] = true; |
|---|
| 328 | #if defined(DUMP_FONT_LOOKUP) |
|---|
| 329 | printf("ps_fontinfo[f+1].name='%s'\n", ps_fontinfo[f+1].name); |
|---|
| 330 | #endif // DUMP_FONT_LOOKUP |
|---|
| 331 | } |
|---|
| 332 | XFreeFontNames(fontlist); |
|---|
| 333 | #if defined(DUMP_FONT_LOOKUP) |
|---|
| 334 | printf("Using OpenWindow fonts\n"); |
|---|
| 335 | #endif |
|---|
| 336 | } |
|---|
| 337 | else { |
|---|
| 338 | for (int f = 0; f<AW_NUM_FONTS; f++) { |
|---|
| 339 | char templat[200]; |
|---|
| 340 | strcpy(templat, x_fontinfo[f].templat); |
|---|
| 341 | strcat(templat, "0-0-*-*-*-*-*-*"); |
|---|
| 342 | |
|---|
| 343 | if ((fontlist = XListFonts(display, templat, 1, &count))) { |
|---|
| 344 | // font with size zero exists -> this font is scalable |
|---|
| 345 | is_scalable[f] = true; |
|---|
| 346 | XFreeFontNames(fontlist); |
|---|
| 347 | } |
|---|
| 348 | else { |
|---|
| 349 | is_scalable[f] = false; |
|---|
| 350 | } |
|---|
| 351 | #if defined(DUMP_FONT_LOOKUP) |
|---|
| 352 | printf("Using %s font for '%s' (templat='%s')\n", is_scalable[f] ? "scalable" : "fixed", x_fontinfo[f].templat, templat); |
|---|
| 353 | #endif // DUMP_FONT_LOOKUP |
|---|
| 354 | } |
|---|
| 355 | } |
|---|
| 356 | } |
|---|
| 357 | |
|---|
| 358 | struct found_font { const char *fn; int s; }; |
|---|
| 359 | |
|---|
| 360 | if (!openwinfonts) { |
|---|
| 361 | found_font *flist = new found_font[FONT_EXAMINE_MAX]; |
|---|
| 362 | |
|---|
| 363 | for (int f = 0; f<AW_NUM_FONTS; f++) { |
|---|
| 364 | if (is_scalable[f]) continue; |
|---|
| 365 | |
|---|
| 366 | // for all non-scalable fonts: |
|---|
| 367 | // query the server for all the font names and sizes and build a list of them |
|---|
| 368 | |
|---|
| 369 | char **fontlist[KNOWN_ISO_VERSIONS]; |
|---|
| 370 | int iso; |
|---|
| 371 | int found_fonts = 0; |
|---|
| 372 | |
|---|
| 373 | for (iso = 0; iso<KNOWN_ISO_VERSIONS; ++iso) fontlist[iso] = NULp; |
|---|
| 374 | |
|---|
| 375 | for (iso = 0; iso<KNOWN_ISO_VERSIONS; ++iso) { |
|---|
| 376 | char *font_template = GBS_global_string_copy("%s*-*-*-*-*-*-%s-*", x_fontinfo[f].templat, known_iso_versions[iso]); |
|---|
| 377 | int count; |
|---|
| 378 | |
|---|
| 379 | fontlist[iso] = XListFonts(display, font_template, FONT_EXAMINE_MAX, &count); |
|---|
| 380 | if (fontlist[iso]) { |
|---|
| 381 | if ((found_fonts+count) >= FONT_EXAMINE_MAX) { |
|---|
| 382 | printf("Warning: Too many fonts found for '%s..%s' - ARB can't examine all fonts\n", x_fontinfo[f].templat, known_iso_versions[iso]); |
|---|
| 383 | count = FONT_EXAMINE_MAX-found_fonts; |
|---|
| 384 | } |
|---|
| 385 | for (int c = 0; c<count; ++c) { |
|---|
| 386 | const char *fontname = fontlist[iso][c]; |
|---|
| 387 | int size = parsesize(fontname); |
|---|
| 388 | flist[found_fonts].fn = fontname; // valid as long fontlist[iso] is not freed! |
|---|
| 389 | flist[found_fonts].s = size; |
|---|
| 390 | found_fonts++; |
|---|
| 391 | } |
|---|
| 392 | } |
|---|
| 393 | |
|---|
| 394 | free(font_template); |
|---|
| 395 | } |
|---|
| 396 | |
|---|
| 397 | #if defined(DUMP_FONT_LOOKUP) |
|---|
| 398 | printf("Considering %i fonts for '%s'\n", found_fonts, x_fontinfo[f].templat); |
|---|
| 399 | #endif // DUMP_FONT_LOOKUP |
|---|
| 400 | |
|---|
| 401 | aw_assert(found_fonts <= FONT_EXAMINE_MAX); |
|---|
| 402 | xfont *nf = NULp; |
|---|
| 403 | |
|---|
| 404 | for (int size = MIN_FONTSIZE; size <= MAX_FONTSIZE; size++) { // scan all useful sizes |
|---|
| 405 | int i; |
|---|
| 406 | for (i = 0; i < found_fonts; i++) { |
|---|
| 407 | if (flist[i].s == size) break; // search first font matching current size |
|---|
| 408 | } |
|---|
| 409 | |
|---|
| 410 | if (i < found_fonts && flist[i].s == size) { |
|---|
| 411 | xfont *newfont = ARB_alloc<xfont>(1); |
|---|
| 412 | |
|---|
| 413 | (nf ? nf->next : x_fontinfo[f].xfontlist) = newfont; |
|---|
| 414 | nf = newfont; |
|---|
| 415 | |
|---|
| 416 | // store size and actual fontname : |
|---|
| 417 | nf->size = size; |
|---|
| 418 | nf->fname = strdup(flist[i].fn); |
|---|
| 419 | nf->fstruct = NULp; |
|---|
| 420 | nf->next = NULp; |
|---|
| 421 | } |
|---|
| 422 | } |
|---|
| 423 | |
|---|
| 424 | if (!nf) { // no font has been found -> fallback to "fixed 12pt" |
|---|
| 425 | aw_assert(!x_fontinfo[f].xfontlist); |
|---|
| 426 | xfont *newfont = ARB_alloc<xfont>(1); |
|---|
| 427 | x_fontinfo[f].xfontlist = newfont; |
|---|
| 428 | |
|---|
| 429 | newfont->size = DEF_FONTSIZE; |
|---|
| 430 | newfont->fname = strdup(NORMAL_FONT); |
|---|
| 431 | newfont->fstruct = NULp; |
|---|
| 432 | newfont->next = NULp; |
|---|
| 433 | } |
|---|
| 434 | |
|---|
| 435 | #if defined(DUMP_FONT_LOOKUP) |
|---|
| 436 | nf = x_fontinfo[f].xfontlist; |
|---|
| 437 | printf("Fonts used for '%s':\n", x_fontinfo[f].templat); |
|---|
| 438 | while (nf) { |
|---|
| 439 | printf("- %2i pt: '%s'\n", nf->size, nf->fname); |
|---|
| 440 | nf = nf->next; |
|---|
| 441 | } |
|---|
| 442 | #endif // DUMP_FONT_LOOKUP |
|---|
| 443 | |
|---|
| 444 | for (iso = 0; iso<KNOWN_ISO_VERSIONS; ++iso) XFreeFontNames(fontlist[iso]); |
|---|
| 445 | } |
|---|
| 446 | |
|---|
| 447 | delete [] flist; |
|---|
| 448 | } |
|---|
| 449 | } |
|---|
| 450 | |
|---|
| 451 | #if defined(DUMP_FONT_DETAILS) |
|---|
| 452 | static void dumpFontInformation(xfont *xf) { |
|---|
| 453 | printf("Font information for '%s'", xf->fname); |
|---|
| 454 | XFontStruct *xfs = xf->fstruct; |
|---|
| 455 | if (xfs) { |
|---|
| 456 | printf(":\n"); |
|---|
| 457 | printf("- max letter ascent = %2i\n", xfs->max_bounds.ascent); |
|---|
| 458 | printf("- max letter descent = %2i\n", xfs->max_bounds.descent); |
|---|
| 459 | printf("- max letter height = %2i\n", xfs->max_bounds.ascent + xfs->max_bounds.descent); |
|---|
| 460 | printf("- max letter width = %2i\n", xfs->max_bounds.width); |
|---|
| 461 | } |
|---|
| 462 | else { |
|---|
| 463 | printf(" (not available, font is not loaded)\n"); |
|---|
| 464 | } |
|---|
| 465 | } |
|---|
| 466 | #endif // DEBUG |
|---|
| 467 | |
|---|
| 468 | /* Lookup an X font, "f" corresponding to a Postscript font style that is |
|---|
| 469 | * close in size to "s" |
|---|
| 470 | */ |
|---|
| 471 | |
|---|
| 472 | #define DEFAULT (-1) |
|---|
| 473 | |
|---|
| 474 | static bool lookfont(Display *tool_d, int f, int s, int& found_size, bool verboose, bool only_query, PIX_FONT *fontstPtr) { |
|---|
| 475 | // returns true if appropriate font is available. |
|---|
| 476 | // |
|---|
| 477 | // 'found_size' is set to the actually found size, which may be bigger or smaller than 's', if the requested size is not available |
|---|
| 478 | // |
|---|
| 479 | // if 'only_query' is true, then only report availability |
|---|
| 480 | // if 'only_query' is false, then actually load the font and store the loaded fontstruct in 'fontstPtr' |
|---|
| 481 | bool found; |
|---|
| 482 | xfont *newfont, *nf, *oldnf; |
|---|
| 483 | |
|---|
| 484 | #if defined(WARN_TODO) |
|---|
| 485 | #warning scalability shall be checked for each font -- not only for first |
|---|
| 486 | #warning fontdetection is called for each GC -- do some caching ? |
|---|
| 487 | #endif |
|---|
| 488 | |
|---|
| 489 | found_size = -1; |
|---|
| 490 | |
|---|
| 491 | if (f == DEFAULT) |
|---|
| 492 | f = 0; // pass back the -normal font font |
|---|
| 493 | if (s < 0) |
|---|
| 494 | s = DEF_FONTSIZE; // default font size |
|---|
| 495 | |
|---|
| 496 | /* see if we've already loaded that font size 's' |
|---|
| 497 | from the font family 'f' */ |
|---|
| 498 | |
|---|
| 499 | found = false; |
|---|
| 500 | |
|---|
| 501 | /* start with the basic font name (e.g. adobe-times-medium-r-normal-... |
|---|
| 502 | OR times-roman for OpenWindows fonts) */ |
|---|
| 503 | |
|---|
| 504 | nf = x_fontinfo[f].xfontlist; |
|---|
| 505 | if (!nf) nf = x_fontinfo[0].xfontlist; |
|---|
| 506 | oldnf = nf; |
|---|
| 507 | if (nf) { |
|---|
| 508 | if (nf->size > s && !is_scalable[f]) { |
|---|
| 509 | found = true; |
|---|
| 510 | } |
|---|
| 511 | else { |
|---|
| 512 | while (nf) { |
|---|
| 513 | if (nf->size == s || |
|---|
| 514 | (!is_scalable[f] && (nf->size >= s && oldnf->size <= s))) |
|---|
| 515 | { |
|---|
| 516 | found = true; |
|---|
| 517 | break; |
|---|
| 518 | } |
|---|
| 519 | oldnf = nf; |
|---|
| 520 | nf = nf->next; |
|---|
| 521 | } |
|---|
| 522 | } |
|---|
| 523 | } |
|---|
| 524 | if (found) { // found exact size (or only larger available) |
|---|
| 525 | if (verboose) { |
|---|
| 526 | if (s < nf->size) fprintf(stderr, "Font size %d not found, using larger %d point\n", s, nf->size); |
|---|
| 527 | #if defined(DUMP_FONT_LOOKUP) |
|---|
| 528 | fprintf(stderr, "Detected font %s\n", nf->fname); |
|---|
| 529 | #endif |
|---|
| 530 | } |
|---|
| 531 | } |
|---|
| 532 | else if (!is_scalable[f]) { // not found, use largest available |
|---|
| 533 | nf = oldnf; |
|---|
| 534 | if (verboose) { |
|---|
| 535 | if (s > nf->size) fprintf(stderr, "Font size %d not found, using smaller %d point\n", s, nf->size); |
|---|
| 536 | #if defined(DUMP_FONT_LOOKUP) |
|---|
| 537 | fprintf(stderr, "Using font %s for size %d\n", nf->fname, s); |
|---|
| 538 | #endif |
|---|
| 539 | } |
|---|
| 540 | } |
|---|
| 541 | else { // SCALABLE; none yet of that size, alloc one and put it in the list |
|---|
| 542 | ARB_alloc(newfont, 1); |
|---|
| 543 | |
|---|
| 544 | // add it on to the end of the list |
|---|
| 545 | nf = oldnf ? oldnf->next : NULp; // store successor |
|---|
| 546 | |
|---|
| 547 | if (!x_fontinfo[f].xfontlist) x_fontinfo[f].xfontlist = newfont; |
|---|
| 548 | else oldnf->next = newfont; |
|---|
| 549 | |
|---|
| 550 | newfont->next = nf; // old successor in fontlist |
|---|
| 551 | newfont->size = s; |
|---|
| 552 | newfont->fstruct = NULp; |
|---|
| 553 | newfont->fname = NULp; |
|---|
| 554 | |
|---|
| 555 | nf = newfont; |
|---|
| 556 | |
|---|
| 557 | if (openwinfonts) { |
|---|
| 558 | // OpenWindows fonts, create font name like times-roman-13 |
|---|
| 559 | |
|---|
| 560 | nf->fname = GBS_global_string_copy("%s-%d", x_fontinfo[f].templat, s); |
|---|
| 561 | } |
|---|
| 562 | else { |
|---|
| 563 | // X11 fonts, create a full XLFD font name |
|---|
| 564 | // attach pointsize to font name, use the pixel field instead of points in the fontname so that the |
|---|
| 565 | // font scales with screen size |
|---|
| 566 | |
|---|
| 567 | for (int iso = 0; iso<KNOWN_ISO_VERSIONS; ++iso) { |
|---|
| 568 | char *fontname = GBS_global_string_copy("%s%d-*-*-*-*-*-%s-*", x_fontinfo[f].templat, s, known_iso_versions[iso]); |
|---|
| 569 | #if defined(DUMP_FONT_LOOKUP) |
|---|
| 570 | fprintf(stderr, "Checking for '%s' (x_fontinfo[%i].templat='%s')\n", fontname, f, x_fontinfo[f].templat); |
|---|
| 571 | #endif |
|---|
| 572 | |
|---|
| 573 | int matching_fonts_found; |
|---|
| 574 | char **matching_fonts = XListFonts(tool_d, fontname, 1, &matching_fonts_found); |
|---|
| 575 | |
|---|
| 576 | if (matching_fonts) { |
|---|
| 577 | XFreeFontNames(matching_fonts); |
|---|
| 578 | aw_assert(matching_fonts_found >= 1); |
|---|
| 579 | nf->fname = fontname; |
|---|
| 580 | break; |
|---|
| 581 | } |
|---|
| 582 | |
|---|
| 583 | free(fontname); |
|---|
| 584 | } |
|---|
| 585 | // @@@ what if nf->fstruct is 0 now ? |
|---|
| 586 | } |
|---|
| 587 | // aw_assert(nf->fname); // fails e.g. for screen-medium-r, but font nevertheless seems to be usable |
|---|
| 588 | } // scalable |
|---|
| 589 | |
|---|
| 590 | bool font_found = true; |
|---|
| 591 | |
|---|
| 592 | if (!nf->fstruct) { |
|---|
| 593 | if (only_query) { |
|---|
| 594 | ; // assume its available (or use XQueryFont to reduce server-client bandwidth) |
|---|
| 595 | } |
|---|
| 596 | else { |
|---|
| 597 | #if defined(DUMP_FONT_LOOKUP) |
|---|
| 598 | if (verboose) fprintf(stderr, "Loading font '%s'\n", nf->fname); |
|---|
| 599 | #endif |
|---|
| 600 | PIX_FONT fontst = XLoadQueryFont(tool_d, nf->fname); |
|---|
| 601 | if (!fontst) { |
|---|
| 602 | fprintf(stderr, "ARB fontpackage: Unexpectedly couldn't load font '%s', falling back to '%s' (f=%i, s=%i)\n", nf->fname, NORMAL_FONT, f, s); |
|---|
| 603 | fontst = XLoadQueryFont(tool_d, NORMAL_FONT); // @@@ may return 0! |
|---|
| 604 | freedup(nf->fname, NORMAL_FONT); // store actual name |
|---|
| 605 | } |
|---|
| 606 | // put the structure in the list |
|---|
| 607 | nf->fstruct = fontst; |
|---|
| 608 | } |
|---|
| 609 | } |
|---|
| 610 | |
|---|
| 611 | #if defined(DUMP_FONT_DETAILS) |
|---|
| 612 | dumpFontInformation(nf); |
|---|
| 613 | #endif // DEBUG |
|---|
| 614 | |
|---|
| 615 | found_size = nf->size; // report used size |
|---|
| 616 | *fontstPtr = nf->fstruct; |
|---|
| 617 | |
|---|
| 618 | return font_found; |
|---|
| 619 | } |
|---|
| 620 | |
|---|
| 621 | static int get_available_fontsizes(Display *tool_d, int f, int *available_sizes) { |
|---|
| 622 | // returns number of available sizes |
|---|
| 623 | // specific sizes are stored in available_sizes[] |
|---|
| 624 | |
|---|
| 625 | int size_count = 0; |
|---|
| 626 | for (int size = MAX_FONTSIZE; size >= MIN_FONTSIZE; --size) { |
|---|
| 627 | int found_size; |
|---|
| 628 | PIX_FONT fontst; |
|---|
| 629 | |
|---|
| 630 | ASSERT_TRUE(lookfont(tool_d, f, size, found_size, false, true, &fontst)); // lookfont should do fallback |
|---|
| 631 | |
|---|
| 632 | if (found_size<size) size = found_size; |
|---|
| 633 | if (found_size == size) available_sizes[size_count++] = size; |
|---|
| 634 | } |
|---|
| 635 | |
|---|
| 636 | // reverse order of found fontsizes |
|---|
| 637 | if (size_count>1) { |
|---|
| 638 | for (int reverse = size_count/2-1; reverse >= 0; --reverse) { |
|---|
| 639 | int o = size_count-1-reverse; |
|---|
| 640 | aw_assert(o >= 0 && o<size_count); |
|---|
| 641 | |
|---|
| 642 | int s = available_sizes[reverse]; |
|---|
| 643 | available_sizes[reverse] = available_sizes[o]; |
|---|
| 644 | available_sizes[o] = s; |
|---|
| 645 | } |
|---|
| 646 | } |
|---|
| 647 | |
|---|
| 648 | return size_count; |
|---|
| 649 | } |
|---|
| 650 | |
|---|
| 651 | static char *caps(char *sentence) { |
|---|
| 652 | bool doCaps = true; |
|---|
| 653 | for (int i = 0; sentence[i]; ++i) { |
|---|
| 654 | if (isalpha(sentence[i])) { |
|---|
| 655 | if (doCaps) { |
|---|
| 656 | sentence[i] = toupper(sentence[i]); |
|---|
| 657 | doCaps = false; |
|---|
| 658 | } |
|---|
| 659 | } |
|---|
| 660 | else { |
|---|
| 661 | doCaps = true; |
|---|
| 662 | } |
|---|
| 663 | } |
|---|
| 664 | return sentence; |
|---|
| 665 | } |
|---|
| 666 | |
|---|
| 667 | |
|---|
| 668 | const char *AW_get_font_specification(AW_font font_nr, bool& found) { |
|---|
| 669 | //! converts fontnr to string |
|---|
| 670 | // |
|---|
| 671 | // @return 0 if font is not available |
|---|
| 672 | |
|---|
| 673 | found = false; |
|---|
| 674 | aw_assert(font_nr >= 0); |
|---|
| 675 | if (font_nr<0 || font_nr>=AW_NUM_FONTS) return NULp; |
|---|
| 676 | |
|---|
| 677 | const char *readable_fontname = NULp; |
|---|
| 678 | struct _xfstruct& xf = x_fontinfo[font_nr]; |
|---|
| 679 | |
|---|
| 680 | if (xf.xfontlist) { |
|---|
| 681 | const char *fontname = xf.xfontlist->fname; |
|---|
| 682 | |
|---|
| 683 | if (strcmp(fontname, "fixed") == 0) { |
|---|
| 684 | readable_fontname = GBS_global_string("[not found: %s]", xf.templat); |
|---|
| 685 | } |
|---|
| 686 | else { |
|---|
| 687 | int pos[14]; |
|---|
| 688 | const char *error = parseFontString(fontname, pos); |
|---|
| 689 | if (error) { |
|---|
| 690 | readable_fontname = GBS_global_string("[%s - parse-error (%s)]", fontname, error); |
|---|
| 691 | } |
|---|
| 692 | else { |
|---|
| 693 | char *fndry = caps(getParsedFontPart(fontname, pos, 0)); |
|---|
| 694 | char *fmly = caps(getParsedFontPart(fontname, pos, 1)); |
|---|
| 695 | char *wght = getParsedFontPart(fontname, pos, 2); wght[3] = 0; |
|---|
| 696 | char *slant = getParsedFontPart(fontname, pos, 3); |
|---|
| 697 | char *rgstry = getParsedFontPart(fontname, pos, 12); |
|---|
| 698 | |
|---|
| 699 | readable_fontname = GBS_global_string("%s %s %s,%s,%s", |
|---|
| 700 | fndry, fmly, |
|---|
| 701 | wght, slant, |
|---|
| 702 | rgstry); |
|---|
| 703 | |
|---|
| 704 | found = true; |
|---|
| 705 | |
|---|
| 706 | delete [] rgstry; |
|---|
| 707 | delete [] slant; |
|---|
| 708 | delete [] wght; |
|---|
| 709 | delete [] fmly; |
|---|
| 710 | delete [] fndry; |
|---|
| 711 | } |
|---|
| 712 | } |
|---|
| 713 | } |
|---|
| 714 | else { |
|---|
| 715 | readable_fontname = xf.templat; |
|---|
| 716 | found = true; |
|---|
| 717 | } |
|---|
| 718 | return readable_fontname; |
|---|
| 719 | } |
|---|
| 720 | |
|---|
| 721 | const char *AW_get_font_shortname(AW_font font_nr) { |
|---|
| 722 | aw_assert(font_nr>=0 && font_nr<AW_NUM_FONTS); |
|---|
| 723 | return x_fontinfo[font_nr].description; |
|---|
| 724 | } |
|---|
| 725 | |
|---|
| 726 | int AW_font_2_xfig(AW_font font_nr) { |
|---|
| 727 | //! converts fontnr to xfigid |
|---|
| 728 | // |
|---|
| 729 | // negative values indicate monospaced f. |
|---|
| 730 | |
|---|
| 731 | if (font_nr<0 || font_nr>=AW_NUM_FONTS) return 0; |
|---|
| 732 | return ps_fontinfo[font_nr+1].xfontnum; |
|---|
| 733 | } |
|---|
| 734 | |
|---|
| 735 | inline bool CI_NonExistChar(const XCharStruct *cs) { |
|---|
| 736 | return |
|---|
| 737 | cs->width == 0 && |
|---|
| 738 | (cs->rbearing|cs->lbearing|cs->ascent|cs->descent) == 0; |
|---|
| 739 | } |
|---|
| 740 | |
|---|
| 741 | inline void CI_GetCharInfo_1D(const XFontStruct *fs, unsigned col, const XCharStruct *def, const XCharStruct*& cs) { |
|---|
| 742 | cs = def; |
|---|
| 743 | aw_assert(fs->min_byte1 == 0 && fs->max_byte1 == 0); // otherwise CI_GetCharInfo_1D is not the appropriate function |
|---|
| 744 | if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { |
|---|
| 745 | if (!fs->per_char) { |
|---|
| 746 | cs = &fs->min_bounds; |
|---|
| 747 | } |
|---|
| 748 | else { |
|---|
| 749 | cs = &fs->per_char[col - fs->min_char_or_byte2]; |
|---|
| 750 | if (CI_NonExistChar(cs)) cs = def; |
|---|
| 751 | } |
|---|
| 752 | } |
|---|
| 753 | } |
|---|
| 754 | |
|---|
| 755 | inline void CI_GetDefaultInfo_1D(const XFontStruct *fs, const XCharStruct*& cs) { |
|---|
| 756 | CI_GetCharInfo_1D(fs, fs->default_char, NULp, cs); |
|---|
| 757 | } |
|---|
| 758 | |
|---|
| 759 | /* CI_GET_CHAR_INFO_2D - return the charinfo struct for the indicated row and |
|---|
| 760 | * column. This is used for fonts that have more than row zero. |
|---|
| 761 | */ |
|---|
| 762 | |
|---|
| 763 | inline void CI_GetCharInfo_2D(const XFontStruct *fs, unsigned row, unsigned col, const XCharStruct *def, const XCharStruct*& cs) { |
|---|
| 764 | cs = def; |
|---|
| 765 | if (row >= fs->min_byte1 && row <= fs->max_byte1 && |
|---|
| 766 | col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) |
|---|
| 767 | { |
|---|
| 768 | if (!fs->per_char) { |
|---|
| 769 | cs = &fs->min_bounds; |
|---|
| 770 | } |
|---|
| 771 | else { |
|---|
| 772 | cs = &fs->per_char[((row - fs->min_byte1) * |
|---|
| 773 | (fs->max_char_or_byte2 - |
|---|
| 774 | fs->min_char_or_byte2 + 1)) + |
|---|
| 775 | (col - fs->min_char_or_byte2)]; |
|---|
| 776 | if (CI_NonExistChar(cs)) cs = def; |
|---|
| 777 | } |
|---|
| 778 | } |
|---|
| 779 | } |
|---|
| 780 | |
|---|
| 781 | inline void CI_GetDefaultInfo_2D(const XFontStruct *fs, const XCharStruct*& cs) { |
|---|
| 782 | unsigned int r = (fs->default_char >> 8); |
|---|
| 783 | unsigned int c = (fs->default_char & 0xff); |
|---|
| 784 | CI_GetCharInfo_2D (fs, r, c, NULp, cs); |
|---|
| 785 | } |
|---|
| 786 | |
|---|
| 787 | /* CI_GetRowzeroCharInfo_2D - do the same thing as CI_GetCharInfo_1D, |
|---|
| 788 | * except that the font has more than one row. This is special case of more |
|---|
| 789 | * general version used in XTextExt16.c since row == 0. This is used when |
|---|
| 790 | * max_byte2 is not zero. A further optimization would do the check for |
|---|
| 791 | * min_byte1 being zero ahead of time. |
|---|
| 792 | */ |
|---|
| 793 | |
|---|
| 794 | inline void CI_GetRowzeroCharInfo_2D(const XFontStruct *fs, unsigned col, const XCharStruct *def, const XCharStruct*& cs) { |
|---|
| 795 | cs = def; |
|---|
| 796 | if (fs->min_byte1 == 0 && |
|---|
| 797 | col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { |
|---|
| 798 | if (!fs->per_char) { |
|---|
| 799 | cs = &fs->min_bounds; |
|---|
| 800 | } |
|---|
| 801 | else { |
|---|
| 802 | cs = &fs->per_char[(col - fs->min_char_or_byte2)]; |
|---|
| 803 | if (CI_NonExistChar(cs)) cs = def; |
|---|
| 804 | } |
|---|
| 805 | } |
|---|
| 806 | } |
|---|
| 807 | |
|---|
| 808 | void AW_GC_Xm::wm_set_font(const AW_font font_nr, const int size, int *found_size) { |
|---|
| 809 | // if found_size != 0 -> return value for used font size |
|---|
| 810 | XFontStruct *xfs; |
|---|
| 811 | { |
|---|
| 812 | int found_font_size; |
|---|
| 813 | ASSERT_TRUE(lookfont(get_common()->get_display(), font_nr, size, found_font_size, true, false, &xfs)); // lookfont should do fallback |
|---|
| 814 | if (found_size) *found_size = found_font_size; |
|---|
| 815 | } |
|---|
| 816 | XSetFont(get_common()->get_display(), gc, xfs->fid); |
|---|
| 817 | curfont = *xfs; |
|---|
| 818 | |
|---|
| 819 | const XCharStruct *cs; |
|---|
| 820 | const XCharStruct *def; // info about default char |
|---|
| 821 | bool singlerow = (xfs->max_byte1 == 0); // optimization |
|---|
| 822 | |
|---|
| 823 | if (singlerow) { // optimization |
|---|
| 824 | CI_GetDefaultInfo_1D(xfs, def); |
|---|
| 825 | } |
|---|
| 826 | else { |
|---|
| 827 | CI_GetDefaultInfo_2D(xfs, def); |
|---|
| 828 | } |
|---|
| 829 | |
|---|
| 830 | aw_assert(AW_FONTINFO_CHAR_ASCII_MIN < AW_FONTINFO_CHAR_ASCII_MAX); |
|---|
| 831 | |
|---|
| 832 | unsigned int i; |
|---|
| 833 | for (i = AW_FONTINFO_CHAR_ASCII_MIN; i <= AW_FONTINFO_CHAR_ASCII_MAX; i++) { |
|---|
| 834 | if (singlerow) CI_GetCharInfo_1D(xfs, i, def, cs); // optimization |
|---|
| 835 | else CI_GetRowzeroCharInfo_2D(xfs, i, def, cs); |
|---|
| 836 | if (cs) set_char_size(i, cs->ascent, cs->descent, cs->width); |
|---|
| 837 | else set_no_char_size(i); |
|---|
| 838 | } |
|---|
| 839 | } |
|---|
| 840 | |
|---|
| 841 | void AW_GC::set_font(const AW_font font_nr, const int size, int *found_size) { |
|---|
| 842 | font_limits.reset(); |
|---|
| 843 | wm_set_font(font_nr, size, found_size); |
|---|
| 844 | fontnr = font_nr; |
|---|
| 845 | fontsize = size; |
|---|
| 846 | } |
|---|
| 847 | |
|---|
| 848 | int AW_GC_Xm::get_available_fontsizes(AW_font font_nr, int *available_sizes) const { |
|---|
| 849 | return ::get_available_fontsizes(get_common()->get_display(), font_nr, available_sizes); |
|---|
| 850 | } |
|---|