glyph.c revision 05b261ec
1/* 2 * 3 * Copyright © 2000 SuSE, Inc. 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of SuSE not be used in advertising or 10 * publicity pertaining to distribution of the software without specific, 11 * written prior permission. SuSE makes no representations about the 12 * suitability of this software for any purpose. It is provided "as is" 13 * without express or implied warranty. 14 * 15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Author: Keith Packard, SuSE, Inc. 23 */ 24 25#ifdef HAVE_DIX_CONFIG_H 26#include <dix-config.h> 27#endif 28 29#include "misc.h" 30#include "scrnintstr.h" 31#include "os.h" 32#include "regionstr.h" 33#include "validate.h" 34#include "windowstr.h" 35#include "input.h" 36#include "resource.h" 37#include "colormapst.h" 38#include "cursorstr.h" 39#include "dixstruct.h" 40#include "gcstruct.h" 41#include "servermd.h" 42#include "picturestr.h" 43#include "glyphstr.h" 44 45#if HAVE_STDINT_H 46#include <stdint.h> 47#elif !defined(UINT32_MAX) 48#define UINT32_MAX 0xffffffffU 49#endif 50 51/* 52 * From Knuth -- a good choice for hash/rehash values is p, p-2 where 53 * p and p-2 are both prime. These tables are sized to have an extra 10% 54 * free to avoid exponential performance degradation as the hash table fills 55 */ 56static GlyphHashSetRec glyphHashSets[] = { 57 { 32, 43, 41 }, 58 { 64, 73, 71 }, 59 { 128, 151, 149 }, 60 { 256, 283, 281 }, 61 { 512, 571, 569 }, 62 { 1024, 1153, 1151 }, 63 { 2048, 2269, 2267 }, 64 { 4096, 4519, 4517 }, 65 { 8192, 9013, 9011 }, 66 { 16384, 18043, 18041 }, 67 { 32768, 36109, 36107 }, 68 { 65536, 72091, 72089 }, 69 { 131072, 144409, 144407 }, 70 { 262144, 288361, 288359 }, 71 { 524288, 576883, 576881 }, 72 { 1048576, 1153459, 1153457 }, 73 { 2097152, 2307163, 2307161 }, 74 { 4194304, 4613893, 4613891 }, 75 { 8388608, 9227641, 9227639 }, 76 { 16777216, 18455029, 18455027 }, 77 { 33554432, 36911011, 36911009 }, 78 { 67108864, 73819861, 73819859 }, 79 { 134217728, 147639589, 147639587 }, 80 { 268435456, 295279081, 295279079 }, 81 { 536870912, 590559793, 590559791 } 82}; 83 84#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) 85 86static const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; 87 88static GlyphHashRec globalGlyphs[GlyphFormatNum]; 89 90static int globalTotalGlyphPrivateSize = 0; 91 92static int glyphPrivateCount = 0; 93 94void 95ResetGlyphPrivates (void) 96{ 97 glyphPrivateCount = 0; 98} 99 100int 101AllocateGlyphPrivateIndex (void) 102{ 103 return glyphPrivateCount++; 104} 105 106Bool 107AllocateGlyphPrivate (ScreenPtr pScreen, 108 int index2, 109 unsigned amount) 110{ 111 PictureScreenPtr ps; 112 unsigned oldamount; 113 114 ps = GetPictureScreenIfSet (pScreen); 115 if (!ps) 116 return FALSE; 117 118 /* Round up sizes for proper alignment */ 119 amount = ((amount + (sizeof (DevUnion) - 1)) / sizeof (DevUnion)) * 120 sizeof (DevUnion); 121 122 if (index2 >= ps->glyphPrivateLen) 123 { 124 unsigned *nsizes; 125 nsizes = (unsigned *) xrealloc (ps->glyphPrivateSizes, 126 (index2 + 1) * sizeof (unsigned)); 127 if (!nsizes) 128 return FALSE; 129 130 while (ps->glyphPrivateLen <= index2) 131 { 132 nsizes[ps->glyphPrivateLen++] = 0; 133 ps->totalGlyphPrivateSize += sizeof (DevUnion); 134 } 135 ps->glyphPrivateSizes = nsizes; 136 } 137 oldamount = ps->glyphPrivateSizes[index2]; 138 if (amount > oldamount) 139 { 140 ps->glyphPrivateSizes[index2] = amount; 141 ps->totalGlyphPrivateSize += (amount - oldamount); 142 } 143 ps->totalGlyphPrivateSize = BitmapBytePad (ps->totalGlyphPrivateSize * 8); 144 145 return TRUE; 146} 147 148static void 149SetGlyphScreenPrivateOffsets (void) 150{ 151 PictureScreenPtr ps; 152 int offset = 0; 153 int i; 154 155 for (i = 0; i < screenInfo.numScreens; i++) 156 { 157 ps = GetPictureScreenIfSet (screenInfo.screens[i]); 158 if (ps && ps->totalGlyphPrivateSize) 159 { 160 ps->glyphPrivateOffset = offset; 161 offset += ps->totalGlyphPrivateSize / sizeof (DevUnion); 162 } 163 } 164} 165 166static void 167SetGlyphPrivatePointers (GlyphPtr glyph) 168{ 169 PictureScreenPtr ps; 170 int i; 171 char *ptr; 172 DevUnion *ppriv; 173 unsigned *sizes; 174 unsigned size; 175 int len; 176 177 for (i = 0; i < screenInfo.numScreens; i++) 178 { 179 ps = GetPictureScreenIfSet (screenInfo.screens[i]); 180 if (ps && ps->totalGlyphPrivateSize) 181 { 182 ppriv = glyph->devPrivates + ps->glyphPrivateOffset; 183 sizes = ps->glyphPrivateSizes; 184 ptr = (char *) (ppriv + ps->glyphPrivateLen); 185 for (len = ps->glyphPrivateLen; --len >= 0; ppriv++, sizes++) 186 { 187 if ((size = *sizes) != 0) 188 { 189 ppriv->ptr = (pointer) ptr; 190 ptr += size; 191 } 192 else 193 ppriv->ptr = (pointer) 0; 194 } 195 } 196 } 197} 198 199static Bool 200ReallocGlobalGlyphPrivate (GlyphPtr glyph) 201{ 202 PictureScreenPtr ps; 203 DevUnion *devPrivates; 204 char *ptr; 205 int i; 206 207 devPrivates = xalloc (globalTotalGlyphPrivateSize); 208 if (!devPrivates) 209 return FALSE; 210 211 ptr = (char *) devPrivates; 212 for (i = 0; i < screenInfo.numScreens; i++) 213 { 214 ps = GetPictureScreenIfSet (screenInfo.screens[i]); 215 if (ps && ps->totalGlyphPrivateSize) 216 { 217 if (ps->glyphPrivateOffset != -1) 218 { 219 memcpy (ptr, glyph->devPrivates + ps->glyphPrivateOffset, 220 ps->totalGlyphPrivateSize); 221 } 222 else if (ps->totalGlyphPrivateSize) 223 { 224 memset (ptr, 0, ps->totalGlyphPrivateSize); 225 } 226 227 ptr += ps->totalGlyphPrivateSize; 228 } 229 } 230 231 if (glyph->devPrivates) 232 xfree (glyph->devPrivates); 233 234 glyph->devPrivates = devPrivates; 235 236 return TRUE; 237} 238 239Bool 240GlyphInit (ScreenPtr pScreen) 241{ 242 PictureScreenPtr ps = GetPictureScreen (pScreen); 243 244 ps->totalGlyphPrivateSize = 0; 245 ps->glyphPrivateSizes = 0; 246 ps->glyphPrivateLen = 0; 247 ps->glyphPrivateOffset = -1; 248 249 return TRUE; 250} 251 252Bool 253GlyphFinishInit (ScreenPtr pScreen) 254{ 255 PictureScreenPtr ps = GetPictureScreen (pScreen); 256 257 if (ps->totalGlyphPrivateSize) 258 { 259 GlyphPtr glyph; 260 int fdepth, i; 261 262 globalTotalGlyphPrivateSize += ps->totalGlyphPrivateSize; 263 264 for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) 265 { 266 if (!globalGlyphs[fdepth].hashSet) 267 continue; 268 269 for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) 270 { 271 glyph = globalGlyphs[fdepth].table[i].glyph; 272 if (glyph && glyph != DeletedGlyph) 273 { 274 if (!ReallocGlobalGlyphPrivate (glyph)) 275 return FALSE; 276 } 277 } 278 } 279 280 SetGlyphScreenPrivateOffsets (); 281 282 for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) 283 { 284 if (!globalGlyphs[fdepth].hashSet) 285 continue; 286 287 for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) 288 { 289 glyph = globalGlyphs[fdepth].table[i].glyph; 290 if (glyph && glyph != DeletedGlyph) 291 { 292 SetGlyphPrivatePointers (glyph); 293 294 if (!(*ps->RealizeGlyph) (pScreen, glyph)) 295 return FALSE; 296 } 297 } 298 } 299 } 300 else 301 ps->glyphPrivateOffset = 0; 302 303 return TRUE; 304} 305 306void 307GlyphUninit (ScreenPtr pScreen) 308{ 309 PictureScreenPtr ps = GetPictureScreen (pScreen); 310 GlyphPtr glyph; 311 int fdepth, i; 312 313 globalTotalGlyphPrivateSize -= ps->totalGlyphPrivateSize; 314 315 for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) 316 { 317 if (!globalGlyphs[fdepth].hashSet) 318 continue; 319 320 for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) 321 { 322 glyph = globalGlyphs[fdepth].table[i].glyph; 323 if (glyph && glyph != DeletedGlyph) 324 { 325 (*ps->UnrealizeGlyph) (pScreen, glyph); 326 327 if (globalTotalGlyphPrivateSize) 328 { 329 if (!ReallocGlobalGlyphPrivate (glyph)) 330 return; 331 } 332 else 333 { 334 if (glyph->devPrivates) 335 xfree (glyph->devPrivates); 336 glyph->devPrivates = NULL; 337 } 338 } 339 } 340 } 341 342 if (globalTotalGlyphPrivateSize) 343 SetGlyphScreenPrivateOffsets (); 344 345 for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) 346 { 347 if (!globalGlyphs[fdepth].hashSet) 348 continue; 349 350 for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) 351 { 352 glyph = globalGlyphs[fdepth].table[i].glyph; 353 if (glyph && glyph != DeletedGlyph) 354 { 355 if (globalTotalGlyphPrivateSize) 356 SetGlyphPrivatePointers (glyph); 357 } 358 } 359 } 360 361 if (ps->glyphPrivateSizes) 362 xfree (ps->glyphPrivateSizes); 363} 364 365GlyphHashSetPtr 366FindGlyphHashSet (CARD32 filled) 367{ 368 int i; 369 370 for (i = 0; i < NGLYPHHASHSETS; i++) 371 if (glyphHashSets[i].entries >= filled) 372 return &glyphHashSets[i]; 373 return 0; 374} 375 376static int _GlyphSetPrivateAllocateIndex = 0; 377 378int 379AllocateGlyphSetPrivateIndex (void) 380{ 381 return _GlyphSetPrivateAllocateIndex++; 382} 383 384void 385ResetGlyphSetPrivateIndex (void) 386{ 387 _GlyphSetPrivateAllocateIndex = 0; 388} 389 390Bool 391_GlyphSetSetNewPrivate (GlyphSetPtr glyphSet, int n, pointer ptr) 392{ 393 pointer *new; 394 395 if (n > glyphSet->maxPrivate) { 396 if (glyphSet->devPrivates && 397 glyphSet->devPrivates != (pointer)(&glyphSet[1])) { 398 new = (pointer *) xrealloc (glyphSet->devPrivates, 399 (n + 1) * sizeof (pointer)); 400 if (!new) 401 return FALSE; 402 } else { 403 new = (pointer *) xalloc ((n + 1) * sizeof (pointer)); 404 if (!new) 405 return FALSE; 406 if (glyphSet->devPrivates) 407 memcpy (new, 408 glyphSet->devPrivates, 409 (glyphSet->maxPrivate + 1) * sizeof (pointer)); 410 } 411 glyphSet->devPrivates = new; 412 /* Zero out new, uninitialize privates */ 413 while (++glyphSet->maxPrivate < n) 414 glyphSet->devPrivates[glyphSet->maxPrivate] = (pointer)0; 415 } 416 glyphSet->devPrivates[n] = ptr; 417 return TRUE; 418} 419 420GlyphRefPtr 421FindGlyphRef (GlyphHashPtr hash, CARD32 signature, Bool match, GlyphPtr compare) 422{ 423 CARD32 elt, step, s; 424 GlyphPtr glyph; 425 GlyphRefPtr table, gr, del; 426 CARD32 tableSize = hash->hashSet->size; 427 428 table = hash->table; 429 elt = signature % tableSize; 430 step = 0; 431 del = 0; 432 for (;;) 433 { 434 gr = &table[elt]; 435 s = gr->signature; 436 glyph = gr->glyph; 437 if (!glyph) 438 { 439 if (del) 440 gr = del; 441 break; 442 } 443 if (glyph == DeletedGlyph) 444 { 445 if (!del) 446 del = gr; 447 else if (gr == del) 448 break; 449 } 450 else if (s == signature && 451 (!match || 452 memcmp (&compare->info, &glyph->info, compare->size) == 0)) 453 { 454 break; 455 } 456 if (!step) 457 { 458 step = signature % hash->hashSet->rehash; 459 if (!step) 460 step = 1; 461 } 462 elt += step; 463 if (elt >= tableSize) 464 elt -= tableSize; 465 } 466 return gr; 467} 468 469CARD32 470HashGlyph (GlyphPtr glyph) 471{ 472 CARD32 *bits = (CARD32 *) &(glyph->info); 473 CARD32 hash; 474 int n = glyph->size / sizeof (CARD32); 475 476 hash = 0; 477 while (n--) 478 hash ^= *bits++; 479 return hash; 480} 481 482#ifdef CHECK_DUPLICATES 483void 484DuplicateRef (GlyphPtr glyph, char *where) 485{ 486 ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); 487} 488 489void 490CheckDuplicates (GlyphHashPtr hash, char *where) 491{ 492 GlyphPtr g; 493 int i, j; 494 495 for (i = 0; i < hash->hashSet->size; i++) 496 { 497 g = hash->table[i].glyph; 498 if (!g || g == DeletedGlyph) 499 continue; 500 for (j = i + 1; j < hash->hashSet->size; j++) 501 if (hash->table[j].glyph == g) 502 DuplicateRef (g, where); 503 } 504} 505#else 506#define CheckDuplicates(a,b) 507#define DuplicateRef(a,b) 508#endif 509 510void 511FreeGlyph (GlyphPtr glyph, int format) 512{ 513 CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); 514 if (--glyph->refcnt == 0) 515 { 516 PictureScreenPtr ps; 517 GlyphRefPtr gr; 518 int i; 519 int first; 520 521 first = -1; 522 for (i = 0; i < globalGlyphs[format].hashSet->size; i++) 523 if (globalGlyphs[format].table[i].glyph == glyph) 524 { 525 if (first != -1) 526 DuplicateRef (glyph, "FreeGlyph check"); 527 first = i; 528 } 529 530 gr = FindGlyphRef (&globalGlyphs[format], 531 HashGlyph (glyph), TRUE, glyph); 532 if (gr - globalGlyphs[format].table != first) 533 DuplicateRef (glyph, "Found wrong one"); 534 if (gr->glyph && gr->glyph != DeletedGlyph) 535 { 536 gr->glyph = DeletedGlyph; 537 gr->signature = 0; 538 globalGlyphs[format].tableEntries--; 539 } 540 541 for (i = 0; i < screenInfo.numScreens; i++) 542 { 543 ps = GetPictureScreenIfSet (screenInfo.screens[i]); 544 if (ps) 545 (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); 546 } 547 548 if (glyph->devPrivates) 549 xfree (glyph->devPrivates); 550 xfree (glyph); 551 } 552} 553 554void 555AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) 556{ 557 GlyphRefPtr gr; 558 CARD32 hash; 559 560 CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); 561 /* Locate existing matching glyph */ 562 hash = HashGlyph (glyph); 563 gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph); 564 if (gr->glyph && gr->glyph != DeletedGlyph) 565 { 566 PictureScreenPtr ps; 567 int i; 568 569 for (i = 0; i < screenInfo.numScreens; i++) 570 { 571 ps = GetPictureScreenIfSet (screenInfo.screens[i]); 572 if (ps) 573 (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); 574 } 575 if (glyph->devPrivates) 576 xfree (glyph->devPrivates); 577 xfree (glyph); 578 glyph = gr->glyph; 579 } 580 else 581 { 582 gr->glyph = glyph; 583 gr->signature = hash; 584 globalGlyphs[glyphSet->fdepth].tableEntries++; 585 } 586 587 /* Insert/replace glyphset value */ 588 gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); 589 ++glyph->refcnt; 590 if (gr->glyph && gr->glyph != DeletedGlyph) 591 FreeGlyph (gr->glyph, glyphSet->fdepth); 592 else 593 glyphSet->hash.tableEntries++; 594 gr->glyph = glyph; 595 gr->signature = id; 596 CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); 597} 598 599Bool 600DeleteGlyph (GlyphSetPtr glyphSet, Glyph id) 601{ 602 GlyphRefPtr gr; 603 GlyphPtr glyph; 604 605 gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); 606 glyph = gr->glyph; 607 if (glyph && glyph != DeletedGlyph) 608 { 609 gr->glyph = DeletedGlyph; 610 glyphSet->hash.tableEntries--; 611 FreeGlyph (glyph, glyphSet->fdepth); 612 return TRUE; 613 } 614 return FALSE; 615} 616 617GlyphPtr 618FindGlyph (GlyphSetPtr glyphSet, Glyph id) 619{ 620 GlyphPtr glyph; 621 622 glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; 623 if (glyph == DeletedGlyph) 624 glyph = 0; 625 return glyph; 626} 627 628GlyphPtr 629AllocateGlyph (xGlyphInfo *gi, int fdepth) 630{ 631 PictureScreenPtr ps; 632 int size; 633 GlyphPtr glyph; 634 int i; 635 size_t padded_width; 636 637 padded_width = PixmapBytePad (gi->width, glyphDepths[fdepth]); 638 if (gi->height && padded_width > (UINT32_MAX - sizeof(GlyphRec))/gi->height) 639 return 0; 640 size = gi->height * padded_width; 641 glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); 642 if (!glyph) 643 return 0; 644 glyph->refcnt = 0; 645 glyph->size = size + sizeof (xGlyphInfo); 646 glyph->info = *gi; 647 648 if (globalTotalGlyphPrivateSize) 649 { 650 glyph->devPrivates = xalloc (globalTotalGlyphPrivateSize); 651 if (!glyph->devPrivates) 652 return 0; 653 654 SetGlyphPrivatePointers (glyph); 655 } else 656 glyph->devPrivates = NULL; 657 658 for (i = 0; i < screenInfo.numScreens; i++) 659 { 660 ps = GetPictureScreenIfSet (screenInfo.screens[i]); 661 if (ps) 662 { 663 if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph)) 664 { 665 while (i--) 666 { 667 ps = GetPictureScreenIfSet (screenInfo.screens[i]); 668 if (ps) 669 (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); 670 } 671 672 if (glyph->devPrivates) 673 xfree (glyph->devPrivates); 674 xfree (glyph); 675 return 0; 676 } 677 } 678 } 679 680 return glyph; 681} 682 683Bool 684AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) 685{ 686 hash->table = (GlyphRefPtr) xalloc (hashSet->size * sizeof (GlyphRefRec)); 687 if (!hash->table) 688 return FALSE; 689 memset (hash->table, 0, hashSet->size * sizeof (GlyphRefRec)); 690 hash->hashSet = hashSet; 691 hash->tableEntries = 0; 692 return TRUE; 693} 694 695Bool 696ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) 697{ 698 CARD32 tableEntries; 699 GlyphHashSetPtr hashSet; 700 GlyphHashRec newHash; 701 GlyphRefPtr gr; 702 GlyphPtr glyph; 703 int i; 704 int oldSize; 705 CARD32 s; 706 707 tableEntries = hash->tableEntries + change; 708 hashSet = FindGlyphHashSet (tableEntries); 709 if (hashSet == hash->hashSet) 710 return TRUE; 711 if (global) 712 CheckDuplicates (hash, "ResizeGlyphHash top"); 713 if (!AllocateGlyphHash (&newHash, hashSet)) 714 return FALSE; 715 if (hash->table) 716 { 717 oldSize = hash->hashSet->size; 718 for (i = 0; i < oldSize; i++) 719 { 720 glyph = hash->table[i].glyph; 721 if (glyph && glyph != DeletedGlyph) 722 { 723 s = hash->table[i].signature; 724 gr = FindGlyphRef (&newHash, s, global, glyph); 725 gr->signature = s; 726 gr->glyph = glyph; 727 ++newHash.tableEntries; 728 } 729 } 730 xfree (hash->table); 731 } 732 *hash = newHash; 733 if (global) 734 CheckDuplicates (hash, "ResizeGlyphHash bottom"); 735 return TRUE; 736} 737 738Bool 739ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) 740{ 741 return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && 742 ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); 743} 744 745GlyphSetPtr 746AllocateGlyphSet (int fdepth, PictFormatPtr format) 747{ 748 GlyphSetPtr glyphSet; 749 int size; 750 751 if (!globalGlyphs[fdepth].hashSet) 752 { 753 if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) 754 return FALSE; 755 } 756 757 size = (sizeof (GlyphSetRec) + 758 (sizeof (pointer) * _GlyphSetPrivateAllocateIndex)); 759 glyphSet = xalloc (size); 760 if (!glyphSet) 761 return FALSE; 762 bzero((char *)glyphSet, size); 763 glyphSet->maxPrivate = _GlyphSetPrivateAllocateIndex - 1; 764 if (_GlyphSetPrivateAllocateIndex) 765 glyphSet->devPrivates = (pointer)(&glyphSet[1]); 766 767 if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) 768 { 769 xfree (glyphSet); 770 return FALSE; 771 } 772 glyphSet->refcnt = 1; 773 glyphSet->fdepth = fdepth; 774 glyphSet->format = format; 775 return glyphSet; 776} 777 778int 779FreeGlyphSet (pointer value, 780 XID gid) 781{ 782 GlyphSetPtr glyphSet = (GlyphSetPtr) value; 783 784 if (--glyphSet->refcnt == 0) 785 { 786 CARD32 i, tableSize = glyphSet->hash.hashSet->size; 787 GlyphRefPtr table = glyphSet->hash.table; 788 GlyphPtr glyph; 789 790 for (i = 0; i < tableSize; i++) 791 { 792 glyph = table[i].glyph; 793 if (glyph && glyph != DeletedGlyph) 794 FreeGlyph (glyph, glyphSet->fdepth); 795 } 796 if (!globalGlyphs[glyphSet->fdepth].tableEntries) 797 { 798 xfree (globalGlyphs[glyphSet->fdepth].table); 799 globalGlyphs[glyphSet->fdepth].table = 0; 800 globalGlyphs[glyphSet->fdepth].hashSet = 0; 801 } 802 else 803 ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); 804 xfree (table); 805 806 if (glyphSet->devPrivates && 807 glyphSet->devPrivates != (pointer)(&glyphSet[1])) 808 xfree(glyphSet->devPrivates); 809 810 xfree (glyphSet); 811 } 812 return Success; 813} 814