1 /************************************************************************
2 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of Digital not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.
14 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 ************************************************************************/
23 /* The panoramix components contained the following notice */
25 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
27 Permission is hereby granted, free of charge, to any person obtaining a copy
28 of this software and associated documentation files (the "Software"), to deal
29 in the Software without restriction, including without limitation the rights
30 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31 copies of the Software.
33 The above copyright notice and this permission notice shall be included in
34 all copies or substantial portions of the Software.
36 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
39 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
40 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
41 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
42 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44 Except as contained in this notice, the name of Digital Equipment Corporation
45 shall not be used in advertising or otherwise to promote the sale, use or other
46 dealings in this Software without prior written authorization from Digital
47 Equipment Corporation.
49 ******************************************************************/
51 #ifdef HAVE_DIX_CONFIG_H
52 #include <dix-config.h>
57 #include <X11/Xproto.h>
58 #include "scrnintstr.h"
60 #include "dixstruct.h"
61 #include "cursorstr.h"
64 #include "dixfontstr.h"
70 #include "xf86bigfontsrv.h"
73 extern pointer fosNaturalParams
;
74 extern FontPtr defaultFont
;
76 static FontPathElementPtr
*font_path_elements
= (FontPathElementPtr
*) 0;
77 static int num_fpes
= 0;
78 static FPEFunctions
*fpe_functions
= (FPEFunctions
*) 0;
79 static int num_fpe_types
= 0;
81 static unsigned char *font_path_string
;
83 static int num_slept_fpes
= 0;
84 static int size_slept_fpes
= 0;
85 static FontPathElementPtr
*slept_fpes
= (FontPathElementPtr
*) 0;
86 static FontPatternCachePtr patternCache
;
99 case BadFontFormat
: /* is there something better? */
108 LoadGlyphs(ClientPtr client
, FontPtr pfont
, unsigned nchars
, int item_size
,
111 if (fpe_functions
[pfont
->fpe
->type
].load_glyphs
)
112 return (*fpe_functions
[pfont
->fpe
->type
].load_glyphs
)
113 (client
, pfont
, 0, nchars
, item_size
, data
);
119 dixGetGlyphs(FontPtr font
, unsigned long count
, unsigned char *chars
,
120 FontEncoding fontEncoding
,
121 unsigned long *glyphcount
, /* RETURN */
122 CharInfoPtr
*glyphs
) /* RETURN */
124 (*font
->get_glyphs
) (font
, count
, chars
, fontEncoding
, glyphcount
, glyphs
);
128 * adding RT_FONT prevents conflict with default cursor font
131 SetDefaultFont(char *defaultfontname
)
137 fid
= FakeClientID(0);
138 err
= OpenFont(serverClient
, fid
, FontLoadAll
| FontOpenSync
,
139 (unsigned) strlen(defaultfontname
), defaultfontname
);
142 err
= dixLookupResourceByType((pointer
*) &pf
, fid
, RT_FONT
, serverClient
,
151 * note that the font wakeup queue is not refcounted. this is because
152 * an fpe needs to be added when it's inited, and removed when it's finally
153 * freed, in order to handle any data that isn't requested, like FS events.
155 * since the only thing that should call these routines is the renderer's
156 * init_fpe() and free_fpe(), there shouldn't be any problem in using
160 QueueFontWakeup(FontPathElementPtr fpe
)
163 FontPathElementPtr
*new;
165 for (i
= 0; i
< num_slept_fpes
; i
++) {
166 if (slept_fpes
[i
] == fpe
) {
170 if (num_slept_fpes
== size_slept_fpes
) {
171 new = (FontPathElementPtr
*)
173 sizeof(FontPathElementPtr
) * (size_slept_fpes
+ 4));
177 size_slept_fpes
+= 4;
179 slept_fpes
[num_slept_fpes
] = fpe
;
184 RemoveFontWakeup(FontPathElementPtr fpe
)
188 for (i
= 0; i
< num_slept_fpes
; i
++) {
189 if (slept_fpes
[i
] == fpe
) {
190 for (j
= i
; j
< num_slept_fpes
; j
++) {
191 slept_fpes
[j
] = slept_fpes
[j
+ 1];
200 FontWakeup(pointer data
, int count
, pointer LastSelectMask
)
203 FontPathElementPtr fpe
;
207 /* wake up any fpe's that may be waiting for information */
208 for (i
= 0; i
< num_slept_fpes
; i
++) {
210 (void) (*fpe_functions
[fpe
->type
].wakeup_fpe
) (fpe
, LastSelectMask
);
214 /* XXX -- these two funcs may want to be broken into macros */
216 UseFPE(FontPathElementPtr fpe
)
222 FreeFPE(FontPathElementPtr fpe
)
225 if (fpe
->refcount
== 0) {
226 (*fpe_functions
[fpe
->type
].free_fpe
) (fpe
);
233 doOpenFont(ClientPtr client
, OFclosurePtr c
)
235 FontPtr pfont
= NullFont
;
236 FontPathElementPtr fpe
= NULL
;
238 int err
= Successful
;
240 char *alias
, *newname
;
245 * Decide at runtime what FontFormat to use.
248 ((screenInfo
.imageByteOrder
== LSBFirst
) ?
249 BitmapFormatByteOrderLSB
: BitmapFormatByteOrderMSB
) |
250 ((screenInfo
.bitmapBitOrder
== LSBFirst
) ?
251 BitmapFormatBitOrderLSB
: BitmapFormatBitOrderMSB
) |
252 BitmapFormatImageRectMin
|
253 #if GLYPHPADBYTES == 1
254 BitmapFormatScanlinePad8
|
256 #if GLYPHPADBYTES == 2
257 BitmapFormatScanlinePad16
|
259 #if GLYPHPADBYTES == 4
260 BitmapFormatScanlinePad32
|
262 #if GLYPHPADBYTES == 8
263 BitmapFormatScanlinePad64
|
265 BitmapFormatScanlineUnit8
;
267 if (client
->clientGone
) {
268 if (c
->current_fpe
< c
->num_fpes
) {
269 fpe
= c
->fpe_list
[c
->current_fpe
];
270 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
275 while (c
->current_fpe
< c
->num_fpes
) {
276 fpe
= c
->fpe_list
[c
->current_fpe
];
277 err
= (*fpe_functions
[fpe
->type
].open_font
)
278 ((pointer
) client
, fpe
, c
->flags
,
279 c
->fontname
, c
->fnamelen
, FontFormat
,
280 BitmapFormatMaskByte
|
281 BitmapFormatMaskBit
|
282 BitmapFormatMaskImageRectangle
|
283 BitmapFormatMaskScanLinePad
|
284 BitmapFormatMaskScanLineUnit
,
285 c
->fontid
, &pfont
, &alias
,
286 c
->non_cachable_font
&& c
->non_cachable_font
->fpe
== fpe
?
287 c
->non_cachable_font
: (FontPtr
) 0);
289 if (err
== FontNameAlias
&& alias
) {
290 newlen
= strlen(alias
);
291 newname
= (char *) realloc(c
->fontname
, newlen
);
296 memmove(newname
, alias
, newlen
);
297 c
->fontname
= newname
;
298 c
->fnamelen
= newlen
;
300 if (--aliascount
<= 0) {
301 /* We've tried resolving this alias 20 times, we're
302 * probably stuck in an infinite loop of aliases pointing
303 * to each other - time to take emergency exit!
305 err
= BadImplementation
;
310 if (err
== BadFontName
) {
314 if (err
== Suspended
) {
315 if (!ClientIsAsleep(client
))
316 ClientSleep(client
, (ClientSleepProcPtr
) doOpenFont
, c
);
324 if (err
!= Successful
)
330 /* check values for firstCol, lastCol, firstRow, and lastRow */
331 if (pfont
->info
.firstCol
> pfont
->info
.lastCol
||
332 pfont
->info
.firstRow
> pfont
->info
.lastRow
||
333 pfont
->info
.lastCol
- pfont
->info
.firstCol
> 255) {
340 if (pfont
->refcnt
== 1) {
342 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
343 pScr
= screenInfo
.screens
[i
];
344 if (pScr
->RealizeFont
) {
345 if (!(*pScr
->RealizeFont
) (pScr
, pfont
)) {
346 CloseFont(pfont
, (Font
) 0);
353 if (!AddResource(c
->fontid
, RT_FONT
, (pointer
) pfont
)) {
357 if (patternCache
&& pfont
!= c
->non_cachable_font
)
358 CacheFontPattern(patternCache
, c
->origFontName
, c
->origFontNameLen
,
361 if (err
!= Successful
&& c
->client
!= serverClient
) {
362 SendErrorToClient(c
->client
, X_OpenFont
, 0,
363 c
->fontid
, FontToXError(err
));
365 ClientWakeup(c
->client
);
367 for (i
= 0; i
< c
->num_fpes
; i
++) {
368 FreeFPE(c
->fpe_list
[i
]);
377 OpenFont(ClientPtr client
, XID fid
, Mask flags
, unsigned lenfname
,
382 FontPtr cached
= (FontPtr
) 0;
384 if (!lenfname
|| lenfname
> XLFDMAXFONTNAMELEN
)
389 ** Check name cache. If we find a cached version of this font that
390 ** is cachable, immediately satisfy the request with it. If we find
391 ** a cached version of this font that is non-cachable, we do not
392 ** satisfy the request with it. Instead, we pass the FontPtr to the
393 ** FPE's open_font code (the fontfile FPE in turn passes the
394 ** information to the rasterizer; the fserve FPE ignores it).
396 ** Presumably, the font is marked non-cachable because the FPE has
397 ** put some licensing restrictions on it. If the FPE, using
398 ** whatever logic it relies on, determines that it is willing to
399 ** share this existing font with the client, then it has the option
400 ** to return the FontPtr we passed it as the newly-opened font.
401 ** This allows the FPE to exercise its licensing logic without
402 ** having to create another instance of a font that already exists.
405 cached
= FindCachedFontPattern(patternCache
, pfontname
, lenfname
);
406 if (cached
&& cached
->info
.cachable
) {
407 if (!AddResource(fid
, RT_FONT
, (pointer
) cached
))
413 c
= malloc(sizeof(OFclosureRec
));
416 c
->fontname
= malloc(lenfname
);
417 c
->origFontName
= pfontname
;
418 c
->origFontNameLen
= lenfname
;
424 * copy the current FPE list, so that if it gets changed by another client
425 * while we're blocking, the request still appears atomic
427 c
->fpe_list
= malloc(sizeof(FontPathElementPtr
) * num_fpes
);
433 memmove(c
->fontname
, pfontname
, lenfname
);
434 for (i
= 0; i
< num_fpes
; i
++) {
435 c
->fpe_list
[i
] = font_path_elements
[i
];
436 UseFPE(c
->fpe_list
[i
]);
441 c
->num_fpes
= num_fpes
;
442 c
->fnamelen
= lenfname
;
444 c
->non_cachable_font
= cached
;
446 (void) doOpenFont(client
, c
);
451 * Decrement font's ref count, and free storage if ref count equals zero
453 * \param value must conform to DeleteType
456 CloseFont(pointer value
, XID fid
)
460 FontPathElementPtr fpe
;
461 FontPtr pfont
= (FontPtr
) value
;
463 if (pfont
== NullFont
)
465 if (--pfont
->refcnt
== 0) {
467 RemoveCachedFontPattern(patternCache
, pfont
);
469 * since the last reference is gone, ask each screen to free any
470 * storage it may have allocated locally for it.
472 for (nscr
= 0; nscr
< screenInfo
.numScreens
; nscr
++) {
473 pscr
= screenInfo
.screens
[nscr
];
474 if (pscr
->UnrealizeFont
)
475 (*pscr
->UnrealizeFont
) (pscr
, pfont
);
477 if (pfont
== defaultFont
)
480 XF86BigfontFreeFontShm(pfont
);
483 (*fpe_functions
[fpe
->type
].close_font
) (fpe
, pfont
);
489 /***====================================================================***/
492 * Sets up pReply as the correct QueryFontReply for pFont with the first
493 * nProtoCCIStructs char infos.
495 * \param pReply caller must allocate this storage
498 QueryFont(FontPtr pFont
, xQueryFontReply
* pReply
, int nProtoCCIStructs
)
504 xCharInfo
*charInfos
[256];
505 unsigned char chars
[512];
510 /* pr->length set in dispatch */
511 pReply
->minCharOrByte2
= pFont
->info
.firstCol
;
512 pReply
->defaultChar
= pFont
->info
.defaultCh
;
513 pReply
->maxCharOrByte2
= pFont
->info
.lastCol
;
514 pReply
->drawDirection
= pFont
->info
.drawDirection
;
515 pReply
->allCharsExist
= pFont
->info
.allExist
;
516 pReply
->minByte1
= pFont
->info
.firstRow
;
517 pReply
->maxByte1
= pFont
->info
.lastRow
;
518 pReply
->fontAscent
= pFont
->info
.fontAscent
;
519 pReply
->fontDescent
= pFont
->info
.fontDescent
;
521 pReply
->minBounds
= pFont
->info
.ink_minbounds
;
522 pReply
->maxBounds
= pFont
->info
.ink_maxbounds
;
524 pReply
->nFontProps
= pFont
->info
.nprops
;
525 pReply
->nCharInfos
= nProtoCCIStructs
;
527 for (i
= 0, pFP
= pFont
->info
.props
, prFP
= (xFontProp
*) (&pReply
[1]);
528 i
< pFont
->info
.nprops
; i
++, pFP
++, prFP
++) {
529 prFP
->name
= pFP
->name
;
530 prFP
->value
= pFP
->value
;
534 ncols
= (unsigned long) (pFont
->info
.lastCol
- pFont
->info
.firstCol
+ 1);
535 prCI
= (xCharInfo
*) (prFP
);
536 for (r
= pFont
->info
.firstRow
;
537 ninfos
< nProtoCCIStructs
&& r
<= (int) pFont
->info
.lastRow
; r
++) {
539 for (c
= pFont
->info
.firstCol
; c
<= (int) pFont
->info
.lastCol
; c
++) {
543 (*pFont
->get_metrics
) (pFont
, ncols
, chars
,
544 TwoD16Bit
, &count
, charInfos
);
546 for (i
= 0; i
< (int) count
&& ninfos
< nProtoCCIStructs
; i
++) {
547 *prCI
= *charInfos
[i
];
556 doListFontsAndAliases(ClientPtr client
, LFclosurePtr c
)
558 FontPathElementPtr fpe
;
559 int err
= Successful
;
560 FontNamesPtr names
= NULL
;
561 char *name
, *resolved
= NULL
;
562 int namelen
, resolvedlen
;
566 xListFontsReply reply
;
571 if (client
->clientGone
) {
572 if (c
->current
.current_fpe
< c
->num_fpes
) {
573 fpe
= c
->fpe_list
[c
->current
.current_fpe
];
574 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
580 if (!c
->current
.patlen
)
583 while (c
->current
.current_fpe
< c
->num_fpes
) {
584 fpe
= c
->fpe_list
[c
->current
.current_fpe
];
587 if (!fpe_functions
[fpe
->type
].start_list_fonts_and_aliases
) {
588 /* This FPE doesn't support/require list_fonts_and_aliases */
590 err
= (*fpe_functions
[fpe
->type
].list_fonts
)
591 ((pointer
) c
->client
, fpe
, c
->current
.pattern
,
592 c
->current
.patlen
, c
->current
.max_names
- c
->names
->nnames
,
595 if (err
== Suspended
) {
596 if (!ClientIsAsleep(client
))
598 (ClientSleepProcPtr
) doListFontsAndAliases
, c
);
607 /* Start of list_fonts_and_aliases functionality. Modeled
608 after list_fonts_with_info in that it resolves aliases,
609 except that the information collected from FPEs is just
610 names, not font info. Each list_next_font_or_alias()
611 returns either a name into name/namelen or an alias into
612 name/namelen and its target name into resolved/resolvedlen.
613 The code at this level then resolves the alias by polling
616 if (!c
->current
.list_started
) {
617 err
= (*fpe_functions
[fpe
->type
].start_list_fonts_and_aliases
)
618 ((pointer
) c
->client
, fpe
, c
->current
.pattern
,
619 c
->current
.patlen
, c
->current
.max_names
- c
->names
->nnames
,
620 &c
->current
.private);
621 if (err
== Suspended
) {
622 if (!ClientIsAsleep(client
))
624 (ClientSleepProcPtr
) doListFontsAndAliases
,
630 if (err
== Successful
)
631 c
->current
.list_started
= TRUE
;
633 if (err
== Successful
) {
637 err
= (*fpe_functions
[fpe
->type
].list_next_font_or_alias
)
638 ((pointer
) c
->client
, fpe
, &name
, &namelen
, &tmpname
,
639 &resolvedlen
, c
->current
.private);
640 if (err
== Suspended
) {
641 if (!ClientIsAsleep(client
))
643 (ClientSleepProcPtr
) doListFontsAndAliases
,
649 if (err
== FontNameAlias
) {
651 resolved
= malloc(resolvedlen
+ 1);
653 memmove(resolved
, tmpname
, resolvedlen
+ 1);
657 if (err
== Successful
) {
660 (void) AddFontNamesName(c
->names
, c
->savedName
,
664 (void) AddFontNamesName(c
->names
, name
, namelen
);
668 * When we get an alias back, save our state and reset back to
669 * the start of the FPE looking for the specified name. As
670 * soon as a real font is found for the alias, pop back to the
673 else if (err
== FontNameAlias
) {
674 char tmp_pattern
[XLFDMAXFONTNAMELEN
];
677 * when an alias recurses, we need to give
678 * the last FPE a chance to clean up; so we call
679 * it again, and assume that the error returned
680 * is BadFontName, indicating the alias resolution
683 memmove(tmp_pattern
, resolved
, resolvedlen
);
689 (void) (*fpe_functions
[fpe
->type
].list_next_font_or_alias
)
690 ((pointer
) c
->client
, fpe
, &tmpname
, &tmpnamelen
,
691 &tmpname
, &tmpnamelen
, c
->current
.private);
692 if (--aliascount
<= 0) {
694 goto ContBadFontName
;
698 c
->saved
= c
->current
;
701 c
->savedName
= malloc(namelen
+ 1);
703 memmove(c
->savedName
, name
, namelen
+ 1);
704 c
->savedNameLen
= namelen
;
707 memmove(c
->current
.pattern
, tmp_pattern
, resolvedlen
);
708 c
->current
.patlen
= resolvedlen
;
709 c
->current
.max_names
= c
->names
->nnames
+ 1;
710 c
->current
.current_fpe
= -1;
711 c
->current
.private = 0;
716 * At the end of this FPE, step to the next. If we've finished
717 * processing an alias, pop state back. If we've collected enough
720 if (err
== BadFontName
) {
722 c
->current
.list_started
= FALSE
;
723 c
->current
.current_fpe
++;
726 if (c
->names
->nnames
== c
->current
.max_names
||
727 c
->current
.current_fpe
== c
->num_fpes
) {
728 c
->haveSaved
= FALSE
;
729 c
->current
= c
->saved
;
730 /* Give the saved namelist a chance to clean itself up */
734 if (c
->names
->nnames
== c
->current
.max_names
)
742 if (err
!= Successful
) {
743 SendErrorToClient(client
, X_ListFonts
, 0, 0, FontToXError(err
));
750 nnames
= names
->nnames
;
753 for (i
= 0; i
< nnames
; i
++)
754 stringLens
+= (names
->length
[i
] <= 255) ? names
->length
[i
] : 0;
756 reply
= (xListFontsReply
) {
758 .length
= bytes_to_int32(stringLens
+ nnames
),
760 .sequenceNumber
= client
->sequence
763 bufptr
= bufferStart
= malloc(reply
.length
<< 2);
765 if (!bufptr
&& reply
.length
) {
766 SendErrorToClient(client
, X_ListFonts
, 0, 0, BadAlloc
);
770 * since WriteToClient long word aligns things, copy to temp buffer and
773 for (i
= 0; i
< nnames
; i
++) {
774 if (names
->length
[i
] > 255)
777 *bufptr
++ = names
->length
[i
];
778 memmove(bufptr
, names
->names
[i
], names
->length
[i
]);
779 bufptr
+= names
->length
[i
];
782 nnames
= reply
.nFonts
;
783 reply
.length
= bytes_to_int32(stringLens
+ nnames
);
784 client
->pSwapReplyFunc
= ReplySwapVector
[X_ListFonts
];
785 WriteSwappedDataToClient(client
, sizeof(xListFontsReply
), &reply
);
786 WriteToClient(client
, stringLens
+ nnames
, bufferStart
);
790 ClientWakeup(client
);
792 for (i
= 0; i
< c
->num_fpes
; i
++)
793 FreeFPE(c
->fpe_list
[i
]);
796 FreeFontNames(names
);
803 ListFonts(ClientPtr client
, unsigned char *pattern
, unsigned length
,
810 * The right error to return here would be BadName, however the
811 * specification does not allow for a Name error on this request.
812 * Perhaps a better solution would be to return a nil list, i.e.
813 * a list containing zero fontnames.
815 if (length
> XLFDMAXFONTNAMELEN
)
818 i
= XaceHook(XACE_SERVER_ACCESS
, client
, DixGetAttrAccess
);
822 if (!(c
= malloc(sizeof *c
)))
824 c
->fpe_list
= malloc(sizeof(FontPathElementPtr
) * num_fpes
);
829 c
->names
= MakeFontNamesRecord(max_names
< 100 ? max_names
: 100);
835 memmove(c
->current
.pattern
, pattern
, length
);
836 for (i
= 0; i
< num_fpes
; i
++) {
837 c
->fpe_list
[i
] = font_path_elements
[i
];
838 UseFPE(c
->fpe_list
[i
]);
841 c
->num_fpes
= num_fpes
;
842 c
->current
.patlen
= length
;
843 c
->current
.current_fpe
= 0;
844 c
->current
.max_names
= max_names
;
845 c
->current
.list_started
= FALSE
;
846 c
->current
.private = 0;
847 c
->haveSaved
= FALSE
;
849 doListFontsAndAliases(client
, c
);
854 doListFontsWithInfo(ClientPtr client
, LFWIclosurePtr c
)
856 FontPathElementPtr fpe
;
857 int err
= Successful
;
861 FontInfoRec fontInfo
, *pFontInfo
;
862 xListFontsWithInfoReply
*reply
;
867 xListFontsWithInfoReply finalReply
;
869 if (client
->clientGone
) {
870 if (c
->current
.current_fpe
< c
->num_fpes
) {
871 fpe
= c
->fpe_list
[c
->current
.current_fpe
];
872 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
877 client
->pSwapReplyFunc
= ReplySwapVector
[X_ListFontsWithInfo
];
878 if (!c
->current
.patlen
)
880 while (c
->current
.current_fpe
< c
->num_fpes
) {
881 fpe
= c
->fpe_list
[c
->current
.current_fpe
];
883 if (!c
->current
.list_started
) {
884 err
= (*fpe_functions
[fpe
->type
].start_list_fonts_with_info
)
885 (client
, fpe
, c
->current
.pattern
, c
->current
.patlen
,
886 c
->current
.max_names
, &c
->current
.private);
887 if (err
== Suspended
) {
888 if (!ClientIsAsleep(client
))
890 (ClientSleepProcPtr
) doListFontsWithInfo
, c
);
895 if (err
== Successful
)
896 c
->current
.list_started
= TRUE
;
898 if (err
== Successful
) {
900 pFontInfo
= &fontInfo
;
901 err
= (*fpe_functions
[fpe
->type
].list_next_font_with_info
)
902 (client
, fpe
, &name
, &namelen
, &pFontInfo
,
903 &numFonts
, c
->current
.private);
904 if (err
== Suspended
) {
905 if (!ClientIsAsleep(client
))
907 (ClientSleepProcPtr
) doListFontsWithInfo
, c
);
914 * When we get an alias back, save our state and reset back to the
915 * start of the FPE looking for the specified name. As soon as a real
916 * font is found for the alias, pop back to the old state
918 if (err
== FontNameAlias
) {
920 * when an alias recurses, we need to give
921 * the last FPE a chance to clean up; so we call
922 * it again, and assume that the error returned
923 * is BadFontName, indicating the alias resolution
929 FontInfoPtr tmpFontInfo
;
932 tmpFontInfo
= &fontInfo
;
933 (void) (*fpe_functions
[fpe
->type
].list_next_font_with_info
)
934 (client
, fpe
, &tmpname
, &tmpnamelen
, &tmpFontInfo
,
935 &numFonts
, c
->current
.private);
936 if (--aliascount
<= 0) {
938 goto ContBadFontName
;
942 c
->saved
= c
->current
;
944 c
->savedNumFonts
= numFonts
;
946 c
->savedName
= malloc(namelen
+ 1);
948 memmove(c
->savedName
, name
, namelen
+ 1);
951 memmove(c
->current
.pattern
, name
, namelen
);
952 c
->current
.patlen
= namelen
;
953 c
->current
.max_names
= 1;
954 c
->current
.current_fpe
= 0;
955 c
->current
.private = 0;
956 c
->current
.list_started
= FALSE
;
959 * At the end of this FPE, step to the next. If we've finished
960 * processing an alias, pop state back. If we've sent enough font
961 * names, quit. Always wait for BadFontName to let the FPE
962 * have a chance to clean up.
964 else if (err
== BadFontName
) {
966 c
->current
.list_started
= FALSE
;
967 c
->current
.current_fpe
++;
970 if (c
->current
.max_names
== 0 ||
971 c
->current
.current_fpe
== c
->num_fpes
) {
972 c
->haveSaved
= FALSE
;
973 c
->saved
.max_names
-= (1 - c
->current
.max_names
);
974 c
->current
= c
->saved
;
977 else if (c
->current
.max_names
== 0)
980 else if (err
== Successful
) {
981 length
= sizeof(*reply
) + pFontInfo
->nprops
* sizeof(xFontProp
);
983 if (c
->length
< length
) {
984 reply
= (xListFontsWithInfoReply
*) realloc(c
->reply
, length
);
989 memset((char *) reply
+ c
->length
, 0, length
- c
->length
);
994 numFonts
= c
->savedNumFonts
;
996 namelen
= strlen(name
);
998 reply
->type
= X_Reply
;
1000 bytes_to_int32(sizeof *reply
- sizeof(xGenericReply
) +
1001 pFontInfo
->nprops
* sizeof(xFontProp
) + namelen
);
1002 reply
->sequenceNumber
= client
->sequence
;
1003 reply
->nameLength
= namelen
;
1004 reply
->minBounds
= pFontInfo
->ink_minbounds
;
1005 reply
->maxBounds
= pFontInfo
->ink_maxbounds
;
1006 reply
->minCharOrByte2
= pFontInfo
->firstCol
;
1007 reply
->maxCharOrByte2
= pFontInfo
->lastCol
;
1008 reply
->defaultChar
= pFontInfo
->defaultCh
;
1009 reply
->nFontProps
= pFontInfo
->nprops
;
1010 reply
->drawDirection
= pFontInfo
->drawDirection
;
1011 reply
->minByte1
= pFontInfo
->firstRow
;
1012 reply
->maxByte1
= pFontInfo
->lastRow
;
1013 reply
->allCharsExist
= pFontInfo
->allExist
;
1014 reply
->fontAscent
= pFontInfo
->fontAscent
;
1015 reply
->fontDescent
= pFontInfo
->fontDescent
;
1016 reply
->nReplies
= numFonts
;
1017 pFP
= (xFontProp
*) (reply
+ 1);
1018 for (i
= 0; i
< pFontInfo
->nprops
; i
++) {
1019 pFP
->name
= pFontInfo
->props
[i
].name
;
1020 pFP
->value
= pFontInfo
->props
[i
].value
;
1023 WriteSwappedDataToClient(client
, length
, reply
);
1024 WriteToClient(client
, namelen
, name
);
1025 if (pFontInfo
== &fontInfo
) {
1026 free(fontInfo
.props
);
1027 free(fontInfo
.isStringProp
);
1029 --c
->current
.max_names
;
1033 length
= sizeof(xListFontsWithInfoReply
);
1034 finalReply
= (xListFontsWithInfoReply
) {
1036 .sequenceNumber
= client
->sequence
,
1037 .length
= bytes_to_int32(sizeof(xListFontsWithInfoReply
)
1038 - sizeof(xGenericReply
))
1040 WriteSwappedDataToClient(client
, length
, &finalReply
);
1042 ClientWakeup(client
);
1044 for (i
= 0; i
< c
->num_fpes
; i
++)
1045 FreeFPE(c
->fpe_list
[i
]);
1054 StartListFontsWithInfo(ClientPtr client
, int length
, unsigned char *pattern
,
1061 * The right error to return here would be BadName, however the
1062 * specification does not allow for a Name error on this request.
1063 * Perhaps a better solution would be to return a nil list, i.e.
1064 * a list containing zero fontnames.
1066 if (length
> XLFDMAXFONTNAMELEN
)
1069 i
= XaceHook(XACE_SERVER_ACCESS
, client
, DixGetAttrAccess
);
1073 if (!(c
= malloc(sizeof *c
)))
1075 c
->fpe_list
= malloc(sizeof(FontPathElementPtr
) * num_fpes
);
1080 memmove(c
->current
.pattern
, pattern
, length
);
1081 for (i
= 0; i
< num_fpes
; i
++) {
1082 c
->fpe_list
[i
] = font_path_elements
[i
];
1083 UseFPE(c
->fpe_list
[i
]);
1086 c
->num_fpes
= num_fpes
;
1089 c
->current
.patlen
= length
;
1090 c
->current
.current_fpe
= 0;
1091 c
->current
.max_names
= max_names
;
1092 c
->current
.list_started
= FALSE
;
1093 c
->current
.private = 0;
1094 c
->savedNumFonts
= 0;
1095 c
->haveSaved
= FALSE
;
1097 doListFontsWithInfo(client
, c
);
1103 #define TextEltHeader 2
1104 #define FontShiftSize 5
1105 static ChangeGCVal clearGC
[] = { {.ptr
= NullPixmap
} };
1107 #define clearGCmask (GCClipMask)
1110 doPolyText(ClientPtr client
, PTclosurePtr c
)
1112 FontPtr pFont
= c
->pGC
->font
, oldpFont
;
1113 int err
= Success
, lgerr
; /* err is in X error, not font error, space */
1114 enum { NEVER_SLEPT
, START_SLEEP
, SLEEPING
} client_state
= NEVER_SLEPT
;
1115 FontPathElementPtr fpe
;
1117 int itemSize
= c
->reqType
== X_PolyText8
? 1 : 2;
1119 if (client
->clientGone
) {
1120 fpe
= c
->pGC
->font
->fpe
;
1121 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
1123 if (ClientIsAsleep(client
)) {
1124 /* Client has died, but we cannot bail out right now. We
1125 need to clean up after the work we did when going to
1126 sleep. Setting the drawable pointer to 0 makes this
1127 happen without any attempts to render or perform other
1128 unnecessary activities. */
1129 c
->pDraw
= (DrawablePtr
) 0;
1137 /* Make sure our drawable hasn't disappeared while we slept. */
1138 if (ClientIsAsleep(client
) && c
->pDraw
) {
1141 dixLookupDrawable(&pDraw
, c
->did
, client
, 0, DixWriteAccess
);
1142 if (c
->pDraw
!= pDraw
) {
1143 /* Our drawable has disappeared. Treat like client died... ask
1144 the FPE code to clean up after client and avoid further
1145 rendering while we clean up after ourself. */
1146 fpe
= c
->pGC
->font
->fpe
;
1147 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
1148 c
->pDraw
= (DrawablePtr
) 0;
1152 client_state
= ClientIsAsleep(client
) ? SLEEPING
: NEVER_SLEPT
;
1154 while (c
->endReq
- c
->pElt
> TextEltHeader
) {
1155 if (*c
->pElt
== FontChange
) {
1158 if (c
->endReq
- c
->pElt
< FontShiftSize
) {
1165 fid
= ((Font
) *(c
->pElt
+ 4)) /* big-endian */
1166 |((Font
) *(c
->pElt
+ 3)) << 8
1167 | ((Font
) *(c
->pElt
+ 2)) << 16 | ((Font
) *(c
->pElt
+ 1)) << 24;
1168 err
= dixLookupResourceByType((pointer
*) &pFont
, fid
, RT_FONT
,
1169 client
, DixUseAccess
);
1170 if (err
!= Success
) {
1171 /* restore pFont for step 4 (described below) */
1174 /* If we're in START_SLEEP mode, the following step
1175 shortens the request... in the unlikely event that
1176 the fid somehow becomes valid before we come through
1177 again to actually execute the polytext, which would
1178 then mess up our refcounting scheme badly. */
1180 c
->endReq
= c
->pElt
;
1185 /* Step 3 (described below) on our new font */
1186 if (client_state
== START_SLEEP
)
1189 if (pFont
!= c
->pGC
->font
&& c
->pDraw
) {
1193 ChangeGC(NullClient
, c
->pGC
, GCFont
, &val
);
1194 ValidateGC(c
->pDraw
, c
->pGC
);
1197 /* Undo the refcnt++ we performed when going to sleep */
1198 if (client_state
== SLEEPING
)
1199 (void) CloseFont(c
->pGC
->font
, (Font
) 0);
1201 c
->pElt
+= FontShiftSize
;
1203 else { /* print a string */
1205 unsigned char *pNextElt
;
1207 pNextElt
= c
->pElt
+ TextEltHeader
+ (*c
->pElt
) * itemSize
;
1208 if (pNextElt
> c
->endReq
) {
1212 if (client_state
== START_SLEEP
) {
1217 lgerr
= LoadGlyphs(client
, c
->pGC
->font
, *c
->pElt
, itemSize
,
1218 c
->pElt
+ TextEltHeader
);
1223 if (lgerr
== Suspended
) {
1224 if (!ClientIsAsleep(client
)) {
1227 PTclosurePtr new_closure
;
1229 /* We're putting the client to sleep. We need to do a few things
1230 to ensure successful and atomic-appearing execution of the
1231 remainder of the request. First, copy the remainder of the
1232 request into a safe malloc'd area. Second, create a scratch GC
1233 to use for the remainder of the request. Third, mark all fonts
1234 referenced in the remainder of the request to prevent their
1235 deallocation. Fourth, make the original GC look like the
1236 request has completed... set its font to the final font value
1237 from this request. These GC manipulations are for the unlikely
1238 (but possible) event that some other client is using the GC.
1239 Steps 3 and 4 are performed by running this procedure through
1240 the remainder of the request in a special no-render mode
1241 indicated by client_state = START_SLEEP. */
1244 /* Allocate a malloc'd closure structure to replace
1245 the local one we were passed */
1246 new_closure
= malloc(sizeof(PTclosureRec
));
1253 len
= new_closure
->endReq
- new_closure
->pElt
;
1254 new_closure
->data
= malloc(len
);
1255 if (!new_closure
->data
) {
1260 memmove(new_closure
->data
, new_closure
->pElt
, len
);
1261 new_closure
->pElt
= new_closure
->data
;
1262 new_closure
->endReq
= new_closure
->pElt
+ len
;
1267 GetScratchGC(new_closure
->pGC
->depth
,
1268 new_closure
->pGC
->pScreen
);
1270 free(new_closure
->data
);
1275 if ((err
= CopyGC(new_closure
->pGC
, pGC
, GCFunction
|
1276 GCPlaneMask
| GCForeground
|
1277 GCBackground
| GCFillStyle
|
1278 GCTile
| GCStipple
|
1280 GCTileStipYOrigin
| GCFont
|
1281 GCSubwindowMode
| GCClipXOrigin
|
1282 GCClipYOrigin
| GCClipMask
)) != Success
) {
1284 free(new_closure
->data
);
1292 ValidateGC(c
->pDraw
, c
->pGC
);
1294 ClientSleep(client
, (ClientSleepProcPtr
) doPolyText
, c
);
1296 /* Set up to perform steps 3 and 4 */
1297 client_state
= START_SLEEP
;
1298 continue; /* on to steps 3 and 4 */
1301 goto xinerama_sleep
;
1304 else if (lgerr
!= Successful
) {
1305 err
= FontToXError(lgerr
);
1309 c
->xorg
+= *((INT8
*) (c
->pElt
+ 1)); /* must be signed */
1310 if (c
->reqType
== X_PolyText8
)
1312 (*c
->pGC
->ops
->PolyText8
) (c
->pDraw
, c
->pGC
, c
->xorg
,
1318 (*c
->pGC
->ops
->PolyText16
) (c
->pDraw
, c
->pGC
, c
->xorg
,
1320 (unsigned short *) (c
->
1330 if (client_state
== START_SLEEP
) {
1332 if (pFont
!= origGC
->font
) {
1336 ChangeGC(NullClient
, origGC
, GCFont
, &val
);
1337 ValidateGC(c
->pDraw
, origGC
);
1340 /* restore pElt pointer for execution of remainder of the request */
1345 if (c
->err
!= Success
)
1347 if (err
!= Success
&& c
->client
!= serverClient
) {
1349 if (noPanoramiXExtension
|| !c
->pGC
->pScreen
->myNum
)
1351 SendErrorToClient(c
->client
, c
->reqType
, 0, 0, err
);
1353 if (ClientIsAsleep(client
)) {
1354 ClientWakeup(c
->client
);
1356 ChangeGC(NullClient
, c
->pGC
, clearGCmask
, clearGC
);
1358 /* Unreference the font from the scratch GC */
1359 CloseFont(c
->pGC
->font
, (Font
) 0);
1360 c
->pGC
->font
= NullFont
;
1362 FreeScratchGC(c
->pGC
);
1370 PolyText(ClientPtr client
, DrawablePtr pDraw
, GC
* pGC
, unsigned char *pElt
,
1371 unsigned char *endReq
, int xorg
, int yorg
, int reqType
, XID did
)
1373 PTclosureRec local_closure
;
1375 local_closure
.pElt
= pElt
;
1376 local_closure
.endReq
= endReq
;
1377 local_closure
.client
= client
;
1378 local_closure
.pDraw
= pDraw
;
1379 local_closure
.xorg
= xorg
;
1380 local_closure
.yorg
= yorg
;
1381 local_closure
.reqType
= reqType
;
1382 local_closure
.pGC
= pGC
;
1383 local_closure
.did
= did
;
1384 local_closure
.err
= Success
;
1386 (void) doPolyText(client
, &local_closure
);
1390 #undef TextEltHeader
1391 #undef FontShiftSize
1394 doImageText(ClientPtr client
, ITclosurePtr c
)
1396 int err
= Success
, lgerr
; /* err is in X error, not font error, space */
1397 FontPathElementPtr fpe
;
1398 int itemSize
= c
->reqType
== X_ImageText8
? 1 : 2;
1400 if (client
->clientGone
) {
1401 fpe
= c
->pGC
->font
->fpe
;
1402 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
1407 /* Make sure our drawable hasn't disappeared while we slept. */
1408 if (ClientIsAsleep(client
) && c
->pDraw
) {
1411 dixLookupDrawable(&pDraw
, c
->did
, client
, 0, DixWriteAccess
);
1412 if (c
->pDraw
!= pDraw
) {
1413 /* Our drawable has disappeared. Treat like client died... ask
1414 the FPE code to clean up after client. */
1415 fpe
= c
->pGC
->font
->fpe
;
1416 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
1422 lgerr
= LoadGlyphs(client
, c
->pGC
->font
, c
->nChars
, itemSize
, c
->data
);
1423 if (lgerr
== Suspended
) {
1424 if (!ClientIsAsleep(client
)) {
1426 unsigned char *data
;
1427 ITclosurePtr new_closure
;
1428 ITclosurePtr old_closure
;
1430 /* We're putting the client to sleep. We need to
1431 save some state. Similar problem to that handled
1432 in doPolyText, but much simpler because the
1433 request structure is much simpler. */
1435 new_closure
= malloc(sizeof(ITclosureRec
));
1444 data
= malloc(c
->nChars
* itemSize
);
1451 memmove(data
, c
->data
, c
->nChars
* itemSize
);
1454 pGC
= GetScratchGC(c
->pGC
->depth
, c
->pGC
->pScreen
);
1462 if ((err
= CopyGC(c
->pGC
, pGC
, GCFunction
| GCPlaneMask
|
1463 GCForeground
| GCBackground
| GCFillStyle
|
1464 GCTile
| GCStipple
| GCTileStipXOrigin
|
1465 GCTileStipYOrigin
| GCFont
|
1466 GCSubwindowMode
| GCClipXOrigin
|
1467 GCClipYOrigin
| GCClipMask
)) != Success
) {
1476 ValidateGC(c
->pDraw
, c
->pGC
);
1478 ClientSleep(client
, (ClientSleepProcPtr
) doImageText
, c
);
1481 goto xinerama_sleep
;
1484 else if (lgerr
!= Successful
) {
1485 err
= FontToXError(lgerr
);
1489 if (c
->reqType
== X_ImageText8
)
1490 (*c
->pGC
->ops
->ImageText8
) (c
->pDraw
, c
->pGC
, c
->xorg
, c
->yorg
,
1491 c
->nChars
, (char *) c
->data
);
1493 (*c
->pGC
->ops
->ImageText16
) (c
->pDraw
, c
->pGC
, c
->xorg
, c
->yorg
,
1494 c
->nChars
, (unsigned short *) c
->data
);
1499 if (err
!= Success
&& c
->client
!= serverClient
) {
1500 SendErrorToClient(c
->client
, c
->reqType
, 0, 0, err
);
1502 if (ClientIsAsleep(client
)) {
1503 ClientWakeup(c
->client
);
1505 ChangeGC(NullClient
, c
->pGC
, clearGCmask
, clearGC
);
1507 /* Unreference the font from the scratch GC */
1508 CloseFont(c
->pGC
->font
, (Font
) 0);
1509 c
->pGC
->font
= NullFont
;
1511 FreeScratchGC(c
->pGC
);
1519 ImageText(ClientPtr client
, DrawablePtr pDraw
, GC
* pGC
, int nChars
,
1520 unsigned char *data
, int xorg
, int yorg
, int reqType
, XID did
)
1522 ITclosureRec local_closure
;
1524 local_closure
.client
= client
;
1525 local_closure
.pDraw
= pDraw
;
1526 local_closure
.pGC
= pGC
;
1527 local_closure
.nChars
= nChars
;
1528 local_closure
.data
= data
;
1529 local_closure
.xorg
= xorg
;
1530 local_closure
.yorg
= yorg
;
1531 local_closure
.reqType
= reqType
;
1532 local_closure
.did
= did
;
1534 (void) doImageText(client
, &local_closure
);
1538 /* does the necessary magic to figure out the fpe type */
1540 DetermineFPEType(char *pathname
)
1544 for (i
= 0; i
< num_fpe_types
; i
++) {
1545 if ((*fpe_functions
[i
].name_check
) (pathname
))
1552 FreeFontPath(FontPathElementPtr
* list
, int n
, Bool force
)
1556 for (i
= 0; i
< n
; i
++) {
1558 /* Sanity check that all refcounts will be 0 by the time
1559 we get to the end of the list. */
1560 int found
= 1; /* the first reference is us */
1563 for (j
= i
+ 1; j
< n
; j
++) {
1564 if (list
[j
] == list
[i
])
1567 if (list
[i
]->refcount
!= found
) {
1568 list
[i
]->refcount
= found
; /* ensure it will get freed */
1576 static FontPathElementPtr
1577 find_existing_fpe(FontPathElementPtr
* list
, int num
, unsigned char *name
,
1580 FontPathElementPtr fpe
;
1583 for (i
= 0; i
< num
; i
++) {
1585 if (fpe
->name_length
== len
&& memcmp(name
, fpe
->name
, len
) == 0)
1588 return (FontPathElementPtr
) 0;
1592 SetFontPathElements(int npaths
, unsigned char *paths
, int *bad
, Bool persist
)
1595 int valid_paths
= 0;
1597 unsigned char *cp
= paths
;
1598 FontPathElementPtr fpe
= NULL
, *fplist
;
1600 fplist
= malloc(sizeof(FontPathElementPtr
) * npaths
);
1605 for (i
= 0; i
< num_fpe_types
; i
++) {
1606 if (fpe_functions
[i
].set_path_hook
)
1607 (*fpe_functions
[i
].set_path_hook
) ();
1609 for (i
= 0; i
< npaths
; i
++) {
1610 len
= (unsigned int) (*cp
++);
1615 ("[dix] Removing empty element from the valid list of fontpaths\n");
1619 /* if it's already in our active list, just reset it */
1621 * note that this can miss FPE's in limbo -- may be worth catching
1622 * them, though it'd muck up refcounting
1624 fpe
= find_existing_fpe(font_path_elements
, num_fpes
, cp
, len
);
1626 err
= (*fpe_functions
[fpe
->type
].reset_fpe
) (fpe
);
1627 if (err
== Successful
) {
1628 UseFPE(fpe
); /* since it'll be decref'd later when freed
1629 * from the old list */
1634 /* if error or can't do it, act like it's a new one */
1636 fpe
= malloc(sizeof(FontPathElementRec
));
1641 fpe
->name
= malloc(len
+ 1);
1649 strncpy(fpe
->name
, (char *) cp
, (int) len
);
1650 fpe
->name
[len
] = '\0';
1651 fpe
->name_length
= len
;
1652 fpe
->type
= DetermineFPEType(fpe
->name
);
1653 if (fpe
->type
== -1)
1656 err
= (*fpe_functions
[fpe
->type
].init_fpe
) (fpe
);
1657 if (err
!= Successful
) {
1660 ("[dix] Could not init font path element %s, removing from list!\n",
1668 if (err
!= Successful
) {
1673 fplist
[valid_paths
++] = fpe
;
1678 FreeFontPath(font_path_elements
, num_fpes
, FALSE
);
1679 font_path_elements
= fplist
;
1681 EmptyFontPatternCache(patternCache
);
1682 num_fpes
= valid_paths
;
1687 while (--valid_paths
>= 0)
1688 FreeFPE(fplist
[valid_paths
]);
1690 return FontToXError(err
);
1694 SetFontPath(ClientPtr client
, int npaths
, unsigned char *paths
)
1696 int err
= XaceHook(XACE_SERVER_ACCESS
, client
, DixManageAccess
);
1702 if (SetDefaultFontPath(defaultFontPath
) != Success
)
1708 err
= SetFontPathElements(npaths
, paths
, &bad
, FALSE
);
1709 client
->errorValue
= bad
;
1715 SetDefaultFontPath(char *path
)
1717 char *temp_path
, *start
, *end
;
1718 unsigned char *cp
, *pp
, *nump
, *newpath
;
1719 int num
= 1, len
, err
, size
= 0, bad
;
1721 /* ensure temp_path contains "built-ins" */
1724 start
= strstr(start
, "built-ins");
1727 end
= start
+ strlen("built-ins");
1728 if ((start
== path
|| start
[-1] == ',') && (!*end
|| *end
== ','))
1733 if (asprintf(&temp_path
, "%s%sbuilt-ins", path
, *path
? "," : "")
1738 temp_path
= strdup(path
);
1743 /* get enough for string, plus values -- use up commas */
1744 len
= strlen(temp_path
) + 1;
1745 nump
= cp
= newpath
= malloc(len
);
1750 pp
= (unsigned char *) temp_path
;
1754 *nump
= (unsigned char) size
;
1765 *nump
= (unsigned char) size
;
1767 err
= SetFontPathElements(num
, newpath
, &bad
, TRUE
);
1776 GetFontPath(ClientPtr client
, int *count
, int *length
, unsigned char **result
)
1781 FontPathElementPtr fpe
;
1783 i
= XaceHook(XACE_SERVER_ACCESS
, client
, DixGetAttrAccess
);
1788 for (i
= 0; i
< num_fpes
; i
++) {
1789 fpe
= font_path_elements
[i
];
1790 len
+= fpe
->name_length
+ 1;
1792 c
= realloc(font_path_string
, len
);
1794 free(font_path_string
);
1795 font_path_string
= NULL
;
1799 font_path_string
= c
;
1801 for (i
= 0; i
< num_fpes
; i
++) {
1802 fpe
= font_path_elements
[i
];
1803 *c
= fpe
->name_length
;
1805 memmove(c
, fpe
->name
, fpe
->name_length
);
1806 c
+= fpe
->name_length
;
1809 *result
= font_path_string
;
1814 DeleteClientFontStuff(ClientPtr client
)
1817 FontPathElementPtr fpe
;
1819 for (i
= 0; i
< num_fpes
; i
++) {
1820 fpe
= font_path_elements
[i
];
1821 if (fpe_functions
[fpe
->type
].client_died
)
1822 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
1829 patternCache
= MakeFontPatternCache();
1831 register_fpe_functions();
1836 GetDefaultPointSize(void)
1843 GetClientResolutions(int *num
)
1845 static struct _FontResolution res
;
1848 pScreen
= screenInfo
.screens
[0];
1849 res
.x_resolution
= (pScreen
->width
* 25.4) / pScreen
->mmWidth
;
1851 * XXX - we'll want this as long as bitmap instances are prevalent
1852 so that we can match them from scalable fonts
1854 if (res
.x_resolution
< 88)
1855 res
.x_resolution
= 75;
1857 res
.x_resolution
= 100;
1858 res
.y_resolution
= (pScreen
->height
* 25.4) / pScreen
->mmHeight
;
1859 if (res
.y_resolution
< 88)
1860 res
.y_resolution
= 75;
1862 res
.y_resolution
= 100;
1863 res
.point_size
= 120;
1869 * returns the type index of the new fpe
1871 * should be called (only once!) by each type of fpe when initialized
1876 RegisterFPEFunctions(NameCheckFunc name_func
,
1877 InitFpeFunc init_func
,
1878 FreeFpeFunc free_func
,
1879 ResetFpeFunc reset_func
,
1880 OpenFontFunc open_func
,
1881 CloseFontFunc close_func
,
1882 ListFontsFunc list_func
,
1883 StartLfwiFunc start_lfwi_func
,
1884 NextLfwiFunc next_lfwi_func
,
1885 WakeupFpeFunc wakeup_func
,
1886 ClientDiedFunc client_died
,
1887 LoadGlyphsFunc load_glyphs
,
1888 StartLaFunc start_list_alias_func
,
1889 NextLaFunc next_list_alias_func
, SetPathFunc set_path_func
)
1894 new = (FPEFunctions
*) realloc(fpe_functions
,
1895 (num_fpe_types
+ 1) * sizeof(FPEFunctions
));
1898 fpe_functions
= new;
1900 fpe_functions
[num_fpe_types
].name_check
= name_func
;
1901 fpe_functions
[num_fpe_types
].open_font
= open_func
;
1902 fpe_functions
[num_fpe_types
].close_font
= close_func
;
1903 fpe_functions
[num_fpe_types
].wakeup_fpe
= wakeup_func
;
1904 fpe_functions
[num_fpe_types
].list_fonts
= list_func
;
1905 fpe_functions
[num_fpe_types
].start_list_fonts_with_info
= start_lfwi_func
;
1906 fpe_functions
[num_fpe_types
].list_next_font_with_info
= next_lfwi_func
;
1907 fpe_functions
[num_fpe_types
].init_fpe
= init_func
;
1908 fpe_functions
[num_fpe_types
].free_fpe
= free_func
;
1909 fpe_functions
[num_fpe_types
].reset_fpe
= reset_func
;
1910 fpe_functions
[num_fpe_types
].client_died
= client_died
;
1911 fpe_functions
[num_fpe_types
].load_glyphs
= load_glyphs
;
1912 fpe_functions
[num_fpe_types
].start_list_fonts_and_aliases
=
1913 start_list_alias_func
;
1914 fpe_functions
[num_fpe_types
].list_next_font_or_alias
= next_list_alias_func
;
1915 fpe_functions
[num_fpe_types
].set_path_hook
= set_path_func
;
1917 return num_fpe_types
++;
1924 FreeFontPatternCache(patternCache
);
1927 FreeFontPath(font_path_elements
, num_fpes
, TRUE
);
1928 font_path_elements
= 0;
1930 free(fpe_functions
);
1932 fpe_functions
= (FPEFunctions
*) 0;
1935 /* convenience functions for FS interface */
1938 find_old_font(XID id
)
1942 dixLookupResourceByType(&pFont
, id
, RT_NONE
, serverClient
, DixReadAccess
);
1943 return (FontPtr
) pFont
;
1948 GetNewFontClientID(void)
1950 return FakeClientID(0);
1955 StoreFontClientFont(FontPtr pfont
, Font id
)
1957 return AddResource(id
, RT_NONE
, (pointer
) pfont
);
1962 DeleteFontClientID(Font id
)
1964 FreeResource(id
, RT_NONE
);
1969 client_auth_generation(ClientPtr client
)
1974 static int fs_handlers_installed
= 0;
1975 static unsigned int last_server_gen
;
1979 init_fs_handlers(FontPathElementPtr fpe
, BlockHandlerProcPtr block_handler
)
1981 /* if server has reset, make sure the b&w handlers are reinstalled */
1982 if (last_server_gen
< serverGeneration
) {
1983 last_server_gen
= serverGeneration
;
1984 fs_handlers_installed
= 0;
1986 if (fs_handlers_installed
== 0) {
1987 if (!RegisterBlockAndWakeupHandlers(block_handler
,
1988 FontWakeup
, (pointer
) 0))
1990 fs_handlers_installed
++;
1992 QueueFontWakeup(fpe
);
1998 remove_fs_handlers(FontPathElementPtr fpe
, BlockHandlerProcPtr block_handler
,
2002 /* remove the handlers if no one else is using them */
2003 if (--fs_handlers_installed
== 0) {
2004 RemoveBlockAndWakeupHandlers(block_handler
, FontWakeup
,
2008 RemoveFontWakeup(fpe
);