You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

341 lines
9.9 KiB

// fontpool.cpp
//
// (C) 2001 Stefan Kebekus
// Distributed under the GPL
#include <kdebug.h>
#include <klocale.h>
#include <kprocess.h>
#include <qapplication.h>
#include <stdlib.h>
#include "fontpool.h"
#include "kdvi.h"
// List of permissible MetaFontModes which are supported by kdvi.
const char *MFModes[] = { "cx", "ljfour", "lexmarks" };
const char *MFModenames[] = { "Canon CX", "LaserJet 4", "Lexmark S" };
const int MFResolutions[] = { 300, 600, 1200 };
fontPool::fontPool(void)
{
proc = 0;
fontList.setAutoDelete(TRUE);
}
unsigned int fontPool::setMetafontMode( unsigned int mode )
{
if (mode >= NumberOfMFModes) {
kdError(4300) << "fontPool::setMetafontMode called with argument " << mode
<< " which is more than the allowed value of " << NumberOfMFModes-1 << endl;
kdError(4300) << "setting mode to " << MFModes[DefaultMFMode] << " at "
<< MFResolutions[DefaultMFMode] << "dpi" << endl;
mode = DefaultMFMode;
}
MetafontMode = mode;
return mode;
}
void fontPool::setMakePK(int flag)
{
makepk = flag;
// If we just disabled font generation, there is nothing left to do.
if (flag == 0)
return;
// If we enable font generation, we look for fonts which have not
// yet been loaded, mark them as "not yet looked up" and try once
// more.
struct font *fontp;
for (fontp=fontList.first(); fontp != 0; fontp=fontList.next() )
if (fontp->filename.isEmpty() )
fontp->flags &= ~font::FONT_KPSE_NAME;
check_if_fonts_are_loaded();
}
class font *fontPool::appendx(char *fontname, float fsize, long checksum, int magstepval, double dconv)
{
class font *fontp;
// reuse font if possible
for ( fontp=fontList.first(); fontp != 0; fontp=fontList.next() ) {
if (strcmp(fontname, fontp->fontname) == 0 && (int (fsize+0.5)) == (int)(fontp->fsize + 0.5)) {
// if font is already in the list
fontp->mark_as_used();
free(fontname);
return fontp;
}
}
// if font doesn't exist yet
fontp = new font(fontname, fsize, checksum, magstepval, dconv, this);
if (fontp == 0) {
kdError(4300) << i18n("Could not allocate memory for a font structure!") << endl;
exit(0);
}
fontList.append(fontp);
// Now start kpsewhich/MetaFont, etc. if necessary
return fontp;
}
QString fontPool::status(void)
{
struct font *fontp;
QString text;
QStringList tmp;
if (fontList.isEmpty())
return i18n("The fontlist is currently empty.");
text.append("<table WIDTH=\"100%\" NOSAVE >");
text.append("<tr><td><b>Name</b></td> <td><b>DPI</b></td> <td><b>Type</b></td> <td><b>Filename</b></td></tr>");
for ( fontp=fontList.first(); fontp != 0; fontp=fontList.next() ) {
QString type;
if (fontp->flags & font::FONT_VIRTUAL)
type = i18n("virtual");
else
type = i18n("regular");
tmp << QString ("<tr><td>%1</td> <td>%2</td> <td>%3</td> <td>%4</td></tr>").arg(fontp->fontname).arg((int)(fontp->fsize+0.5)).arg(type).arg(fontp->filename);
}
tmp.sort();
text.append(tmp.join("\n"));
text.append("</table>");
return text;
}
char fontPool::check_if_fonts_are_loaded(unsigned char pass)
{
struct font *fontp;
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "Check if fonts have been looked for..." << endl;
#endif
// Check if kpsewhich is still running. In that case there certainly
// not all fonts have been properly looked up.
if (proc != 0) {
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "... no, kpsewhich is still running." << endl;
#endif
emit fonts_info(this);
return -1;
}
// Is there a font whose name we did not try to find out yet?
for (fontp=fontList.first(); fontp != 0; fontp=fontList.next() )
if ((fontp->flags & font::FONT_KPSE_NAME) == 0)
break;
if (fontp == 0) {
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "... yes, all fonts are there, or could not be found." << endl;
#endif
emit fonts_info(this);
return 0; // That says that all fonts are loaded.
}
// Just make sure that MetafontMode is in the permissible range, so
// as to avoid core dumps.
if (MetafontMode >= NumberOfMFModes) {
kdError(4300) << "fontPool::appendx called with bad MetafontMode " << MetafontMode
<< " which is more than the allowed value of " << NumberOfMFModes-1 << endl;
kdError(4300) << "setting mode to " << MFModes[DefaultMFMode] << " at "
<< MFResolutions[DefaultMFMode] << "dpi" << endl;
MetafontMode = DefaultMFMode;
}
// Set up the kpsewhich process. If pass == 0, look for vf-fonts and
// disable automatic font generation as vf-fonts can't be
// generated. If pass != 0, ennable font generation, if it was
// enabled globally.
proc = new KShellProcess();
if (proc == 0) {
kdError(4300) << "Could not allocate ShellProcess for the kpsewhich command." << endl;
exit(0);
}
MetafontOutput.left(0);
qApp->connect(proc, SIGNAL(receivedStdout(KProcess *, char *, int)),
this, SLOT(kpsewhich_output_receiver(KProcess *, char *, int)));
qApp->connect(proc, SIGNAL(processExited(KProcess *)),
this, SLOT(kpsewhich_terminated(KProcess *)));
qApp->connect(proc, SIGNAL(receivedStderr(KProcess *, char *, int)),
this, SLOT(mf_output_receiver(KProcess *, char *, int)));
proc->clearArguments();
*proc << "kpsewhich";
*proc << QString("--dpi %1").arg(MFResolutions[MetafontMode]);
*proc << QString("--mode %1").arg(MFModes[MetafontMode]);
// Enable automatic pk-font generation only in the second pass, and
// only if the user expressidly asked for it.
if ((makepk == 0) || (pass == 0))
*proc << "--no-mktex pk";
else
*proc << "--mktex pk";
int numFontsInJob = 0;
for (fontp=fontList.first(); fontp != 0; fontp=fontList.next() )
if ((fontp->flags & font::FONT_KPSE_NAME) == 0) {
numFontsInJob++;
*proc << QString("%1.%2pk").arg(fontp->fontname).arg((int)(fontp->fsize + 0.5));
// In the first pass, we look also for virtual fonts.
if (pass == 0)
*proc << QString("%1.vf").arg(fontp->fontname);
// In the second (last) pass, mark the font "looked up". As this
// is the last chance that the filename could be found, we
// ensure that if the filename is still not found now, we won't
// look any further.
if (pass != 0)
fontp->flags |= font::FONT_KPSE_NAME;
}
if (pass != 0)
emit(totalFontsInJob(numFontsInJob));
kpsewhichOutput = "";
proc->start(KProcess::NotifyOnExit, KProcess::All);
emit fonts_info(this);
return -1; // That says that not all fonts are loaded.
}
void fontPool::kpsewhich_terminated(KProcess *)
{
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "kpsewhich terminated" << endl;
#endif
delete proc;
proc = 0;
QStringList fileNameList = QStringList::split('\n', kpsewhichOutput);
for (class font *fontp=fontList.first(); fontp != 0; fontp=fontList.next() )
if (fontp->filename.isEmpty() == true) {
QString fontname = QString("%1.%2pk").arg(fontp->fontname).arg((int)(fontp->fsize + 0.5));
QStringList matchingFiles = fileNameList.grep(fontname);
if (matchingFiles.isEmpty() != true) {
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "Associated " << fontname << " to " << matchingFiles.first() << endl;
#endif
fontp->fontNameReceiver(matchingFiles.first());
fontp->flags |= font::FONT_KPSE_NAME;
continue;
}
fontname = QString("%1.vf").arg(fontp->fontname);
matchingFiles = fileNameList.grep(fontname);
if (matchingFiles.isEmpty() != true) {
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "Associated " << fontname << "to " << matchingFiles.first() << endl;
#endif
fontp->fontNameReceiver(matchingFiles.first());
fontp->flags |= font::FONT_KPSE_NAME;
emit fonts_info(this);
// Constructing a virtual font will most likely insert other
// fonts into the fontList. After that, fontList.next() will
// no longer work. It is therefore safer to start over.
fontp=fontList.first();
}
}
if (check_if_fonts_are_loaded(1) == 0) {
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "Emitting fonts_have_been_loaded()" << endl;
#endif
emit(fonts_have_been_loaded());
}
return;
}
void fontPool::reset_fonts(void)
{
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "Reset Fonts" << endl;
#endif
struct font *fontp;
struct glyph *glyphp;
for ( fontp=fontList.first(); fontp != 0; fontp=fontList.next() )
if ((fontp->flags & font::FONT_LOADED) && !(fontp->flags & font::FONT_VIRTUAL))
for (glyphp = fontp->glyphtable; glyphp < fontp->glyphtable + font::max_num_of_chars_in_font; ++glyphp)
glyphp->clearShrunkCharacter();
}
void fontPool::mark_fonts_as_unused(void)
{
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "Mark_fonts_as_unused" << endl;
#endif
struct font *fontp;
for ( fontp =fontList.first(); fontp != 0; fontp=fontList.next() )
fontp->flags &= ~font::FONT_IN_USE;
}
void fontPool::release_fonts(void)
{
#ifdef DEBUG_FONTPOOL
kdDebug(4300) << "Release_fonts" << endl;
#endif
struct font *fontp = fontList.first();
while(fontp != 0) {
if ((fontp->flags & font::FONT_IN_USE) != font::FONT_IN_USE) {
fontList.removeRef(fontp);
fontp = fontList.first();
} else
fontp = fontList.next();
}
}
void fontPool::mf_output_receiver(KProcess *, char *buffer, int buflen)
{
int numleft;
// Paranoia.
if (buflen < 0)
return;
QString op = QString::fromLocal8Bit(buffer, buflen);
MetafontOutput.append(op);
// We'd like to print only full lines of text.
while( (numleft = MetafontOutput.find('\n')) != -1) {
emit(MFOutput(MetafontOutput.left(numleft+1)));
// kdDebug(4300) << "MF OUTPUT RECEIVED: " << MetafontOutput.left(numleft+1);
MetafontOutput = MetafontOutput.remove(0,numleft+1);
}
}
void fontPool::kpsewhich_output_receiver(KProcess *, char *buffer, int buflen)
{
kpsewhichOutput.append(QString::fromLocal8Bit(buffer, buflen));
emit(numFoundFonts(kpsewhichOutput.contains('\n')));
}
void fontPool::abortGeneration(void)
{
kdDebug(4300) << "Font generation is aborted." << endl;
if (proc != 0)
if (proc->isRunning()) {
proc->kill();
}
}