xf86bigfont.c revision 9ace9065
1/* 2 * BIGFONT extension for sharing font metrics between clients (if possible) 3 * and for transmitting font metrics to clients in a compressed form. 4 * 5 * Copyright (c) 1999-2000 Bruno Haible 6 * Copyright (c) 1999-2000 The XFree86 Project, Inc. 7 */ 8 9/* THIS IS NOT AN X CONSORTIUM STANDARD */ 10 11/* 12 * Big fonts suffer from the following: All clients that have opened a 13 * font can access the complete glyph metrics array (the XFontStruct member 14 * `per_char') directly, without going through a macro. Moreover these 15 * glyph metrics are ink metrics, i.e. are not redundant even for a 16 * fixed-width font. For a Unicode font, the size of this array is 768 KB. 17 * 18 * Problems: 1. It eats a lot of memory in each client. 2. All this glyph 19 * metrics data is piped through the socket when the font is opened. 20 * 21 * This extension addresses these two problems for local clients, by using 22 * shared memory. It also addresses the second problem for non-local clients, 23 * by compressing the data before transmit by a factor of nearly 6. 24 * 25 * If you use this extension, your OS ought to nicely support shared memory. 26 * This means: Shared memory should be swappable to the swap, and the limits 27 * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB, 28 * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls 29 * on segments that have already been marked "removed", because it permits 30 * these segments to be cleaned up by the OS if the X server is killed with 31 * signal SIGKILL. 32 * 33 * This extension is transparently exploited by Xlib (functions XQueryFont, 34 * XLoadQueryFont). 35 */ 36 37#ifdef HAVE_DIX_CONFIG_H 38#include <dix-config.h> 39#endif 40 41#include <sys/types.h> 42#ifdef HAS_SHM 43#if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2) 44/* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */ 45/* Linux libc4 and libc5 only (because glibc doesn't include kernel headers): 46 Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define 47 PAGE_SIZE. It is defined in <asm/page.h>. */ 48#include <asm/page.h> 49#endif 50#ifdef SVR4 51#include <sys/sysmacros.h> 52#endif 53#if defined(__CYGWIN__) 54#include <sys/param.h> 55#include <sys/sysmacros.h> 56#endif 57#include <sys/ipc.h> 58#include <sys/shm.h> 59#include <sys/stat.h> 60#include <stdlib.h> 61#include <unistd.h> 62#include <time.h> 63#include <errno.h> 64#endif 65 66#include <X11/X.h> 67#include <X11/Xproto.h> 68#include "misc.h" 69#include "os.h" 70#include "dixstruct.h" 71#include "gcstruct.h" 72#include "dixfontstr.h" 73#include "extnsionst.h" 74#include "protocol-versions.h" 75 76#include <X11/extensions/xf86bigfproto.h> 77#include "xf86bigfontsrv.h" 78 79static void XF86BigfontResetProc( 80 ExtensionEntry * /* extEntry */ 81 ); 82 83 84#ifdef HAS_SHM 85 86/* A random signature, transmitted to the clients so they can verify that the 87 shared memory segment they are attaching to was really established by the 88 X server they are talking to. */ 89static CARD32 signature; 90 91/* Index for additional information stored in a FontRec's devPrivates array. */ 92static int FontShmdescIndex; 93 94static unsigned int pagesize; 95 96static Bool badSysCall = FALSE; 97 98#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__) 99 100#include <sys/signal.h> 101 102static void 103SigSysHandler( 104 int signo) 105{ 106 badSysCall = TRUE; 107} 108 109static Bool 110CheckForShmSyscall(void) 111{ 112 void (*oldHandler)(int); 113 int shmid = -1; 114 115 /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ 116 oldHandler = signal(SIGSYS, SigSysHandler); 117 118 badSysCall = FALSE; 119 shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); 120 if (shmid != -1) 121 { 122 /* Successful allocation - clean up */ 123 shmctl(shmid, IPC_RMID, NULL); 124 } 125 else 126 { 127 /* Allocation failed */ 128 badSysCall = TRUE; 129 } 130 signal(SIGSYS, oldHandler); 131 return !badSysCall; 132} 133 134#define MUST_CHECK_FOR_SHM_SYSCALL 135 136#endif 137 138#endif 139 140/* ========== Management of shared memory segments ========== */ 141 142#ifdef HAS_SHM 143 144#ifdef __linux__ 145/* On Linux, shared memory marked as "removed" can still be attached. 146 Nice feature, because the kernel will automatically free the associated 147 storage when the server and all clients are gone. */ 148#define EARLY_REMOVE 149#endif 150 151typedef struct _ShmDesc { 152 struct _ShmDesc *next; 153 struct _ShmDesc **prev; 154 int shmid; 155 char *attach_addr; 156} ShmDescRec, *ShmDescPtr; 157 158static ShmDescPtr ShmList = (ShmDescPtr) NULL; 159 160static ShmDescPtr 161shmalloc( 162 unsigned int size) 163{ 164 ShmDescPtr pDesc; 165 int shmid; 166 char *addr; 167 168#ifdef MUST_CHECK_FOR_SHM_SYSCALL 169 if (pagesize == 0) 170 return (ShmDescPtr) NULL; 171#endif 172 173 /* On some older Linux systems, the number of shared memory segments 174 system-wide is 127. In Linux 2.4, it is 4095. 175 Therefore there is a tradeoff to be made between allocating a 176 shared memory segment on one hand, and allocating memory and piping 177 the glyph metrics on the other hand. If the glyph metrics size is 178 small, we prefer the traditional way. */ 179 if (size < 3500) 180 return (ShmDescPtr) NULL; 181 182 pDesc = malloc(sizeof(ShmDescRec)); 183 if (!pDesc) 184 return (ShmDescPtr) NULL; 185 186 size = (size + pagesize-1) & -pagesize; 187 shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); 188 if (shmid == -1) { 189 ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n", 190 size, strerror(errno)); 191 free(pDesc); 192 return (ShmDescPtr) NULL; 193 } 194 195 if ((addr = shmat(shmid, 0, 0)) == (char *)-1) { 196 ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n", 197 size, strerror(errno)); 198 shmctl(shmid, IPC_RMID, (void *) 0); 199 free(pDesc); 200 return (ShmDescPtr) NULL; 201 } 202 203#ifdef EARLY_REMOVE 204 shmctl(shmid, IPC_RMID, (void *) 0); 205#endif 206 207 pDesc->shmid = shmid; 208 pDesc->attach_addr = addr; 209 if (ShmList) ShmList->prev = &pDesc->next; 210 pDesc->next = ShmList; 211 pDesc->prev = &ShmList; 212 ShmList = pDesc; 213 214 return pDesc; 215} 216 217static void 218shmdealloc( 219 ShmDescPtr pDesc) 220{ 221#ifndef EARLY_REMOVE 222 shmctl(pDesc->shmid, IPC_RMID, (void *) 0); 223#endif 224 shmdt(pDesc->attach_addr); 225 226 if (pDesc->next) pDesc->next->prev = pDesc->prev; 227 *pDesc->prev = pDesc->next; 228 free(pDesc); 229} 230 231#endif 232 233/* Called when a font is closed. */ 234void 235XF86BigfontFreeFontShm( 236 FontPtr pFont) 237{ 238#ifdef HAS_SHM 239 ShmDescPtr pDesc; 240 241 /* If during shutdown of the server, XF86BigfontCleanup() has already 242 * called shmdealloc() for all segments, we don't need to do it here. 243 */ 244 if (!ShmList) 245 return; 246 247 pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex); 248 if (pDesc) 249 shmdealloc(pDesc); 250#endif 251} 252 253/* Called upon fatal signal. */ 254void 255XF86BigfontCleanup(void) 256{ 257#ifdef HAS_SHM 258 while (ShmList) 259 shmdealloc(ShmList); 260#endif 261} 262 263/* Called when a server generation dies. */ 264static void 265XF86BigfontResetProc( 266 ExtensionEntry* extEntry) 267{ 268 /* This function is normally called from CloseDownExtensions(), called 269 * from main(). It will be followed by a call to FreeAllResources(), 270 * which will call XF86BigfontFreeFontShm() for each font. Thus it 271 * appears that we do not need to do anything in this function. -- 272 * But I prefer to write robust code, and not keep shared memory lying 273 * around when it's not needed any more. (Someone might close down the 274 * extension without calling FreeAllResources()...) 275 */ 276 XF86BigfontCleanup(); 277} 278 279 280/* ========== Handling of extension specific requests ========== */ 281 282static int 283ProcXF86BigfontQueryVersion( 284 ClientPtr client) 285{ 286 xXF86BigfontQueryVersionReply reply; 287 288 REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq); 289 reply.type = X_Reply; 290 reply.length = 0; 291 reply.sequenceNumber = client->sequence; 292 reply.majorVersion = SERVER_XF86BIGFONT_MAJOR_VERSION; 293 reply.minorVersion = SERVER_XF86BIGFONT_MINOR_VERSION; 294 reply.uid = geteuid(); 295 reply.gid = getegid(); 296#ifdef HAS_SHM 297 reply.signature = signature; 298#else 299 reply.signature = 0; /* This is redundant. Avoids uninitialized memory. */ 300#endif 301 reply.capabilities = 302#ifdef HAS_SHM 303 (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0) 304#else 305 0 306#endif 307 ; /* may add more bits here in future versions */ 308 if (client->swapped) { 309 char tmp; 310 swaps(&reply.sequenceNumber, tmp); 311 swapl(&reply.length, tmp); 312 swaps(&reply.majorVersion, tmp); 313 swaps(&reply.minorVersion, tmp); 314 swapl(&reply.uid, tmp); 315 swapl(&reply.gid, tmp); 316 swapl(&reply.signature, tmp); 317 } 318 WriteToClient(client, 319 sizeof(xXF86BigfontQueryVersionReply), (char *)&reply); 320 return Success; 321} 322 323static void 324swapCharInfo( 325 xCharInfo *pCI) 326{ 327 char tmp; 328 329 swaps(&pCI->leftSideBearing, tmp); 330 swaps(&pCI->rightSideBearing, tmp); 331 swaps(&pCI->characterWidth, tmp); 332 swaps(&pCI->ascent, tmp); 333 swaps(&pCI->descent, tmp); 334 swaps(&pCI->attributes, tmp); 335} 336 337/* static CARD32 hashCI (xCharInfo *p); */ 338#define hashCI(p) \ 339 (CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \ 340 (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \ 341 (p->characterWidth << 16) + \ 342 (p->ascent << 11) + (p->descent << 6)) ^ p->attributes) 343 344static int 345ProcXF86BigfontQueryFont( 346 ClientPtr client) 347{ 348 FontPtr pFont; 349 REQUEST(xXF86BigfontQueryFontReq); 350 CARD32 stuff_flags; 351 xCharInfo* pmax; 352 xCharInfo* pmin; 353 int nCharInfos; 354 int shmid; 355#ifdef HAS_SHM 356 ShmDescPtr pDesc = NULL; 357#else 358#define pDesc 0 359#endif 360 xCharInfo* pCI; 361 CARD16* pIndex2UniqIndex; 362 CARD16* pUniqIndex2Index; 363 CARD32 nUniqCharInfos; 364 365#if 0 366 REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq); 367#else 368 switch (client->req_len) { 369 case 2: /* client with version 1.0 libX11 */ 370 stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0); 371 break; 372 case 3: /* client with version 1.1 libX11 */ 373 stuff_flags = stuff->flags; 374 break; 375 default: 376 return BadLength; 377 } 378#endif 379 if (dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess) != Success) 380 return BadFont; /* procotol spec says only error is BadFont */ 381 382 pmax = FONTINKMAX(pFont); 383 pmin = FONTINKMIN(pFont); 384 nCharInfos = 385 (pmax->rightSideBearing == pmin->rightSideBearing 386 && pmax->leftSideBearing == pmin->leftSideBearing 387 && pmax->descent == pmin->descent 388 && pmax->ascent == pmin->ascent 389 && pmax->characterWidth == pmin->characterWidth) 390 ? 0 : N2dChars(pFont); 391 shmid = -1; 392 pCI = NULL; 393 pIndex2UniqIndex = NULL; 394 pUniqIndex2Index = NULL; 395 nUniqCharInfos = 0; 396 397 if (nCharInfos > 0) { 398#ifdef HAS_SHM 399 if (!badSysCall) 400 pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex); 401 if (pDesc) { 402 pCI = (xCharInfo *) pDesc->attach_addr; 403 if (stuff_flags & XF86Bigfont_FLAGS_Shm) 404 shmid = pDesc->shmid; 405 } else { 406 if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall) 407 pDesc = shmalloc(nCharInfos * sizeof(xCharInfo) 408 + sizeof(CARD32)); 409 if (pDesc) { 410 pCI = (xCharInfo *) pDesc->attach_addr; 411 shmid = pDesc->shmid; 412 } else { 413#endif 414 pCI = malloc(nCharInfos * sizeof(xCharInfo)); 415 if (!pCI) 416 return BadAlloc; 417#ifdef HAS_SHM 418 } 419#endif 420 /* Fill nCharInfos starting at pCI. */ 421 { 422 xCharInfo* prCI = pCI; 423 int ninfos = 0; 424 int ncols = pFont->info.lastCol - pFont->info.firstCol + 1; 425 int row; 426 for (row = pFont->info.firstRow; 427 row <= pFont->info.lastRow && ninfos < nCharInfos; 428 row++) { 429 unsigned char chars[512]; 430 xCharInfo* tmpCharInfos[256]; 431 unsigned long count; 432 int col; 433 unsigned long i; 434 i = 0; 435 for (col = pFont->info.firstCol; 436 col <= pFont->info.lastCol; 437 col++) { 438 chars[i++] = row; 439 chars[i++] = col; 440 } 441 (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit, 442 &count, tmpCharInfos); 443 for (i = 0; i < count && ninfos < nCharInfos; i++) { 444 *prCI++ = *tmpCharInfos[i]; 445 ninfos++; 446 } 447 } 448 } 449#ifdef HAS_SHM 450 if (pDesc && !badSysCall) { 451 *(CARD32 *)(pCI + nCharInfos) = signature; 452 if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) { 453 shmdealloc(pDesc); 454 return BadAlloc; 455 } 456 } 457 } 458#endif 459 if (shmid == -1) { 460 /* Cannot use shared memory, so remove-duplicates the xCharInfos 461 using a temporary hash table. */ 462 /* Note that CARD16 is suitable as index type, because 463 nCharInfos <= 0x10000. */ 464 CARD32 hashModulus; 465 CARD16* pHash2UniqIndex; 466 CARD16* pUniqIndex2NextUniqIndex; 467 CARD32 NextIndex; 468 CARD32 NextUniqIndex; 469 CARD16* tmp; 470 CARD32 i, j; 471 472 hashModulus = 67; 473 if (hashModulus > nCharInfos+1) 474 hashModulus = nCharInfos+1; 475 476 tmp = malloc((4*nCharInfos+1) * sizeof(CARD16)); 477 if (!tmp) { 478 if (!pDesc) free(pCI); 479 return BadAlloc; 480 } 481 pIndex2UniqIndex = tmp; 482 /* nCharInfos elements */ 483 pUniqIndex2Index = tmp + nCharInfos; 484 /* max. nCharInfos elements */ 485 pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos; 486 /* max. nCharInfos elements */ 487 pHash2UniqIndex = tmp + 3*nCharInfos; 488 /* hashModulus (<= nCharInfos+1) elements */ 489 490 /* Note that we can use 0xffff as end-of-list indicator, because 491 even if nCharInfos = 0x10000, 0xffff can not occur as valid 492 entry before the last element has been inserted. And once the 493 last element has been inserted, we don't need the hash table 494 any more. */ 495 for (j = 0; j < hashModulus; j++) 496 pHash2UniqIndex[j] = (CARD16)(-1); 497 498 NextUniqIndex = 0; 499 for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) { 500 xCharInfo* p = &pCI[NextIndex]; 501 CARD32 hashCode = hashCI(p) % hashModulus; 502 for (i = pHash2UniqIndex[hashCode]; 503 i != (CARD16)(-1); 504 i = pUniqIndex2NextUniqIndex[i]) { 505 j = pUniqIndex2Index[i]; 506 if (pCI[j].leftSideBearing == p->leftSideBearing 507 && pCI[j].rightSideBearing == p->rightSideBearing 508 && pCI[j].characterWidth == p->characterWidth 509 && pCI[j].ascent == p->ascent 510 && pCI[j].descent == p->descent 511 && pCI[j].attributes == p->attributes) 512 break; 513 } 514 if (i != (CARD16)(-1)) { 515 /* Found *p at Index j, UniqIndex i */ 516 pIndex2UniqIndex[NextIndex] = i; 517 } else { 518 /* Allocate a new entry in the Uniq table */ 519 if (hashModulus <= 2*NextUniqIndex 520 && hashModulus < nCharInfos+1) { 521 /* Time to increate hash table size */ 522 hashModulus = 2*hashModulus+1; 523 if (hashModulus > nCharInfos+1) 524 hashModulus = nCharInfos+1; 525 for (j = 0; j < hashModulus; j++) 526 pHash2UniqIndex[j] = (CARD16)(-1); 527 for (i = 0; i < NextUniqIndex; i++) 528 pUniqIndex2NextUniqIndex[i] = (CARD16)(-1); 529 for (i = 0; i < NextUniqIndex; i++) { 530 j = pUniqIndex2Index[i]; 531 p = &pCI[j]; 532 hashCode = hashCI(p) % hashModulus; 533 pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode]; 534 pHash2UniqIndex[hashCode] = i; 535 } 536 p = &pCI[NextIndex]; 537 hashCode = hashCI(p) % hashModulus; 538 } 539 i = NextUniqIndex++; 540 pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode]; 541 pHash2UniqIndex[hashCode] = i; 542 pUniqIndex2Index[i] = NextIndex; 543 pIndex2UniqIndex[NextIndex] = i; 544 } 545 } 546 nUniqCharInfos = NextUniqIndex; 547 /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */ 548 } 549 } 550 551 { 552 int nfontprops = pFont->info.nprops; 553 int rlength = 554 sizeof(xXF86BigfontQueryFontReply) 555 + nfontprops * sizeof(xFontProp) 556 + (nCharInfos > 0 && shmid == -1 557 ? nUniqCharInfos * sizeof(xCharInfo) 558 + (nCharInfos+1)/2 * 2 * sizeof(CARD16) 559 : 0); 560 xXF86BigfontQueryFontReply* reply = malloc(rlength); 561 char* p; 562 if (!reply) { 563 if (nCharInfos > 0) { 564 if (shmid == -1) free(pIndex2UniqIndex); 565 if (!pDesc) free(pCI); 566 } 567 return BadAlloc; 568 } 569 reply->type = X_Reply; 570 reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); 571 reply->sequenceNumber = client->sequence; 572 reply->minBounds = pFont->info.ink_minbounds; 573 reply->maxBounds = pFont->info.ink_maxbounds; 574 reply->minCharOrByte2 = pFont->info.firstCol; 575 reply->maxCharOrByte2 = pFont->info.lastCol; 576 reply->defaultChar = pFont->info.defaultCh; 577 reply->nFontProps = pFont->info.nprops; 578 reply->drawDirection = pFont->info.drawDirection; 579 reply->minByte1 = pFont->info.firstRow; 580 reply->maxByte1 = pFont->info.lastRow; 581 reply->allCharsExist = pFont->info.allExist; 582 reply->fontAscent = pFont->info.fontAscent; 583 reply->fontDescent = pFont->info.fontDescent; 584 reply->nCharInfos = nCharInfos; 585 reply->nUniqCharInfos = nUniqCharInfos; 586 reply->shmid = shmid; 587 reply->shmsegoffset = 0; 588 if (client->swapped) { 589 char tmp; 590 swaps(&reply->sequenceNumber, tmp); 591 swapl(&reply->length, tmp); 592 swapCharInfo(&reply->minBounds); 593 swapCharInfo(&reply->maxBounds); 594 swaps(&reply->minCharOrByte2, tmp); 595 swaps(&reply->maxCharOrByte2, tmp); 596 swaps(&reply->defaultChar, tmp); 597 swaps(&reply->nFontProps, tmp); 598 swaps(&reply->fontAscent, tmp); 599 swaps(&reply->fontDescent, tmp); 600 swapl(&reply->nCharInfos, tmp); 601 swapl(&reply->nUniqCharInfos, tmp); 602 swapl(&reply->shmid, tmp); 603 swapl(&reply->shmsegoffset, tmp); 604 } 605 p = (char*) &reply[1]; 606 { 607 FontPropPtr pFP; 608 xFontProp* prFP; 609 int i; 610 for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p; 611 i < nfontprops; 612 i++, pFP++, prFP++) { 613 prFP->name = pFP->name; 614 prFP->value = pFP->value; 615 if (client->swapped) { 616 char tmp; 617 swapl(&prFP->name, tmp); 618 swapl(&prFP->value, tmp); 619 } 620 } 621 p = (char*) prFP; 622 } 623 if (nCharInfos > 0 && shmid == -1) { 624 xCharInfo* pci; 625 CARD16* ps; 626 int i, j; 627 pci = (xCharInfo*) p; 628 for (i = 0; i < nUniqCharInfos; i++, pci++) { 629 *pci = pCI[pUniqIndex2Index[i]]; 630 if (client->swapped) 631 swapCharInfo(pci); 632 } 633 ps = (CARD16*) pci; 634 for (j = 0; j < nCharInfos; j++, ps++) { 635 *ps = pIndex2UniqIndex[j]; 636 if (client->swapped) { 637 char tmp; 638 swaps(ps, tmp); 639 } 640 } 641 } 642 WriteToClient(client, rlength, (char *)reply); 643 free(reply); 644 if (nCharInfos > 0) { 645 if (shmid == -1) free(pIndex2UniqIndex); 646 if (!pDesc) free(pCI); 647 } 648 return Success; 649 } 650} 651 652static int 653ProcXF86BigfontDispatch( 654 ClientPtr client) 655{ 656 REQUEST(xReq); 657 658 switch (stuff->data) { 659 case X_XF86BigfontQueryVersion: 660 return ProcXF86BigfontQueryVersion(client); 661 case X_XF86BigfontQueryFont: 662 return ProcXF86BigfontQueryFont(client); 663 default: 664 return BadRequest; 665 } 666} 667 668static int 669SProcXF86BigfontQueryVersion( 670 ClientPtr client) 671{ 672 REQUEST(xXF86BigfontQueryVersionReq); 673 char tmp; 674 675 swaps(&stuff->length, tmp); 676 return ProcXF86BigfontQueryVersion(client); 677} 678 679static int 680SProcXF86BigfontQueryFont( 681 ClientPtr client) 682{ 683 REQUEST(xXF86BigfontQueryFontReq); 684 char tmp; 685 686 swaps(&stuff->length, tmp); 687 REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq); 688 swapl(&stuff->id, tmp); 689 return ProcXF86BigfontQueryFont(client); 690} 691 692static int 693SProcXF86BigfontDispatch( 694 ClientPtr client) 695{ 696 REQUEST(xReq); 697 698 switch (stuff->data) { 699 case X_XF86BigfontQueryVersion: 700 return SProcXF86BigfontQueryVersion(client); 701 case X_XF86BigfontQueryFont: 702 return SProcXF86BigfontQueryFont(client); 703 default: 704 return BadRequest; 705 } 706} 707 708void 709XFree86BigfontExtensionInit(void) 710{ 711 if (AddExtension(XF86BIGFONTNAME, 712 XF86BigfontNumberEvents, 713 XF86BigfontNumberErrors, 714 ProcXF86BigfontDispatch, 715 SProcXF86BigfontDispatch, 716 XF86BigfontResetProc, 717 StandardMinorOpcode)) { 718#ifdef HAS_SHM 719#ifdef MUST_CHECK_FOR_SHM_SYSCALL 720 /* 721 * Note: Local-clients will not be optimized without shared memory 722 * support. Remote-client optimization does not depend on shared 723 * memory support. Thus, the extension is still registered even 724 * when shared memory support is not functional. 725 */ 726 if (!CheckForShmSyscall()) { 727 ErrorF(XF86BIGFONTNAME " extension local-client optimization disabled due to lack of shared memory support in the kernel\n"); 728 return; 729 } 730#endif 731 732 srand((unsigned int) time(NULL)); 733 signature = ((unsigned int) (65536.0/(RAND_MAX+1.0) * rand()) << 16) 734 + (unsigned int) (65536.0/(RAND_MAX+1.0) * rand()); 735 /* fprintf(stderr, "signature = 0x%08X\n", signature); */ 736 737 FontShmdescIndex = AllocateFontPrivateIndex(); 738 739#if !defined(CSRG_BASED) && !defined(__CYGWIN__) 740 pagesize = SHMLBA; 741#else 742# ifdef _SC_PAGESIZE 743 pagesize = sysconf(_SC_PAGESIZE); 744# else 745 pagesize = getpagesize(); 746# endif 747#endif 748#endif 749 } 750} 751