Exemple #1
0
/* All caches for a single format share a single pixmap for glyph storage,
 * allowing mixing glyphs of different sizes without paying a penalty
 * for switching between mask pixmaps. (Note that for a size of font
 * right at the border between two sizes, we might be switching for almost
 * every glyph.)
 *
 * This function allocates the storage pixmap, and then fills in the
 * rest of the allocated structures for all caches with the given format.
 */
static Bool
exaRealizeGlyphCaches(ScreenPtr pScreen, unsigned int format)
{
    ExaScreenPriv(pScreen);

    int depth = PIXMAN_FORMAT_DEPTH(format);
    PictFormatPtr pPictFormat;
    PixmapPtr pPixmap;
    PicturePtr pPicture;
    CARD32 component_alpha;
    int height;
    int i;
    int error;

    pPictFormat = PictureMatchFormat(pScreen, depth, format);
    if (!pPictFormat)
        return FALSE;

    /* Compute the total vertical size needed for the format */

    height = 0;
    for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
        ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
        int rows;

        if (cache->format != format)
            continue;

        cache->yOffset = height;

        rows = (cache->size + cache->columns - 1) / cache->columns;
        height += rows * cache->glyphHeight;
    }

    /* Now allocate the pixmap and picture */
    pPixmap = (*pScreen->CreatePixmap) (pScreen,
                                        CACHE_PICTURE_WIDTH, height, depth, 0);
    if (!pPixmap)
        return FALSE;

    component_alpha = NeedsComponent(pPictFormat->format);
    pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
                             CPComponentAlpha, &component_alpha, serverClient,
                             &error);

    (*pScreen->DestroyPixmap) (pPixmap);        /* picture holds a refcount */

    if (!pPicture)
        return FALSE;

    /* And store the picture in all the caches for the format */
    for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
        ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
        int j;

        if (cache->format != format)
            continue;

        cache->picture = pPicture;
        cache->picture->refcnt++;
        cache->hashEntries = malloc(sizeof(int) * cache->hashSize);
        cache->glyphs = malloc(sizeof(ExaCachedGlyphRec) * cache->size);
        cache->glyphCount = 0;

        if (!cache->hashEntries || !cache->glyphs)
            goto bail;

        for (j = 0; j < cache->hashSize; j++)
            cache->hashEntries[j] = -1;

        cache->evictionPosition = rand() % cache->size;
    }

    /* Each cache references the picture individually */
    FreePicture((pointer) pPicture, (XID) 0);
    return TRUE;

 bail:
    exaUnrealizeGlyphCaches(pScreen, format);
    return FALSE;
}
Exemple #2
0
void
exaGlyphs(CARD8 op,
          PicturePtr pSrc,
          PicturePtr pDst,
          PictFormatPtr maskFormat,
          INT16 xSrc,
          INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
    PixmapPtr pMaskPixmap = 0;
    PicturePtr pMask = NULL;
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
    int width = 0, height = 0;
    int x, y;
    int first_xOff = list->xOff, first_yOff = list->yOff;
    int n;
    GlyphPtr glyph;
    int error;
    BoxRec extents = { 0, 0, 0, 0 };
    CARD32 component_alpha;
    ExaGlyphBuffer buffer;

    if (maskFormat) {
        ExaScreenPriv(pScreen);
        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;

        if (maskFormat->depth == 1) {
            PictFormatPtr a8Format = PictureMatchFormat(pScreen, 8, PICT_a8);

            if (a8Format)
                maskFormat = a8Format;
        }

        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 ||
            (!component_alpha && pExaScr->info->CheckComposite &&
             !(*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, NULL, pMask)))
        {
            PictFormatPtr argbFormat;

            (*pScreen->DestroyPixmap) (pMaskPixmap);

            if (!pMask)
                return;

            /* The driver can't seem to composite to a8, let's try argb (but
             * without component-alpha) */
            FreePicture((pointer) pMask, (XID) 0);

            argbFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8);

            if (argbFormat)
                maskFormat = argbFormat;

            pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
                                                    maskFormat->depth,
                                                    CREATE_PIXMAP_USAGE_SCRATCH);
            if (!pMaskPixmap)
                return;

            pMask = CreatePicture(0, &pMaskPixmap->drawable, maskFormat, 0, 0,
                                  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 {
        x = 0;
        y = 0;
    }
    buffer.count = 0;
    buffer.mask = NULL;
    while (nlist--) {
        x += list->xOff;
        y += list->yOff;
        n = list->len;
        while (n--) {
            glyph = *glyphs++;

            if (glyph->info.width > 0 && glyph->info.height > 0) {
                /* pGlyph->info.{x,y} compensate for empty space in the glyph. */
                if (maskFormat) {
                    if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
                                       0, 0, 0, 0, x - glyph->info.x,
                                       y - glyph->info.y) ==
                        ExaGlyphNeedFlush) {
                        exaGlyphsToMask(pMask, &buffer);
                        exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
                                       0, 0, 0, 0, x - glyph->info.x,
                                       y - glyph->info.y);
                    }
                }
                else {
                    if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
                                       xSrc + (x - glyph->info.x) - first_xOff,
                                       ySrc + (y - glyph->info.y) - first_yOff,
                                       0, 0, x - glyph->info.x,
                                       y - glyph->info.y)
                        == ExaGlyphNeedFlush) {
                        exaGlyphsToDst(pSrc, pDst, &buffer);
                        exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
                                       xSrc + (x - glyph->info.x) - first_xOff,
                                       ySrc + (y - glyph->info.y) - first_yOff,
                                       0, 0, x - glyph->info.x,
                                       y - glyph->info.y);
                    }
                }
            }

            x += glyph->info.xOff;
            y += glyph->info.yOff;
        }
        list++;
    }

    if (buffer.count) {
        if (maskFormat)
            exaGlyphsToMask(pMask, &buffer);
        else
            exaGlyphsToDst(pSrc, pDst, &buffer);
    }

    if (maskFormat) {
        x = extents.x1;
        y = extents.y1;
        CompositePicture(op,
                         pSrc,
                         pMask,
                         pDst,
                         xSrc + x - first_xOff,
                         ySrc + y - first_yOff, 0, 0, x, y, width, height);
        FreePicture((pointer) pMask, (XID) 0);
        (*pScreen->DestroyPixmap) (pMaskPixmap);
    }
}
void
uxa_glyphs(CARD8 op,
	   PicturePtr pSrc,
	   PicturePtr pDst,
	   PictFormatPtr maskFormat,
	   INT16 xSrc, INT16 ySrc,
	   int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
	ScreenPtr screen = pDst->pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);

	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
		int ok;

		uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW);
		uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO);
		ok = glamor_glyphs_nf(op,
				     pSrc, pDst, maskFormat,
				     xSrc, ySrc, nlist, list, glyphs);
		uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO);
		uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW);

		if (!ok)
			goto fallback;

		return;
	}

	if (!uxa_screen->info->prepare_composite ||
	    uxa_screen->force_fallback ||
	    !uxa_drawable_is_offscreen(pDst->pDrawable) ||
	    pDst->alphaMap || pSrc->alphaMap ||
	    /* XXX we fail to handle (rare) non-solid sources correctly. */
	    !is_solid(pSrc)) {
fallback:
	    uxa_check_glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
	    return;
	}

	/* basic sanity check */
	if (uxa_screen->info->check_composite &&
	    !uxa_screen->info->check_composite(op, pSrc, NULL, pDst, 0, 0)) {
		goto fallback;
	}

	ValidatePicture(pSrc);
	ValidatePicture(pDst);

	if (!maskFormat) {
		/* If we don't have a mask format but all the glyphs have the same format,
		 * require ComponentAlpha and don't intersect, use the glyph format as mask
		 * format for the full benefits of the glyph cache.
		 */
		if (NeedsComponent(list[0].format->format)) {
			Bool sameFormat = TRUE;
			int i;

			maskFormat = list[0].format;

			for (i = 0; i < nlist; i++) {
				if (maskFormat->format != list[i].format->format) {
					sameFormat = FALSE;
					break;
				}
			}

			if (!sameFormat ||
			    uxa_glyphs_intersect(nlist, list, glyphs))
				maskFormat = NULL;
		}
	}

	if (!maskFormat) {
		if (uxa_glyphs_to_dst(op, pSrc, pDst,
				      xSrc, ySrc,
				      nlist, list, glyphs))
			goto fallback;
	} else {
		if (uxa_glyphs_via_mask(op,
					pSrc, pDst, maskFormat,
					xSrc, ySrc,
					nlist, list, glyphs))
			goto fallback;
	}
}
static int
uxa_glyphs_via_mask(CARD8 op,
		    PicturePtr pSrc,
		    PicturePtr pDst,
		    PictFormatPtr maskFormat,
		    INT16 xSrc, INT16 ySrc,
		    int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
	ScreenPtr screen = pDst->pDrawable->pScreen;
	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
	CARD32 component_alpha;
	PixmapPtr pixmap, white_pixmap;
	PicturePtr glyph_atlas, mask, white;
	int xDst = list->xOff, yDst = list->yOff;
	int x, y, width, height;
	int dst_off_x, dst_off_y;
	int n, error;
	BoxRec box;

	uxa_glyph_extents(nlist, list, glyphs, &box);
	if (box.x2 <= box.x1 || box.y2 <= box.y1)
		return 0;

	dst_off_x = box.x1;
	dst_off_y = box.y1;

	width  = box.x2 - box.x1;
	height = box.y2 - box.y1;
	x = -box.x1;
	y = -box.y1;

	if (maskFormat->depth == 1) {
		PictFormatPtr a8Format =
			PictureMatchFormat(screen, 8, PICT_a8);

		if (!a8Format)
			return -1;

		maskFormat = a8Format;
	}

	pixmap = screen->CreatePixmap(screen, width, height,
				      maskFormat->depth,
				      CREATE_PIXMAP_USAGE_SCRATCH);
	if (!pixmap)
		return 1;

	if (!uxa_pixmap_is_offscreen(pixmap)) {
		screen->DestroyPixmap(pixmap);
		return -1;
	}

	white_pixmap = NULL;
	white = create_white_solid(screen);
	if (white)
		white_pixmap = uxa_get_drawable_pixmap(white->pDrawable);
	if (!white_pixmap) {
		if (white)
			FreePicture(white, 0);
		screen->DestroyPixmap(pixmap);
		return -1;
	}

	uxa_clear_pixmap(screen, uxa_screen, pixmap);

	component_alpha = NeedsComponent(maskFormat->format);
	mask = CreatePicture(0, &pixmap->drawable,
			      maskFormat, CPComponentAlpha,
			      &component_alpha, serverClient, &error);
	screen->DestroyPixmap(pixmap);

	if (!mask) {
		FreePicture(white, 0);
		return 1;
	}

	ValidatePicture(mask);

	glyph_atlas = NULL;
	while (nlist--) {
		x += list->xOff;
		y += list->yOff;
		n = list->len;
		while (n--) {
			GlyphPtr glyph = *glyphs++;
			PicturePtr this_atlas;
			int glyph_x, glyph_y;
			struct uxa_glyph *priv;

			if (glyph->info.width == 0 || glyph->info.height == 0)
				goto next_glyph;

			priv = uxa_glyph_get_private(glyph);
			if (priv != NULL) {
				glyph_x = priv->x;
				glyph_y = priv->y;
				this_atlas = priv->cache->picture;
			} else {
				if (glyph_atlas) {
					uxa_screen->info->done_composite(pixmap);
					glyph_atlas = NULL;
				}
				this_atlas = uxa_glyph_cache(screen, glyph, &glyph_x, &glyph_y);
				if (this_atlas == NULL) {
					/* no cache for this glyph */
					this_atlas = GetGlyphPicture(glyph, screen);
					glyph_x = glyph_y = 0;
				}
			}

			if (this_atlas != glyph_atlas) {
				PixmapPtr glyph_pixmap;

				if (glyph_atlas)
					uxa_screen->info->done_composite(pixmap);

				glyph_pixmap =
					uxa_get_drawable_pixmap(this_atlas->pDrawable);
				if (!uxa_pixmap_is_offscreen(glyph_pixmap) ||
				    !uxa_screen->info->prepare_composite(PictOpAdd,
									 white, this_atlas, mask,
									 white_pixmap, glyph_pixmap, pixmap)) {
					FreePicture(white, 0);
					FreePicture(mask, 0);
					return -1;
				}

				glyph_atlas = this_atlas;
			}

			uxa_screen->info->composite(pixmap,
						    0, 0,
						    glyph_x, glyph_y,
						    x - glyph->info.x,
						    y - glyph->info.y,
						    glyph->info.width,
						    glyph->info.height);

next_glyph:
			x += glyph->info.xOff;
			y += glyph->info.yOff;
		}
		list++;
	}
	if (glyph_atlas)
		uxa_screen->info->done_composite(pixmap);

	uxa_composite(op,
		      pSrc, mask, pDst,
		      dst_off_x + xSrc - xDst,
		      dst_off_y + ySrc - yDst,
		      0, 0,
		      dst_off_x, dst_off_y,
		      width, height);

	FreePicture(white, 0);
	FreePicture(mask, 0);
	return 0;
}
static void
uxa_check_glyphs(CARD8 op,
		 PicturePtr src,
		 PicturePtr dst,
		 PictFormatPtr maskFormat,
		 INT16 xSrc,
		 INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
	pixman_image_t *image;
	PixmapPtr scratch;
	PicturePtr mask, mask_src = NULL, mask_dst = NULL, white = NULL;
	int width = 0, height = 0;
	int x, y, n;
	int xDst = list->xOff, yDst = list->yOff;
	BoxRec extents = { 0, 0, 0, 0 };
	CARD8 mask_op = 0;

	if (maskFormat) {
		pixman_format_code_t format;
		CARD32 component_alpha;
		xRenderColor color;
		int error;

		uxa_glyph_extents(nlist, list, glyphs, &extents);
		if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
			return;

		width = extents.x2 - extents.x1;
		height = extents.y2 - extents.y1;

		format = maskFormat->format |
			(BitsPerPixel(maskFormat->depth) << 24);
		image =
			pixman_image_create_bits(format, width, height, NULL, 0);
		if (!image)
			return;

		scratch = GetScratchPixmapHeader(dst->pDrawable->pScreen, width, height,
						 PIXMAN_FORMAT_DEPTH(format),
						 PIXMAN_FORMAT_BPP(format),
						 pixman_image_get_stride(image),
						 pixman_image_get_data(image));

		if (!scratch) {
			pixman_image_unref(image);
			return;
		}

		component_alpha = NeedsComponent(maskFormat->format);
		mask = CreatePicture(0, &scratch->drawable,
				     maskFormat, CPComponentAlpha,
				     &component_alpha, serverClient, &error);
		if (!mask) {
			FreeScratchPixmapHeader(scratch);
			pixman_image_unref(image);
			return;
		}
		ValidatePicture(mask);

		x = -extents.x1;
		y = -extents.y1;

		color.red = color.green = color.blue = color.alpha = 0xffff;
		white = CreateSolidPicture(0, &color, &error);

		mask_op = op;
		op = PictOpAdd;

		mask_src = src;
		src = white;

		mask_dst = dst;
		dst = mask;
	} else {
		mask = dst;
		x = 0;
		y = 0;
	}

	while (nlist--) {
		x += list->xOff;
		y += list->yOff;
		n = list->len;
		while (n--) {
			GlyphPtr glyph = *glyphs++;
			PicturePtr g = GetGlyphPicture(glyph, dst->pDrawable->pScreen);
			if (g) {
				CompositePicture(op, src, g, dst,
						 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 (white)
		FreePicture(white, 0);

	if (maskFormat) {
		x = extents.x1;
		y = extents.y1;
		CompositePicture(mask_op, mask_src, mask, mask_dst,
				 xSrc + x - xDst,
				 ySrc + y - yDst,
				 0, 0,
				 x, y,
				 width, height);
		FreePicture(mask, 0);
		FreeScratchPixmapHeader(scratch);
		pixman_image_unref(image);
	}
}
/* All caches for a single format share a single pixmap for glyph storage,
 * allowing mixing glyphs of different sizes without paying a penalty
 * for switching between source pixmaps. (Note that for a size of font
 * right at the border between two sizes, we might be switching for almost
 * every glyph.)
 *
 * This function allocates the storage pixmap, and then fills in the
 * rest of the allocated structures for all caches with the given format.
 */
static Bool uxa_realize_glyph_caches(ScreenPtr pScreen)
{
	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
	unsigned int formats[] = {
		PIXMAN_a8,
		PIXMAN_a8r8g8b8,
	};
	int i;

	if (uxa_screen->glyph_cache_initialized)
		return TRUE;

	uxa_screen->glyph_cache_initialized = TRUE;
	memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches));

	for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
		uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
		PixmapPtr pixmap;
		PicturePtr picture;
		CARD32 component_alpha;
		int depth = PIXMAN_FORMAT_DEPTH(formats[i]);
		int error;
		PictFormatPtr pPictFormat = PictureMatchFormat(pScreen, depth, formats[i]);
		if (!pPictFormat)
			goto bail;

		/* Now allocate the pixmap and picture */
		pixmap = pScreen->CreatePixmap(pScreen,
					       CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE, depth,
					       INTEL_CREATE_PIXMAP_TILING_X);
		if (!pixmap)
			goto bail;
		if (!uxa_pixmap_is_offscreen(pixmap)) {
			/* Presume shadow is in-effect */
			pScreen->DestroyPixmap(pixmap);
			uxa_unrealize_glyph_caches(pScreen);
			return TRUE;
		}

		component_alpha = NeedsComponent(pPictFormat->format);
		picture = CreatePicture(0, &pixmap->drawable, pPictFormat,
					CPComponentAlpha, &component_alpha,
					serverClient, &error);

		pScreen->DestroyPixmap(pixmap);

		if (!picture)
			goto bail;

		ValidatePicture(picture);

		cache->picture = picture;
		cache->glyphs = calloc(sizeof(GlyphPtr), GLYPH_CACHE_SIZE);
		if (!cache->glyphs)
			goto bail;

		cache->evict = rand() % GLYPH_CACHE_SIZE;
	}
	assert(i == UXA_NUM_GLYPH_CACHE_FORMATS);

	return TRUE;

bail:
	uxa_unrealize_glyph_caches(pScreen);
	return FALSE;
}
Exemple #7
0
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);
    }
}