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