summaryrefslogtreecommitdiff
path: root/render/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/render.c')
-rw-r--r--render/render.c156
1 files changed, 121 insertions, 35 deletions
diff --git a/render/render.c b/render/render.c
index caaa2781c..1a1cd7a0e 100644
--- a/render/render.c
+++ b/render/render.c
@@ -1080,24 +1080,31 @@ ProcRenderFreeGlyphSet (ClientPtr client)
}
typedef struct _GlyphNew {
- Glyph id;
- GlyphPtr glyph;
+ Glyph id;
+ GlyphPtr glyph;
+ Bool found;
+ unsigned char sha1[20];
} GlyphNewRec, *GlyphNewPtr;
+#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
+
static int
ProcRenderAddGlyphs (ClientPtr client)
{
GlyphSetPtr glyphSet;
REQUEST(xRenderAddGlyphsReq);
GlyphNewRec glyphsLocal[NLOCALGLYPH];
- GlyphNewPtr glyphsBase, glyphs;
- GlyphPtr glyph;
+ GlyphNewPtr glyphsBase, glyphs, glyph_new;
int remain, nglyphs;
CARD32 *gids;
xGlyphInfo *gi;
CARD8 *bits;
int size;
int err = BadAlloc;
+ int i, screen;
+ PicturePtr pSrc = NULL, pDst = NULL;
+ PixmapPtr pSrcPix = NULL, pDstPix = NULL;
+ CARD32 component_alpha;
REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq);
glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
@@ -1114,11 +1121,15 @@ ProcRenderAddGlyphs (ClientPtr client)
if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec))
return BadAlloc;
- if (nglyphs <= NLOCALGLYPH)
+ component_alpha = NeedsComponent (glyphSet->format->format);
+
+ if (nglyphs <= NLOCALGLYPH) {
+ memset (glyphsLocal, 0, sizeof (glyphsLocal));
glyphsBase = glyphsLocal;
+ }
else
{
- glyphsBase = (GlyphNewPtr) Xalloc (nglyphs * sizeof (GlyphNewRec));
+ glyphsBase = (GlyphNewPtr) Xcalloc (nglyphs * sizeof (GlyphNewRec));
if (!glyphsBase)
return BadAlloc;
}
@@ -1131,58 +1142,133 @@ ProcRenderAddGlyphs (ClientPtr client)
gi = (xGlyphInfo *) (gids + nglyphs);
bits = (CARD8 *) (gi + nglyphs);
remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs;
- while (remain >= 0 && nglyphs)
+ for (i = 0; i < nglyphs; i++)
{
- glyph = AllocateGlyph (gi, glyphSet->fdepth);
- if (!glyph)
- {
- err = BadAlloc;
- goto bail;
- }
-
- glyphs->glyph = glyph;
- glyphs->id = *gids;
-
- size = glyph->size - sizeof (xGlyphInfo);
+ glyph_new = &glyphs[i];
+ size = gi[i].height * PixmapBytePad (gi[i].width,
+ glyphSet->format->depth);
if (remain < size)
break;
- memcpy ((CARD8 *) (glyph + 1), bits, size);
+
+ err = HashGlyph (&gi[i], bits, size, glyph_new->sha1);
+ if (err)
+ goto bail;
+
+ glyph_new->glyph = FindGlyphByHash (glyph_new->sha1,
+ glyphSet->fdepth);
+
+ if (glyph_new->glyph && glyph_new->glyph != DeletedGlyph)
+ {
+ glyph_new->found = TRUE;
+ }
+ else
+ {
+ GlyphPtr glyph;
+
+ glyph_new->found = FALSE;
+ glyph_new->glyph = glyph = AllocateGlyph (&gi[i], glyphSet->fdepth);
+ if (! glyph)
+ {
+ err = BadAlloc;
+ goto bail;
+ }
+
+ for (screen = 0; screen < screenInfo.numScreens; screen++)
+ {
+ int width = gi[i].width;
+ int height = gi[i].height;
+ int depth = glyphSet->format->depth;
+ ScreenPtr pScreen;
+ int error;
+
+ pScreen = screenInfo.screens[screen];
+ pSrcPix = GetScratchPixmapHeader (pScreen,
+ width, height,
+ depth, depth,
+ -1, bits);
+ if (! pSrcPix)
+ {
+ err = BadAlloc;
+ goto bail;
+ }
+
+ pSrc = CreatePicture (0, &pSrcPix->drawable,
+ glyphSet->format, 0, NULL,
+ serverClient, &error);
+ if (! pSrc)
+ {
+ err = BadAlloc;
+ goto bail;
+ }
+
+ pDstPix = (pScreen->CreatePixmap) (pScreen,
+ width, height, depth);
+
+ GlyphPicture (glyph)[screen] = pDst =
+ CreatePicture (0, &pDstPix->drawable,
+ glyphSet->format,
+ CPComponentAlpha, &component_alpha,
+ serverClient, &error);
+
+ /* The picture takes a reference to the pixmap, so we
+ drop ours. */
+ (pScreen->DestroyPixmap) (pDstPix);
+
+ if (! pDst)
+ {
+ err = BadAlloc;
+ goto bail;
+ }
+
+ CompositePicture (PictOpSrc,
+ pSrc,
+ None,
+ pDst,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ width, height);
+
+ FreePicture ((pointer) pSrc, 0);
+ pSrc = NULL;
+ FreeScratchPixmapHeader (pSrcPix);
+ pSrcPix = NULL;
+ }
+
+ memcpy (glyph_new->glyph->sha1, glyph_new->sha1, 20);
+ }
+
+ glyph_new->id = gids[i];
if (size & 3)
size += 4 - (size & 3);
bits += size;
remain -= size;
- gi++;
- gids++;
- glyphs++;
- nglyphs--;
}
- if (nglyphs || remain)
+ if (remain || i < nglyphs)
{
err = BadLength;
goto bail;
}
- nglyphs = stuff->nglyphs;
if (!ResizeGlyphSet (glyphSet, nglyphs))
{
err = BadAlloc;
goto bail;
}
- glyphs = glyphsBase;
- while (nglyphs--) {
- AddGlyph (glyphSet, glyphs->glyph, glyphs->id);
- glyphs++;
- }
+ for (i = 0; i < nglyphs; i++)
+ AddGlyph (glyphSet, glyphs[i].glyph, glyphs[i].id);
if (glyphsBase != glyphsLocal)
Xfree (glyphsBase);
return client->noClientException;
bail:
- while (glyphs != glyphsBase)
- {
- --glyphs;
- xfree (glyphs->glyph);
- }
+ if (pSrc)
+ FreePicture ((pointer) pSrc, 0);
+ if (pSrcPix)
+ FreeScratchPixmapHeader (pSrcPix);
+ for (i = 0; i < nglyphs; i++)
+ if (glyphs[i].glyph && ! glyphs[i].found)
+ xfree (glyphs[i].glyph);
if (glyphsBase != glyphsLocal)
Xfree (glyphsBase);
return err;