/** Render string of 16-bit \a chars (foreground only) in \a pDrawable * on the back-end server associated with \a pDrawable's screen. If * the offscreen optimization is enabled, only draw when \a pDrawable * is at least partially visible. */ int dmxPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) { DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); unsigned long n, i; int w; CharInfoPtr charinfo[255]; Drawable draw; GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, &n, charinfo); /* Calculate text width */ w = 0; for (i = 0; i < n; i++) w += charinfo[i]->metrics.characterWidth; if (n != 0 && !DMX_GCOPS_OFFSCREEN(pDrawable)) { DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); XDrawString16(dmxScreen->beDisplay, draw, pGCPriv->gc, x, y, (XChar2b *)chars, count); dmxSync(dmxScreen, FALSE); } return x+w; }
static void glamor_get_glyphs(FontPtr font, glamor_font_t *glamor_font, int count, char *chars, Bool sixteen, CharInfoPtr *charinfo) { unsigned long nglyphs; FontEncoding encoding; int char_step; int c; if (sixteen) { char_step = 2; if (FONTLASTROW(font) == 0) encoding = Linear16Bit; else encoding = TwoD16Bit; } else { char_step = 1; encoding = Linear8Bit; } /* If the font has a default character, then we shouldn't have to * worry about missing glyphs, so just get the whole string all at * once. Otherwise, we have to fetch chars one at a time to notice * missing ones. */ if (glamor_font->default_char) { GetGlyphs(font, (unsigned long) count, (unsigned char *) chars, encoding, &nglyphs, charinfo); /* Make sure it worked. There's a bug in libXfont through * version 1.4.7 which would cause it to fail when the font is * a 2D font without a first row, and the application sends a * 1-d request. In this case, libXfont would return zero * glyphs, even when the font had a default character. * * It's easy enough for us to work around that bug here by * simply checking the returned nglyphs and falling through to * the one-at-a-time code below. Not doing this check would * result in uninitialized memory accesses in the rendering code. */ if (nglyphs == count) return; } for (c = 0; c < count; c++) { GetGlyphs(font, 1, (unsigned char *) chars, encoding, &nglyphs, &charinfo[c]); if (!nglyphs) charinfo[c] = NULL; chars += char_step; } }
static void glamor_get_glyphs(FontPtr font, glamor_font_t *glamor_font, int count, char *chars, Bool sixteen, CharInfoPtr *charinfo) { unsigned long nglyphs; FontEncoding encoding; int char_step; if (sixteen) { char_step = 2; if (FONTLASTROW(font) == 0) encoding = Linear16Bit; else encoding = TwoD16Bit; } else { char_step = 1; encoding = Linear8Bit; } /* If the font has a default character, then we don't have to * worry about missing glyphs, so just get the whole string all at * once. Otherwise, we have to fetch chars one at a time to notice * missing ones. */ if (glamor_font->default_char) { GetGlyphs(font, (unsigned long) count, (unsigned char *) chars, encoding, &nglyphs, charinfo); } else { int c; for (c = 0; c < count; c++) { GetGlyphs(font, 1, (unsigned char *) chars, encoding, &nglyphs, &charinfo[c]); if (!nglyphs) charinfo[c] = NULL; chars += char_step; } } }
static int MakeBitmapsFromFont(FontPtr pFont, int first, int count, int list_base) { unsigned long i, nglyphs; CARD8 chs[2]; /* the font index we are going after */ CharInfoPtr pci; int rv; /* return value */ int encoding = (FONTLASTROW(pFont) == 0) ? Linear16Bit : TwoD16Bit; CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES, FALSE)); CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_LSB_FIRST, BITMAP_BIT_ORDER == LSBFirst)); CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, 0)); CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, 0)); CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, 0)); CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_ALIGNMENT, GLYPHPADBYTES)); for (i = 0; i < count; i++) { chs[0] = (first + i) >> 8; /* high byte is first byte */ chs[1] = first + i; (*pFont->get_glyphs) (pFont, 1, chs, (FontEncoding) encoding, &nglyphs, &pci); /* ** Define a display list containing just a glBitmap() call. */ CALL_NewList(GET_DISPATCH(), (list_base + i, GL_COMPILE)); if (nglyphs) { rv = __glXMakeBitmapFromGlyph(pFont, pci); if (rv) { return rv; } } CALL_EndList(GET_DISPATCH(), ()); } return Success; }
static int glamor_text(DrawablePtr drawable, GCPtr gc, glamor_font_t *glamor_font, glamor_program *prog, int x, int y, int count, char *s_chars, CharInfoPtr *charinfo, Bool sixteen) { unsigned char *chars = (unsigned char *) s_chars; FontPtr font = gc->font; int off_x, off_y; int c; int nglyph; GLshort *v; char *vbo_offset; CharInfoPtr ci; int firstRow = font->info.firstRow; int firstCol = font->info.firstCol; int glyph_spacing_x = glamor_font->glyph_width_bytes * 8; int glyph_spacing_y = glamor_font->glyph_height; int box_x, box_y; PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); /* Set the font as texture 1 */ glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id); glUniform1i(prog->font_uniform, 1); /* Set up the vertex buffers for the font and destination */ v = glamor_get_vbo_space(drawable->pScreen, count * (6 * sizeof (GLshort)), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE, 6 * sizeof (GLshort), vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 1); glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE, 6 * sizeof (GLshort), vbo_offset + 4 * sizeof (GLshort)); /* Set the vertex coordinates */ nglyph = 0; for (c = 0; c < count; c++) { if ((ci = *charinfo++)) { int x1 = x + ci->metrics.leftSideBearing; int y1 = y - ci->metrics.ascent; int width = GLYPHWIDTHPIXELS(ci); int height = GLYPHHEIGHTPIXELS(ci); int tx, ty = 0; int row = 0, col; x += ci->metrics.characterWidth; if (sixteen) { if (ci == glamor_font->default_char) { row = glamor_font->default_row; col = glamor_font->default_col; } else { row = chars[0]; col = chars[1]; } if (FONTLASTROW(font) != 0) ty = (row - firstRow) * glyph_spacing_y; else col += row << 8; } else { if (ci == glamor_font->default_char) col = glamor_font->default_col; else col = chars[0]; } tx = (col - firstCol) * glyph_spacing_x; v[ 0] = x1; v[ 1] = y1; v[ 2] = width; v[ 3] = height; v[ 4] = tx; v[ 5] = ty; v += 6; nglyph++; } chars += 1 + sixteen; } glamor_put_vbo_space(drawable->pScreen); if (nglyph != 0) { glEnable(GL_SCISSOR_TEST); glamor_pixmap_loop(pixmap_priv, box_x, box_y) { BoxPtr box = RegionRects(gc->pCompositeClip); int nbox = RegionNumRects(gc->pCompositeClip); glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y); /* Run over the clip list, drawing the glyphs * in each box */ while (nbox--) { glScissor(box->x1 + off_x, box->y1 + off_y, box->x2 - box->x1, box->y2 - box->y1); box++; glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph); } }