From 0f834b91a4768673833ab4917e87d86c237bb1a6 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 23 Mar 2012 10:05:55 +0100 Subject: libX11 xserver fontconfig mesa pixman xkbcomp xkeyboard-config git update 23 Mar 2012 --- xorg-server/render/glyph.c | 1434 +++++++++++++++++++++----------------------- 1 file changed, 686 insertions(+), 748 deletions(-) (limited to 'xorg-server/render/glyph.c') diff --git a/xorg-server/render/glyph.c b/xorg-server/render/glyph.c index ab20da625..a143e9eb5 100644 --- a/xorg-server/render/glyph.c +++ b/xorg-server/render/glyph.c @@ -1,748 +1,686 @@ -/* - * - * Copyright © 2000 SuSE, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Keith Packard, SuSE, Inc. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "xsha1.h" - -#include "misc.h" -#include "scrnintstr.h" -#include "os.h" -#include "regionstr.h" -#include "validate.h" -#include "windowstr.h" -#include "input.h" -#include "resource.h" -#include "colormapst.h" -#include "cursorstr.h" -#include "dixstruct.h" -#include "gcstruct.h" -#include "servermd.h" -#include "picturestr.h" -#include "glyphstr.h" -#include "mipict.h" - -/* - * From Knuth -- a good choice for hash/rehash values is p, p-2 where - * p and p-2 are both prime. These tables are sized to have an extra 10% - * free to avoid exponential performance degradation as the hash table fills - */ -static GlyphHashSetRec glyphHashSets[] = { - { 32, 43, 41 }, - { 64, 73, 71 }, - { 128, 151, 149 }, - { 256, 283, 281 }, - { 512, 571, 569 }, - { 1024, 1153, 1151 }, - { 2048, 2269, 2267 }, - { 4096, 4519, 4517 }, - { 8192, 9013, 9011 }, - { 16384, 18043, 18041 }, - { 32768, 36109, 36107 }, - { 65536, 72091, 72089 }, - { 131072, 144409, 144407 }, - { 262144, 288361, 288359 }, - { 524288, 576883, 576881 }, - { 1048576, 1153459, 1153457 }, - { 2097152, 2307163, 2307161 }, - { 4194304, 4613893, 4613891 }, - { 8388608, 9227641, 9227639 }, - { 16777216, 18455029, 18455027 }, - { 33554432, 36911011, 36911009 }, - { 67108864, 73819861, 73819859 }, - { 134217728, 147639589, 147639587 }, - { 268435456, 295279081, 295279079 }, - { 536870912, 590559793, 590559791 } -}; - -#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) - -static const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; - -static GlyphHashRec globalGlyphs[GlyphFormatNum]; - -void -GlyphUninit (ScreenPtr pScreen) -{ - PictureScreenPtr ps = GetPictureScreen (pScreen); - GlyphPtr glyph; - int fdepth, i; - int scrno = pScreen->myNum; - - for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) - { - if (!globalGlyphs[fdepth].hashSet) - continue; - - for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) - { - glyph = globalGlyphs[fdepth].table[i].glyph; - if (glyph && glyph != DeletedGlyph) - { - if (GlyphPicture(glyph)[scrno]) - { - FreePicture ((pointer) GlyphPicture (glyph)[scrno], 0); - GlyphPicture(glyph)[scrno] = NULL; - } - (*ps->UnrealizeGlyph) (pScreen, glyph); - } - } - } -} - -GlyphHashSetPtr -FindGlyphHashSet (CARD32 filled) -{ - int i; - - for (i = 0; i < NGLYPHHASHSETS; i++) - if (glyphHashSets[i].entries >= filled) - return &glyphHashSets[i]; - return 0; -} - -GlyphRefPtr -FindGlyphRef (GlyphHashPtr hash, - CARD32 signature, - Bool match, - unsigned char sha1[20]) -{ - CARD32 elt, step, s; - GlyphPtr glyph; - GlyphRefPtr table, gr, del; - CARD32 tableSize = hash->hashSet->size; - - table = hash->table; - elt = signature % tableSize; - step = 0; - del = 0; - for (;;) - { - gr = &table[elt]; - s = gr->signature; - glyph = gr->glyph; - if (!glyph) - { - if (del) - gr = del; - break; - } - if (glyph == DeletedGlyph) - { - if (!del) - del = gr; - else if (gr == del) - break; - } - else if (s == signature && - (!match || - memcmp (glyph->sha1, sha1, 20) == 0)) - { - break; - } - if (!step) - { - step = signature % hash->hashSet->rehash; - if (!step) - step = 1; - } - elt += step; - if (elt >= tableSize) - elt -= tableSize; - } - return gr; -} - -int -HashGlyph (xGlyphInfo *gi, - CARD8 *bits, - unsigned long size, - unsigned char sha1[20]) -{ - void *ctx = x_sha1_init(); - int success; - - if (!ctx) - return BadAlloc; - - success = x_sha1_update(ctx, gi, sizeof(xGlyphInfo)); - if (!success) - return BadAlloc; - success = x_sha1_update(ctx, bits, size); - if (!success) - return BadAlloc; - success = x_sha1_final(ctx, sha1); - if (!success) - return BadAlloc; - return Success; -} - -GlyphPtr -FindGlyphByHash (unsigned char sha1[20], int format) -{ - GlyphRefPtr gr; - CARD32 signature = *(CARD32 *) sha1; - - if (!globalGlyphs[format].hashSet) - return NULL; - - gr = FindGlyphRef (&globalGlyphs[format], - signature, TRUE, sha1); - - if (gr->glyph && gr->glyph != DeletedGlyph) - return gr->glyph; - else - return NULL; -} - -#ifdef CHECK_DUPLICATES -void -DuplicateRef (GlyphPtr glyph, char *where) -{ - ErrorF ("Duplicate Glyph 0x%x from %s\n", glyph, where); -} - -void -CheckDuplicates (GlyphHashPtr hash, char *where) -{ - GlyphPtr g; - int i, j; - - for (i = 0; i < hash->hashSet->size; i++) - { - g = hash->table[i].glyph; - if (!g || g == DeletedGlyph) - continue; - for (j = i + 1; j < hash->hashSet->size; j++) - if (hash->table[j].glyph == g) - DuplicateRef (g, where); - } -} -#else -#define CheckDuplicates(a,b) -#define DuplicateRef(a,b) -#endif - -static void -FreeGlyphPicture(GlyphPtr glyph) -{ - PictureScreenPtr ps; - int i; - - for (i = 0; i < screenInfo.numScreens; i++) - { - ScreenPtr pScreen = screenInfo.screens[i]; - - if (GlyphPicture(glyph)[i]) - FreePicture ((pointer) GlyphPicture (glyph)[i], 0); - - ps = GetPictureScreenIfSet (pScreen); - if (ps) - (*ps->UnrealizeGlyph) (pScreen, glyph); - } -} - - -void -FreeGlyph (GlyphPtr glyph, int format) -{ - CheckDuplicates (&globalGlyphs[format], "FreeGlyph"); - if (--glyph->refcnt == 0) - { - GlyphRefPtr gr; - int i; - int first; - CARD32 signature; - - first = -1; - for (i = 0; i < globalGlyphs[format].hashSet->size; i++) - if (globalGlyphs[format].table[i].glyph == glyph) - { - if (first != -1) - DuplicateRef (glyph, "FreeGlyph check"); - first = i; - } - - signature = *(CARD32 *) glyph->sha1; - gr = FindGlyphRef (&globalGlyphs[format], signature, - TRUE, glyph->sha1); - if (gr - globalGlyphs[format].table != first) - DuplicateRef (glyph, "Found wrong one"); - if (gr->glyph && gr->glyph != DeletedGlyph) - { - gr->glyph = DeletedGlyph; - gr->signature = 0; - globalGlyphs[format].tableEntries--; - } - - FreeGlyphPicture(glyph); - dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); - } -} - -void -AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) -{ - GlyphRefPtr gr; - CARD32 signature; - - CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); - /* Locate existing matching glyph */ - signature = *(CARD32 *) glyph->sha1; - gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], signature, - TRUE, glyph->sha1); - if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph) - { - FreeGlyphPicture(glyph); - dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); - glyph = gr->glyph; - } - else if (gr->glyph != glyph) - { - gr->glyph = glyph; - gr->signature = signature; - globalGlyphs[glyphSet->fdepth].tableEntries++; - } - - /* Insert/replace glyphset value */ - gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); - ++glyph->refcnt; - if (gr->glyph && gr->glyph != DeletedGlyph) - FreeGlyph (gr->glyph, glyphSet->fdepth); - else - glyphSet->hash.tableEntries++; - gr->glyph = glyph; - gr->signature = id; - CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); -} - -Bool -DeleteGlyph (GlyphSetPtr glyphSet, Glyph id) -{ - GlyphRefPtr gr; - GlyphPtr glyph; - - gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0); - glyph = gr->glyph; - if (glyph && glyph != DeletedGlyph) - { - gr->glyph = DeletedGlyph; - glyphSet->hash.tableEntries--; - FreeGlyph (glyph, glyphSet->fdepth); - return TRUE; - } - return FALSE; -} - -GlyphPtr -FindGlyph (GlyphSetPtr glyphSet, Glyph id) -{ - GlyphPtr glyph; - - glyph = FindGlyphRef (&glyphSet->hash, id, FALSE, 0)->glyph; - if (glyph == DeletedGlyph) - glyph = 0; - return glyph; -} - -GlyphPtr -AllocateGlyph (xGlyphInfo *gi, int fdepth) -{ - PictureScreenPtr ps; - int size; - GlyphPtr glyph; - int i; - int head_size; - - head_size = sizeof (GlyphRec) + screenInfo.numScreens * sizeof (PicturePtr); - size = (head_size + dixPrivatesSize(PRIVATE_GLYPH)); - glyph = (GlyphPtr) malloc (size); - if (!glyph) - return 0; - glyph->refcnt = 0; - glyph->size = size + sizeof (xGlyphInfo); - glyph->info = *gi; - dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH); - - for (i = 0; i < screenInfo.numScreens; i++) - { - GlyphPicture(glyph)[i] = NULL; - ps = GetPictureScreenIfSet (screenInfo.screens[i]); - - if (ps) - { - if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph)) - goto bail; - } - } - - return glyph; - -bail: - while (i--) - { - ps = GetPictureScreenIfSet (screenInfo.screens[i]); - if (ps) - (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); - } - - dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); - return 0; -} - -Bool -AllocateGlyphHash (GlyphHashPtr hash, GlyphHashSetPtr hashSet) -{ - hash->table = calloc(hashSet->size, sizeof (GlyphRefRec)); - if (!hash->table) - return FALSE; - hash->hashSet = hashSet; - hash->tableEntries = 0; - return TRUE; -} - -Bool -ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global) -{ - CARD32 tableEntries; - GlyphHashSetPtr hashSet; - GlyphHashRec newHash; - GlyphRefPtr gr; - GlyphPtr glyph; - int i; - int oldSize; - CARD32 s; - - tableEntries = hash->tableEntries + change; - hashSet = FindGlyphHashSet (tableEntries); - if (hashSet == hash->hashSet) - return TRUE; - if (global) - CheckDuplicates (hash, "ResizeGlyphHash top"); - if (!AllocateGlyphHash (&newHash, hashSet)) - return FALSE; - if (hash->table) - { - oldSize = hash->hashSet->size; - for (i = 0; i < oldSize; i++) - { - glyph = hash->table[i].glyph; - if (glyph && glyph != DeletedGlyph) - { - s = hash->table[i].signature; - gr = FindGlyphRef (&newHash, s, global, glyph->sha1); - gr->signature = s; - gr->glyph = glyph; - ++newHash.tableEntries; - } - } - free(hash->table); - } - *hash = newHash; - if (global) - CheckDuplicates (hash, "ResizeGlyphHash bottom"); - return TRUE; -} - -Bool -ResizeGlyphSet (GlyphSetPtr glyphSet, CARD32 change) -{ - return (ResizeGlyphHash (&glyphSet->hash, change, FALSE) && - ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], change, TRUE)); -} - -GlyphSetPtr -AllocateGlyphSet (int fdepth, PictFormatPtr format) -{ - GlyphSetPtr glyphSet; - - if (!globalGlyphs[fdepth].hashSet) - { - if (!AllocateGlyphHash (&globalGlyphs[fdepth], &glyphHashSets[0])) - return FALSE; - } - - glyphSet = dixAllocateObjectWithPrivates(GlyphSetRec, PRIVATE_GLYPHSET); - if (!glyphSet) - return FALSE; - - if (!AllocateGlyphHash (&glyphSet->hash, &glyphHashSets[0])) - { - free(glyphSet); - return FALSE; - } - glyphSet->refcnt = 1; - glyphSet->fdepth = fdepth; - glyphSet->format = format; - return glyphSet; -} - -int -FreeGlyphSet (pointer value, - XID gid) -{ - GlyphSetPtr glyphSet = (GlyphSetPtr) value; - - if (--glyphSet->refcnt == 0) - { - CARD32 i, tableSize = glyphSet->hash.hashSet->size; - GlyphRefPtr table = glyphSet->hash.table; - GlyphPtr glyph; - - for (i = 0; i < tableSize; i++) - { - glyph = table[i].glyph; - if (glyph && glyph != DeletedGlyph) - FreeGlyph (glyph, glyphSet->fdepth); - } - if (!globalGlyphs[glyphSet->fdepth].tableEntries) - { - free(globalGlyphs[glyphSet->fdepth].table); - globalGlyphs[glyphSet->fdepth].table = 0; - globalGlyphs[glyphSet->fdepth].hashSet = 0; - } - else - ResizeGlyphHash (&globalGlyphs[glyphSet->fdepth], 0, TRUE); - free(table); - dixFreeObjectWithPrivates(glyphSet, PRIVATE_GLYPHSET); - } - return Success; -} - -static void -GlyphExtents (int nlist, - GlyphListPtr list, - GlyphPtr *glyphs, - BoxPtr extents) -{ - int x1, x2, y1, y2; - int n; - GlyphPtr glyph; - int x, y; - - x = 0; - y = 0; - extents->x1 = MAXSHORT; - extents->x2 = MINSHORT; - extents->y1 = MAXSHORT; - extents->y2 = MINSHORT; - while (nlist--) - { - x += list->xOff; - y += list->yOff; - n = list->len; - list++; - while (n--) - { - glyph = *glyphs++; - x1 = x - glyph->info.x; - if (x1 < MINSHORT) - x1 = MINSHORT; - y1 = y - glyph->info.y; - if (y1 < MINSHORT) - y1 = MINSHORT; - x2 = x1 + glyph->info.width; - if (x2 > MAXSHORT) - x2 = MAXSHORT; - y2 = y1 + glyph->info.height; - if (y2 > MAXSHORT) - y2 = MAXSHORT; - if (x1 < extents->x1) - extents->x1 = x1; - if (x2 > extents->x2) - extents->x2 = x2; - if (y1 < extents->y1) - extents->y1 = y1; - if (y2 > extents->y2) - extents->y2 = y2; - x += glyph->info.xOff; - y += glyph->info.yOff; - } - } -} - -#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) - -void -CompositeGlyphs (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int nlist, - GlyphListPtr lists, - GlyphPtr *glyphs) -{ - PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); - - ValidatePicture (pSrc); - ValidatePicture (pDst); - (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, glyphs); -} - -Bool -miRealizeGlyph (ScreenPtr pScreen, - GlyphPtr glyph) -{ - return TRUE; -} - -void -miUnrealizeGlyph (ScreenPtr pScreen, - GlyphPtr glyph) -{ -} - -void -miGlyphs (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int nlist, - GlyphListPtr list, - GlyphPtr *glyphs) -{ - PicturePtr pPicture; - PixmapPtr pMaskPixmap = 0; - PicturePtr pMask; - ScreenPtr pScreen = pDst->pDrawable->pScreen; - int width = 0, height = 0; - int x, y; - int xDst = list->xOff, yDst = list->yOff; - int n; - GlyphPtr glyph; - int error; - BoxRec extents = {0, 0, 0, 0}; - CARD32 component_alpha; - - if (maskFormat) - { - GCPtr pGC; - xRectangle rect; - - GlyphExtents (nlist, list, glyphs, &extents); - - if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) - return; - width = extents.x2 - extents.x1; - height = extents.y2 - extents.y1; - pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, - maskFormat->depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pMaskPixmap) - return; - component_alpha = NeedsComponent(maskFormat->format); - pMask = CreatePicture (0, &pMaskPixmap->drawable, - maskFormat, CPComponentAlpha, &component_alpha, - serverClient, &error); - if (!pMask) - { - (*pScreen->DestroyPixmap) (pMaskPixmap); - return; - } - pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); - ValidateGC (&pMaskPixmap->drawable, pGC); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); - FreeScratchGC (pGC); - x = -extents.x1; - y = -extents.y1; - } - else - { - pMask = pDst; - x = 0; - y = 0; - } - while (nlist--) - { - x += list->xOff; - y += list->yOff; - n = list->len; - while (n--) - { - glyph = *glyphs++; - pPicture = GlyphPicture (glyph)[pScreen->myNum]; - - if (pPicture) - { - if (maskFormat) - { - CompositePicture (PictOpAdd, - pPicture, - None, - pMask, - 0, 0, - 0, 0, - x - glyph->info.x, - y - glyph->info.y, - glyph->info.width, - glyph->info.height); - } - else - { - CompositePicture (op, - pSrc, - pPicture, - pDst, - xSrc + (x - glyph->info.x) - xDst, - ySrc + (y - glyph->info.y) - yDst, - 0, 0, - x - glyph->info.x, - y - glyph->info.y, - glyph->info.width, - glyph->info.height); - } - } - - x += glyph->info.xOff; - y += glyph->info.yOff; - } - list++; - } - if (maskFormat) - { - x = extents.x1; - y = extents.y1; - CompositePicture (op, - pSrc, - pMask, - pDst, - xSrc + x - xDst, - ySrc + y - yDst, - 0, 0, - x, y, - width, height); - FreePicture ((pointer) pMask, (XID) 0); - (*pScreen->DestroyPixmap) (pMaskPixmap); - } -} +/* + * + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "xsha1.h" + +#include "misc.h" +#include "scrnintstr.h" +#include "os.h" +#include "regionstr.h" +#include "validate.h" +#include "windowstr.h" +#include "input.h" +#include "resource.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "servermd.h" +#include "picturestr.h" +#include "glyphstr.h" +#include "mipict.h" + +/* + * From Knuth -- a good choice for hash/rehash values is p, p-2 where + * p and p-2 are both prime. These tables are sized to have an extra 10% + * free to avoid exponential performance degradation as the hash table fills + */ +static GlyphHashSetRec glyphHashSets[] = { + {32, 43, 41}, + {64, 73, 71}, + {128, 151, 149}, + {256, 283, 281}, + {512, 571, 569}, + {1024, 1153, 1151}, + {2048, 2269, 2267}, + {4096, 4519, 4517}, + {8192, 9013, 9011}, + {16384, 18043, 18041}, + {32768, 36109, 36107}, + {65536, 72091, 72089}, + {131072, 144409, 144407}, + {262144, 288361, 288359}, + {524288, 576883, 576881}, + {1048576, 1153459, 1153457}, + {2097152, 2307163, 2307161}, + {4194304, 4613893, 4613891}, + {8388608, 9227641, 9227639}, + {16777216, 18455029, 18455027}, + {33554432, 36911011, 36911009}, + {67108864, 73819861, 73819859}, + {134217728, 147639589, 147639587}, + {268435456, 295279081, 295279079}, + {536870912, 590559793, 590559791} +}; + +#define NGLYPHHASHSETS (sizeof(glyphHashSets)/sizeof(glyphHashSets[0])) + +static const CARD8 glyphDepths[GlyphFormatNum] = { 1, 4, 8, 16, 32 }; + +static GlyphHashRec globalGlyphs[GlyphFormatNum]; + +void +GlyphUninit(ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreen(pScreen); + GlyphPtr glyph; + int fdepth, i; + int scrno = pScreen->myNum; + + for (fdepth = 0; fdepth < GlyphFormatNum; fdepth++) { + if (!globalGlyphs[fdepth].hashSet) + continue; + + for (i = 0; i < globalGlyphs[fdepth].hashSet->size; i++) { + glyph = globalGlyphs[fdepth].table[i].glyph; + if (glyph && glyph != DeletedGlyph) { + if (GlyphPicture(glyph)[scrno]) { + FreePicture((pointer) GlyphPicture(glyph)[scrno], 0); + GlyphPicture(glyph)[scrno] = NULL; + } + (*ps->UnrealizeGlyph) (pScreen, glyph); + } + } + } +} + +GlyphHashSetPtr +FindGlyphHashSet(CARD32 filled) +{ + int i; + + for (i = 0; i < NGLYPHHASHSETS; i++) + if (glyphHashSets[i].entries >= filled) + return &glyphHashSets[i]; + return 0; +} + +GlyphRefPtr +FindGlyphRef(GlyphHashPtr hash, + CARD32 signature, Bool match, unsigned char sha1[20]) +{ + CARD32 elt, step, s; + GlyphPtr glyph; + GlyphRefPtr table, gr, del; + CARD32 tableSize = hash->hashSet->size; + + table = hash->table; + elt = signature % tableSize; + step = 0; + del = 0; + for (;;) { + gr = &table[elt]; + s = gr->signature; + glyph = gr->glyph; + if (!glyph) { + if (del) + gr = del; + break; + } + if (glyph == DeletedGlyph) { + if (!del) + del = gr; + else if (gr == del) + break; + } + else if (s == signature && + (!match || memcmp(glyph->sha1, sha1, 20) == 0)) { + break; + } + if (!step) { + step = signature % hash->hashSet->rehash; + if (!step) + step = 1; + } + elt += step; + if (elt >= tableSize) + elt -= tableSize; + } + return gr; +} + +int +HashGlyph(xGlyphInfo * gi, + CARD8 *bits, unsigned long size, unsigned char sha1[20]) +{ + void *ctx = x_sha1_init(); + int success; + + if (!ctx) + return BadAlloc; + + success = x_sha1_update(ctx, gi, sizeof(xGlyphInfo)); + if (!success) + return BadAlloc; + success = x_sha1_update(ctx, bits, size); + if (!success) + return BadAlloc; + success = x_sha1_final(ctx, sha1); + if (!success) + return BadAlloc; + return Success; +} + +GlyphPtr +FindGlyphByHash(unsigned char sha1[20], int format) +{ + GlyphRefPtr gr; + CARD32 signature = *(CARD32 *) sha1; + + if (!globalGlyphs[format].hashSet) + return NULL; + + gr = FindGlyphRef(&globalGlyphs[format], signature, TRUE, sha1); + + if (gr->glyph && gr->glyph != DeletedGlyph) + return gr->glyph; + else + return NULL; +} + +#ifdef CHECK_DUPLICATES +void +DuplicateRef(GlyphPtr glyph, char *where) +{ + ErrorF("Duplicate Glyph 0x%x from %s\n", glyph, where); +} + +void +CheckDuplicates(GlyphHashPtr hash, char *where) +{ + GlyphPtr g; + int i, j; + + for (i = 0; i < hash->hashSet->size; i++) { + g = hash->table[i].glyph; + if (!g || g == DeletedGlyph) + continue; + for (j = i + 1; j < hash->hashSet->size; j++) + if (hash->table[j].glyph == g) + DuplicateRef(g, where); + } +} +#else +#define CheckDuplicates(a,b) +#define DuplicateRef(a,b) +#endif + +static void +FreeGlyphPicture(GlyphPtr glyph) +{ + PictureScreenPtr ps; + int i; + + for (i = 0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + + if (GlyphPicture(glyph)[i]) + FreePicture((pointer) GlyphPicture(glyph)[i], 0); + + ps = GetPictureScreenIfSet(pScreen); + if (ps) + (*ps->UnrealizeGlyph) (pScreen, glyph); + } +} + +void +FreeGlyph(GlyphPtr glyph, int format) +{ + CheckDuplicates(&globalGlyphs[format], "FreeGlyph"); + if (--glyph->refcnt == 0) { + GlyphRefPtr gr; + int i; + int first; + CARD32 signature; + + first = -1; + for (i = 0; i < globalGlyphs[format].hashSet->size; i++) + if (globalGlyphs[format].table[i].glyph == glyph) { + if (first != -1) + DuplicateRef(glyph, "FreeGlyph check"); + first = i; + } + + signature = *(CARD32 *) glyph->sha1; + gr = FindGlyphRef(&globalGlyphs[format], signature, TRUE, glyph->sha1); + if (gr - globalGlyphs[format].table != first) + DuplicateRef(glyph, "Found wrong one"); + if (gr->glyph && gr->glyph != DeletedGlyph) { + gr->glyph = DeletedGlyph; + gr->signature = 0; + globalGlyphs[format].tableEntries--; + } + + FreeGlyphPicture(glyph); + dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); + } +} + +void +AddGlyph(GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id) +{ + GlyphRefPtr gr; + CARD32 signature; + + CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph top global"); + /* Locate existing matching glyph */ + signature = *(CARD32 *) glyph->sha1; + gr = FindGlyphRef(&globalGlyphs[glyphSet->fdepth], signature, + TRUE, glyph->sha1); + if (gr->glyph && gr->glyph != DeletedGlyph && gr->glyph != glyph) { + FreeGlyphPicture(glyph); + dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); + glyph = gr->glyph; + } + else if (gr->glyph != glyph) { + gr->glyph = glyph; + gr->signature = signature; + globalGlyphs[glyphSet->fdepth].tableEntries++; + } + + /* Insert/replace glyphset value */ + gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0); + ++glyph->refcnt; + if (gr->glyph && gr->glyph != DeletedGlyph) + FreeGlyph(gr->glyph, glyphSet->fdepth); + else + glyphSet->hash.tableEntries++; + gr->glyph = glyph; + gr->signature = id; + CheckDuplicates(&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom"); +} + +Bool +DeleteGlyph(GlyphSetPtr glyphSet, Glyph id) +{ + GlyphRefPtr gr; + GlyphPtr glyph; + + gr = FindGlyphRef(&glyphSet->hash, id, FALSE, 0); + glyph = gr->glyph; + if (glyph && glyph != DeletedGlyph) { + gr->glyph = DeletedGlyph; + glyphSet->hash.tableEntries--; + FreeGlyph(glyph, glyphSet->fdepth); + return TRUE; + } + return FALSE; +} + +GlyphPtr +FindGlyph(GlyphSetPtr glyphSet, Glyph id) +{ + GlyphPtr glyph; + + glyph = FindGlyphRef(&glyphSet->hash, id, FALSE, 0)->glyph; + if (glyph == DeletedGlyph) + glyph = 0; + return glyph; +} + +GlyphPtr +AllocateGlyph(xGlyphInfo * gi, int fdepth) +{ + PictureScreenPtr ps; + int size; + GlyphPtr glyph; + int i; + int head_size; + + head_size = sizeof(GlyphRec) + screenInfo.numScreens * sizeof(PicturePtr); + size = (head_size + dixPrivatesSize(PRIVATE_GLYPH)); + glyph = (GlyphPtr) malloc(size); + if (!glyph) + return 0; + glyph->refcnt = 0; + glyph->size = size + sizeof(xGlyphInfo); + glyph->info = *gi; + dixInitPrivates(glyph, (char *) glyph + head_size, PRIVATE_GLYPH); + + for (i = 0; i < screenInfo.numScreens; i++) { + GlyphPicture(glyph)[i] = NULL; + ps = GetPictureScreenIfSet(screenInfo.screens[i]); + + if (ps) { + if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph)) + goto bail; + } + } + + return glyph; + + bail: + while (i--) { + ps = GetPictureScreenIfSet(screenInfo.screens[i]); + if (ps) + (*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); + } + + dixFreeObjectWithPrivates(glyph, PRIVATE_GLYPH); + return 0; +} + +Bool +AllocateGlyphHash(GlyphHashPtr hash, GlyphHashSetPtr hashSet) +{ + hash->table = calloc(hashSet->size, sizeof(GlyphRefRec)); + if (!hash->table) + return FALSE; + hash->hashSet = hashSet; + hash->tableEntries = 0; + return TRUE; +} + +Bool +ResizeGlyphHash(GlyphHashPtr hash, CARD32 change, Bool global) +{ + CARD32 tableEntries; + GlyphHashSetPtr hashSet; + GlyphHashRec newHash; + GlyphRefPtr gr; + GlyphPtr glyph; + int i; + int oldSize; + CARD32 s; + + tableEntries = hash->tableEntries + change; + hashSet = FindGlyphHashSet(tableEntries); + if (hashSet == hash->hashSet) + return TRUE; + if (global) + CheckDuplicates(hash, "ResizeGlyphHash top"); + if (!AllocateGlyphHash(&newHash, hashSet)) + return FALSE; + if (hash->table) { + oldSize = hash->hashSet->size; + for (i = 0; i < oldSize; i++) { + glyph = hash->table[i].glyph; + if (glyph && glyph != DeletedGlyph) { + s = hash->table[i].signature; + gr = FindGlyphRef(&newHash, s, global, glyph->sha1); + + gr->signature = s; + gr->glyph = glyph; + ++newHash.tableEntries; + } + } + free(hash->table); + } + *hash = newHash; + if (global) + CheckDuplicates(hash, "ResizeGlyphHash bottom"); + return TRUE; +} + +Bool +ResizeGlyphSet(GlyphSetPtr glyphSet, CARD32 change) +{ + return (ResizeGlyphHash(&glyphSet->hash, change, FALSE) && + ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], change, TRUE)); +} + +GlyphSetPtr +AllocateGlyphSet(int fdepth, PictFormatPtr format) +{ + GlyphSetPtr glyphSet; + + if (!globalGlyphs[fdepth].hashSet) { + if (!AllocateGlyphHash(&globalGlyphs[fdepth], &glyphHashSets[0])) + return FALSE; + } + + glyphSet = dixAllocateObjectWithPrivates(GlyphSetRec, PRIVATE_GLYPHSET); + if (!glyphSet) + return FALSE; + + if (!AllocateGlyphHash(&glyphSet->hash, &glyphHashSets[0])) { + free(glyphSet); + return FALSE; + } + glyphSet->refcnt = 1; + glyphSet->fdepth = fdepth; + glyphSet->format = format; + return glyphSet; +} + +int +FreeGlyphSet(pointer value, XID gid) +{ + GlyphSetPtr glyphSet = (GlyphSetPtr) value; + + if (--glyphSet->refcnt == 0) { + CARD32 i, tableSize = glyphSet->hash.hashSet->size; + GlyphRefPtr table = glyphSet->hash.table; + GlyphPtr glyph; + + for (i = 0; i < tableSize; i++) { + glyph = table[i].glyph; + if (glyph && glyph != DeletedGlyph) + FreeGlyph(glyph, glyphSet->fdepth); + } + if (!globalGlyphs[glyphSet->fdepth].tableEntries) { + free(globalGlyphs[glyphSet->fdepth].table); + globalGlyphs[glyphSet->fdepth].table = 0; + globalGlyphs[glyphSet->fdepth].hashSet = 0; + } + else + ResizeGlyphHash(&globalGlyphs[glyphSet->fdepth], 0, TRUE); + free(table); + dixFreeObjectWithPrivates(glyphSet, PRIVATE_GLYPHSET); + } + return Success; +} + +static void +GlyphExtents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents) +{ + int x1, x2, y1, y2; + int n; + GlyphPtr glyph; + int x, y; + + x = 0; + y = 0; + extents->x1 = MAXSHORT; + extents->x2 = MINSHORT; + extents->y1 = MAXSHORT; + extents->y2 = MINSHORT; + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + list++; + while (n--) { + glyph = *glyphs++; + x1 = x - glyph->info.x; + if (x1 < MINSHORT) + x1 = MINSHORT; + y1 = y - glyph->info.y; + if (y1 < MINSHORT) + y1 = MINSHORT; + x2 = x1 + glyph->info.width; + if (x2 > MAXSHORT) + x2 = MAXSHORT; + y2 = y1 + glyph->info.height; + if (y2 > MAXSHORT) + y2 = MAXSHORT; + if (x1 < extents->x1) + extents->x1 = x1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y1 < extents->y1) + extents->y1 = y1; + if (y2 > extents->y2) + extents->y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + } +} + +#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) + +void +CompositeGlyphs(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, int nlist, GlyphListPtr lists, GlyphPtr * glyphs) +{ + PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + + ValidatePicture(pSrc); + ValidatePicture(pDst); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, lists, + glyphs); +} + +Bool +miRealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph) +{ + return TRUE; +} + +void +miUnrealizeGlyph(ScreenPtr pScreen, GlyphPtr glyph) +{ +} + +void +miGlyphs(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) +{ + PicturePtr pPicture; + PixmapPtr pMaskPixmap = 0; + PicturePtr pMask; + ScreenPtr pScreen = pDst->pDrawable->pScreen; + int width = 0, height = 0; + int x, y; + int xDst = list->xOff, yDst = list->yOff; + int n; + GlyphPtr glyph; + int error; + BoxRec extents = { 0, 0, 0, 0 }; + CARD32 component_alpha; + + if (maskFormat) { + GCPtr pGC; + xRectangle rect; + + GlyphExtents(nlist, list, glyphs, &extents); + + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) + return; + width = extents.x2 - extents.x1; + height = extents.y2 - extents.y1; + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + maskFormat->depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pMaskPixmap) + return; + component_alpha = NeedsComponent(maskFormat->format); + pMask = CreatePicture(0, &pMaskPixmap->drawable, + maskFormat, CPComponentAlpha, &component_alpha, + serverClient, &error); + if (!pMask) { + (*pScreen->DestroyPixmap) (pMaskPixmap); + return; + } + pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen); + ValidateGC(&pMaskPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); + FreeScratchGC(pGC); + x = -extents.x1; + y = -extents.y1; + } + else { + pMask = pDst; + x = 0; + y = 0; + } + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) { + glyph = *glyphs++; + pPicture = GlyphPicture(glyph)[pScreen->myNum]; + + if (pPicture) { + if (maskFormat) { + CompositePicture(PictOpAdd, + pPicture, + None, + pMask, + 0, 0, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, glyph->info.height); + } + else { + CompositePicture(op, + pSrc, + pPicture, + pDst, + xSrc + (x - glyph->info.x) - xDst, + ySrc + (y - glyph->info.y) - yDst, + 0, 0, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, glyph->info.height); + } + } + + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + } + if (maskFormat) { + x = extents.x1; + y = extents.y1; + CompositePicture(op, + pSrc, + pMask, + pDst, + xSrc + x - xDst, + ySrc + y - yDst, 0, 0, x, y, width, height); + FreePicture((pointer) pMask, (XID) 0); + (*pScreen->DestroyPixmap) (pMaskPixmap); + } +} -- cgit v1.2.3