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
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(); |
|
} |
|
}
|
|
|