1
/* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.27 2003/02/15 03:47:05 dawes Exp $ */
2
/************************************************************************
3
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
7
Permission to use, copy, modify, and distribute this software and its
8
documentation for any purpose and without fee is hereby granted,
9
provided that the above copyright notice appear in all copies and that
10
both that copyright notice and this permission notice appear in
11
supporting documentation, and that the name of Digital not be
12
used in advertising or publicity pertaining to distribution of the
13
software without specific, written prior permission.
15
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23
************************************************************************/
25
/* $Xorg: dixfonts.c,v 1.4 2000/08/17 19:48:18 cpqbld Exp $ */
31
#include "scrnintstr.h"
33
#include "dixstruct.h"
34
#include "cursorstr.h"
37
#include "dixfontstr.h"
45
#include "panoramiX.h"
53
#define _XF86BIGFONT_SERVER_
54
#include "xf86bigfont.h"
57
#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics
59
extern pointer fosNaturalParams;
60
extern FontPtr defaultFont;
62
static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
63
static int num_fpes = 0;
64
FPEFunctions *fpe_functions = (FPEFunctions *) 0;
65
static int num_fpe_types = 0;
67
static unsigned char *font_path_string;
69
static int num_slept_fpes = 0;
70
static int size_slept_fpes = 0;
71
static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
72
static FontPatternCachePtr patternCache;
86
case BadFontFormat: /* is there something better? */
96
* adding RT_FONT prevents conflict with default cursor font
99
SetDefaultFont(defaultfontname)
100
char *defaultfontname;
106
fid = FakeClientID(0);
107
err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
108
(unsigned) strlen(defaultfontname), defaultfontname);
111
pf = (FontPtr) LookupIDByType(fid, RT_FONT);
112
if (pf == (FontPtr) NULL)
119
* note that the font wakeup queue is not refcounted. this is because
120
* an fpe needs to be added when it's inited, and removed when it's finally
121
* freed, in order to handle any data that isn't requested, like FS events.
123
* since the only thing that should call these routines is the renderer's
124
* init_fpe() and free_fpe(), there shouldn't be any problem in using
129
FontPathElementPtr fpe;
132
FontPathElementPtr *new;
134
for (i = 0; i < num_slept_fpes; i++) {
135
if (slept_fpes[i] == fpe) {
138
fprintf(stderr, "re-queueing fpe wakeup\n");
144
if (num_slept_fpes == size_slept_fpes) {
145
new = (FontPathElementPtr *)
147
sizeof(FontPathElementPtr) * (size_slept_fpes + 4));
151
size_slept_fpes += 4;
153
slept_fpes[num_slept_fpes] = fpe;
158
RemoveFontWakeup(fpe)
159
FontPathElementPtr fpe;
164
for (i = 0; i < num_slept_fpes; i++) {
165
if (slept_fpes[i] == fpe) {
166
for (j = i; j < num_slept_fpes; j++) {
167
slept_fpes[j] = slept_fpes[j + 1];
177
FontWakeup(data, count, LastSelectMask)
180
pointer LastSelectMask;
183
FontPathElementPtr fpe;
187
/* wake up any fpe's that may be waiting for information */
188
for (i = 0; i < num_slept_fpes; i++) {
190
(void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask);
194
/* XXX -- these two funcs may want to be broken into macros */
196
#if NeedFunctionPrototypes
197
UseFPE(FontPathElementPtr fpe)
200
FontPathElementPtr fpe;
207
#if NeedFunctionPrototypes
208
FreeFPE (FontPathElementPtr fpe)
211
FontPathElementPtr fpe;
215
if (fpe->refcount == 0) {
216
(*fpe_functions[fpe->type].free_fpe) (fpe);
223
#if NeedFunctionPrototypes
224
doOpenFont(ClientPtr client, OFclosurePtr c)
226
doOpenFont(client, c)
231
FontPtr pfont = NullFont;
232
FontPathElementPtr fpe = NULL;
234
int err = Successful;
241
* Decide at runtime what FontFormat to use.
245
((screenInfo.imageByteOrder == LSBFirst) ?
246
BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
248
((screenInfo.bitmapBitOrder == LSBFirst) ?
249
BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
251
BitmapFormatImageRectMin |
253
#if GLYPHPADBYTES == 1
254
BitmapFormatScanlinePad8 |
257
#if GLYPHPADBYTES == 2
258
BitmapFormatScanlinePad16 |
261
#if GLYPHPADBYTES == 4
262
BitmapFormatScanlinePad32 |
265
#if GLYPHPADBYTES == 8
266
BitmapFormatScanlinePad64 |
269
BitmapFormatScanlineUnit8;
271
if (client->clientGone)
273
if (c->current_fpe < c->num_fpes)
275
fpe = c->fpe_list[c->current_fpe];
276
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
281
while (c->current_fpe < c->num_fpes) {
282
fpe = c->fpe_list[c->current_fpe];
283
err = (*fpe_functions[fpe->type].open_font)
284
((pointer) client, fpe, c->flags,
285
c->fontname, c->fnamelen, FontFormat,
286
BitmapFormatMaskByte |
287
BitmapFormatMaskBit |
288
BitmapFormatMaskImageRectangle |
289
BitmapFormatMaskScanLinePad |
290
BitmapFormatMaskScanLineUnit,
291
c->fontid, &pfont, &alias,
292
c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
293
c->non_cachable_font :
296
if (err == FontNameAlias && alias) {
297
newlen = strlen(alias);
298
newname = (char *) xrealloc(c->fontname, newlen);
303
memmove(newname, alias, newlen);
304
c->fontname = newname;
305
c->fnamelen = newlen;
307
if (--aliascount <= 0)
311
if (err == BadFontName) {
315
if (err == Suspended) {
318
ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c);
325
if (err != Successful)
334
if (pfont->refcnt == 1) {
336
for (i = 0; i < screenInfo.numScreens; i++) {
337
pScr = screenInfo.screens[i];
338
if (pScr->RealizeFont)
340
if (!(*pScr->RealizeFont) (pScr, pfont))
342
CloseFont (pfont, (Font) 0);
349
if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) {
353
if (patternCache && pfont != c->non_cachable_font)
354
CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen,
357
if (err != Successful && c->client != serverClient) {
358
SendErrorToClient(c->client, X_OpenFont, 0,
359
c->fontid, FontToXError(err));
362
ClientWakeup(c->client);
363
for (i = 0; i < c->num_fpes; i++) {
364
FreeFPE(c->fpe_list[i]);
373
OpenFont(client, fid, flags, lenfname, pfontname)
382
FontPtr cached = (FontPtr)0;
386
f = (char *)xalloc(lenfname + 1);
387
memmove(f, pfontname, lenfname);
389
ErrorF("OpenFont: fontname is \"%s\"\n", f);
392
if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
398
** Check name cache. If we find a cached version of this font that
399
** is cachable, immediately satisfy the request with it. If we find
400
** a cached version of this font that is non-cachable, we do not
401
** satisfy the request with it. Instead, we pass the FontPtr to the
402
** FPE's open_font code (the fontfile FPE in turn passes the
403
** information to the rasterizer; the fserve FPE ignores it).
405
** Presumably, the font is marked non-cachable because the FPE has
406
** put some licensing restrictions on it. If the FPE, using
407
** whatever logic it relies on, determines that it is willing to
408
** share this existing font with the client, then it has the option
409
** to return the FontPtr we passed it as the newly-opened font.
410
** This allows the FPE to exercise its licensing logic without
411
** having to create another instance of a font that already exists.
414
cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
415
if (cached && cached->info.cachable)
417
if (!AddResource(fid, RT_FONT, (pointer) cached))
423
c = (OFclosurePtr) xalloc(sizeof(OFclosureRec));
426
c->fontname = (char *) xalloc(lenfname);
427
c->origFontName = pfontname;
428
c->origFontNameLen = lenfname;
434
* copy the current FPE list, so that if it gets changed by another client
435
* while we're blocking, the request still appears atomic
437
c->fpe_list = (FontPathElementPtr *)
438
xalloc(sizeof(FontPathElementPtr) * num_fpes);
444
memmove(c->fontname, pfontname, lenfname);
445
for (i = 0; i < num_fpes; i++) {
446
c->fpe_list[i] = font_path_elements[i];
447
UseFPE(c->fpe_list[i]);
452
c->num_fpes = num_fpes;
453
c->fnamelen = lenfname;
456
c->non_cachable_font = cached;
458
(void) doOpenFont(client, c);
463
* Decrement font's ref count, and free storage if ref count equals zero
467
CloseFont(value, fid)
468
pointer value; /* must conform to DeleteType */
473
FontPathElementPtr fpe;
474
FontPtr pfont = (FontPtr)value;
476
if (pfont == NullFont)
478
if (--pfont->refcnt == 0) {
480
RemoveCachedFontPattern (patternCache, pfont);
482
* since the last reference is gone, ask each screen to free any
483
* storage it may have allocated locally for it.
485
for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
486
pscr = screenInfo.screens[nscr];
487
if (pscr->UnrealizeFont)
488
(*pscr->UnrealizeFont) (pscr, pfont);
490
if (pfont == defaultFont)
493
LbxFreeFontTag(pfont);
496
XF86BigfontFreeFontShm(pfont);
499
(*fpe_functions[fpe->type].close_font) (fpe, pfont);
506
/***====================================================================***/
509
* \ Sets up pReply as the correct QueryFontReply for pFont with the first
510
* nProtoCCIStructs char infos. \
514
QueryFont(pFont, pReply, nProtoCCIStructs)
516
xQueryFontReply *pReply; /* caller must allocate this storage */
517
int nProtoCCIStructs;
525
xCharInfo *charInfos[256];
526
unsigned char chars[512];
531
/* pr->length set in dispatch */
532
pReply->minCharOrByte2 = pFont->info.firstCol;
533
pReply->defaultChar = pFont->info.defaultCh;
534
pReply->maxCharOrByte2 = pFont->info.lastCol;
535
pReply->drawDirection = pFont->info.drawDirection;
536
pReply->allCharsExist = pFont->info.allExist;
537
pReply->minByte1 = pFont->info.firstRow;
538
pReply->maxByte1 = pFont->info.lastRow;
539
pReply->fontAscent = pFont->info.fontAscent;
540
pReply->fontDescent = pFont->info.fontDescent;
542
pReply->minBounds = pFont->info.ink_minbounds;
543
pReply->maxBounds = pFont->info.ink_maxbounds;
545
pReply->nFontProps = pFont->info.nprops;
546
pReply->nCharInfos = nProtoCCIStructs;
548
for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
549
i < pFont->info.nprops;
550
i++, pFP++, prFP++) {
551
prFP->name = pFP->name;
552
prFP->value = pFP->value;
556
ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
557
prCI = (xCharInfo *) (prFP);
558
for (r = pFont->info.firstRow;
559
ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow;
562
for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) {
566
(*pFont->get_metrics) (pFont, ncols, chars,
567
TwoD16Bit, &count, charInfos);
569
for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
570
*prCI = *charInfos[i];
579
#if NeedFunctionPrototypes
580
doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
582
doListFontsAndAliases(client, c)
587
FontPathElementPtr fpe;
588
int err = Successful;
589
FontNamesPtr names = NULL;
590
char *name, *resolved=NULL;
591
int namelen, resolvedlen;
595
xListFontsReply reply;
600
if (client->clientGone)
602
if (c->current.current_fpe < c->num_fpes)
604
fpe = c->fpe_list[c->current.current_fpe];
605
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
611
if (!c->current.patlen)
614
while (c->current.current_fpe < c->num_fpes) {
615
fpe = c->fpe_list[c->current.current_fpe];
618
if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
620
/* This FPE doesn't support/require list_fonts_and_aliases */
622
err = (*fpe_functions[fpe->type].list_fonts)
623
((pointer) c->client, fpe, c->current.pattern,
624
c->current.patlen, c->current.max_names - c->names->nnames,
627
if (err == Suspended) {
631
(ClientSleepProcPtr)doListFontsAndAliases,
641
/* Start of list_fonts_and_aliases functionality. Modeled
642
after list_fonts_with_info in that it resolves aliases,
643
except that the information collected from FPEs is just
644
names, not font info. Each list_next_font_or_alias()
645
returns either a name into name/namelen or an alias into
646
name/namelen and its target name into resolved/resolvedlen.
647
The code at this level then resolves the alias by polling
650
if (!c->current.list_started) {
651
err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
652
((pointer) c->client, fpe, c->current.pattern,
653
c->current.patlen, c->current.max_names - c->names->nnames,
654
&c->current.private);
655
if (err == Suspended) {
658
(ClientSleepProcPtr)doListFontsAndAliases,
664
if (err == Successful)
665
c->current.list_started = TRUE;
667
if (err == Successful) {
670
err = (*fpe_functions[fpe->type].list_next_font_or_alias)
671
((pointer) c->client, fpe, &name, &namelen, &tmpname,
672
&resolvedlen, c->current.private);
673
if (err == Suspended) {
676
(ClientSleepProcPtr)doListFontsAndAliases,
682
if (err == FontNameAlias) {
683
if (resolved) xfree(resolved);
684
resolved = (char *) xalloc(resolvedlen + 1);
686
memmove(resolved, tmpname, resolvedlen + 1);
690
if (err == Successful)
695
(void)AddFontNamesName(c->names, c->savedName,
699
(void)AddFontNamesName(c->names, name, namelen);
703
* When we get an alias back, save our state and reset back to
704
* the start of the FPE looking for the specified name. As
705
* soon as a real font is found for the alias, pop back to the
708
else if (err == FontNameAlias) {
709
char tmp_pattern[XLFDMAXFONTNAMELEN];
711
* when an alias recurses, we need to give
712
* the last FPE a chance to clean up; so we call
713
* it again, and assume that the error returned
714
* is BadFontName, indicating the alias resolution
717
memmove(tmp_pattern, resolved, resolvedlen);
724
(void) (*fpe_functions[fpe->type].list_next_font_or_alias)
725
((pointer) c->client, fpe, &tmpname, &tmpnamelen,
726
&tmpname, &tmpnamelen, c->current.private);
727
if (--aliascount <= 0)
730
goto ContBadFontName;
735
c->saved = c->current;
739
c->savedName = (char *)xalloc(namelen + 1);
741
memmove(c->savedName, name, namelen + 1);
742
c->savedNameLen = namelen;
745
memmove(c->current.pattern, tmp_pattern, resolvedlen);
746
c->current.patlen = resolvedlen;
747
c->current.max_names = c->names->nnames + 1;
748
c->current.current_fpe = -1;
749
c->current.private = 0;
754
* At the end of this FPE, step to the next. If we've finished
755
* processing an alias, pop state back. If we've collected enough
758
if (err == BadFontName) {
760
c->current.list_started = FALSE;
761
c->current.current_fpe++;
765
if (c->names->nnames == c->current.max_names ||
766
c->current.current_fpe == c->num_fpes) {
767
c->haveSaved = FALSE;
768
c->current = c->saved;
769
/* Give the saved namelist a chance to clean itself up */
773
if (c->names->nnames == c->current.max_names)
781
if (err != Successful) {
782
SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
789
nnames = names->nnames;
792
for (i = 0; i < nnames; i++)
793
stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
795
reply.type = X_Reply;
796
reply.length = (stringLens + nnames + 3) >> 2;
797
reply.nFonts = nnames;
798
reply.sequenceNumber = client->sequence;
800
bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2);
802
if (!bufptr && reply.length) {
803
SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
807
* since WriteToClient long word aligns things, copy to temp buffer and
810
for (i = 0; i < nnames; i++) {
811
if (names->length[i] > 255)
815
*bufptr++ = names->length[i];
816
memmove( bufptr, names->names[i], names->length[i]);
817
bufptr += names->length[i];
820
nnames = reply.nFonts;
821
reply.length = (stringLens + nnames + 3) >> 2;
822
client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
823
WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
824
(void) WriteToClient(client, stringLens + nnames, bufferStart);
825
DEALLOCATE_LOCAL(bufferStart);
829
ClientWakeup(client);
830
for (i = 0; i < c->num_fpes; i++)
831
FreeFPE(c->fpe_list[i]);
833
if (c->savedName) xfree(c->savedName);
834
FreeFontNames(names);
836
if (resolved) xfree(resolved);
841
ListFonts(client, pattern, length, max_names)
843
unsigned char *pattern;
845
unsigned int max_names;
851
* The right error to return here would be BadName, however the
852
* specification does not allow for a Name error on this request.
853
* Perhaps a better solution would be to return a nil list, i.e.
854
* a list containing zero fontnames.
856
if (length > XLFDMAXFONTNAMELEN)
859
if (!(c = (LFclosurePtr) xalloc(sizeof *c)))
861
c->fpe_list = (FontPathElementPtr *)
862
xalloc(sizeof(FontPathElementPtr) * num_fpes);
867
c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
874
memmove( c->current.pattern, pattern, length);
875
for (i = 0; i < num_fpes; i++) {
876
c->fpe_list[i] = font_path_elements[i];
877
UseFPE(c->fpe_list[i]);
880
c->num_fpes = num_fpes;
881
c->current.patlen = length;
882
c->current.current_fpe = 0;
883
c->current.max_names = max_names;
884
c->current.list_started = FALSE;
885
c->current.private = 0;
886
c->haveSaved = FALSE;
889
doListFontsAndAliases(client, c);
894
doListFontsWithInfo(client, c)
898
FontPathElementPtr fpe;
899
int err = Successful;
903
FontInfoRec fontInfo,
905
xListFontsWithInfoReply *reply;
910
xListFontsWithInfoReply finalReply;
912
if (client->clientGone)
914
if (c->current.current_fpe < c->num_fpes)
916
fpe = c->fpe_list[c->current.current_fpe];
917
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
922
client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
923
if (!c->current.patlen)
925
while (c->current.current_fpe < c->num_fpes)
927
fpe = c->fpe_list[c->current.current_fpe];
929
if (!c->current.list_started)
931
err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
932
(client, fpe, c->current.pattern, c->current.patlen,
933
c->current.max_names, &c->current.private);
934
if (err == Suspended)
938
ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
943
if (err == Successful)
944
c->current.list_started = TRUE;
946
if (err == Successful)
949
pFontInfo = &fontInfo;
950
err = (*fpe_functions[fpe->type].list_next_font_with_info)
951
(client, fpe, &name, &namelen, &pFontInfo,
952
&numFonts, c->current.private);
953
if (err == Suspended)
958
(ClientSleepProcPtr)doListFontsWithInfo,
966
* When we get an alias back, save our state and reset back to the
967
* start of the FPE looking for the specified name. As soon as a real
968
* font is found for the alias, pop back to the old state
970
if (err == FontNameAlias)
973
* when an alias recurses, we need to give
974
* the last FPE a chance to clean up; so we call
975
* it again, and assume that the error returned
976
* is BadFontName, indicating the alias resolution
983
FontInfoPtr tmpFontInfo;
986
tmpFontInfo = &fontInfo;
987
(void) (*fpe_functions[fpe->type].list_next_font_with_info)
988
(client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
989
&numFonts, c->current.private);
990
if (--aliascount <= 0)
993
goto ContBadFontName;
998
c->saved = c->current;
1000
c->savedNumFonts = numFonts;
1001
c->savedName = (char *) pFontInfo;
1004
memmove(c->current.pattern, name, namelen);
1005
c->current.patlen = namelen;
1006
c->current.max_names = 1;
1007
c->current.current_fpe = 0;
1008
c->current.private = 0;
1009
c->current.list_started = FALSE;
1012
* At the end of this FPE, step to the next. If we've finished
1013
* processing an alias, pop state back. If we've sent enough font
1014
* names, quit. Always wait for BadFontName to let the FPE
1015
* have a chance to clean up.
1017
else if (err == BadFontName)
1020
c->current.list_started = FALSE;
1021
c->current.current_fpe++;
1025
if (c->current.max_names == 0 ||
1026
c->current.current_fpe == c->num_fpes)
1028
c->haveSaved = FALSE;
1029
c->saved.max_names -= (1 - c->current.max_names);
1030
c->current = c->saved;
1033
else if (c->current.max_names == 0)
1036
else if (err == Successful)
1038
length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
1040
if (c->length < length)
1042
reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length);
1053
numFonts = c->savedNumFonts;
1054
name = c->savedName;
1055
namelen = strlen(name);
1057
reply->type = X_Reply;
1058
reply->length = (sizeof *reply - sizeof(xGenericReply) +
1059
pFontInfo->nprops * sizeof(xFontProp) +
1061
reply->sequenceNumber = client->sequence;
1062
reply->nameLength = namelen;
1063
reply->minBounds = pFontInfo->ink_minbounds;
1064
reply->maxBounds = pFontInfo->ink_maxbounds;
1065
reply->minCharOrByte2 = pFontInfo->firstCol;
1066
reply->maxCharOrByte2 = pFontInfo->lastCol;
1067
reply->defaultChar = pFontInfo->defaultCh;
1068
reply->nFontProps = pFontInfo->nprops;
1069
reply->drawDirection = pFontInfo->drawDirection;
1070
reply->minByte1 = pFontInfo->firstRow;
1071
reply->maxByte1 = pFontInfo->lastRow;
1072
reply->allCharsExist = pFontInfo->allExist;
1073
reply->fontAscent = pFontInfo->fontAscent;
1074
reply->fontDescent = pFontInfo->fontDescent;
1075
reply->nReplies = numFonts;
1076
pFP = (xFontProp *) (reply + 1);
1077
for (i = 0; i < pFontInfo->nprops; i++)
1079
pFP->name = pFontInfo->props[i].name;
1080
pFP->value = pFontInfo->props[i].value;
1083
WriteSwappedDataToClient(client, length, reply);
1084
(void) WriteToClient(client, namelen, name);
1085
if (pFontInfo == &fontInfo)
1087
xfree(fontInfo.props);
1088
xfree(fontInfo.isStringProp);
1090
--c->current.max_names;
1094
length = sizeof(xListFontsWithInfoReply);
1095
bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply));
1096
finalReply.type = X_Reply;
1097
finalReply.sequenceNumber = client->sequence;
1098
finalReply.length = (sizeof(xListFontsWithInfoReply)
1099
- sizeof(xGenericReply)) >> 2;
1100
WriteSwappedDataToClient(client, length, &finalReply);
1103
ClientWakeup(client);
1104
for (i = 0; i < c->num_fpes; i++)
1105
FreeFPE(c->fpe_list[i]);
1113
StartListFontsWithInfo(client, length, pattern, max_names)
1116
unsigned char *pattern;
1123
* The right error to return here would be BadName, however the
1124
* specification does not allow for a Name error on this request.
1125
* Perhaps a better solution would be to return a nil list, i.e.
1126
* a list containing zero fontnames.
1128
if (length > XLFDMAXFONTNAMELEN)
1131
if (!(c = (LFWIclosurePtr) xalloc(sizeof *c)))
1133
c->fpe_list = (FontPathElementPtr *)
1134
xalloc(sizeof(FontPathElementPtr) * num_fpes);
1140
memmove(c->current.pattern, pattern, length);
1141
for (i = 0; i < num_fpes; i++)
1143
c->fpe_list[i] = font_path_elements[i];
1144
UseFPE(c->fpe_list[i]);
1147
c->num_fpes = num_fpes;
1150
c->current.patlen = length;
1151
c->current.current_fpe = 0;
1152
c->current.max_names = max_names;
1153
c->current.list_started = FALSE;
1154
c->current.private = 0;
1155
c->savedNumFonts = 0;
1156
c->haveSaved = FALSE;
1158
doListFontsWithInfo(client, c);
1164
#define TextEltHeader 2
1165
#define FontShiftSize 5
1166
static XID clearGC[] = { CT_NONE };
1167
#define clearGCmask (GCClipMask)
1170
doPolyText(client, c)
1172
register PTclosurePtr c;
1174
register FontPtr pFont = c->pGC->font, oldpFont;
1176
int err = Success, lgerr; /* err is in X error, not font error, space */
1177
enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT;
1178
FontPathElementPtr fpe;
1181
if (client->clientGone)
1183
fpe = c->pGC->font->fpe;
1184
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1188
/* Client has died, but we cannot bail out right now. We
1189
need to clean up after the work we did when going to
1190
sleep. Setting the drawable pointer to 0 makes this
1191
happen without any attempts to render or perform other
1192
unnecessary activities. */
1193
c->pDraw = (DrawablePtr)0;
1202
/* Make sure our drawable hasn't disappeared while we slept. */
1205
c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did,
1206
RC_DRAWABLE, SecurityWriteAccess))
1208
/* Our drawable has disappeared. Treat like client died... ask
1209
the FPE code to clean up after client and avoid further
1210
rendering while we clean up after ourself. */
1211
fpe = c->pGC->font->fpe;
1212
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1213
c->pDraw = (DrawablePtr)0;
1216
client_state = c->slept ? SLEEPING : NEVER_SLEPT;
1218
while (c->endReq - c->pElt > TextEltHeader)
1220
if (*c->pElt == FontChange)
1222
if (c->endReq - c->pElt < FontShiftSize)
1231
fid = ((Font)*(c->pElt+4)) /* big-endian */
1232
| ((Font)*(c->pElt+3)) << 8
1233
| ((Font)*(c->pElt+2)) << 16
1234
| ((Font)*(c->pElt+1)) << 24;
1235
pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT,
1236
SecurityReadAccess);
1239
client->errorValue = fid;
1241
/* restore pFont and fid for step 4 (described below) */
1245
/* If we're in START_SLEEP mode, the following step
1246
shortens the request... in the unlikely event that
1247
the fid somehow becomes valid before we come through
1248
again to actually execute the polytext, which would
1249
then mess up our refcounting scheme badly. */
1251
c->endReq = c->pElt;
1256
/* Step 3 (described below) on our new font */
1257
if (client_state == START_SLEEP)
1261
if (pFont != c->pGC->font && c->pDraw)
1263
ChangeGC( c->pGC, GCFont, &fid);
1264
ValidateGC(c->pDraw, c->pGC);
1265
if (c->reqType == X_PolyText8)
1266
c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8;
1268
c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16;
1271
/* Undo the refcnt++ we performed when going to sleep */
1272
if (client_state == SLEEPING)
1273
(void)CloseFont(c->pGC->font, (Font)0);
1275
c->pElt += FontShiftSize;
1277
else /* print a string */
1279
unsigned char *pNextElt;
1280
pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize;
1281
if ( pNextElt > c->endReq)
1286
if (client_state == START_SLEEP)
1293
lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize,
1294
c->pElt + TextEltHeader);
1296
else lgerr = Successful;
1298
if (lgerr == Suspended)
1303
PTclosurePtr new_closure;
1305
/* We're putting the client to sleep. We need to do a few things
1306
to ensure successful and atomic-appearing execution of the
1307
remainder of the request. First, copy the remainder of the
1308
request into a safe malloc'd area. Second, create a scratch GC
1309
to use for the remainder of the request. Third, mark all fonts
1310
referenced in the remainder of the request to prevent their
1311
deallocation. Fourth, make the original GC look like the
1312
request has completed... set its font to the final font value
1313
from this request. These GC manipulations are for the unlikely
1314
(but possible) event that some other client is using the GC.
1315
Steps 3 and 4 are performed by running this procedure through
1316
the remainder of the request in a special no-render mode
1317
indicated by client_state = START_SLEEP. */
1320
/* Allocate a malloc'd closure structure to replace
1321
the local one we were passed */
1322
new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec));
1331
len = c->endReq - c->pElt;
1332
c->data = (unsigned char *)xalloc(len);
1339
memmove(c->data, c->pElt, len);
1341
c->endReq = c->pElt + len;
1345
pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
1353
if ((err = CopyGC(c->pGC, pGC, GCFunction |
1354
GCPlaneMask | GCForeground |
1355
GCBackground | GCFillStyle |
1356
GCTile | GCStipple |
1358
GCTileStipYOrigin | GCFont |
1359
GCSubwindowMode | GCClipXOrigin |
1360
GCClipYOrigin | GCClipMask)) !=
1371
ValidateGC(c->pDraw, c->pGC);
1375
(ClientSleepProcPtr)doPolyText,
1378
/* Set up to perform steps 3 and 4 */
1379
client_state = START_SLEEP;
1380
continue; /* on to steps 3 and 4 */
1384
else if (lgerr != Successful)
1386
err = FontToXError(lgerr);
1391
c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */
1392
c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg,
1393
*c->pElt, c->pElt + TextEltHeader);
1401
if (client_state == START_SLEEP)
1404
if (pFont != origGC->font)
1406
ChangeGC(origGC, GCFont, &fid);
1407
ValidateGC(c->pDraw, origGC);
1410
/* restore pElt pointer for execution of remainder of the request */
1415
if (c->err != Success) err = c->err;
1416
if (err != Success && c->client != serverClient) {
1418
if (noPanoramiXExtension || !c->pGC->pScreen->myNum)
1420
SendErrorToClient(c->client, c->reqType, 0, 0, err);
1424
ClientWakeup(c->client);
1425
ChangeGC(c->pGC, clearGCmask, clearGC);
1427
/* Unreference the font from the scratch GC */
1428
CloseFont(c->pGC->font, (Font)0);
1429
c->pGC->font = NullFont;
1431
FreeScratchGC(c->pGC);
1439
PolyText(client, pDraw, pGC, pElt, endReq, xorg, yorg, reqType, did)
1443
unsigned char *pElt;
1444
unsigned char *endReq;
1450
PTclosureRec local_closure;
1452
local_closure.pElt = pElt;
1453
local_closure.endReq = endReq;
1454
local_closure.client = client;
1455
local_closure.pDraw = pDraw;
1456
local_closure.xorg = xorg;
1457
local_closure.yorg = yorg;
1458
if ((local_closure.reqType = reqType) == X_PolyText8)
1460
local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8;
1461
local_closure.itemSize = 1;
1465
local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16;
1466
local_closure.itemSize = 2;
1468
local_closure.pGC = pGC;
1469
local_closure.did = did;
1470
local_closure.err = Success;
1471
local_closure.slept = FALSE;
1473
(void) doPolyText(client, &local_closure);
1478
#undef TextEltHeader
1479
#undef FontShiftSize
1482
doImageText(client, c)
1484
register ITclosurePtr c;
1486
int err = Success, lgerr; /* err is in X error, not font error, space */
1487
FontPathElementPtr fpe;
1489
if (client->clientGone)
1491
fpe = c->pGC->font->fpe;
1492
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1497
/* Make sure our drawable hasn't disappeared while we slept. */
1500
c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did,
1501
RC_DRAWABLE, SecurityWriteAccess))
1503
/* Our drawable has disappeared. Treat like client died... ask
1504
the FPE code to clean up after client. */
1505
fpe = c->pGC->font->fpe;
1506
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1511
lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data);
1512
if (lgerr == Suspended)
1516
unsigned char *data;
1517
ITclosurePtr new_closure;
1519
/* We're putting the client to sleep. We need to
1520
save some state. Similar problem to that handled
1521
in doPolyText, but much simpler because the
1522
request structure is much simpler. */
1524
new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec));
1533
data = (unsigned char *)xalloc(c->nChars * c->itemSize);
1540
memmove(data, c->data, c->nChars * c->itemSize);
1543
pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
1551
if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
1552
GCForeground | GCBackground | GCFillStyle |
1553
GCTile | GCStipple | GCTileStipXOrigin |
1554
GCTileStipYOrigin | GCFont |
1555
GCSubwindowMode | GCClipXOrigin |
1556
GCClipYOrigin | GCClipMask)) != Success)
1565
ValidateGC(c->pDraw, c->pGC);
1568
ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c);
1572
else if (lgerr != Successful)
1574
err = FontToXError(lgerr);
1579
(* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg,
1580
c->nChars, c->data);
1585
if (err != Success && c->client != serverClient) {
1586
SendErrorToClient(c->client, c->reqType, 0, 0, err);
1590
ClientWakeup(c->client);
1591
ChangeGC(c->pGC, clearGCmask, clearGC);
1593
/* Unreference the font from the scratch GC */
1594
CloseFont(c->pGC->font, (Font)0);
1595
c->pGC->font = NullFont;
1597
FreeScratchGC(c->pGC);
1605
ImageText(client, pDraw, pGC, nChars, data, xorg, yorg, reqType, did)
1610
unsigned char *data;
1616
ITclosureRec local_closure;
1618
local_closure.client = client;
1619
local_closure.pDraw = pDraw;
1620
local_closure.pGC = pGC;
1621
local_closure.nChars = nChars;
1622
local_closure.data = data;
1623
local_closure.xorg = xorg;
1624
local_closure.yorg = yorg;
1625
if ((local_closure.reqType = reqType) == X_ImageText8)
1627
local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8;
1628
local_closure.itemSize = 1;
1632
local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16;
1633
local_closure.itemSize = 2;
1635
local_closure.did = did;
1636
local_closure.slept = FALSE;
1638
(void) doImageText(client, &local_closure);
1643
/* does the necessary magic to figure out the fpe type */
1645
#if NeedFunctionPrototypes
1646
DetermineFPEType(char *pathname)
1648
DetermineFPEType(pathname)
1654
for (i = 0; i < num_fpe_types; i++) {
1655
if ((*fpe_functions[i].name_check) (pathname))
1663
#if NeedFunctionPrototypes
1664
FreeFontPath(FontPathElementPtr *list, int n, Bool force)
1666
FreeFontPath(list, n, force)
1667
FontPathElementPtr *list;
1674
for (i = 0; i < n; i++) {
1676
/* Sanity check that all refcounts will be 0 by the time
1677
we get to the end of the list. */
1678
int found = 1; /* the first reference is us */
1680
for (j = i+1; j < n; j++) {
1681
if (list[j] == list[i])
1684
if (list[i]->refcount != found) {
1685
ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n",
1686
list[i]->name_length, list[i]->name,
1687
list[i]->refcount, found);
1688
list[i]->refcount = found; /* ensure it will get freed */
1693
xfree((char *) list);
1696
static FontPathElementPtr
1697
#if NeedFunctionPrototypes
1698
find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len)
1700
find_existing_fpe(list, num, name, len)
1701
FontPathElementPtr *list;
1703
unsigned char *name;
1707
FontPathElementPtr fpe;
1710
for (i = 0; i < num; i++) {
1712
if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0)
1715
return (FontPathElementPtr) 0;
1720
#if NeedFunctionPrototypes
1721
SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
1723
SetFontPathElements(npaths, paths, bad, persist)
1725
unsigned char *paths;
1731
int valid_paths = 0;
1733
unsigned char *cp = paths;
1734
FontPathElementPtr fpe = NULL, *fplist;
1736
fplist = (FontPathElementPtr *)
1737
xalloc(sizeof(FontPathElementPtr) * npaths);
1742
for (i = 0; i < num_fpe_types; i++) {
1743
if (fpe_functions[i].set_path_hook)
1744
(*fpe_functions[i].set_path_hook) ();
1746
for (i = 0; i < npaths; i++)
1748
len = (unsigned int) (*cp++);
1753
ErrorF ("Removing empty element from the valid list of fontpaths\n");
1758
/* if it's already in our active list, just reset it */
1760
* note that this can miss FPE's in limbo -- may be worth catching
1761
* them, though it'd muck up refcounting
1763
fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len);
1766
err = (*fpe_functions[fpe->type].reset_fpe) (fpe);
1767
if (err == Successful)
1769
UseFPE(fpe);/* since it'll be decref'd later when freed
1770
* from the old list */
1775
/* if error or can't do it, act like it's a new one */
1778
fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec));
1784
fpe->name = (char *) xalloc(len + 1);
1793
strncpy(fpe->name, (char *) cp, (int) len);
1794
fpe->name[len] = '\0';
1795
fpe->name_length = len;
1796
fpe->type = DetermineFPEType(fpe->name);
1797
if (fpe->type == -1)
1800
err = (*fpe_functions[fpe->type].init_fpe) (fpe);
1801
if (err != Successful)
1805
ErrorF("Could not init font path element %s, removing from list!\n",
1813
if (err != Successful)
1820
fplist[valid_paths++] = fpe;
1825
FreeFontPath(font_path_elements, num_fpes, FALSE);
1826
font_path_elements = fplist;
1828
EmptyFontPatternCache(patternCache);
1829
num_fpes = valid_paths;
1834
while (--valid_paths >= 0)
1835
FreeFPE(fplist[valid_paths]);
1837
return FontToXError(err);
1840
/* XXX -- do we need to pass error down to each renderer? */
1842
SetFontPath(client, npaths, paths, error)
1845
unsigned char *paths;
1851
if (SetDefaultFontPath(defaultFontPath) != Success)
1854
err = SetFontPathElements(npaths, paths, error, FALSE);
1860
SetDefaultFontPath(path)
1873
/* get enough for string, plus values -- use up commas */
1874
len = strlen(path) + 1;
1875
nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len);
1878
pp = (unsigned char *) path;
1882
*nump = (unsigned char) size;
1892
*nump = (unsigned char) size;
1894
err = SetFontPathElements(num, newpath, &bad, TRUE);
1896
DEALLOCATE_LOCAL(newpath);
1902
GetFontPath(count, length)
1909
FontPathElementPtr fpe;
1912
for (i = 0; i < num_fpes; i++) {
1913
fpe = font_path_elements[i];
1914
len += fpe->name_length + 1;
1916
font_path_string = (unsigned char *) xrealloc(font_path_string, len);
1917
if (!font_path_string)
1920
c = font_path_string;
1922
for (i = 0; i < num_fpes; i++) {
1923
fpe = font_path_elements[i];
1924
*c = fpe->name_length;
1926
memmove(c, fpe->name, fpe->name_length);
1927
c += fpe->name_length;
1930
return font_path_string;
1934
LoadGlyphs(client, pfont, nchars, item_size, data)
1939
unsigned char *data;
1941
if (fpe_functions[pfont->fpe->type].load_glyphs)
1942
return (*fpe_functions[pfont->fpe->type].load_glyphs)
1943
(client, pfont, 0, nchars, item_size, data);
1949
DeleteClientFontStuff(client)
1953
FontPathElementPtr fpe;
1955
for (i = 0; i < num_fpes; i++)
1957
fpe = font_path_elements[i];
1958
if (fpe_functions[fpe->type].client_died)
1959
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1966
patternCache = MakeFontPatternCache();
1968
#ifndef KDRIVESERVER
1969
if (screenInfo.numScreens > screenInfo.numVideoScreens) {
1970
PrinterFontRegisterFpeFunctions();
1971
FontFileCheckRegisterFpeFunctions();
1972
check_fs_register_fpe_functions();
1977
BuiltinRegisterFpeFunctions();
1979
FontFileRegisterFpeFunctions();
1980
#ifndef NOFONTSERVERACCESS
1981
fs_register_fpe_functions();
1987
GetDefaultPointSize ()
1994
GetClientResolutions (num)
1997
if (requestingClient && requestingClient->fontResFunc != NULL &&
1998
!requestingClient->clientGone)
2000
return (*requestingClient->fontResFunc)(requestingClient, num);
2003
static struct _FontResolution res;
2006
pScreen = screenInfo.screens[0];
2007
res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth;
2009
* XXX - we'll want this as long as bitmap instances are prevalent
2010
so that we can match them from scalable fonts
2012
if (res.x_resolution < 88)
2013
res.x_resolution = 75;
2015
res.x_resolution = 100;
2016
res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight;
2017
if (res.y_resolution < 88)
2018
res.y_resolution = 75;
2020
res.y_resolution = 100;
2021
res.point_size = 120;
2028
* returns the type index of the new fpe
2030
* should be called (only once!) by each type of fpe when initialized
2034
RegisterFPEFunctions(NameCheckFunc name_func,
2035
InitFpeFunc init_func,
2036
FreeFpeFunc free_func,
2037
ResetFpeFunc reset_func,
2038
OpenFontFunc open_func,
2039
CloseFontFunc close_func,
2040
ListFontsFunc list_func,
2041
StartLfwiFunc start_lfwi_func,
2042
NextLfwiFunc next_lfwi_func,
2043
WakeupFpeFunc wakeup_func,
2044
ClientDiedFunc client_died,
2045
LoadGlyphsFunc load_glyphs,
2046
StartLaFunc start_list_alias_func,
2047
NextLaFunc next_list_alias_func,
2048
SetPathFunc set_path_func)
2053
new = (FPEFunctions *) xrealloc(fpe_functions,
2054
(num_fpe_types + 1) * sizeof(FPEFunctions));
2057
fpe_functions = new;
2059
fpe_functions[num_fpe_types].name_check = name_func;
2060
fpe_functions[num_fpe_types].open_font = open_func;
2061
fpe_functions[num_fpe_types].close_font = close_func;
2062
fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func;
2063
fpe_functions[num_fpe_types].list_fonts = list_func;
2064
fpe_functions[num_fpe_types].start_list_fonts_with_info =
2066
fpe_functions[num_fpe_types].list_next_font_with_info =
2068
fpe_functions[num_fpe_types].init_fpe = init_func;
2069
fpe_functions[num_fpe_types].free_fpe = free_func;
2070
fpe_functions[num_fpe_types].reset_fpe = reset_func;
2071
fpe_functions[num_fpe_types].client_died = client_died;
2072
fpe_functions[num_fpe_types].load_glyphs = load_glyphs;
2073
fpe_functions[num_fpe_types].start_list_fonts_and_aliases =
2074
start_list_alias_func;
2075
fpe_functions[num_fpe_types].list_next_font_or_alias =
2076
next_list_alias_func;
2077
fpe_functions[num_fpe_types].set_path_hook = set_path_func;
2079
return num_fpe_types++;
2086
FreeFontPatternCache(patternCache);
2089
FreeFontPath(font_path_elements, num_fpes, TRUE);
2090
font_path_elements = 0;
2092
xfree(fpe_functions);
2094
fpe_functions = (FPEFunctions *) 0;
2097
/* convenience functions for FS interface */
2103
return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE,
2104
SecurityUnknownAccess);
2108
GetNewFontClientID()
2110
return FakeClientID(0);
2114
StoreFontClientFont(pfont, id)
2118
return AddResource(id, RT_NONE, (pointer) pfont);
2122
DeleteFontClientID(id)
2125
FreeResource(id, RT_NONE);
2129
client_auth_generation(client)
2135
static int fs_handlers_installed = 0;
2136
static unsigned int last_server_gen;
2139
init_fs_handlers(fpe, block_handler)
2140
FontPathElementPtr fpe;
2141
BlockHandlerProcPtr block_handler;
2143
/* if server has reset, make sure the b&w handlers are reinstalled */
2144
if (last_server_gen < serverGeneration) {
2145
last_server_gen = serverGeneration;
2146
fs_handlers_installed = 0;
2148
if (fs_handlers_installed == 0) {
2151
fprintf(stderr, "adding FS b & w handlers\n");
2154
if (!RegisterBlockAndWakeupHandlers(block_handler,
2155
FontWakeup, (pointer) 0))
2157
fs_handlers_installed++;
2159
QueueFontWakeup(fpe);
2164
remove_fs_handlers(fpe, block_handler, all)
2165
FontPathElementPtr fpe;
2166
BlockHandlerProcPtr block_handler;
2170
/* remove the handlers if no one else is using them */
2171
if (--fs_handlers_installed == 0) {
2174
fprintf(stderr, "removing FS b & w handlers\n");
2177
RemoveBlockAndWakeupHandlers(block_handler, FontWakeup,
2181
RemoveFontWakeup(fpe);
2185
#define GLWIDTHBYTESPADDED(bits,nbytes) \
2186
((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \
2187
:(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \
2188
:(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \
2189
:(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \
2192
#define GLYPH_SIZE(ch, nbytes) \
2193
GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \
2194
(ch)->metrics.leftSideBearing, (nbytes))
2195
dump_char_ascii(cip)
2202
static unsigned maskTab[] = {
2203
(1 << 7), (1 << 6), (1 << 5), (1 << 4),
2204
(1 << 3), (1 << 2), (1 << 1), (1 << 0),
2207
bpr = GLYPH_SIZE(cip, 4);
2208
for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) {
2209
pointer row = (pointer) cip->bits + r * bpr;
2212
for (l = 0; l <= (cip->metrics.rightSideBearing -
2213
cip->metrics.leftSideBearing); l++) {
2214
if (maskTab[l & 7] & row[l >> 3])