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 ******************************************************************/
52 #ifdef HAVE_DIX_CONFIG_H
53 #include <dix-config.h>
58 #include <X11/Xproto.h>
59 #include "scrnintstr.h"
61 #include "dixstruct.h"
62 #include "cursorstr.h"
65 #include "dixfontstr.h"
74 #include "panoramiX.h"
78 #define _XF86BIGFONT_SERVER_
79 #include <X11/extensions/xf86bigfont.h>
82 #define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics
84 extern pointer fosNaturalParams
;
85 extern FontPtr defaultFont
;
87 static FontPathElementPtr
*font_path_elements
= (FontPathElementPtr
*) 0;
88 static int num_fpes
= 0;
89 _X_EXPORT FPEFunctions
*fpe_functions
= (FPEFunctions
*) 0;
90 static int num_fpe_types
= 0;
92 static unsigned char *font_path_string
;
94 static int num_slept_fpes
= 0;
95 static int size_slept_fpes
= 0;
96 static FontPathElementPtr
*slept_fpes
= (FontPathElementPtr
*) 0;
97 static FontPatternCachePtr patternCache
;
111 case BadFontFormat
: /* is there something better? */
121 * adding RT_FONT prevents conflict with default cursor font
124 SetDefaultFont(char *defaultfontname
)
130 fid
= FakeClientID(0);
131 err
= OpenFont(serverClient
, fid
, FontLoadAll
| FontOpenSync
,
132 (unsigned) strlen(defaultfontname
), defaultfontname
);
135 pf
= (FontPtr
) LookupIDByType(fid
, RT_FONT
);
136 if (pf
== (FontPtr
) NULL
)
143 * note that the font wakeup queue is not refcounted. this is because
144 * an fpe needs to be added when it's inited, and removed when it's finally
145 * freed, in order to handle any data that isn't requested, like FS events.
147 * since the only thing that should call these routines is the renderer's
148 * init_fpe() and free_fpe(), there shouldn't be any problem in using
152 QueueFontWakeup(FontPathElementPtr fpe
)
155 FontPathElementPtr
*new;
157 for (i
= 0; i
< num_slept_fpes
; i
++) {
158 if (slept_fpes
[i
] == fpe
) {
162 if (num_slept_fpes
== size_slept_fpes
) {
163 new = (FontPathElementPtr
*)
165 sizeof(FontPathElementPtr
) * (size_slept_fpes
+ 4));
169 size_slept_fpes
+= 4;
171 slept_fpes
[num_slept_fpes
] = fpe
;
176 RemoveFontWakeup(FontPathElementPtr fpe
)
181 for (i
= 0; i
< num_slept_fpes
; i
++) {
182 if (slept_fpes
[i
] == fpe
) {
183 for (j
= i
; j
< num_slept_fpes
; j
++) {
184 slept_fpes
[j
] = slept_fpes
[j
+ 1];
193 FontWakeup(pointer data
, int count
, pointer LastSelectMask
)
196 FontPathElementPtr fpe
;
200 /* wake up any fpe's that may be waiting for information */
201 for (i
= 0; i
< num_slept_fpes
; i
++) {
203 (void) (*fpe_functions
[fpe
->type
].wakeup_fpe
) (fpe
, LastSelectMask
);
207 /* XXX -- these two funcs may want to be broken into macros */
209 UseFPE(FontPathElementPtr fpe
)
215 FreeFPE (FontPathElementPtr fpe
)
218 if (fpe
->refcount
== 0) {
219 (*fpe_functions
[fpe
->type
].free_fpe
) (fpe
);
226 doOpenFont(ClientPtr client
, OFclosurePtr c
)
228 FontPtr pfont
= NullFont
;
229 FontPathElementPtr fpe
= NULL
;
231 int err
= Successful
;
238 * Decide at runtime what FontFormat to use.
242 ((screenInfo
.imageByteOrder
== LSBFirst
) ?
243 BitmapFormatByteOrderLSB
: BitmapFormatByteOrderMSB
) |
245 ((screenInfo
.bitmapBitOrder
== LSBFirst
) ?
246 BitmapFormatBitOrderLSB
: BitmapFormatBitOrderMSB
) |
248 BitmapFormatImageRectMin
|
250 #if GLYPHPADBYTES == 1
251 BitmapFormatScanlinePad8
|
254 #if GLYPHPADBYTES == 2
255 BitmapFormatScanlinePad16
|
258 #if GLYPHPADBYTES == 4
259 BitmapFormatScanlinePad32
|
262 #if GLYPHPADBYTES == 8
263 BitmapFormatScanlinePad64
|
266 BitmapFormatScanlineUnit8
;
268 if (client
->clientGone
)
270 if (c
->current_fpe
< c
->num_fpes
)
272 fpe
= c
->fpe_list
[c
->current_fpe
];
273 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
278 while (c
->current_fpe
< c
->num_fpes
) {
279 fpe
= c
->fpe_list
[c
->current_fpe
];
280 err
= (*fpe_functions
[fpe
->type
].open_font
)
281 ((pointer
) client
, fpe
, c
->flags
,
282 c
->fontname
, c
->fnamelen
, FontFormat
,
283 BitmapFormatMaskByte
|
284 BitmapFormatMaskBit
|
285 BitmapFormatMaskImageRectangle
|
286 BitmapFormatMaskScanLinePad
|
287 BitmapFormatMaskScanLineUnit
,
288 c
->fontid
, &pfont
, &alias
,
289 c
->non_cachable_font
&& c
->non_cachable_font
->fpe
== fpe
?
290 c
->non_cachable_font
:
293 if (err
== FontNameAlias
&& alias
) {
294 newlen
= strlen(alias
);
295 newname
= (char *) xrealloc(c
->fontname
, newlen
);
300 memmove(newname
, alias
, newlen
);
301 c
->fontname
= newname
;
302 c
->fnamelen
= newlen
;
304 if (--aliascount
<= 0)
308 if (err
== BadFontName
) {
312 if (err
== Suspended
) {
315 ClientSleep(client
, (ClientSleepProcPtr
)doOpenFont
, (pointer
) c
);
322 if (err
!= Successful
)
331 if (pfont
->refcnt
== 1) {
333 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
334 pScr
= screenInfo
.screens
[i
];
335 if (pScr
->RealizeFont
)
337 if (!(*pScr
->RealizeFont
) (pScr
, pfont
))
339 CloseFont (pfont
, (Font
) 0);
346 if (!AddResource(c
->fontid
, RT_FONT
, (pointer
) pfont
)) {
350 if (patternCache
&& pfont
!= c
->non_cachable_font
)
351 CacheFontPattern(patternCache
, c
->origFontName
, c
->origFontNameLen
,
354 if (err
!= Successful
&& c
->client
!= serverClient
) {
355 SendErrorToClient(c
->client
, X_OpenFont
, 0,
356 c
->fontid
, FontToXError(err
));
359 ClientWakeup(c
->client
);
360 for (i
= 0; i
< c
->num_fpes
; i
++) {
361 FreeFPE(c
->fpe_list
[i
]);
370 OpenFont(ClientPtr client
, XID fid
, Mask flags
, unsigned lenfname
, char *pfontname
)
374 FontPtr cached
= (FontPtr
)0;
378 f
= (char *)xalloc(lenfname
+ 1);
379 memmove(f
, pfontname
, lenfname
);
381 ErrorF("OpenFont: fontname is \"%s\"\n", f
);
384 if (!lenfname
|| lenfname
> XLFDMAXFONTNAMELEN
)
390 ** Check name cache. If we find a cached version of this font that
391 ** is cachable, immediately satisfy the request with it. If we find
392 ** a cached version of this font that is non-cachable, we do not
393 ** satisfy the request with it. Instead, we pass the FontPtr to the
394 ** FPE's open_font code (the fontfile FPE in turn passes the
395 ** information to the rasterizer; the fserve FPE ignores it).
397 ** Presumably, the font is marked non-cachable because the FPE has
398 ** put some licensing restrictions on it. If the FPE, using
399 ** whatever logic it relies on, determines that it is willing to
400 ** share this existing font with the client, then it has the option
401 ** to return the FontPtr we passed it as the newly-opened font.
402 ** This allows the FPE to exercise its licensing logic without
403 ** having to create another instance of a font that already exists.
406 cached
= FindCachedFontPattern(patternCache
, pfontname
, lenfname
);
407 if (cached
&& cached
->info
.cachable
)
409 if (!AddResource(fid
, RT_FONT
, (pointer
) cached
))
415 c
= (OFclosurePtr
) xalloc(sizeof(OFclosureRec
));
418 c
->fontname
= (char *) xalloc(lenfname
);
419 c
->origFontName
= pfontname
;
420 c
->origFontNameLen
= lenfname
;
426 * copy the current FPE list, so that if it gets changed by another client
427 * while we're blocking, the request still appears atomic
429 c
->fpe_list
= (FontPathElementPtr
*)
430 xalloc(sizeof(FontPathElementPtr
) * num_fpes
);
436 memmove(c
->fontname
, pfontname
, lenfname
);
437 for (i
= 0; i
< num_fpes
; i
++) {
438 c
->fpe_list
[i
] = font_path_elements
[i
];
439 UseFPE(c
->fpe_list
[i
]);
444 c
->num_fpes
= num_fpes
;
445 c
->fnamelen
= lenfname
;
448 c
->non_cachable_font
= cached
;
450 (void) doOpenFont(client
, c
);
455 * Decrement font's ref count, and free storage if ref count equals zero
457 * \param value must conform to DeleteType
460 CloseFont(pointer value
, XID fid
)
464 FontPathElementPtr fpe
;
465 FontPtr pfont
= (FontPtr
)value
;
467 if (pfont
== NullFont
)
469 if (--pfont
->refcnt
== 0) {
471 RemoveCachedFontPattern (patternCache
, pfont
);
473 * since the last reference is gone, ask each screen to free any
474 * storage it may have allocated locally for it.
476 for (nscr
= 0; nscr
< screenInfo
.numScreens
; nscr
++) {
477 pscr
= screenInfo
.screens
[nscr
];
478 if (pscr
->UnrealizeFont
)
479 (*pscr
->UnrealizeFont
) (pscr
, pfont
);
481 if (pfont
== defaultFont
)
484 XF86BigfontFreeFontShm(pfont
);
487 (*fpe_functions
[fpe
->type
].close_font
) (fpe
, pfont
);
494 /***====================================================================***/
497 * Sets up pReply as the correct QueryFontReply for pFont with the first
498 * nProtoCCIStructs char infos.
500 * \param pReply caller must allocate this storage
503 QueryFont(FontPtr pFont
, xQueryFontReply
*pReply
, int nProtoCCIStructs
)
511 xCharInfo
*charInfos
[256];
512 unsigned char chars
[512];
517 /* pr->length set in dispatch */
518 pReply
->minCharOrByte2
= pFont
->info
.firstCol
;
519 pReply
->defaultChar
= pFont
->info
.defaultCh
;
520 pReply
->maxCharOrByte2
= pFont
->info
.lastCol
;
521 pReply
->drawDirection
= pFont
->info
.drawDirection
;
522 pReply
->allCharsExist
= pFont
->info
.allExist
;
523 pReply
->minByte1
= pFont
->info
.firstRow
;
524 pReply
->maxByte1
= pFont
->info
.lastRow
;
525 pReply
->fontAscent
= pFont
->info
.fontAscent
;
526 pReply
->fontDescent
= pFont
->info
.fontDescent
;
528 pReply
->minBounds
= pFont
->info
.ink_minbounds
;
529 pReply
->maxBounds
= pFont
->info
.ink_maxbounds
;
531 pReply
->nFontProps
= pFont
->info
.nprops
;
532 pReply
->nCharInfos
= nProtoCCIStructs
;
534 for (i
= 0, pFP
= pFont
->info
.props
, prFP
= (xFontProp
*) (&pReply
[1]);
535 i
< pFont
->info
.nprops
;
536 i
++, pFP
++, prFP
++) {
537 prFP
->name
= pFP
->name
;
538 prFP
->value
= pFP
->value
;
542 ncols
= (unsigned long) (pFont
->info
.lastCol
- pFont
->info
.firstCol
+ 1);
543 prCI
= (xCharInfo
*) (prFP
);
544 for (r
= pFont
->info
.firstRow
;
545 ninfos
< nProtoCCIStructs
&& r
<= (int)pFont
->info
.lastRow
;
548 for (c
= pFont
->info
.firstCol
; c
<= (int)pFont
->info
.lastCol
; c
++) {
552 (*pFont
->get_metrics
) (pFont
, ncols
, chars
,
553 TwoD16Bit
, &count
, charInfos
);
555 for (i
= 0; i
< (int) count
&& ninfos
< nProtoCCIStructs
; i
++) {
556 *prCI
= *charInfos
[i
];
565 doListFontsAndAliases(ClientPtr client
, LFclosurePtr c
)
567 FontPathElementPtr fpe
;
568 int err
= Successful
;
569 FontNamesPtr names
= NULL
;
570 char *name
, *resolved
=NULL
;
571 int namelen
, resolvedlen
;
575 xListFontsReply reply
;
580 if (client
->clientGone
)
582 if (c
->current
.current_fpe
< c
->num_fpes
)
584 fpe
= c
->fpe_list
[c
->current
.current_fpe
];
585 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
591 if (!c
->current
.patlen
)
594 while (c
->current
.current_fpe
< c
->num_fpes
) {
595 fpe
= c
->fpe_list
[c
->current
.current_fpe
];
598 if (!fpe_functions
[fpe
->type
].start_list_fonts_and_aliases
)
600 /* This FPE doesn't support/require list_fonts_and_aliases */
602 err
= (*fpe_functions
[fpe
->type
].list_fonts
)
603 ((pointer
) c
->client
, fpe
, c
->current
.pattern
,
604 c
->current
.patlen
, c
->current
.max_names
- c
->names
->nnames
,
607 if (err
== Suspended
) {
611 (ClientSleepProcPtr
)doListFontsAndAliases
,
621 /* Start of list_fonts_and_aliases functionality. Modeled
622 after list_fonts_with_info in that it resolves aliases,
623 except that the information collected from FPEs is just
624 names, not font info. Each list_next_font_or_alias()
625 returns either a name into name/namelen or an alias into
626 name/namelen and its target name into resolved/resolvedlen.
627 The code at this level then resolves the alias by polling
630 if (!c
->current
.list_started
) {
631 err
= (*fpe_functions
[fpe
->type
].start_list_fonts_and_aliases
)
632 ((pointer
) c
->client
, fpe
, c
->current
.pattern
,
633 c
->current
.patlen
, c
->current
.max_names
- c
->names
->nnames
,
634 &c
->current
.private);
635 if (err
== Suspended
) {
638 (ClientSleepProcPtr
)doListFontsAndAliases
,
644 if (err
== Successful
)
645 c
->current
.list_started
= TRUE
;
647 if (err
== Successful
) {
650 err
= (*fpe_functions
[fpe
->type
].list_next_font_or_alias
)
651 ((pointer
) c
->client
, fpe
, &name
, &namelen
, &tmpname
,
652 &resolvedlen
, c
->current
.private);
653 if (err
== Suspended
) {
656 (ClientSleepProcPtr
)doListFontsAndAliases
,
662 if (err
== FontNameAlias
) {
663 if (resolved
) xfree(resolved
);
664 resolved
= (char *) xalloc(resolvedlen
+ 1);
666 memmove(resolved
, tmpname
, resolvedlen
+ 1);
670 if (err
== Successful
)
675 (void)AddFontNamesName(c
->names
, c
->savedName
,
679 (void)AddFontNamesName(c
->names
, name
, namelen
);
683 * When we get an alias back, save our state and reset back to
684 * the start of the FPE looking for the specified name. As
685 * soon as a real font is found for the alias, pop back to the
688 else if (err
== FontNameAlias
) {
689 char tmp_pattern
[XLFDMAXFONTNAMELEN
];
691 * when an alias recurses, we need to give
692 * the last FPE a chance to clean up; so we call
693 * it again, and assume that the error returned
694 * is BadFontName, indicating the alias resolution
697 memmove(tmp_pattern
, resolved
, resolvedlen
);
704 (void) (*fpe_functions
[fpe
->type
].list_next_font_or_alias
)
705 ((pointer
) c
->client
, fpe
, &tmpname
, &tmpnamelen
,
706 &tmpname
, &tmpnamelen
, c
->current
.private);
707 if (--aliascount
<= 0)
710 goto ContBadFontName
;
715 c
->saved
= c
->current
;
719 c
->savedName
= (char *)xalloc(namelen
+ 1);
721 memmove(c
->savedName
, name
, namelen
+ 1);
722 c
->savedNameLen
= namelen
;
725 memmove(c
->current
.pattern
, tmp_pattern
, resolvedlen
);
726 c
->current
.patlen
= resolvedlen
;
727 c
->current
.max_names
= c
->names
->nnames
+ 1;
728 c
->current
.current_fpe
= -1;
729 c
->current
.private = 0;
734 * At the end of this FPE, step to the next. If we've finished
735 * processing an alias, pop state back. If we've collected enough
738 if (err
== BadFontName
) {
740 c
->current
.list_started
= FALSE
;
741 c
->current
.current_fpe
++;
745 if (c
->names
->nnames
== c
->current
.max_names
||
746 c
->current
.current_fpe
== c
->num_fpes
) {
747 c
->haveSaved
= FALSE
;
748 c
->current
= c
->saved
;
749 /* Give the saved namelist a chance to clean itself up */
753 if (c
->names
->nnames
== c
->current
.max_names
)
761 if (err
!= Successful
) {
762 SendErrorToClient(client
, X_ListFonts
, 0, 0, FontToXError(err
));
769 nnames
= names
->nnames
;
772 for (i
= 0; i
< nnames
; i
++)
773 stringLens
+= (names
->length
[i
] <= 255) ? names
->length
[i
] : 0;
775 reply
.type
= X_Reply
;
776 reply
.length
= (stringLens
+ nnames
+ 3) >> 2;
777 reply
.nFonts
= nnames
;
778 reply
.sequenceNumber
= client
->sequence
;
780 bufptr
= bufferStart
= (char *) ALLOCATE_LOCAL(reply
.length
<< 2);
782 if (!bufptr
&& reply
.length
) {
783 SendErrorToClient(client
, X_ListFonts
, 0, 0, BadAlloc
);
787 * since WriteToClient long word aligns things, copy to temp buffer and
790 for (i
= 0; i
< nnames
; i
++) {
791 if (names
->length
[i
] > 255)
795 *bufptr
++ = names
->length
[i
];
796 memmove( bufptr
, names
->names
[i
], names
->length
[i
]);
797 bufptr
+= names
->length
[i
];
800 nnames
= reply
.nFonts
;
801 reply
.length
= (stringLens
+ nnames
+ 3) >> 2;
802 client
->pSwapReplyFunc
= ReplySwapVector
[X_ListFonts
];
803 WriteSwappedDataToClient(client
, sizeof(xListFontsReply
), &reply
);
804 (void) WriteToClient(client
, stringLens
+ nnames
, bufferStart
);
805 DEALLOCATE_LOCAL(bufferStart
);
809 ClientWakeup(client
);
810 for (i
= 0; i
< c
->num_fpes
; i
++)
811 FreeFPE(c
->fpe_list
[i
]);
813 if (c
->savedName
) xfree(c
->savedName
);
814 FreeFontNames(names
);
816 if (resolved
) xfree(resolved
);
821 ListFonts(ClientPtr client
, unsigned char *pattern
, unsigned length
,
828 * The right error to return here would be BadName, however the
829 * specification does not allow for a Name error on this request.
830 * Perhaps a better solution would be to return a nil list, i.e.
831 * a list containing zero fontnames.
833 if (length
> XLFDMAXFONTNAMELEN
)
836 if (!(c
= (LFclosurePtr
) xalloc(sizeof *c
)))
838 c
->fpe_list
= (FontPathElementPtr
*)
839 xalloc(sizeof(FontPathElementPtr
) * num_fpes
);
844 c
->names
= MakeFontNamesRecord(max_names
< 100 ? max_names
: 100);
851 memmove( c
->current
.pattern
, pattern
, length
);
852 for (i
= 0; i
< num_fpes
; i
++) {
853 c
->fpe_list
[i
] = font_path_elements
[i
];
854 UseFPE(c
->fpe_list
[i
]);
857 c
->num_fpes
= num_fpes
;
858 c
->current
.patlen
= length
;
859 c
->current
.current_fpe
= 0;
860 c
->current
.max_names
= max_names
;
861 c
->current
.list_started
= FALSE
;
862 c
->current
.private = 0;
863 c
->haveSaved
= FALSE
;
866 doListFontsAndAliases(client
, c
);
871 doListFontsWithInfo(ClientPtr client
, LFWIclosurePtr c
)
873 FontPathElementPtr fpe
;
874 int err
= Successful
;
878 FontInfoRec fontInfo
,
880 xListFontsWithInfoReply
*reply
;
885 xListFontsWithInfoReply finalReply
;
887 if (client
->clientGone
)
889 if (c
->current
.current_fpe
< c
->num_fpes
)
891 fpe
= c
->fpe_list
[c
->current
.current_fpe
];
892 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
897 client
->pSwapReplyFunc
= ReplySwapVector
[X_ListFontsWithInfo
];
898 if (!c
->current
.patlen
)
900 while (c
->current
.current_fpe
< c
->num_fpes
)
902 fpe
= c
->fpe_list
[c
->current
.current_fpe
];
904 if (!c
->current
.list_started
)
906 err
= (*fpe_functions
[fpe
->type
].start_list_fonts_with_info
)
907 (client
, fpe
, c
->current
.pattern
, c
->current
.patlen
,
908 c
->current
.max_names
, &c
->current
.private);
909 if (err
== Suspended
)
913 ClientSleep(client
, (ClientSleepProcPtr
)doListFontsWithInfo
, c
);
918 if (err
== Successful
)
919 c
->current
.list_started
= TRUE
;
921 if (err
== Successful
)
924 pFontInfo
= &fontInfo
;
925 err
= (*fpe_functions
[fpe
->type
].list_next_font_with_info
)
926 (client
, fpe
, &name
, &namelen
, &pFontInfo
,
927 &numFonts
, c
->current
.private);
928 if (err
== Suspended
)
933 (ClientSleepProcPtr
)doListFontsWithInfo
,
941 * When we get an alias back, save our state and reset back to the
942 * start of the FPE looking for the specified name. As soon as a real
943 * font is found for the alias, pop back to the old state
945 if (err
== FontNameAlias
)
948 * when an alias recurses, we need to give
949 * the last FPE a chance to clean up; so we call
950 * it again, and assume that the error returned
951 * is BadFontName, indicating the alias resolution
958 FontInfoPtr tmpFontInfo
;
961 tmpFontInfo
= &fontInfo
;
962 (void) (*fpe_functions
[fpe
->type
].list_next_font_with_info
)
963 (client
, fpe
, &tmpname
, &tmpnamelen
, &tmpFontInfo
,
964 &numFonts
, c
->current
.private);
965 if (--aliascount
<= 0)
968 goto ContBadFontName
;
973 c
->saved
= c
->current
;
975 c
->savedNumFonts
= numFonts
;
978 c
->savedName
= (char *)xalloc(namelen
+ 1);
980 memmove(c
->savedName
, name
, namelen
+ 1);
983 memmove(c
->current
.pattern
, name
, namelen
);
984 c
->current
.patlen
= namelen
;
985 c
->current
.max_names
= 1;
986 c
->current
.current_fpe
= 0;
987 c
->current
.private = 0;
988 c
->current
.list_started
= FALSE
;
991 * At the end of this FPE, step to the next. If we've finished
992 * processing an alias, pop state back. If we've sent enough font
993 * names, quit. Always wait for BadFontName to let the FPE
994 * have a chance to clean up.
996 else if (err
== BadFontName
)
999 c
->current
.list_started
= FALSE
;
1000 c
->current
.current_fpe
++;
1004 if (c
->current
.max_names
== 0 ||
1005 c
->current
.current_fpe
== c
->num_fpes
)
1007 c
->haveSaved
= FALSE
;
1008 c
->saved
.max_names
-= (1 - c
->current
.max_names
);
1009 c
->current
= c
->saved
;
1012 else if (c
->current
.max_names
== 0)
1015 else if (err
== Successful
)
1017 length
= sizeof(*reply
) + pFontInfo
->nprops
* sizeof(xFontProp
);
1019 if (c
->length
< length
)
1021 reply
= (xListFontsWithInfoReply
*) xrealloc(c
->reply
, length
);
1032 numFonts
= c
->savedNumFonts
;
1033 name
= c
->savedName
;
1034 namelen
= strlen(name
);
1036 reply
->type
= X_Reply
;
1037 reply
->length
= (sizeof *reply
- sizeof(xGenericReply
) +
1038 pFontInfo
->nprops
* sizeof(xFontProp
) +
1040 reply
->sequenceNumber
= client
->sequence
;
1041 reply
->nameLength
= namelen
;
1042 reply
->minBounds
= pFontInfo
->ink_minbounds
;
1043 reply
->maxBounds
= pFontInfo
->ink_maxbounds
;
1044 reply
->minCharOrByte2
= pFontInfo
->firstCol
;
1045 reply
->maxCharOrByte2
= pFontInfo
->lastCol
;
1046 reply
->defaultChar
= pFontInfo
->defaultCh
;
1047 reply
->nFontProps
= pFontInfo
->nprops
;
1048 reply
->drawDirection
= pFontInfo
->drawDirection
;
1049 reply
->minByte1
= pFontInfo
->firstRow
;
1050 reply
->maxByte1
= pFontInfo
->lastRow
;
1051 reply
->allCharsExist
= pFontInfo
->allExist
;
1052 reply
->fontAscent
= pFontInfo
->fontAscent
;
1053 reply
->fontDescent
= pFontInfo
->fontDescent
;
1054 reply
->nReplies
= numFonts
;
1055 pFP
= (xFontProp
*) (reply
+ 1);
1056 for (i
= 0; i
< pFontInfo
->nprops
; i
++)
1058 pFP
->name
= pFontInfo
->props
[i
].name
;
1059 pFP
->value
= pFontInfo
->props
[i
].value
;
1062 WriteSwappedDataToClient(client
, length
, reply
);
1063 (void) WriteToClient(client
, namelen
, name
);
1064 if (pFontInfo
== &fontInfo
)
1066 xfree(fontInfo
.props
);
1067 xfree(fontInfo
.isStringProp
);
1069 --c
->current
.max_names
;
1073 length
= sizeof(xListFontsWithInfoReply
);
1074 bzero((char *) &finalReply
, sizeof(xListFontsWithInfoReply
));
1075 finalReply
.type
= X_Reply
;
1076 finalReply
.sequenceNumber
= client
->sequence
;
1077 finalReply
.length
= (sizeof(xListFontsWithInfoReply
)
1078 - sizeof(xGenericReply
)) >> 2;
1079 WriteSwappedDataToClient(client
, length
, &finalReply
);
1082 ClientWakeup(client
);
1083 for (i
= 0; i
< c
->num_fpes
; i
++)
1084 FreeFPE(c
->fpe_list
[i
]);
1087 if (c
->savedName
) xfree(c
->savedName
);
1093 StartListFontsWithInfo(ClientPtr client
, int length
, unsigned char *pattern
,
1100 * The right error to return here would be BadName, however the
1101 * specification does not allow for a Name error on this request.
1102 * Perhaps a better solution would be to return a nil list, i.e.
1103 * a list containing zero fontnames.
1105 if (length
> XLFDMAXFONTNAMELEN
)
1108 if (!(c
= (LFWIclosurePtr
) xalloc(sizeof *c
)))
1110 c
->fpe_list
= (FontPathElementPtr
*)
1111 xalloc(sizeof(FontPathElementPtr
) * num_fpes
);
1117 memmove(c
->current
.pattern
, pattern
, length
);
1118 for (i
= 0; i
< num_fpes
; i
++)
1120 c
->fpe_list
[i
] = font_path_elements
[i
];
1121 UseFPE(c
->fpe_list
[i
]);
1124 c
->num_fpes
= num_fpes
;
1127 c
->current
.patlen
= length
;
1128 c
->current
.current_fpe
= 0;
1129 c
->current
.max_names
= max_names
;
1130 c
->current
.list_started
= FALSE
;
1131 c
->current
.private = 0;
1132 c
->savedNumFonts
= 0;
1133 c
->haveSaved
= FALSE
;
1136 doListFontsWithInfo(client
, c
);
1142 #define TextEltHeader 2
1143 #define FontShiftSize 5
1144 static XID clearGC
[] = { CT_NONE
};
1145 #define clearGCmask (GCClipMask)
1148 doPolyText(ClientPtr client
, PTclosurePtr c
)
1150 FontPtr pFont
= c
->pGC
->font
, oldpFont
;
1152 int err
= Success
, lgerr
; /* err is in X error, not font error, space */
1153 enum { NEVER_SLEPT
, START_SLEEP
, SLEEPING
} client_state
= NEVER_SLEPT
;
1154 FontPathElementPtr fpe
;
1157 if (client
->clientGone
)
1159 fpe
= c
->pGC
->font
->fpe
;
1160 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
1164 /* Client has died, but we cannot bail out right now. We
1165 need to clean up after the work we did when going to
1166 sleep. Setting the drawable pointer to 0 makes this
1167 happen without any attempts to render or perform other
1168 unnecessary activities. */
1169 c
->pDraw
= (DrawablePtr
)0;
1178 /* Make sure our drawable hasn't disappeared while we slept. */
1181 c
->pDraw
!= (DrawablePtr
)SecurityLookupIDByClass(client
, c
->did
,
1182 RC_DRAWABLE
, DixWriteAccess
))
1184 /* Our drawable has disappeared. Treat like client died... ask
1185 the FPE code to clean up after client and avoid further
1186 rendering while we clean up after ourself. */
1187 fpe
= c
->pGC
->font
->fpe
;
1188 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
1189 c
->pDraw
= (DrawablePtr
)0;
1192 client_state
= c
->slept
? SLEEPING
: NEVER_SLEPT
;
1194 while (c
->endReq
- c
->pElt
> TextEltHeader
)
1196 if (*c
->pElt
== FontChange
)
1198 if (c
->endReq
- c
->pElt
< FontShiftSize
)
1207 fid
= ((Font
)*(c
->pElt
+4)) /* big-endian */
1208 | ((Font
)*(c
->pElt
+3)) << 8
1209 | ((Font
)*(c
->pElt
+2)) << 16
1210 | ((Font
)*(c
->pElt
+1)) << 24;
1211 pFont
= (FontPtr
)SecurityLookupIDByType(client
, fid
, RT_FONT
,
1215 client
->errorValue
= fid
;
1217 /* restore pFont and fid for step 4 (described below) */
1221 /* If we're in START_SLEEP mode, the following step
1222 shortens the request... in the unlikely event that
1223 the fid somehow becomes valid before we come through
1224 again to actually execute the polytext, which would
1225 then mess up our refcounting scheme badly. */
1227 c
->endReq
= c
->pElt
;
1232 /* Step 3 (described below) on our new font */
1233 if (client_state
== START_SLEEP
)
1237 if (pFont
!= c
->pGC
->font
&& c
->pDraw
)
1239 ChangeGC( c
->pGC
, GCFont
, &fid
);
1240 ValidateGC(c
->pDraw
, c
->pGC
);
1241 if (c
->reqType
== X_PolyText8
)
1242 c
->polyText
= (PolyTextPtr
) c
->pGC
->ops
->PolyText8
;
1244 c
->polyText
= (PolyTextPtr
) c
->pGC
->ops
->PolyText16
;
1247 /* Undo the refcnt++ we performed when going to sleep */
1248 if (client_state
== SLEEPING
)
1249 (void)CloseFont(c
->pGC
->font
, (Font
)0);
1251 c
->pElt
+= FontShiftSize
;
1253 else /* print a string */
1255 unsigned char *pNextElt
;
1256 pNextElt
= c
->pElt
+ TextEltHeader
+ (*c
->pElt
)*c
->itemSize
;
1257 if ( pNextElt
> c
->endReq
)
1262 if (client_state
== START_SLEEP
)
1269 lgerr
= LoadGlyphs(client
, c
->pGC
->font
, *c
->pElt
, c
->itemSize
,
1270 c
->pElt
+ TextEltHeader
);
1272 else lgerr
= Successful
;
1274 if (lgerr
== Suspended
)
1279 PTclosurePtr new_closure
;
1281 /* We're putting the client to sleep. We need to do a few things
1282 to ensure successful and atomic-appearing execution of the
1283 remainder of the request. First, copy the remainder of the
1284 request into a safe malloc'd area. Second, create a scratch GC
1285 to use for the remainder of the request. Third, mark all fonts
1286 referenced in the remainder of the request to prevent their
1287 deallocation. Fourth, make the original GC look like the
1288 request has completed... set its font to the final font value
1289 from this request. These GC manipulations are for the unlikely
1290 (but possible) event that some other client is using the GC.
1291 Steps 3 and 4 are performed by running this procedure through
1292 the remainder of the request in a special no-render mode
1293 indicated by client_state = START_SLEEP. */
1296 /* Allocate a malloc'd closure structure to replace
1297 the local one we were passed */
1298 new_closure
= (PTclosurePtr
) xalloc(sizeof(PTclosureRec
));
1307 len
= c
->endReq
- c
->pElt
;
1308 c
->data
= (unsigned char *)xalloc(len
);
1315 memmove(c
->data
, c
->pElt
, len
);
1317 c
->endReq
= c
->pElt
+ len
;
1321 pGC
= GetScratchGC(c
->pGC
->depth
, c
->pGC
->pScreen
);
1329 if ((err
= CopyGC(c
->pGC
, pGC
, GCFunction
|
1330 GCPlaneMask
| GCForeground
|
1331 GCBackground
| GCFillStyle
|
1332 GCTile
| GCStipple
|
1334 GCTileStipYOrigin
| GCFont
|
1335 GCSubwindowMode
| GCClipXOrigin
|
1336 GCClipYOrigin
| GCClipMask
)) !=
1347 ValidateGC(c
->pDraw
, c
->pGC
);
1351 (ClientSleepProcPtr
)doPolyText
,
1354 /* Set up to perform steps 3 and 4 */
1355 client_state
= START_SLEEP
;
1356 continue; /* on to steps 3 and 4 */
1360 else if (lgerr
!= Successful
)
1362 err
= FontToXError(lgerr
);
1367 c
->xorg
+= *((INT8
*)(c
->pElt
+ 1)); /* must be signed */
1368 c
->xorg
= (* c
->polyText
)(c
->pDraw
, c
->pGC
, c
->xorg
, c
->yorg
,
1369 *c
->pElt
, c
->pElt
+ TextEltHeader
);
1377 if (client_state
== START_SLEEP
)
1380 if (pFont
!= origGC
->font
)
1382 ChangeGC(origGC
, GCFont
, &fid
);
1383 ValidateGC(c
->pDraw
, origGC
);
1386 /* restore pElt pointer for execution of remainder of the request */
1391 if (c
->err
!= Success
) err
= c
->err
;
1392 if (err
!= Success
&& c
->client
!= serverClient
) {
1394 if (noPanoramiXExtension
|| !c
->pGC
->pScreen
->myNum
)
1396 SendErrorToClient(c
->client
, c
->reqType
, 0, 0, err
);
1400 ClientWakeup(c
->client
);
1401 ChangeGC(c
->pGC
, clearGCmask
, clearGC
);
1403 /* Unreference the font from the scratch GC */
1404 CloseFont(c
->pGC
->font
, (Font
)0);
1405 c
->pGC
->font
= NullFont
;
1407 FreeScratchGC(c
->pGC
);
1415 PolyText(ClientPtr client
, DrawablePtr pDraw
, GC
*pGC
, unsigned char *pElt
,
1416 unsigned char *endReq
, int xorg
, int yorg
, int reqType
, XID did
)
1418 PTclosureRec local_closure
;
1420 local_closure
.pElt
= pElt
;
1421 local_closure
.endReq
= endReq
;
1422 local_closure
.client
= client
;
1423 local_closure
.pDraw
= pDraw
;
1424 local_closure
.xorg
= xorg
;
1425 local_closure
.yorg
= yorg
;
1426 if ((local_closure
.reqType
= reqType
) == X_PolyText8
)
1428 local_closure
.polyText
= (PolyTextPtr
) pGC
->ops
->PolyText8
;
1429 local_closure
.itemSize
= 1;
1433 local_closure
.polyText
= (PolyTextPtr
) pGC
->ops
->PolyText16
;
1434 local_closure
.itemSize
= 2;
1436 local_closure
.pGC
= pGC
;
1437 local_closure
.did
= did
;
1438 local_closure
.err
= Success
;
1439 local_closure
.slept
= FALSE
;
1441 (void) doPolyText(client
, &local_closure
);
1446 #undef TextEltHeader
1447 #undef FontShiftSize
1450 doImageText(ClientPtr client
, ITclosurePtr c
)
1452 int err
= Success
, lgerr
; /* err is in X error, not font error, space */
1453 FontPathElementPtr fpe
;
1455 if (client
->clientGone
)
1457 fpe
= c
->pGC
->font
->fpe
;
1458 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
1463 /* Make sure our drawable hasn't disappeared while we slept. */
1466 c
->pDraw
!= (DrawablePtr
)SecurityLookupIDByClass(client
, c
->did
,
1467 RC_DRAWABLE
, DixWriteAccess
))
1469 /* Our drawable has disappeared. Treat like client died... ask
1470 the FPE code to clean up after client. */
1471 fpe
= c
->pGC
->font
->fpe
;
1472 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
1477 lgerr
= LoadGlyphs(client
, c
->pGC
->font
, c
->nChars
, c
->itemSize
, c
->data
);
1478 if (lgerr
== Suspended
)
1482 unsigned char *data
;
1483 ITclosurePtr new_closure
;
1485 /* We're putting the client to sleep. We need to
1486 save some state. Similar problem to that handled
1487 in doPolyText, but much simpler because the
1488 request structure is much simpler. */
1490 new_closure
= (ITclosurePtr
) xalloc(sizeof(ITclosureRec
));
1499 data
= (unsigned char *)xalloc(c
->nChars
* c
->itemSize
);
1506 memmove(data
, c
->data
, c
->nChars
* c
->itemSize
);
1509 pGC
= GetScratchGC(c
->pGC
->depth
, c
->pGC
->pScreen
);
1517 if ((err
= CopyGC(c
->pGC
, pGC
, GCFunction
| GCPlaneMask
|
1518 GCForeground
| GCBackground
| GCFillStyle
|
1519 GCTile
| GCStipple
| GCTileStipXOrigin
|
1520 GCTileStipYOrigin
| GCFont
|
1521 GCSubwindowMode
| GCClipXOrigin
|
1522 GCClipYOrigin
| GCClipMask
)) != Success
)
1531 ValidateGC(c
->pDraw
, c
->pGC
);
1534 ClientSleep(client
, (ClientSleepProcPtr
)doImageText
, (pointer
) c
);
1538 else if (lgerr
!= Successful
)
1540 err
= FontToXError(lgerr
);
1545 (* c
->imageText
)(c
->pDraw
, c
->pGC
, c
->xorg
, c
->yorg
,
1546 c
->nChars
, c
->data
);
1551 if (err
!= Success
&& c
->client
!= serverClient
) {
1552 SendErrorToClient(c
->client
, c
->reqType
, 0, 0, err
);
1556 ClientWakeup(c
->client
);
1557 ChangeGC(c
->pGC
, clearGCmask
, clearGC
);
1559 /* Unreference the font from the scratch GC */
1560 CloseFont(c
->pGC
->font
, (Font
)0);
1561 c
->pGC
->font
= NullFont
;
1563 FreeScratchGC(c
->pGC
);
1571 ImageText(ClientPtr client
, DrawablePtr pDraw
, GC
*pGC
, int nChars
,
1572 unsigned char *data
, int xorg
, int yorg
, int reqType
, XID did
)
1574 ITclosureRec local_closure
;
1576 local_closure
.client
= client
;
1577 local_closure
.pDraw
= pDraw
;
1578 local_closure
.pGC
= pGC
;
1579 local_closure
.nChars
= nChars
;
1580 local_closure
.data
= data
;
1581 local_closure
.xorg
= xorg
;
1582 local_closure
.yorg
= yorg
;
1583 if ((local_closure
.reqType
= reqType
) == X_ImageText8
)
1585 local_closure
.imageText
= (ImageTextPtr
) pGC
->ops
->ImageText8
;
1586 local_closure
.itemSize
= 1;
1590 local_closure
.imageText
= (ImageTextPtr
) pGC
->ops
->ImageText16
;
1591 local_closure
.itemSize
= 2;
1593 local_closure
.did
= did
;
1594 local_closure
.slept
= FALSE
;
1596 (void) doImageText(client
, &local_closure
);
1601 /* does the necessary magic to figure out the fpe type */
1603 DetermineFPEType(char *pathname
)
1607 for (i
= 0; i
< num_fpe_types
; i
++) {
1608 if ((*fpe_functions
[i
].name_check
) (pathname
))
1616 FreeFontPath(FontPathElementPtr
*list
, int n
, Bool force
)
1620 for (i
= 0; i
< n
; i
++) {
1622 /* Sanity check that all refcounts will be 0 by the time
1623 we get to the end of the list. */
1624 int found
= 1; /* the first reference is us */
1626 for (j
= i
+1; j
< n
; j
++) {
1627 if (list
[j
] == list
[i
])
1630 if (list
[i
]->refcount
!= found
) {
1631 ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n",
1632 list
[i
]->name_length
, list
[i
]->name
,
1633 list
[i
]->refcount
, found
);
1634 list
[i
]->refcount
= found
; /* ensure it will get freed */
1639 xfree((char *) list
);
1642 static FontPathElementPtr
1643 find_existing_fpe(FontPathElementPtr
*list
, int num
, unsigned char *name
, int len
)
1645 FontPathElementPtr fpe
;
1648 for (i
= 0; i
< num
; i
++) {
1650 if (fpe
->name_length
== len
&& memcmp(name
, fpe
->name
, len
) == 0)
1653 return (FontPathElementPtr
) 0;
1658 SetFontPathElements(int npaths
, unsigned char *paths
, int *bad
, Bool persist
)
1661 int valid_paths
= 0;
1663 unsigned char *cp
= paths
;
1664 FontPathElementPtr fpe
= NULL
, *fplist
;
1666 fplist
= (FontPathElementPtr
*)
1667 xalloc(sizeof(FontPathElementPtr
) * npaths
);
1672 for (i
= 0; i
< num_fpe_types
; i
++) {
1673 if (fpe_functions
[i
].set_path_hook
)
1674 (*fpe_functions
[i
].set_path_hook
) ();
1676 for (i
= 0; i
< npaths
; i
++)
1678 len
= (unsigned int) (*cp
++);
1683 ErrorF ("Removing empty element from the valid list of fontpaths\n");
1688 /* if it's already in our active list, just reset it */
1690 * note that this can miss FPE's in limbo -- may be worth catching
1691 * them, though it'd muck up refcounting
1693 fpe
= find_existing_fpe(font_path_elements
, num_fpes
, cp
, len
);
1696 err
= (*fpe_functions
[fpe
->type
].reset_fpe
) (fpe
);
1697 if (err
== Successful
)
1699 UseFPE(fpe
);/* since it'll be decref'd later when freed
1700 * from the old list */
1705 /* if error or can't do it, act like it's a new one */
1708 fpe
= (FontPathElementPtr
) xalloc(sizeof(FontPathElementRec
));
1714 fpe
->name
= (char *) xalloc(len
+ 1);
1723 strncpy(fpe
->name
, (char *) cp
, (int) len
);
1724 fpe
->name
[len
] = '\0';
1725 fpe
->name_length
= len
;
1726 fpe
->type
= DetermineFPEType(fpe
->name
);
1727 if (fpe
->type
== -1)
1730 err
= (*fpe_functions
[fpe
->type
].init_fpe
) (fpe
);
1731 if (err
!= Successful
)
1735 ErrorF("Could not init font path element %s, removing from list!\n",
1743 if (err
!= Successful
)
1750 fplist
[valid_paths
++] = fpe
;
1755 FreeFontPath(font_path_elements
, num_fpes
, FALSE
);
1756 font_path_elements
= fplist
;
1758 EmptyFontPatternCache(patternCache
);
1759 num_fpes
= valid_paths
;
1764 while (--valid_paths
>= 0)
1765 FreeFPE(fplist
[valid_paths
]);
1767 return FontToXError(err
);
1770 /* XXX -- do we need to pass error down to each renderer? */
1772 SetFontPath(ClientPtr client
, int npaths
, unsigned char *paths
, int *error
)
1777 if (SetDefaultFontPath(defaultFontPath
) != Success
)
1780 err
= SetFontPathElements(npaths
, paths
, error
, FALSE
);
1786 SetDefaultFontPath(char *path
)
1798 /* get enough for string, plus values -- use up commas */
1799 len
= strlen(path
) + 1;
1800 nump
= cp
= newpath
= (unsigned char *) ALLOCATE_LOCAL(len
);
1803 pp
= (unsigned char *) path
;
1807 *nump
= (unsigned char) size
;
1817 *nump
= (unsigned char) size
;
1819 err
= SetFontPathElements(num
, newpath
, &bad
, TRUE
);
1821 DEALLOCATE_LOCAL(newpath
);
1827 GetFontPath(int *count
, int *length
)
1832 FontPathElementPtr fpe
;
1835 for (i
= 0; i
< num_fpes
; i
++) {
1836 fpe
= font_path_elements
[i
];
1837 len
+= fpe
->name_length
+ 1;
1839 font_path_string
= (unsigned char *) xrealloc(font_path_string
, len
);
1840 if (!font_path_string
)
1843 c
= font_path_string
;
1845 for (i
= 0; i
< num_fpes
; i
++) {
1846 fpe
= font_path_elements
[i
];
1847 *c
= fpe
->name_length
;
1849 memmove(c
, fpe
->name
, fpe
->name_length
);
1850 c
+= fpe
->name_length
;
1853 return font_path_string
;
1857 LoadGlyphs(ClientPtr client
, FontPtr pfont
, unsigned nchars
, int item_size
, unsigned char *data
)
1859 if (fpe_functions
[pfont
->fpe
->type
].load_glyphs
)
1860 return (*fpe_functions
[pfont
->fpe
->type
].load_glyphs
)
1861 (client
, pfont
, 0, nchars
, item_size
, data
);
1867 DeleteClientFontStuff(ClientPtr client
)
1870 FontPathElementPtr fpe
;
1872 for (i
= 0; i
< num_fpes
; i
++)
1874 fpe
= font_path_elements
[i
];
1875 if (fpe_functions
[fpe
->type
].client_died
)
1876 (*fpe_functions
[fpe
->type
].client_died
) ((pointer
) client
, fpe
);
1883 patternCache
= MakeFontPatternCache();
1885 #ifndef BUILTIN_FONTS
1886 if (screenInfo
.numScreens
> screenInfo
.numVideoScreens
) {
1887 PrinterFontRegisterFpeFunctions();
1888 FontFileCheckRegisterFpeFunctions();
1889 check_fs_register_fpe_functions();
1893 #ifdef BUILTIN_FONTS
1894 BuiltinRegisterFpeFunctions();
1896 FontFileRegisterFpeFunctions();
1898 #ifndef NOFONTSERVERACCESS
1899 fs_register_fpe_functions();
1905 GetDefaultPointSize ()
1912 GetClientResolutions (int *num
)
1914 if (requestingClient
&& requestingClient
->fontResFunc
!= NULL
&&
1915 !requestingClient
->clientGone
)
1917 return (*requestingClient
->fontResFunc
)(requestingClient
, num
);
1920 static struct _FontResolution res
;
1923 pScreen
= screenInfo
.screens
[0];
1924 res
.x_resolution
= (pScreen
->width
* 25.4) / pScreen
->mmWidth
;
1926 * XXX - we'll want this as long as bitmap instances are prevalent
1927 so that we can match them from scalable fonts
1929 if (res
.x_resolution
< 88)
1930 res
.x_resolution
= 75;
1932 res
.x_resolution
= 100;
1933 res
.y_resolution
= (pScreen
->height
* 25.4) / pScreen
->mmHeight
;
1934 if (res
.y_resolution
< 88)
1935 res
.y_resolution
= 75;
1937 res
.y_resolution
= 100;
1938 res
.point_size
= 120;
1945 * returns the type index of the new fpe
1947 * should be called (only once!) by each type of fpe when initialized
1951 RegisterFPEFunctions(NameCheckFunc name_func
,
1952 InitFpeFunc init_func
,
1953 FreeFpeFunc free_func
,
1954 ResetFpeFunc reset_func
,
1955 OpenFontFunc open_func
,
1956 CloseFontFunc close_func
,
1957 ListFontsFunc list_func
,
1958 StartLfwiFunc start_lfwi_func
,
1959 NextLfwiFunc next_lfwi_func
,
1960 WakeupFpeFunc wakeup_func
,
1961 ClientDiedFunc client_died
,
1962 LoadGlyphsFunc load_glyphs
,
1963 StartLaFunc start_list_alias_func
,
1964 NextLaFunc next_list_alias_func
,
1965 SetPathFunc set_path_func
)
1970 new = (FPEFunctions
*) xrealloc(fpe_functions
,
1971 (num_fpe_types
+ 1) * sizeof(FPEFunctions
));
1974 fpe_functions
= new;
1976 fpe_functions
[num_fpe_types
].name_check
= name_func
;
1977 fpe_functions
[num_fpe_types
].open_font
= open_func
;
1978 fpe_functions
[num_fpe_types
].close_font
= close_func
;
1979 fpe_functions
[num_fpe_types
].wakeup_fpe
= wakeup_func
;
1980 fpe_functions
[num_fpe_types
].list_fonts
= list_func
;
1981 fpe_functions
[num_fpe_types
].start_list_fonts_with_info
=
1983 fpe_functions
[num_fpe_types
].list_next_font_with_info
=
1985 fpe_functions
[num_fpe_types
].init_fpe
= init_func
;
1986 fpe_functions
[num_fpe_types
].free_fpe
= free_func
;
1987 fpe_functions
[num_fpe_types
].reset_fpe
= reset_func
;
1988 fpe_functions
[num_fpe_types
].client_died
= client_died
;
1989 fpe_functions
[num_fpe_types
].load_glyphs
= load_glyphs
;
1990 fpe_functions
[num_fpe_types
].start_list_fonts_and_aliases
=
1991 start_list_alias_func
;
1992 fpe_functions
[num_fpe_types
].list_next_font_or_alias
=
1993 next_list_alias_func
;
1994 fpe_functions
[num_fpe_types
].set_path_hook
= set_path_func
;
1996 return num_fpe_types
++;
2003 FreeFontPatternCache(patternCache
);
2006 FreeFontPath(font_path_elements
, num_fpes
, TRUE
);
2007 font_path_elements
= 0;
2009 xfree(fpe_functions
);
2011 fpe_functions
= (FPEFunctions
*) 0;
2014 /* convenience functions for FS interface */
2017 find_old_font(XID id
)
2019 return (FontPtr
) SecurityLookupIDByType(NullClient
, id
, RT_NONE
,
2024 GetNewFontClientID()
2026 return FakeClientID(0);
2030 StoreFontClientFont(FontPtr pfont
, Font id
)
2032 return AddResource(id
, RT_NONE
, (pointer
) pfont
);
2036 DeleteFontClientID(Font id
)
2038 FreeResource(id
, RT_NONE
);
2042 client_auth_generation(ClientPtr client
)
2047 static int fs_handlers_installed
= 0;
2048 static unsigned int last_server_gen
;
2051 init_fs_handlers(FontPathElementPtr fpe
, BlockHandlerProcPtr block_handler
)
2053 /* if server has reset, make sure the b&w handlers are reinstalled */
2054 if (last_server_gen
< serverGeneration
) {
2055 last_server_gen
= serverGeneration
;
2056 fs_handlers_installed
= 0;
2058 if (fs_handlers_installed
== 0) {
2059 if (!RegisterBlockAndWakeupHandlers(block_handler
,
2060 FontWakeup
, (pointer
) 0))
2062 fs_handlers_installed
++;
2064 QueueFontWakeup(fpe
);
2069 remove_fs_handlers(FontPathElementPtr fpe
, BlockHandlerProcPtr block_handler
, Bool all
)
2072 /* remove the handlers if no one else is using them */
2073 if (--fs_handlers_installed
== 0) {
2074 RemoveBlockAndWakeupHandlers(block_handler
, FontWakeup
,
2078 RemoveFontWakeup(fpe
);