source: branches/port5/WINDOW/AW_xfont.cxx

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