mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-25 02:45:38 +00:00
started to implement colored font specials (not yet working)
svn path=/trunk/kdegraphics/kdvi/; revision=217530
This commit is contained in:
parent
b666639843
commit
0d4ef35d19
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
8
dviwin.h
8
dviwin.h
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
78
fontpool.cpp
78
fontpool.cpp
|
@ -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
|
||||
|
|
12
fontpool.h
12
fontpool.h
|
@ -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
|
||||
|
||||
|
||||
|
|
5
glyph.h
5
glyph.h
|
@ -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;
|
||||
|
|
44
special.cpp
44
special.cpp
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue