/** 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; }
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); }