1706f2543Smrg/* 2706f2543Smrg * 3706f2543Smrg * Copyright © 2000 SuSE, Inc. 4706f2543Smrg * 5706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 7706f2543Smrg * the above copyright notice appear in all copies and that both that 8706f2543Smrg * copyright notice and this permission notice appear in supporting 9706f2543Smrg * documentation, and that the name of SuSE not be used in advertising or 10706f2543Smrg * publicity pertaining to distribution of the software without specific, 11706f2543Smrg * written prior permission. SuSE makes no representations about the 12706f2543Smrg * suitability of this software for any purpose. It is provided "as is" 13706f2543Smrg * without express or implied warranty. 14706f2543Smrg * 15706f2543Smrg * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 16706f2543Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 17706f2543Smrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18706f2543Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 19706f2543Smrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 20706f2543Smrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21706f2543Smrg * 22706f2543Smrg * Author: Keith Packard, SuSE, Inc. 23706f2543Smrg */ 24706f2543Smrg 25706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 26706f2543Smrg#include <dix-config.h> 27706f2543Smrg#endif 28706f2543Smrg 29706f2543Smrg#include "xsha1.h" 30706f2543Smrg 31706f2543Smrg#include "misc.h" 32706f2543Smrg#include "scrnintstr.h" 33706f2543Smrg#include "os.h" 34706f2543Smrg#include "regionstr.h" 35706f2543Smrg#include "validate.h" 36706f2543Smrg#include "windowstr.h" 37706f2543Smrg#include "input.h" 38706f2543Smrg#include "resource.h" 39706f2543Smrg#include "colormapst.h" 40706f2543Smrg#include "cursorstr.h" 41706f2543Smrg#include "dixstruct.h" 42706f2543Smrg#include "gcstruct.h" 43706f2543Smrg#include "servermd.h" 44706f2543Smrg#include "picturestr.h" 45706f2543Smrg#include "glyphstr.h" 46706f2543Smrg#include "mipict.h" 47706f2543Smrg 48706f2543Smrg/* 49706f2543Smrg * From Knuth -- a good choice for hash/rehash values is p, p-2 where 50706f2543Smrg * p and p-2 are both prime. These tables are sized to have an extra 10% 51706f2543Smrg * free to avoid exponential performance degradation as the hash table fills 52706f2543Smrg */ 53706f2543Smrgstatic GlyphHashSetRec glyphHashSets[] = { 54706f2543Smrg { 32, 43, 41 }, 55706f2543Smrg { 64, 73, 71 }, 56706f2543Smrg { 128, 151, 149 }, 57706f2543Smrg { 256, 283, 281 }, 58706f2543Smrg { 512, 571, 569 }, 59706f2543Smrg { 1024, 1153, 1151 }, 60706f2543Smrg { 2048, 2269, 2267 }, 61706f2543Smrg { 4096, 4519, 4517 }, 62706f2543Smrg { 8192, 9013, 9011 }, 63706f2543Smrg { 16384, 18043, 18041 }, 64706f2543Smrg { 32768, 36109, 36107 }, 65706f2543Smrg { 65536, 72091, 72089 }, 66706f2543Smrg { 131072, 144409, 144407 }, 67706f2543Smrg { 262144, 288361, 288359 }, 68706f2543Smrg { 524288, 576883, 576881 }, 69706f2543Smrg { 1048576, 1153459, 1153457 }, 70706f2543Smrg { 2097152, 2307163, 2307161 }, 71706f2543Smrg { 4194304, 4613893, 4613891 }, 72706f2543Smrg { 8388608, 9227641, 9227639 }, 73706f2543Smrg { 16777216, 18455029, 18455027 }, 74706f2543Smrg { 33554432, 36911011, 36911009 }, 75706f2543Smrg { 67108864, 73819861, 73819859 }, 76706f2543Smrg { 134217728, 147639589, 147639587 }, 77706f2543Smrg { 268435456, 295279081, 295279079 }, 78706f2543Smrg { 536870912, 590559793, 590559791 } 79706f2543Smrg}; 80706f2543Smrg 81706f2543Smrg#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) 82706f2543Smrg 83706f2543Smrgstatic const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; 84706f2543Smrg 85706f2543Smrgstatic GlyphHashRec globalGlyphs[GlyphFormatNum]; 86706f2543Smrg 87706f2543Smrgvoid 88706f2543SmrgGlyphUninit (ScreenPtr pScreen) 89706f2543Smrg{ 90706f2543Smrg PictureScreenPtr ps = GetPictureScreen (pScreen); 91706f2543Smrg GlyphPtr glyph; 92706f2543Smrg int fdepth, i; 93706f2543Smrg int scrno = pScreen->myNum; 94706f2543Smrg 95706f2543Smrg for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) 96706f2543Smrg { 97706f2543Smrg if (!globalGlyphs[fdepth].hashSet) 98706f2543Smrg continue; 99706f2543Smrg 100706f2543Smrg for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) 101706f2543Smrg { 102706f2543Smrg glyph = globalGlyphs[fdepth].table[i].glyph; 103706f2543Smrg if (glyph && glyph != DeletedGlyph) 104706f2543Smrg { 105706f2543Smrg if (GlyphPicture(glyph)[scrno]) 106706f2543Smrg { 107706f2543Smrg FreePicture ((pointer) GlyphPicture (glyph)[scrno], 0); 108706f2543Smrg GlyphPicture(glyph)[scrno] = NULL; 109706f2543Smrg } 110706f2543Smrg (*ps->UnrealizeGlyph) (pScreen, glyph); 111706f2543Smrg } 112706f2543Smrg } 113706f2543Smrg } 114706f2543Smrg} 115706f2543Smrg 116706f2543SmrgGlyphHashSetPtr 117706f2543SmrgFindGlyphHashSet (CARD32 filled) 118706f2543Smrg{ 119706f2543Smrg int i; 120706f2543Smrg 121706f2543Smrg for (i = 0; i < NGLYPHHASHSETS; i++) 122706f2543Smrg if (glyphHashSets[i].entries >= filled) 123706f2543Smrg return &glyphHashSets[i]; 124706f2543Smrg return 0; 125706f2543Smrg} 126706f2543Smrg 127706f2543SmrgGlyphRefPtr 128706f2543SmrgFindGlyphRef (GlyphHashPtr hash, 129706f2543Smrg CARD32 signature, 130706f2543Smrg Bool match, 131706f2543Smrg unsigned char sha1[20]) 132706f2543Smrg{ 133706f2543Smrg CARD32 elt, step, s; 134706f2543Smrg GlyphPtr glyph; 135706f2543Smrg GlyphRefPtr table, gr, del; 136706f2543Smrg CARD32 tableSize = hash->hashSet->size; 137706f2543Smrg 138706f2543Smrg table = hash->table; 139706f2543Smrg elt = signature % tableSize; 140706f2543Smrg step = 0; 141706f2543Smrg del = 0; 142706f2543Smrg for (;;) 143706f2543Smrg { 144706f2543Smrg gr = &table[elt]; 145706f2543Smrg s = gr->signature; 146706f2543Smrg glyph = gr->glyph; 147706f2543Smrg if (!glyph) 148706f2543Smrg { 149706f2543Smrg if (del) 150706f2543Smrg gr = del; 151706f2543Smrg break; 152706f2543Smrg } 153706f2543Smrg if (glyph == DeletedGlyph) 154706f2543Smrg { 155706f2543Smrg if (!del) 156706f2543Smrg del = gr; 157706f2543Smrg else if (gr == del) 158706f2543Smrg break; 159706f2543Smrg } 160706f2543Smrg else if (s == signature && 161706f2543Smrg (!match || 162706f2543Smrg memcmp (glyph->sha1, sha1, 20) == 0)) 163706f2543Smrg { 164706f2543Smrg break; 165706f2543Smrg } 166706f2543Smrg if (!step) 167706f2543Smrg { 168706f2543Smrg step = signature % hash->hashSet->rehash; 169706f2543Smrg if (!step) 170706f2543Smrg step = 1; 171706f2543Smrg } 172706f2543Smrg elt += step; 173706f2543Smrg if (elt >= tableSize) 174706f2543Smrg elt -= tableSize; 175706f2543Smrg } 176706f2543Smrg return gr; 177706f2543Smrg} 178706f2543Smrg 179706f2543Smrgint 180706f2543SmrgHashGlyph (xGlyphInfo *gi, 181706f2543Smrg CARD8 *bits, 182706f2543Smrg unsigned long size, 183706f2543Smrg unsigned char sha1[20]) 184706f2543Smrg{ 185706f2543Smrg void *ctx = x_sha1_init(); 186706f2543Smrg int success; 187706f2543Smrg 188706f2543Smrg if (!ctx) 189706f2543Smrg return BadAlloc; 190706f2543Smrg 191706f2543Smrg success = x_sha1_update(ctx, gi, sizeof(xGlyphInfo)); 192706f2543Smrg if (!success) 193706f2543Smrg return BadAlloc; 194706f2543Smrg success = x_sha1_update(ctx, bits, size); 195706f2543Smrg if (!success) 196706f2543Smrg return BadAlloc; 197706f2543Smrg success = x_sha1_final(ctx, sha1); 198706f2543Smrg if (!success) 199706f2543Smrg return BadAlloc; 200706f2543Smrg return Success; 201706f2543Smrg} 202706f2543Smrg 203706f2543SmrgGlyphPtr 204706f2543SmrgFindGlyphByHash (unsigned char sha1[20], int format) 205706f2543Smrg{ 206706f2543Smrg GlyphRefPtr gr; 207706f2543Smrg CARD32 signature = *(CARD32 *) sha1; 208706f2543Smrg 209706f2543Smrg if (!globalGlyphs[format].hashSet) 210706f2543Smrg return NULL; 211706f2543Smrg 212706f2543Smrg gr = FindGlyphRef (&globalGlyphs[format], 213706f2543Smrg signature, TRUE, sha1); 214706f2543Smrg 215706f2543Smrg if (gr->glyph && gr->glyph != DeletedGlyph) 216706f2543Smrg return gr->glyph; 217706f2543Smrg else 218706f2543Smrg return NULL; 219706f2543Smrg} 220706f2543Smrg 221706f2543Smrg#ifdef CHECK_DUPLICATES 222706f2543Smrgvoid 223706f2543SmrgDuplicateRef (GlyphPtr glyph, char *where) 224706f2543Smrg{ 225706f2543Smrg ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); 226706f2543Smrg} 227706f2543Smrg 228706f2543Smrgvoid 229706f2543SmrgCheckDuplicates (GlyphHashPtr hash, char *where) 230706f2543Smrg{ 231706f2543Smrg GlyphPtr g; 232706f2543Smrg int i, j; 233706f2543Smrg 234706f2543Smrg for (i = 0; i < hash->hashSet->size; i++) 235706f2543Smrg { 236706f2543Smrg g = hash->table[i].glyph; 237706f2543Smrg if (!g || g == DeletedGlyph) 238706f2543Smrg continue; 239706f2543Smrg for (j = i + 1; j < hash->hashSet->size; j++) 240706f2543Smrg if (hash->table[j].glyph == g) 241706f2543Smrg DuplicateRef (g, where); 242706f2543Smrg } 243706f2543Smrg} 244706f2543Smrg#else 245706f2543Smrg#define CheckDuplicates(a,b) 246706f2543Smrg#define DuplicateRef(a,b) 247706f2543Smrg#endif 248706f2543Smrg 249706f2543Smrgstatic void 250706f2543SmrgFreeGlyphPicture(GlyphPtr glyph) 251706f2543Smrg{ 252706f2543Smrg PictureScreenPtr ps; 253706f2543Smrg int i; 254706f2543Smrg 255706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) 256706f2543Smrg { 257706f2543Smrg ScreenPtr pScreen = screenInfo.screens[i]; 258706f2543Smrg 259706f2543Smrg if (GlyphPicture(glyph)[i]) 260706f2543Smrg FreePicture ((pointer) GlyphPicture (glyph)[i], 0); 261706f2543Smrg 262706f2543Smrg ps = GetPictureScreenIfSet (pScreen); 263706f2543Smrg if (ps) 264706f2543Smrg (*ps->UnrealizeGlyph) (pScreen, glyph); 265706f2543Smrg } 266706f2543Smrg} 267706f2543Smrg 268706f2543Smrg 269706f2543Smrgvoid 270706f2543SmrgFreeGlyph (GlyphPtr glyph, int format) 271706f2543Smrg{ 272706f2543Smrg CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); 273706f2543Smrg if (--glyph->refcnt == 0) 274706f2543Smrg { 275706f2543Smrg GlyphRefPtr gr; 276706f2543Smrg int i; 277706f2543Smrg int first; 278706f2543Smrg CARD32 signature; 279706f2543Smrg 280706f2543Smrg first = -1; 281706f2543Smrg for (i = 0; i < globalGlyphs[format].hashSet->size; i++) 282706f2543Smrg if (globalGlyphs[format].table[i].glyph == glyph) 283706f2543Smrg { 284706f2543Smrg if (first != -1) 285706f2543Smrg DuplicateRef (glyph, "FreeGlyph check"); 286706f2543Smrg first = i; 287706f2543Smrg } 288706f2543Smrg 289706f2543Smrg signature = *(CARD32 *) glyph->sha1; 290706f2543Smrg gr = FindGlyphRef (&globalGlyphs[format], signature, 291706f2543Smrg TRUE, glyph->sha1); 292706f2543Smrg if (gr - globalGlyphs[format].table != first) 293706f2543Smrg DuplicateRef (glyph, "Found wrong one"); 294706f2543Smrg if (gr->glyph && gr->glyph != DeletedGlyph) 295706f2543Smrg { 296706f2543Smrg gr->glyph = DeletedGlyph; 297706f2543Smrg gr->signature = 0; 298706f2543Smrg globalGlyphs[format].tableEntries--; 299706f2543Smrg } 300706f2543Smrg 301706f2543Smrg FreeGlyphPicture(glyph); 302706f2543Smrg dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); 303706f2543Smrg } 304706f2543Smrg} 305706f2543Smrg 306706f2543Smrgvoid 307706f2543SmrgAddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) 308706f2543Smrg{ 309706f2543Smrg GlyphRefPtr gr; 310706f2543Smrg CARD32 signature; 311706f2543Smrg 312706f2543Smrg CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); 313706f2543Smrg /* Locate existing matching glyph */ 314706f2543Smrg signature = *(CARD32 *) glyph->sha1; 315706f2543Smrg gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], signature, 316706f2543Smrg TRUE, glyph->sha1); 317706f2543Smrg if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph) 318706f2543Smrg { 319706f2543Smrg FreeGlyphPicture(glyph); 320706f2543Smrg dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); 321706f2543Smrg glyph = gr->glyph; 322706f2543Smrg } 323706f2543Smrg else if (gr->glyph != glyph) 324706f2543Smrg { 325706f2543Smrg gr->glyph = glyph; 326706f2543Smrg gr->signature = signature; 327706f2543Smrg globalGlyphs[glyphSet->fdepth].tableEntries++; 328706f2543Smrg } 329706f2543Smrg 330706f2543Smrg /* Insert/replace glyphset value */ 331706f2543Smrg gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); 332706f2543Smrg ++glyph->refcnt; 333706f2543Smrg if (gr->glyph && gr->glyph != DeletedGlyph) 334706f2543Smrg FreeGlyph (gr->glyph, glyphSet->fdepth); 335706f2543Smrg else 336706f2543Smrg glyphSet->hash.tableEntries++; 337706f2543Smrg gr->glyph = glyph; 338706f2543Smrg gr->signature = id; 339706f2543Smrg CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); 340706f2543Smrg} 341706f2543Smrg 342706f2543SmrgBool 343706f2543SmrgDeleteGlyph (GlyphSetPtr glyphSet, Glyph id) 344706f2543Smrg{ 345706f2543Smrg GlyphRefPtr gr; 346706f2543Smrg GlyphPtr glyph; 347706f2543Smrg 348706f2543Smrg gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); 349706f2543Smrg glyph = gr->glyph; 350706f2543Smrg if (glyph && glyph != DeletedGlyph) 351706f2543Smrg { 352706f2543Smrg gr->glyph = DeletedGlyph; 353706f2543Smrg glyphSet->hash.tableEntries--; 354706f2543Smrg FreeGlyph (glyph, glyphSet->fdepth); 355706f2543Smrg return TRUE; 356706f2543Smrg } 357706f2543Smrg return FALSE; 358706f2543Smrg} 359706f2543Smrg 360706f2543SmrgGlyphPtr 361706f2543SmrgFindGlyph (GlyphSetPtr glyphSet, Glyph id) 362706f2543Smrg{ 363706f2543Smrg GlyphPtr glyph; 364706f2543Smrg 365706f2543Smrg glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; 366706f2543Smrg if (glyph == DeletedGlyph) 367706f2543Smrg glyph = 0; 368706f2543Smrg return glyph; 369706f2543Smrg} 370706f2543Smrg 371706f2543SmrgGlyphPtr 372706f2543SmrgAllocateGlyph (xGlyphInfo *gi, int fdepth) 373706f2543Smrg{ 374706f2543Smrg PictureScreenPtr ps; 375706f2543Smrg int size; 376706f2543Smrg GlyphPtr glyph; 377706f2543Smrg int i; 378706f2543Smrg int head_size; 379706f2543Smrg 380706f2543Smrg head_size = sizeof (GlyphRec) + screenInfo.numScreens * sizeof (PicturePtr); 381706f2543Smrg size = (head_size + dixPrivatesSize(PRIVATE_GLYPH)); 382706f2543Smrg glyph = (GlyphPtr) malloc (size); 383706f2543Smrg if (!glyph) 384706f2543Smrg return 0; 385706f2543Smrg glyph->refcnt = 0; 386706f2543Smrg glyph->size = size + sizeof (xGlyphInfo); 387706f2543Smrg glyph->info = *gi; 388706f2543Smrg dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH); 389706f2543Smrg 390706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) 391706f2543Smrg { 392706f2543Smrg GlyphPicture(glyph)[i] = NULL; 393706f2543Smrg ps = GetPictureScreenIfSet (screenInfo.screens[i]); 394706f2543Smrg 395706f2543Smrg if (ps) 396706f2543Smrg { 397706f2543Smrg if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph)) 398706f2543Smrg goto bail; 399706f2543Smrg } 400706f2543Smrg } 401706f2543Smrg 402706f2543Smrg return glyph; 403706f2543Smrg 404706f2543Smrgbail: 405706f2543Smrg while (i--) 406706f2543Smrg { 407706f2543Smrg ps = GetPictureScreenIfSet (screenInfo.screens[i]); 408706f2543Smrg if (ps) 409706f2543Smrg (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); 410706f2543Smrg } 411706f2543Smrg 412706f2543Smrg dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); 413706f2543Smrg return 0; 414706f2543Smrg} 415706f2543Smrg 416706f2543SmrgBool 417706f2543SmrgAllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) 418706f2543Smrg{ 419706f2543Smrg hash->table = calloc(hashSet->size, sizeof (GlyphRefRec)); 420706f2543Smrg if (!hash->table) 421706f2543Smrg return FALSE; 422706f2543Smrg hash->hashSet = hashSet; 423706f2543Smrg hash->tableEntries = 0; 424706f2543Smrg return TRUE; 425706f2543Smrg} 426706f2543Smrg 427706f2543SmrgBool 428706f2543SmrgResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) 429706f2543Smrg{ 430706f2543Smrg CARD32 tableEntries; 431706f2543Smrg GlyphHashSetPtr hashSet; 432706f2543Smrg GlyphHashRec newHash; 433706f2543Smrg GlyphRefPtr gr; 434706f2543Smrg GlyphPtr glyph; 435706f2543Smrg int i; 436706f2543Smrg int oldSize; 437706f2543Smrg CARD32 s; 438706f2543Smrg 439706f2543Smrg tableEntries = hash->tableEntries + change; 440706f2543Smrg hashSet = FindGlyphHashSet (tableEntries); 441706f2543Smrg if (hashSet == hash->hashSet) 442706f2543Smrg return TRUE; 443706f2543Smrg if (global) 444706f2543Smrg CheckDuplicates (hash, "ResizeGlyphHash top"); 445706f2543Smrg if (!AllocateGlyphHash (&newHash, hashSet)) 446706f2543Smrg return FALSE; 447706f2543Smrg if (hash->table) 448706f2543Smrg { 449706f2543Smrg oldSize = hash->hashSet->size; 450706f2543Smrg for (i = 0; i < oldSize; i++) 451706f2543Smrg { 452706f2543Smrg glyph = hash->table[i].glyph; 453706f2543Smrg if (glyph && glyph != DeletedGlyph) 454706f2543Smrg { 455706f2543Smrg s = hash->table[i].signature; 456706f2543Smrg gr = FindGlyphRef (&newHash, s, global, glyph->sha1); 457706f2543Smrg gr->signature = s; 458706f2543Smrg gr->glyph = glyph; 459706f2543Smrg ++newHash.tableEntries; 460706f2543Smrg } 461706f2543Smrg } 462706f2543Smrg free(hash->table); 463706f2543Smrg } 464706f2543Smrg *hash = newHash; 465706f2543Smrg if (global) 466706f2543Smrg CheckDuplicates (hash, "ResizeGlyphHash bottom"); 467706f2543Smrg return TRUE; 468706f2543Smrg} 469706f2543Smrg 470706f2543SmrgBool 471706f2543SmrgResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) 472706f2543Smrg{ 473706f2543Smrg return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && 474706f2543Smrg ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); 475706f2543Smrg} 476706f2543Smrg 477706f2543SmrgGlyphSetPtr 478706f2543SmrgAllocateGlyphSet (int fdepth, PictFormatPtr format) 479706f2543Smrg{ 480706f2543Smrg GlyphSetPtr glyphSet; 481706f2543Smrg 482706f2543Smrg if (!globalGlyphs[fdepth].hashSet) 483706f2543Smrg { 484706f2543Smrg if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) 485706f2543Smrg return FALSE; 486706f2543Smrg } 487706f2543Smrg 488706f2543Smrg glyphSet = dixAllocateObjectWithPrivates(GlyphSetRec, PRIVATE_GLYPHSET); 489706f2543Smrg if (!glyphSet) 490706f2543Smrg return FALSE; 491706f2543Smrg 492706f2543Smrg if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) 493706f2543Smrg { 494706f2543Smrg free(glyphSet); 495706f2543Smrg return FALSE; 496706f2543Smrg } 497706f2543Smrg glyphSet->refcnt = 1; 498706f2543Smrg glyphSet->fdepth = fdepth; 499706f2543Smrg glyphSet->format = format; 500706f2543Smrg return glyphSet; 501706f2543Smrg} 502706f2543Smrg 503706f2543Smrgint 504706f2543SmrgFreeGlyphSet (pointer value, 505706f2543Smrg XID gid) 506706f2543Smrg{ 507706f2543Smrg GlyphSetPtr glyphSet = (GlyphSetPtr) value; 508706f2543Smrg 509706f2543Smrg if (--glyphSet->refcnt == 0) 510706f2543Smrg { 511706f2543Smrg CARD32 i, tableSize = glyphSet->hash.hashSet->size; 512706f2543Smrg GlyphRefPtr table = glyphSet->hash.table; 513706f2543Smrg GlyphPtr glyph; 514706f2543Smrg 515706f2543Smrg for (i = 0; i < tableSize; i++) 516706f2543Smrg { 517706f2543Smrg glyph = table[i].glyph; 518706f2543Smrg if (glyph && glyph != DeletedGlyph) 519706f2543Smrg FreeGlyph (glyph, glyphSet->fdepth); 520706f2543Smrg } 521706f2543Smrg if (!globalGlyphs[glyphSet->fdepth].tableEntries) 522706f2543Smrg { 523706f2543Smrg free(globalGlyphs[glyphSet->fdepth].table); 524706f2543Smrg globalGlyphs[glyphSet->fdepth].table = 0; 525706f2543Smrg globalGlyphs[glyphSet->fdepth].hashSet = 0; 526706f2543Smrg } 527706f2543Smrg else 528706f2543Smrg ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); 529706f2543Smrg free(table); 530706f2543Smrg dixFreeObjectWithPrivates(glyphSet, PRIVATE_GLYPHSET); 531706f2543Smrg } 532706f2543Smrg return Success; 533706f2543Smrg} 534706f2543Smrg 535706f2543Smrgstatic void 536706f2543SmrgGlyphExtents (int nlist, 537706f2543Smrg GlyphListPtr list, 538706f2543Smrg GlyphPtr *glyphs, 539706f2543Smrg BoxPtr extents) 540706f2543Smrg{ 541706f2543Smrg int x1, x2, y1, y2; 542706f2543Smrg int n; 543706f2543Smrg GlyphPtr glyph; 544706f2543Smrg int x, y; 545706f2543Smrg 546706f2543Smrg x = 0; 547706f2543Smrg y = 0; 548706f2543Smrg extents->x1 = MAXSHORT; 549706f2543Smrg extents->x2 = MINSHORT; 550706f2543Smrg extents->y1 = MAXSHORT; 551706f2543Smrg extents->y2 = MINSHORT; 552706f2543Smrg while (nlist--) 553706f2543Smrg { 554706f2543Smrg x += list->xOff; 555706f2543Smrg y += list->yOff; 556706f2543Smrg n = list->len; 557706f2543Smrg list++; 558706f2543Smrg while (n--) 559706f2543Smrg { 560706f2543Smrg glyph = *glyphs++; 561706f2543Smrg x1 = x - glyph->info.x; 562706f2543Smrg if (x1 < MINSHORT) 563706f2543Smrg x1 = MINSHORT; 564706f2543Smrg y1 = y - glyph->info.y; 565706f2543Smrg if (y1 < MINSHORT) 566706f2543Smrg y1 = MINSHORT; 567706f2543Smrg x2 = x1 + glyph->info.width; 568706f2543Smrg if (x2 > MAXSHORT) 569706f2543Smrg x2 = MAXSHORT; 570706f2543Smrg y2 = y1 + glyph->info.height; 571706f2543Smrg if (y2 > MAXSHORT) 572706f2543Smrg y2 = MAXSHORT; 573706f2543Smrg if (x1 < extents->x1) 574706f2543Smrg extents->x1 = x1; 575706f2543Smrg if (x2 > extents->x2) 576706f2543Smrg extents->x2 = x2; 577706f2543Smrg if (y1 < extents->y1) 578706f2543Smrg extents->y1 = y1; 579706f2543Smrg if (y2 > extents->y2) 580706f2543Smrg extents->y2 = y2; 581706f2543Smrg x += glyph->info.xOff; 582706f2543Smrg y += glyph->info.yOff; 583706f2543Smrg } 584706f2543Smrg } 585706f2543Smrg} 586706f2543Smrg 587706f2543Smrg#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) 588706f2543Smrg 589706f2543Smrgvoid 590706f2543SmrgCompositeGlyphs (CARD8 op, 591706f2543Smrg PicturePtr pSrc, 592706f2543Smrg PicturePtr pDst, 593706f2543Smrg PictFormatPtr maskFormat, 594706f2543Smrg INT16 xSrc, 595706f2543Smrg INT16 ySrc, 596706f2543Smrg int nlist, 597706f2543Smrg GlyphListPtr lists, 598706f2543Smrg GlyphPtr *glyphs) 599706f2543Smrg{ 600706f2543Smrg PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 601706f2543Smrg 602706f2543Smrg ValidatePicture (pSrc); 603706f2543Smrg ValidatePicture (pDst); 604706f2543Smrg (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); 605706f2543Smrg} 606706f2543Smrg 607706f2543SmrgBool 608706f2543SmrgmiRealizeGlyph (ScreenPtr pScreen, 609706f2543Smrg GlyphPtr glyph) 610706f2543Smrg{ 611706f2543Smrg return TRUE; 612706f2543Smrg} 613706f2543Smrg 614706f2543Smrgvoid 615706f2543SmrgmiUnrealizeGlyph (ScreenPtr pScreen, 616706f2543Smrg GlyphPtr glyph) 617706f2543Smrg{ 618706f2543Smrg} 619706f2543Smrg 620706f2543Smrgvoid 621706f2543SmrgmiGlyphs (CARD8 op, 622706f2543Smrg PicturePtr pSrc, 623706f2543Smrg PicturePtr pDst, 624706f2543Smrg PictFormatPtr maskFormat, 625706f2543Smrg INT16 xSrc, 626706f2543Smrg INT16 ySrc, 627706f2543Smrg int nlist, 628706f2543Smrg GlyphListPtr list, 629706f2543Smrg GlyphPtr *glyphs) 630706f2543Smrg{ 631706f2543Smrg PicturePtr pPicture; 632706f2543Smrg PixmapPtr pMaskPixmap = 0; 633706f2543Smrg PicturePtr pMask; 634706f2543Smrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 635706f2543Smrg int width = 0, height = 0; 636706f2543Smrg int x, y; 637706f2543Smrg int xDst = list->xOff, yDst = list->yOff; 638706f2543Smrg int n; 639706f2543Smrg GlyphPtr glyph; 640706f2543Smrg int error; 641706f2543Smrg BoxRec extents = {0, 0, 0, 0}; 642706f2543Smrg CARD32 component_alpha; 643706f2543Smrg 644706f2543Smrg if (maskFormat) 645706f2543Smrg { 646706f2543Smrg GCPtr pGC; 647706f2543Smrg xRectangle rect; 648706f2543Smrg 649706f2543Smrg GlyphExtents (nlist, list, glyphs, &extents); 650706f2543Smrg 651706f2543Smrg if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) 652706f2543Smrg return; 653706f2543Smrg width = extents.x2 - extents.x1; 654706f2543Smrg height = extents.y2 - extents.y1; 655706f2543Smrg pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 656706f2543Smrg maskFormat->depth, 657706f2543Smrg CREATE_PIXMAP_USAGE_SCRATCH); 658706f2543Smrg if (!pMaskPixmap) 659706f2543Smrg return; 660706f2543Smrg component_alpha = NeedsComponent(maskFormat->format); 661706f2543Smrg pMask = CreatePicture (0, &pMaskPixmap->drawable, 662706f2543Smrg maskFormat, CPComponentAlpha, &component_alpha, 663706f2543Smrg serverClient, &error); 664706f2543Smrg if (!pMask) 665706f2543Smrg { 666706f2543Smrg (*pScreen->DestroyPixmap) (pMaskPixmap); 667706f2543Smrg return; 668706f2543Smrg } 669706f2543Smrg pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); 670706f2543Smrg ValidateGC (&pMaskPixmap->drawable, pGC); 671706f2543Smrg rect.x = 0; 672706f2543Smrg rect.y = 0; 673706f2543Smrg rect.width = width; 674706f2543Smrg rect.height = height; 675706f2543Smrg (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); 676706f2543Smrg FreeScratchGC (pGC); 677706f2543Smrg x = -extents.x1; 678706f2543Smrg y = -extents.y1; 679706f2543Smrg } 680706f2543Smrg else 681706f2543Smrg { 682706f2543Smrg pMask = pDst; 683706f2543Smrg x = 0; 684706f2543Smrg y = 0; 685706f2543Smrg } 686706f2543Smrg while (nlist--) 687706f2543Smrg { 688706f2543Smrg x += list->xOff; 689706f2543Smrg y += list->yOff; 690706f2543Smrg n = list->len; 691706f2543Smrg while (n--) 692706f2543Smrg { 693706f2543Smrg glyph = *glyphs++; 694706f2543Smrg pPicture = GlyphPicture (glyph)[pScreen->myNum]; 695706f2543Smrg 696706f2543Smrg if (pPicture) 697706f2543Smrg { 698706f2543Smrg if (maskFormat) 699706f2543Smrg { 700706f2543Smrg CompositePicture (PictOpAdd, 701706f2543Smrg pPicture, 702706f2543Smrg None, 703706f2543Smrg pMask, 704706f2543Smrg 0, 0, 705706f2543Smrg 0, 0, 706706f2543Smrg x - glyph->info.x, 707706f2543Smrg y - glyph->info.y, 708706f2543Smrg glyph->info.width, 709706f2543Smrg glyph->info.height); 710706f2543Smrg } 711706f2543Smrg else 712706f2543Smrg { 713706f2543Smrg CompositePicture (op, 714706f2543Smrg pSrc, 715706f2543Smrg pPicture, 716706f2543Smrg pDst, 717706f2543Smrg xSrc + (x - glyph->info.x) - xDst, 718706f2543Smrg ySrc + (y - glyph->info.y) - yDst, 719706f2543Smrg 0, 0, 720706f2543Smrg x - glyph->info.x, 721706f2543Smrg y - glyph->info.y, 722706f2543Smrg glyph->info.width, 723706f2543Smrg glyph->info.height); 724706f2543Smrg } 725706f2543Smrg } 726706f2543Smrg 727706f2543Smrg x += glyph->info.xOff; 728706f2543Smrg y += glyph->info.yOff; 729706f2543Smrg } 730706f2543Smrg list++; 731706f2543Smrg } 732706f2543Smrg if (maskFormat) 733706f2543Smrg { 734706f2543Smrg x = extents.x1; 735706f2543Smrg y = extents.y1; 736706f2543Smrg CompositePicture (op, 737706f2543Smrg pSrc, 738706f2543Smrg pMask, 739706f2543Smrg pDst, 740706f2543Smrg xSrc + x - xDst, 741706f2543Smrg ySrc + y - yDst, 742706f2543Smrg 0, 0, 743706f2543Smrg x, y, 744706f2543Smrg width, height); 745706f2543Smrg FreePicture ((pointer) pMask, (XID) 0); 746706f2543Smrg (*pScreen->DestroyPixmap) (pMaskPixmap); 747706f2543Smrg } 748706f2543Smrg} 749