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 ************************************************************************/
24 /* $XConsortium: dixfonts.c /main/58 1996/09/28 17:11:55 rws $ */
25 /* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.6 1996/12/23 06:29:40 dawes Exp $ */
31 #include "scrnintstr.h"
33 #include "dixstruct.h"
34 #include "cursorstr.h"
37 #include "dixfontstr.h"
44 #define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics
46 static Mask FontFormat =
47 #if IMAGE_BYTE_ORDER == LSBFirst
48 BitmapFormatByteOrderLSB |
50 BitmapFormatByteOrderMSB |
53 #if BITMAP_BIT_ORDER == LSBFirst
54 BitmapFormatBitOrderLSB |
56 BitmapFormatBitOrderMSB |
59 BitmapFormatImageRectMin |
61 #if GLYPHPADBYTES == 1
62 BitmapFormatScanlinePad8 |
65 #if GLYPHPADBYTES == 2
66 BitmapFormatScanlinePad16 |
69 #if GLYPHPADBYTES == 4
70 BitmapFormatScanlinePad32 |
73 #if GLYPHPADBYTES == 8
74 BitmapFormatScanlinePad64 |
77 BitmapFormatScanlineUnit8;
79 extern pointer fosNaturalParams;
80 extern FontPtr defaultFont;
82 static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
83 static int num_fpes = 0;
84 static FPEFunctions *fpe_functions = (FPEFunctions *) 0;
85 static int num_fpe_types = 0;
87 static unsigned char *font_path_string;
89 static int num_slept_fpes = 0;
90 static int size_slept_fpes = 0;
91 static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
92 static FontPatternCachePtr patternCache;
106 case BadFontFormat: /* is there something better? */
116 * adding RT_FONT prevents conflict with default cursor font
119 SetDefaultFont(defaultfontname)
120 char *defaultfontname;
126 fid = FakeClientID(0);
127 err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
128 (unsigned) strlen(defaultfontname), defaultfontname);
131 pf = (FontPtr) LookupIDByType(fid, RT_FONT);
132 if (pf == (FontPtr) NULL)
139 * note that the font wakeup queue is not refcounted. this is because
140 * an fpe needs to be added when it's inited, and removed when it's finally
141 * freed, in order to handle any data that isn't requested, like FS events.
143 * since the only thing that should call these routines is the renderer's
144 * init_fpe() and free_fpe(), there shouldn't be any problem in using
149 FontPathElementPtr fpe;
152 FontPathElementPtr *new;
154 for (i = 0; i < num_slept_fpes; i++) {
155 if (slept_fpes[i] == fpe) {
158 fprintf(stderr, "re-queueing fpe wakeup\n");
164 if (num_slept_fpes == size_slept_fpes) {
165 new = (FontPathElementPtr *)
167 sizeof(FontPathElementPtr) * (size_slept_fpes + 4));
171 size_slept_fpes += 4;
173 slept_fpes[num_slept_fpes] = fpe;
178 RemoveFontWakeup(fpe)
179 FontPathElementPtr fpe;
184 for (i = 0; i < num_slept_fpes; i++) {
185 if (slept_fpes[i] == fpe) {
186 for (j = i; j < num_slept_fpes; j++) {
187 slept_fpes[j] = slept_fpes[j + 1];
197 FontWakeup(data, count, LastSelectMask)
200 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 #if NeedFunctionPrototypes
217 UseFPE(FontPathElementPtr fpe)
220 FontPathElementPtr fpe;
227 #if NeedFunctionPrototypes
228 FreeFPE (FontPathElementPtr fpe)
231 FontPathElementPtr fpe;
235 if (fpe->refcount == 0) {
236 (*fpe_functions[fpe->type].free_fpe) (fpe);
243 #if NeedFunctionPrototypes
244 doOpenFont(ClientPtr client, OFclosurePtr c)
246 doOpenFont(client, c)
251 FontPtr pfont = NullFont;
252 FontPathElementPtr fpe;
254 int err = Successful;
261 if (client->clientGone)
263 if (c->current_fpe < c->num_fpes)
265 fpe = c->fpe_list[c->current_fpe];
266 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
271 while (c->current_fpe < c->num_fpes) {
272 fpe = c->fpe_list[c->current_fpe];
273 err = (*fpe_functions[fpe->type].open_font)
274 ((pointer) client, fpe, c->flags,
275 c->fontname, c->fnamelen, FontFormat,
276 BitmapFormatMaskByte |
277 BitmapFormatMaskBit |
278 BitmapFormatMaskImageRectangle |
279 BitmapFormatMaskScanLinePad |
280 BitmapFormatMaskScanLineUnit,
281 c->fontid, &pfont, &alias,
282 c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
283 c->non_cachable_font :
286 if (err == FontNameAlias && alias) {
287 newlen = strlen(alias);
288 newname = (char *) xrealloc(c->fontname, newlen);
293 memmove(newname, alias, newlen);
294 c->fontname = newname;
295 c->fnamelen = newlen;
297 if (--aliascount <= 0)
301 if (err == BadFontName) {
305 if (err == Suspended) {
308 ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c);
315 if (err != Successful)
324 if (pfont->refcnt == 1) {
326 for (i = 0; i < screenInfo.numScreens; i++) {
327 pScr = screenInfo.screens[i];
328 if (pScr->RealizeFont)
330 if (!(*pScr->RealizeFont) (pScr, pfont))
332 CloseFont (pfont, (Font) 0);
339 if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) {
343 if (patternCache && pfont != c->non_cachable_font)
344 CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen,
347 if (err != Successful && c->client != serverClient) {
348 SendErrorToClient(c->client, X_OpenFont, 0,
349 c->fontid, FontToXError(err));
352 ClientWakeup(c->client);
353 for (i = 0; i < c->num_fpes; i++) {
354 FreeFPE(c->fpe_list[i]);
363 OpenFont(client, fid, flags, lenfname, pfontname)
372 FontPtr cached = (FontPtr)0;
376 f = (char *)xalloc(lenfname + 1);
377 memmove(f, pfontname, lenfname);
379 ErrorF("OpenFont: fontname is \"%s\"\n", f);
388 ** Check name cache. If we find a cached version of this font that
389 ** is cachable, immediately satisfy the request with it. If we find
390 ** a cached version of this font that is non-cachable, we do not
391 ** satisfy the request with it. Instead, we pass the FontPtr to the
392 ** FPE's open_font code (the fontfile FPE in turn passes the
393 ** information to the rasterizer; the fserve FPE ignores it).
395 ** Presumably, the font is marked non-cachable because the FPE has
396 ** put some licensing restrictions on it. If the FPE, using
397 ** whatever logic it relies on, determines that it is willing to
398 ** share this existing font with the client, then it has the option
399 ** to return the FontPtr we passed it as the newly-opened font.
400 ** This allows the FPE to exercise its licensing logic without
401 ** having to create another instance of a font that already exists.
404 cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
405 if (cached && cached->info.cachable)
407 if (!AddResource(fid, RT_FONT, (pointer) cached))
413 c = (OFclosurePtr) xalloc(sizeof(OFclosureRec));
416 c->fontname = (char *) xalloc(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 = (FontPathElementPtr *)
428 xalloc(sizeof(FontPathElementPtr) * num_fpes);
434 memmove(c->fontname, pfontname, lenfname);
435 for (i = 0; i < num_fpes; i++) {
436 c->fpe_list[i] = font_path_elements[i];
437 UseFPE(c->fpe_list[i]);
442 c->num_fpes = num_fpes;
443 c->fnamelen = lenfname;
446 c->non_cachable_font = cached;
448 (void) doOpenFont(client, c);
453 * Decrement font's ref count, and free storage if ref count equals zero
457 CloseFont(value, fid)
458 pointer value; /* must conform to DeleteType */
463 FontPathElementPtr fpe;
464 FontPtr pfont = (FontPtr)value;
466 if (pfont == NullFont)
468 if (--pfont->refcnt == 0) {
469 if (patternCache && pfont->info.cachable)
470 RemoveCachedFontPattern (patternCache, pfont);
472 * since the last reference is gone, ask each screen to free any
473 * storage it may have allocated locally for it.
475 for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
476 pscr = screenInfo.screens[nscr];
477 if (pscr->UnrealizeFont)
478 (*pscr->UnrealizeFont) (pscr, pfont);
480 if (pfont == defaultFont)
483 LbxFreeFontTag(pfont);
486 (*fpe_functions[fpe->type].close_font) (fpe, pfont);
493 /***====================================================================***/
496 * \ Sets up pReply as the correct QueryFontReply for pFont with the first
497 * nProtoCCIStructs char infos. \
501 QueryFont(pFont, pReply, nProtoCCIStructs)
503 xQueryFontReply *pReply; /* caller must allocate this storage */
504 int nProtoCCIStructs;
512 xCharInfo *charInfos[256];
513 unsigned char chars[512];
518 /* pr->length set in dispatch */
519 pReply->minCharOrByte2 = pFont->info.firstCol;
520 pReply->defaultChar = pFont->info.defaultCh;
521 pReply->maxCharOrByte2 = pFont->info.lastCol;
522 pReply->drawDirection = pFont->info.drawDirection;
523 pReply->allCharsExist = pFont->info.allExist;
524 pReply->minByte1 = pFont->info.firstRow;
525 pReply->maxByte1 = pFont->info.lastRow;
526 pReply->fontAscent = pFont->info.fontAscent;
527 pReply->fontDescent = pFont->info.fontDescent;
529 pReply->minBounds = pFont->info.ink_minbounds;
530 pReply->maxBounds = pFont->info.ink_maxbounds;
532 pReply->nFontProps = pFont->info.nprops;
533 pReply->nCharInfos = nProtoCCIStructs;
535 for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
536 i < pFont->info.nprops;
537 i++, pFP++, prFP++) {
538 prFP->name = pFP->name;
539 prFP->value = pFP->value;
543 ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
544 prCI = (xCharInfo *) (prFP);
545 for (r = pFont->info.firstRow;
546 ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow;
549 for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) {
553 (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
556 for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
557 *prCI = *charInfos[i];
566 #if NeedFunctionPrototypes
567 doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
569 doListFontsAndAliases(client, c)
574 FontPathElementPtr fpe;
575 int err = Successful;
576 FontNamesPtr names = NULL;
577 char *name, *resolved=NULL;
578 int namelen, resolvedlen;
582 xListFontsReply reply;
587 if (client->clientGone)
589 if (c->current.current_fpe < c->num_fpes)
591 fpe = c->fpe_list[c->current.current_fpe];
592 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
598 if (!c->current.patlen)
601 while (c->current.current_fpe < c->num_fpes) {
602 fpe = c->fpe_list[c->current.current_fpe];
605 if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
607 /* This FPE doesn't support/require list_fonts_and_aliases */
609 err = (*fpe_functions[fpe->type].list_fonts)
610 ((pointer) c->client, fpe, c->current.pattern,
611 c->current.patlen, c->current.max_names - c->names->nnames,
614 if (err == Suspended) {
618 (ClientSleepProcPtr)doListFontsAndAliases,
628 /* Start of list_fonts_and_aliases functionality. Modeled
629 after list_fonts_with_info in that it resolves aliases,
630 except that the information collected from FPEs is just
631 names, not font info. Each list_next_font_or_alias()
632 returns either a name into name/namelen or an alias into
633 name/namelen and its target name into resolved/resolvedlen.
634 The code at this level then resolves the alias by polling
637 if (!c->current.list_started) {
638 err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
639 ((pointer) c->client, fpe, c->current.pattern,
640 c->current.patlen, c->current.max_names - c->names->nnames,
641 &c->current.private);
642 if (err == Suspended) {
645 (ClientSleepProcPtr)doListFontsAndAliases,
651 if (err == Successful)
652 c->current.list_started = TRUE;
654 if (err == Successful) {
657 err = (*fpe_functions[fpe->type].list_next_font_or_alias)
658 ((pointer) c->client, fpe, &name, &namelen, &tmpname,
659 &resolvedlen, c->current.private);
660 if (err == Suspended) {
663 (ClientSleepProcPtr)doListFontsAndAliases,
669 if (err == FontNameAlias) {
670 if (resolved) xfree(resolved);
671 resolved = (char *) xalloc(resolvedlen + 1);
673 memmove(resolved, tmpname, resolvedlen + 1);
677 if (err == Successful)
682 (void)AddFontNamesName(c->names, c->savedName,
686 (void)AddFontNamesName(c->names, name, namelen);
690 * When we get an alias back, save our state and reset back to
691 * the start of the FPE looking for the specified name. As
692 * soon as a real font is found for the alias, pop back to the
695 else if (err == FontNameAlias) {
696 char tmp_pattern[256];
698 * when an alias recurses, we need to give
699 * the last FPE a chance to clean up; so we call
700 * it again, and assume that the error returned
701 * is BadFontName, indicating the alias resolution
704 memmove(tmp_pattern, resolved, resolvedlen);
711 (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
712 ((pointer) c->client, fpe, &tmpname, &tmpnamelen,
713 &tmpname, &tmpnamelen, c->current.private);
714 if (--aliascount <= 0)
717 goto ContBadFontName;
722 c->saved = c->current;
726 c->savedName = (char *)xalloc(namelen + 1);
728 memmove(c->savedName, name, namelen + 1);
729 c->savedNameLen = namelen;
732 memmove(c->current.pattern, tmp_pattern, resolvedlen);
733 c->current.patlen = resolvedlen;
734 c->current.max_names = c->names->nnames + 1;
735 c->current.current_fpe = -1;
736 c->current.private = 0;
741 * At the end of this FPE, step to the next. If we've finished
742 * processing an alias, pop state back. If we've collected enough
745 if (err == BadFontName) {
747 c->current.list_started = FALSE;
748 c->current.current_fpe++;
752 if (c->names->nnames == c->current.max_names ||
753 c->current.current_fpe == c->num_fpes) {
754 c->haveSaved = FALSE;
755 c->current = c->saved;
756 /* Give the saved namelist a chance to clean itself up */
760 if (c->names->nnames == c->current.max_names)
768 if (err != Successful) {
769 SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
776 nnames = names->nnames;
779 for (i = 0; i < nnames; i++)
780 stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
782 reply.type = X_Reply;
783 reply.length = (stringLens + nnames + 3) >> 2;
784 reply.nFonts = nnames;
785 reply.sequenceNumber = client->sequence;
787 bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2);
789 if (!bufptr && reply.length) {
790 SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
794 * since WriteToClient long word aligns things, copy to temp buffer and
797 for (i = 0; i < nnames; i++) {
798 if (names->length[i] > 255)
802 *bufptr++ = names->length[i];
803 memmove( bufptr, names->names[i], names->length[i]);
804 bufptr += names->length[i];
807 nnames = reply.nFonts;
808 reply.length = (stringLens + nnames + 3) >> 2;
809 client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
810 WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
811 (void) WriteToClient(client, stringLens + nnames, bufferStart);
812 DEALLOCATE_LOCAL(bufferStart);
816 ClientWakeup(client);
817 for (i = 0; i < c->num_fpes; i++)
818 FreeFPE(c->fpe_list[i]);
820 if (c->savedName) xfree(c->savedName);
821 FreeFontNames(names);
823 if (resolved) xfree(resolved);
828 ListFonts(client, pattern, length, max_names)
830 unsigned char *pattern;
832 unsigned int max_names;
837 if (!(c = (LFclosurePtr) xalloc(sizeof *c)))
839 c->fpe_list = (FontPathElementPtr *)
840 xalloc(sizeof(FontPathElementPtr) * num_fpes);
845 c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
852 memmove( c->current.pattern, pattern, length);
853 for (i = 0; i < num_fpes; i++) {
854 c->fpe_list[i] = font_path_elements[i];
855 UseFPE(c->fpe_list[i]);
858 c->num_fpes = num_fpes;
859 c->current.patlen = length;
860 c->current.current_fpe = 0;
861 c->current.max_names = max_names;
862 c->current.list_started = FALSE;
863 c->current.private = 0;
864 c->haveSaved = FALSE;
867 doListFontsAndAliases(client, c);
872 doListFontsWithInfo(client, c)
876 FontPathElementPtr fpe;
877 int err = Successful;
881 FontInfoRec fontInfo,
883 xListFontsWithInfoReply *reply;
888 xListFontsWithInfoReply finalReply;
890 if (client->clientGone)
892 if (c->current.current_fpe < c->num_fpes)
894 fpe = c->fpe_list[c->current.current_fpe];
895 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
900 client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
901 if (!c->current.patlen)
903 while (c->current.current_fpe < c->num_fpes)
905 fpe = c->fpe_list[c->current.current_fpe];
907 if (!c->current.list_started)
909 err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
910 (client, fpe, c->current.pattern, c->current.patlen,
911 c->current.max_names, &c->current.private);
912 if (err == Suspended)
916 ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
921 if (err == Successful)
922 c->current.list_started = TRUE;
924 if (err == Successful)
927 pFontInfo = &fontInfo;
928 err = (*fpe_functions[fpe->type].list_next_font_with_info)
929 (client, fpe, &name, &namelen, &pFontInfo,
930 &numFonts, c->current.private);
931 if (err == Suspended)
936 (ClientSleepProcPtr)doListFontsWithInfo,
944 * When we get an alias back, save our state and reset back to the
945 * start of the FPE looking for the specified name. As soon as a real
946 * font is found for the alias, pop back to the old state
948 if (err == FontNameAlias)
951 * when an alias recurses, we need to give
952 * the last FPE a chance to clean up; so we call
953 * it again, and assume that the error returned
954 * is BadFontName, indicating the alias resolution
961 FontInfoPtr tmpFontInfo;
964 tmpFontInfo = &fontInfo;
965 (void) (*fpe_functions[fpe->type].list_next_font_with_info)
966 (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
967 &numFonts, c->current.private);
968 if (--aliascount <= 0)
971 goto ContBadFontName;
976 c->saved = c->current;
978 c->savedNumFonts = numFonts;
979 c->savedName = (char *) pFontInfo;
982 memmove(c->current.pattern, name, namelen);
983 c->current.patlen = namelen;
984 c->current.max_names = 1;
985 c->current.current_fpe = 0;
986 c->current.private = 0;
987 c->current.list_started = FALSE;
990 * At the end of this FPE, step to the next. If we've finished
991 * processing an alias, pop state back. If we've sent enough font
992 * names, quit. Always wait for BadFontName to let the FPE
993 * have a chance to clean up.
995 else if (err == BadFontName)
998 c->current.list_started = FALSE;
999 c->current.current_fpe++;
1003 if (c->current.max_names == 0 ||
1004 c->current.current_fpe == c->num_fpes)
1006 c->haveSaved = FALSE;
1007 c->saved.max_names -= (1 - c->current.max_names);
1008 c->current = c->saved;
1011 else if (c->current.max_names == 0)
1014 else if (err == Successful)
1016 length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
1018 if (c->length < length)
1020 reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length);
1031 numFonts = c->savedNumFonts;
1032 name = c->savedName;
1033 namelen = strlen(name);
1035 reply->type = X_Reply;
1036 reply->length = (sizeof *reply - sizeof(xGenericReply) +
1037 pFontInfo->nprops * sizeof(xFontProp) +
1039 reply->sequenceNumber = client->sequence;
1040 reply->nameLength = namelen;
1041 reply->minBounds = pFontInfo->ink_minbounds;
1042 reply->maxBounds = pFontInfo->ink_maxbounds;
1043 reply->minCharOrByte2 = pFontInfo->firstCol;
1044 reply->maxCharOrByte2 = pFontInfo->lastCol;
1045 reply->defaultChar = pFontInfo->defaultCh;
1046 reply->nFontProps = pFontInfo->nprops;
1047 reply->drawDirection = pFontInfo->drawDirection;
1048 reply->minByte1 = pFontInfo->firstRow;
1049 reply->maxByte1 = pFontInfo->lastRow;
1050 reply->allCharsExist = pFontInfo->allExist;
1051 reply->fontAscent = pFontInfo->fontAscent;
1052 reply->fontDescent = pFontInfo->fontDescent;
1053 reply->nReplies = numFonts;
1054 pFP = (xFontProp *) (reply + 1);
1055 for (i = 0; i < pFontInfo->nprops; i++)
1057 pFP->name = pFontInfo->props[i].name;
1058 pFP->value = pFontInfo->props[i].value;
1061 WriteSwappedDataToClient(client, length, reply);
1062 (void) WriteToClient(client, namelen, name);
1063 if (pFontInfo == &fontInfo)
1065 xfree(fontInfo.props);
1066 xfree(fontInfo.isStringProp);
1068 --c->current.max_names;
1072 length = sizeof(xListFontsWithInfoReply);
1073 bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply));
1074 finalReply.type = X_Reply;
1075 finalReply.sequenceNumber = client->sequence;
1076 finalReply.length = (sizeof(xListFontsWithInfoReply)
1077 - sizeof(xGenericReply)) >> 2;
1078 WriteSwappedDataToClient(client, length, &finalReply);
1081 ClientWakeup(client);
1082 for (i = 0; i < c->num_fpes; i++)
1083 FreeFPE(c->fpe_list[i]);
1091 StartListFontsWithInfo(client, length, pattern, max_names)
1094 unsigned char *pattern;
1100 if (!(c = (LFWIclosurePtr) xalloc(sizeof *c)))
1102 c->fpe_list = (FontPathElementPtr *)
1103 xalloc(sizeof(FontPathElementPtr) * num_fpes);
1109 memmove(c->current.pattern, pattern, length);
1110 for (i = 0; i < num_fpes; i++)
1112 c->fpe_list[i] = font_path_elements[i];
1113 UseFPE(c->fpe_list[i]);
1116 c->num_fpes = num_fpes;
1119 c->current.patlen = length;
1120 c->current.current_fpe = 0;
1121 c->current.max_names = max_names;
1122 c->current.list_started = FALSE;
1123 c->current.private = 0;
1124 c->savedNumFonts = 0;
1125 c->haveSaved = FALSE;
1127 doListFontsWithInfo(client, c);
1133 #define TextEltHeader 2
1134 #define FontShiftSize 5
1135 static XID clearGC[] = { CT_NONE };
1136 #define clearGCmask (GCClipMask)
1139 doPolyText(client, c)
1141 register PTclosurePtr c;
1143 register FontPtr pFont = c->pGC->font, oldpFont;
1145 int err = Success, lgerr; /* err is in X error, not font error, space */
1146 enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state;
1147 FontPathElementPtr fpe;
1150 if (client->clientGone)
1152 fpe = c->pGC->font->fpe;
1153 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1157 /* Client has died, but we cannot bail out right now. We
1158 need to clean up after the work we did when going to
1159 sleep. Setting the drawable pointer to 0 makes this
1160 happen without any attempts to render or perform other
1161 unnecessary activities. */
1162 c->pDraw = (DrawablePtr)0;
1171 /* Make sure our drawable hasn't disappeared while we slept. */
1174 c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did,
1175 RC_DRAWABLE, SecurityWriteAccess))
1177 /* Our drawable has disappeared. Treat like client died... ask
1178 the FPE code to clean up after client and avoid further
1179 rendering while we clean up after ourself. */
1180 fpe = c->pGC->font->fpe;
1181 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1182 c->pDraw = (DrawablePtr)0;
1185 client_state = c->slept ? SLEEPING : NEVER_SLEPT;
1187 while (c->endReq - c->pElt > TextEltHeader)
1189 if (*c->pElt == FontChange)
1191 if (c->endReq - c->pElt < FontShiftSize)
1200 fid = ((Font)*(c->pElt+4)) /* big-endian */
1201 | ((Font)*(c->pElt+3)) << 8
1202 | ((Font)*(c->pElt+2)) << 16
1203 | ((Font)*(c->pElt+1)) << 24;
1204 pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT,
1205 SecurityReadAccess);
1208 client->errorValue = fid;
1210 /* restore pFont and fid for step 4 (described below) */
1214 /* If we're in START_SLEEP mode, the following step
1215 shortens the request... in the unlikely event that
1216 the fid somehow becomes valid before we come through
1217 again to actually execute the polytext, which would
1218 then mess up our refcounting scheme badly. */
1220 c->endReq = c->pElt;
1225 /* Step 3 (described below) on our new font */
1226 if (client_state == START_SLEEP)
1230 if (pFont != c->pGC->font && c->pDraw)
1232 ChangeGC( c->pGC, GCFont, &fid);
1233 ValidateGC(c->pDraw, c->pGC);
1234 if (c->reqType == X_PolyText8)
1235 c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8;
1237 c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16;
1240 /* Undo the refcnt++ we performed when going to sleep */
1241 if (client_state == SLEEPING)
1242 (void)CloseFont(c->pGC->font, (Font)0);
1244 c->pElt += FontShiftSize;
1246 else /* print a string */
1248 unsigned char *pNextElt;
1249 pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize;
1250 if ( pNextElt > c->endReq)
1255 if (client_state == START_SLEEP)
1262 lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize,
1263 c->pElt + TextEltHeader);
1265 else lgerr = Successful;
1267 if (lgerr == Suspended)
1272 PTclosurePtr new_closure;
1274 /* We're putting the client to sleep. We need to do a few things
1275 to ensure successful and atomic-appearing execution of the
1276 remainder of the request. First, copy the remainder of the
1277 request into a safe malloc'd area. Second, create a scratch GC
1278 to use for the remainder of the request. Third, mark all fonts
1279 referenced in the remainder of the request to prevent their
1280 deallocation. Fourth, make the original GC look like the
1281 request has completed... set its font to the final font value
1282 from this request. These GC manipulations are for the unlikely
1283 (but possible) event that some other client is using the GC.
1284 Steps 3 and 4 are performed by running this procedure through
1285 the remainder of the request in a special no-render mode
1286 indicated by client_state = START_SLEEP. */
1289 /* Allocate a malloc'd closure structure to replace
1290 the local one we were passed */
1291 new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec));
1300 len = c->endReq - c->pElt;
1301 c->data = (unsigned char *)xalloc(len);
1308 memmove(c->data, c->pElt, len);
1310 c->endReq = c->pElt + len;
1314 pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
1322 if ((err = CopyGC(c->pGC, pGC, GCFunction |
1323 GCPlaneMask | GCForeground |
1324 GCBackground | GCFillStyle |
1325 GCTile | GCStipple |
1327 GCTileStipYOrigin | GCFont |
1328 GCSubwindowMode | GCClipXOrigin |
1329 GCClipYOrigin | GCClipMask)) !=
1340 ValidateGC(c->pDraw, c->pGC);
1344 (ClientSleepProcPtr)doPolyText,
1347 /* Set up to perform steps 3 and 4 */
1348 client_state = START_SLEEP;
1349 continue; /* on to steps 3 and 4 */
1353 else if (lgerr != Successful)
1355 err = FontToXError(lgerr);
1360 c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */
1361 c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg,
1362 *c->pElt, c->pElt + TextEltHeader);
1370 if (client_state == START_SLEEP)
1373 if (pFont != origGC->font)
1375 ChangeGC(origGC, GCFont, &fid);
1376 ValidateGC(c->pDraw, origGC);
1379 /* restore pElt pointer for execution of remainder of the request */
1384 if (c->err != Success) err = c->err;
1385 if (err != Success && c->client != serverClient) {
1386 SendErrorToClient(c->client, c->reqType, 0, 0, err);
1390 ClientWakeup(c->client);
1391 ChangeGC(c->pGC, clearGCmask, clearGC);
1393 /* Unreference the font from the scratch GC */
1394 CloseFont(c->pGC->font, (Font)0);
1395 c->pGC->font = NullFont;
1397 FreeScratchGC(c->pGC);
1405 PolyText(client, pDraw, pGC, pElt, endReq, xorg, yorg, reqType, did)
1409 unsigned char *pElt;
1410 unsigned char *endReq;
1416 PTclosureRec local_closure;
1418 local_closure.pElt = pElt;
1419 local_closure.endReq = endReq;
1420 local_closure.client = client;
1421 local_closure.pDraw = pDraw;
1422 local_closure.xorg = xorg;
1423 local_closure.yorg = yorg;
1424 if ((local_closure.reqType = reqType) == X_PolyText8)
1426 local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8;
1427 local_closure.itemSize = 1;
1431 local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16;
1432 local_closure.itemSize = 2;
1434 local_closure.pGC = pGC;
1435 local_closure.did = did;
1436 local_closure.err = Success;
1437 local_closure.slept = FALSE;
1439 (void) doPolyText(client, &local_closure);
1444 #undef TextEltHeader
1445 #undef FontShiftSize
1448 doImageText(client, c)
1450 register 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, SecurityWriteAccess))
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(client, pDraw, pGC, nChars, data, xorg, yorg, reqType, did)
1576 unsigned char *data;
1582 ITclosureRec local_closure;
1584 local_closure.client = client;
1585 local_closure.pDraw = pDraw;
1586 local_closure.pGC = pGC;
1587 local_closure.nChars = nChars;
1588 local_closure.data = data;
1589 local_closure.xorg = xorg;
1590 local_closure.yorg = yorg;
1591 if ((local_closure.reqType = reqType) == X_ImageText8)
1593 local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8;
1594 local_closure.itemSize = 1;
1598 local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16;
1599 local_closure.itemSize = 2;
1601 local_closure.did = did;
1602 local_closure.slept = FALSE;
1604 (void) doImageText(client, &local_closure);
1609 /* does the necessary magic to figure out the fpe type */
1611 #if NeedFunctionPrototypes
1612 DetermineFPEType(char *pathname)
1614 DetermineFPEType(pathname)
1620 for (i = 0; i < num_fpe_types; i++) {
1621 if ((*fpe_functions[i].name_check) (pathname))
1629 #if NeedFunctionPrototypes
1630 FreeFontPath(FontPathElementPtr *list, int n, Bool force)
1632 FreeFontPath(list, n, force)
1633 FontPathElementPtr *list;
1640 for (i = 0; i < n; i++) {
1642 /* Sanity check that all refcounts will be 0 by the time
1643 we get to the end of the list. */
1644 int found = 1; /* the first reference is us */
1646 for (j = i+1; j < n; j++) {
1647 if (list[j] == list[i])
1650 if (list[i]->refcount != found) {
1651 ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n",
1652 list[i]->name_length, list[i]->name,
1653 list[i]->refcount, found);
1654 list[i]->refcount = found; /* ensure it will get freed */
1659 xfree((char *) list);
1662 static FontPathElementPtr
1663 #if NeedFunctionPrototypes
1664 find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len)
1666 find_existing_fpe(list, num, name, len)
1667 FontPathElementPtr *list;
1669 unsigned char *name;
1673 FontPathElementPtr fpe;
1676 for (i = 0; i < num; i++) {
1678 if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0)
1681 return (FontPathElementPtr) 0;
1686 #if NeedFunctionPrototypes
1687 SetFontPathElements(int npaths, unsigned char *paths, int *bad)
1689 SetFontPathElements(npaths, paths, bad)
1691 unsigned char *paths;
1697 int valid_paths = 0;
1699 unsigned char *cp = paths;
1700 FontPathElementPtr fpe,
1703 fplist = (FontPathElementPtr *)
1704 xalloc(sizeof(FontPathElementPtr) * npaths);
1709 for (i = 0; i < num_fpe_types; i++) {
1710 if (fpe_functions[i].set_path_hook)
1711 (*fpe_functions[i].set_path_hook) ();
1713 for (i = 0; i < npaths; i++) {
1714 len = (unsigned int) (*cp++);
1717 /* if it's already in our active list, just reset it */
1719 * note that this can miss FPE's in limbo -- may be worth catching
1720 * them, though it'd muck up refcounting
1722 fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len);
1724 err = (*fpe_functions[fpe->type].reset_fpe) (fpe);
1725 if (err == Successful) {
1726 UseFPE(fpe);/* since it'll be decref'd later when freed
1727 * from the old list */
1728 fplist[valid_paths++] = fpe;
1732 /* if error or can't do it, act like it's a new one */
1734 fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec));
1739 fpe->name = (char *) xalloc(len + 1);
1747 strncpy(fpe->name, (char *) cp, (int) len);
1749 fpe->name[len] = '\0';
1750 fpe->name_length = len;
1751 fpe->type = DetermineFPEType(fpe->name);
1752 if (fpe->type == -1) {
1758 err = (*fpe_functions[fpe->type].init_fpe) (fpe);
1759 if (err != Successful) {
1765 fplist[valid_paths++] = fpe;
1773 FreeFontPath(font_path_elements, num_fpes, FALSE);
1774 font_path_elements = fplist;
1776 EmptyFontPatternCache(patternCache);
1777 num_fpes = valid_paths;
1788 /* XXX -- do we need to pass error down to each renderer? */
1790 SetFontPath(client, npaths, paths, error)
1793 unsigned char *paths;
1799 if (SetDefaultFontPath(defaultFontPath) != Success)
1802 err = SetFontPathElements(npaths, paths, error);
1807 /*** TJR - dirty hack - this variable is used in lib/font/fontfile/dirfile.c */
1808 int settingDefaultFontPath = 0;
1811 SetDefaultFontPath(path)
1824 /* get enough for string, plus values -- use up commas */
1825 len = strlen(path) + 1;
1826 nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len);
1829 pp = (unsigned char *) path;
1833 *nump = (unsigned char) size;
1843 *nump = (unsigned char) size;
1845 settingDefaultFontPath = 1;
1847 err = SetFontPathElements(num, newpath, &bad);
1849 settingDefaultFontPath = 0;
1851 DEALLOCATE_LOCAL(newpath);
1857 GetFontPath(count, length)
1864 FontPathElementPtr fpe;
1867 for (i = 0; i < num_fpes; i++) {
1868 fpe = font_path_elements[i];
1869 len += fpe->name_length + 1;
1871 font_path_string = (unsigned char *) xrealloc(font_path_string, len);
1872 if (!font_path_string)
1875 c = font_path_string;
1877 for (i = 0; i < num_fpes; i++) {
1878 fpe = font_path_elements[i];
1879 *c = fpe->name_length;
1881 memmove(c, fpe->name, fpe->name_length);
1882 c += fpe->name_length;
1885 return font_path_string;
1889 LoadGlyphs(client, pfont, nchars, item_size, data)
1894 unsigned char *data;
1896 if (fpe_functions[pfont->fpe->type].load_glyphs)
1897 return (*fpe_functions[pfont->fpe->type].load_glyphs)
1898 (client, pfont, 0, nchars, item_size, data);
1904 DeleteClientFontStuff(client)
1908 FontPathElementPtr fpe;
1910 for (i = 0; i < num_fpes; i++)
1912 fpe = font_path_elements[i];
1913 if (fpe_functions[fpe->type].client_died)
1914 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1921 patternCache = MakeFontPatternCache();
1923 if (screenInfo.numScreens > screenInfo.numVideoScreens) {
1924 PrinterFontRegisterFpeFunctions();
1925 FontFileCheckRegisterFpeFunctions();
1926 check_fs_register_fpe_functions();
1928 FontFileRegisterFpeFunctions();
1929 fs_register_fpe_functions();
1934 GetDefaultPointSize ()
1941 GetClientResolutions (num)
1944 if (requestingClient && requestingClient->fontResFunc != NULL &&
1945 !requestingClient->clientGone)
1947 return (*requestingClient->fontResFunc)(requestingClient, num);
1950 static struct _FontResolution res;
1953 pScreen = screenInfo.screens[0];
1954 res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth;
1956 * XXX - we'll want this as long as bitmap instances are prevalent
1957 so that we can match them from scalable fonts
1959 if (res.x_resolution < 88)
1960 res.x_resolution = 75;
1962 res.x_resolution = 100;
1963 res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight;
1964 if (res.y_resolution < 88)
1965 res.y_resolution = 75;
1967 res.y_resolution = 100;
1968 res.point_size = 120;
1975 * returns the type index of the new fpe
1977 * should be called (only once!) by each type of fpe when initialized
1981 #if NeedFunctionPrototypes
1982 RegisterFPEFunctions(
1987 FontPathElementPtr /* fpe */
1990 FontPathElementPtr /* fpe */
1993 FontPathElementPtr /* fpe */
1996 pointer /* client */,
1997 FontPathElementPtr /* fpe */,
2001 fsBitmapFormat /* format */,
2002 fsBitmapFormatMask /* fmask */,
2003 unsigned long /* id (type XID or FSID) */,
2004 FontPtr* /* pFont */,
2005 char** /* aliasName */,
2006 FontPtr /* non_cachable_font */
2009 FontPathElementPtr /* fpe */,
2013 pointer /* client */,
2014 FontPathElementPtr /* fpe */,
2018 FontNamesPtr /* names */
2020 int (*start_lfwi_func) (
2021 pointer /* client */,
2022 FontPathElementPtr /* fpe */,
2026 pointer* /* privatep */
2028 int (*next_lfwi_func) (
2029 pointer /* client */,
2030 FontPathElementPtr /* fpe */,
2033 FontInfoPtr* /* info */,
2034 int* /* numFonts */,
2035 pointer /* private */
2037 int (*wakeup_func) (
2038 FontPathElementPtr /* fpe */,
2039 unsigned long* /* LastSelectMask */
2041 int (*client_died) (
2042 pointer /* client */,
2043 FontPathElementPtr /* fpe */
2045 int (*load_glyphs) (
2046 pointer /* client */,
2047 FontPtr /* pfont */,
2048 Bool /* range_flag */,
2049 unsigned int /* nchars */,
2050 int /* item_size */,
2051 unsigned char* /* data */
2053 int (*start_list_alias_func) (
2054 pointer /* client */,
2055 FontPathElementPtr /* fpe */,
2059 pointer* /* privatep */
2061 int (*next_list_alias_func) (
2062 pointer /* client */,
2063 FontPathElementPtr /* fpe */,
2065 int* /* namelenp */,
2066 char** /* resolvedp */,
2067 int* /* resolvedlenp */,
2068 pointer /* private */
2070 void (*set_path_func) (
2075 RegisterFPEFunctions(name_func, init_func, free_func, reset_func,
2076 open_func, close_func, list_func, start_lfwi_func, next_lfwi_func,
2077 wakeup_func, client_died, load_glyphs,
2078 start_list_alias_func, next_list_alias_func,
2080 Bool (*name_func) ();
2081 int (*init_func) ();
2082 int (*free_func) ();
2083 int (*reset_func) ();
2084 int (*open_func) ();
2085 int (*close_func) ();
2086 int (*list_func) ();
2087 int (*start_lfwi_func) ();
2088 int (*next_lfwi_func) ();
2089 int (*wakeup_func) ();
2090 int (*client_died) ();
2091 int (*load_glyphs) ();
2092 int (*start_list_alias_func) ();
2093 int (*next_list_alias_func) ();
2094 void (*set_path_func) ();
2100 new = (FPEFunctions *) xrealloc(fpe_functions,
2101 (num_fpe_types + 1) * sizeof(FPEFunctions));
2104 fpe_functions = new;
2106 fpe_functions[num_fpe_types].name_check = name_func;
2107 fpe_functions[num_fpe_types].open_font = open_func;
2108 fpe_functions[num_fpe_types].close_font = close_func;
2109 fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func;
2110 fpe_functions[num_fpe_types].list_fonts = list_func;
2111 fpe_functions[num_fpe_types].start_list_fonts_with_info =
2113 fpe_functions[num_fpe_types].list_next_font_with_info =
2115 fpe_functions[num_fpe_types].init_fpe = init_func;
2116 fpe_functions[num_fpe_types].free_fpe = free_func;
2117 fpe_functions[num_fpe_types].reset_fpe = reset_func;
2118 fpe_functions[num_fpe_types].client_died = client_died;
2119 fpe_functions[num_fpe_types].load_glyphs = load_glyphs;
2120 fpe_functions[num_fpe_types].start_list_fonts_and_aliases =
2121 start_list_alias_func;
2122 fpe_functions[num_fpe_types].list_next_font_or_alias =
2123 next_list_alias_func;
2124 fpe_functions[num_fpe_types].set_path_hook = set_path_func;
2126 return num_fpe_types++;
2133 FreeFontPatternCache(patternCache);
2136 FreeFontPath(font_path_elements, num_fpes, TRUE);
2137 font_path_elements = 0;
2139 xfree(fpe_functions);
2141 fpe_functions = (FPEFunctions *) 0;
2144 /* convenience functions for FS interface */
2150 return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE,
2151 SecurityUnknownAccess);
2155 GetNewFontClientID()
2157 return FakeClientID(0);
2161 StoreFontClientFont(pfont, id)
2165 return AddResource(id, RT_NONE, (pointer) pfont);
2169 DeleteFontClientID(id)
2172 FreeResource(id, RT_NONE);
2176 client_auth_generation(client)
2182 static int fs_handlers_installed = 0;
2183 static unsigned int last_server_gen;
2186 init_fs_handlers(fpe, block_handler)
2187 FontPathElementPtr fpe;
2188 BlockHandlerProcPtr block_handler;
2190 /* if server has reset, make sure the b&w handlers are reinstalled */
2191 if (last_server_gen < serverGeneration) {
2192 last_server_gen = serverGeneration;
2193 fs_handlers_installed = 0;
2195 if (fs_handlers_installed == 0) {
2198 fprintf(stderr, "adding FS b & w handlers\n");
2201 if (!RegisterBlockAndWakeupHandlers(block_handler,
2202 FontWakeup, (pointer) 0))
2204 fs_handlers_installed++;
2206 QueueFontWakeup(fpe);
2211 remove_fs_handlers(fpe, block_handler, all)
2212 FontPathElementPtr fpe;
2213 BlockHandlerProcPtr block_handler;
2217 /* remove the handlers if no one else is using them */
2218 if (--fs_handlers_installed == 0) {
2221 fprintf(stderr, "removing FS b & w handlers\n");
2224 RemoveBlockAndWakeupHandlers(block_handler, FontWakeup,
2228 RemoveFontWakeup(fpe);
2232 #define GLWIDTHBYTESPADDED(bits,nbytes) \
2233 ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \
2234 :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \
2235 :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \
2236 :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \
2239 #define GLYPH_SIZE(ch, nbytes) \
2240 GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \
2241 (ch)->metrics.leftSideBearing, (nbytes))
2242 dump_char_ascii(cip)
2249 static unsigned maskTab[] = {
2250 (1 << 7), (1 << 6), (1 << 5), (1 << 4),
2251 (1 << 3), (1 << 2), (1 << 1), (1 << 0),
2254 bpr = GLYPH_SIZE(cip, 4);
2255 for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) {
2256 pointer row = (pointer) cip->bits + r * bpr;
2259 for (l = 0; l <= (cip->metrics.rightSideBearing -
2260 cip->metrics.leftSideBearing); l++) {
2261 if (maskTab[l & 7] & row[l >> 3])