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 817e31ba66Smrg#define NGLYPHHASHSETS ARRAY_SIZE(glyphHashSets) 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 248875c6e4fSmrgvoid 249f7df2e56SmrgFreeGlyph(GlyphPtr glyph, int format) 25005b261ecSmrg{ 251f7df2e56Smrg CheckDuplicates(&globalGlyphs[format], "FreeGlyph"); 252875c6e4fSmrg BUG_RETURN(glyph->refcnt == 0); 253f7df2e56Smrg if (--glyph->refcnt == 0) { 254f7df2e56Smrg GlyphRefPtr gr; 255f7df2e56Smrg int i; 256f7df2e56Smrg int first; 257f7df2e56Smrg CARD32 signature; 258f7df2e56Smrg 259f7df2e56Smrg first = -1; 260f7df2e56Smrg for (i = 0; i < globalGlyphs[format].hashSet->size; i++) 261f7df2e56Smrg if (globalGlyphs[format].table[i].glyph == glyph) { 262f7df2e56Smrg if (first != -1) 263f7df2e56Smrg DuplicateRef(glyph, "FreeGlyph check"); 264f7df2e56Smrg first = i; 265f7df2e56Smrg } 266f7df2e56Smrg 267f7df2e56Smrg signature = *(CARD32 *) glyph->sha1; 268f7df2e56Smrg gr = FindGlyphRef(&globalGlyphs[format], signature, TRUE, glyph->sha1); 269f7df2e56Smrg if (gr - globalGlyphs[format].table != first) 270f7df2e56Smrg DuplicateRef(glyph, "Found wrong one"); 271f7df2e56Smrg if (gr->glyph && gr->glyph != DeletedGlyph) { 272f7df2e56Smrg gr->glyph = DeletedGlyph; 273f7df2e56Smrg gr->signature = 0; 274f7df2e56Smrg globalGlyphs[format].tableEntries--; 275f7df2e56Smrg } 276f7df2e56Smrg 277f7df2e56Smrg FreeGlyphPicture(glyph); 278f7df2e56Smrg dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); 27905b261ecSmrg } 28005b261ecSmrg} 28105b261ecSmrg 28205b261ecSmrgvoid 283f7df2e56SmrgAddGlyph(GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) 28405b261ecSmrg{ 285f7df2e56Smrg GlyphRefPtr gr; 286f7df2e56Smrg CARD32 signature; 28705b261ecSmrg 288f7df2e56Smrg CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); 28905b261ecSmrg /* Locate existing matching glyph */ 2904642e01fSmrg signature = *(CARD32 *) glyph->sha1; 291f7df2e56Smrg gr = FindGlyphRef(&globalGlyphs[glyphSet->fdepth], signature, 292f7df2e56Smrg TRUE, glyph->sha1); 293f7df2e56Smrg if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph) { 294f7df2e56Smrg glyph = gr->glyph; 29505b261ecSmrg } 296f7df2e56Smrg else if (gr->glyph != glyph) { 297f7df2e56Smrg gr->glyph = glyph; 298f7df2e56Smrg gr->signature = signature; 299f7df2e56Smrg globalGlyphs[glyphSet->fdepth].tableEntries++; 30005b261ecSmrg } 301f7df2e56Smrg 30205b261ecSmrg /* Insert/replace glyphset value */ 303f7df2e56Smrg gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0); 30405b261ecSmrg ++glyph->refcnt; 30505b261ecSmrg if (gr->glyph && gr->glyph != DeletedGlyph) 306f7df2e56Smrg FreeGlyph(gr->glyph, glyphSet->fdepth); 30705b261ecSmrg else 308f7df2e56Smrg glyphSet->hash.tableEntries++; 30905b261ecSmrg gr->glyph = glyph; 31005b261ecSmrg gr->signature = id; 311f7df2e56Smrg CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); 31205b261ecSmrg} 31305b261ecSmrg 31405b261ecSmrgBool 315f7df2e56SmrgDeleteGlyph(GlyphSetPtr glyphSet, Glyph id) 31605b261ecSmrg{ 317f7df2e56Smrg GlyphRefPtr gr; 318f7df2e56Smrg GlyphPtr glyph; 31905b261ecSmrg 320f7df2e56Smrg gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0); 32105b261ecSmrg glyph = gr->glyph; 322f7df2e56Smrg if (glyph && glyph != DeletedGlyph) { 323f7df2e56Smrg gr->glyph = DeletedGlyph; 324f7df2e56Smrg glyphSet->hash.tableEntries--; 325f7df2e56Smrg FreeGlyph(glyph, glyphSet->fdepth); 326f7df2e56Smrg return TRUE; 32705b261ecSmrg } 32805b261ecSmrg return FALSE; 32905b261ecSmrg} 33005b261ecSmrg 33105b261ecSmrgGlyphPtr 332f7df2e56SmrgFindGlyph(GlyphSetPtr glyphSet, Glyph id) 33305b261ecSmrg{ 334f7df2e56Smrg GlyphPtr glyph; 33505b261ecSmrg 336f7df2e56Smrg glyph = FindGlyphRef(&glyphSet->hash, id, FALSE, 0)->glyph; 33705b261ecSmrg if (glyph == DeletedGlyph) 338f7df2e56Smrg glyph = 0; 33905b261ecSmrg return glyph; 34005b261ecSmrg} 34105b261ecSmrg 34205b261ecSmrgGlyphPtr 343f7df2e56SmrgAllocateGlyph(xGlyphInfo * gi, int fdepth) 34405b261ecSmrg{ 34505b261ecSmrg PictureScreenPtr ps; 346f7df2e56Smrg int size; 347f7df2e56Smrg GlyphPtr glyph; 348f7df2e56Smrg int i; 349f7df2e56Smrg int head_size; 3504642e01fSmrg 351f7df2e56Smrg head_size = sizeof(GlyphRec) + screenInfo.numScreens * sizeof(PicturePtr); 3524202a189Smrg size = (head_size + dixPrivatesSize(PRIVATE_GLYPH)); 353f7df2e56Smrg glyph = (GlyphPtr) malloc(size); 35405b261ecSmrg if (!glyph) 355f7df2e56Smrg return 0; 356875c6e4fSmrg glyph->refcnt = 1; 357f7df2e56Smrg glyph->size = size + sizeof(xGlyphInfo); 35805b261ecSmrg glyph->info = *gi; 3594202a189Smrg dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH); 36005b261ecSmrg 361f7df2e56Smrg for (i = 0; i < screenInfo.numScreens; i++) { 362f7df2e56Smrg ScreenPtr pScreen = screenInfo.screens[i]; 363f7df2e56Smrg SetGlyphPicture(glyph, pScreen, NULL); 364f7df2e56Smrg ps = GetPictureScreenIfSet(pScreen); 3654642e01fSmrg 366f7df2e56Smrg if (ps) { 367f7df2e56Smrg if (!(*ps->RealizeGlyph) (pScreen, glyph)) 368f7df2e56Smrg goto bail; 369f7df2e56Smrg } 37005b261ecSmrg } 371f7df2e56Smrg 37205b261ecSmrg return glyph; 3734642e01fSmrg 374f7df2e56Smrg bail: 375f7df2e56Smrg while (i--) { 376f7df2e56Smrg ps = GetPictureScreenIfSet(screenInfo.screens[i]); 377f7df2e56Smrg if (ps) 378f7df2e56Smrg (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); 3794642e01fSmrg } 3804642e01fSmrg 3814202a189Smrg dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); 3824642e01fSmrg return 0; 38305b261ecSmrg} 384f7df2e56Smrg 385f7df2e56Smrgstatic Bool 386f7df2e56SmrgAllocateGlyphHash(GlyphHashPtr hash, GlyphHashSetPtr hashSet) 38705b261ecSmrg{ 388f7df2e56Smrg hash->table = calloc(hashSet->size, sizeof(GlyphRefRec)); 38905b261ecSmrg if (!hash->table) 390f7df2e56Smrg return FALSE; 39105b261ecSmrg hash->hashSet = hashSet; 39205b261ecSmrg hash->tableEntries = 0; 39305b261ecSmrg return TRUE; 39405b261ecSmrg} 39505b261ecSmrg 396f7df2e56Smrgstatic Bool 397f7df2e56SmrgResizeGlyphHash(GlyphHashPtr hash, CARD32 change, Bool global) 39805b261ecSmrg{ 399f7df2e56Smrg CARD32 tableEntries; 40005b261ecSmrg GlyphHashSetPtr hashSet; 401f7df2e56Smrg GlyphHashRec newHash; 402f7df2e56Smrg GlyphRefPtr gr; 403f7df2e56Smrg GlyphPtr glyph; 404f7df2e56Smrg int i; 405f7df2e56Smrg int oldSize; 406f7df2e56Smrg CARD32 s; 40705b261ecSmrg 40805b261ecSmrg tableEntries = hash->tableEntries + change; 409f7df2e56Smrg hashSet = FindGlyphHashSet(tableEntries); 41005b261ecSmrg if (hashSet == hash->hashSet) 411f7df2e56Smrg return TRUE; 41205b261ecSmrg if (global) 413f7df2e56Smrg CheckDuplicates(hash, "ResizeGlyphHash top"); 414f7df2e56Smrg if (!AllocateGlyphHash(&newHash, hashSet)) 415f7df2e56Smrg return FALSE; 416f7df2e56Smrg if (hash->table) { 417f7df2e56Smrg oldSize = hash->hashSet->size; 418f7df2e56Smrg for (i = 0; i < oldSize; i++) { 419f7df2e56Smrg glyph = hash->table[i].glyph; 420f7df2e56Smrg if (glyph && glyph != DeletedGlyph) { 421f7df2e56Smrg s = hash->table[i].signature; 422f7df2e56Smrg gr = FindGlyphRef(&newHash, s, global, glyph->sha1); 423f7df2e56Smrg 424f7df2e56Smrg gr->signature = s; 425f7df2e56Smrg gr->glyph = glyph; 426f7df2e56Smrg ++newHash.tableEntries; 427f7df2e56Smrg } 428f7df2e56Smrg } 429f7df2e56Smrg free(hash->table); 43005b261ecSmrg } 43105b261ecSmrg *hash = newHash; 43205b261ecSmrg if (global) 433f7df2e56Smrg CheckDuplicates(hash, "ResizeGlyphHash bottom"); 43405b261ecSmrg return TRUE; 43505b261ecSmrg} 43605b261ecSmrg 43705b261ecSmrgBool 438f7df2e56SmrgResizeGlyphSet(GlyphSetPtr glyphSet, CARD32 change) 43905b261ecSmrg{ 440f7df2e56Smrg return (ResizeGlyphHash(&glyphSet->hash, change, FALSE) && 441f7df2e56Smrg ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], change, TRUE)); 44205b261ecSmrg} 443f7df2e56Smrg 44405b261ecSmrgGlyphSetPtr 445f7df2e56SmrgAllocateGlyphSet(int fdepth, PictFormatPtr format) 44605b261ecSmrg{ 447f7df2e56Smrg GlyphSetPtr glyphSet; 448f7df2e56Smrg 449f7df2e56Smrg if (!globalGlyphs[fdepth].hashSet) { 450f7df2e56Smrg if (!AllocateGlyphHash(&globalGlyphs[fdepth], &glyphHashSets[0])) 451f7df2e56Smrg return FALSE; 45205b261ecSmrg } 45305b261ecSmrg 4544202a189Smrg glyphSet = dixAllocateObjectWithPrivates(GlyphSetRec, PRIVATE_GLYPHSET); 45505b261ecSmrg if (!glyphSet) 456f7df2e56Smrg return FALSE; 45705b261ecSmrg 458f7df2e56Smrg if (!AllocateGlyphHash(&glyphSet->hash, &glyphHashSets[0])) { 459f7df2e56Smrg free(glyphSet); 460f7df2e56Smrg return FALSE; 46105b261ecSmrg } 46205b261ecSmrg glyphSet->refcnt = 1; 46305b261ecSmrg glyphSet->fdepth = fdepth; 46405b261ecSmrg glyphSet->format = format; 465f7df2e56Smrg return glyphSet; 46605b261ecSmrg} 46705b261ecSmrg 46805b261ecSmrgint 469f7df2e56SmrgFreeGlyphSet(void *value, XID gid) 47005b261ecSmrg{ 471f7df2e56Smrg GlyphSetPtr glyphSet = (GlyphSetPtr) value; 472f7df2e56Smrg 473f7df2e56Smrg if (--glyphSet->refcnt == 0) { 474f7df2e56Smrg CARD32 i, tableSize = glyphSet->hash.hashSet->size; 475f7df2e56Smrg GlyphRefPtr table = glyphSet->hash.table; 476f7df2e56Smrg GlyphPtr glyph; 477f7df2e56Smrg 478f7df2e56Smrg for (i = 0; i < tableSize; i++) { 479f7df2e56Smrg glyph = table[i].glyph; 480f7df2e56Smrg if (glyph && glyph != DeletedGlyph) 481f7df2e56Smrg FreeGlyph(glyph, glyphSet->fdepth); 482f7df2e56Smrg } 483f7df2e56Smrg if (!globalGlyphs[glyphSet->fdepth].tableEntries) { 484f7df2e56Smrg free(globalGlyphs[glyphSet->fdepth].table); 485f7df2e56Smrg globalGlyphs[glyphSet->fdepth].table = 0; 486f7df2e56Smrg globalGlyphs[glyphSet->fdepth].hashSet = 0; 487f7df2e56Smrg } 488f7df2e56Smrg else 489f7df2e56Smrg ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], 0, TRUE); 490f7df2e56Smrg free(table); 491f7df2e56Smrg dixFreeObjectWithPrivates(glyphSet, PRIVATE_GLYPHSET); 49205b261ecSmrg } 49305b261ecSmrg return Success; 49405b261ecSmrg} 4954642e01fSmrg 4964642e01fSmrgstatic void 497f7df2e56SmrgGlyphExtents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents) 4984642e01fSmrg{ 499f7df2e56Smrg int x1, x2, y1, y2; 500f7df2e56Smrg int n; 501f7df2e56Smrg GlyphPtr glyph; 502f7df2e56Smrg int x, y; 503f7df2e56Smrg 5044642e01fSmrg x = 0; 5054642e01fSmrg y = 0; 5064642e01fSmrg extents->x1 = MAXSHORT; 5074642e01fSmrg extents->x2 = MINSHORT; 5084642e01fSmrg extents->y1 = MAXSHORT; 5094642e01fSmrg extents->y2 = MINSHORT; 510f7df2e56Smrg while (nlist--) { 511f7df2e56Smrg x += list->xOff; 512f7df2e56Smrg y += list->yOff; 513f7df2e56Smrg n = list->len; 514f7df2e56Smrg list++; 515f7df2e56Smrg while (n--) { 516f7df2e56Smrg glyph = *glyphs++; 517f7df2e56Smrg x1 = x - glyph->info.x; 518f7df2e56Smrg if (x1 < MINSHORT) 519f7df2e56Smrg x1 = MINSHORT; 520f7df2e56Smrg y1 = y - glyph->info.y; 521f7df2e56Smrg if (y1 < MINSHORT) 522f7df2e56Smrg y1 = MINSHORT; 523f7df2e56Smrg x2 = x1 + glyph->info.width; 524f7df2e56Smrg if (x2 > MAXSHORT) 525f7df2e56Smrg x2 = MAXSHORT; 526f7df2e56Smrg y2 = y1 + glyph->info.height; 527f7df2e56Smrg if (y2 > MAXSHORT) 528f7df2e56Smrg y2 = MAXSHORT; 529f7df2e56Smrg if (x1 < extents->x1) 530f7df2e56Smrg extents->x1 = x1; 531f7df2e56Smrg if (x2 > extents->x2) 532f7df2e56Smrg extents->x2 = x2; 533f7df2e56Smrg if (y1 < extents->y1) 534f7df2e56Smrg extents->y1 = y1; 535f7df2e56Smrg if (y2 > extents->y2) 536f7df2e56Smrg extents->y2 = y2; 537f7df2e56Smrg x += glyph->info.xOff; 538f7df2e56Smrg y += glyph->info.yOff; 539f7df2e56Smrg } 5404642e01fSmrg } 5414642e01fSmrg} 5424642e01fSmrg 5434642e01fSmrg#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) 5444642e01fSmrg 5454202a189Smrgvoid 546f7df2e56SmrgCompositeGlyphs(CARD8 op, 547f7df2e56Smrg PicturePtr pSrc, 548f7df2e56Smrg PicturePtr pDst, 549f7df2e56Smrg PictFormatPtr maskFormat, 550f7df2e56Smrg INT16 xSrc, 551f7df2e56Smrg INT16 ySrc, int nlist, GlyphListPtr lists, GlyphPtr * glyphs) 5524642e01fSmrg{ 553f7df2e56Smrg PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 5544642e01fSmrg 555f7df2e56Smrg ValidatePicture(pSrc); 556f7df2e56Smrg ValidatePicture(pDst); 557f7df2e56Smrg (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, 558f7df2e56Smrg glyphs); 5594642e01fSmrg} 5604642e01fSmrg 5614642e01fSmrgBool 562f7df2e56SmrgmiRealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph) 5634642e01fSmrg{ 5644642e01fSmrg return TRUE; 5654642e01fSmrg} 5664642e01fSmrg 5674642e01fSmrgvoid 568f7df2e56SmrgmiUnrealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph) 5694642e01fSmrg{ 5704642e01fSmrg} 5714642e01fSmrg 5724202a189Smrgvoid 573f7df2e56SmrgmiGlyphs(CARD8 op, 574f7df2e56Smrg PicturePtr pSrc, 575f7df2e56Smrg PicturePtr pDst, 576f7df2e56Smrg PictFormatPtr maskFormat, 577f7df2e56Smrg INT16 xSrc, 578f7df2e56Smrg INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) 5794642e01fSmrg{ 580f7df2e56Smrg PicturePtr pPicture; 581f7df2e56Smrg PixmapPtr pMaskPixmap = 0; 582f7df2e56Smrg PicturePtr pMask; 583f7df2e56Smrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 584f7df2e56Smrg int width = 0, height = 0; 585f7df2e56Smrg int x, y; 586f7df2e56Smrg int xDst = list->xOff, yDst = list->yOff; 587f7df2e56Smrg int n; 588f7df2e56Smrg GlyphPtr glyph; 589f7df2e56Smrg int error; 590f7df2e56Smrg BoxRec extents = { 0, 0, 0, 0 }; 591f7df2e56Smrg CARD32 component_alpha; 592f7df2e56Smrg 593f7df2e56Smrg if (maskFormat) { 594f7df2e56Smrg GCPtr pGC; 595f7df2e56Smrg xRectangle rect; 596f7df2e56Smrg 597f7df2e56Smrg GlyphExtents(nlist, list, glyphs, &extents); 598f7df2e56Smrg 599f7df2e56Smrg if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) 600f7df2e56Smrg return; 601f7df2e56Smrg width = extents.x2 - extents.x1; 602f7df2e56Smrg height = extents.y2 - extents.y1; 603f7df2e56Smrg pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 604f7df2e56Smrg maskFormat->depth, 605f7df2e56Smrg CREATE_PIXMAP_USAGE_SCRATCH); 606f7df2e56Smrg if (!pMaskPixmap) 607f7df2e56Smrg return; 608f7df2e56Smrg component_alpha = NeedsComponent(maskFormat->format); 609f7df2e56Smrg pMask = CreatePicture(0, &pMaskPixmap->drawable, 610f7df2e56Smrg maskFormat, CPComponentAlpha, &component_alpha, 611f7df2e56Smrg serverClient, &error); 612f7df2e56Smrg if (!pMask) { 613f7df2e56Smrg (*pScreen->DestroyPixmap) (pMaskPixmap); 614f7df2e56Smrg return; 615f7df2e56Smrg } 616f7df2e56Smrg pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen); 617f7df2e56Smrg ValidateGC(&pMaskPixmap->drawable, pGC); 618f7df2e56Smrg rect.x = 0; 619f7df2e56Smrg rect.y = 0; 620f7df2e56Smrg rect.width = width; 621f7df2e56Smrg rect.height = height; 622f7df2e56Smrg (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); 623f7df2e56Smrg FreeScratchGC(pGC); 624f7df2e56Smrg x = -extents.x1; 625f7df2e56Smrg y = -extents.y1; 6264642e01fSmrg } 627f7df2e56Smrg else { 628f7df2e56Smrg pMask = pDst; 629f7df2e56Smrg x = 0; 630f7df2e56Smrg y = 0; 6314642e01fSmrg } 632f7df2e56Smrg while (nlist--) { 633f7df2e56Smrg x += list->xOff; 634f7df2e56Smrg y += list->yOff; 635f7df2e56Smrg n = list->len; 636f7df2e56Smrg while (n--) { 637f7df2e56Smrg glyph = *glyphs++; 638f7df2e56Smrg pPicture = GetGlyphPicture(glyph, pScreen); 639f7df2e56Smrg 640f7df2e56Smrg if (pPicture) { 641f7df2e56Smrg if (maskFormat) { 642f7df2e56Smrg CompositePicture(PictOpAdd, 643f7df2e56Smrg pPicture, 644f7df2e56Smrg None, 645f7df2e56Smrg pMask, 646f7df2e56Smrg 0, 0, 647f7df2e56Smrg 0, 0, 648f7df2e56Smrg x - glyph->info.x, 649f7df2e56Smrg y - glyph->info.y, 650f7df2e56Smrg glyph->info.width, glyph->info.height); 651f7df2e56Smrg } 652f7df2e56Smrg else { 653f7df2e56Smrg CompositePicture(op, 654f7df2e56Smrg pSrc, 655f7df2e56Smrg pPicture, 656f7df2e56Smrg pDst, 657f7df2e56Smrg xSrc + (x - glyph->info.x) - xDst, 658f7df2e56Smrg ySrc + (y - glyph->info.y) - yDst, 659f7df2e56Smrg 0, 0, 660f7df2e56Smrg x - glyph->info.x, 661f7df2e56Smrg y - glyph->info.y, 662f7df2e56Smrg glyph->info.width, glyph->info.height); 663f7df2e56Smrg } 664f7df2e56Smrg } 665f7df2e56Smrg 666f7df2e56Smrg x += glyph->info.xOff; 667f7df2e56Smrg y += glyph->info.yOff; 668f7df2e56Smrg } 669f7df2e56Smrg list++; 6704642e01fSmrg } 671f7df2e56Smrg if (maskFormat) { 672f7df2e56Smrg x = extents.x1; 673f7df2e56Smrg y = extents.y1; 674f7df2e56Smrg CompositePicture(op, 675f7df2e56Smrg pSrc, 676f7df2e56Smrg pMask, 677f7df2e56Smrg pDst, 678f7df2e56Smrg xSrc + x - xDst, 679f7df2e56Smrg ySrc + y - yDst, 0, 0, x, y, width, height); 680f7df2e56Smrg FreePicture((void *) pMask, (XID) 0); 681f7df2e56Smrg (*pScreen->DestroyPixmap) (pMaskPixmap); 6824642e01fSmrg } 6834642e01fSmrg} 684f7df2e56Smrg 685f7df2e56SmrgPicturePtr GetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen) 686f7df2e56Smrg{ 687f7df2e56Smrg if (pScreen->isGPU) 688f7df2e56Smrg return NULL; 689f7df2e56Smrg return GlyphPicture(glyph)[pScreen->myNum]; 690f7df2e56Smrg} 691f7df2e56Smrg 692f7df2e56Smrgvoid SetGlyphPicture(GlyphPtr glyph, ScreenPtr pScreen, PicturePtr picture) 693f7df2e56Smrg{ 694f7df2e56Smrg GlyphPicture(glyph)[pScreen->myNum] = picture; 695f7df2e56Smrg} 696