diff --git a/TeXFont_PFB.cpp b/TeXFont_PFB.cpp index ae8e46944..cc1048620 100644 --- a/TeXFont_PFB.cpp +++ b/TeXFont_PFB.cpp @@ -195,17 +195,57 @@ glyph *TeXFont_PFB::getGlyph(Q_UINT16 ch, bool generateCharacterPixmap, QColor c } else { QImage imgi(slot->bitmap.width, slot->bitmap.rows, 32); imgi.setAlphaBuffer(true); - uchar *srcScanLine = slot->bitmap.buffer; - for(int row=0; rowbitmap.rows; row++) { - uchar *destScanLine = imgi.scanLine(row); - for(int col=0; colbitmap.width; col++) { - destScanLine[4*col+0] = color.blue(); - destScanLine[4*col+1] = color.green(); - destScanLine[4*col+2] = color.red(); - destScanLine[4*col+3] = srcScanLine[col]; + + // Do QPixmaps fully support the alpha channel? If yes, we use + // that. Otherwise, use other routines as a fallback + if (parent->font_pool->QPixmapSupportsAlpha) { + // If the alpha channel is properly supported, we set the + // character glyph to a colored rectangle, and define the + // character outline only using the alpha channel. That + // ensures good quality rendering for overlapping characters. + uchar *srcScanLine = slot->bitmap.buffer; + for(int row=0; rowbitmap.rows; row++) { + uchar *destScanLine = imgi.scanLine(row); + for(int col=0; colbitmap.width; col++) { + destScanLine[4*col+0] = color.blue(); + destScanLine[4*col+1] = color.green(); + destScanLine[4*col+2] = color.red(); + destScanLine[4*col+3] = srcScanLine[col]; + } + srcScanLine += slot->bitmap.pitch; + } + } else { + // If the alpha channel is not supported... QT seems to turn + // the alpha channel into a crude bitmap which is used to mask + // the resulting QPixmap. In this case, we define the + // character outline using the image data, and use the alpha + // channel only to store "maximally opaque" or "completely + // transparent" values. When characters are rendered, + // overlapping characters are no longer correctly drawn, but + // quality is still sufficient for most purposes. One notable + // exception is output from the gftodvi program, which will be + // partially unreadable. + Q_UINT16 rInv = 0xFF - color.red(); + Q_UINT16 gInv = 0xFF - color.green(); + Q_UINT16 bInv = 0xFF - color.blue(); + + for(Q_UINT16 y=0; ybitmap.rows; y++) { + Q_UINT8 *srcScanLine = slot->bitmap.buffer + y*slot->bitmap.pitch; + unsigned int *destScanLine = (unsigned int *)imgi.scanLine(y); + for(Q_UINT16 col=0; colbitmap.width; col++) { + Q_UINT16 data = *srcScanLine; + // The value stored in "data" now has the following meaning: + // data = 0 -> white; data = 0xff -> use "color" + *destScanLine = qRgba(0xFF - (rInv*data + 0x7F) / 0xFF, + 0xFF - (gInv*data + 0x7F) / 0xFF, + 0xFF - (bInv*data + 0x7F) / 0xFF, + (data > 0x03) ? 0xff : 0x00); + destScanLine++; + srcScanLine++; + } } - srcScanLine += slot->bitmap.pitch; } + g->shrunkenCharacter.convertFromImage (imgi, 0); g->x2 = -slot->bitmap_left; g->y2 = slot->bitmap_top; diff --git a/TeXFont_PK.cpp b/TeXFont_PK.cpp index 19334c62f..1f497758c 100644 --- a/TeXFont_PK.cpp +++ b/TeXFont_PK.cpp @@ -264,15 +264,52 @@ glyph *TeXFont_PK::getGlyph(Q_UINT16 ch, bool generateCharacterPixmap, QColor co xydata[shrunk_width*y + x] = (int)(value/shrinkFactor); } - // Generate the alpha-channel. QImage im32(shrunk_width, shrunk_height, 32); - im32.fill(qRgb(color.red(), color.green(), color.blue())); - im32.setAlphaBuffer(TRUE); - for(Q_UINT16 y=0; yfont_pool->QPixmapSupportsAlpha) { + // If the alpha channel is properly supported, we set the + // character glyph to a colored rectangle, and define the + // character outline only using the alpha channel. That ensures + // good quality rendering for overlapping characters. + im32.fill(qRgb(color.red(), color.green(), color.blue())); + for(Q_UINT16 y=0; y white; data = 0xff -> use "color" + *destScanLine = qRgba(0xFF - (rInv*data + 0x7F) / 0xFF, + 0xFF - (gInv*data + 0x7F) / 0xFF, + 0xFF - (bInv*data + 0x7F) / 0xFF, + (data > 0x03) ? 0xff : 0x00); + destScanLine++; + srcScanLine++; + } + } } + g->shrunkenCharacter.convertFromImage(im32,0); g->shrunkenCharacter.setOptimization(QPixmap::BestOptim); } diff --git a/fontpool.cpp b/fontpool.cpp index 4e69df323..d9fa824d8 100644 --- a/fontpool.cpp +++ b/fontpool.cpp @@ -14,7 +14,8 @@ #include #include - +#include +#include #include #include "fontpool.h" @@ -22,6 +23,10 @@ #include "performanceMeasurement.h" #include "TeXFont.h" + + + + // List of permissible MetaFontModes which are supported by kdvi. const char *MFModes[] = { "cx", "ljfour", "lexmarks" }; @@ -49,6 +54,7 @@ fontPool::fontPool(void) MetafontMode = DefaultMFMode; fontList.setAutoDelete(TRUE); + kdDebug() << "Checking Xft Extension 1" << endl; #ifdef HAVE_FREETYPE // Initialize the Freetype Library @@ -75,6 +81,37 @@ fontPool::fontPool(void) qApp->connect(this, SIGNAL(show_progress(void)), progress, SLOT(show(void))); qApp->connect(progress, SIGNAL(finished(void)), this, SLOT(abortGeneration(void))); } + + + // Check if the QT library supports the alpha channel of + // pixmaps. Experiments show that --depending of the configuration + // of QT at compile and runtime or the availability of the XFt + // extension, alpha channels are either supported, or silently + // converted to 1-bit masks. + QImage start(1, 1, 32); // Generate a 1x1 image, black with alpha=0x10 + start.setAlphaBuffer(true); + Q_UINT32 *destScanLine = (Q_UINT32 *)start.scanLine(0); + *destScanLine = 0x80000000; + QPixmap intermediate(start); + QPixmap dest(1,1); + dest.fill(Qt::white); + QPainter paint( &dest ); + paint.drawPixmap(0, 0, intermediate); + paint.end(); + start = dest.convertToImage().convertDepth(32); + Q_UINT8 result = *(start.scanLine(0)) & 0xff; + + if ((result == 0xff) || (result == 0x00)) { +#ifdef DEBUG_FONTPOOL + kdDebug(4300) << "fontPool::fontPool(): QPixmap does not support the alpha channel" << endl; +#endif + QPixmapSupportsAlpha = false; + } else { +#ifdef DEBUG_FONTPOOL + kdDebug(4300) << "fontPool::fontPool(): QPixmap supports the alpha channel" << endl; +#endif + QPixmapSupportsAlpha = true; + } } diff --git a/fontpool.h b/fontpool.h index f06383ee3..ed2af8ad5 100644 --- a/fontpool.h +++ b/fontpool.h @@ -145,6 +145,15 @@ Q_OBJECT fontEncodingPool encodingPool; #endif + /** This flag is set during the construction of the fontPool + object. It indicates if the QT library supports the alpha + channel of pixmaps. Experiments show that --depending of the + configuration of QT at compile and runtime or the availability + of the XFt extension, alpha channels are either supported, or + silently converted to 1-bit masks. The redering routines in the + TeXFont implementation use this flag to choose the apropriate + drawing routines for the different setups. */ + bool QPixmapSupportsAlpha; signals: /** Emitted to indicate that the progress dialog should show up now. */