glyph.c revision 4642e01f
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 1905b261ecSmrg * 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 294642e01fSmrg#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */ 304642e01fSmrg# include <sha1.h> 314642e01fSmrg#else /* Use OpenSSL's libcrypto */ 324642e01fSmrg# include <stddef.h> /* buggy openssl/sha.h wants size_t */ 334642e01fSmrg# include <openssl/sha.h> 344642e01fSmrg#endif 354642e01fSmrg 3605b261ecSmrg#include "misc.h" 3705b261ecSmrg#include "scrnintstr.h" 3805b261ecSmrg#include "os.h" 3905b261ecSmrg#include "regionstr.h" 4005b261ecSmrg#include "validate.h" 4105b261ecSmrg#include "windowstr.h" 4205b261ecSmrg#include "input.h" 4305b261ecSmrg#include "resource.h" 4405b261ecSmrg#include "colormapst.h" 4505b261ecSmrg#include "cursorstr.h" 4605b261ecSmrg#include "dixstruct.h" 4705b261ecSmrg#include "gcstruct.h" 4805b261ecSmrg#include "servermd.h" 4905b261ecSmrg#include "picturestr.h" 5005b261ecSmrg#include "glyphstr.h" 514642e01fSmrg#include "mipict.h" 5205b261ecSmrg 5305b261ecSmrg/* 5405b261ecSmrg * From Knuth -- a good choice for hash/rehash values is p, p-2 where 5505b261ecSmrg * p and p-2 are both prime. These tables are sized to have an extra 10% 5605b261ecSmrg * free to avoid exponential performance degradation as the hash table fills 5705b261ecSmrg */ 5805b261ecSmrgstatic GlyphHashSetRec glyphHashSets[] = { 5905b261ecSmrg { 32, 43, 41 }, 6005b261ecSmrg { 64, 73, 71 }, 6105b261ecSmrg { 128, 151, 149 }, 6205b261ecSmrg { 256, 283, 281 }, 6305b261ecSmrg { 512, 571, 569 }, 6405b261ecSmrg { 1024, 1153, 1151 }, 6505b261ecSmrg { 2048, 2269, 2267 }, 6605b261ecSmrg { 4096, 4519, 4517 }, 6705b261ecSmrg { 8192, 9013, 9011 }, 6805b261ecSmrg { 16384, 18043, 18041 }, 6905b261ecSmrg { 32768, 36109, 36107 }, 7005b261ecSmrg { 65536, 72091, 72089 }, 7105b261ecSmrg { 131072, 144409, 144407 }, 7205b261ecSmrg { 262144, 288361, 288359 }, 7305b261ecSmrg { 524288, 576883, 576881 }, 7405b261ecSmrg { 1048576, 1153459, 1153457 }, 7505b261ecSmrg { 2097152, 2307163, 2307161 }, 7605b261ecSmrg { 4194304, 4613893, 4613891 }, 7705b261ecSmrg { 8388608, 9227641, 9227639 }, 7805b261ecSmrg { 16777216, 18455029, 18455027 }, 7905b261ecSmrg { 33554432, 36911011, 36911009 }, 8005b261ecSmrg { 67108864, 73819861, 73819859 }, 8105b261ecSmrg { 134217728, 147639589, 147639587 }, 8205b261ecSmrg { 268435456, 295279081, 295279079 }, 8305b261ecSmrg { 536870912, 590559793, 590559791 } 8405b261ecSmrg}; 8505b261ecSmrg 8605b261ecSmrg#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) 8705b261ecSmrg 8805b261ecSmrgstatic const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; 8905b261ecSmrg 9005b261ecSmrgstatic GlyphHashRec globalGlyphs[GlyphFormatNum]; 9105b261ecSmrg 9205b261ecSmrgstatic void 934642e01fSmrgFreeGlyphPrivates (GlyphPtr glyph) 9405b261ecSmrg{ 954642e01fSmrg dixFreePrivates(glyph->devPrivates); 964642e01fSmrg glyph->devPrivates = NULL; 9705b261ecSmrg} 9805b261ecSmrg 9905b261ecSmrgvoid 10005b261ecSmrgGlyphUninit (ScreenPtr pScreen) 10105b261ecSmrg{ 10205b261ecSmrg PictureScreenPtr ps = GetPictureScreen (pScreen); 10305b261ecSmrg GlyphPtr glyph; 10405b261ecSmrg int fdepth, i; 10505b261ecSmrg 10605b261ecSmrg for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) 10705b261ecSmrg { 10805b261ecSmrg if (!globalGlyphs[fdepth].hashSet) 10905b261ecSmrg continue; 11005b261ecSmrg 11105b261ecSmrg for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) 11205b261ecSmrg { 11305b261ecSmrg glyph = globalGlyphs[fdepth].table[i].glyph; 11405b261ecSmrg if (glyph && glyph != DeletedGlyph) 11505b261ecSmrg { 11605b261ecSmrg (*ps->UnrealizeGlyph) (pScreen, glyph); 1174642e01fSmrg FreeGlyphPrivates(glyph); 11805b261ecSmrg } 11905b261ecSmrg } 12005b261ecSmrg } 12105b261ecSmrg 12205b261ecSmrg for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) 12305b261ecSmrg { 12405b261ecSmrg if (!globalGlyphs[fdepth].hashSet) 12505b261ecSmrg continue; 12605b261ecSmrg 12705b261ecSmrg for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) 12805b261ecSmrg glyph = globalGlyphs[fdepth].table[i].glyph; 12905b261ecSmrg } 13005b261ecSmrg} 13105b261ecSmrg 13205b261ecSmrgGlyphHashSetPtr 13305b261ecSmrgFindGlyphHashSet (CARD32 filled) 13405b261ecSmrg{ 13505b261ecSmrg int i; 13605b261ecSmrg 13705b261ecSmrg for (i = 0; i < NGLYPHHASHSETS; i++) 13805b261ecSmrg if (glyphHashSets[i].entries >= filled) 13905b261ecSmrg return &glyphHashSets[i]; 14005b261ecSmrg return 0; 14105b261ecSmrg} 14205b261ecSmrg 14305b261ecSmrgGlyphRefPtr 1444642e01fSmrgFindGlyphRef (GlyphHashPtr hash, 1454642e01fSmrg CARD32 signature, 1464642e01fSmrg Bool match, 1474642e01fSmrg unsigned char sha1[20]) 14805b261ecSmrg{ 14905b261ecSmrg CARD32 elt, step, s; 15005b261ecSmrg GlyphPtr glyph; 15105b261ecSmrg GlyphRefPtr table, gr, del; 15205b261ecSmrg CARD32 tableSize = hash->hashSet->size; 15305b261ecSmrg 15405b261ecSmrg table = hash->table; 15505b261ecSmrg elt = signature % tableSize; 15605b261ecSmrg step = 0; 15705b261ecSmrg del = 0; 15805b261ecSmrg for (;;) 15905b261ecSmrg { 16005b261ecSmrg gr = &table[elt]; 16105b261ecSmrg s = gr->signature; 16205b261ecSmrg glyph = gr->glyph; 16305b261ecSmrg if (!glyph) 16405b261ecSmrg { 16505b261ecSmrg if (del) 16605b261ecSmrg gr = del; 16705b261ecSmrg break; 16805b261ecSmrg } 16905b261ecSmrg if (glyph == DeletedGlyph) 17005b261ecSmrg { 17105b261ecSmrg if (!del) 17205b261ecSmrg del = gr; 17305b261ecSmrg else if (gr == del) 17405b261ecSmrg break; 17505b261ecSmrg } 17605b261ecSmrg else if (s == signature && 17705b261ecSmrg (!match || 1784642e01fSmrg memcmp (glyph->sha1, sha1, 20) == 0)) 17905b261ecSmrg { 18005b261ecSmrg break; 18105b261ecSmrg } 18205b261ecSmrg if (!step) 18305b261ecSmrg { 18405b261ecSmrg step = signature % hash->hashSet->rehash; 18505b261ecSmrg if (!step) 18605b261ecSmrg step = 1; 18705b261ecSmrg } 18805b261ecSmrg elt += step; 18905b261ecSmrg if (elt >= tableSize) 19005b261ecSmrg elt -= tableSize; 19105b261ecSmrg } 19205b261ecSmrg return gr; 19305b261ecSmrg} 19405b261ecSmrg 1954642e01fSmrgint 1964642e01fSmrgHashGlyph (xGlyphInfo *gi, 1974642e01fSmrg CARD8 *bits, 1984642e01fSmrg unsigned long size, 1994642e01fSmrg unsigned char sha1[20]) 20005b261ecSmrg{ 2014642e01fSmrg#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */ 2024642e01fSmrg SHA1_CTX ctx; 2034642e01fSmrg 2044642e01fSmrg SHA1Init (&ctx); 2054642e01fSmrg SHA1Update (&ctx, gi, sizeof (xGlyphInfo)); 2064642e01fSmrg SHA1Update (&ctx, bits, size); 2074642e01fSmrg SHA1Final (sha1, &ctx); 2084642e01fSmrg#else /* Use OpenSSL's libcrypto */ 2094642e01fSmrg SHA_CTX ctx; 2104642e01fSmrg int success; 2114642e01fSmrg 2124642e01fSmrg success = SHA1_Init (&ctx); 2134642e01fSmrg if (! success) 2144642e01fSmrg return BadAlloc; 2154642e01fSmrg 2164642e01fSmrg success = SHA1_Update (&ctx, gi, sizeof (xGlyphInfo)); 2174642e01fSmrg if (! success) 2184642e01fSmrg return BadAlloc; 2194642e01fSmrg 2204642e01fSmrg success = SHA1_Update (&ctx, bits, size); 2214642e01fSmrg if (! success) 2224642e01fSmrg return BadAlloc; 2234642e01fSmrg 2244642e01fSmrg success = SHA1_Final (sha1, &ctx); 2254642e01fSmrg if (! success) 2264642e01fSmrg return BadAlloc; 2274642e01fSmrg#endif 2284642e01fSmrg 2294642e01fSmrg return Success; 2304642e01fSmrg} 2314642e01fSmrg 2324642e01fSmrgGlyphPtr 2334642e01fSmrgFindGlyphByHash (unsigned char sha1[20], int format) 2344642e01fSmrg{ 2354642e01fSmrg GlyphRefPtr gr; 2364642e01fSmrg CARD32 signature = *(CARD32 *) sha1; 2374642e01fSmrg 2384642e01fSmrg gr = FindGlyphRef (&globalGlyphs[format], 2394642e01fSmrg signature, TRUE, sha1); 2404642e01fSmrg 2414642e01fSmrg if (gr->glyph && gr->glyph != DeletedGlyph) 2424642e01fSmrg return gr->glyph; 2434642e01fSmrg else 2444642e01fSmrg return NULL; 24505b261ecSmrg} 24605b261ecSmrg 24705b261ecSmrg#ifdef CHECK_DUPLICATES 24805b261ecSmrgvoid 24905b261ecSmrgDuplicateRef (GlyphPtr glyph, char *where) 25005b261ecSmrg{ 25105b261ecSmrg ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); 25205b261ecSmrg} 25305b261ecSmrg 25405b261ecSmrgvoid 25505b261ecSmrgCheckDuplicates (GlyphHashPtr hash, char *where) 25605b261ecSmrg{ 25705b261ecSmrg GlyphPtr g; 25805b261ecSmrg int i, j; 25905b261ecSmrg 26005b261ecSmrg for (i = 0; i < hash->hashSet->size; i++) 26105b261ecSmrg { 26205b261ecSmrg g = hash->table[i].glyph; 26305b261ecSmrg if (!g || g == DeletedGlyph) 26405b261ecSmrg continue; 26505b261ecSmrg for (j = i + 1; j < hash->hashSet->size; j++) 26605b261ecSmrg if (hash->table[j].glyph == g) 26705b261ecSmrg DuplicateRef (g, where); 26805b261ecSmrg } 26905b261ecSmrg} 27005b261ecSmrg#else 27105b261ecSmrg#define CheckDuplicates(a,b) 27205b261ecSmrg#define DuplicateRef(a,b) 27305b261ecSmrg#endif 27405b261ecSmrg 27505b261ecSmrgvoid 27605b261ecSmrgFreeGlyph (GlyphPtr glyph, int format) 27705b261ecSmrg{ 27805b261ecSmrg CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); 27905b261ecSmrg if (--glyph->refcnt == 0) 28005b261ecSmrg { 28105b261ecSmrg PictureScreenPtr ps; 28205b261ecSmrg GlyphRefPtr gr; 28305b261ecSmrg int i; 28405b261ecSmrg int first; 2854642e01fSmrg CARD32 signature; 28605b261ecSmrg 28705b261ecSmrg first = -1; 28805b261ecSmrg for (i = 0; i < globalGlyphs[format].hashSet->size; i++) 28905b261ecSmrg if (globalGlyphs[format].table[i].glyph == glyph) 29005b261ecSmrg { 29105b261ecSmrg if (first != -1) 29205b261ecSmrg DuplicateRef (glyph, "FreeGlyph check"); 29305b261ecSmrg first = i; 29405b261ecSmrg } 29505b261ecSmrg 2964642e01fSmrg signature = *(CARD32 *) glyph->sha1; 2974642e01fSmrg gr = FindGlyphRef (&globalGlyphs[format], signature, 2984642e01fSmrg TRUE, glyph->sha1); 29905b261ecSmrg if (gr - globalGlyphs[format].table != first) 30005b261ecSmrg DuplicateRef (glyph, "Found wrong one"); 30105b261ecSmrg if (gr->glyph && gr->glyph != DeletedGlyph) 30205b261ecSmrg { 30305b261ecSmrg gr->glyph = DeletedGlyph; 30405b261ecSmrg gr->signature = 0; 30505b261ecSmrg globalGlyphs[format].tableEntries--; 30605b261ecSmrg } 30705b261ecSmrg 30805b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) 30905b261ecSmrg { 3104642e01fSmrg ScreenPtr pScreen = screenInfo.screens[i]; 3114642e01fSmrg 3124642e01fSmrg FreePicture ((pointer) GlyphPicture (glyph)[i], 0); 3134642e01fSmrg 3144642e01fSmrg ps = GetPictureScreenIfSet (pScreen); 31505b261ecSmrg if (ps) 3164642e01fSmrg (*ps->UnrealizeGlyph) (pScreen, glyph); 31705b261ecSmrg } 31805b261ecSmrg 3194642e01fSmrg FreeGlyphPrivates(glyph); 32005b261ecSmrg xfree (glyph); 32105b261ecSmrg } 32205b261ecSmrg} 32305b261ecSmrg 32405b261ecSmrgvoid 32505b261ecSmrgAddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) 32605b261ecSmrg{ 32705b261ecSmrg GlyphRefPtr gr; 3284642e01fSmrg CARD32 signature; 32905b261ecSmrg 33005b261ecSmrg CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); 33105b261ecSmrg /* Locate existing matching glyph */ 3324642e01fSmrg signature = *(CARD32 *) glyph->sha1; 3334642e01fSmrg gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], signature, 3344642e01fSmrg TRUE, glyph->sha1); 3354642e01fSmrg if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph) 33605b261ecSmrg { 33705b261ecSmrg PictureScreenPtr ps; 33805b261ecSmrg int i; 33905b261ecSmrg 34005b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) 34105b261ecSmrg { 34205b261ecSmrg ps = GetPictureScreenIfSet (screenInfo.screens[i]); 34305b261ecSmrg if (ps) 34405b261ecSmrg (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); 34505b261ecSmrg } 3464642e01fSmrg FreeGlyphPrivates(glyph); 34705b261ecSmrg xfree (glyph); 34805b261ecSmrg glyph = gr->glyph; 34905b261ecSmrg } 3504642e01fSmrg else if (gr->glyph != glyph) 35105b261ecSmrg { 35205b261ecSmrg gr->glyph = glyph; 3534642e01fSmrg gr->signature = signature; 35405b261ecSmrg globalGlyphs[glyphSet->fdepth].tableEntries++; 35505b261ecSmrg } 35605b261ecSmrg 35705b261ecSmrg /* Insert/replace glyphset value */ 35805b261ecSmrg gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); 35905b261ecSmrg ++glyph->refcnt; 36005b261ecSmrg if (gr->glyph && gr->glyph != DeletedGlyph) 36105b261ecSmrg FreeGlyph (gr->glyph, glyphSet->fdepth); 36205b261ecSmrg else 36305b261ecSmrg glyphSet->hash.tableEntries++; 36405b261ecSmrg gr->glyph = glyph; 36505b261ecSmrg gr->signature = id; 36605b261ecSmrg CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); 36705b261ecSmrg} 36805b261ecSmrg 36905b261ecSmrgBool 37005b261ecSmrgDeleteGlyph (GlyphSetPtr glyphSet, Glyph id) 37105b261ecSmrg{ 37205b261ecSmrg GlyphRefPtr gr; 37305b261ecSmrg GlyphPtr glyph; 37405b261ecSmrg 37505b261ecSmrg gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); 37605b261ecSmrg glyph = gr->glyph; 37705b261ecSmrg if (glyph && glyph != DeletedGlyph) 37805b261ecSmrg { 37905b261ecSmrg gr->glyph = DeletedGlyph; 38005b261ecSmrg glyphSet->hash.tableEntries--; 38105b261ecSmrg FreeGlyph (glyph, glyphSet->fdepth); 38205b261ecSmrg return TRUE; 38305b261ecSmrg } 38405b261ecSmrg return FALSE; 38505b261ecSmrg} 38605b261ecSmrg 38705b261ecSmrgGlyphPtr 38805b261ecSmrgFindGlyph (GlyphSetPtr glyphSet, Glyph id) 38905b261ecSmrg{ 39005b261ecSmrg GlyphPtr glyph; 39105b261ecSmrg 39205b261ecSmrg glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; 39305b261ecSmrg if (glyph == DeletedGlyph) 39405b261ecSmrg glyph = 0; 39505b261ecSmrg return glyph; 39605b261ecSmrg} 39705b261ecSmrg 39805b261ecSmrgGlyphPtr 39905b261ecSmrgAllocateGlyph (xGlyphInfo *gi, int fdepth) 40005b261ecSmrg{ 40105b261ecSmrg PictureScreenPtr ps; 40205b261ecSmrg int size; 40305b261ecSmrg GlyphPtr glyph; 40405b261ecSmrg int i; 4054642e01fSmrg 4064642e01fSmrg size = screenInfo.numScreens * sizeof (PicturePtr); 40705b261ecSmrg glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); 40805b261ecSmrg if (!glyph) 40905b261ecSmrg return 0; 41005b261ecSmrg glyph->refcnt = 0; 41105b261ecSmrg glyph->size = size + sizeof (xGlyphInfo); 41205b261ecSmrg glyph->info = *gi; 4134642e01fSmrg glyph->devPrivates = NULL; 41405b261ecSmrg 41505b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) 41605b261ecSmrg { 41705b261ecSmrg ps = GetPictureScreenIfSet (screenInfo.screens[i]); 4184642e01fSmrg 41905b261ecSmrg if (ps) 42005b261ecSmrg { 42105b261ecSmrg if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph)) 4224642e01fSmrg goto bail; 42305b261ecSmrg } 42405b261ecSmrg } 42505b261ecSmrg 42605b261ecSmrg return glyph; 4274642e01fSmrg 4284642e01fSmrgbail: 4294642e01fSmrg while (i--) 4304642e01fSmrg { 4314642e01fSmrg ps = GetPictureScreenIfSet (screenInfo.screens[i]); 4324642e01fSmrg if (ps) 4334642e01fSmrg (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); 4344642e01fSmrg } 4354642e01fSmrg 4364642e01fSmrg FreeGlyphPrivates(glyph); 4374642e01fSmrg xfree (glyph); 4384642e01fSmrg return 0; 43905b261ecSmrg} 44005b261ecSmrg 44105b261ecSmrgBool 44205b261ecSmrgAllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) 44305b261ecSmrg{ 4444642e01fSmrg hash->table = xcalloc (hashSet->size, sizeof (GlyphRefRec)); 44505b261ecSmrg if (!hash->table) 44605b261ecSmrg return FALSE; 44705b261ecSmrg hash->hashSet = hashSet; 44805b261ecSmrg hash->tableEntries = 0; 44905b261ecSmrg return TRUE; 45005b261ecSmrg} 45105b261ecSmrg 45205b261ecSmrgBool 45305b261ecSmrgResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) 45405b261ecSmrg{ 45505b261ecSmrg CARD32 tableEntries; 45605b261ecSmrg GlyphHashSetPtr hashSet; 45705b261ecSmrg GlyphHashRec newHash; 45805b261ecSmrg GlyphRefPtr gr; 45905b261ecSmrg GlyphPtr glyph; 46005b261ecSmrg int i; 46105b261ecSmrg int oldSize; 46205b261ecSmrg CARD32 s; 46305b261ecSmrg 46405b261ecSmrg tableEntries = hash->tableEntries + change; 46505b261ecSmrg hashSet = FindGlyphHashSet (tableEntries); 46605b261ecSmrg if (hashSet == hash->hashSet) 46705b261ecSmrg return TRUE; 46805b261ecSmrg if (global) 46905b261ecSmrg CheckDuplicates (hash, "ResizeGlyphHash top"); 47005b261ecSmrg if (!AllocateGlyphHash (&newHash, hashSet)) 47105b261ecSmrg return FALSE; 47205b261ecSmrg if (hash->table) 47305b261ecSmrg { 47405b261ecSmrg oldSize = hash->hashSet->size; 47505b261ecSmrg for (i = 0; i < oldSize; i++) 47605b261ecSmrg { 47705b261ecSmrg glyph = hash->table[i].glyph; 47805b261ecSmrg if (glyph && glyph != DeletedGlyph) 47905b261ecSmrg { 48005b261ecSmrg s = hash->table[i].signature; 4814642e01fSmrg gr = FindGlyphRef (&newHash, s, global, glyph->sha1); 48205b261ecSmrg gr->signature = s; 48305b261ecSmrg gr->glyph = glyph; 48405b261ecSmrg ++newHash.tableEntries; 48505b261ecSmrg } 48605b261ecSmrg } 48705b261ecSmrg xfree (hash->table); 48805b261ecSmrg } 48905b261ecSmrg *hash = newHash; 49005b261ecSmrg if (global) 49105b261ecSmrg CheckDuplicates (hash, "ResizeGlyphHash bottom"); 49205b261ecSmrg return TRUE; 49305b261ecSmrg} 49405b261ecSmrg 49505b261ecSmrgBool 49605b261ecSmrgResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) 49705b261ecSmrg{ 49805b261ecSmrg return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && 49905b261ecSmrg ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); 50005b261ecSmrg} 50105b261ecSmrg 50205b261ecSmrgGlyphSetPtr 50305b261ecSmrgAllocateGlyphSet (int fdepth, PictFormatPtr format) 50405b261ecSmrg{ 50505b261ecSmrg GlyphSetPtr glyphSet; 50605b261ecSmrg int size; 50705b261ecSmrg 50805b261ecSmrg if (!globalGlyphs[fdepth].hashSet) 50905b261ecSmrg { 51005b261ecSmrg if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) 51105b261ecSmrg return FALSE; 51205b261ecSmrg } 51305b261ecSmrg 5144642e01fSmrg size = sizeof (GlyphSetRec); 5154642e01fSmrg glyphSet = xcalloc (1, size); 51605b261ecSmrg if (!glyphSet) 51705b261ecSmrg return FALSE; 51805b261ecSmrg 51905b261ecSmrg if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) 52005b261ecSmrg { 52105b261ecSmrg xfree (glyphSet); 52205b261ecSmrg return FALSE; 52305b261ecSmrg } 52405b261ecSmrg glyphSet->refcnt = 1; 52505b261ecSmrg glyphSet->fdepth = fdepth; 52605b261ecSmrg glyphSet->format = format; 52705b261ecSmrg return glyphSet; 52805b261ecSmrg} 52905b261ecSmrg 53005b261ecSmrgint 53105b261ecSmrgFreeGlyphSet (pointer value, 53205b261ecSmrg XID gid) 53305b261ecSmrg{ 53405b261ecSmrg GlyphSetPtr glyphSet = (GlyphSetPtr) value; 53505b261ecSmrg 53605b261ecSmrg if (--glyphSet->refcnt == 0) 53705b261ecSmrg { 53805b261ecSmrg CARD32 i, tableSize = glyphSet->hash.hashSet->size; 53905b261ecSmrg GlyphRefPtr table = glyphSet->hash.table; 54005b261ecSmrg GlyphPtr glyph; 54105b261ecSmrg 54205b261ecSmrg for (i = 0; i < tableSize; i++) 54305b261ecSmrg { 54405b261ecSmrg glyph = table[i].glyph; 54505b261ecSmrg if (glyph && glyph != DeletedGlyph) 54605b261ecSmrg FreeGlyph (glyph, glyphSet->fdepth); 54705b261ecSmrg } 54805b261ecSmrg if (!globalGlyphs[glyphSet->fdepth].tableEntries) 54905b261ecSmrg { 55005b261ecSmrg xfree (globalGlyphs[glyphSet->fdepth].table); 55105b261ecSmrg globalGlyphs[glyphSet->fdepth].table = 0; 55205b261ecSmrg globalGlyphs[glyphSet->fdepth].hashSet = 0; 55305b261ecSmrg } 55405b261ecSmrg else 55505b261ecSmrg ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); 55605b261ecSmrg xfree (table); 5574642e01fSmrg dixFreePrivates(glyphSet->devPrivates); 55805b261ecSmrg xfree (glyphSet); 55905b261ecSmrg } 56005b261ecSmrg return Success; 56105b261ecSmrg} 5624642e01fSmrg 5634642e01fSmrgstatic void 5644642e01fSmrgGlyphExtents (int nlist, 5654642e01fSmrg GlyphListPtr list, 5664642e01fSmrg GlyphPtr *glyphs, 5674642e01fSmrg BoxPtr extents) 5684642e01fSmrg{ 5694642e01fSmrg int x1, x2, y1, y2; 5704642e01fSmrg int n; 5714642e01fSmrg GlyphPtr glyph; 5724642e01fSmrg int x, y; 5734642e01fSmrg 5744642e01fSmrg x = 0; 5754642e01fSmrg y = 0; 5764642e01fSmrg extents->x1 = MAXSHORT; 5774642e01fSmrg extents->x2 = MINSHORT; 5784642e01fSmrg extents->y1 = MAXSHORT; 5794642e01fSmrg extents->y2 = MINSHORT; 5804642e01fSmrg while (nlist--) 5814642e01fSmrg { 5824642e01fSmrg x += list->xOff; 5834642e01fSmrg y += list->yOff; 5844642e01fSmrg n = list->len; 5854642e01fSmrg list++; 5864642e01fSmrg while (n--) 5874642e01fSmrg { 5884642e01fSmrg glyph = *glyphs++; 5894642e01fSmrg x1 = x - glyph->info.x; 5904642e01fSmrg if (x1 < MINSHORT) 5914642e01fSmrg x1 = MINSHORT; 5924642e01fSmrg y1 = y - glyph->info.y; 5934642e01fSmrg if (y1 < MINSHORT) 5944642e01fSmrg y1 = MINSHORT; 5954642e01fSmrg x2 = x1 + glyph->info.width; 5964642e01fSmrg if (x2 > MAXSHORT) 5974642e01fSmrg x2 = MAXSHORT; 5984642e01fSmrg y2 = y1 + glyph->info.height; 5994642e01fSmrg if (y2 > MAXSHORT) 6004642e01fSmrg y2 = MAXSHORT; 6014642e01fSmrg if (x1 < extents->x1) 6024642e01fSmrg extents->x1 = x1; 6034642e01fSmrg if (x2 > extents->x2) 6044642e01fSmrg extents->x2 = x2; 6054642e01fSmrg if (y1 < extents->y1) 6064642e01fSmrg extents->y1 = y1; 6074642e01fSmrg if (y2 > extents->y2) 6084642e01fSmrg extents->y2 = y2; 6094642e01fSmrg x += glyph->info.xOff; 6104642e01fSmrg y += glyph->info.yOff; 6114642e01fSmrg } 6124642e01fSmrg } 6134642e01fSmrg} 6144642e01fSmrg 6154642e01fSmrg#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) 6164642e01fSmrg 6174642e01fSmrg_X_EXPORT void 6184642e01fSmrgCompositeGlyphs (CARD8 op, 6194642e01fSmrg PicturePtr pSrc, 6204642e01fSmrg PicturePtr pDst, 6214642e01fSmrg PictFormatPtr maskFormat, 6224642e01fSmrg INT16 xSrc, 6234642e01fSmrg INT16 ySrc, 6244642e01fSmrg int nlist, 6254642e01fSmrg GlyphListPtr lists, 6264642e01fSmrg GlyphPtr *glyphs) 6274642e01fSmrg{ 6284642e01fSmrg PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); 6294642e01fSmrg 6304642e01fSmrg ValidatePicture (pSrc); 6314642e01fSmrg ValidatePicture (pDst); 6324642e01fSmrg (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); 6334642e01fSmrg} 6344642e01fSmrg 6354642e01fSmrgBool 6364642e01fSmrgmiRealizeGlyph (ScreenPtr pScreen, 6374642e01fSmrg GlyphPtr glyph) 6384642e01fSmrg{ 6394642e01fSmrg return TRUE; 6404642e01fSmrg} 6414642e01fSmrg 6424642e01fSmrgvoid 6434642e01fSmrgmiUnrealizeGlyph (ScreenPtr pScreen, 6444642e01fSmrg GlyphPtr glyph) 6454642e01fSmrg{ 6464642e01fSmrg} 6474642e01fSmrg 6484642e01fSmrg_X_EXPORT void 6494642e01fSmrgmiGlyphs (CARD8 op, 6504642e01fSmrg PicturePtr pSrc, 6514642e01fSmrg PicturePtr pDst, 6524642e01fSmrg PictFormatPtr maskFormat, 6534642e01fSmrg INT16 xSrc, 6544642e01fSmrg INT16 ySrc, 6554642e01fSmrg int nlist, 6564642e01fSmrg GlyphListPtr list, 6574642e01fSmrg GlyphPtr *glyphs) 6584642e01fSmrg{ 6594642e01fSmrg PicturePtr pPicture; 6604642e01fSmrg PixmapPtr pMaskPixmap = 0; 6614642e01fSmrg PicturePtr pMask; 6624642e01fSmrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 6634642e01fSmrg int width = 0, height = 0; 6644642e01fSmrg int x, y; 6654642e01fSmrg int xDst = list->xOff, yDst = list->yOff; 6664642e01fSmrg int n; 6674642e01fSmrg GlyphPtr glyph; 6684642e01fSmrg int error; 6694642e01fSmrg BoxRec extents = {0, 0, 0, 0}; 6704642e01fSmrg CARD32 component_alpha; 6714642e01fSmrg 6724642e01fSmrg if (maskFormat) 6734642e01fSmrg { 6744642e01fSmrg GCPtr pGC; 6754642e01fSmrg xRectangle rect; 6764642e01fSmrg 6774642e01fSmrg GlyphExtents (nlist, list, glyphs, &extents); 6784642e01fSmrg 6794642e01fSmrg if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) 6804642e01fSmrg return; 6814642e01fSmrg width = extents.x2 - extents.x1; 6824642e01fSmrg height = extents.y2 - extents.y1; 6834642e01fSmrg pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 6844642e01fSmrg maskFormat->depth, 6854642e01fSmrg CREATE_PIXMAP_USAGE_SCRATCH); 6864642e01fSmrg if (!pMaskPixmap) 6874642e01fSmrg return; 6884642e01fSmrg component_alpha = NeedsComponent(maskFormat->format); 6894642e01fSmrg pMask = CreatePicture (0, &pMaskPixmap->drawable, 6904642e01fSmrg maskFormat, CPComponentAlpha, &component_alpha, 6914642e01fSmrg serverClient, &error); 6924642e01fSmrg if (!pMask) 6934642e01fSmrg { 6944642e01fSmrg (*pScreen->DestroyPixmap) (pMaskPixmap); 6954642e01fSmrg return; 6964642e01fSmrg } 6974642e01fSmrg pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); 6984642e01fSmrg ValidateGC (&pMaskPixmap->drawable, pGC); 6994642e01fSmrg rect.x = 0; 7004642e01fSmrg rect.y = 0; 7014642e01fSmrg rect.width = width; 7024642e01fSmrg rect.height = height; 7034642e01fSmrg (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); 7044642e01fSmrg FreeScratchGC (pGC); 7054642e01fSmrg x = -extents.x1; 7064642e01fSmrg y = -extents.y1; 7074642e01fSmrg } 7084642e01fSmrg else 7094642e01fSmrg { 7104642e01fSmrg pMask = pDst; 7114642e01fSmrg x = 0; 7124642e01fSmrg y = 0; 7134642e01fSmrg } 7144642e01fSmrg while (nlist--) 7154642e01fSmrg { 7164642e01fSmrg x += list->xOff; 7174642e01fSmrg y += list->yOff; 7184642e01fSmrg n = list->len; 7194642e01fSmrg while (n--) 7204642e01fSmrg { 7214642e01fSmrg glyph = *glyphs++; 7224642e01fSmrg pPicture = GlyphPicture (glyph)[pScreen->myNum]; 7234642e01fSmrg 7244642e01fSmrg if (maskFormat) 7254642e01fSmrg { 7264642e01fSmrg CompositePicture (PictOpAdd, 7274642e01fSmrg pPicture, 7284642e01fSmrg None, 7294642e01fSmrg pMask, 7304642e01fSmrg 0, 0, 7314642e01fSmrg 0, 0, 7324642e01fSmrg x - glyph->info.x, 7334642e01fSmrg y - glyph->info.y, 7344642e01fSmrg glyph->info.width, 7354642e01fSmrg glyph->info.height); 7364642e01fSmrg } 7374642e01fSmrg else 7384642e01fSmrg { 7394642e01fSmrg CompositePicture (op, 7404642e01fSmrg pSrc, 7414642e01fSmrg pPicture, 7424642e01fSmrg pDst, 7434642e01fSmrg xSrc + (x - glyph->info.x) - xDst, 7444642e01fSmrg ySrc + (y - glyph->info.y) - yDst, 7454642e01fSmrg 0, 0, 7464642e01fSmrg x - glyph->info.x, 7474642e01fSmrg y - glyph->info.y, 7484642e01fSmrg glyph->info.width, 7494642e01fSmrg glyph->info.height); 7504642e01fSmrg } 7514642e01fSmrg 7524642e01fSmrg x += glyph->info.xOff; 7534642e01fSmrg y += glyph->info.yOff; 7544642e01fSmrg } 7554642e01fSmrg list++; 7564642e01fSmrg } 7574642e01fSmrg if (maskFormat) 7584642e01fSmrg { 7594642e01fSmrg x = extents.x1; 7604642e01fSmrg y = extents.y1; 7614642e01fSmrg CompositePicture (op, 7624642e01fSmrg pSrc, 7634642e01fSmrg pMask, 7644642e01fSmrg pDst, 7654642e01fSmrg xSrc + x - xDst, 7664642e01fSmrg ySrc + y - yDst, 7674642e01fSmrg 0, 0, 7684642e01fSmrg x, y, 7694642e01fSmrg width, height); 7704642e01fSmrg FreePicture ((pointer) pMask, (XID) 0); 7714642e01fSmrg (*pScreen->DestroyPixmap) (pMaskPixmap); 7724642e01fSmrg } 7734642e01fSmrg} 774