OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [unix/] [tkUnixFont.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkUnixFont.c --
3
 *
4
 *      Contains the Unix implementation of the platform-independant
5
 *      font package interface.
6
 *
7
 * Copyright (c) 1996 Sun Microsystems, Inc.
8
 *
9
 * See the file "license.terms" for information on usage and redistribution
10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
 *
12
 * RCS: @(#) $Id: tkUnixFont.c,v 1.1.1.1 2002-01-16 10:26:01 markom Exp $
13
 */
14
 
15
#include "tkPort.h"
16
#include "tkInt.h"
17
#include "tkUnixInt.h"
18
 
19
#include "tkFont.h"
20
 
21
#ifndef ABS
22
#define ABS(n)  (((n) < 0) ? -(n) : (n))
23
#endif
24
 
25
/*
26
 * The following structure represents Unix's implementation of a font.
27
 */
28
 
29
typedef struct UnixFont {
30
    TkFont font;                /* Stuff used by generic font package.  Must
31
                                 * be first in structure. */
32
    Display *display;           /* The display to which font belongs. */
33
    XFontStruct *fontStructPtr; /* X information about font. */
34
    char types[256];            /* Array giving types of all characters in
35
                                 * the font, used when displaying control
36
                                 * characters.  See below for definition. */
37
    int widths[256];            /* Array giving widths of all possible
38
                                 * characters in the font. */
39
    int underlinePos;           /* Offset from baseline to origin of
40
                                 * underline bar (used for simulating a native
41
                                 * underlined font). */
42
    int barHeight;              /* Height of underline or overstrike bar
43
                                 * (used for simulating a native underlined or
44
                                 * strikeout font). */
45
} UnixFont;
46
 
47
/*
48
 * Possible values for entries in the "types" field in a UnixFont structure,
49
 * which classifies the types of all characters in the given font.  This
50
 * information is used when measuring and displaying characters.
51
 *
52
 * NORMAL:              Standard character.
53
 * REPLACE:             This character doesn't print:  instead of
54
 *                      displaying character, display a replacement
55
 *                      sequence like "\n" (for those characters where
56
 *                      ANSI C defines such a sequence) or a sequence
57
 *                      of the form "\xdd" where dd is the hex equivalent
58
 *                      of the character.
59
 * SKIP:                Don't display anything for this character.  This
60
 *                      is only used where the font doesn't contain
61
 *                      all the characters needed to generate
62
 *                      replacement sequences.
63
 */
64
 
65
#define NORMAL          0
66
#define REPLACE         1
67
#define SKIP            2
68
 
69
/*
70
 * Characters used when displaying control sequences.
71
 */
72
 
73
static char hexChars[] = "0123456789abcdefxtnvr\\";
74
 
75
/*
76
 * The following table maps some control characters to sequences like '\n'
77
 * rather than '\x10'.  A zero entry in the table means no such mapping
78
 * exists, and the table only maps characters less than 0x10.
79
 */
80
 
81
static char mapChars[] = {
82
    0, 0, 0, 0, 0, 0, 0,
83
    'a', 'b', 't', 'n', 'v', 'f', 'r',
84
 
85
};
86
 
87
 
88
static UnixFont *       AllocFont _ANSI_ARGS_((TkFont *tkFontPtr,
89
                            Tk_Window tkwin, XFontStruct *fontStructPtr,
90
                            CONST char *fontName));
91
static void             DrawChars _ANSI_ARGS_((Display *display,
92
                            Drawable drawable, GC gc, UnixFont *fontPtr,
93
                            CONST char *source, int numChars, int x,
94
                            int y));
95
static int              GetControlCharSubst _ANSI_ARGS_((int c, char buf[4]));
96
 
97
 
98
/*
99
 *---------------------------------------------------------------------------
100
 *
101
 * TkpGetNativeFont --
102
 *
103
 *      Map a platform-specific native font name to a TkFont.
104
 *
105
 * Results:
106
 *      The return value is a pointer to a TkFont that represents the
107
 *      native font.  If a native font by the given name could not be
108
 *      found, the return value is NULL.
109
 *
110
 *      Every call to this procedure returns a new TkFont structure,
111
 *      even if the name has already been seen before.  The caller should
112
 *      call TkpDeleteFont() when the font is no longer needed.
113
 *
114
 *      The caller is responsible for initializing the memory associated
115
 *      with the generic TkFont when this function returns and releasing
116
 *      the contents of the generic TkFont before calling TkpDeleteFont().
117
 *
118
 * Side effects:
119
 *      None.
120
 *
121
 *---------------------------------------------------------------------------
122
 */
123
 
124
TkFont *
125
TkpGetNativeFont(tkwin, name)
126
    Tk_Window tkwin;            /* For display where font will be used. */
127
    CONST char *name;           /* Platform-specific font name. */
128
{
129
    XFontStruct *fontStructPtr;
130
 
131
    fontStructPtr = XLoadQueryFont(Tk_Display(tkwin), name);
132
    if (fontStructPtr == NULL) {
133
        return NULL;
134
    }
135
 
136
    return (TkFont *) AllocFont(NULL, tkwin, fontStructPtr, name);
137
}
138
 
139
/*
140
 *---------------------------------------------------------------------------
141
 *
142
 * TkpGetFontFromAttributes --
143
 *
144
 *      Given a desired set of attributes for a font, find a font with
145
 *      the closest matching attributes.
146
 *
147
 * Results:
148
 *      The return value is a pointer to a TkFont that represents the
149
 *      font with the desired attributes.  If a font with the desired
150
 *      attributes could not be constructed, some other font will be
151
 *      substituted automatically.
152
 *
153
 *      Every call to this procedure returns a new TkFont structure,
154
 *      even if the specified attributes have already been seen before.
155
 *      The caller should call TkpDeleteFont() to free the platform-
156
 *      specific data when the font is no longer needed.
157
 *
158
 *      The caller is responsible for initializing the memory associated
159
 *      with the generic TkFont when this function returns and releasing
160
 *      the contents of the generic TkFont before calling TkpDeleteFont().
161
 *
162
 * Side effects:
163
 *      None.
164
 *
165
 *---------------------------------------------------------------------------
166
 */
167
TkFont *
168
TkpGetFontFromAttributes(tkFontPtr, tkwin, faPtr)
169
    TkFont *tkFontPtr;          /* If non-NULL, store the information in
170
                                 * this existing TkFont structure, rather than
171
                                 * allocating a new structure to hold the
172
                                 * font; the existing contents of the font
173
                                 * will be released.  If NULL, a new TkFont
174
                                 * structure is allocated. */
175
    Tk_Window tkwin;            /* For display where font will be used. */
176
    CONST TkFontAttributes *faPtr;  /* Set of attributes to match. */
177
{
178
    int numNames, score, i, scaleable, pixelsize, xaPixelsize;
179
    int bestIdx, bestScore, bestScaleableIdx, bestScaleableScore;
180
    TkXLFDAttributes xa;
181
    char buf[256];
182
    UnixFont *fontPtr;
183
    char **nameList;
184
    XFontStruct *fontStructPtr;
185
    CONST char *fmt, *family;
186
    double d;
187
 
188
    family = faPtr->family;
189
    if (family == NULL) {
190
        family = "*";
191
    }
192
 
193
    pixelsize = -faPtr->pointsize;
194
    if (pixelsize < 0) {
195
        d = -pixelsize * 25.4 / 72;
196
        d *= WidthOfScreen(Tk_Screen(tkwin));
197
        d /= WidthMMOfScreen(Tk_Screen(tkwin));
198
        d += 0.5;
199
        pixelsize = (int) d;
200
    }
201
 
202
    /*
203
     * Replace the standard Windows and Mac family names with the names that
204
     * X likes.
205
     */
206
 
207
    if ((strcasecmp("Times New Roman", family) == 0)
208
            || (strcasecmp("New York", family) == 0)) {
209
        family = "Times";
210
    } else if ((strcasecmp("Courier New", family) == 0)
211
            || (strcasecmp("Monaco", family) == 0)) {
212
        family = "Courier";
213
    } else if ((strcasecmp("Arial", family) == 0)
214
            || (strcasecmp("Geneva", family) == 0)) {
215
        family = "Helvetica";
216
    }
217
 
218
    /*
219
     * First try for the Q&D exact match.
220
     */
221
 
222
#if 0
223
    sprintf(buf, "-*-%.200s-%s-%c-normal-*-*-%d-*-*-*-*-iso8859-1", family,
224
            ((faPtr->weight > TK_FW_NORMAL) ? "bold" : "medium"),
225
            ((faPtr->slant == TK_FS_ROMAN) ? 'r' :
226
                    (faPtr->slant == TK_FS_ITALIC) ? 'i' : 'o'),
227
            faPtr->pointsize * 10);
228
    fontStructPtr = XLoadQueryFont(Tk_Display(tkwin), buf);
229
#else
230
    fontStructPtr = NULL;
231
#endif
232
 
233
    if (fontStructPtr != NULL) {
234
        goto end;
235
    }
236
    /*
237
     * Couldn't find exact match.  Now fall back to other available
238
     * physical fonts.
239
     */
240
 
241
    fmt = "-*-%.240s-*-*-*-*-*-*-*-*-*-*-*-*";
242
    sprintf(buf, fmt, family);
243
    nameList = XListFonts(Tk_Display(tkwin), buf, 10000, &numNames);
244
    if (numNames == 0) {
245
        /*
246
         * Try getting some system font.
247
         */
248
 
249
        sprintf(buf, fmt, "fixed");
250
        nameList = XListFonts(Tk_Display(tkwin), buf, 10000, &numNames);
251
        if (numNames == 0) {
252
            getsystem:
253
            fontStructPtr = XLoadQueryFont(Tk_Display(tkwin), "fixed");
254
            if (fontStructPtr == NULL) {
255
                fontStructPtr = XLoadQueryFont(Tk_Display(tkwin), "*");
256
                if (fontStructPtr == NULL) {
257
                    panic("TkpGetFontFromAttributes: cannot get any font");
258
                }
259
            }
260
            goto end;
261
        }
262
    }
263
 
264
    /*
265
     * Inspect each of the XLFDs and pick the one that most closely
266
     * matches the desired attributes.
267
     */
268
 
269
    bestIdx = 0;
270
    bestScore = INT_MAX;
271
    bestScaleableIdx = 0;
272
    bestScaleableScore = INT_MAX;
273
 
274
    for (i = 0; i < numNames; i++) {
275
        score = 0;
276
        scaleable = 0;
277
        if (TkParseXLFD(nameList[i], &xa) != TCL_OK) {
278
            continue;
279
        }
280
        xaPixelsize = -xa.fa.pointsize;
281
 
282
        /*
283
         * Since most people used to use -adobe-* in their XLFDs,
284
         * preserve the preference for "adobe" foundry.  Otherwise
285
         * some applications looks may change slightly if another foundry
286
         * is chosen.
287
         */
288
 
289
        if (strcasecmp(xa.foundry, "adobe") != 0) {
290
            score += 3000;
291
        }
292
        if (xa.fa.pointsize == 0) {
293
            /*
294
             * A scaleable font is almost always acceptable, but the
295
             * corresponding bitmapped font would be better.
296
             */
297
 
298
            score += 10;
299
            scaleable = 1;
300
        } else {
301
            /*
302
             * A font that is too small is better than one that is too
303
             * big.
304
             */
305
 
306
            if (xaPixelsize > pixelsize) {
307
                score += (xaPixelsize - pixelsize) * 120;
308
            } else {
309
                score += (pixelsize - xaPixelsize) * 100;
310
            }
311
        }
312
 
313
        score += ABS(xa.fa.weight - faPtr->weight) * 30;
314
        score += ABS(xa.fa.slant - faPtr->slant) * 25;
315
        if (xa.slant == TK_FS_OBLIQUE) {
316
            /*
317
             * Italic fonts are preferred over oblique. */
318
 
319
            score += 4;
320
        }
321
 
322
        if (xa.setwidth != TK_SW_NORMAL) {
323
            /*
324
             * The normal setwidth is highly preferred.
325
             */
326
            score += 2000;
327
        }
328
        if (xa.charset == TK_CS_OTHER) {
329
            /*
330
             * The standard character set is highly preferred over
331
             * foreign languages charsets (because we don't support
332
             * other languages yet).
333
             */
334
            score += 11000;
335
        }
336
        if ((xa.charset == TK_CS_NORMAL) && (xa.encoding != 1)) {
337
            /*
338
             * The '1' encoding for the characters above 0x7f is highly
339
             * preferred over the other encodings.
340
             */
341
            score += 8000;
342
        }
343
 
344
        if (scaleable) {
345
            if (score < bestScaleableScore) {
346
                bestScaleableIdx = i;
347
                bestScaleableScore = score;
348
            }
349
        } else {
350
            if (score < bestScore) {
351
                bestIdx = i;
352
                bestScore = score;
353
            }
354
        }
355
        if (score == 0) {
356
            break;
357
        }
358
    }
359
 
360
    /*
361
     * Now we know which is the closest matching scaleable font and the
362
     * closest matching bitmapped font.  If the scaleable font was a
363
     * better match, try getting the scaleable font; however, if the
364
     * scalable font was not actually available in the desired
365
     * pointsize, fall back to the closest bitmapped font.
366
     */
367
 
368
    fontStructPtr = NULL;
369
    if (bestScaleableScore < bestScore) {
370
        char *str, *rest;
371
 
372
        /*
373
         * Fill in the desired pointsize info for this font.
374
         */
375
 
376
        tryscale:
377
        str = nameList[bestScaleableIdx];
378
        for (i = 0; i < XLFD_PIXEL_SIZE - 1; i++) {
379
            str = strchr(str + 1, '-');
380
        }
381
        rest = str;
382
        for (i = XLFD_PIXEL_SIZE - 1; i < XLFD_REGISTRY; i++) {
383
            rest = strchr(rest + 1, '-');
384
        }
385
        *str = '\0';
386
        sprintf(buf, "%.240s-*-%d-*-*-*-*-*%s", nameList[bestScaleableIdx],
387
                pixelsize, rest);
388
        *str = '-';
389
        fontStructPtr = XLoadQueryFont(Tk_Display(tkwin), buf);
390
        bestScaleableScore = INT_MAX;
391
    }
392
    if (fontStructPtr == NULL) {
393
        strcpy(buf, nameList[bestIdx]);
394
        fontStructPtr = XLoadQueryFont(Tk_Display(tkwin), buf);
395
        if (fontStructPtr == NULL) {
396
            /*
397
             * This shouldn't happen because the font name is one of the
398
             * names that X gave us to use, but it does anyhow.
399
             */
400
 
401
            if (bestScaleableScore < INT_MAX) {
402
                goto tryscale;
403
            } else {
404
                XFreeFontNames(nameList);
405
                goto getsystem;
406
            }
407
        }
408
    }
409
    XFreeFontNames(nameList);
410
 
411
    end:
412
    fontPtr = AllocFont(tkFontPtr, tkwin, fontStructPtr, buf);
413
    fontPtr->font.fa.underline  = faPtr->underline;
414
    fontPtr->font.fa.overstrike = faPtr->overstrike;
415
 
416
    return (TkFont *) fontPtr;
417
}
418
 
419
 
420
/*
421
 *---------------------------------------------------------------------------
422
 *
423
 * TkpDeleteFont --
424
 *
425
 *      Called to release a font allocated by TkpGetNativeFont() or
426
 *      TkpGetFontFromAttributes().  The caller should have already
427
 *      released the fields of the TkFont that are used exclusively by
428
 *      the generic TkFont code.
429
 *
430
 * Results:
431
 *      None.
432
 *
433
 * Side effects:
434
 *      TkFont is deallocated.
435
 *
436
 *---------------------------------------------------------------------------
437
 */
438
 
439
void
440
TkpDeleteFont(tkFontPtr)
441
    TkFont *tkFontPtr;          /* Token of font to be deleted. */
442
{
443
    UnixFont *fontPtr;
444
 
445
    fontPtr = (UnixFont *) tkFontPtr;
446
 
447
    XFreeFont(fontPtr->display, fontPtr->fontStructPtr);
448
    ckfree((char *) fontPtr);
449
}
450
 
451
/*
452
 *---------------------------------------------------------------------------
453
 *
454
 * TkpGetFontFamilies --
455
 *
456
 *      Return information about the font families that are available
457
 *      on the display of the given window.
458
 *
459
 * Results:
460
 *      interp->result is modified to hold a list of all the available
461
 *      font families.
462
 *
463
 * Side effects:
464
 *      None.
465
 *
466
 *---------------------------------------------------------------------------
467
 */
468
 
469
void
470
TkpGetFontFamilies(interp, tkwin)
471
    Tcl_Interp *interp;
472
    Tk_Window tkwin;
473
{
474
    int i, new, numNames;
475
    char *family, *end, *p;
476
    Tcl_HashTable familyTable;
477
    Tcl_HashEntry *hPtr;
478
    Tcl_HashSearch search;
479
    char **nameList;
480
 
481
    Tcl_InitHashTable(&familyTable, TCL_STRING_KEYS);
482
 
483
    nameList = XListFonts(Tk_Display(tkwin), "*", 10000, &numNames);
484
    for (i = 0; i < numNames; i++) {
485
        if (nameList[i][0] != '-') {
486
            continue;
487
        }
488
        family = strchr(nameList[i] + 1, '-');
489
        if (family == NULL) {
490
            continue;
491
        }
492
        family++;
493
        end = strchr(family, '-');
494
        if (end == NULL) {
495
            continue;
496
        }
497
        *end = '\0';
498
        for (p = family; *p != '\0'; p++) {
499
            if (isupper(UCHAR(*p))) {
500
                *p = tolower(UCHAR(*p));
501
            }
502
        }
503
        Tcl_CreateHashEntry(&familyTable, family, &new);
504
    }
505
 
506
    hPtr = Tcl_FirstHashEntry(&familyTable, &search);
507
    while (hPtr != NULL) {
508
        Tcl_AppendElement(interp, Tcl_GetHashKey(&familyTable, hPtr));
509
        hPtr = Tcl_NextHashEntry(&search);
510
    }
511
 
512
    Tcl_DeleteHashTable(&familyTable);
513
    XFreeFontNames(nameList);
514
}
515
 
516
/*
517
 *---------------------------------------------------------------------------
518
 *
519
 *  Tk_MeasureChars --
520
 *
521
 *      Determine the number of characters from the string that will fit
522
 *      in the given horizontal span.  The measurement is done under the
523
 *      assumption that Tk_DrawChars() will be used to actually display
524
 *      the characters.
525
 *
526
 * Results:
527
 *      The return value is the number of characters from source that
528
 *      fit into the span that extends from 0 to maxLength.  *lengthPtr is
529
 *      filled with the x-coordinate of the right edge of the last
530
 *      character that did fit.
531
 *
532
 * Side effects:
533
 *      None.
534
 *
535
 *---------------------------------------------------------------------------
536
 */
537
int
538
Tk_MeasureChars(tkfont, source, numChars, maxLength, flags, lengthPtr)
539
    Tk_Font tkfont;             /* Font in which characters will be drawn. */
540
    CONST char *source;         /* Characters to be displayed.  Need not be
541
                                 * '\0' terminated. */
542
    int numChars;               /* Maximum number of characters to consider
543
                                 * from source string. */
544
    int maxLength;              /* If > 0, maxLength specifies the longest
545
                                 * permissible line length; don't consider any
546
                                 * character that would cross this
547
                                 * x-position.  If <= 0, then line length is
548
                                 * unbounded and the flags argument is
549
                                 * ignored. */
550
    int flags;                  /* Various flag bits OR-ed together:
551
                                 * TK_PARTIAL_OK means include the last char
552
                                 * which only partially fit on this line.
553
                                 * TK_WHOLE_WORDS means stop on a word
554
                                 * boundary, if possible.
555
                                 * TK_AT_LEAST_ONE means return at least one
556
                                 * character even if no characters fit. */
557
    int *lengthPtr;             /* Filled with x-location just after the
558
                                 * terminating character. */
559
{
560
    UnixFont *fontPtr;
561
    CONST char *p;              /* Current character. */
562
    CONST char *term;           /* Pointer to most recent character that
563
                                 * may legally be a terminating character. */
564
    int termX;                  /* X-position just after term. */
565
    int curX;                   /* X-position corresponding to p. */
566
    int newX;                   /* X-position corresponding to p+1. */
567
    int c, sawNonSpace;
568
 
569
    fontPtr = (UnixFont *) tkfont;
570
 
571
    if (numChars == 0) {
572
        *lengthPtr = 0;
573
        return 0;
574
    }
575
 
576
    if (maxLength <= 0) {
577
        maxLength = INT_MAX;
578
    }
579
 
580
    newX = curX = termX = 0;
581
    p = term = source;
582
    sawNonSpace = !isspace(UCHAR(*p));
583
 
584
    /*
585
     * Scan the input string one character at a time, calculating width.
586
     */
587
 
588
    for (c = UCHAR(*p); ; ) {
589
        newX += fontPtr->widths[c];
590
        if (newX > maxLength) {
591
            break;
592
        }
593
        curX = newX;
594
        numChars--;
595
        p++;
596
        if (numChars == 0) {
597
            term = p;
598
            termX = curX;
599
            break;
600
        }
601
 
602
        c = UCHAR(*p);
603
        if (isspace(c)) {
604
            if (sawNonSpace) {
605
                term = p;
606
                termX = curX;
607
                sawNonSpace = 0;
608
            }
609
        } else {
610
            sawNonSpace = 1;
611
        }
612
    }
613
 
614
    /*
615
     * P points to the first character that doesn't fit in the desired
616
     * span.  Use the flags to figure out what to return.
617
     */
618
 
619
    if ((flags & TK_PARTIAL_OK) && (numChars > 0) && (curX < maxLength)) {
620
        /*
621
         * Include the first character that didn't quite fit in the desired
622
         * span.  The width returned will include the width of that extra
623
         * character.
624
         */
625
 
626
        numChars--;
627
        curX = newX;
628
        p++;
629
    }
630
    if ((flags & TK_AT_LEAST_ONE) && (term == source) && (numChars > 0)) {
631
        term = p;
632
        termX = curX;
633
        if (term == source) {
634
            term++;
635
            termX = newX;
636
        }
637
    } else if ((numChars == 0) || !(flags & TK_WHOLE_WORDS)) {
638
        term = p;
639
        termX = curX;
640
    }
641
 
642
    *lengthPtr = termX;
643
    return term-source;
644
}
645
 
646
/*
647
 *---------------------------------------------------------------------------
648
 *
649
 * Tk_DrawChars, DrawChars --
650
 *
651
 *      Draw a string of characters on the screen.  Tk_DrawChars()
652
 *      expands control characters that occur in the string to \X or
653
 *      \xXX sequences.  DrawChars() just draws the strings.
654
 *
655
 * Results:
656
 *      None.
657
 *
658
 * Side effects:
659
 *      Information gets drawn on the screen.
660
 *
661
 *---------------------------------------------------------------------------
662
 */
663
 
664
void
665
Tk_DrawChars(display, drawable, gc, tkfont, source, numChars, x, y)
666
    Display *display;           /* Display on which to draw. */
667
    Drawable drawable;          /* Window or pixmap in which to draw. */
668
    GC gc;                      /* Graphics context for drawing characters. */
669
    Tk_Font tkfont;             /* Font in which characters will be drawn;
670
                                 * must be the same as font used in GC. */
671
    CONST char *source;         /* Characters to be displayed.  Need not be
672
                                 * '\0' terminated.  All Tk meta-characters
673
                                 * (tabs, control characters, and newlines)
674
                                 * should be stripped out of the string that
675
                                 * is passed to this function.  If they are
676
                                 * not stripped out, they will be displayed as
677
                                 * regular printing characters. */
678
    int numChars;               /* Number of characters in string. */
679
    int x, y;                   /* Coordinates at which to place origin of
680
                                 * string when drawing. */
681
{
682
    UnixFont *fontPtr;
683
    CONST char *p;
684
    int i, type;
685
    char buf[4];
686
 
687
    fontPtr = (UnixFont *) tkfont;
688
 
689
    p = source;
690
    for (i = 0; i < numChars; i++) {
691
        type = fontPtr->types[UCHAR(*p)];
692
        if (type != NORMAL) {
693
            DrawChars(display, drawable, gc, fontPtr, source, p - source, x, y);
694
            x += XTextWidth(fontPtr->fontStructPtr, source, p - source);
695
            if (type == REPLACE) {
696
                DrawChars(display, drawable, gc, fontPtr, buf,
697
                        GetControlCharSubst(UCHAR(*p), buf), x, y);
698
                x += fontPtr->widths[UCHAR(*p)];
699
            }
700
            source = p + 1;
701
        }
702
        p++;
703
    }
704
 
705
    DrawChars(display, drawable, gc, fontPtr, source, p - source, x, y);
706
}
707
 
708
static void
709
DrawChars(display, drawable, gc, fontPtr, source, numChars, x, y)
710
    Display *display;           /* Display on which to draw. */
711
    Drawable drawable;          /* Window or pixmap in which to draw. */
712
    GC gc;                      /* Graphics context for drawing characters. */
713
    UnixFont *fontPtr;          /* Font in which characters will be drawn;
714
                                 * must be the same as font used in GC. */
715
    CONST char *source;         /* Characters to be displayed.  Need not be
716
                                 * '\0' terminated.  All Tk meta-characters
717
                                 * (tabs, control characters, and newlines)
718
                                 * should be stripped out of the string that
719
                                 * is passed to this function.  If they are
720
                                 * not stripped out, they will be displayed as
721
                                 * regular printing characters. */
722
    int numChars;               /* Number of characters in string. */
723
    int x, y;                   /* Coordinates at which to place origin of
724
                                 * string when drawing. */
725
{
726
    /*
727
     * Perform a quick sanity check to ensure we won't overflow the X
728
     * coordinate space.
729
     */
730
 
731
    if ((x + (fontPtr->fontStructPtr->max_bounds.width * numChars) > 0x7fff)) {
732
        int length;
733
 
734
        /*
735
         * The string we are being asked to draw is too big and would overflow
736
         * the X coordinate space.  Unfortunatley X servers aren't too bright
737
         * and so they won't deal with this case cleanly.  We need to truncate
738
         * the string before sending it to X.
739
         */
740
 
741
        numChars = Tk_MeasureChars((Tk_Font) fontPtr, source, numChars,
742
                0x7fff - x, 0, &length);
743
    }
744
 
745
    XDrawString(display, drawable, gc, x, y, source, numChars);
746
 
747
    if (fontPtr->font.fa.underline != 0) {
748
        XFillRectangle(display, drawable, gc, x,
749
                y + fontPtr->underlinePos,
750
                (unsigned) XTextWidth(fontPtr->fontStructPtr, source, numChars),
751
                (unsigned) fontPtr->barHeight);
752
    }
753
    if (fontPtr->font.fa.overstrike != 0) {
754
        y -= fontPtr->font.fm.descent + (fontPtr->font.fm.ascent) / 10;
755
        XFillRectangle(display, drawable, gc, x, y,
756
                (unsigned) XTextWidth(fontPtr->fontStructPtr, source, numChars),
757
                (unsigned) fontPtr->barHeight);
758
    }
759
}
760
 
761
/*
762
 *---------------------------------------------------------------------------
763
 *
764
 * AllocFont --
765
 *
766
 *      Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
767
 *      Allocates and intializes the memory for a new TkFont that
768
 *      wraps the platform-specific data.
769
 *
770
 * Results:
771
 *      Returns pointer to newly constructed TkFont.
772
 *
773
 *      The caller is responsible for initializing the fields of the
774
 *      TkFont that are used exclusively by the generic TkFont code, and
775
 *      for releasing those fields before calling TkpDeleteFont().
776
 *
777
 * Side effects:
778
 *      Memory allocated.
779
 *
780
 *---------------------------------------------------------------------------
781
 */
782
 
783
static UnixFont *
784
AllocFont(tkFontPtr, tkwin, fontStructPtr, fontName)
785
    TkFont *tkFontPtr;          /* If non-NULL, store the information in
786
                                 * this existing TkFont structure, rather than
787
                                 * allocating a new structure to hold the
788
                                 * font; the existing contents of the font
789
                                 * will be released.  If NULL, a new TkFont
790
                                 * structure is allocated. */
791
    Tk_Window tkwin;            /* For display where font will be used. */
792
    XFontStruct *fontStructPtr; /* X information about font. */
793
    CONST char *fontName;       /* The string passed to XLoadQueryFont() to
794
                                 * construct the fontStructPtr. */
795
{
796
    UnixFont *fontPtr;
797
    unsigned long value;
798
    int i, width, firstChar, lastChar, n, replaceOK;
799
    char *name, *p;
800
    char buf[4];
801
    TkXLFDAttributes xa;
802
    double d;
803
 
804
    if (tkFontPtr != NULL) {
805
        fontPtr = (UnixFont *) tkFontPtr;
806
        XFreeFont(fontPtr->display, fontPtr->fontStructPtr);
807
    } else {
808
        fontPtr = (UnixFont *) ckalloc(sizeof(UnixFont));
809
    }
810
 
811
    /*
812
     * Encapsulate the generic stuff in the TkFont.
813
     */
814
 
815
    fontPtr->font.fid           = fontStructPtr->fid;
816
 
817
    if (XGetFontProperty(fontStructPtr, XA_FONT, &value) && (value != 0)) {
818
        name = Tk_GetAtomName(tkwin, (Atom) value);
819
        TkInitFontAttributes(&xa.fa);
820
        if (TkParseXLFD(name, &xa) == TCL_OK) {
821
            goto ok;
822
        }
823
    }
824
    TkInitFontAttributes(&xa.fa);
825
    if (TkParseXLFD(fontName, &xa) != TCL_OK) {
826
        TkInitFontAttributes(&fontPtr->font.fa);
827
        fontPtr->font.fa.family = Tk_GetUid(fontName);
828
    } else {
829
        ok:
830
        fontPtr->font.fa = xa.fa;
831
    }
832
 
833
    if (fontPtr->font.fa.pointsize < 0) {
834
        d = -fontPtr->font.fa.pointsize * 72 / 25.4;
835
        d *= WidthMMOfScreen(Tk_Screen(tkwin));
836
        d /= WidthOfScreen(Tk_Screen(tkwin));
837
        d += 0.5;
838
        fontPtr->font.fa.pointsize = (int) d;
839
    }
840
 
841
    fontPtr->font.fm.ascent     = fontStructPtr->ascent;
842
    fontPtr->font.fm.descent    = fontStructPtr->descent;
843
    fontPtr->font.fm.maxWidth   = fontStructPtr->max_bounds.width;
844
    fontPtr->font.fm.fixed      = 1;
845
    fontPtr->display            = Tk_Display(tkwin);
846
    fontPtr->fontStructPtr      = fontStructPtr;
847
 
848
    /*
849
     * Classify the characters.
850
     */
851
 
852
    firstChar = fontStructPtr->min_char_or_byte2;
853
    lastChar = fontStructPtr->max_char_or_byte2;
854
    for (i = 0; i < 256; i++) {
855
        if ((i == 0177) || (i < firstChar) || (i > lastChar)) {
856
            fontPtr->types[i] = REPLACE;
857
        } else {
858
            fontPtr->types[i] = NORMAL;
859
        }
860
    }
861
 
862
    /*
863
     * Compute the widths for all the normal characters.  Any other
864
     * characters are given an initial width of 0.  Also, this determines
865
     * if this is a fixed or variable width font, by comparing the widths
866
     * of all the normal characters.
867
     */
868
 
869
    width = 0;
870
    for (i = 0; i < 256; i++) {
871
        if (fontPtr->types[i] != NORMAL) {
872
            n = 0;
873
        } else if (fontStructPtr->per_char == NULL) {
874
            n = fontStructPtr->max_bounds.width;
875
        } else {
876
            n = fontStructPtr->per_char[i - firstChar].width;
877
        }
878
        fontPtr->widths[i] = n;
879
        if (n != 0) {
880
            if (width == 0) {
881
                width = n;
882
            } else if (width != n) {
883
                fontPtr->font.fm.fixed = 0;
884
            }
885
        }
886
    }
887
 
888
    /*
889
     * Compute the widths of the characters that should be replaced with
890
     * control character expansions.  If the appropriate chars are not
891
     * available in this font, then control character expansions will not
892
     * be used; control chars will be invisible & zero-width.
893
     */
894
 
895
    replaceOK = 1;
896
    for (p = hexChars; *p != '\0'; p++) {
897
        if ((UCHAR(*p) < firstChar) || (UCHAR(*p) > lastChar)) {
898
            replaceOK = 0;
899
            break;
900
        }
901
    }
902
    for (i = 0; i < 256; i++) {
903
        if (fontPtr->types[i] == REPLACE) {
904
            if (replaceOK) {
905
                n = GetControlCharSubst(i, buf);
906
                for ( ; --n >= 0; ) {
907
                    fontPtr->widths[i] += fontPtr->widths[UCHAR(buf[n])];
908
                }
909
            } else {
910
                fontPtr->types[i] = SKIP;
911
            }
912
        }
913
    }
914
 
915
    if (XGetFontProperty(fontStructPtr, XA_UNDERLINE_POSITION, &value)) {
916
        fontPtr->underlinePos = value;
917
    } else {
918
        /*
919
         * If the XA_UNDERLINE_POSITION property does not exist, the X
920
         * manual recommends using the following value:
921
         */
922
 
923
        fontPtr->underlinePos = fontStructPtr->descent / 2;
924
    }
925
    fontPtr->barHeight = 0;
926
    if (XGetFontProperty(fontStructPtr, XA_UNDERLINE_THICKNESS, &value)) {
927
        /*
928
         * Sometimes this is 0 even though it shouldn't be.
929
         */
930
        fontPtr->barHeight = value;
931
    }
932
    if (fontPtr->barHeight == 0) {
933
        /*
934
         * If the XA_UNDERLINE_THICKNESS property does not exist, the X
935
         * manual recommends using the width of the stem on a capital
936
         * letter.  I don't know of a way to get the stem width of a letter,
937
         * so guess and use 1/3 the width of a capital I.
938
         */
939
 
940
        fontPtr->barHeight = fontPtr->widths['I'] / 3;
941
        if (fontPtr->barHeight == 0) {
942
            fontPtr->barHeight = 1;
943
        }
944
    }
945
    if (fontPtr->underlinePos + fontPtr->barHeight > fontStructPtr->descent) {
946
        /*
947
         * If this set of cobbled together values would cause the bottom of
948
         * the underline bar to stick below the descent of the font, jack
949
         * the underline up a bit higher.
950
         */
951
 
952
        fontPtr->barHeight = fontStructPtr->descent - fontPtr->underlinePos;
953
        if (fontPtr->barHeight == 0) {
954
            fontPtr->underlinePos--;
955
            fontPtr->barHeight = 1;
956
        }
957
    }
958
 
959
    return fontPtr;
960
}
961
 
962
/*
963
 *---------------------------------------------------------------------------
964
 *
965
 * GetControlCharSubst --
966
 *
967
 *      When displaying text in a widget, a backslashed escape sequence
968
 *      is substituted for control characters that occur in the text.
969
 *      Given a control character, fill in a buffer with the replacement
970
 *      string that should be displayed.
971
 *
972
 * Results:
973
 *      The return value is the length of the substitute string.  buf is
974
 *      filled with the substitute string; it is not '\0' terminated.
975
 *
976
 * Side effects:
977
 *      None.
978
 *
979
 *---------------------------------------------------------------------------
980
 */
981
 
982
static int
983
GetControlCharSubst(c, buf)
984
    int         c;              /* The control character to be replaced. */
985
    char        buf[4];         /* Buffer that gets replacement string.  It
986
                                 * only needs to be 4 characters long. */
987
{
988
    buf[0] = '\\';
989
    if ((c < sizeof(mapChars)) && (mapChars[c] != 0)) {
990
        buf[1] = mapChars[c];
991
        return 2;
992
    } else {
993
        buf[1] = 'x';
994
        buf[2] = hexChars[(c >> 4) & 0xf];
995
        buf[3] = hexChars[c & 0xf];
996
        return 4;
997
    }
998
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.