/*! \internal This is basically a substitute for glxUseXFont() which can only handle XLFD fonts. This version relies on XFT v2 to render the glyphs, but it works with all fonts that XFT2 provides - both antialiased and aliased bitmap and outline fonts. */ void qgl_use_font(QFontEngineXft *engine, int first, int count, int listBase) { GLfloat color[4]; glGetFloatv(GL_CURRENT_COLOR, color); // save the pixel unpack state GLint gl_swapbytes, gl_lsbfirst, gl_rowlength, gl_skiprows, gl_skippixels, gl_alignment; glGetIntegerv (GL_UNPACK_SWAP_BYTES, &gl_swapbytes); glGetIntegerv (GL_UNPACK_LSB_FIRST, &gl_lsbfirst); glGetIntegerv (GL_UNPACK_ROW_LENGTH, &gl_rowlength); glGetIntegerv (GL_UNPACK_SKIP_ROWS, &gl_skiprows); glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &gl_skippixels); glGetIntegerv (GL_UNPACK_ALIGNMENT, &gl_alignment); glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); Bool antialiased = False; #if 0 // disable antialias support for now XftPatternGetBool(engine->pattern(), XFT_ANTIALIAS, 0, &antialiased); #endif #ifdef QT_XFT2 FT_Face face = XftLockFace(engine->font()); #else FT_Face face = engine->face(); #endif // start generating font glyphs for (int i = first; i < count; ++i) { int list = listBase + i; GLfloat x0, y0, dx, dy; FT_Error err; err = FT_Load_Glyph(face, FT_Get_Char_Index(face, i), FT_LOAD_DEFAULT); if (err) { qDebug("failed loading glyph %d from font", i); Q_ASSERT(!err); } err = FT_Render_Glyph(face->glyph, (antialiased ? ft_render_mode_normal : ft_render_mode_mono)); if (err) { qDebug("failed rendering glyph %d from font", i); Q_ASSERT(!err); } FT_Bitmap bm = face->glyph->bitmap; x0 = face->glyph->metrics.horiBearingX >> 6; y0 = (face->glyph->metrics.height - face->glyph->metrics.horiBearingY) >> 6; dx = face->glyph->metrics.horiAdvance >> 6; dy = 0; int sz = bm.pitch * bm.rows; uint *aa_glyph = 0; uchar *ua_glyph = 0; if (antialiased) aa_glyph = new uint[sz]; else ua_glyph = new uchar[sz]; // convert to GL format for (int y = 0; y < bm.rows; ++y) { for (int x = 0; x < bm.pitch; ++x) { int c1 = y*bm.pitch + x; int c2 = (bm.rows - y - 1) > 0 ? (bm.rows-y-1)*bm.pitch + x : x; if (antialiased) { aa_glyph[c1] = (int(color[0]*255) << 24) | (int(color[1]*255) << 16) | (int(color[2]*255) << 8) | bm.buffer[c2]; } else { ua_glyph[c1] = bm.buffer[c2]; } } } glNewList(list, GL_COMPILE); if (antialiased) { // calling glBitmap() is just a trick to move the current // raster pos, since glGet*() won't work in display lists glBitmap(0, 0, 0, 0, x0, -y0, 0); glDrawPixels(bm.pitch, bm.rows, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, aa_glyph); glBitmap(0, 0, 0, 0, dx-x0, y0, 0); } else { glBitmap(bm.pitch*8, bm.rows, -x0, y0, dx, dy, ua_glyph); } glEndList(); antialiased ? delete[] aa_glyph : delete[] ua_glyph; } #ifdef QT_XFT2 XftUnlockFace(engine->font()); #endif // restore pixel unpack settings glPixelStorei(GL_UNPACK_SWAP_BYTES, gl_swapbytes); glPixelStorei(GL_UNPACK_LSB_FIRST, gl_lsbfirst); glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_rowlength); glPixelStorei(GL_UNPACK_SKIP_ROWS, gl_skiprows); glPixelStorei(GL_UNPACK_SKIP_PIXELS, gl_skippixels); glPixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment); }
XFontStruct* XftCoreOpen (Display *dpy, XftPattern *pattern) { XftCoreFont *cf; char *xlfd; char *xlfd_pixel = 0; char *i, *o; int d; Bool scalable; double pixel_size; int pixel_int; XFontStruct *ret; #if 0 printf ("Core "); XftPatternPrint (pattern); #endif if (XftPatternGetString (pattern, XFT_XLFD, 0, &xlfd) != XftResultMatch) return 0; if (XftPatternGetBool (pattern, XFT_SCALABLE, 0, &scalable) != XftResultMatch) return 0; if (scalable) { if (XftPatternGetDouble (pattern, XFT_PIXEL_SIZE, 0, &pixel_size) != XftResultMatch) return 0; pixel_int = (int) (pixel_size + 0.5); if (pixel_int) { xlfd_pixel = (char *) malloc (strlen (xlfd) + 32); i = xlfd; o = xlfd_pixel; d = 0; while (d != 7 && *i) { if ((*o++ = *i++) == '-') d++; } if (*i) { sprintf (o, "%d", pixel_int); o += strlen (o); while (*i != '-') ++i; } while ((*o++ = *i++)); #if 0 printf ("original %s sized %s\n", xlfd, xlfd_pixel); #endif xlfd = xlfd_pixel; } } for (cf = _XftCoreFonts; cf; cf = cf->next) { if (cf->display == dpy && !_XftStrCmpIgnoreCase (cf->xlfd, xlfd)) { cf->ref++; if (_XftFontDebug () & XFT_DBG_REF) { printf ("Xlfd \"%s\" matches existing font (%d)\n", xlfd, cf->ref); } break; } } if (!cf) { ret = XLoadQueryFont (dpy, xlfd); if (!ret) return 0; cf = (XftCoreFont *) malloc (sizeof (XftCoreFont) + strlen (xlfd) + 1); if (!cf) { XFreeFont (dpy, ret); return 0; } if (_XftFontDebug () & XFT_DBG_REF) printf ("Xlfd \"%s\" matches new font\n", xlfd); cf->next = _XftCoreFonts; _XftCoreFonts = cf; cf->ref = 1; cf->font = ret; cf->xlfd = (char *) (cf + 1); strcpy (cf->xlfd, xlfd); } if (xlfd_pixel) free (xlfd_pixel); return cf->font; }