/* ** Make a single GL bitmap from a single X glyph */ static int __glXMakeBitmapFromGlyph(FontPtr font, CharInfoPtr pci) { int i, j; int widthPadded; /* width of glyph in bytes, as padded by X */ int allocBytes; /* bytes to allocate to store bitmap */ int w; /* width of glyph in bits */ int h; /* height of glyph */ register unsigned char *pglyph; register unsigned char *p; unsigned char *allocbuf; #define __GL_CHAR_BUF_SIZE 2048 unsigned char buf[__GL_CHAR_BUF_SIZE]; w = GLYPHWIDTHPIXELS(pci); h = GLYPHHEIGHTPIXELS(pci); widthPadded = GLYPHWIDTHBYTESPADDED(pci); /* ** Use the local buf if possible, otherwise malloc. */ allocBytes = widthPadded * h; if (allocBytes <= __GL_CHAR_BUF_SIZE) { p = buf; allocbuf = 0; } else { p = (unsigned char *) malloc(allocBytes); if (!p) return BadAlloc; allocbuf = p; } /* ** We have to reverse the picture, top to bottom */ pglyph = FONTGLYPHBITS(FONTGLYPHS(font), pci) + (h - 1) * widthPadded; for (j = 0; j < h; j++) { for (i = 0; i < widthPadded; i++) { p[i] = pglyph[i]; } pglyph -= widthPadded; p += widthPadded; } CALL_Bitmap(GET_DISPATCH(), (w, h, -pci->metrics.leftSideBearing, pci->metrics.descent, pci->metrics.characterWidth, 0, allocbuf ? allocbuf : buf)); free(allocbuf); return Success; #undef __GL_CHAR_BUF_SIZE }
void fbImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr * ppciInit, pointer pglyphBase) { FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); CharInfoPtr *ppci; CharInfoPtr pci; unsigned char *pglyph; /* pointer bits in glyph */ int gWidth, gHeight; /* width and height of glyph */ FbStride gStride; /* stride of glyph */ Bool opaque; int n; int gx, gy; void (*glyph) (FbBits *, FbStride, int, FbStip *, FbBits, int, int); FbBits *dst = 0; FbStride dstStride = 0; int dstBpp = 0; int dstXoff = 0, dstYoff = 0; glyph = 0; if (pPriv->and == 0) { fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); switch (dstBpp) { case 8: glyph = fbGlyph8; break; case 16: glyph = fbGlyph16; break; case 24: glyph = fbGlyph24; break; case 32: glyph = fbGlyph32; break; } } x += pDrawable->x; y += pDrawable->y; if (TERMINALFONT(pGC->font) && !glyph ) { opaque = TRUE; } else { int xBack, widthBack; int yBack, heightBack; ppci = ppciInit; n = nglyph; widthBack = 0; while (n--) widthBack += (*ppci++)->metrics.characterWidth; xBack = x; if (widthBack < 0) { xBack += widthBack; widthBack = -widthBack; } yBack = y - FONTASCENT(pGC->font); heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); fbSolidBoxClipped(pDrawable, fbGetCompositeClip(pGC), xBack, yBack, xBack + widthBack, yBack + heightBack, fbAnd(GXcopy, pPriv->bg, pPriv->pm), fbXor(GXcopy, pPriv->bg, pPriv->pm)); opaque = FALSE; } ppci = ppciInit; while (nglyph--) { pci = *ppci++; pglyph = FONTGLYPHBITS(pglyphBase, pci); gWidth = GLYPHWIDTHPIXELS(pci); gHeight = GLYPHHEIGHTPIXELS(pci); if (gWidth && gHeight) { gx = x + pci->metrics.leftSideBearing; gy = y - pci->metrics.ascent; if (glyph && gWidth <= sizeof(FbStip) * 8 && fbGlyphIn(fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) { (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, (FbStip *) pglyph, pPriv->fg, gx + dstXoff, gHeight); } else { gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); fbPutXYImage(pDrawable, fbGetCompositeClip(pGC), pPriv->fg, pPriv->bg, pPriv->pm, GXcopy, opaque, gx, gy, gWidth, gHeight, (FbStip *) pglyph, gStride, 0); } } x += pci->metrics.characterWidth; } }
void fbPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase) { FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); CharInfoPtr pci; unsigned char *pglyph; /* pointer bits in glyph */ int gx, gy; int gWidth, gHeight; /* width and height of glyph */ FbStride gStride; /* stride of glyph */ void (*glyph) (FbBits *, FbStride, int, FbStip *, FbBits, int, int); FbBits *dst = 0; FbStride dstStride = 0; int dstBpp = 0; int dstXoff = 0, dstYoff = 0; glyph = 0; if (pGC->fillStyle == FillSolid && pPriv->and == 0) { fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); switch (dstBpp) { case 8: glyph = fbGlyph8; break; case 16: glyph = fbGlyph16; break; case 24: glyph = fbGlyph24; break; case 32: glyph = fbGlyph32; break; } } x += pDrawable->x; y += pDrawable->y; while (nglyph--) { pci = *ppci++; pglyph = FONTGLYPHBITS(pglyphBase, pci); gWidth = GLYPHWIDTHPIXELS(pci); gHeight = GLYPHHEIGHTPIXELS(pci); if (gWidth && gHeight) { gx = x + pci->metrics.leftSideBearing; gy = y - pci->metrics.ascent; if (glyph && gWidth <= sizeof(FbStip) * 8 && fbGlyphIn(fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) { (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, (FbStip *) pglyph, pPriv->xor, gx + dstXoff, gHeight); } else { gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); fbPushImage(pDrawable, pGC, (FbStip *) pglyph, gStride, 0, gx, gy, gWidth, gHeight); } } x += pci->metrics.characterWidth; } }
void miPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { int width, height; PixmapPtr pPixmap; int nbyLine; /* bytes per line of padded pixmap */ FontPtr pfont; GCPtr pGCtmp; int i; int j; unsigned char *pbits; /* buffer for PutImage */ unsigned char *pb; /* temp pointer into buffer */ CharInfoPtr pci; /* currect char info */ unsigned char *pglyph; /* pointer bits in glyph */ int gWidth, gHeight; /* width and height of glyph */ int nbyGlyphWidth; /* bytes per scanline of glyph */ int nbyPadGlyph; /* server padded line of glyph */ XID gcvals[3]; if (pGC->miTranslate) { x += pDrawable->x; y += pDrawable->y; } pfont = pGC->font; width = FONTMAXBOUNDS(pfont,rightSideBearing) - FONTMINBOUNDS(pfont,leftSideBearing); height = FONTMAXBOUNDS(pfont,ascent) + FONTMAXBOUNDS(pfont,descent); pPixmap = (*pDrawable->pScreen->CreatePixmap)(pDrawable->pScreen, width, height, 1); if (!pPixmap) return; pGCtmp = GetScratchGC(1, pDrawable->pScreen); if (!pGCtmp) { (*pDrawable->pScreen->DestroyPixmap)(pPixmap); return; } gcvals[0] = GXcopy; gcvals[1] = 1; gcvals[2] = 0; DoChangeGC(pGCtmp, GCFunction|GCForeground|GCBackground, gcvals, 0); nbyLine = BitmapBytePad(width); pbits = (unsigned char *)ALLOCATE_LOCAL(height*nbyLine); if (!pbits) { (*pDrawable->pScreen->DestroyPixmap)(pPixmap); FreeScratchGC(pGCtmp); return; } while(nglyph--) { pci = *ppci++; pglyph = FONTGLYPHBITS(pglyphBase, pci); gWidth = GLYPHWIDTHPIXELS(pci); gHeight = GLYPHHEIGHTPIXELS(pci); if (gWidth && gHeight) { nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(pci); nbyPadGlyph = BitmapBytePad(gWidth); if (nbyGlyphWidth == nbyPadGlyph #if GLYPHPADBYTES != 4 && (((int) pglyph) & 3) == 0 #endif ) { pb = pglyph; } else { for (i=0, pb = pbits; i<gHeight; i++, pb = pbits+(i*nbyPadGlyph)) for (j = 0; j < nbyGlyphWidth; j++) *pb++ = *pglyph++; pb = pbits; } if ((pGCtmp->serialNumber) != (pPixmap->drawable.serialNumber)) ValidateGC((DrawablePtr)pPixmap, pGCtmp); (*pGCtmp->ops->PutImage)((DrawablePtr)pPixmap, pGCtmp, pPixmap->drawable.depth, 0, 0, gWidth, gHeight, 0, XYBitmap, (char *)pb); if ((pGC->serialNumber) != (pDrawable->serialNumber)) ValidateGC(pDrawable, pGC); (*pGC->ops->PushPixels)(pGC, pPixmap, pDrawable, gWidth, gHeight, x + pci->metrics.leftSideBearing, y - pci->metrics.ascent); } x += pci->metrics.characterWidth; } (*pDrawable->pScreen->DestroyPixmap)(pPixmap); DEALLOCATE_LOCAL(pbits); FreeScratchGC(pGCtmp); }
glamor_font_t * glamor_font_get(ScreenPtr screen, FontPtr font) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_font_t *privates; glamor_font_t *glamor_font; int overall_width, overall_height; int num_rows; int num_cols; int glyph_width_pixels; int glyph_width_bytes; int glyph_height; int row, col; unsigned char c[2]; CharInfoPtr glyph; unsigned long count; char *bits; if (glamor_priv->glsl_version < 130) return NULL; privates = FontGetPrivate(font, glamor_font_private_index); if (!privates) { privates = calloc(glamor_font_screen_count, sizeof (glamor_font_t)); if (!privates) return NULL; FontSetPrivate(font, glamor_font_private_index, privates); } glamor_font = &privates[screen->myNum]; if (glamor_font->realized) return glamor_font; /* Figure out how many glyphs are in the font */ num_cols = font->info.lastCol - font->info.firstCol + 1; num_rows = font->info.lastRow - font->info.firstRow + 1; /* Figure out the size of each glyph */ glyph_width_pixels = font->info.maxbounds.rightSideBearing - font->info.minbounds.leftSideBearing; glyph_height = font->info.maxbounds.ascent + font->info.maxbounds.descent; glyph_width_bytes = (glyph_width_pixels + 7) >> 3; glamor_font->glyph_width_pixels = glyph_width_pixels; glamor_font->glyph_width_bytes = glyph_width_bytes; glamor_font->glyph_height = glyph_height; /* * Layout the font two blocks of columns wide. * This avoids a problem with some fonts that are too high to fit. */ glamor_font->row_width = glyph_width_bytes * num_cols; if (num_rows > 1) { overall_width = glamor_font->row_width * 2; overall_height = glyph_height * ((num_rows + 1) / 2); } else { overall_width = glamor_font->row_width; overall_height = glyph_height; } if (overall_width > glamor_priv->max_fbo_size || overall_height > glamor_priv->max_fbo_size) { /* fallback if we don't fit inside a texture */ return NULL; } bits = malloc(overall_width * overall_height); if (!bits) return NULL; /* Check whether the font has a default character */ c[0] = font->info.lastRow + 1; c[1] = font->info.lastCol + 1; (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); glamor_font->default_char = count ? glyph : NULL; glamor_font->default_row = font->info.defaultCh >> 8; glamor_font->default_col = font->info.defaultCh; glamor_priv = glamor_get_screen_private(screen); glamor_make_current(glamor_priv); glGenTextures(1, &glamor_font->texture_id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* Paint all of the glyphs */ for (row = 0; row < num_rows; row++) { for (col = 0; col < num_cols; col++) { c[0] = row + font->info.firstRow; c[1] = col + font->info.firstCol; (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); if (count) { char *dst; char *src = glyph->bits; unsigned y; dst = bits; /* get offset of start of first row */ dst += (row / 2) * glyph_height * overall_width; /* add offset into second row */ dst += (row & 1) ? glamor_font->row_width : 0; dst += col * glyph_width_bytes; for (y = 0; y < GLYPHHEIGHTPIXELS(glyph); y++) { memcpy(dst, src, GLYPHWIDTHBYTES(glyph)); dst += overall_width; src += GLYPHWIDTHBYTESPADDED(glyph); } } } } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glamor_priv->suppress_gl_out_of_memory_logging = true; glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, overall_width, overall_height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, bits); glamor_priv->suppress_gl_out_of_memory_logging = false; if (glGetError() == GL_OUT_OF_MEMORY) return NULL; free(bits); glamor_font->realized = TRUE; return glamor_font; }
static Bool glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc, int start_x, int y, unsigned int nglyph, CharInfoPtr *ppci, void *pglyph_base) { ScreenPtr screen = drawable->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv; glamor_program *prog; RegionPtr clip = gc->pCompositeClip; int box_index; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) goto bail; glamor_make_current(glamor_priv); prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_glyph_blt_progs, &glamor_facet_poly_glyph_blt); if (!prog) goto bail; glEnableVertexAttribArray(GLAMOR_VERTEX_POS); start_x += drawable->x; y += drawable->y; glamor_pixmap_loop(pixmap_priv, box_index) { int x; int n; int num_points, max_points; INT16 *points = NULL; int off_x, off_y; char *vbo_offset; glamor_set_destination_drawable(drawable, box_index, FALSE, TRUE, prog->matrix_uniform, &off_x, &off_y); max_points = 500; num_points = 0; x = start_x; for (n = 0; n < nglyph; n++) { CharInfoPtr charinfo = ppci[n]; int w = GLYPHWIDTHPIXELS(charinfo); int h = GLYPHHEIGHTPIXELS(charinfo); uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo); if (w && h) { int glyph_x = x + charinfo->metrics.leftSideBearing; int glyph_y = y - charinfo->metrics.ascent; int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo); int xx, yy; for (yy = 0; yy < h; yy++) { uint8_t *glyph = glyphbits; for (xx = 0; xx < w; glyph += ((xx&7) == 7), xx++) { int pt_x_i = glyph_x + xx; int pt_y_i = glyph_y + yy; if (!(*glyph & (1 << (xx & 7)))) continue; if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL)) continue; if (!num_points) { points = glamor_get_vbo_space(screen, max_points * (2 * sizeof (INT16)), &vbo_offset); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, 0, vbo_offset); } *points++ = pt_x_i; *points++ = pt_y_i; num_points++; if (num_points == max_points) { glamor_put_vbo_space(screen); glDrawArrays(GL_POINTS, 0, num_points); num_points = 0; } } glyphbits += glyph_stride; } } x += charinfo->metrics.characterWidth; } if (num_points) { glamor_put_vbo_space(screen); glDrawArrays(GL_POINTS, 0, num_points); } }
void fbImageGlyphBlt(DrawablePtr drawable, GCPtr gc, int x, int y, unsigned int nglyph, CharInfoPtr * ppciInit, pointer glyphs) { FbGCPrivPtr pgc = fb_gc(gc); CharInfoPtr *ppci; CharInfoPtr pci; unsigned char *pglyph; /* pointer bits in glyph */ int gWidth, gHeight; /* width and height of glyph */ FbStride gStride; /* stride of glyph */ bool opaque; int n; int gx, gy; void (*raster)(FbBits *, FbStride, int, FbStip *, FbBits, int, int); FbBits *dst = 0; FbStride dstStride = 0; int dstBpp = 0; int dstXoff = 0, dstYoff = 0; DBG(("%s x %d\n", __FUNCTION__, nglyph)); raster = 0; if (pgc->and == 0) { dstBpp = drawable->bitsPerPixel; switch (dstBpp) { case 8: raster = fbGlyph8; break; case 16: raster = fbGlyph16; break; case 32: raster = fbGlyph32; break; } } x += drawable->x; y += drawable->y; if (TERMINALFONT(gc->font) && !raster) { opaque = TRUE; } else { int xBack, widthBack; int yBack, heightBack; ppci = ppciInit; n = nglyph; widthBack = 0; while (n--) widthBack += (*ppci++)->metrics.characterWidth; xBack = x; if (widthBack < 0) { xBack += widthBack; widthBack = -widthBack; } yBack = y - FONTASCENT(gc->font); heightBack = FONTASCENT(gc->font) + FONTDESCENT(gc->font); fbSolidBoxClipped(drawable, gc, xBack, yBack, xBack + widthBack, yBack + heightBack); opaque = FALSE; } ppci = ppciInit; while (nglyph--) { pci = *ppci++; pglyph = FONTGLYPHBITS(glyphs, pci); gWidth = GLYPHWIDTHPIXELS(pci); gHeight = GLYPHHEIGHTPIXELS(pci); if (gWidth && gHeight) { gx = x + pci->metrics.leftSideBearing; gy = y - pci->metrics.ascent; if (raster && gWidth <= sizeof(FbStip) * 8 && fbGlyphIn(gc, gx, gy, gWidth, gHeight)) { fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); raster(dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, (FbStip *) pglyph, pgc->fg, gx + dstXoff, gHeight); } else { gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); fbPutXYImage(drawable, gc, pgc->fg, pgc->bg, pgc->pm, GXcopy, opaque, gx, gy, gWidth, gHeight, (FbStip *) pglyph, gStride, 0); } } x += pci->metrics.characterWidth; } }
void fbPolyGlyphBlt(DrawablePtr drawable, GCPtr gc, int x, int y, unsigned int nglyph, CharInfoPtr * ppci, pointer glyphs) { FbGCPrivPtr pgc = fb_gc(gc); CharInfoPtr pci; unsigned char *pglyph; /* pointer bits in glyph */ int gx, gy; int gWidth, gHeight; /* width and height of glyph */ FbStride gStride; /* stride of glyph */ void (*raster) (FbBits *, FbStride, int, FbStip *, FbBits, int, int); FbBits *dst = 0; FbStride dstStride = 0; int dstBpp = 0; int dstXoff = 0, dstYoff = 0; DBG(("%s x %d\n", __FUNCTION__, nglyph)); raster = 0; if (gc->fillStyle == FillSolid && pgc->and == 0) { dstBpp = drawable->bitsPerPixel; switch (dstBpp) { case 8: raster = fbGlyph8; break; case 16: raster = fbGlyph16; break; case 32: raster = fbGlyph32; break; } } x += drawable->x; y += drawable->y; while (nglyph--) { pci = *ppci++; pglyph = FONTGLYPHBITS(glyphs, pci); gWidth = GLYPHWIDTHPIXELS(pci); gHeight = GLYPHHEIGHTPIXELS(pci); if (gWidth && gHeight) { gx = x + pci->metrics.leftSideBearing; gy = y - pci->metrics.ascent; if (raster && gWidth <= sizeof(FbStip) * 8 && fbGlyphIn(gc, gx, gy, gWidth, gHeight)) { fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff); raster(dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, (FbStip *) pglyph, pgc->xor, gx + dstXoff, gHeight); } else { gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); fbPushImage(drawable, gc, (FbStip *)pglyph, gStride, 0, gx, gy, gWidth, gHeight); } } x += pci->metrics.characterWidth; } }