Пример #1
0
void
XftGlyphFontSpecRender (Display			    *dpy,
			int			    op,
			Picture			    src,
			Picture			    dst,
			int			    srcx,
			int			    srcy,
			_Xconst XftGlyphFontSpec    *glyphs,
			int			    nglyphs)
{
    int		    i, j;
    XftFont	    *prevPublic;
    XftFontInt	    *firstFont;
    FT_UInt	    missing[XFT_NMISSING];
    int		    nmissing;
    int		    n;
    FT_UInt	    g;
    XftGlyph	    *glyph;
    FT_UInt	    max;
    int		    size, width;
    char	    *char8;
    unsigned short  *char16;
    unsigned int    *char32;
    unsigned int    char_local[NUM_LOCAL];
    unsigned int    *chars;
    XGlyphElt8	    *elts;
    XGlyphElt8	    elts_local[NUM_ELT_LOCAL];
    FcBool	    glyphs_loaded;
    int		    nelt;
    int		    x, y;
    
    if (!nglyphs)
	return;
    
    /*
     * Load missing glyphs.  Have to load them
     * one at a time in case the font changes
     */
    max = 0;
    glyphs_loaded = FcFalse;
    g = glyphs[0].glyph;
    for (i = 0; i < nglyphs; i++)
    {
	XftFont	    *pub = glyphs[i].font;
	XftFontInt  *font = (XftFontInt *) pub;
	g = glyphs[i].glyph;
	if (g > max)
	    max = g;
	nmissing = 0;
	if (XftFontCheckGlyph (dpy, pub, FcTrue, g, missing, &nmissing))
	    glyphs_loaded = FcTrue;
	if (nmissing)
	    XftFontLoadGlyphs (dpy, pub, FcTrue, missing, nmissing);
	if (!font->format)
	    goto bail1;
	if (!font->glyphset)
	    goto bail1;
    }
    
    /*
     * See what encoding size is needed
     */
    if (max < 0x100)
    {
	size = sizeof (char);
	width = 1;
    }
    else if (max < 0x10000)
    {
	size = sizeof (unsigned short);
	width = 2;
    }
    else
    {
	size = sizeof (unsigned int);
	width = 4;
    }
    chars = char_local;
    if (nglyphs * size > NUM_LOCAL)
    {
	chars = malloc (nglyphs * size);
	if (!chars)
	    goto bail1;
    }
    char8 = (char *) chars;
    char16 = (unsigned short *) chars;
    char32 = (unsigned int *) chars;
    
    /*
     * Compute the number of glyph elts needed
     */
    nelt = 1;
    firstFont = 0;
    for (i = 0; i < nglyphs; i++)
    {
	XftFont	    *pub = glyphs[i].font;
	XftFontInt  *font = (XftFontInt *) pub;
	g = glyphs[i].glyph;
	/* Substitute default for non-existant glyphs */
	if (g >= font->num_glyphs || !font->glyphs[g])
	    g = 0;
	if (font->glyphs[g])
	{
	    firstFont = font;
	    break;
	}
    }
    if (i == nglyphs)
	goto bail2;
    glyph = firstFont->glyphs[g];
    x = glyphs[i].x + glyph->metrics.xOff;
    y = glyphs[i].y + glyph->metrics.yOff;
    prevPublic = 0;
    while (++i < nglyphs)
    {
	XftFont	    *pub = glyphs[i].font;
	XftFontInt  *font = (XftFontInt *) pub;
	g = glyphs[i].glyph;
	/* Substitute default for non-existant glyphs */
	if (g >= font->num_glyphs || !font->glyphs[g])
	    g = 0;
	/* 
	 * check to see if the glyph is placed where it would
	 * fall using the normal spacing
	 */
	if ((glyph = font->glyphs[g]))
	{
	    if (pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y)
	    {
		prevPublic = pub;
		x = glyphs[i].x;
		y = glyphs[i].y;
		++nelt;
	    }
	    x += glyph->metrics.xOff;
	    y += glyph->metrics.yOff;
	}
    }

    elts = elts_local;
    if (nelt > NUM_ELT_LOCAL)
    {
	elts = malloc (nelt * sizeof (XGlyphElt8));
	if (!elts)
	    goto bail2;
    }

    /*
     * Generate the list of glyph elts
     */
    nelt = 0;
    x = y = 0;
    n = 0;
    j = 0;
    prevPublic = 0;
    for (i = 0; i < nglyphs; i++)
    {
	XftFont	    *pub = glyphs[i].font;
	XftFontInt  *font = (XftFontInt *) pub;
	
	g = glyphs[i].glyph;
	/* Substitute default for non-existant glyphs */
	if (g >= font->num_glyphs || !font->glyphs[g])
	    g = 0;
	if ((glyph = font->glyphs[g]))
	{
	    if (!i || pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y)
	    {
		if (n)
		{
		    elts[nelt].nchars = n;
		    nelt++;
		}
		elts[nelt].glyphset = font->glyphset;
		elts[nelt].chars = char8 + size * j;
		elts[nelt].xOff = glyphs[i].x - x;
		elts[nelt].yOff = glyphs[i].y - y;
		prevPublic = pub;
		x = glyphs[i].x;
		y = glyphs[i].y;
		n = 0;
	    }
	    switch (width) {
	    case 1: char8[j] = (char) g; break;
	    case 2: char16[j] = (unsigned short) g; break;
	    case 4: char32[j] = (unsigned int) g; break;
	    }
	    x += glyph->metrics.xOff;
	    y += glyph->metrics.yOff;
	    j++;
	    n++;
	}
    }
    if (n)
    {
	elts[nelt].nchars = n;
	nelt++;
    }
    switch (width) {
    case 1:
	XRenderCompositeText8 (dpy, op, src, dst, firstFont->format,
			       srcx, srcy, glyphs[0].x, glyphs[0].y,
			       elts, nelt);
	break;
    case 2:
	XRenderCompositeText16 (dpy, op, src, dst, firstFont->format,
				srcx, srcy, glyphs[0].x, glyphs[0].y,
				(XGlyphElt16 *) elts, nelt);
	break;
    case 4:
	XRenderCompositeText32 (dpy, op, src, dst, firstFont->format,
				srcx, srcy, glyphs[0].x, glyphs[0].y,
				(XGlyphElt32 *) elts, nelt);
	break;
    }

    if (elts != elts_local)
	free (elts);
bail2:
    if (chars != char_local)
	free (chars);
bail1:
    if (glyphs_loaded)
	for (i = 0; i < nglyphs; i++)
	    _XftFontManageMemory (dpy, glyphs[i].font);
}
Пример #2
0
/** Composite glyphs on each screen into the requested picture.  If
 *  either the src or dest picture has not been allocated due to lazy
 *  window creation, this request will gracefully return. */
