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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [mac/] [tkMacFont.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkMacFont.c --
3
 *
4
 *      Contains the Macintosh implementation of the platform-independant
5
 *      font package interface.
6
 *
7
 * Copyright (c) 1990-1994 The Regents of the University of California.
8
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 *
13
 * RCS: @(#) $Id: tkMacFont.c,v 1.1.1.1 2002-01-16 10:25:55 markom Exp $
14
 */
15
 
16
#include <Windows.h>
17
#include <Strings.h>
18
#include <Fonts.h>
19
#include <Resources.h>
20
 
21
#include "tkMacInt.h"
22
#include "tkFont.h"
23
#include "tkPort.h"
24
 
25
/*
26
 * The following structure represents the Macintosh's' implementation of a
27
 * font.
28
 */
29
 
30
typedef struct MacFont {
31
    TkFont font;                /* Stuff used by generic font package.  Must
32
                                 * be first in structure. */
33
    short family;
34
    short size;
35
    short style;
36
} MacFont;
37
 
38
static GWorldPtr gWorld = NULL;
39
 
40
static TkFont *         AllocMacFont _ANSI_ARGS_((TkFont *tkfont,
41
                            Tk_Window tkwin, int family, int size, int style));
42
 
43
 
44
/*
45
 *---------------------------------------------------------------------------
46
 *
47
 * TkpGetNativeFont --
48
 *
49
 *      Map a platform-specific native font name to a TkFont.
50
 *
51
 * Results:
52
 *      The return value is a pointer to a TkFont that represents the
53
 *      native font.  If a native font by the given name could not be
54
 *      found, the return value is NULL.
55
 *
56
 *      Every call to this procedure returns a new TkFont structure,
57
 *      even if the name has already been seen before.  The caller should
58
 *      call TkpDeleteFont() when the font is no longer needed.
59
 *
60
 *      The caller is responsible for initializing the memory associated
61
 *      with the generic TkFont when this function returns and releasing
62
 *      the contents of the generics TkFont before calling TkpDeleteFont().
63
 *
64
 * Side effects:
65
 *      None.
66
 *
67
 *---------------------------------------------------------------------------
68
 */
69
 
70
TkFont *
71
TkpGetNativeFont(
72
    Tk_Window tkwin,    /* For display where font will be used. */
73
    CONST char *name)   /* Platform-specific font name. */
74
{
75
    short family;
76
 
77
    if (strcmp(name, "system") == 0) {
78
        family = GetSysFont();
79
    } else if (strcmp(name, "application") == 0) {
80
        family = GetAppFont();
81
    } else {
82
        return NULL;
83
    }
84
 
85
    return AllocMacFont(NULL, tkwin, family, 0, 0);
86
}
87
 
88
/*
89
 *---------------------------------------------------------------------------
90
 *
91
 * TkpGetFontFromAttributes --
92
 *
93
 *      Given a desired set of attributes for a font, find a font with
94
 *      the closest matching attributes.
95
 *
96
 * Results:
97
 *      The return value is a pointer to a TkFont that represents the
98
 *      font with the desired attributes.  If a font with the desired
99
 *      attributes could not be constructed, some other font will be
100
 *      substituted automatically.
101
 *
102
 *      Every call to this procedure returns a new TkFont structure,
103
 *      even if the specified attributes have already been seen before.
104
 *      The caller should call TkpDeleteFont() to free the platform-
105
 *      specific data when the font is no longer needed.
106
 *
107
 *      The caller is responsible for initializing the memory associated
108
 *      with the generic TkFont when this function returns and releasing
109
 *      the contents of the generic TkFont before calling TkpDeleteFont().
110
 *
111
 * Side effects:
112
 *      None.
113
 *
114
 *---------------------------------------------------------------------------
115
 */
116
TkFont *
117
TkpGetFontFromAttributes(
118
    TkFont *tkFontPtr,          /* If non-NULL, store the information in
119
                                 * this existing TkFont structure, rather than
120
                                 * allocating a new structure to hold the
121
                                 * font; the existing contents of the font
122
                                 * will be released.  If NULL, a new TkFont
123
                                 * structure is allocated. */
124
    Tk_Window tkwin,            /* For display where font will be used. */
125
    CONST TkFontAttributes *faPtr)  /* Set of attributes to match. */
126
{
127
    char buf[257];
128
    size_t len;
129
    short family, size, style;
130
 
131
    if (faPtr->family == NULL) {
132
        family = 0;
133
    } else {
134
        CONST char *familyName;
135
 
136
        familyName = faPtr->family;
137
        if (strcasecmp(familyName, "Times New Roman") == 0) {
138
            familyName = "Times";
139
        } else if (strcasecmp(familyName, "Courier New") == 0) {
140
            familyName = "Courier";
141
        } else if (strcasecmp(familyName, "Arial") == 0) {
142
            familyName = "Helvetica";
143
        }
144
 
145
        len = strlen(familyName);
146
        if (len > 255) {
147
            len = 255;
148
        }
149
        buf[0] = (char) len;
150
        memcpy(buf + 1, familyName, len);
151
        buf[len + 1] = '\0';
152
        GetFNum((StringPtr) buf, &family);
153
    }
154
 
155
    size = faPtr->pointsize;
156
    if (size <= 0) {
157
        size = GetDefFontSize();
158
    }
159
 
160
    style = 0;
161
    if (faPtr->weight != TK_FW_NORMAL) {
162
        style |= bold;
163
    }
164
    if (faPtr->slant != TK_FS_ROMAN) {
165
        style |= italic;
166
    }
167
    if (faPtr->underline) {
168
        style |= underline;
169
    }
170
 
171
    return AllocMacFont(tkFontPtr, tkwin, family, size, style);
172
}
173
 
174
/*
175
 *---------------------------------------------------------------------------
176
 *
177
 * TkpDeleteFont --
178
 *
179
 *      Called to release a font allocated by TkpGetNativeFont() or
180
 *      TkpGetFontFromAttributes().  The caller should have already
181
 *      released the fields of the TkFont that are used exclusively by
182
 *      the generic TkFont code.
183
 *
184
 * Results:
185
 *      None.
186
 *
187
 * Side effects:
188
 *      TkFont is deallocated.
189
 *
190
 *---------------------------------------------------------------------------
191
 */
192
 
193
void
194
TkpDeleteFont(
195
    TkFont *tkFontPtr)          /* Token of font to be deleted. */
196
{
197
    ckfree((char *) tkFontPtr);
198
}
199
 
200
/*
201
 *---------------------------------------------------------------------------
202
 *
203
 * TkpGetFontFamilies --
204
 *
205
 *      Return information about the font families that are available
206
 *      on the display of the given window.
207
 *
208
 * Results:
209
 *      interp->result is modified to hold a list of all the available
210
 *      font families.
211
 *
212
 * Side effects:
213
 *      None.
214
 *
215
 *---------------------------------------------------------------------------
216
 */
217
 
218
void
219
TkpGetFontFamilies(
220
    Tcl_Interp *interp,         /* Interp to hold result. */
221
    Tk_Window tkwin)            /* For display to query. */
222
{
223
    MenuHandle fontMenu;
224
    int i;
225
    char itemText[257];
226
 
227
    fontMenu = NewMenu(1, "\px");
228
    AddResMenu(fontMenu, 'FONT');
229
 
230
    for (i = 1; i < CountMItems(fontMenu); i++) {
231
        /*
232
         * Each item is a pascal string. Convert it to C and append.
233
         */
234
        GetMenuItemText(fontMenu, i, (unsigned char *) itemText);
235
        itemText[itemText[0] + 1] = '\0';
236
        Tcl_AppendElement(interp, &itemText[1]);
237
    }
238
    DisposeMenu(fontMenu);
239
}
240
 
241
 
242
/*
243
 *---------------------------------------------------------------------------
244
 *
245
 * TkMacIsCharacterMissing --
246
 *
247
 *      Given a tkFont and a character determines whether the character has
248
 *      a glyph defined in the font or not. Note that this is potentially
249
 *      not compatible with Mac OS 8 as it looks at the font handle
250
 *      structure directly. Looks into the character array of the font
251
 *      handle to determine whether the glyph is defined or not.
252
 *
253
 * Results:
254
 *      Returns a 1 if the character is missing, a 0 if it is not.
255
 *
256
 * Side effects:
257
 *      None.
258
 *
259
 *---------------------------------------------------------------------------
260
 */
261
 
262
int
263
TkMacIsCharacterMissing(
264
    Tk_Font tkfont,             /* The font we are looking in. */
265
    unsigned int searchChar)    /* The character we are looking for. */
266
{
267
    MacFont *fontPtr = (MacFont *) tkfont;
268
    FMInput fm;
269
    FontRec **fontRecHandle;
270
 
271
    fm.family = fontPtr->family;
272
    fm.size = fontPtr->size;
273
    fm.face = fontPtr->style;
274
    fm.needBits = 0;
275
    fm.device = 0;
276
    fm.numer.h = fm.numer.v = fm.denom.h = fm.denom.v = 1;
277
 
278
    /*
279
     * This element of the FMOutput structure was changed between the 2.0 & 3.0
280
     * versions of the Universal Headers.
281
     */
282
 
283
#if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300)
284
    fontRecHandle = (FontRec **) FMSwapFont(&fm)->fontResult;
285
#else
286
    fontRecHandle = (FontRec **) FMSwapFont(&fm)->fontHandle;
287
#endif
288
    return *(short *) ((long) &(*fontRecHandle)->owTLoc
289
            + ((long)((*fontRecHandle)->owTLoc + searchChar
290
            - (*fontRecHandle)->firstChar) * sizeof(short))) == -1;
291
}
292
 
293
 
294
/*
295
 *---------------------------------------------------------------------------
296
 *
297
 *  Tk_MeasureChars --
298
 *
299
 *      Determine the number of characters from the string that will fit
300
 *      in the given horizontal span.  The measurement is done under the
301
 *      assumption that Tk_DrawChars() will be used to actually display
302
 *      the characters.
303
 *
304
 * Results:
305
 *      The return value is the number of characters from source that
306
 *      fit into the span that extends from 0 to maxLength.  *lengthPtr is
307
 *      filled with the x-coordinate of the right edge of the last
308
 *      character that did fit.
309
 *
310
 * Side effects:
311
 *      None.
312
 *
313
 *---------------------------------------------------------------------------
314
 */
315
 
316
int
317
Tk_MeasureChars(
318
    Tk_Font tkfont,             /* Font in which characters will be drawn. */
319
    CONST char *source,         /* Characters to be displayed.  Need not be
320
                                 * '\0' terminated. */
321
    int numChars,               /* Maximum number of characters to consider
322
                                 * from source string. */
323
    int maxLength,              /* If > 0, maxLength specifies the longest
324
                                 * permissible line length; don't consider any
325
                                 * character that would cross this
326
                                 * x-position.  If <= 0, then line length is
327
                                 * unbounded and the flags argument is
328
                                 * ignored. */
329
    int flags,                  /* Various flag bits OR-ed together:
330
                                 * TK_PARTIAL_OK means include the last char
331
                                 * which only partially fit on this line.
332
                                 * TK_WHOLE_WORDS means stop on a word
333
                                 * boundary, if possible.
334
                                 * TK_AT_LEAST_ONE means return at least one
335
                                 * character even if no characters fit. */
336
    int *lengthPtr)             /* Filled with x-location just after the
337
                                 * terminating character. */
338
{
339
    short staticWidths[128];
340
    short *widths;
341
    CONST char *p, *term;
342
    int curX, termX, curIdx, sawNonSpace;
343
    MacFont *fontPtr;
344
    CGrafPtr saveWorld;
345
    GDHandle saveDevice;
346
 
347
    if (numChars == 0) {
348
        *lengthPtr = 0;
349
        return 0;
350
    }
351
 
352
    if (gWorld == NULL) {
353
        Rect rect = {0, 0, 1, 1};
354
 
355
        if (NewGWorld(&gWorld, 0, &rect, NULL, NULL, 0) != noErr) {
356
            panic("NewGWorld failed in Tk_MeasureChars");
357
        }
358
    }
359
    GetGWorld(&saveWorld, &saveDevice);
360
    SetGWorld(gWorld, NULL);
361
 
362
    fontPtr = (MacFont *) tkfont;
363
    TextFont(fontPtr->family);
364
    TextSize(fontPtr->size);
365
    TextFace(fontPtr->style);
366
 
367
    if (maxLength <= 0) {
368
        *lengthPtr = TextWidth(source, 0, numChars);
369
        SetGWorld(saveWorld, saveDevice);
370
        return numChars;
371
    }
372
 
373
    if (numChars > maxLength) {
374
        /*
375
         * Assume that all chars are at least 1 pixel wide, so there's no
376
         * need to measure more characters than there are pixels.  This
377
         * assumption could be refined to an iterative approach that would
378
         * use that as a starting point and try more chars if necessary (if
379
         * there actually were some zero-width chars).
380
         */
381
 
382
        numChars = maxLength;
383
    }
384
    if (numChars > SHRT_MAX) {
385
        /*
386
         * If they are trying to measure more than 32767 chars at one time,
387
         * it would require several separate measurements.
388
         */
389
 
390
        numChars = SHRT_MAX;
391
    }
392
 
393
    widths = staticWidths;
394
    if (numChars >= sizeof(staticWidths) / sizeof(staticWidths[0])) {
395
        widths = (short *) ckalloc((numChars + 1) * sizeof(short));
396
    }
397
 
398
    MeasureText((short) numChars, source, widths);
399
 
400
    if (widths[numChars] <= maxLength) {
401
        curX = widths[numChars];
402
        curIdx = numChars;
403
    } else {
404
        p = term = source;
405
        curX = termX = 0;
406
 
407
        sawNonSpace = !isspace(UCHAR(*p));
408
        for (curIdx = 1; ; curIdx++) {
409
            if (isspace(UCHAR(*p))) {
410
                if (sawNonSpace) {
411
                    term = p;
412
                    termX = widths[curIdx - 1];
413
                    sawNonSpace = 0;
414
                }
415
            } else {
416
                sawNonSpace = 1;
417
            }
418
            if (widths[curIdx] > maxLength) {
419
                curIdx--;
420
                curX = widths[curIdx];
421
                break;
422
            }
423
            p++;
424
        }
425
        if (flags & TK_PARTIAL_OK) {
426
            curIdx++;
427
            curX = widths[curIdx];
428
        }
429
        if ((curIdx == 0) && (flags & TK_AT_LEAST_ONE)) {
430
            /*
431
             * The space was too small to hold even one character.  Since at
432
             * least one character must always fit on a line, return the width
433
             * of the first character.
434
             */
435
 
436
            curX = TextWidth(source, 0, 1);
437
            curIdx = 1;
438
        } else if (flags & TK_WHOLE_WORDS) {
439
            /*
440
             * Break at last word that fits on the line.
441
             */
442
 
443
            if ((flags & TK_AT_LEAST_ONE) && (term == source)) {
444
                /*
445
                 * The space was too small to hold an entire word.  This
446
                 * is the only word on the line, so just return the part of th
447
                 * word that fit.
448
                 */
449
 
450
                 ;
451
            } else {
452
                curIdx = term - source;
453
                curX = termX;
454
            }
455
        }
456
    }
457
 
458
    if (widths != staticWidths) {
459
        ckfree((char *) widths);
460
    }
461
 
462
    *lengthPtr = curX;
463
 
464
    SetGWorld(saveWorld, saveDevice);
465
 
466
    return curIdx;
467
}
468
 
469
/*
470
 *---------------------------------------------------------------------------
471
 *
472
 * Tk_DrawChars --
473
 *
474
 *      Draw a string of characters on the screen.
475
 *
476
 * Results:
477
 *      None.
478
 *
479
 * Side effects:
480
 *      Information gets drawn on the screen.
481
 *
482
 *---------------------------------------------------------------------------
483
 */
484
 
485
void
486
Tk_DrawChars(
487
    Display *display,           /* Display on which to draw. */
488
    Drawable drawable,          /* Window or pixmap in which to draw. */
489
    GC gc,                      /* Graphics context for drawing characters. */
490
    Tk_Font tkfont,             /* Font in which characters will be drawn;
491
                                 * must be the same as font used in GC. */
492
    CONST char *source,         /* Characters to be displayed.  Need not be
493
                                 * '\0' terminated.  All Tk meta-characters
494
                                 * (tabs, control characters, and newlines)
495
                                 * should be stripped out of the string that
496
                                 * is passed to this function.  If they are
497
                                 * not stripped out, they will be displayed as
498
                                 * regular printing characters. */
499
    int numChars,               /* Number of characters in string. */
500
    int x, int y)               /* Coordinates at which to place origin of
501
                                 * string when drawing. */
502
{
503
    MacFont *fontPtr;
504
    MacDrawable *macWin;
505
    RGBColor macColor, origColor;
506
    GWorldPtr destPort;
507
    CGrafPtr saveWorld;
508
    GDHandle saveDevice;
509
    short txFont, txFace, txSize;
510
    BitMapPtr stippleMap;
511
 
512
    fontPtr = (MacFont *) tkfont;
513
    macWin = (MacDrawable *) drawable;
514
 
515
    destPort = TkMacGetDrawablePort(drawable);
516
    GetGWorld(&saveWorld, &saveDevice);
517
    SetGWorld(destPort, NULL);
518
 
519
    TkMacSetUpClippingRgn(drawable);
520
    TkMacSetUpGraphicsPort(gc);
521
 
522
    txFont = tcl_macQdPtr->thePort->txFont;
523
    txFace = tcl_macQdPtr->thePort->txFace;
524
    txSize = tcl_macQdPtr->thePort->txSize;
525
    GetForeColor(&origColor);
526
 
527
    if ((gc->fill_style == FillStippled
528
            || gc->fill_style == FillOpaqueStippled)
529
            && gc->stipple != None) {
530
        Pixmap pixmap;
531
        GWorldPtr bufferPort;
532
 
533
        stippleMap = TkMacMakeStippleMap(drawable, gc->stipple);
534
 
535
        pixmap = Tk_GetPixmap(display, drawable,
536
                stippleMap->bounds.right, stippleMap->bounds.bottom, 0);
537
 
538
        bufferPort = TkMacGetDrawablePort(pixmap);
539
        SetGWorld(bufferPort, NULL);
540
 
541
        TextFont(fontPtr->family);
542
        TextSize(fontPtr->size);
543
        TextFace(fontPtr->style);
544
 
545
        if (TkSetMacColor(gc->foreground, &macColor) == true) {
546
            RGBForeColor(&macColor);
547
        }
548
 
549
        ShowPen();
550
        MoveTo((short) 0, (short) 0);
551
        FillRect(&stippleMap->bounds, &tcl_macQdPtr->white);
552
        MoveTo((short) x, (short) y);
553
        DrawText(source, 0, (short) numChars);
554
 
555
        SetGWorld(destPort, NULL);
556
        CopyDeepMask(&((GrafPtr) bufferPort)->portBits, stippleMap,
557
                &((GrafPtr) destPort)->portBits, &stippleMap->bounds,
558
                &stippleMap->bounds, &((GrafPtr) destPort)->portRect,
559
                srcOr, NULL);
560
 
561
        /* TODO: this doesn't work quite right - it does a blend.   you can't
562
         * draw white text when you have a stipple.
563
         */
564
 
565
        Tk_FreePixmap(display, pixmap);
566
        ckfree(stippleMap->baseAddr);
567
        ckfree((char *)stippleMap);
568
    } else {
569
        TextFont(fontPtr->family);
570
        TextSize(fontPtr->size);
571
        TextFace(fontPtr->style);
572
 
573
        if (TkSetMacColor(gc->foreground, &macColor) == true) {
574
            RGBForeColor(&macColor);
575
        }
576
 
577
        ShowPen();
578
        MoveTo((short) (macWin->xOff + x), (short) (macWin->yOff + y));
579
        DrawText(source, 0, (short) numChars);
580
    }
581
 
582
    TextFont(txFont);
583
    TextSize(txSize);
584
    TextFace(txFace);
585
    RGBForeColor(&origColor);
586
    SetGWorld(saveWorld, saveDevice);
587
}
588
 
589
/*
590
 *---------------------------------------------------------------------------
591
 *
592
 * AllocMacFont --
593
 *
594
 *      Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
595
 *      Allocates and intializes the memory for a new TkFont that
596
 *      wraps the platform-specific data.
597
 *
598
 * Results:
599
 *      Returns pointer to newly constructed TkFont.
600
 *
601
 *      The caller is responsible for initializing the fields of the
602
 *      TkFont that are used exclusively by the generic TkFont code, and
603
 *      for releasing those fields before calling TkpDeleteFont().
604
 *
605
 * Side effects:
606
 *      Memory allocated.
607
 *
608
 *---------------------------------------------------------------------------
609
 */
610
 
611
static TkFont *
612
AllocMacFont(
613
    TkFont *tkFontPtr,          /* If non-NULL, store the information in
614
                                 * this existing TkFont structure, rather than
615
                                 * allocating a new structure to hold the
616
                                 * font; the existing contents of the font
617
                                 * will be released.  If NULL, a new TkFont
618
                                 * structure is allocated. */
619
    Tk_Window tkwin,            /* For display where font will be used. */
620
    int family,                 /* Macintosh font family. */
621
    int size,                   /* Point size for Macintosh font. */
622
    int style)                  /* Macintosh style bits. */
623
{
624
    char buf[257];
625
    FontInfo fi;
626
    MacFont *fontPtr;
627
    TkFontAttributes *faPtr;
628
    TkFontMetrics *fmPtr;
629
    CGrafPtr saveWorld;
630
    GDHandle saveDevice;
631
 
632
    if (gWorld == NULL) {
633
        Rect rect = {0, 0, 1, 1};
634
 
635
        if (NewGWorld(&gWorld, 0, &rect, NULL, NULL, 0) != noErr) {
636
            panic("NewGWorld failed in AllocMacFont");
637
        }
638
    }
639
    GetGWorld(&saveWorld, &saveDevice);
640
    SetGWorld(gWorld, NULL);
641
 
642
    if (tkFontPtr == NULL) {
643
        fontPtr = (MacFont *) ckalloc(sizeof(MacFont));
644
    } else {
645
        fontPtr = (MacFont *) tkFontPtr;
646
    }
647
 
648
    fontPtr->font.fid   = (Font) fontPtr;
649
 
650
    faPtr = &fontPtr->font.fa;
651
    GetFontName(family, (StringPtr) buf);
652
    buf[UCHAR(buf[0]) + 1] = '\0';
653
    faPtr->family       = Tk_GetUid(buf + 1);
654
    faPtr->pointsize    = size;
655
    faPtr->weight       = (style & bold) ? TK_FW_BOLD : TK_FW_NORMAL;
656
    faPtr->slant        = (style & italic) ? TK_FS_ITALIC : TK_FS_ROMAN;
657
    faPtr->underline    = ((style & underline) != 0);
658
    faPtr->overstrike   = 0;
659
 
660
    fmPtr = &fontPtr->font.fm;
661
    TextFont(family);
662
    TextSize(size);
663
    TextFace(style);
664
    GetFontInfo(&fi);
665
    fmPtr->ascent       = fi.ascent;
666
    fmPtr->descent      = fi.descent;
667
    fmPtr->maxWidth     = fi.widMax;
668
    fmPtr->fixed        = (CharWidth('i') == CharWidth('w'));
669
 
670
    fontPtr->family     = (short) family;
671
    fontPtr->size       = (short) size;
672
    fontPtr->style      = (short) style;
673
 
674
    SetGWorld(saveWorld, saveDevice);
675
 
676
    return (TkFont *) fontPtr;
677
}
678
 

powered by: WebSVN 2.1.0

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