glyph.c revision f7df2e56
105b261ecSmrg/* 205b261ecSmrg * 305b261ecSmrg * Copyright © 2000 SuSE, Inc. 405b261ecSmrg * 505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 705b261ecSmrg * the above copyright notice appear in all copies and that both that 805b261ecSmrg * copyright notice and this permission notice appear in supporting 905b261ecSmrg * documentation, and that the name of SuSE not be used in advertising or 1005b261ecSmrg * publicity pertaining to distribution of the software without specific, 1105b261ecSmrg * written prior permission. SuSE makes no representations about the 1205b261ecSmrg * suitability of this software for any purpose. It is provided "as is" 1305b261ecSmrg * without express or implied warranty. 1405b261ecSmrg * 1505b261ecSmrg * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 1605b261ecSmrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 1705b261ecSmrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1805b261ecSmrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 19f7df2e56Smrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 2005b261ecSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2105b261ecSmrg * 2205b261ecSmrg * Author: Keith Packard, SuSE, Inc. 2305b261ecSmrg */ 2405b261ecSmrg 2505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2605b261ecSmrg#include <dix-config.h> 2705b261ecSmrg#endif 2805b261ecSmrg 294202a189Smrg#include "xsha1.h" 304642e01fSmrg 3105b261ecSmrg#include "misc.h" 3205b261ecSmrg#include "scrnintstr.h" 3305b261ecSmrg#include "os.h" 3405b261ecSmrg#include "regionstr.h" 3505b261ecSmrg#include "validate.h" 3605b261ecSmrg#include "windowstr.h" 3705b261ecSmrg#include "input.h" 3805b261ecSmrg#include "resource.h" 3905b261ecSmrg#include "colormapst.h" 4005b261ecSmrg#include "cursorstr.h" 4105b261ecSmrg#include "dixstruct.h" 4205b261ecSmrg#include "gcstruct.h" 4305b261ecSmrg#include "servermd.h" 4405b261ecSmrg#include "picturestr.h" 4505b261ecSmrg#include "glyphstr.h" 464642e01fSmrg#include "mipict.h" 4705b261ecSmrg 4805b261ecSmrg/* 4905b261ecSmrg * From Knuth -- a good choice for hash/rehash values is p, p-2 where 5005b261ecSmrg * p and p-2 are both prime. These tables are sized to have an extra 10% 5105b261ecSmrg * free to avoid exponential performance degradation as the hash table fills 5205b261ecSmrg */ 5305b261ecSmrgstatic GlyphHashSetRec glyphHashSets[] = { 54f7df2e56Smrg {32, 43, 41}, 55f7df2e56Smrg {64, 73, 71}, 56f7df2e56Smrg {128, 151, 149}, 57f7df2e56Smrg {256, 283, 281}, 58f7df2e56Smrg {512, 571, 569}, 59f7df2e56Smrg {1024, 1153, 1151}, 60f7df2e56Smrg {2048, 2269, 2267}, 61f7df2e56Smrg {4096, 4519, 4517}, 62f7df2e56Smrg {8192, 9013, 9011}, 63f7df2e56Smrg {16384, 18043, 18041}, 64f7df2e56Smrg {32768, 36109, 36107}, 65f7df2e56Smrg {65536, 72091, 72089}, 66f7df2e56Smrg {131072, 144409, 144407}, 67f7df2e56Smrg {262144, 288361, 288359}, 68f7df2e56Smrg {524288, 576883, 576881}, 69f7df2e56Smrg {1048576, 1153459, 1153457}, 70f7df2e56Smrg {2097152, 2307163, 2307161}, 71f7df2e56Smrg {4194304, 4613893, 4613891}, 72f7df2e56Smrg {8388608, 9227641, 9227639}, 73f7df2e56Smrg {16777216, 18455029, 18455027}, 74f7df2e56Smrg {33554432, 36911011, 36911009}, 75f7df2e56Smrg {67108864, 73819861, 73819859}, 76f7df2e56Smrg {134217728, 147639589, 147639587}, 77f7df2e56Smrg {268435456, 295279081, 295279079}, 78f7df2e56Smrg {536870912, 590559793, 590559791} 7905b261ecSmrg}; 8005b261ecSmrg 8105b261ecSmrg#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) 8205b261ecSmrg 83f7df2e56Smrgstatic GlyphHashRec globalGlyphs[GlyphFormatNum]; 8405b261ecSmrg 8505b261ecSmrgvoid 86f7df2e56SmrgGlyphUninit(ScreenPtr pScreen) 8705b261ecSmrg{ 88f7df2e56Smrg PictureScreenPtr ps = GetPictureScreen(pScreen); 89f7df2e56Smrg GlyphPtr glyph; 90f7df2e56Smrg int fdepth, i; 91f7df2e56Smrg 92f7df2e56Smrg for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) { 93f7df2e56Smrg if (!globalGlyphs[fdepth].hashSet) 94f7df2e56Smrg continue; 95f7df2e56Smrg 96f7df2e56Smrg for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) { 97f7df2e56Smrg glyph = globalGlyphs[fdepth].table[i].glyph; 98f7df2e56Smrg if (glyph && glyph != DeletedGlyph) { 99f7df2e56Smrg if (GetGlyphPicture(glyph, pScreen)) { 100f7df2e56Smrg FreePicture((void *) GetGlyphPicture(glyph, pScreen), 0); 101f7df2e56Smrg SetGlyphPicture(glyph, pScreen, NULL); 102f7df2e56Smrg } 103f7df2e56Smrg (*ps->UnrealizeGlyph) (pScreen, glyph); 104f7df2e56Smrg } 105f7df2e56Smrg } 10605b261ecSmrg } 10705b261ecSmrg} 10805b261ecSmrg 109f7df2e56Smrgstatic GlyphHashSetPtr 110f7df2e56SmrgFindGlyphHashSet(CARD32 filled) 11105b261ecSmrg{ 112f7df2e56Smrg int i; 11305b261ecSmrg 11405b261ecSmrg for (i = 0; i < NGLYPHHASHSETS; i++) 115f7df2e56Smrg if (glyphHashSets[i].entries >= filled) 116f7df2e56Smrg return &glyphHashSets[i]; 11705b261ecSmrg return 0; 11805b261ecSmrg} 11905b261ecSmrg 120f7df2e56Smrgstatic GlyphRefPtr 121f7df2e56SmrgFindGlyphRef(GlyphHashPtr hash, 122f7df2e56Smrg CARD32 signature, Bool match, unsigned char sha1[20]) 12305b261ecSmrg{ 124f7df2e56Smrg CARD32 elt, step, s; 125f7df2e56Smrg GlyphPtr glyph; 126f7df2e56Smrg GlyphRefPtr table, gr, del; 127f7df2e56Smrg CARD32 tableSize = hash->hashSet->size; 12805b261ecSmrg 12905b261ecSmrg table = hash->table; 13005b261ecSmrg elt = signature % tableSize; 13105b261ecSmrg step = 0; 13205b261ecSmrg del = 0; 133f7df2e56Smrg for (;;) { 134f7df2e56Smrg gr = &table[elt]; 135f7df2e56Smrg s = gr->signature; 136f7df2e56Smrg glyph = gr->glyph; 137f7df2e56Smrg if (!glyph) { 138f7df2e56Smrg if (del) 139f7df2e56Smrg gr = del; 140f7df2e56Smrg break; 141f7df2e56Smrg } 142f7df2e56Smrg if (glyph == DeletedGlyph) { 143f7df2e56Smrg if (!del) 144f7df2e56Smrg del = gr; 145f7df2e56Smrg else if (gr == del) 146f7df2e56Smrg break; 147f7df2e56Smrg } 148f7df2e56Smrg else if (s == signature && 149f7df2e56Smrg (!match || memcmp(glyph->sha1, sha1, 20) == 0)) { 150f7df2e56Smrg break; 151f7df2e56Smrg } 152f7df2e56Smrg if (!step) { 153f7df2e56Smrg step = signature % hash->hashSet->rehash; 154f7df2e56Smrg if (!step) 155f7df2e56Smrg step = 1; 156f7df2e56Smrg } 157f7df2e56Smrg elt += step; 158f7df2e56Smrg if (elt >= tableSize) 159f7df2e56Smrg elt -= tableSize; 16005b261ecSmrg } 16105b261ecSmrg return gr; 16205b261ecSmrg} 16305b261ecSmrg 1644642e01fSmrgint 165f7df2e56SmrgHashGlyph(xGlyphInfo * gi, 166f7df2e56Smrg CARD8 *bits, unsigned long size, unsigned char sha1[20]) 16705b261ecSmrg{ 1684202a189Smrg void *ctx = x_sha1_init(); 1694642e01fSmrg int success; 1704642e01fSmrg 1714202a189Smrg if (!ctx) 172f7df2e56Smrg return BadAlloc; 1734642e01fSmrg 1744202a189Smrg success = x_sha1_update(ctx, gi, sizeof(xGlyphInfo)); 1754202a189Smrg if (!success) 176f7df2e56Smrg return BadAlloc; 1774202a189Smrg success = x_sha1_update(ctx, bits, size); 1784202a189Smrg if (!success) 179f7df2e56Smrg return BadAlloc; 1804202a189Smrg success = x_sha1_final(ctx, sha1); 1814202a189Smrg if (!success) 182f7df2e56Smrg return BadAlloc; 1834642e01fSmrg return Success; 1844642e01fSmrg} 1854642e01fSmrg 1864642e01fSmrgGlyphPtr 187f7df2e56SmrgFindGlyphByHash(unsigned char sha1[20], int format) 1884642e01fSmrg{ 1894642e01fSmrg GlyphRefPtr gr; 1904642e01fSmrg CARD32 signature = *(CARD32 *) sha1; 1914642e01fSmrg 192ad5464f4Smrg if (!globalGlyphs[format].hashSet) 193f7df2e56Smrg return NULL; 194ad5464f4Smrg 195f7df2e56Smrg gr = FindGlyphRef(&globalGlyphs[format], signature, TRUE, sha1); 1964642e01fSmrg 1974642e01fSmrg if (gr->glyph && gr->glyph != DeletedGlyph) 198f7df2e56Smrg return gr->glyph; 1994642e01fSmrg else 200f7df2e56Smrg return NULL; 20105b261ecSmrg} 20205b261ecSmrg 20305b261ecSmrg#ifdef CHECK_DUPLICATES 20405b261ecSmrgvoid 205f7df2e56SmrgDuplicateRef(GlyphPtr glyph, char *where) 20605b261ecSmrg{ 207f7df2e56Smrg ErrorF("Duplicate Glyph 0x%x from %s\n", glyph, where); 20805b261ecSmrg} 20905b261ecSmrg 21005b261ecSmrgvoid 211f7df2e56SmrgCheckDuplicates(GlyphHashPtr hash, char *where) 21205b261ecSmrg{ 213f7df2e56Smrg GlyphPtr g; 214f7df2e56Smrg int i, j; 215f7df2e56Smrg 216f7df2e56Smrg for (i = 0; i < hash->hashSet->size; i++) { 217f7df2e56Smrg g = hash->table[i].glyph; 218f7df2e56Smrg if (!g || g == DeletedGlyph) 219f7df2e56Smrg continue; 220f7df2e56Smrg for (j = i + 1; j < hash->hashSet->size; j++) 221f7df2e56Smrg if (hash->table[j].glyph == g) 222f7df2e56Smrg DuplicateRef(g, where); 22305b261ecSmrg } 22405b261ecSmrg} 22505b261ecSmrg#else 22605b261ecSmrg#define CheckDuplicates(a,b) 22705b261ecSmrg#define DuplicateRef(a,b) 22805b261ecSmrg#endif 22905b261ecSmrg 2304202a189Smrgstatic void 2314202a189SmrgFreeGlyphPicture(GlyphPtr glyph) 2324202a189Smrg{ 2334202a189Smrg PictureScreenPtr ps; 2344202a189Smrg int i; 2354202a189Smrg 236f7df2e56Smrg for (i = 0; i < screenInfo.numScreens; i++) { 2374202a189Smrg ScreenPtr pScreen = screenInfo.screens[i]; 2384202a189Smrg 239f7df2e56Smrg if (GetGlyphPicture(glyph, pScreen)) 240f7df2e56Smrg FreePicture((void *) GetGlyphPicture(glyph, pScreen), 0); 2414202a189Smrg 242f7df2e56Smrg ps = GetPictureScreenIfSet(pScreen); 2434202a189Smrg if (ps) 2444202a189Smrg (*ps->UnrealizeGlyph) (pScreen, glyph); 2454202a189Smrg } 2464202a189Smrg} 2474202a189Smrg 248f7df2e56Smrgstatic void 249f7df2e56SmrgFreeGlyph(GlyphPtr glyph, int format) 25005b261ecSmrg{ 251f7df2e56Smrg CheckDuplicates(&globalGlyphs[format], "FreeGlyph"); 252f7df2e56Smrg if (--glyph->refcnt == 0) { 253f7df2e56Smrg GlyphRefPtr gr; 254f7df2e56Smrg int i; 255f7df2e56Smrg int first; 256f7df2e56Smrg CARD32 signature; 257f7df2e56Smrg 258f7df2e56Smrg first = -1; 259f7df2e56Smrg for (i = 0; i < globalGlyphs[format].hashSet->size; i++) 260f7df2e56Smrg if (globalGlyphs[format].table[i].glyph == glyph) { 261f7df2e56Smrg if (first != -1) 262f7df2e56Smrg DuplicateRef(glyph, "FreeGlyph check"); 263f7df2e56Smrg first = i; 264f7df2e56Smrg } 265f7df2e56Smrg 266f7df2e56Smrg signature = *(CARD32 *) glyph->sha1; 267f7df2e56Smrg gr = FindGlyphRef(&globalGlyphs[format], signature, TRUE, glyph->sha1); 268f7df2e56Smrg if (gr - globalGlyphs[format].table != first) 269f7df2e56Smrg DuplicateRef(glyph, "Found wrong one"); 270f7df2e56Smrg if (gr->glyph && gr->glyph != DeletedGlyph) { 271f7df2e56Smrg gr->glyph = DeletedGlyph; 272f7df2e56Smrg gr->signature = 0; 273f7df2e56Smrg globalGlyphs[format].tableEntries--; 274f7df2e56Smrg } 275f7df2e56Smrg 276f7df2e56Smrg FreeGlyphPicture(glyph); 277f7df2e56Smrg dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); 27805b261ecSmrg } 27905b261ecSmrg} 28005b261ecSmrg 28105b261ecSmrgvoid 282f7df2e56SmrgAddGlyph(GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) 28305b261ecSmrg{ 284f7df2e56Smrg GlyphRefPtr gr; 285f7df2e56Smrg CARD32 signature; 28605b261ecSmrg 287f7df2e56Smrg CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); 28805b261ecSmrg /* Locate existing matching glyph */ 2894642e01fSmrg signature = *(CARD32 *) glyph->sha1; 290f7df2e56Smrg gr = FindGlyphRef(&globalGlyphs[glyphSet->fdepth], signature, 291f7df2e56Smrg TRUE, glyph->sha1); 292f7df2e56Smrg if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph) { 293f7df2e56Smrg FreeGlyphPicture(glyph); 294f7df2e56Smrg dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); 295f7df2e56Smrg glyph = gr->glyph; 29605b261ecSmrg } 297f7df2e56Smrg else if (gr->glyph != glyph) { 298f7df2e56Smrg gr->glyph = glyph; 299f7df2e56Smrg gr->signature = signature; 300f7df2e56Smrg globalGlyphs[glyphSet->fdepth].tableEntries++; 30105b261ecSmrg } 302f7df2e56Smrg 30305b261ecSmrg /* Insert/replace glyphset value */ 304f7df2e56Smrg gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0); 30505b261ecSmrg ++glyph->refcnt; 30605b261ecSmrg if (gr->glyph && gr->glyph != DeletedGlyph) 307f7df2e56Smrg FreeGlyph(gr->glyph, glyphSet->fdepth); 30805b261ecSmrg else 309f7df2e56Smrg glyphSet->hash.tableEntries++; 31005b261ecSmrg gr->glyph = glyph; 31105b261ecSmrg gr->signature = id; 312f7df2e56Smrg CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); 31305b261ecSmrg} 31405b261ecSmrg 31505b261ecSmrgBool 316f7df2e56SmrgDeleteGlyph(GlyphSetPtr glyphSet, Glyph id) 31705b261ecSmrg{ 318f7df2e56Smrg GlyphRefPtr gr; 319f7df2e56Smrg GlyphPtr glyph; 32005b261ecSmrg 321f7df2e56Smrg gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0); 32205b261ecSmrg glyph = gr->glyph; 323f7df2e56Smrg if (glyph && glyph != DeletedGlyph) { 324f7df2e56Smrg gr->glyph = DeletedGlyph; 325f7df2e56Smrg glyphSet->hash.tableEntries--; 326f7df2e56Smrg FreeGlyph(glyph, glyphSet->fdepth); 327f7df2e56Smrg return TRUE; 32805b261ecSmrg } 32905b261ecSmrg return FALSE; 33005b261ecSmrg} 33105b261ecSmrg 33205b261ecSmrgGlyphPtr 333f7df2e56SmrgFindGlyph(GlyphSetPtr glyphSet, Glyph id) 33405b261ecSmrg{ 335f7df2e56Smrg GlyphPtr glyph; 33605b261ecSmrg 337f7df2e56Smrg glyph = FindGlyphRef(&glyphSet->hash, id, FALSE, 0)->glyph; 33805b261ecSmrg if (glyph == DeletedGlyph) 339f7df2e56Smrg glyph = 0; 34005b261ecSmrg return glyph; 34105b261ecSmrg} 34205b261ecSmrg 34305b261ecSmrgGlyphPtr 344f7df2e56SmrgAllocateGlyph(xGlyphInfo * gi, int fdepth) 34505b261ecSmrg{ 34605b261ecSmrg PictureScreenPtr ps; 347f7df2e56Smrg int size; 348f7df2e56Smrg GlyphPtr glyph; 349f7df2e56Smrg int i; 350f7df2e56Smrg int head_size; 3514642e01fSmrg 352f7df2e56Smrg head_size = sizeof(GlyphRec) + screenInfo.numScreens * sizeof(PicturePtr); 3534202a189Smrg size = (head_size + dixPrivatesSize(PRIVATE_GLYPH)); 354f7df2e56Smrg glyph = (GlyphPtr) malloc(size); 35505b261ecSmrg if (!glyph) 356f7df2e56Smrg return 0; 35705b261ecSmrg glyph->refcnt = 0; 358f7df2e56Smrg glyph->size = size + sizeof(xGlyphInfo); 35905b261ecSmrg glyph->info = *gi; 3604202a189Smrg dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH); 36105b261ecSmrg 362f7df2e56Smrg for (i = 0; i < screenInfo.numScreens; i++) { 363f7df2e56Smrg ScreenPtr pScreen = screenInfo.screens[i]; 364f7df2e56Smrg SetGlyphPicture(glyph, pScreen, NULL); 365f7df2e56Smrg ps = GetPictureScreenIfSet(pScreen); 3664642e01fSmrg 367f7df2e56Smrg if (ps) { 368f7df2e56Smrg if (!(*ps->RealizeGlyph) (pScreen, glyph)) 369f7df2e56Smrg goto bail; 370f7df2e56Smrg } 37105b261ecSmrg } 372f7df2e56Smrg 37305b261ecSmrg return glyph; 3744642e01fSmrg 375f7df2e56Smrg bail: 376f7df2e56Smrg while (i--) { 377f7df2e56Smrg ps = GetPictureScreenIfSet(screenInfo.screens[i]); 378f7df2e56Smrg if (ps) 379f7df2e56Smrg (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); 3804642e01fSmrg } 3814642e01fSmrg 3824202a189Smrg dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); 3834642e01fSmrg return 0; 38405b261ecSmrg} 385f7df2e56Smrg 386f7df2e56Smrgstatic Bool 387f7df2e56SmrgAllocateGlyphHash(GlyphHashPtr hash, GlyphHashSetPtr hashSet) 38805b261ecSmrg{ 389f7df2e56Smrg hash->table = calloc(hashSet->size, sizeof(GlyphRefRec)); 39005b261ecSmrg if (!hash->table) 391f7df2e56Smrg return FALSE; 39205b261ecSmrg hash->hashSet = hashSet; 39305b261ecSmrg hash->tableEntries = 0; 39405b261ecSmrg return TRUE; 39505b261ecSmrg} 39605b261ecSmrg 397f7df2e56Smrgstatic Bool 398f7df2e56SmrgResizeGlyphHash(GlyphHashPtr hash, CARD32 change, Bool global) 39905b261ecSmrg{ 400f7df2e56Smrg CARD32 tableEntries; 40105b261ecSmrg GlyphHashSetPtr hashSet; 402f7df2e56Smrg GlyphHashRec newHash; 403f7df2e56Smrg GlyphRefPtr gr; 404f7df2e56Smrg GlyphPtr glyph; 405f7df2e56Smrg int i; 406f7df2e56Smrg int oldSize; 407f7df2e56Smrg CARD32 s; 40805b261ecSmrg 40905b261ecSmrg tableEntries = hash->tableEntries + change; 410f7df2e56Smrg hashSet = FindGlyphHashSet(tableEntries); 41105b261ecSmrg if (hashSet == hash->hashSet) 412f7df2e56Smrg return TRUE; 41305b261ecSmrg if (global) 414f7df2e56Smrg CheckDuplicates(hash, "ResizeGlyphHash top"); 415f7df2e56Smrg if (!AllocateGlyphHash(&newHash, hashSet)) 416f7df2e56Smrg return FALSE; 417f7df2e56Smrg if (hash->table) { 418f7df2e56Smrg oldSize = hash->hashSet->size; 419f7df2e56Smrg for (i = 0; i < oldSize; i++) { 420f7df2e56Smrg glyph = hash->table[i].glyph; 421f7df2e56Smrg if (glyph && glyph != DeletedGlyph) { 422f7df2e56Smrg s = hash->table[i].signature; 423f7df2e56Smrg gr = FindGlyphRef(&newHash, s, global, glyph->sha1); 424f7df2e56Smrg 425f7df2e56Smrg gr->signature = s; 426f7df2e56Smrg gr->glyph = glyph; 427f7df2e56Smrg ++newHash.tableEntries; 428f7df2e56Smrg } 429f7df2e56Smrg } 430f7df2e56Smrg free(hash->table); 43105b261ecSmrg } 43205b261ecSmrg *hash = newHash; 43305b261ecSmrg if (global) 434f7df2e56Smrg CheckDuplicates(hash, "ResizeGlyphHash bottom"); 43505b261ecSmrg return TRUE; 43605b261ecSmrg} 43705b261ecSmrg 43805b261ecSmrgBool 439f7df2e56SmrgResizeGlyphSet(GlyphSetPtr glyphSet, CARD32 change) 44005b261ecSmrg{ 441f7df2e56Smrg return (ResizeGlyphHash(&glyphSet->hash, change, FALSE) && 442f7df2e56Smrg ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], change, TRUE)); 44305b261ecSmrg} 444f7df2e56Smrg 44505b261ecSmrgGlyphSetPtr 446f7df2e56SmrgAllocateGlyphSet(int fdepth, PictFormatPtr format) 44705b261ecSmrg{ 448f7df2e56Smrg GlyphSetPtr glyphSet; 449f7df2e56Smrg 450f7df2e56Smrg if (!globalGlyphs[fdepth].hashSet) { 451f7df2e56Smrg if (!AllocateGlyphHash(&globalGlyphs[fdepth], &glyphHashSets[0])) 452f7df2e56Smrg return FALSE; 45305b261ecSmrg } 45405b261ecSmrg 4554202a189Smrg glyphSet = dixAllocateObjectWithPrivates(GlyphSetRec, PRIVATE_GLYPHSET); 45605b261ecSmrg if (!glyphSet) 457f7df2e56Smrg return FALSE; 45805b261ecSmrg 459f7df2e56Smrg if (!AllocateGlyphHash(&glyphSet->hash, &glyphHashSets[0])) { 460f7df2e56Smrg free(glyphSet); 461f7df2e56Smrg return FALSE; 46205b261ecSmrg } 46305b261ecSmrg glyphSet->refcnt = 1; 46405b261ecSmrg glyphSet->fdepth = fdepth; 46505b261ecSmrg glyphSet->format = format; 466f7df2e56Smrg return glyphSet; 46705b261ecSmrg} 46805b261ecSmrg 46905b261ecSmrgint 470f7df2e56SmrgFreeGlyphSet(void *value, XID gid) 47105b261ecSmrg{ 472f7df2e56Smrg GlyphSetPtr glyphSet = (GlyphSetPtr) value; 473f7df2e56Smrg 474f7df2e56Smrg if (--glyphSet->refcnt == 0) { 475f7df2e56Smrg CARD32 i, tableSize = glyphSet->hash.hashSet->size; 476f7df2e56Smrg GlyphRefPtr table = glyphSet->hash.table; 477f7df2e56Smrg GlyphPtr glyph; 478f7df2e56Smrg 479f7df2e56Smrg for (i = 0; i < tableSize; i++) { 480f7df2e56Smrg glyph = table[i].glyph; 481f7df2e56Smrg if (glyph && glyph != DeletedGlyph) 482f7df2e56Smrg FreeGlyph(glyph, glyphSet->fdepth); 483f7df2e56Smrg } 484f7df2e56Smrg if (!globalGlyphs[glyphSet->fdepth].tableEntries) { 485f7df2e56Smrg free(globalGlyphs[glyphSet->fdepth].table); 486f7df2e56Smrg globalGlyphs[glyphSet->fdepth].table = 0; 487f7df2e56Smrg globalGlyphs[glyphSet->fdepth].hashSet = 0; 488f7df2e56Smrg } 489f7df2e56Smrg else 490f7df2e56Smrg ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], 0, TRUE); 491f7df2e56Smrg free(table); 492f7df2e56Smrg dixFreeObjectWithPrivates(glyphSet, PRIVATE_GLYPHSET); 49305b261ecSmrg } 49405b261ecSmrg return Success; 49505b261ecSmrg} 4964642e01fSmrg 4974642e01fSmrgstatic void 498f7df2e56SmrgGlyphExtents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents) 4994642e01fSmrg{ 500f7df2e56Smrg int x1, x2, y1, y2; 501f7df2e56Smrg int n; 502f7df2e56Smrg GlyphPtr glyph; 503f7df2e56Smrg int x, y; 504f7df2e56Smrg 5054642e01fSmrg x = 0; 5064642e01fSmrg y = 0; 5074642e01fSmrg extents->x1 = MAXSHORT; 5084642e01fSmrg extents->x2 = MINSHORT; 5094642e01fSmrg extents->y1 = MAXSHORT; 5104642e01fSmrg extents->y2 = MINSHORT; 511f7df2e56Smrg while (nlist--) { 512f7df2e56Smrg x += list->xOff; 513f7df2e56Smrg y += list->yOff; 514f7df2e56Smrg n = list->len; 515f7df2e56Smrg list++; 516f7df2e56Smrg while (n--) { 517f7df2e56Smrg glyph = *glyphs++; 518f7df2e56Smrg x1 = x - glyph->info.x; 519f7df2e56Smrg if (x1 < MINSHORT) 520f7df2e56Smrg x1 = MINSHORT; 521f7df2e56Smrg y1 = y - glyph->info.y; 522f7df2e56Smrg if (y1 < MINSHORT) 523f7df2e56Smrg y1 = MINSHORT; 524f7df2e56Smrg x2 = x1 + glyph->info.width; 525f7df2e56Smrg if (x2 > MAXSHORT) 526f7df2e56Smrg x2 = MAXSHORT; 527f7df2e56Smrg y2 = y1 + glyph->info.height; 528f7df2e56Smrg if (y2 > MAXSHORT) 529f7df2e56Smrg y2 = MAXSHORT; 530f7df2e56Smrg if (x1 < extents->x1) 531f7df2e56Smrg extents->x1 = x1; 532f7df2e56Smrg if (x2 > extents->x2) 533f7df2e56Smrg extents->x2 = x2; 534f7df2e56Smrg if (y1 < extents->y1) 535f7df2e56Smrg extents->y1 = y1; 536f7df2e56Smrg if (y2 > extents->y2) 537f7df2e56Smrg extents->y2 = y2; 538f7df2e56Smrg x += glyph->info.xOff; 539f7df2e56Smrg y += glyph->info.yOff; 540f7df2e56Smrg } 5414642e01fSmrg } 5424642e01fSmrg} 5434642e01fSmrg 5444642e01fSmrg#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) 5454642e01fSmrg 5464202a189Smrgvoid 547f7df2e56SmrgCompositeGlyphs(CARD8 op, 548f7df2e56Smrg PicturePtr pSrc, 549f7df2e56Smrg PicturePtr pDst, 550f7df2e56Smrg PictFormatPtr maskFormat, 551f7df2e56Smrg INT16 xSrc, 552f7df2e56Smrg INT16 ySrc, int nlist, GlyphListPtr lists, GlyphPtr * glyphs) 5534642e01fSmrg{ 554f7df2e56Smrg PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 5554642e01fSmrg 556f7df2e56Smrg ValidatePicture(pSrc); 557f7df2e56Smrg ValidatePicture(pDst); 558f7df2e56Smrg (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, 559f7df2e56Smrg glyphs); 5604642e01fSmrg} 5614642e01fSmrg 5624642e01fSmrgBool 563f7df2e56SmrgmiRealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph) 5644642e01fSmrg{ 5654642e01fSmrg return TRUE; 5664642e01fSmrg} 5674642e01fSmrg 5684642e01fSmrgvoid 569f7df2e56SmrgmiUnrealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph) 5704642e01fSmrg{ 5714642e01fSmrg} 5724642e01fSmrg 5734202a189Smrgvoid 574f7df2e56SmrgmiGlyphs(CARD8 op, 575f7df2e56Smrg PicturePtr pSrc, 576f7df2e56Smrg PicturePtr pDst, 577f7df2e56Smrg PictFormatPtr maskFormat, 578f7df2e56Smrg INT16 xSrc, 579f7df2e56Smrg INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) 5804642e01fSmrg{ 581f7df2e56Smrg PicturePtr pPicture; 582f7df2e56Smrg PixmapPtr pMaskPixmap = 0; 583f7df2e56Smrg PicturePtr pMask; 584f7df2e56Smrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 585f7df2e56Smrg int width = 0, height = 0; 586f7df2e56Smrg int x, y; 587f7df2e56Smrg int xDst = list->xOff, yDst = list->yOff; 588f7df2e56Smrg int n; 589f7df2e56Smrg GlyphPtr glyph; 590f7df2e56Smrg int error; 591f7df2e56Smrg BoxRec extents = { 0, 0, 0, 0 }; 592f7df2e56Smrg CARD32 component_alpha; 593f7df2e56Smrg 594f7df2e56Smrg if (maskFormat) { 595f7df2e56Smrg GCPtr pGC; 596f7df2e56Smrg xRectangle rect; 597f7df2e56Smrg 598f7df2e56Smrg GlyphExtents(nlist, list, glyphs, &extents); 599f7df2e56Smrg 600f7df2e56Smrg if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) 601f7df2e56Smrg return; 602f7df2e56Smrg width = extents.x2 - extents.x1; 603f7df2e56Smrg height = extents.y2 - extents.y1; 604f7df2e56Smrg pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 605f7df2e56Smrg maskFormat->depth, 606f7df2e56Smrg CREATE_PIXMAP_USAGE_SCRATCH); 607f7df2e56Smrg if (!pMaskPixmap) 608f7df2e56Smrg return; 609f7df2e56Smrg component_alpha = NeedsComponent(maskFormat->format); 610f7df2e56Smrg pMask = CreatePicture(0, &pMaskPixmap->drawable, 611f7df2e56Smrg maskFormat, CPComponentAlpha, &component_alpha, 612f7df2e56Smrg serverClient, &error); 613f7df2e56Smrg if (!pMask) { 614f7df2e56Smrg (*pScreen->DestroyPixmap) (pMaskPixmap); 615f7df2e56Smrg return; 616f7df2e56Smrg } 617f7df2e56Smrg pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen); 618f7df2e56Smrg ValidateGC(&pMaskPixmap->drawable, pGC); 619f7df2e56Smrg rect.x = 0; 620f7df2e56Smrg rect.y = 0; 621f7df2e56Smrg rect.width = width; 622f7df2e56Smrg rect.height = height; 623f7df2e56Smrg (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); 624f7df2e56Smrg FreeScratchGC(pGC); 625f7df2e56Smrg x = -extents.x1; 626f7df2e56Smrg y = -extents.y1; 6274642e01fSmrg } 628f7df2e56Smrg else { 629f7df2e56Smrg pMask = pDst; 630f7df2e56Smrg x = 0; 631f7df2e56Smrg y = 0; 6324642e01fSmrg } 633f7df2e56Smrg while (nlist--) { 634f7df2e56Smrg x += list->xOff; 635f7df2e56Smrg y += list->yOff; 636f7df2e56Smrg n = list->len; 637f7df2e56Smrg while (n--) { 638f7df2e56Smrg glyph = *glyphs++; 639f7df2e56Smrg pPicture = GetGlyphPicture(glyph, pScreen); 640f7df2e56Smrg 641f7df2e56Smrg if (pPicture) { 642f7df2e56Smrg if (maskFormat) { 643f7df2e56Smrg CompositePicture(PictOpAdd, 644f7df2e56Smrg pPicture, 645f7df2e56Smrg None, 646f7df2e56Smrg pMask, 647f7df2e56Smrg 0, 0, 648f7df2e56Smrg 0, 0, 649f7df2e56Smrg x - glyph->info.x, 650f7df2e56Smrg y - glyph->info.y, 651f7df2e56Smrg glyph->info.width, glyph->info.height); 652f7df2e56Smrg } 653f7df2e56Smrg else { 654f7df2e56Smrg CompositePicture(op, 655f7df2e56Smrg pSrc, 656f7df2e56Smrg pPicture, 657f7df2e56Smrg pDst, 658f7df2e56Smrg xSrc + (x - glyph->info.x) - xDst, 659f7df2e56Smrg ySrc + (y - glyph->info.y) - yDst, 660f7df2e56Smrg 0, 0, 661f7df2e56Smrg x - glyph->info.x, 662f7df2e56Smrg y - glyph->info.y, 663f7df2e56Smrg glyph->info.width, glyph->info.height); 664f7df2e56Smrg } 665f7df2e56Smrg } 666f7df2e56Smrg 667f7df2e56Smrg x += glyph->info.xOff; 668f7df2e56Smrg y += glyph->info.yOff; 669f7df2e56Smrg } 670f7df2e56Smrg list++; 6714642e01fSmrg } 672f7df2e56Smrg if (maskFormat) { 673f7df2e56Smrg x = extents.x1; 674f7df2e56Smrg y = extents.y1; 675f7df2e56Smrg CompositePicture(op, 676f7df2e56Smrg pSrc, 677f7df2e56Smrg pMask, 678f7df2e56Smrg pDst, 679f7df2e56Smrg xSrc + x - xDst, 680f7df2e56Smrg ySrc + y - yDst, 0, 0, x, y, width, height); 681f7df2e56Smrg FreePicture((void *) pMask, (XID) 0); 682f7df2e56Smrg (*pScreen->DestroyPixmap) (pMaskPixmap); 6834642e01fSmrg } 6844642e01fSmrg} 685f7df2e56Smrg 686f7df2e56SmrgPicturePtr GetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen) 687f7df2e56Smrg{ 688f7df2e56Smrg if (pScreen->isGPU) 689f7df2e56Smrg return NULL; 690f7df2e56Smrg return GlyphPicture(glyph)[pScreen->myNum]; 691f7df2e56Smrg} 692f7df2e56Smrg 693f7df2e56Smrgvoid SetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen, PicturePtr picture) 694f7df2e56Smrg{ 695f7df2e56Smrg GlyphPicture(glyph)[pScreen->myNum] = picture; 696f7df2e56Smrg} 697