static int
dmxProcRenderCompositeGlyphs(ClientPtr client)
{
    int ret;

    REQUEST(xRenderCompositeGlyphsReq);

    ret = dmxSaveRenderVector[stuff->renderReqType] (client);

    /* For the following to work with PanoramiX, it assumes that Render
     * wraps the ProcRenderVector after dmxRenderInit has been called.
     */
    if (ret == Success) {
        PicturePtr pSrc;
        dmxPictPrivPtr pSrcPriv;
        PicturePtr pDst;
        dmxPictPrivPtr pDstPriv;
        PictFormatPtr pFmt;
        XRenderPictFormat *pFormat;
        int size;

        int scrnNum;
        DMXScreenInfo *dmxScreen;

        CARD8 *buffer;
        CARD8 *end;
        int space;

        int nglyph;
        char *glyphs;
        char *curGlyph;

        xGlyphElt *elt;
        int nelt;
        XGlyphElt8 *elts;
        XGlyphElt8 *curElt;

        GlyphSetPtr glyphSet;
        dmxGlyphPrivPtr glyphPriv;

        dixLookupResourceByType((pointer *) &pSrc,
                                stuff->src, PictureType, client, DixReadAccess);

        pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
        if (!pSrcPriv->pict)
            return ret;

        dixLookupResourceByType((pointer *) &pDst,
                                stuff->dst, PictureType,
                                client, DixWriteAccess);

        pDstPriv = DMX_GET_PICT_PRIV(pDst);
        if (!pDstPriv->pict)
            return ret;

        scrnNum = pDst->pDrawable->pScreen->myNum;
        dmxScreen = &dmxScreens[scrnNum];

        /* Note: If the back-end display has been detached, then it
         * should not be possible to reach here since the pSrcPriv->pict
         * and pDstPriv->pict will have already been set to 0.
         */
        if (!dmxScreen->beDisplay)
            return ret;

        if (stuff->maskFormat)
            dixLookupResourceByType((pointer *) &pFmt,
                                    stuff->maskFormat, PictFormatType,
                                    client, DixReadAccess);
        else
            pFmt = NULL;

        pFormat = dmxFindFormat(dmxScreen, pFmt);

        switch (stuff->renderReqType) {
        case X_RenderCompositeGlyphs8:
            size = sizeof(CARD8);
            break;
        case X_RenderCompositeGlyphs16:
            size = sizeof(CARD16);
            break;
        case X_RenderCompositeGlyphs32:
            size = sizeof(CARD32);
            break;
        default:
            return BadPictOp;   /* Can't happen */
        }

        buffer = (CARD8 *) (stuff + 1);
        end = (CARD8 *) stuff + (stuff->length << 2);
        nelt = 0;
        nglyph = 0;
        while (buffer + sizeof(xGlyphElt) < end) {
            elt = (xGlyphElt *) buffer;
            buffer += sizeof(xGlyphElt);

            if (elt->len == 0xff) {
                buffer += 4;
            }
            else {
                nelt++;
                nglyph += elt->len;
                space = size * elt->len;
                if (space & 3)
                    space += 4 - (space & 3);
                buffer += space;
            }
        }

        /* The following only works for Render version > 0.2 */

        /* All of the XGlyphElt* structure sizes are identical */
        elts = malloc(nelt * sizeof(XGlyphElt8));
        if (!elts)
            return BadAlloc;

        glyphs = malloc(nglyph * size);
        if (!glyphs) {
            free(elts);
            return BadAlloc;
        }

        buffer = (CARD8 *) (stuff + 1);
        end = (CARD8 *) stuff + (stuff->length << 2);
        curGlyph = glyphs;
        curElt = elts;

        dixLookupResourceByType((pointer *) &glyphSet,
                                stuff->glyphset, GlyphSetType,
                                client, DixReadAccess);
        glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);

        while (buffer + sizeof(xGlyphElt) < end) {
            elt = (xGlyphElt *) buffer;
            buffer += sizeof(xGlyphElt);

            if (elt->len == 0xff) {
                dixLookupResourceByType((pointer *) &glyphSet,
                                        *((CARD32 *) buffer),
                                        GlyphSetType, client, DixReadAccess);
                glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
                buffer += 4;
            }
            else {
                curElt->glyphset = glyphPriv->glyphSets[scrnNum];
                curElt->xOff = elt->deltax;
                curElt->yOff = elt->deltay;
                curElt->nchars = elt->len;
                curElt->chars = curGlyph;

                memcpy(curGlyph, buffer, size * elt->len);
                curGlyph += size * elt->len;

                curElt++;

                space = size * elt->len;
                if (space & 3)
                    space += 4 - (space & 3);
                buffer += space;
            }
        }

        switch (stuff->renderReqType) {
        case X_RenderCompositeGlyphs8:
            XRenderCompositeText8(dmxScreen->beDisplay, stuff->op,
                                  pSrcPriv->pict, pDstPriv->pict,
                                  pFormat,
                                  stuff->xSrc, stuff->ySrc, 0, 0, elts, nelt);
            break;
        case X_RenderCompositeGlyphs16:
            XRenderCompositeText16(dmxScreen->beDisplay, stuff->op,
                                   pSrcPriv->pict, pDstPriv->pict,
                                   pFormat,
                                   stuff->xSrc, stuff->ySrc,
                                   0, 0, (XGlyphElt16 *) elts, nelt);
            break;
        case X_RenderCompositeGlyphs32:
            XRenderCompositeText32(dmxScreen->beDisplay, stuff->op,
                                   pSrcPriv->pict, pDstPriv->pict,
                                   pFormat,
                                   stuff->xSrc, stuff->ySrc,
                                   0, 0, (XGlyphElt32 *) elts, nelt);
            break;
        }

        dmxSync(dmxScreen, FALSE);

        free(elts);
        free(glyphs);
    }

    return ret;
}
Пример #3
0
static void single(struct test *t, enum target target)
{
	struct glyph_iter gi;
	int n;

	printf("Testing single glyph (%s): ", test_target_name(target));
	fflush(stdout);

	glyph_iter_init(&gi, t, target);
	while (glyph_iter_next(&gi)) {
		XGlyphElt8 elt;
		char id[N_GLYPHS];

		for (n = 0; n < N_GLYPHS; n++) {
			id[n] = n;

			elt.chars = &id[n];
			elt.nchars = 1;
			elt.xOff = 0;
			elt.yOff = 0;

			clear(gi.out.dpy, &gi.out.tt, &colors[gi.dst_color]);
			elt.glyphset = gi.out.glyphset;
			XRenderCompositeText8 (gi.out.dpy->dpy, gi.op,
					       gi.out.src,
					       gi.out.tt.picture,
					       gi.out.mask_format,
					       0, 0,
					       0, 8,
					       &elt, 1);

			clear(gi.ref.dpy, &gi.ref.tt, &colors[gi.dst_color]);
			elt.glyphset = gi.ref.glyphset;
			XRenderCompositeText8 (gi.ref.dpy->dpy, gi.op,
					       gi.ref.src,
					       gi.ref.tt.picture,
					       gi.ref.mask_format,
					       0, 0,
					       0, 8,
					       &elt, 1);
			test_compare(t,
				     gi.out.tt.draw, gi.out.tt.format,
				     gi.ref.tt.draw, gi.ref.tt.format,
				     0, 0, gi.out.tt.width, gi.out.tt.height,
				     glyph_iter_to_string(&gi,
							  "glyph=%s",
							  glyph_name(n)));
		}

		elt.chars = &id[0];
		elt.nchars = n;
		clear(gi.out.dpy, &gi.out.tt, &colors[gi.dst_color]);
		elt.glyphset = gi.out.glyphset;
		XRenderCompositeText8 (gi.out.dpy->dpy, gi.op,
				       gi.out.src,
				       gi.out.tt.picture,
				       gi.out.mask_format,
				       0, 0,
				       0, 8,
				       &elt, 1);

		clear(gi.ref.dpy, &gi.ref.tt, &colors[gi.dst_color]);
		elt.glyphset = gi.ref.glyphset;
		XRenderCompositeText8 (gi.ref.dpy->dpy, gi.op,
				       gi.ref.src,
				       gi.ref.tt.picture,
				       gi.ref.mask_format,
				       0, 0,
				       0, 8,
				       &elt, 1);
		test_compare(t,
			     gi.out.tt.draw, gi.out.tt.format,
			     gi.ref.tt.draw, gi.ref.tt.format,
			     0, 0, gi.out.tt.width, gi.out.tt.height,
			     glyph_iter_to_string(&gi, "all"));
	}
	glyph_iter_fini(&gi);
}