mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-25 02:45:38 +00:00
significant improvement in startup-performance for DVI file with lots of fonts
svn path=/trunk/kdegraphics/kdvi/; revision=218683
This commit is contained in:
parent
b1702ef090
commit
5b40d68f24
7
TODO
7
TODO
|
@ -2,6 +2,11 @@ ToDo-List for kdvi
|
|||
|
||||
URGENT / URGENT BUGFIXING
|
||||
|
||||
o Checksum mismatches in all PK files
|
||||
o Bad display of virtual font ligatures
|
||||
o implement background according to DVIPS specifications, make it work is there is PS on the page
|
||||
o improve performance and perceived performance (see also under 'highly desirable')
|
||||
|
||||
o add "papersize" which does not display the margin
|
||||
o get rid of useless README.kdvi
|
||||
o Proper handling of the base-url
|
||||
|
@ -12,8 +17,6 @@ HIGHLY DESIRABLE
|
|||
|
||||
o Speedup, in particular for ghostscript and glyph enlarging.
|
||||
|
||||
o Support for colored font specials
|
||||
|
||||
o Support papersize information given by the dvi-file on a page-by-page
|
||||
basis.
|
||||
|
||||
|
|
|
@ -100,27 +100,17 @@ void TeXFontDefinition::fontNameReceiver(QString fname)
|
|||
set_char_p = &dviWindow::set_char;
|
||||
int magic = two(file);
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
if (fname.endsWith(".pfb")) {
|
||||
fclose(file);
|
||||
file = 0;
|
||||
font = new TeXFont_PFB(this);
|
||||
set_char_p = &dviWindow::set_char;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fname.endsWith("pk"))
|
||||
if (magic == PK_MAGIC) {
|
||||
fclose(file);
|
||||
file = 0;
|
||||
font = new TeXFont_PK(this);
|
||||
set_char_p = &dviWindow::set_char;
|
||||
if ((font->checksum != 0) && (checksum != font->checksum))
|
||||
if ((checksum != 0) && (checksum != font->checksum))
|
||||
kdWarning(4300) << i18n("Checksum mismatch for font file %1").arg(filename) << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (fname.endsWith(".vf"))
|
||||
if (magic == VF_MAGIC) {
|
||||
read_VF_index();
|
||||
|
@ -135,8 +125,20 @@ void TeXFontDefinition::fontNameReceiver(QString fname)
|
|||
set_char_p = &dviWindow::set_char;
|
||||
return;
|
||||
}
|
||||
|
||||
kdError(4300) << i18n("Cannot recognize format for font file %1").arg(filename) << endl; // @@@ Do sth smarter here
|
||||
|
||||
// None of these known types? Then it should be Type1 or TrueType,
|
||||
// supported by the FreeType library
|
||||
fclose(file);
|
||||
file = 0;
|
||||
#ifdef HAVE_FREETYPE
|
||||
font = new TeXFont_PFB(this);
|
||||
set_char_p = &dviWindow::set_char;
|
||||
return;
|
||||
#else
|
||||
// If we don't have the FreeType library, we should never have
|
||||
// reached this point. Complain, and leave this font blank
|
||||
kdError(4300) << i18n("Cannot recognize format for font file %1").arg(filename) << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -213,8 +213,8 @@ glyph *TeXFont_PK::getGlyph(Q_UINT16 ch, bool generateCharacterPixmap, QColor co
|
|||
// character.
|
||||
QBitmap bm(characterBitmaps[ch]->bytes_wide*8, (int)characterBitmaps[ch]->h, (const uchar *)(characterBitmaps[ch]->bits), TRUE);
|
||||
// ... turn it into a Pixmap (highly inefficient, please improve)
|
||||
g->shrunkenCharacter.resize(characterBitmaps[ch]->w + pre_cols+post_cols, characterBitmaps[ch]->h + pre_rows+post_rows);
|
||||
QPainter paint(&g->shrunkenCharacter);
|
||||
QPixmap intpm(characterBitmaps[ch]->w + pre_cols+post_cols, characterBitmaps[ch]->h + pre_rows+post_rows);
|
||||
QPainter paint(&intpm);
|
||||
paint.setBackgroundColor(Qt::white);
|
||||
paint.setPen( Qt::black );
|
||||
paint.fillRect(0,0,characterBitmaps[ch]->w + pre_cols+post_cols, characterBitmaps[ch]->h + pre_rows+post_rows, Qt::white);
|
||||
|
@ -224,7 +224,7 @@ glyph *TeXFont_PK::getGlyph(Q_UINT16 ch, bool generateCharacterPixmap, QColor co
|
|||
// Generate an Image and shrink it to the proper size. By the
|
||||
// documentation of smoothScale, the resulting Image will be
|
||||
// 8-bit.
|
||||
QImage EightBitImage = g->shrunkenCharacter.convertToImage().smoothScale(shrunk_width, shrunk_height).convertDepth(32);
|
||||
QImage EightBitImage = intpm.convertToImage().smoothScale(shrunk_width, shrunk_height).convertDepth(32);
|
||||
|
||||
// Generate the alpha-channel. This again is highly inefficient.
|
||||
// Would anybody please produce a faster routine?
|
||||
|
|
|
@ -189,6 +189,7 @@ void dvifile::read_postamble(void)
|
|||
font_pool->release_fonts();
|
||||
}
|
||||
|
||||
|
||||
void dvifile::prepare_pages()
|
||||
{
|
||||
#ifdef DEBUG_DVIFILE
|
||||
|
@ -196,6 +197,9 @@ void dvifile::prepare_pages()
|
|||
#endif
|
||||
|
||||
page_offset = new Q_UINT32[total_pages+1];
|
||||
for(int i=0; i<=total_pages; i++)
|
||||
page_offset[i] = 0;
|
||||
|
||||
if (page_offset == 0) {
|
||||
kdError(4300) << "No memory for page list!" << endl;
|
||||
return;
|
||||
|
@ -207,8 +211,7 @@ void dvifile::prepare_pages()
|
|||
|
||||
// Follow back pointers through pages in the DVI file, storing the
|
||||
// offsets in the page_offset table.
|
||||
// @@@@ ADD CHECK FOR CONSISTENCY !!! NEVER LET THE COMMAND PTR POINT OUTSIDE THE ALLOCATED MEM !!!!
|
||||
while (i > 0) {
|
||||
while (i > 0) {
|
||||
command_pointer = dvi_Data + page_offset[i--];
|
||||
if (readUINT8() != BOP) {
|
||||
errorMsg = i18n("The page %1 does not start with the BOP command.").arg(i+1);
|
||||
|
@ -217,7 +220,7 @@ void dvifile::prepare_pages()
|
|||
command_pointer += 10 * 4;
|
||||
page_offset[i] = readUINT32();
|
||||
if ((dvi_Data+page_offset[i] < dvi_Data)||(dvi_Data+page_offset[i] > dvi_Data+size_of_file))
|
||||
page_offset[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
39
dviwin.cpp
39
dviwin.cpp
|
@ -44,13 +44,13 @@
|
|||
#include "fontprogress.h"
|
||||
#include "infodialog.h"
|
||||
#include "optiondialog.h"
|
||||
#include "performanceMeasurement.h"
|
||||
#include "xdvi.h"
|
||||
#include "zoomlimits.h"
|
||||
|
||||
|
||||
QPainter foreGroundPaint; // QPainter used for text
|
||||
|
||||
|
||||
//------ now comes the dviWindow class implementation ----------
|
||||
|
||||
dviWindow::dviWindow(double zoom, QWidget *parent, const char *name )
|
||||
|
@ -77,7 +77,7 @@ dviWindow::dviWindow(double zoom, QWidget *parent, const char *name )
|
|||
exit(-1);
|
||||
}
|
||||
connect(font_pool, SIGNAL( setStatusBarText( const QString& ) ), this, SIGNAL( setStatusBarText( const QString& ) ) );
|
||||
connect(font_pool, SIGNAL(fonts_have_been_loaded()), this, SLOT(all_fonts_loaded()));
|
||||
connect(font_pool, SIGNAL(fonts_have_been_loaded(fontPool *)), this, SLOT(all_fonts_loaded(fontPool *)));
|
||||
|
||||
info = new infoDialog(this);
|
||||
if (info == 0) {
|
||||
|
@ -86,7 +86,7 @@ dviWindow::dviWindow(double zoom, QWidget *parent, const char *name )
|
|||
kdError(4300) << "Could not allocate memory for the info dialog." << endl;
|
||||
} else {
|
||||
qApp->connect(font_pool, SIGNAL(MFOutput(QString)), info, SLOT(outputReceiver(QString)));
|
||||
qApp->connect(font_pool, SIGNAL(fonts_info(fontPool *)), info, SLOT(setFontInfo(fontPool *)));
|
||||
qApp->connect(font_pool, SIGNAL(fonts_have_been_loaded(fontPool *)), info, SLOT(setFontInfo(fontPool *)));
|
||||
qApp->connect(font_pool, SIGNAL(new_kpsewhich_run(QString)), info, SLOT(clear(QString)));
|
||||
}
|
||||
|
||||
|
@ -254,19 +254,20 @@ void dviWindow::drawPage()
|
|||
kdDebug(4300) << "dviWindow::drawPage()" << endl;
|
||||
#endif
|
||||
|
||||
start:
|
||||
shrinkfactor = MFResolutions[font_pool->getMetafontMode()]/(xres*_zoom);
|
||||
setCursor(arrowCursor);
|
||||
|
||||
|
||||
// Stop any animation which may be in progress
|
||||
if (timerIdent != 0) {
|
||||
killTimer(timerIdent);
|
||||
timerIdent = 0;
|
||||
animationCounter = 0;
|
||||
}
|
||||
|
||||
|
||||
// Remove the mouse selection
|
||||
DVIselection.clear();
|
||||
|
||||
|
||||
// Stop if there is no dvi-file present
|
||||
if ( dviFile == 0 ) {
|
||||
resize(0, 0);
|
||||
|
@ -357,6 +358,19 @@ void dviWindow::drawPage()
|
|||
}
|
||||
update();
|
||||
emit contents_changed();
|
||||
|
||||
#ifdef PERFORMANCE_MEASUREMENT
|
||||
if (performanceFlag == 1) {
|
||||
qApp->processEvents(30);
|
||||
current_page++;
|
||||
if (current_page < dviFile->total_pages)
|
||||
goto start;
|
||||
else {
|
||||
kdDebug(4300) << "Time required to draw all pages: " << performanceTimer.restart() << "ms" << endl;
|
||||
performanceFlag = 2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -494,6 +508,13 @@ bool dviWindow::setFile(QString fname, QString ref, bool sourceMarker)
|
|||
|
||||
if (dviFile->page_offset == 0)
|
||||
return false;
|
||||
|
||||
// Prescan phase starts here
|
||||
#ifdef PERFORMANCE_MEASUREMENT
|
||||
kdDebug(4300) << "Time elapsed till prescan phase starts " << performanceTimer.elapsed() << "ms" << endl;
|
||||
QTime preScanTimer;
|
||||
preScanTimer.start();
|
||||
#endif
|
||||
|
||||
for(current_page=0; current_page < dviFile->total_pages; current_page++) {
|
||||
PostScriptOutPutString = new QString();
|
||||
|
@ -515,13 +536,17 @@ bool dviWindow::setFile(QString fname, QString ref, bool sourceMarker)
|
|||
}
|
||||
PostScriptOutPutString = NULL;
|
||||
is_current_page_drawn = 0;
|
||||
|
||||
#ifdef PERFORMANCE_MEASUREMENT
|
||||
kdDebug(4300) << "Time required for prescan phase: " << preScanTimer.restart() << "ms" << endl;
|
||||
#endif
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
reference = ref;
|
||||
return true;
|
||||
}
|
||||
|
||||
void dviWindow::all_fonts_loaded(void)
|
||||
void dviWindow::all_fonts_loaded(fontPool *)
|
||||
{
|
||||
if (dviFile == 0)
|
||||
return;
|
||||
|
|
6
dviwin.h
6
dviwin.h
|
@ -39,6 +39,10 @@ class TeXFontDefinition;
|
|||
|
||||
extern const int MFResolutions[];
|
||||
|
||||
|
||||
// If this is defined, KDVI will emitt debugging messages to tell how
|
||||
// long certain tasks take
|
||||
|
||||
class DVI_Hyperlink {
|
||||
public:
|
||||
DVI_Hyperlink() {}
|
||||
|
@ -202,7 +206,7 @@ public slots:
|
|||
corresponding section of the DVI file can be found. If so, it
|
||||
will emit a "requestGotoPage", otherwise it will just call
|
||||
drawpage */
|
||||
void all_fonts_loaded();
|
||||
void all_fonts_loaded(fontPool *);
|
||||
|
||||
signals:
|
||||
/** Emitted to indicate that a hyperlink has been clicked on, and
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "dviwin.h"
|
||||
#include "dvi.h"
|
||||
#include "fontpool.h"
|
||||
#include "performanceMeasurement.h"
|
||||
#include "TeXFont.h"
|
||||
#include "xdvi.h"
|
||||
|
||||
|
@ -70,7 +71,6 @@
|
|||
extern QPainter foreGroundPaint;
|
||||
|
||||
|
||||
|
||||
/** Routine to print characters. */
|
||||
|
||||
void dviWindow::set_char(unsigned int cmd, unsigned int ch)
|
||||
|
@ -571,12 +571,25 @@ void dviWindow::draw_page(void)
|
|||
if (font_pool->check_if_fonts_filenames_are_looked_up() == false)
|
||||
return;
|
||||
|
||||
#ifdef PERFORMANCE_MEASUREMENT
|
||||
// If this is the first time a page is drawn, take the time that is
|
||||
// elapsed till the kdvi_multipage was constructed, and print
|
||||
// it. Set the flag so that is message will not be printed again.
|
||||
if (performanceFlag == 0) {
|
||||
kdDebug(4300) << "Time elapsed till the first page is drawn: " << performanceTimer.restart() << "ms" << endl;
|
||||
exit(0);
|
||||
performanceFlag = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DEBUG_RENDER
|
||||
kdDebug() <<"draw_page" << endl;
|
||||
#endif
|
||||
|
||||
foreGroundPaint.fillRect(pixmap->rect(), PS_interface->getBackgroundColor(current_page) );
|
||||
|
||||
// Render the PostScript background, if there is one.
|
||||
foreGroundPaint.fillRect(pixmap->rect(), Qt::white );
|
||||
if (_postscript) {
|
||||
QPixmap *pxm = PS_interface->graphics(current_page);
|
||||
if (pxm != NULL) {
|
||||
|
|
44
fontpool.cpp
44
fontpool.cpp
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "fontpool.h"
|
||||
#include "fontprogress.h"
|
||||
#include "performanceMeasurement.h"
|
||||
#include "TeXFont.h"
|
||||
|
||||
// List of permissible MetaFontModes which are supported by kdvi.
|
||||
|
@ -27,6 +28,11 @@ const char *MFModes[] = { "cx", "ljfour", "lexmarks" };
|
|||
const char *MFModenames[] = { "Canon CX", "LaserJet 4", "Lexmark S" };
|
||||
const int MFResolutions[] = { 300, 600, 1200 };
|
||||
|
||||
#ifdef PERFORMANCE_MEASUREMENT
|
||||
QTime fontPoolTimer;
|
||||
bool fontPoolTimerFlag;
|
||||
#endif
|
||||
|
||||
//#define DEBUG_FONTPOOL
|
||||
|
||||
fontPool::fontPool(void)
|
||||
|
@ -176,7 +182,7 @@ void fontPool::setParameters( unsigned int _metafontMode, bool _makePK, bool _en
|
|||
if (kpsewhichNeeded == true)
|
||||
check_if_fonts_filenames_are_looked_up();
|
||||
else
|
||||
emit fonts_have_been_loaded();
|
||||
emit fonts_have_been_loaded(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -207,7 +213,12 @@ class TeXFontDefinition *fontPool::appendx(QString fontname, Q_UINT32 checksum,
|
|||
exit(0);
|
||||
}
|
||||
fontList.append(fontp);
|
||||
|
||||
|
||||
#ifdef PERFORMANCE_MEASUREMENT
|
||||
fontPoolTimer.start();
|
||||
fontPoolTimerFlag = false;
|
||||
#endif
|
||||
|
||||
// Now start kpsewhich/MetaFont, etc. if necessary
|
||||
return fontp;
|
||||
}
|
||||
|
@ -215,6 +226,10 @@ class TeXFontDefinition *fontPool::appendx(QString fontname, Q_UINT32 checksum,
|
|||
|
||||
QString fontPool::status(void)
|
||||
{
|
||||
#ifdef DEBUG_FONTPOOL
|
||||
kdDebug(4300) << "fontPool::status() called" << endl;
|
||||
#endif
|
||||
|
||||
QString text;
|
||||
QStringList tmp;
|
||||
|
||||
|
@ -261,10 +276,9 @@ bool fontPool::check_if_fonts_filenames_are_looked_up(void)
|
|||
#ifdef DEBUG_FONTPOOL
|
||||
kdDebug(4300) << "... no, kpsewhich is still running." << endl;
|
||||
#endif
|
||||
emit fonts_info(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Is there a font whose name we did not try to find out yet?
|
||||
TeXFontDefinition *fontp = fontList.first();
|
||||
while( fontp != 0 ) {
|
||||
|
@ -277,7 +291,6 @@ bool fontPool::check_if_fonts_filenames_are_looked_up(void)
|
|||
#ifdef DEBUG_FONTPOOL
|
||||
kdDebug(4300) << "... yes, all fonts are there, or could not be found." << endl;
|
||||
#endif
|
||||
emit fonts_info(this);
|
||||
return true; // That says that all fonts are loaded.
|
||||
}
|
||||
|
||||
|
@ -293,13 +306,12 @@ void fontPool::start_kpsewhich(void)
|
|||
kdDebug(4300) << "fontPool::start_kpsewhich(void) called" << endl;
|
||||
#endif
|
||||
|
||||
// Check if kpsewhich is still running. In that case certainly not
|
||||
// all fonts have been properly looked up.
|
||||
// Check if kpsewhich is still running. In that case we certainly do
|
||||
// not want to run another kpsewhich process
|
||||
if (proc != 0) {
|
||||
#ifdef DEBUG_FONTPOOL
|
||||
kdDebug(4300) << "kpsewhich is still running." << endl;
|
||||
#endif
|
||||
emit fonts_info(this);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -398,7 +410,7 @@ void fontPool::start_kpsewhich(void)
|
|||
#endif
|
||||
break;
|
||||
case 1:
|
||||
// In the second pass, we generate PK fonts, but be also look
|
||||
// In the second pass, we generate PK fonts, but we also look
|
||||
// for PFB fonts, as they might be used by virtual fonts.
|
||||
#ifdef HAVE_FREETYPE
|
||||
if ((useType1Fonts == true) && (FreeType_could_be_loaded == true)) {
|
||||
|
@ -452,8 +464,6 @@ void fontPool::start_kpsewhich(void)
|
|||
if (proc->start(KProcess::NotifyOnExit, KProcess::AllOutput) == false) {
|
||||
kdError(4300) << "kpsewhich failed to start" << endl;
|
||||
}
|
||||
|
||||
emit fonts_info(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -502,7 +512,6 @@ void fontPool::kpsewhich_terminated(KProcess *)
|
|||
#endif
|
||||
fontp->fontNameReceiver(matchingFiles.first());
|
||||
fontp->flags |= TeXFontDefinition::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.
|
||||
|
@ -514,7 +523,7 @@ void fontPool::kpsewhich_terminated(KProcess *)
|
|||
}
|
||||
|
||||
// Check if some font filenames are still missing. If not, or if we
|
||||
// have just finished the lass pass, we quit here.
|
||||
// have just finished the last pass, we quit here.
|
||||
bool all_fonts_are_found = true;
|
||||
|
||||
fontp = fontList.first();
|
||||
|
@ -527,10 +536,13 @@ void fontPool::kpsewhich_terminated(KProcess *)
|
|||
}
|
||||
if ((all_fonts_are_found) || (pass >= 2)) {
|
||||
#ifdef DEBUG_FONTPOOL
|
||||
kdDebug(4300) << "Emitting fonts_have_been_loaded()" << endl;
|
||||
kdDebug(4300) << "Emitting fonts_have_been_loaded(this)" << endl;
|
||||
#endif
|
||||
#ifdef PERFORMANCE_MEASUREMENT
|
||||
kdDebug(4300) << "Time required to look up fonts: " << fontPoolTimer.elapsed() << "ms" << endl;
|
||||
#endif
|
||||
emit setStatusBarText(QString::null);
|
||||
emit fonts_have_been_loaded();
|
||||
emit fonts_have_been_loaded(this);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -614,7 +626,7 @@ void fontPool::setDisplayResolution( double _displayResolution_in_dpi )
|
|||
}
|
||||
|
||||
// Do something that causes re-rendering of the dvi-window
|
||||
emit fonts_have_been_loaded();
|
||||
emit fonts_have_been_loaded(this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ signals:
|
|||
|
||||
/** Emitted to indicate that all the fonts have now been loaded so
|
||||
that the first page can be rendered. */
|
||||
void fonts_have_been_loaded(void);
|
||||
void fonts_have_been_loaded(fontPool *);
|
||||
|
||||
/** The title says it all... */
|
||||
void hide_progress_dialog(void);
|
||||
|
@ -179,12 +179,6 @@ signals:
|
|||
info dialog window. */
|
||||
void new_kpsewhich_run(QString);
|
||||
|
||||
/** Emitted when the font-pool has changed. The class receiving the
|
||||
signal might whish to call status() in order to receive the
|
||||
data. We don't send the data here directly as the compilation of
|
||||
the string is quite costy. */
|
||||
void fonts_info(fontPool *);
|
||||
|
||||
/** Passed through to the top-level kpart. */
|
||||
void setStatusBarText( const QString& );
|
||||
|
||||
|
|
|
@ -19,8 +19,16 @@
|
|||
#include "kdvi_multipage.h"
|
||||
#include "kviewpart.h"
|
||||
#include "optiondialog.h"
|
||||
#include "performanceMeasurement.h"
|
||||
#include "zoomlimits.h"
|
||||
|
||||
#ifdef PERFORMANCE_MEASUREMENT
|
||||
// These objects are explained in the file "performanceMeasurement.h"
|
||||
QTime performanceTimer;
|
||||
int performanceFlag = 0;
|
||||
#endif
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void *init_kdvipart()
|
||||
|
@ -66,6 +74,10 @@ KInstance *KDVIMultiPageFactory::instance()
|
|||
KDVIMultiPage::KDVIMultiPage(QWidget *parentWidget, const char *widgetName, QObject *parent, const char *name)
|
||||
: KMultiPage(parentWidget, widgetName, parent, name), window(0), options(0)
|
||||
{
|
||||
#ifdef PERFORMANCE_MEASUREMENT
|
||||
performanceTimer.start();
|
||||
#endif
|
||||
|
||||
timer_id = -1;
|
||||
setInstance(KDVIMultiPageFactory::instance());
|
||||
|
||||
|
@ -145,7 +157,7 @@ void KDVIMultiPage::jumpToReference(QString reference)
|
|||
{
|
||||
if (window != 0) {
|
||||
window->reference = reference;
|
||||
window->all_fonts_loaded(); // In spite of its name, this method tries to parse the reference.
|
||||
window->all_fonts_loaded(0); // In spite of its name, this method tries to parse the reference.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
20
performanceMeasurement.h
Normal file
20
performanceMeasurement.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
//#define PERFORMANCE_MEASUREMENT
|
||||
|
||||
#ifdef PERFORMANCE_MEASUREMENT
|
||||
#include <qdatetime.h>
|
||||
|
||||
// This is the central timer used for performance measurement. It is
|
||||
// set to zero and started when the kdvi_multipage is
|
||||
// constructed. This object is statically defined in
|
||||
// kdvi_multipage.cpp.
|
||||
extern QTime performanceTimer;
|
||||
|
||||
// A flag that is set to TRUE once the first page of the document was
|
||||
// successfully drawn. This object is statically defined in
|
||||
// kdvi_multipage.cpp.
|
||||
// 0 = initial value
|
||||
// 1 = first page was drawn
|
||||
// 2 = last page was drawn
|
||||
extern int performanceFlag;
|
||||
#endif
|
538
pk.cpp
538
pk.cpp
|
@ -1,538 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1994 Paul Vojta. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* NOTE:
|
||||
* xdvi is based on prior work as noted in the modification history, below.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DVI previewer for X.
|
||||
*
|
||||
* Eric Cooper, CMU, September 1985.
|
||||
*
|
||||
* Code derived from dvi-imagen.c.
|
||||
*
|
||||
* Modification history:
|
||||
* 1/1986 Modified for X.10 --Bob Scheifler, MIT LCS.
|
||||
* 7/1988 Modified for X.11 --Mark Eichin, MIT
|
||||
* 12/1988 Added 'R' option, toolkit, magnifying glass
|
||||
* --Paul Vojta, UC Berkeley.
|
||||
* 2/1989 Added tpic support --Jeffrey Lee, U of Toronto
|
||||
* 4/1989 Modified for System V --Donald Richardson, Clarkson Univ.
|
||||
* 3/1990 Added VMS support --Scott Allendorf, U of Iowa
|
||||
* 7/1990 Added reflection mode --Michael Pak, Hebrew U of Jerusalem
|
||||
* 1/1992 Added greyscale code --Till Brychcy, Techn. Univ. Muenchen
|
||||
* and Lee Hetherington, MIT
|
||||
* 4/1994 Added DPS support, bounding box
|
||||
* --Ricardo Telichevesky
|
||||
* and Luis Miguel Silveira, MIT RLE.
|
||||
*/
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <klocale.h>
|
||||
|
||||
#include "font.h"
|
||||
#include "dviwin.h"
|
||||
#include "kdvi.h" // This is where debugging flags are set.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "glyph.h"
|
||||
#include "xdvi.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#define BMUNIT Q_UINT32
|
||||
#define BITS_PER_BMUNIT 32
|
||||
#define BYTES_PER_BMUNIT 4
|
||||
|
||||
#define ADD(a, b) ((BMUNIT *) (((char *) a) + b))
|
||||
#define SUB(a, b) ((BMUNIT *) (((char *) a) - b))
|
||||
|
||||
|
||||
extern void oops(QString message);
|
||||
|
||||
/*
|
||||
* Allocate bitmap for given font and character
|
||||
*/
|
||||
|
||||
void alloc_bitmap(bitmap *bitmap)
|
||||
{
|
||||
register unsigned int size;
|
||||
|
||||
/* width must be multiple of 16 bits for raster_op */
|
||||
bitmap->bytes_wide = ROUNDUP((int) bitmap->w, BITS_PER_BMUNIT) * BYTES_PER_BMUNIT;
|
||||
size = bitmap->bytes_wide * bitmap->h;
|
||||
bitmap->bits = new char[size != 0 ? size : 1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This table is used for changing the bit order in a byte. The
|
||||
// expression bitflp[byte] takes a byte in big endian and gives the
|
||||
// little endian equivalent of that.
|
||||
static const uchar bitflip[256] = {
|
||||
0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
|
||||
8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
|
||||
4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
|
||||
12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
|
||||
2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
|
||||
10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
|
||||
6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
|
||||
14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
|
||||
1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
|
||||
9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
|
||||
5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
|
||||
13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
|
||||
3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
|
||||
11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
|
||||
7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
|
||||
15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
|
||||
};
|
||||
|
||||
BMUNIT bit_masks[33] = {
|
||||
0x0, 0x1, 0x3, 0x7,
|
||||
0xf, 0x1f, 0x3f, 0x7f,
|
||||
0xff, 0x1ff, 0x3ff, 0x7ff,
|
||||
0xfff, 0x1fff, 0x3fff, 0x7fff,
|
||||
0xffff, 0x1ffff, 0x3ffff, 0x7ffff,
|
||||
0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
|
||||
0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff,
|
||||
0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
|
||||
0xffffffff
|
||||
};
|
||||
|
||||
|
||||
/***
|
||||
*** PK font reading routines.
|
||||
*** Public routines are read_PK_index and read_PK_char.
|
||||
***/
|
||||
|
||||
#define PK_ID 89
|
||||
#define PK_CMD_START 240
|
||||
#define PK_X1 240
|
||||
#define PK_X2 241
|
||||
#define PK_X3 242
|
||||
#define PK_X4 243
|
||||
#define PK_Y 244
|
||||
#define PK_POST 245
|
||||
#define PK_NOOP 246
|
||||
#define PK_PRE 247
|
||||
|
||||
static int PK_flag_byte;
|
||||
static unsigned PK_input_byte;
|
||||
static int PK_bitpos;
|
||||
static int PK_dyn_f;
|
||||
static int PK_repeat_count;
|
||||
|
||||
int font::PK_get_nyb(FILE *fp)
|
||||
{
|
||||
#ifdef DEBUG_PK
|
||||
kdDebug(4300) << "PK_get_nyb" << endl;
|
||||
#endif
|
||||
unsigned temp;
|
||||
if (PK_bitpos < 0) {
|
||||
PK_input_byte = one(fp);
|
||||
PK_bitpos = 4;
|
||||
}
|
||||
temp = PK_input_byte >> PK_bitpos;
|
||||
PK_bitpos -= 4;
|
||||
return (temp & 0xf);
|
||||
}
|
||||
|
||||
|
||||
int font::PK_packed_num(FILE *fp)
|
||||
{
|
||||
#ifdef DEBUG_PK
|
||||
kdDebug(4300) << "PK_packed_num" << endl;
|
||||
#endif
|
||||
|
||||
int i,j;
|
||||
|
||||
if ((i = PK_get_nyb(fp)) == 0) {
|
||||
do {
|
||||
j = PK_get_nyb(fp);
|
||||
++i;
|
||||
}
|
||||
while (j == 0);
|
||||
while (i > 0) {
|
||||
j = (j << 4) | PK_get_nyb(fp);
|
||||
--i;
|
||||
}
|
||||
return (j - 15 + ((13 - PK_dyn_f) << 4) + PK_dyn_f);
|
||||
}
|
||||
else {
|
||||
if (i <= PK_dyn_f) return i;
|
||||
if (i < 14)
|
||||
return (((i - PK_dyn_f - 1) << 4) + PK_get_nyb(fp)
|
||||
+ PK_dyn_f + 1);
|
||||
if (i == 14) PK_repeat_count = PK_packed_num(fp);
|
||||
else PK_repeat_count = 1;
|
||||
return PK_packed_num(fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void font::PK_skip_specials(void)
|
||||
{
|
||||
#ifdef DEBUG_PK
|
||||
kdDebug(4300) << "PK_skip_specials" << endl;
|
||||
#endif
|
||||
|
||||
int i,j;
|
||||
register FILE *fp = file;
|
||||
|
||||
do {
|
||||
PK_flag_byte = one(fp);
|
||||
if (PK_flag_byte >= PK_CMD_START) {
|
||||
switch (PK_flag_byte) {
|
||||
case PK_X1 :
|
||||
case PK_X2 :
|
||||
case PK_X3 :
|
||||
case PK_X4 :
|
||||
i = 0;
|
||||
for (j = PK_CMD_START; j <= PK_flag_byte; ++j)
|
||||
i = (i << 8) | one(fp);
|
||||
while (i--) (void) one(fp);
|
||||
break;
|
||||
case PK_Y :
|
||||
(void) four(fp);
|
||||
case PK_POST :
|
||||
case PK_NOOP :
|
||||
break;
|
||||
default :
|
||||
oops(i18n("Unexpected %1 in PK file %2").arg(PK_flag_byte).arg(filename) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (PK_flag_byte != PK_POST && PK_flag_byte >= PK_CMD_START)
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Public routines
|
||||
*/
|
||||
|
||||
void font::read_PK_char(unsigned int ch)
|
||||
{
|
||||
#ifdef DEBUG_PK
|
||||
kdDebug(4300) << "read_PK_char" << endl;
|
||||
#endif
|
||||
|
||||
int i, j;
|
||||
int n;
|
||||
int row_bit_pos;
|
||||
bool paint_switch;
|
||||
BMUNIT *cp;
|
||||
register struct glyph *g;
|
||||
register FILE *fp = file;
|
||||
long fpwidth;
|
||||
BMUNIT word = 0;
|
||||
int word_weight, bytes_wide;
|
||||
int rows_left, h_bit, count;
|
||||
|
||||
g = glyphtable + ch;
|
||||
PK_flag_byte = g->x2;
|
||||
PK_dyn_f = PK_flag_byte >> 4;
|
||||
paint_switch = ((PK_flag_byte & 8) != 0);
|
||||
PK_flag_byte &= 0x7;
|
||||
if (PK_flag_byte == 7)
|
||||
n = 4;
|
||||
else
|
||||
if (PK_flag_byte > 3)
|
||||
n = 2;
|
||||
else
|
||||
n = 1;
|
||||
|
||||
#ifdef DEBUG_PK
|
||||
kdDebug(4300) << "loading pk char " << ch << ", char type " << n << endl;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* now read rest of character preamble
|
||||
*/
|
||||
if (n != 4)
|
||||
fpwidth = num(fp, 3);
|
||||
else {
|
||||
fpwidth = sfour(fp);
|
||||
(void) four(fp); /* horizontal escapement */
|
||||
}
|
||||
(void) num(fp, n); /* vertical escapement */
|
||||
{
|
||||
unsigned long w, h;
|
||||
|
||||
w = num(fp, n);
|
||||
h = num(fp, n);
|
||||
if (w > 0x7fff || h > 0x7fff)
|
||||
oops(i18n("The character %1 is too large in file %2").arg(ch).arg(fontname));
|
||||
g->bitmap.w = w;
|
||||
g->bitmap.h = h;
|
||||
}
|
||||
g->x = snum(fp, n);
|
||||
g->y = snum(fp, n);
|
||||
|
||||
g->dvi_advance_in_DVI_units = fpwidth; // ####
|
||||
|
||||
alloc_bitmap(&g->bitmap);
|
||||
cp = (BMUNIT *) g->bitmap.bits;
|
||||
|
||||
/*
|
||||
* read character data into *cp
|
||||
*/
|
||||
bytes_wide = ROUNDUP((int) g->bitmap.w, BITS_PER_BMUNIT) * BYTES_PER_BMUNIT;
|
||||
PK_bitpos = -1;
|
||||
|
||||
// The routines which read the character depend on the byte
|
||||
// ordering. In principle, the byte order should be detected at
|
||||
// compile time and the proper routing chosen. For the moment, as
|
||||
// autoconf is somewhat complicated for the author, we prefer a
|
||||
// simpler -even if somewhat slower approach and detect the ordering
|
||||
// at runtime. That should of course be changed in the future.
|
||||
|
||||
int wordSize;
|
||||
bool bigEndian;
|
||||
qSysInfo (&wordSize, &bigEndian);
|
||||
|
||||
if (bigEndian) {
|
||||
// Routine for big Endian machines. Applies e.g. to Motorola and
|
||||
// (Ultra-)Sparc processors.
|
||||
|
||||
#ifdef DEBUG_PK
|
||||
kdDebug(4300) << "big Endian byte ordering" << endl;
|
||||
#endif
|
||||
|
||||
if (PK_dyn_f == 14) { /* get raster by bits */
|
||||
memset(g->bitmap.bits, 0, (int) g->bitmap.h * bytes_wide);
|
||||
for (i = 0; i < (int) g->bitmap.h; i++) { /* get all rows */
|
||||
cp = ADD(g->bitmap.bits, i * bytes_wide);
|
||||
row_bit_pos = BITS_PER_BMUNIT;
|
||||
for (j = 0; j < (int) g->bitmap.w; j++) { /* get one row */
|
||||
if (--PK_bitpos < 0) {
|
||||
word = one(fp);
|
||||
PK_bitpos = 7;
|
||||
}
|
||||
if (--row_bit_pos < 0) {
|
||||
cp++;
|
||||
row_bit_pos = BITS_PER_BMUNIT - 1;
|
||||
}
|
||||
if (word & (1 << PK_bitpos))
|
||||
*cp |= 1 << row_bit_pos;
|
||||
}
|
||||
}
|
||||
} else { /* get packed raster */
|
||||
rows_left = g->bitmap.h;
|
||||
h_bit = g->bitmap.w;
|
||||
PK_repeat_count = 0;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
word = 0;
|
||||
while (rows_left > 0) {
|
||||
count = PK_packed_num(fp);
|
||||
while (count > 0) {
|
||||
if (count < word_weight && count < h_bit) {
|
||||
h_bit -= count;
|
||||
word_weight -= count;
|
||||
if (paint_switch)
|
||||
word |= bit_masks[count] << word_weight;
|
||||
count = 0;
|
||||
} else
|
||||
if (count >= h_bit && h_bit <= word_weight) {
|
||||
if (paint_switch)
|
||||
word |= bit_masks[h_bit] << (word_weight - h_bit);
|
||||
*cp++ = word;
|
||||
/* "output" row(s) */
|
||||
for (i = PK_repeat_count * bytes_wide /
|
||||
BYTES_PER_BMUNIT; i > 0; --i) {
|
||||
*cp = *SUB(cp, bytes_wide);
|
||||
++cp;
|
||||
}
|
||||
rows_left -= PK_repeat_count + 1;
|
||||
PK_repeat_count = 0;
|
||||
word = 0;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
count -= h_bit;
|
||||
h_bit = g->bitmap.w;
|
||||
} else {
|
||||
if (paint_switch)
|
||||
word |= bit_masks[word_weight];
|
||||
*cp++ = word;
|
||||
word = 0;
|
||||
count -= word_weight;
|
||||
h_bit -= word_weight;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
}
|
||||
}
|
||||
paint_switch = 1 - paint_switch;
|
||||
}
|
||||
if (cp != ((BMUNIT *) (g->bitmap.bits + bytes_wide * g->bitmap.h)))
|
||||
oops(i18n("Wrong number of bits stored: char. %1, font %2").arg(ch).arg(fontname));
|
||||
if (rows_left != 0 || h_bit != g->bitmap.w)
|
||||
oops(i18n("Bad pk file (%1), too many bits").arg(fontname));
|
||||
}
|
||||
|
||||
// The data in the bitmap is now in the processor's bit order,
|
||||
// that is, big endian. Since XWindows needs little endian, we
|
||||
// need to change the bit order now.
|
||||
register unsigned char* bitmapData = (unsigned char*) g->bitmap.bits;
|
||||
register unsigned char* endOfData = bitmapData + g->bitmap.bytes_wide*g->bitmap.h;
|
||||
while(bitmapData < endOfData) {
|
||||
*bitmapData = bitflip[*bitmapData];
|
||||
bitmapData++;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Routines for small Endian start here. This applies e.g. to
|
||||
// Intel and Alpha processors.
|
||||
|
||||
#ifdef DEBUG_PK
|
||||
kdDebug(4300) << "small Endian byte ordering" << endl;
|
||||
#endif
|
||||
|
||||
if (PK_dyn_f == 14) { /* get raster by bits */
|
||||
memset(g->bitmap.bits, 0, (int) g->bitmap.h * bytes_wide);
|
||||
for (i = 0; i < (int) g->bitmap.h; i++) { /* get all rows */
|
||||
cp = ADD(g->bitmap.bits, i * bytes_wide);
|
||||
row_bit_pos = -1;
|
||||
for (j = 0; j < (int) g->bitmap.w; j++) { /* get one row */
|
||||
if (--PK_bitpos < 0) {
|
||||
word = one(fp);
|
||||
PK_bitpos = 7;
|
||||
}
|
||||
if (++row_bit_pos >= BITS_PER_BMUNIT) {
|
||||
cp++;
|
||||
row_bit_pos = 0;
|
||||
}
|
||||
if (word & (1 << PK_bitpos))
|
||||
*cp |= 1 << row_bit_pos;
|
||||
}
|
||||
}
|
||||
} else { /* get packed raster */
|
||||
rows_left = g->bitmap.h;
|
||||
h_bit = g->bitmap.w;
|
||||
PK_repeat_count = 0;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
word = 0;
|
||||
while (rows_left > 0) {
|
||||
count = PK_packed_num(fp);
|
||||
while (count > 0) {
|
||||
if (count < word_weight && count < h_bit) {
|
||||
if (paint_switch)
|
||||
word |= bit_masks[count] << (BITS_PER_BMUNIT - word_weight);
|
||||
h_bit -= count;
|
||||
word_weight -= count;
|
||||
count = 0;
|
||||
} else
|
||||
if (count >= h_bit && h_bit <= word_weight) {
|
||||
if (paint_switch)
|
||||
word |= bit_masks[h_bit] << (BITS_PER_BMUNIT - word_weight);
|
||||
*cp++ = word;
|
||||
/* "output" row(s) */
|
||||
for (i = PK_repeat_count * bytes_wide /
|
||||
BYTES_PER_BMUNIT; i > 0; --i) {
|
||||
*cp = *SUB(cp, bytes_wide);
|
||||
++cp;
|
||||
}
|
||||
rows_left -= PK_repeat_count + 1;
|
||||
PK_repeat_count = 0;
|
||||
word = 0;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
count -= h_bit;
|
||||
h_bit = g->bitmap.w;
|
||||
} else {
|
||||
if (paint_switch)
|
||||
word |= bit_masks[word_weight] << (BITS_PER_BMUNIT - word_weight);
|
||||
*cp++ = word;
|
||||
word = 0;
|
||||
count -= word_weight;
|
||||
h_bit -= word_weight;
|
||||
word_weight = BITS_PER_BMUNIT;
|
||||
}
|
||||
}
|
||||
paint_switch = 1 - paint_switch;
|
||||
}
|
||||
if (cp != ((BMUNIT *) (g->bitmap.bits + bytes_wide * g->bitmap.h)))
|
||||
oops(i18n("Wrong number of bits stored: char. %1, font %2").arg(ch).arg(fontname));
|
||||
if (rows_left != 0 || h_bit != g->bitmap.w)
|
||||
oops(i18n("Bad pk file (%1), too many bits").arg(fontname));
|
||||
}
|
||||
} // endif: big or small Endian?
|
||||
}
|
||||
|
||||
void font::read_PK_index(void)
|
||||
{
|
||||
#ifdef DEBUG_PK
|
||||
kdDebug(4300) << "Reading PK pixel file " << filename << endl;
|
||||
#endif
|
||||
|
||||
fseek(file, (long) one(file), SEEK_CUR); /* skip comment */
|
||||
|
||||
(void) four(file); /* skip design size */
|
||||
Q_UINT32 file_checksum = four(file);
|
||||
if (checksum && checksum && file_checksum != checksum)
|
||||
kdWarning(4300) << i18n("Checksum mismatch for PK font file %3 (dvi=%1, pk=%2)").arg(checksum).arg(file_checksum).arg(filename) << endl;
|
||||
|
||||
int hppp = sfour(file);
|
||||
int vppp = sfour(file);
|
||||
if (hppp != vppp)
|
||||
kdWarning(4300) << i18n("Font has non-square aspect ratio ") << vppp << ":" << hppp << endl;
|
||||
|
||||
// Prepare glyph array.
|
||||
glyphtable = new glyph[max_num_of_chars_in_font];
|
||||
if (glyphtable == 0) {
|
||||
kdError(4300) << i18n("Could not allocate memory for a glyph table.") << endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
// Read glyph directory (really a whole pass over the file).
|
||||
for (;;) {
|
||||
int bytes_left, flag_low_bits;
|
||||
unsigned int ch;
|
||||
|
||||
PK_skip_specials();
|
||||
if (PK_flag_byte == PK_POST)
|
||||
break;
|
||||
flag_low_bits = PK_flag_byte & 0x7;
|
||||
if (flag_low_bits == 7) {
|
||||
bytes_left = four(file);
|
||||
ch = four(file);
|
||||
} else
|
||||
if (flag_low_bits > 3) {
|
||||
bytes_left = ((flag_low_bits - 4) << 16) + two(file);
|
||||
ch = one(file);
|
||||
} else {
|
||||
bytes_left = (flag_low_bits << 8) + one(file);
|
||||
ch = one(file);
|
||||
}
|
||||
glyphtable[ch].addr = ftell(file);
|
||||
glyphtable[ch].x2 = PK_flag_byte;
|
||||
fseek(file, (long) bytes_left, SEEK_CUR);
|
||||
#ifdef DEBUG_PK
|
||||
kdDebug(4300) << "Scanning pk char " << ch << "at " << glyphtable[ch].addr << endl;
|
||||
#endif
|
||||
}
|
||||
}
|
75
psgs.cpp
75
psgs.cpp
|
@ -23,15 +23,9 @@ pageInfo::~pageInfo() {
|
|||
// ======================================================
|
||||
|
||||
ghostscript_interface::ghostscript_interface(double dpi, int pxlw, int pxlh) {
|
||||
//@@@ Error checking !
|
||||
pageList = new QIntDict<pageInfo>(256);
|
||||
pageList->setAutoDelete(TRUE);
|
||||
|
||||
MemoryCache = new QIntCache<QPixmap>(PAGES_IN_MEMORY_CACHE, PAGES_IN_MEMORY_CACHE);
|
||||
MemoryCache->setAutoDelete(TRUE);
|
||||
|
||||
DiskCache = new QIntCache<KTempFile>(PAGES_IN_DISK_CACHE, PAGES_IN_DISK_CACHE);
|
||||
DiskCache->setAutoDelete(TRUE);
|
||||
pageList.setAutoDelete(TRUE);
|
||||
MemoryCache.setAutoDelete(TRUE);
|
||||
DiskCache.setAutoDelete(TRUE);
|
||||
|
||||
PostScriptHeaderString = new QString();
|
||||
resolution = dpi;
|
||||
|
@ -40,12 +34,6 @@ ghostscript_interface::ghostscript_interface(double dpi, int pxlw, int pxlh) {
|
|||
}
|
||||
|
||||
ghostscript_interface::~ghostscript_interface() {
|
||||
if (pageList != 0L)
|
||||
delete pageList;
|
||||
if (MemoryCache != 0L)
|
||||
delete MemoryCache;
|
||||
if (DiskCache != 0L)
|
||||
delete DiskCache;
|
||||
if (PostScriptHeaderString != 0L)
|
||||
delete PostScriptHeaderString;
|
||||
}
|
||||
|
@ -56,58 +44,61 @@ void ghostscript_interface::setSize(double dpi, int pxlw, int pxlh) {
|
|||
pixel_page_w = pxlw;
|
||||
pixel_page_h = pxlh;
|
||||
|
||||
MemoryCache->clear();
|
||||
DiskCache->clear();
|
||||
MemoryCache.clear();
|
||||
DiskCache.clear();
|
||||
}
|
||||
|
||||
|
||||
void ghostscript_interface::setPostScript(int page, QString PostScript) {
|
||||
if (pageList->find(page) == 0) {
|
||||
if (pageList.find(page) == 0) {
|
||||
pageInfo *info = new pageInfo(PostScript);
|
||||
// Check if dict is big enough
|
||||
if (pageList->count() > pageList->size() -2)
|
||||
pageList->resize(pageList->size()*2);
|
||||
pageList->insert(page, info);
|
||||
if (pageList.count() > pageList.size() -2)
|
||||
pageList.resize(pageList.size()*2);
|
||||
pageList.insert(page, info);
|
||||
} else
|
||||
*(pageList->find(page)->PostScriptString) = PostScript;
|
||||
*(pageList.find(page)->PostScriptString) = PostScript;
|
||||
}
|
||||
|
||||
|
||||
void ghostscript_interface::setColor(int page, QColor background_color) {
|
||||
if (pageList->find(page) == 0) {
|
||||
if (pageList.find(page) == 0) {
|
||||
pageInfo *info = new pageInfo(QString::null);
|
||||
info->background = background_color;
|
||||
// Check if dict is big enough
|
||||
if (pageList->count() > pageList->size() -2)
|
||||
pageList->resize(pageList->size()*2);
|
||||
pageList->insert(page, info);
|
||||
} else
|
||||
pageList->find(page)->background = background_color;
|
||||
if (pageList.count() > pageList.size() -2)
|
||||
pageList.resize(pageList.size()*2);
|
||||
pageList.insert(page, info);
|
||||
} else
|
||||
pageList.find(page)->background = background_color;
|
||||
}
|
||||
|
||||
|
||||
// Returns the background color for a certain page. This color is
|
||||
// always guaranteed to be valid
|
||||
|
||||
QColor ghostscript_interface::getBackgroundColor(int page) {
|
||||
if (pageList->find(page) == 0)
|
||||
if (pageList.find(page) == 0)
|
||||
return Qt::white;
|
||||
else
|
||||
return pageList->find(page)->background;
|
||||
return pageList.find(page)->background;
|
||||
}
|
||||
|
||||
|
||||
void ghostscript_interface::clear(void) {
|
||||
PostScriptHeaderString->truncate(0);
|
||||
|
||||
MemoryCache->clear();
|
||||
DiskCache->clear();
|
||||
MemoryCache.clear();
|
||||
DiskCache.clear();
|
||||
|
||||
// Deletes all items, removes temporary files, etc.
|
||||
pageList->clear();
|
||||
pageList.clear();
|
||||
}
|
||||
|
||||
void ghostscript_interface::gs_generate_graphics_file(int page, QString filename) {
|
||||
emit(setStatusBarText(i18n("Generating PostScript graphics...")));
|
||||
|
||||
pageInfo *info = pageList->find(page);
|
||||
pageInfo *info = pageList.find(page);
|
||||
|
||||
// Generate a PNG-file
|
||||
// Step 1: Write the PostScriptString to a File
|
||||
|
@ -162,23 +153,23 @@ void ghostscript_interface::gs_generate_graphics_file(int page, QString filename
|
|||
|
||||
QPixmap *ghostscript_interface::graphics(int page) {
|
||||
|
||||
pageInfo *info = pageList->find(page);
|
||||
pageInfo *info = pageList.find(page);
|
||||
|
||||
// No PostScript? Then return immediately.
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
if ((info == 0) || (info->PostScriptString->isEmpty()))
|
||||
return 0;
|
||||
|
||||
// Gfx exists in the MemoryCache?
|
||||
QPixmap *CachedCopy = MemoryCache->find(page);
|
||||
QPixmap *CachedCopy = MemoryCache.find(page);
|
||||
if (CachedCopy != NULL)
|
||||
return new QPixmap(*CachedCopy);
|
||||
|
||||
// Gfx exists in the DiskCache?
|
||||
KTempFile *CachedCopyFile = DiskCache->find(page);
|
||||
KTempFile *CachedCopyFile = DiskCache.find(page);
|
||||
if (CachedCopyFile != NULL) {
|
||||
QPixmap *MemoryCopy = new QPixmap(CachedCopyFile->name());
|
||||
QPixmap *ReturnCopy = new QPixmap(*MemoryCopy);
|
||||
MemoryCache->insert(page, MemoryCopy);
|
||||
MemoryCache.insert(page, MemoryCopy);
|
||||
return ReturnCopy;
|
||||
}
|
||||
|
||||
|
@ -192,8 +183,8 @@ QPixmap *ghostscript_interface::graphics(int page) {
|
|||
|
||||
QPixmap *MemoryCopy = new QPixmap(GfxFile->name());
|
||||
QPixmap *ReturnCopy = new QPixmap(*MemoryCopy);
|
||||
MemoryCache->insert(page, MemoryCopy);
|
||||
DiskCache->insert(page, GfxFile);
|
||||
MemoryCache.insert(page, MemoryCopy);
|
||||
DiskCache.insert(page, GfxFile);
|
||||
return ReturnCopy;
|
||||
}
|
||||
#include "psgs.moc"
|
||||
|
|
6
psgs.h
6
psgs.h
|
@ -59,15 +59,15 @@ public:
|
|||
|
||||
private:
|
||||
void gs_generate_graphics_file(int page, QString filename);
|
||||
QIntDict<pageInfo> *pageList;
|
||||
QIntDict<pageInfo> pageList;
|
||||
|
||||
// Chache to store pages which contain PostScript and are therefore
|
||||
// slow to render.
|
||||
QIntCache<QPixmap> *MemoryCache;
|
||||
QIntCache<QPixmap> MemoryCache;
|
||||
|
||||
// Chache to store pages which contain PostScript and are therefore
|
||||
// slow to render.
|
||||
QIntCache<KTempFile> *DiskCache;
|
||||
QIntCache<KTempFile> DiskCache;
|
||||
|
||||
double resolution; // in dots per inch
|
||||
int pixel_page_w; // in pixels
|
||||
|
|
|
@ -172,11 +172,10 @@ void dviWindow::background_special(QString cp)
|
|||
{
|
||||
// The color specials are ignored during rendering, and used only in
|
||||
// the pre-scan phase
|
||||
if (PostScriptOutPutString == NULL) {
|
||||
if (PostScriptOutPutString != NULL) {
|
||||
QColor col = parseColorSpecification(cp.stripWhiteSpace());
|
||||
|
||||
//@@@@ do something with the color!
|
||||
|
||||
if (col.isValid())
|
||||
PS_interface->setColor(current_page, col);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue