~ubuntu-branches/ubuntu/lucid/perl-tk/lucid

« back to all changes in this revision

Viewing changes to pTk/mTk/unix/tkUnixXft.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Tuckley
  • Date: 2008-02-15 13:56:59 UTC
  • mfrom: (1.1.3 upstream) (4.1.1 hardy)
  • Revision ID: james.westby@ubuntu.com-20080215135659-ru2oqlykuju20fav
Tags: 1:804.028-1
* New Upstream Release (Closes: #463080).
* Update to Debhelper v5.
* Build with XFT=1 (Closes: #411129).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * $Id: tkUnixRFont.c,v 1.5 2003/08/31 20:25:12 keithp Exp $
3
 
 *
4
 
 * Copyright © 2003 Keith Packard
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 that
9
 
 * copyright notice and this permission notice appear in supporting
10
 
 * documentation, and that the name of Keith Packard not be used in
11
 
 * advertising or publicity pertaining to distribution of the software without
12
 
 * specific, written prior permission.  Keith Packard makes no
13
 
 * representations about the suitability of this software for any purpose.  It
14
 
 * is provided "as is" without express or implied warranty.
15
 
 *
16
 
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
 
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18
 
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19
 
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20
 
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21
 
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
 
 * PERFORMANCE OF THIS SOFTWARE.
 
2
 * tkUnixRFont.c --
 
3
 *
 
4
 *      Alternate implementation of tkUnixFont.c using Xft.
 
5
 *
 
6
 * Copyright (c) 2002-2003 Keith Packard
 
7
 *
 
8
 * See the file "license.terms" for information on usage and redistribution of
 
9
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 
10
 *
 
11
 * RCS: @(#) $Id: tkUnixRFont.c,v 1.13 2006/03/23 22:08:51 rmax Exp $
23
12
 */
24
13
 
25
14
#include "tkUnixInt.h"
27
16
 
28
17
#ifdef USE_XFT_FONTS
29
18
 
 
19
#ifdef NEED_FT2BUILD_H
 
20
#include <ft2build.h>
 
21
#endif
30
22
#include <X11/Xft/Xft.h>
31
23
#include <ctype.h>
32
24
 
33
 
typedef struct _UnixFtFace {
34
 
    XftFont         *ftFont;
35
 
    FcPattern       *source;
36
 
    FcCharSet       *charset;
 
25
typedef struct {
 
26
    XftFont *ftFont;
 
27
    FcPattern *source;
 
28
    FcCharSet *charset;
37
29
} UnixFtFace;
38
30
 
39
 
typedef struct _UnixFtFont {
40
 
    TkFont          font;       /* Stuff used by generic font package.  Must
41
 
                                 * be first in structure. */
42
 
    UnixFtFace      *faces;
43
 
    int             nfaces;
44
 
    FcCharSet       *charset;
45
 
    FcPattern       *pattern;
 
31
typedef struct {
 
32
    TkFont font;                /* Stuff used by generic font package. Must be
 
33
                                 * first in structure. */
 
34
    UnixFtFace *faces;
 
35
    int nfaces;
 
36
    FcCharSet *charset;
 
37
    FcPattern *pattern;
46
38
 
47
 
    Display         *display;
48
 
    int             screen;
49
 
    XftDraw         *ftDraw;
50
 
    Drawable        drawable;
51
 
    XftColor        color;
 
39
    Display *display;
 
40
    int screen;
 
41
    XftDraw *ftDraw;
 
42
    Drawable drawable;
 
43
    XftColor color;
52
44
} UnixFtFont;
53
45
 
 
46
/*
 
47
 * Forward declarations...
 
48
 */
 
49
 
 
50
static void             FinishedWithFont(UnixFtFont *fontPtr);
 
51
static XftFont *        GetFont(UnixFtFont *fontPtr, FcChar32 ucs4);
 
52
static UnixFtFont *     InitFont(Tk_Window tkwin, FcPattern *pattern,
 
53
                            UnixFtFont *fontPtr);
 
54
 
 
55
/*
 
56
 * Package initialization:
 
57
 *      Nothing to do here except register the fact that we're using Xft in
 
58
 *      the TIP 59 configuration database.
 
59
 */
 
60
 
 
61
#ifndef TCL_CFGVAL_ENCODING
 
62
#define TCL_CFGVAL_ENCODING "ascii"
 
63
#endif
 
64
 
54
65
void
55
 
TkpFontPkgInit(mainPtr)
56
 
    TkMainInfo *mainPtr;        /* The application being created. */
 
66
TkpFontPkgInit(
 
67
    TkMainInfo *mainPtr)        /* The application being created. */
57
68
{
 
69
#if 0
 
70
    static Tcl_Config cfg[] = {
 
71
        { "fontsystem", "xft" },
 
72
        { 0,0 }
 
73
    };
 
74
 
 
75
    Tcl_RegisterConfig(mainPtr->interp, "tk", cfg, TCL_CFGVAL_ENCODING);
 
76
#endif
58
77
}
59
 
 
 
78
 
60
79
static XftFont *
61
 
GetFont (UnixFtFont *fontPtr, FcChar32 ucs4)
 
80
GetFont(
 
81
    UnixFtFont *fontPtr,
 
82
    FcChar32 ucs4)
62
83
{
63
 
    int     i;
 
84
    int i;
64
85
 
65
 
    if (ucs4)
66
 
    {
67
 
        for (i = 0; i < fontPtr->nfaces; i++)
68
 
        {
69
 
            FcCharSet   *charset = fontPtr->faces[i].charset;
70
 
            if (charset && FcCharSetHasChar (charset, ucs4))
 
86
    if (ucs4) {
 
87
        for (i = 0; i < fontPtr->nfaces; i++) {
 
88
            FcCharSet *charset = fontPtr->faces[i].charset;
 
89
            if (charset && FcCharSetHasChar(charset, ucs4)) {
71
90
                break;
 
91
            }
72
92
        }
73
 
        if (i == fontPtr->nfaces)
 
93
        if (i == fontPtr->nfaces) {
74
94
            i = 0;
75
 
    }
76
 
    else
 
95
        }
 
96
    } else {
77
97
        i = 0;
78
 
    if (!fontPtr->faces[i].ftFont)
79
 
    {
80
 
        FcPattern   *pat = FcFontRenderPrepare (0, fontPtr->pattern,
81
 
                                                fontPtr->faces[i].source);
82
 
                                                
83
 
        fontPtr->faces[i].ftFont = XftFontOpenPattern (fontPtr->display,
84
 
                                                       pat);
 
98
    }
 
99
    if (!fontPtr->faces[i].ftFont) {
 
100
        FcPattern *pat = FcFontRenderPrepare(0, fontPtr->pattern,
 
101
                fontPtr->faces[i].source);
 
102
 
 
103
        fontPtr->faces[i].ftFont = XftFontOpenPattern(fontPtr->display, pat);
85
104
    }
86
105
    return fontPtr->faces[i].ftFont;
87
106
}
88
 
 
89
 
static void
90
 
FiniFont (UnixFtFont *fontPtr)
91
 
{
92
 
    Display         *display = fontPtr->display;
93
 
    Tk_ErrorHandler handler;
94
 
    int             i;
95
 
 
96
 
    handler = Tk_CreateErrorHandler(display, -1, -1, -1,
97
 
                                    (Tk_ErrorProc *) NULL, (ClientData) NULL);
98
 
    for (i = 0; i < fontPtr->nfaces; i++)
99
 
    {
100
 
        if (fontPtr->faces[i].ftFont) {
101
 
            XftFontClose (fontPtr->display, fontPtr->faces[i].ftFont);
102
 
#if 0
103
 
            /* Doing this clears a leak but can also core ... */
104
 
            FcPatternDestroy (fontPtr->faces[i].ftFont->pattern);
105
 
#endif
106
 
        }
107
 
        if (fontPtr->faces[i].source)
108
 
            FcPatternDestroy (fontPtr->faces[i].source);
109
 
        if (fontPtr->faces[i].charset)
110
 
            FcCharSetDestroy (fontPtr->faces[i].charset);
111
 
    }
112
 
 
113
 
    fontPtr->nfaces  = 0;
114
 
    if (fontPtr->faces) {
115
 
        ckfree((char *) fontPtr->faces);
116
 
        fontPtr->faces = NULL;
117
 
    }
118
 
 
119
 
    if (fontPtr->charset) {
120
 
        FcCharSetDestroy (fontPtr->charset);
121
 
        fontPtr->charset = NULL;
122
 
    }
123
 
 
124
 
    if (fontPtr->pattern) {
125
 
        FcPatternDestroy (fontPtr->pattern);
126
 
        fontPtr->pattern = NULL;
127
 
    }
128
 
 
129
 
 
130
 
    if (fontPtr->ftDraw) {
131
 
        XftDrawDestroy (fontPtr->ftDraw);
132
 
        fontPtr->ftDraw = NULL;
133
 
    }
134
 
 
135
 
    if (fontPtr->font.fid) {
136
 
        XUnloadFont (fontPtr->display, fontPtr->font.fid);
137
 
        fontPtr->font.fid = None;
138
 
    }
139
 
 
140
 
    Tk_DeleteErrorHandler(handler);
141
 
}
 
107
 
 
108
/*
 
109
 *---------------------------------------------------------------------------
 
110
 *
 
111
 * InitFont --
 
112
 *
 
113
 *      Initializes the fields of a UnixFtFont structure. If fontPtr is NULL,
 
114
 *      also allocates a new UnixFtFont.
 
115
 *
 
116
 * Results:
 
117
 *      On error, frees fontPtr and returns NULL, otherwise returns fontPtr.
 
118
 *
 
119
 *---------------------------------------------------------------------------
 
120
 */
142
121
 
143
122
static UnixFtFont *
144
 
InitFont (UnixFtFont *fontPtr, Tk_Window tkwin, FcPattern *pattern)
 
123
InitFont(
 
124
    Tk_Window tkwin,
 
125
    FcPattern *pattern,
 
126
    UnixFtFont *fontPtr)
145
127
{
146
 
    TkFontAttributes    *faPtr;
147
 
    TkFontMetrics       *fmPtr;
148
 
    char                *family;
149
 
    int                 weight, slant;
150
 
    double              dSize;
151
 
    int                 size;
152
 
    int                 spacing;
153
 
    FcFontSet           *set = NULL;
154
 
    FcCharSet           *charset = NULL;
155
 
    FcResult            result;
156
 
    int                 i;
157
 
    XftFont             *ftFont = NULL;
158
 
    UnixFtFace          *faces = NULL;
159
 
 
160
 
    FcConfigSubstitute (0, pattern, FcMatchPattern);
161
 
    XftDefaultSubstitute (Tk_Display (tkwin),
162
 
                          Tk_ScreenNumber (tkwin),
163
 
                          pattern);
 
128
    TkFontAttributes *faPtr;
 
129
    TkFontMetrics *fmPtr;
 
130
    char *family;
 
131
    int weight, slant, spacing, i;
 
132
    int size;
 
133
    double dSize;
 
134
    FcFontSet *set;
 
135
    FcCharSet *charset;
 
136
    FcResult result;
 
137
    XftFont *ftFont;
 
138
 
 
139
    if (!fontPtr) {
 
140
        fontPtr = (UnixFtFont *) ckalloc(sizeof(UnixFtFont));
 
141
    }
 
142
 
 
143
    FcConfigSubstitute(0, pattern, FcMatchPattern);
 
144
    XftDefaultSubstitute(Tk_Display(tkwin), Tk_ScreenNumber(tkwin), pattern);
164
145
 
165
146
    /*
166
147
     * Generate the list of fonts
167
148
     */
168
 
    set = FcFontSort (0, pattern, FcTrue, &charset, &result);
169
 
 
170
 
    if (!set)
171
 
    {
172
 
        goto freePattern;
173
 
    }
174
 
 
175
 
 
176
 
#if 0
177
 
    FcPatternPrint(pattern);
178
 
#endif
179
 
 
180
 
    faces = (UnixFtFace *) ckalloc (set->nfont * sizeof (UnixFtFace));
181
 
    if (!faces)
182
 
    {
183
 
   freeSet:
184
 
        FcFontSetDestroy (set);
185
 
   freePattern:
186
 
        FcCharSetDestroy (charset);
187
 
        FcPatternDestroy (pattern);
 
149
 
 
150
    set = FcFontSort(0, pattern, FcTrue, &charset, &result);
 
151
    if (!set) {
 
152
        FcPatternDestroy(pattern);
 
153
        ckfree((char *) fontPtr);
188
154
        return NULL;
189
155
    }
190
156
 
191
 
#if 0
192
 
    FcFontSetPrint(set);
193
 
#endif
194
 
 
195
 
    if (fontPtr) {
196
 
        FiniFont(fontPtr);
197
 
    }
198
 
    else {
199
 
        fontPtr = (UnixFtFont *) ckalloc (sizeof (UnixFtFont));
200
 
    }
201
 
    if (!fontPtr) {
202
 
        if (faces)
203
 
            ckfree((char *) faces);
204
 
        goto freeSet;
205
 
    }
206
 
 
207
157
    fontPtr->charset = charset;
208
158
    fontPtr->pattern = pattern;
209
 
    fontPtr->faces   = faces;
210
 
    fontPtr->nfaces  = set->nfont;
 
159
    fontPtr->faces = (UnixFtFace *) ckalloc(set->nfont * sizeof(UnixFtFace));
 
160
    fontPtr->nfaces = set->nfont;
211
161
 
212
162
    /*
213
163
     * Fill in information about each returned font
214
164
     */
215
 
    for (i = 0; i < set->nfont; i++)
216
 
    {
 
165
 
 
166
    for (i = 0; i < set->nfont; i++) {
217
167
        fontPtr->faces[i].ftFont = 0;
218
168
        fontPtr->faces[i].source = set->fonts[i];
219
 
        if (FcPatternGetCharSet (set->fonts[i], FC_CHARSET, 0, &charset) == FcResultMatch)
220
 
            fontPtr->faces[i].charset = FcCharSetCopy (charset);
221
 
        else
 
169
        if (FcPatternGetCharSet(set->fonts[i], FC_CHARSET, 0,
 
170
                &charset) == FcResultMatch) {
 
171
            fontPtr->faces[i].charset = FcCharSetCopy(charset);
 
172
        } else {
222
173
            fontPtr->faces[i].charset = 0;
 
174
        }
223
175
    }
224
176
 
225
 
    FcFontSetDestroy (set);
226
 
 
227
 
    fontPtr->font.fid   = XLoadFont (Tk_Display (tkwin), "fixed");
228
 
 
229
 
    fontPtr->display    = Tk_Display (tkwin);
230
 
    fontPtr->screen     = Tk_ScreenNumber (tkwin);
231
 
    fontPtr->ftDraw     = 0;
232
 
    fontPtr->drawable   = 0;
233
 
    fontPtr->color.color.red  = 0;
234
 
    fontPtr->color.color.green= 0;
 
177
    fontPtr->font.fid = XLoadFont(Tk_Display(tkwin), "fixed");
 
178
    fontPtr->display = Tk_Display(tkwin);
 
179
    fontPtr->screen = Tk_ScreenNumber(tkwin);
 
180
    fontPtr->ftDraw = 0;
 
181
    fontPtr->drawable = 0;
 
182
    fontPtr->color.color.red = 0;
 
183
    fontPtr->color.color.green = 0;
235
184
    fontPtr->color.color.blue = 0;
236
 
    fontPtr->color.color.alpha= 0xffff;
 
185
    fontPtr->color.color.alpha = 0xffff;
237
186
    fontPtr->color.pixel = 0xffffffff;
238
187
 
239
 
    faPtr               = &fontPtr->font.fa;
240
 
 
241
 
    /* Now get 0'th font */
242
 
    ftFont              = GetFont (fontPtr, 0);
243
 
 
244
 
    /* And set Tk's actuals from its pattern */
245
 
    pattern = ftFont->pattern;
 
188
    ftFont = GetFont(fontPtr, 0);
246
189
 
247
190
    /*
248
191
     * Build the Tk font structure
249
192
     */
250
 
    if (XftPatternGetString (pattern, XFT_FAMILY, 0, &family) != XftResultMatch)
 
193
 
 
194
    if (XftPatternGetString(ftFont->pattern, XFT_FAMILY, 0,
 
195
            &family) != XftResultMatch) {
251
196
        family = "Unknown";
 
197
    }
252
198
 
253
 
    if (XftPatternGetInteger (pattern, XFT_WEIGHT, 0, &weight) != XftResultMatch)
 
199
    if (XftPatternGetInteger(ftFont->pattern, XFT_WEIGHT, 0,
 
200
            &weight) != XftResultMatch) {
254
201
        weight = XFT_WEIGHT_MEDIUM;
255
 
    if (weight <= XFT_WEIGHT_MEDIUM)
 
202
    }
 
203
    if (weight <= XFT_WEIGHT_MEDIUM) {
256
204
        weight = TK_FW_NORMAL;
257
 
    else
 
205
    } else {
258
206
        weight = TK_FW_BOLD;
 
207
    }
259
208
 
260
 
    if (XftPatternGetInteger (pattern, XFT_SLANT, 0, &slant) != XftResultMatch)
 
209
    if (XftPatternGetInteger(ftFont->pattern, XFT_SLANT, 0,
 
210
            &slant) != XftResultMatch) {
261
211
        slant = XFT_SLANT_ROMAN;
262
 
    if (slant <= XFT_SLANT_ROMAN)
 
212
    }
 
213
    if (slant <= XFT_SLANT_ROMAN) {
263
214
        slant = TK_FS_ROMAN;
264
 
    else
 
215
    } else {
265
216
        slant = TK_FS_ITALIC;
 
217
    }
266
218
 
267
 
    if (XftPatternGetDouble (pattern, XFT_PIXEL_SIZE, 0, &dSize)
268
 
                                != XftResultMatch) {
269
 
        if (XftPatternGetDouble (pattern, XFT_SIZE, 0, &dSize)
270
 
                                != XftResultMatch) {
 
219
    /* Different font size handling in Tcl/Tk and Perl/Tk */
 
220
    if (XftPatternGetDouble(pattern, XFT_PIXEL_SIZE, 0,
 
221
                &dSize) != XftResultMatch) {
 
222
        if (XftPatternGetDouble(pattern, XFT_SIZE, 0, &dSize)
 
223
                        != XftResultMatch) {
271
224
            size = -12;
272
 
        }
273
 
        else {
 
225
        } else {
274
226
            size = (int)(dSize+0.5);
275
227
        }
276
 
    }
277
 
    else {
 
228
    } else {
278
229
        size = -(int)(dSize+0.5);
279
230
    }
280
231
 
281
 
    if (XftPatternGetInteger (pattern, XFT_SPACING, 0, &spacing) != XftResultMatch)
 
232
    if (XftPatternGetInteger(ftFont->pattern, XFT_SPACING, 0,
 
233
            &spacing) != XftResultMatch) {
282
234
        spacing = XFT_PROPORTIONAL;
283
 
    if (spacing == XFT_PROPORTIONAL)
 
235
    }
 
236
    if (spacing == XFT_PROPORTIONAL) {
284
237
        spacing = 0;
285
 
    else
 
238
    } else {
286
239
        spacing = 1;
287
 
#if 0
288
 
    printf ("%p family %s size %g=>%d weight %d slant %d id=%d\n",
289
 
            fontPtr, family, dSize, size, weight, slant, fontPtr->font.fid);
290
 
#endif
291
 
 
292
 
    faPtr->family       = family;
293
 
    faPtr->size         = size;
294
 
    faPtr->weight       = weight;
295
 
    faPtr->slant        = slant;
296
 
    faPtr->underline    = 0;
297
 
    faPtr->overstrike   = 0;
298
 
 
299
 
    fmPtr               = &fontPtr->font.fm;
300
 
    fmPtr->ascent       = ftFont->ascent;
301
 
    fmPtr->descent      = ftFont->descent;
302
 
    fmPtr->maxWidth     = ftFont->max_advance_width;
303
 
    fmPtr->fixed        = spacing;
 
240
    }
 
241
#if DEBUG_FONTSEL
 
242
    printf("family %s size %g weight %d slant %d\n",
 
243
            family, size, weight, slant);
 
244
#endif /* DEBUG_FONTSEL */
 
245
 
 
246
    faPtr = &fontPtr->font.fa;
 
247
    faPtr->family = family;
 
248
    faPtr->size = size;
 
249
    faPtr->weight = weight;
 
250
    faPtr->slant = slant;
 
251
    faPtr->underline = 0;
 
252
    faPtr->overstrike = 0;
 
253
 
 
254
    fmPtr = &fontPtr->font.fm;
 
255
    fmPtr->ascent = ftFont->ascent;
 
256
    fmPtr->descent = ftFont->descent;
 
257
    fmPtr->maxWidth = ftFont->max_advance_width;
 
258
    fmPtr->fixed = spacing;
304
259
 
305
260
    return fontPtr;
306
261
}
 
262
 
 
263
static void
 
264
FinishedWithFont(
 
265
    UnixFtFont *fontPtr)
 
266
{
 
267
    Display *display = fontPtr->display;
 
268
    Tk_ErrorHandler handler;
 
269
    int i;
307
270
 
 
271
    handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL,
 
272
            (ClientData) NULL);
 
273
    for (i = 0; i < fontPtr->nfaces; i++) {
 
274
        if (fontPtr->faces[i].ftFont) {
 
275
            XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont);
 
276
        }
 
277
        if (fontPtr->faces[i].source) {
 
278
            FcPatternDestroy(fontPtr->faces[i].source);
 
279
        }
 
280
        if (fontPtr->faces[i].charset) {
 
281
            FcCharSetDestroy(fontPtr->faces[i].charset);
 
282
        }
 
283
    }
 
284
    if (fontPtr->ftDraw) {
 
285
        XftDrawDestroy(fontPtr->ftDraw);
 
286
    }
 
287
    if (fontPtr->font.fid) {
 
288
        XUnloadFont(fontPtr->display, fontPtr->font.fid);
 
289
    }
 
290
    Tk_DeleteErrorHandler(handler);
 
291
}
 
292
 
308
293
TkFont *
309
 
TkpGetNativeFont(tkwin, name)
310
 
    Tk_Window tkwin;            /* For display where font will be used. */
311
 
    CONST char *name;           /* Platform-specific font name. */
 
294
TkpGetNativeFont(
 
295
    Tk_Window tkwin,            /* For display where font will be used. */
 
296
    CONST char *name)           /* Platform-specific font name. */
312
297
{
313
 
    UnixFtFont  *fontPtr = NULL;
314
 
    FcPattern   *pattern = NULL;
315
 
#if 0
316
 
    printf ("TkpGetNativeFont '%s'\n", name);
317
 
#endif
 
298
    UnixFtFont *fontPtr;
 
299
    FcPattern *pattern;
 
300
#if DEBUG_FONTSEL
 
301
    printf("TkpGetNativeFont %s\n", name);
 
302
#endif /* DEBUG_FONTSEL */
 
303
 
 
304
    /*
 
305
     * The font handling in Perl/Tk differs here:
 
306
     * TkFontParseXLFD and FcNameParse are used before trying XftXlfdParse
 
307
     */
318
308
    if (*name == '-') {
319
 
#if 0
320
 
        /* This parses full names ok, but result is mis-scaled for some reason */
321
 
        pattern = XftXlfdParse (name, FcFalse, FcFalse);
322
 
#endif
323
 
        if (!pattern) {
324
 
            TkFontAttributes fa;
325
 
            TkXLFDAttributes xa;
326
 
            if (TkFontParseXLFD(name, &fa, &xa) != TCL_OK) {
327
 
                return NULL;
328
 
            }
329
 
            else {
330
 
                return TkpGetFontFromAttributes(NULL, tkwin, &fa);
331
 
            }
 
309
        TkFontAttributes fa;
 
310
        TkXLFDAttributes xa;
 
311
        if (TkFontParseXLFD(name, &fa, &xa) != TCL_OK) {
 
312
            return NULL;
 
313
        } else {
 
314
            return TkpGetFontFromAttributes(NULL, tkwin, &fa);
332
315
        }
333
 
    }
334
 
    else if (strpbrk(name,":,=") || !strpbrk(name," {")) {
 
316
    } else if (strpbrk(name,":,=") || !strpbrk(name," {")) {
335
317
        pattern = FcNameParse (name);
336
 
    }
337
 
    if (pattern) {
338
 
        fontPtr = InitFont (NULL, tkwin, pattern);
339
 
    }
340
 
    else {
341
 
        
342
 
    }
343
 
    if (fontPtr) {
344
 
        return &fontPtr->font;
345
 
    }
346
 
    return NULL;
 
318
    } else {
 
319
        /* Tcl/Tk version */
 
320
        pattern = XftXlfdParse(name, FcFalse, FcFalse);
 
321
    }
 
322
    if (!pattern) {
 
323
        return NULL;
 
324
    }
 
325
 
 
326
    /*
 
327
     * Should also try: pattern = FcNameParse(name); but generic/tkFont.c
 
328
     * expects TkpGetNativeFont() to only work on XLFD names under Unix.
 
329
     */
 
330
 
 
331
    fontPtr = InitFont(tkwin, pattern, NULL);
 
332
    if (!fontPtr) {
 
333
        return NULL;
 
334
    }
 
335
    return &fontPtr->font;
347
336
}
348
 
 
 
337
 
349
338
TkFont *
350
 
TkpGetFontFromAttributes(tkFontPtr, tkwin, faPtr)
351
 
    TkFont *tkFontPtr;          /* If non-NULL, store the information in
352
 
                                 * this existing TkFont structure, rather than
 
339
TkpGetFontFromAttributes(
 
340
    TkFont *tkFontPtr,          /* If non-NULL, store the information in this
 
341
                                 * existing TkFont structure, rather than
353
342
                                 * allocating a new structure to hold the
354
343
                                 * font; the existing contents of the font
355
 
                                 * will be released.  If NULL, a new TkFont
 
344
                                 * will be released. If NULL, a new TkFont
356
345
                                 * structure is allocated. */
357
 
    Tk_Window tkwin;            /* For display where font will be used. */
358
 
    CONST TkFontAttributes *faPtr;
 
346
    Tk_Window tkwin,            /* For display where font will be used. */
 
347
    CONST TkFontAttributes *faPtr)
359
348
                                /* Set of attributes to match. */
360
349
{
361
 
    XftPattern  *pattern;
362
 
    int         weight, slant;
363
 
    UnixFtFont  *fontPtr = (UnixFtFont *)tkFontPtr;
 
350
    XftPattern *pattern;
 
351
    int weight, slant;
 
352
    UnixFtFont *fontPtr;
364
353
 
365
 
    pattern = XftPatternBuild (0,
366
 
                               XFT_FAMILY, XftTypeString, faPtr->family,
367
 
                               0);
368
 
    if (faPtr->size > 0)
369
 
        XftPatternAddInteger (pattern, XFT_SIZE, faPtr->size);
370
 
    else
371
 
        XftPatternAddInteger (pattern, XFT_PIXEL_SIZE, -faPtr->size);
 
354
#if DEBUG_FONTSEL
 
355
    printf("TkpGetFontFromAttributes %s-%d %d %d\n", faPtr->family,
 
356
            faPtr->size, faPtr->weight, faPtr->slant);
 
357
#endif /* DEBUG_FONTSEL */
 
358
    pattern = XftPatternCreate();
 
359
    if (faPtr->family) {
 
360
        XftPatternAddString(pattern, XFT_FAMILY, faPtr->family);
 
361
    }
 
362
    if (faPtr->size > 0) {
 
363
        XftPatternAddInteger(pattern, XFT_SIZE, faPtr->size);
 
364
    } else if (faPtr->size < 0) {
 
365
        XftPatternAddInteger(pattern, XFT_PIXEL_SIZE, -faPtr->size);
 
366
    } else {
 
367
        XftPatternAddInteger(pattern, XFT_SIZE, 12);
 
368
    }
372
369
    switch (faPtr->weight) {
373
370
    case TK_FW_NORMAL:
374
371
    default:
378
375
        weight = XFT_WEIGHT_BOLD;
379
376
        break;
380
377
    }
381
 
    XftPatternAddInteger (pattern, XFT_WEIGHT, weight);
 
378
    XftPatternAddInteger(pattern, XFT_WEIGHT, weight);
382
379
    switch (faPtr->slant) {
383
380
    case TK_FS_ROMAN:
384
381
    default:
391
388
        slant = XFT_SLANT_OBLIQUE;
392
389
        break;
393
390
    }
394
 
    XftPatternAddInteger (pattern, XFT_SLANT, slant);
 
391
    XftPatternAddInteger(pattern, XFT_SLANT, slant);
395
392
 
396
 
    fontPtr = InitFont (fontPtr, tkwin, pattern);
397
 
#if 0
398
 
    printf ("%p TkpGetFontFromAttributes %s-%d %d %d\n", fontPtr,
399
 
            faPtr->family, faPtr->size, faPtr->weight, faPtr->slant);
400
 
#endif
401
 
    if (!fontPtr)
 
393
    fontPtr = (UnixFtFont *) tkFontPtr;
 
394
    if (fontPtr != NULL) {
 
395
        FinishedWithFont(fontPtr);
 
396
    }
 
397
    fontPtr = InitFont(tkwin, pattern, fontPtr);
 
398
    if (!fontPtr) {
402
399
        return NULL;
 
400
    }
403
401
    return &fontPtr->font;
404
402
}
405
 
 
 
403
 
406
404
void
407
 
TkpDeleteFont(tkFontPtr)
408
 
    TkFont *tkFontPtr;          /* Token of font to be deleted. */
 
405
TkpDeleteFont(
 
406
    TkFont *tkFontPtr)          /* Token of font to be deleted. */
409
407
{
410
 
    UnixFtFont  *fontPtr = (UnixFtFont *) tkFontPtr;
 
408
    UnixFtFont *fontPtr = (UnixFtFont *) tkFontPtr;
411
409
 
412
 
    FiniFont (fontPtr);
 
410
    FinishedWithFont(fontPtr);
413
411
    /* XXX tkUnixFont.c doesn't free tkFontPtr... */
414
412
}
 
413
 
 
414
/*
 
415
 *---------------------------------------------------------------------------
 
416
 *
 
417
 * TkpGetFontFamilies --
 
418
 *
 
419
 *      Return information about the font families that are available on the
 
420
 *      display of the given window.
 
421
 *
 
422
 * Results:
 
423
 *      Modifies interp's result object to hold a list of all the available
 
424
 *      font families.
 
425
 *
 
426
 *---------------------------------------------------------------------------
 
427
 */
415
428
 
416
429
void
417
 
TkpGetFontFamilies(interp, tkwin)
418
 
    Tcl_Interp *interp;         /* Interp to hold result. */
419
 
    Tk_Window tkwin;            /* For display to query. */
 
430
TkpGetFontFamilies(
 
431
    Tcl_Interp *interp,         /* Interp to hold result. */
 
432
    Tk_Window tkwin)            /* For display to query. */
420
433
{
421
 
    Tcl_Obj     *resultPtr, *strPtr;
422
 
    XftFontSet  *list;
423
 
    int         i;
424
 
    char        *family;
425
 
 
426
 
    resultPtr = Tcl_GetObjResult(interp);
427
 
 
428
 
    list = XftListFonts (Tk_Display (tkwin),
429
 
                         Tk_ScreenNumber (tkwin),
430
 
                         0,
431
 
                         XFT_FAMILY,
432
 
                         0);
433
 
    for (i = 0; i < list->nfont; i++)
434
 
    {
435
 
        if (XftPatternGetString (list->fonts[i], XFT_FAMILY, 0, &family) == XftResultMatch)
436
 
        {
437
 
            strPtr = Tcl_NewStringObj(Tk_GetUid (family), -1);
438
 
            Tcl_ListObjAppendElement (NULL, resultPtr, strPtr);
 
434
    Tcl_Obj *resultPtr, *strPtr;
 
435
    XftFontSet *list;
 
436
    int i;
 
437
    char *family;
 
438
 
 
439
    resultPtr = Tcl_NewListObj(0, NULL);
 
440
 
 
441
    list = XftListFonts(Tk_Display(tkwin), Tk_ScreenNumber(tkwin), 0,
 
442
            XFT_FAMILY, 0);
 
443
    for (i = 0; i < list->nfont; i++) {
 
444
        if (XftPatternGetString(list->fonts[i], XFT_FAMILY, 0,
 
445
                &family) == XftResultMatch) {
 
446
            strPtr = Tcl_NewStringObj(Tk_GetUid(family), -1);
 
447
            Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
439
448
        }
440
449
    }
441
 
    XftFontSetDestroy (list);
 
450
    XftFontSetDestroy(list);
 
451
 
 
452
    Tcl_SetObjResult(interp, resultPtr);
442
453
}
 
454
 
 
455
/*
 
456
 *-------------------------------------------------------------------------
 
457
 *
 
458
 * TkpGetSubFonts --
 
459
 *
 
460
 *      Called by [testfont subfonts] in the Tk testing package.
 
461
 *
 
462
 * Results:
 
463
 *      Sets interp's result to a list of the faces used by tkfont
 
464
 *
 
465
 *-------------------------------------------------------------------------
 
466
 */
443
467
 
444
468
void
445
 
TkpGetSubFonts(interp, tkfont)
446
 
    Tcl_Interp *interp;
447
 
    Tk_Font tkfont;
 
469
TkpGetSubFonts(
 
470
    Tcl_Interp *interp,
 
471
    Tk_Font tkfont)
448
472
{
449
 
    Tcl_Obj     *objv[4];
450
 
    Tcl_Obj     *resultPtr, *listPtr;
451
 
    UnixFtFont  *fontPtr = (UnixFtFont *) tkfont;
452
 
    char        *family, *foundry, *encoding, *file;
453
 
    XftFont     *ftFont = GetFont (fontPtr, 0);
454
 
    int i;
455
 
    int used;
 
473
    Tcl_Obj *objv[5], *listPtr, *resultPtr;
 
474
    UnixFtFont *fontPtr = (UnixFtFont *) tkfont;
456
475
    FcPattern *pattern;
457
 
 
458
 
    resultPtr = Tcl_GetObjResult(interp);
459
 
    for (i = 0; i < fontPtr->nfaces; i++) {
460
 
        if (fontPtr->faces[i].ftFont) {
461
 
            pattern = fontPtr->faces[i].ftFont->pattern;
462
 
            used = 1;
463
 
        }
464
 
        else {
465
 
            pattern = fontPtr->faces[i].source;
466
 
            used = 0;
467
 
            continue;
468
 
        }
469
 
#if 0
470
 
        FcPatternPrint(pattern);
471
 
#endif
472
 
        if (XftPatternGetString (pattern, XFT_FAMILY,
473
 
                             0, &family) != XftResultMatch)
474
 
            {
475
 
                family = "";
476
 
            }
477
 
        if (XftPatternGetString (pattern, XFT_FOUNDRY,
478
 
                             0, &foundry) != XftResultMatch)
479
 
            {
480
 
                foundry = "";
481
 
            }
482
 
        if (XftPatternGetString (pattern, XFT_ENCODING,
483
 
                             0, &encoding))
484
 
            {
485
 
                encoding = "";
486
 
            }
487
 
        if (XftPatternGetString (pattern, XFT_FILE,
488
 
                             0, &file))
489
 
            {
490
 
                file = "";
491
 
            }
 
476
    char *family, *foundry, *encoding, *file;
 
477
    int i;
 
478
 
 
479
    resultPtr = Tcl_NewListObj(0, NULL);
 
480
 
 
481
    for (i = 0; i < fontPtr->nfaces ; ++i) {
 
482
        pattern = FcFontRenderPrepare(0, fontPtr->pattern,
 
483
                fontPtr->faces[i].source);
 
484
 
 
485
        if (XftPatternGetString(pattern, XFT_FAMILY, 0,
 
486
                &family) != XftResultMatch) {
 
487
            family = "Unknown";
 
488
        }
 
489
        if (XftPatternGetString(pattern, XFT_FOUNDRY, 0,
 
490
                &foundry) != XftResultMatch) {
 
491
            foundry = "Unknown";
 
492
        }
 
493
        if (XftPatternGetString(pattern, XFT_ENCODING, 0,
 
494
                &encoding) != XftResultMatch) {
 
495
            encoding = "Unknown";
 
496
        }
 
497
        if (XftPatternGetString(pattern, XFT_FILE, 0,
 
498
                &file) != XftResultMatch) {
 
499
            encoding = "Unknown";
 
500
        }
492
501
        objv[0] = Tcl_NewStringObj(family, -1);
493
 
        objv[1] = Tcl_NewStringObj(file, -1);
494
 
        objv[2] = Tcl_NewStringObj(foundry, -1);
495
 
        objv[3] = Tcl_NewStringObj(encoding, -1);
496
 
        listPtr = Tcl_NewListObj (4, objv);
497
 
        Tcl_ListObjAppendElement (interp, resultPtr, listPtr);
 
502
        objv[1] = Tcl_NewStringObj(foundry, -1);
 
503
        objv[2] = Tcl_NewStringObj(encoding, -1);
 
504
        objv[3] = Tcl_NewIntObj(-1); /* trigger (?), NYI, added in Perl/Tk */
 
505
        objv[4] = Tcl_NewStringObj(file, -1); /* added in Perl/Tk */
 
506
        listPtr = Tcl_NewListObj(5, objv);
 
507
        Tcl_ListObjAppendElement(NULL, resultPtr, listPtr);
498
508
    }
 
509
    Tcl_SetObjResult(interp, resultPtr);
499
510
}
500
 
 
 
511
 
501
512
int
502
 
Tk_MeasureChars(tkfont, source, numBytes, maxLength, flags, lengthPtr)
503
 
    Tk_Font tkfont;             /* Font in which characters will be drawn. */
504
 
    CONST char *source;         /* UTF-8 string to be displayed.  Need not be
 
513
Tk_MeasureChars(
 
514
    Tk_Font tkfont,             /* Font in which characters will be drawn. */
 
515
    CONST char *source,         /* UTF-8 string to be displayed. Need not be
505
516
                                 * '\0' terminated. */
506
 
    int numBytes;               /* Maximum number of bytes to consider
507
 
                                 * from source string. */
508
 
    int maxLength;              /* If >= 0, maxLength specifies the longest
 
517
    int numBytes,               /* Maximum number of bytes to consider from
 
518
                                 * source string. */
 
519
    int maxLength,              /* If >= 0, maxLength specifies the longest
509
520
                                 * permissible line length in pixels; don't
510
521
                                 * consider any character that would cross
511
 
                                 * this x-position.  If < 0, then line length
 
522
                                 * this x-position. If < 0, then line length
512
523
                                 * is unbounded and the flags argument is
513
524
                                 * ignored. */
514
 
    int flags;                  /* Various flag bits OR-ed together:
 
525
    int flags,                  /* Various flag bits OR-ed together:
515
526
                                 * TK_PARTIAL_OK means include the last char
516
527
                                 * which only partially fit on this line.
517
528
                                 * TK_WHOLE_WORDS means stop on a word
518
 
                                 * boundary, if possible.
519
 
                                 * TK_AT_LEAST_ONE means return at least one
520
 
                                 * character even if no characters fit. */
521
 
    int *lengthPtr;             /* Filled with x-location just after the
 
529
                                 * boundary, if possible. TK_AT_LEAST_ONE
 
530
                                 * means return at least one character even if
 
531
                                 * no characters fit. */
 
532
    int *lengthPtr)             /* Filled with x-location just after the
522
533
                                 * terminating character. */
523
534
{
524
 
    UnixFtFont      *fontPtr = (UnixFtFont *) tkfont;
525
 
    XftFont         *ftFont;
526
 
    FcChar32        c;
527
 
    int             clen;
528
 
    XGlyphInfo      extents;
529
 
    int             curX, newX;
530
 
    int             termByte = 0;
531
 
    int             termX = 0;
532
 
    int             curByte, newByte;
533
 
    int             sawNonSpace;
 
535
    UnixFtFont *fontPtr = (UnixFtFont *) tkfont;
 
536
    XftFont *ftFont;
 
537
    FcChar32 c;
 
538
    int clen;
 
539
    XGlyphInfo extents;
 
540
    int curX, newX;
 
541
    int termByte = 0, termX = 0;
 
542
    int curByte, newByte, sawNonSpace;
 
543
#if DEBUG_FONTSEL
 
544
    char string[256];
 
545
    int len = 0;
 
546
#endif /* DEBUG_FONTSEL */
534
547
 
535
548
    curX = 0;
536
549
    curByte = 0;
537
550
    sawNonSpace = 0;
538
 
 
539
 
    while (numBytes > 0)
540
 
    {
541
 
        c = 0;
542
 
        clen = FcUtf8ToUcs4 ((FcChar8 *) source, &c, numBytes);
 
551
    while (numBytes > 0) {
 
552
        Tcl_UniChar unichar;
 
553
 
 
554
        clen = Tcl_UtfToUniChar(source, &unichar);
 
555
        c = (FcChar32)unichar;
 
556
 
543
557
        if (clen <= 0) {
544
 
            /* Not supposed to happen - did happen in Text widget
545
 
             * abort() for now - could also take 1byte == 1 char ?
 
558
            /*
 
559
             * This can't happen (but see #1185640)
546
560
             */
547
 
            LangDebug("numByte=%d s='%.*s' c=%x clen=%d\n",
548
 
                       numBytes, numBytes, source, c, clen);
549
 
            abort();
 
561
 
 
562
            *lengthPtr = curX;
 
563
            return curByte;
550
564
        }
 
565
 
551
566
        source += clen;
552
567
        numBytes -= clen;
553
 
        if (c < 256 && isspace (c))
554
 
        {
555
 
            if (sawNonSpace)
556
 
            {
 
568
        if (c < 256 && isspace(c)) {            /* I18N: ??? */
 
569
            if (sawNonSpace) {
557
570
                termByte = curByte;
558
571
                termX = curX;
559
572
                sawNonSpace = 0;
560
573
            }
561
 
        }
562
 
        else
 
574
        } else {
563
575
            sawNonSpace = 1;
564
 
 
565
 
        ftFont = GetFont (fontPtr, c);
566
 
 
567
 
        XftTextExtents32 (fontPtr->display, ftFont, &c, 1, &extents);
568
 
 
569
 
        newX    = curX + extents.xOff;
 
576
        }
 
577
 
 
578
#if DEBUG_FONTSEL
 
579
        string[len++] = (char) c;
 
580
#endif /* DEBUG_FONTSEL */
 
581
        ftFont = GetFont(fontPtr, c);
 
582
 
 
583
        XftTextExtents32(fontPtr->display, ftFont, &c, 1, &extents);
 
584
 
 
585
        newX = curX + extents.xOff;
570
586
        newByte = curByte + clen;
571
 
 
572
 
#if 0
573
 
        LangDebug("%s ch=%d x=%d+w=%d => %d out of %d, curB=%d newB=%d leaving %d\n",
574
 
                  __FUNCTION__,c,curX,extents.xOff,newX,maxLength,
575
 
                  curByte, newByte, numBytes);
576
 
#endif
577
 
 
578
 
        if (maxLength >= 0 && newX > maxLength)
579
 
        {
580
 
            if ((flags & TK_PARTIAL_OK) ||
581
 
                ((flags & TK_AT_LEAST_ONE) && curByte == 0))
582
 
            {
 
587
        if (maxLength >= 0 && newX > maxLength) {
 
588
            if (flags & TK_PARTIAL_OK ||
 
589
                    (flags & TK_AT_LEAST_ONE && curByte == 0)) {
583
590
                curX = newX;
584
591
                curByte = newByte;
585
 
            }
586
 
            else if ((flags & TK_WHOLE_WORDS) && termByte != 0)
587
 
            {
 
592
            } else if (flags & TK_WHOLE_WORDS && termX != 0) {
588
593
                curX = termX;
589
594
                curByte = termByte;
590
595
            }
591
596
            break;
592
597
        }
593
 
        
594
 
        curX     = newX;
595
 
        curByte  = newByte;
 
598
 
 
599
        curX = newX;
 
600
        curByte = newByte;
596
601
    }
 
602
#if DEBUG_FONTSEL
 
603
    string[len] = '\0';
 
604
    printf("MeasureChars %s length %d bytes %d\n", string, curX, curByte);
 
605
#endif /* DEBUG_FONTSEL */
597
606
    *lengthPtr = curX;
598
607
    return curByte;
599
608
}
600
 
 
 
609
 
 
610
int
 
611
TkpMeasureCharsInContext(Tk_Font tkfont, CONST char * source, int numBytes,
 
612
                         int rangeStart, int rangeLength, int maxLength,
 
613
                         int flags, int * lengthPtr)
 
614
{
 
615
    (void) numBytes; /*unused*/
 
616
    return Tk_MeasureChars(tkfont, source + rangeStart, rangeLength,
 
617
            maxLength, flags, lengthPtr);
 
618
}
 
619
 
601
620
#define NUM_SPEC    1024
602
621
 
603
622
void
604
 
Tk_DrawChars(display, drawable, gc, tkfont, source, numBytes, x, y)
605
 
    Display *display;           /* Display on which to draw. */
606
 
    Drawable drawable;          /* Window or pixmap in which to draw. */
607
 
    GC gc;                      /* Graphics context for drawing characters. */
608
 
    Tk_Font tkfont;             /* Font in which characters will be drawn;
 
623
Tk_DrawChars(
 
624
    Display *display,           /* Display on which to draw. */
 
625
    Drawable drawable,          /* Window or pixmap in which to draw. */
 
626
    GC gc,                      /* Graphics context for drawing characters. */
 
627
    Tk_Font tkfont,             /* Font in which characters will be drawn;
609
628
                                 * must be the same as font used in GC. */
610
 
    CONST char *source;         /* UTF-8 string to be displayed.  Need not be
611
 
                                 * '\0' terminated.  All Tk meta-characters
 
629
    CONST char *source,         /* UTF-8 string to be displayed. Need not be
 
630
                                 * '\0' terminated. All Tk meta-characters
612
631
                                 * (tabs, control characters, and newlines)
613
632
                                 * should be stripped out of the string that
614
 
                                 * is passed to this function.  If they are
615
 
                                 * not stripped out, they will be displayed as
 
633
                                 * is passed to this function. If they are not
 
634
                                 * stripped out, they will be displayed as
616
635
                                 * regular printing characters. */
617
 
    int numBytes;               /* Number of bytes in string. */
618
 
    int x, y;                   /* Coordinates at which to place origin of
 
636
    int numBytes,               /* Number of bytes in string. */
 
637
    int x, int y)               /* Coordinates at which to place origin of
619
638
                                 * string when drawing. */
620
639
{
621
 
    UnixFtFont          *fontPtr = (UnixFtFont *) tkfont;
622
 
    XGCValues           values;
623
 
    XColor              xcolor;
624
 
    int                 clen;
625
 
    XftGlyphFontSpec    specs[NUM_SPEC];
626
 
    int                 nspec;
627
 
    XGlyphInfo          metrics;
628
 
 
629
 
#if 0
630
 
    printf("%p DrawChars '%.*s'\n",fontPtr,numBytes,source);
631
 
#endif
632
 
 
633
 
    if (fontPtr->ftDraw == 0)
634
 
    {
635
 
#if 0
636
 
        printf ("Switch to drawable 0x%x\n", drawable);
637
 
#endif
638
 
        fontPtr->ftDraw = XftDrawCreate (display,
639
 
                                         drawable,
640
 
                                         DefaultVisual (display,
641
 
                                                        fontPtr->screen),
642
 
                                         DefaultColormap (display,
643
 
                                                          fontPtr->screen));
 
640
    const int maxCoord = 0x7FFF;        /* Xft coordinates are 16 bit values */
 
641
    UnixFtFont *fontPtr = (UnixFtFont *) tkfont;
 
642
    XGCValues values;
 
643
    XColor xcolor;
 
644
    int clen;
 
645
    XftGlyphFontSpec specs[NUM_SPEC];
 
646
    int nspec;
 
647
    XGlyphInfo metrics;
 
648
 
 
649
    if (fontPtr->ftDraw == 0) {
 
650
#if DEBUG_FONTSEL
 
651
        printf("Switch to drawable 0x%x\n", drawable);
 
652
#endif /* DEBUG_FONTSEL */
 
653
        fontPtr->ftDraw = XftDrawCreate(display, drawable,
 
654
                DefaultVisual(display, fontPtr->screen),
 
655
                DefaultColormap(display, fontPtr->screen));
644
656
        fontPtr->drawable = drawable;
645
 
    }
646
 
    /* Seem to need this even if drawable is same ? */
647
 
    else /* if (fontPtr->drawable != drawable) */
648
 
    {
 
657
    } else {
649
658
        Tk_ErrorHandler handler;
650
659
 
651
 
        handler = Tk_CreateErrorHandler(display, -1, -1, -1,
652
 
                                        (Tk_ErrorProc *) NULL, (ClientData) NULL);
653
 
        XftDrawChange (fontPtr->ftDraw, drawable);
 
660
        handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL,
 
661
                (ClientData) NULL);
 
662
        XftDrawChange(fontPtr->ftDraw, drawable);
654
663
        fontPtr->drawable = drawable;
655
664
        Tk_DeleteErrorHandler(handler);
656
665
    }
657
 
    XGetGCValues (display, gc, GCForeground, &values);
658
 
    if (values.foreground != fontPtr->color.pixel)
659
 
    {
 
666
    XGetGCValues(display, gc, GCForeground, &values);
 
667
    if (values.foreground != fontPtr->color.pixel) {
660
668
        xcolor.pixel = values.foreground;
661
 
        XQueryColor (display, DefaultColormap (display,
662
 
                                               fontPtr->screen),
663
 
                     &xcolor);
 
669
        XQueryColor(display, DefaultColormap(display, fontPtr->screen),
 
670
                &xcolor);
664
671
        fontPtr->color.color.red = xcolor.red;
665
672
        fontPtr->color.color.green = xcolor.green;
666
673
        fontPtr->color.color.blue = xcolor.blue;
668
675
        fontPtr->color.pixel = values.foreground;
669
676
    }
670
677
    nspec = 0;
671
 
    while (numBytes > 0)
672
 
    {
673
 
        XftFont     *ftFont;
674
 
        FcChar32    c;
675
 
        
676
 
        clen = FcUtf8ToUcs4 ((FcChar8 *) source, &c, numBytes);
 
678
    while (numBytes > 0 && x <= maxCoord && y <= maxCoord) {
 
679
        XftFont *ftFont;
 
680
        FcChar32 c;
 
681
 
 
682
        clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
 
683
        if (clen <= 0) {
 
684
            /*
 
685
             * This should not happen, but it can.
 
686
             */
 
687
 
 
688
            return;
 
689
        }
677
690
        source += clen;
678
691
        numBytes -= clen;
679
692
 
680
 
        ftFont = GetFont (fontPtr, c);
681
 
        if (ftFont)
682
 
        {
 
693
        ftFont = GetFont(fontPtr, c);
 
694
        if (ftFont) {
683
695
            specs[nspec].font = ftFont;
684
 
            specs[nspec].glyph = XftCharIndex (fontPtr->display, ftFont, c);
 
696
            specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);
685
697
            specs[nspec].x = x;
686
698
            specs[nspec].y = y;
687
 
 
688
 
            XftGlyphExtents (fontPtr->display, ftFont, &specs[nspec].glyph,
689
 
                             1, &metrics);
 
699
            XftGlyphExtents(fontPtr->display, ftFont, &specs[nspec].glyph, 1,
 
700
                    &metrics);
690
701
            x += metrics.xOff;
691
702
            y += metrics.yOff;
692
703
            nspec++;
693
 
            if (nspec == NUM_SPEC)
694
 
            {
695
 
                XftDrawGlyphFontSpec (fontPtr->ftDraw, &fontPtr->color,
696
 
                                      specs, nspec);
 
704
            if (nspec == NUM_SPEC) {
 
705
                XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color,
 
706
                        specs, nspec);
697
707
                nspec = 0;
698
708
            }
699
709
        }
700
710
    }
701
 
    if (nspec)
702
 
        XftDrawGlyphFontSpec (fontPtr->ftDraw, &fontPtr->color,
703
 
                              specs, nspec);
 
711
    if (nspec) {
 
712
        XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color, specs, nspec);
 
713
    }
704
714
}
 
715
 
 
716
#endif
705
717
 
706
 
#endif /* USE_XFT_FONTS */
 
718
/*
 
719
 * Local Variables:
 
720
 * mode: c
 
721
 * c-basic-offset: 4
 
722
 * fill-column: 78
 
723
 * End:
 
724
 */