started to implement colored font specials (not yet working)

svn path=/trunk/kdegraphics/kdvi/; revision=217530
This commit is contained in:
Stefan Kebekus 2003-04-01 11:09:15 +00:00
parent b666639843
commit 0d4ef35d19
16 changed files with 201 additions and 39 deletions

View file

@ -31,7 +31,7 @@ class TeXFont {
glyphtable[i].shrunkenCharacter.resize(0, 0);
};
virtual glyph *getGlyph(unsigned int character, bool generateCharacterPixmap=false) =0;
virtual glyph *getGlyph(Q_UINT16 character, bool generateCharacterPixmap=false, QColor color=Qt::black) =0;
// Checksum of the font. Used e.g. by PK fonts. This field is filled

View file

@ -48,16 +48,28 @@ TeXFont_PFB::TeXFont_PFB(TeXFontDefinition *parent)
fatalErrorInFontLoading = true;
return;
}
// kdDebug() << "Encodings of " << parent->filename << endl;
FT_CharMap charmap;
int n;
for ( n = 0; n < face->num_charmaps; n++ ) {
charmap = face->charmaps[n];
// kdDebug() << " Platform " << charmap->platform_id << endl;
// kdDebug() << " Encoding " << charmap->encoding_id << endl;
if ((charmap->platform_id == 7)|| (charmap->encoding_id == 2))
FT_Set_Charmap( face, charmap );
}
}
TeXFont_PFB::~TeXFont_PFB()
{
// @@@@ Missing: Free resources!
FT_Done_Face( face );
}
glyph *TeXFont_PFB::getGlyph(unsigned int ch, bool generateCharacterPixmap)
glyph *TeXFont_PFB::getGlyph(Q_UINT16 ch, bool generateCharacterPixmap, QColor color)
{
#ifdef DEBUG_PFB
kdDebug(4300) << "TeXFont_PFB::getGlyph( ch=" << ch << ", '" << (char)(ch) << "', generateCharacterPixmap=" << generateCharacterPixmap << " )" << endl;
@ -71,7 +83,8 @@ glyph *TeXFont_PFB::getGlyph(unsigned int ch, bool generateCharacterPixmap)
// This is the address of the glyph that will be returned.
struct glyph *g = glyphtable+ch;
if (fatalErrorInFontLoading == true)
return g;
@ -94,9 +107,9 @@ glyph *TeXFont_PFB::getGlyph(unsigned int ch, bool generateCharacterPixmap)
// load glyph image into the slot and erase the previous one
if (parent->font_pool->getUseFontHints() == true)
error = FT_Load_Glyph(face, ch, FT_LOAD_DEFAULT );
error = FT_Load_Glyph(face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT );
else
error = FT_Load_Glyph(face, ch, FT_LOAD_NO_HINTING );
error = FT_Load_Glyph(face, FT_Get_Char_Index( face, ch ), FT_LOAD_NO_HINTING );
if (error) {
QString msg = i18n("FreeType is unable to load glyph #%1 from font file %2.").arg(ch).arg(parent->filename);
if (errorMessage.isEmpty())
@ -152,7 +165,7 @@ glyph *TeXFont_PFB::getGlyph(unsigned int ch, bool generateCharacterPixmap)
// Load glyph width, if that hasn't been done yet.
if (g->dvi_advance_in_units_of_design_size_by_2e20 == 0) {
int error = FT_Load_Glyph(face, ch, FT_LOAD_NO_SCALE );
int error = FT_Load_Glyph(face, FT_Get_Char_Index( face, ch ), FT_LOAD_NO_SCALE );
if (error) {
QString msg = i18n("FreeType is unable to load metric for glyph #%1 from font file %2.").arg(ch).arg(parent->filename);
if (errorMessage.isEmpty())

View file

@ -30,7 +30,7 @@ class TeXFont_PFB : public TeXFont {
TeXFont_PFB(TeXFontDefinition *parent);
~TeXFont_PFB();
glyph *getGlyph(unsigned int character, bool generateCharacterPixmap=false);
glyph *getGlyph(Q_UINT16 character, bool generateCharacterPixmap=false, QColor color=Qt::black);
private:
FT_Face face;

View file

@ -113,7 +113,7 @@ TeXFont_PK::~TeXFont_PK()
}
glyph *TeXFont_PK::getGlyph(unsigned int ch, bool generateCharacterPixmap)
glyph *TeXFont_PK::getGlyph(Q_UINT16 ch, bool generateCharacterPixmap, QColor color)
{
#ifdef DEBUG_PK
kdDebug(4300) << "TeXFont_PK::getGlyph( ch=" << ch << ", generateCharacterPixmap=" << generateCharacterPixmap << " )" << endl;
@ -221,20 +221,29 @@ glyph *TeXFont_PK::getGlyph(unsigned int ch, bool generateCharacterPixmap)
// Generate an Image and shrink it to the proper size. By the
// documentation of smoothScale, the resulting Image will be
// 8-bit.
QImage im = g->shrunkenCharacter.convertToImage().smoothScale(shrunk_width, shrunk_height);
QImage EightBitImage = g->shrunkenCharacter.convertToImage().smoothScale(shrunk_width, shrunk_height).convertDepth(32);
/*
QImage bm((uchar *)(characterBitmaps[ch]->bits),
characterBitmaps[ch]->bytes_wide*8, (int)characterBitmaps[ch]->h,
1, (QRgb *)0, 2, QImage::IgnoreEndian);
bm.setColor(0, qRgb(0x00,0x00,0x00));
bm.setColor(1, qRgb(0xFF,0xFF,0xFF));
QImage EightBitImage = bm.smoothScale(shrunk_width, shrunk_height).convertDepth(32);
*/
// Generate the alpha-channel. This again is highly inefficient.
// Would anybody please produce a faster routine?
QImage im32 = im.convertDepth(32);
QImage im32(shrunk_width, shrunk_height, 32);
im32.setAlphaBuffer(TRUE);
for(int y=0; y<im.height(); y++) {
QRgb *imag_scanline = (QRgb *)im32.scanLine(y);
for(int x=0; x<im.width(); x++) {
// Make White => Transparent
if ((0x00ffffff & *imag_scanline) == 0x00ffffff)
*imag_scanline &= 0x00ffffff;
else
*imag_scanline |= 0xff000000;
imag_scanline++; // Disgusting pointer arithmetic. Should be forbidden.
for(Q_UINT16 y=0; y<shrunk_height; y++) {
Q_UINT8 *srcScanLine = (Q_UINT8 *)EightBitImage.scanLine(y);
Q_UINT8 *destScanLine = (Q_UINT8 *)im32.scanLine(y);
for(Q_UINT16 col=0; col<shrunk_width; col++) {
destScanLine[4*col+0] = 0x00;
destScanLine[4*col+1] = 0x00;
destScanLine[4*col+2] = 0x00;
destScanLine[4*col+3] = 0xFF-srcScanLine[4*col];
}
}
g->shrunkenCharacter.convertFromImage(im32,0);

View file

@ -14,7 +14,7 @@ class TeXFont_PK : public TeXFont {
TeXFont_PK(TeXFontDefinition *parent);
~TeXFont_PK();
glyph *getGlyph(unsigned int character, bool generateCharacterPixmap=false);
glyph *getGlyph(Q_UINT16 character, bool generateCharacterPixmap=false, QColor color=Qt::black);
private:
FILE *file; // open font file or NULL

View file

@ -120,7 +120,7 @@ TeXFont_TFM::~TeXFont_TFM()
}
glyph *TeXFont_TFM::getGlyph(unsigned int characterCode, bool generateCharacterPixmap)
glyph *TeXFont_TFM::getGlyph(Q_UINT16 characterCode, bool generateCharacterPixmap, QColor color)
{
#ifdef DEBUG_TFM
kdDebug(4300) << "TeXFont_TFM::getGlyph( ch=" << ch << ", generateCharacterPixmap=" << generateCharacterPixmap << " )" << endl;

View file

@ -31,7 +31,7 @@ class TeXFont_TFM : public TeXFont {
TeXFont_TFM(TeXFontDefinition *parent);
~TeXFont_TFM();
glyph *getGlyph(unsigned int character, bool generateCharacterPixmap=false);
glyph *getGlyph(Q_UINT16 character, bool generateCharacterPixmap=false, QColor color=Qt::black);
private:
fix_word characterWidth_in_units_of_design_size[256];

View file

@ -228,10 +228,11 @@ dvifile::dvifile(QString fname, fontPool *pool, bool sourceSpecialMark)
kdDebug() << "init_dvi_file: " << fname << endl;
#endif
errorMsg = QString::null;
dvi_Data = 0;
page_offset = 0;
font_pool = pool;
errorMsg = QString::null;
errorCounter = 0;
dvi_Data = 0;
page_offset = 0;
font_pool = pool;
sourceSpecialMarker = sourceSpecialMark;
QFile file(fname);

View file

@ -41,6 +41,12 @@ class dvifile : public bigEndianByteReader
double cmPerDVIunit;
/** This member is set to zero on construction and can be used by
other software to count error messages that were printed when
the DVI-file was processed. Suggested application: limit the
number of error messages to, say, 25. */
Q_UINT8 errorCounter;
private:
/** process_preamble reads the information in the preamble and
stores it into global variables for later use. */

View file

@ -280,6 +280,10 @@ void dviWindow::drawPage()
return;
if ( !pixmap->paintingActive() ) {
// Reset colors
colorStack.clear();
globalColor = Qt::black;
foreGroundPaint.begin( pixmap );
QApplication::setOverrideCursor( waitCursor );
errorMsg = QString::null;

View file

@ -140,6 +140,7 @@ public:
void special(long nbytes);
void color_special(QString cp);
void html_href_special(QString cp);
void html_anchor_end(void);
void html_anchor_special(QString cp);
@ -265,6 +266,13 @@ private:
Level 0, published by the TUG DVI driver standards committee. */
QValueStack<struct framedata> stack;
/** A stack where color are stored, according to the documentation of
DVIPS */
QValueStack<QColor> colorStack;
/** The global color is to be used when the color stack is empty */
QColor globalColor;
/** Methods and counters used for the animation to mark the target of
an hyperlink. */
int timerIdent;

View file

@ -79,7 +79,11 @@ void dviWindow::set_char(unsigned int cmd, unsigned int ch)
kdDebug(4300) << "set_char #" << ch << endl;
#endif
glyph *g = ((TeXFont *)(currinf.fontp->font))->getGlyph(ch, true);
glyph *g;
if (colorStack.isEmpty())
g = ((TeXFont *)(currinf.fontp->font))->getGlyph(ch, true, globalColor);
else
g = ((TeXFont *)(currinf.fontp->font))->getGlyph(ch, true, colorStack.top());
if (g == NULL)
return;

View file

@ -9,7 +9,12 @@
#include <klocale.h>
#include <kmessagebox.h>
#include <kprocess.h>
#include <kprocio.h>
#include <kstringhandler.h>
#include <qapplication.h>
#include <qfile.h>
#include <stdlib.h>
#include "fontpool.h"
@ -40,8 +45,41 @@ fontPool::fontPool(void)
fontList.setAutoDelete(TRUE);
#ifdef HAVE_FREETYPE
// Initialize the Freetype Library
if ( FT_Init_FreeType( &FreeType_library ) != 0 ) {
kdError(4300) << "Cannot load the FreeType library. KDVI proceeds without FreeType support." << endl;
FreeType_could_be_loaded = false;
} else {
FreeType_could_be_loaded = true;
// Read the map file of ps2pk which will provide us with a
// dictionary "TeX Font names for Type1 fonts" <-> "Name of font
// files" (example: the font "Times-Roman" is called "ptmr8y" in
// the DVI file, but the Type1 font file name is "utmr8a.pfb". We
// use the map file of "ps2pk" because that progam has, like kdvi
// (and unlike dvips), no built-in fonts.
KProcIO proc;
proc << "kpsewhich" << "--format=dvips config" << "ps2pk.map";
proc.start(KProcess::Block);
QString map_fileName;
proc.readln(map_fileName);
map_fileName = map_fileName.stripWhiteSpace();
QFile file( map_fileName );
if ( file.open( IO_ReadOnly ) ) {
QTextStream stream( &file );
QString line;
while ( !stream.atEnd() ) {
line = stream.readLine().stripWhiteSpace();
if (line.at(0) == '%')
continue;
QString TeXName = KStringHandler::word(line, (unsigned int)0);
QString fontFileName = line.section('<', -1);
fontFilenames[TeXName] = fontFileName;
}
file.close();
}
}
#endif
@ -70,6 +108,11 @@ fontPool::~fontPool(void)
kdDebug(4300) << "fontPool::~fontPool(void) called" << endl;
#endif
#ifdef HAVE_FREETYPE
if (FreeType_could_be_loaded == true)
FT_Done_FreeType( FreeType_library );
#endif
if (progress)
delete progress;
}
@ -334,10 +377,16 @@ void fontPool::start_kpsewhich(void)
case 0:
// In the first pass, we look for PK fonts, and also for virtual fonts.
#ifdef HAVE_FREETYPE
if (useType1Fonts == true) {
*proc << KShellProcess::quote(QString("%1.pfb").arg(fontp->fontname));
if ((useType1Fonts == true) && (FreeType_could_be_loaded == true)) {
QString filename;
QMap<QString,QString>::Iterator it = fontFilenames.find(fontp->fontname);
if (it == fontFilenames.end())
filename = fontp->fontname;
else
filename = *it;
*proc << KShellProcess::quote(QString("%1.pfb").arg(filename));
#ifdef DEBUG_FONTPOOL
shellProcessCmdLine += KShellProcess::quote(QString("%1.pfb").arg(fontp->fontname)) + " ";
shellProcessCmdLine += KShellProcess::quote(QString("%1.pfb").arg(filename)) + " ";
#endif
}
#endif
@ -352,10 +401,16 @@ void fontPool::start_kpsewhich(void)
// In the second pass, we generate PK fonts, but be also look
// for PFB fonts, as they might be used by virtual fonts.
#ifdef HAVE_FREETYPE
if (useType1Fonts == true) {
*proc << KShellProcess::quote(QString("%1.pfb").arg(fontp->fontname));
if ((useType1Fonts == true) && (FreeType_could_be_loaded == true)) {
QString filename;
QMap<QString,QString>::Iterator it = fontFilenames.find(fontp->fontname);
if (it == fontFilenames.end())
filename = fontp->fontname;
else
filename = *it;
*proc << KShellProcess::quote(QString("%1.pfb").arg(filename));
#ifdef DEBUG_FONTPOOL
shellProcessCmdLine += KShellProcess::quote(QString("%1.pfb").arg(fontp->fontname)) + " ";
shellProcessCmdLine += KShellProcess::quote(QString("%1.pfb").arg(filename)) + " ";
#endif
}
#endif
@ -434,7 +489,13 @@ void fontPool::kpsewhich_terminated(KProcess *)
TeXFontDefinition *fontp=fontList.first();
while ( fontp != 0 ) {
if (fontp->filename.isEmpty() == true) {
QStringList matchingFiles = fileNameList.grep(fontp->fontname);
QStringList matchingFiles;
QMap<QString,QString>::Iterator it = fontFilenames.find(fontp->fontname);
if (it != fontFilenames.end())
matchingFiles =fileNameList.grep(*it);
if (matchingFiles.isEmpty() == true)
matchingFiles += fileNameList.grep(fontp->fontname);
if (matchingFiles.isEmpty() != true) {
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "Associated " << fontp->fontname << " to " << matchingFiles.first() << endl;
@ -472,8 +533,7 @@ void fontPool::kpsewhich_terminated(KProcess *)
emit fonts_have_been_loaded();
return;
}
if (pass == 0) {
pass = 1;
// If automatic pk-font generation is enabled, we call

View file

@ -11,6 +11,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
#endif
#include <qmap.h>
#include <qptrlist.h>
#include <qstringlist.h>
#include <qobject.h>
@ -137,6 +138,17 @@ Q_OBJECT
/** A handle to the FreeType library, which is used by TeXFont_PFM
font objects, if KDVI is compiled with FreeType support. */
FT_Library FreeType_library;
/** Simple marker. Set to 'true', if the FreeType library was loaded
successfully */
bool FreeType_could_be_loaded;
/** This maps TeX font names to actual filenames that we can look up
with kpsewhich. Unfortunately, this is necessary for a number of
Type1 fonts, such as URWBookmanL-DemiBold whose TeX name is
'rpbkd' but which is contained in the file 'ubkd8a.pfb'. The
contents of 'ps2pk.map' is parsed to set up this map. */
QMap<QString, QString> fontFilenames;
#endif

View file

@ -2,6 +2,7 @@
#ifndef _GLYPH_H
#define _GLYPH_H
#include <qcolor.h>
#include <qpixmap.h>
@ -17,7 +18,9 @@ class glyph {
~glyph();
// address of bitmap in font file
long addr;
long addr;
QColor color;
// DVI units to move reference point
Q_INT32 dvi_advance_in_units_of_design_size_by_2e20;

View file

@ -10,6 +10,7 @@
#include <kdebug.h>
#include <klocale.h>
#include <kprocio.h>
#include <kstringhandler.h>
#include <qdir.h>
#include <qfile.h>
#include <qfileinfo.h>
@ -22,6 +23,35 @@
extern QPainter foreGroundPaint;
void dviWindow::color_special(QString cp)
{
kdDebug(4300) << "Color special: " << cp << endl;
// The color specials are ignore during the pre-scan phase, we use
// them only during rendering
if (PostScriptOutPutString == NULL) {
cp = cp.stripWhiteSpace();
QString command = KStringHandler::word(cp, (unsigned int)0);
if (command == "pop") {
// Take color off the stack
return;
}
if (command == "push") {
// Get color specification
// Set color
return;
}
// Get color specification
// Set color for the rest of this page
return;
}
}
void dviWindow::html_anchor_special(QString cp)
{
if (PostScriptOutPutString != NULL) { // only during scanning, not during rendering
@ -354,6 +384,18 @@ void dviWindow::applicationDoSpecial(char *cp)
return;
}
kdError(4300) << i18n("The special command \"") << special_command << i18n("\" is not implemented.") << endl;
// color specials
if (special_command.find("color", 0, false) == 0) {
color_special(special_command.mid(5));
return;
}
if (dviFile->errorCounter < 25) {
kdError(4300) << i18n("The special command \"") << special_command << i18n("\" is not implemented.") << endl;
dviFile->errorCounter++;
if (dviFile->errorCounter == 25)
kdError(4300) << i18n("That makes 25 errors. Further error messages will not be printed.") << endl;
}
return;
}