dvirenderer.cpp.svn-base
来自「okular」· SVN-BASE 代码 · 共 801 行 · 第 1/2 页
SVN-BASE
801 行
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-//// Class: dviRenderer//// Class for rendering TeX DVI files.// Part of KDVI- A previewer for TeX DVI files.//// (C) 2001-2005 Stefan Kebekus// Distributed under the GPL//#include <config.h>#include "dviRenderer.h"#include "dviFile.h"#include "dvisourcesplitter.h"#include "hyperlink.h"#include "kvs_debug.h"#include "prebookmark.h"#include "psgs.h"//#include "renderedDviPagePixmap.h"#include "dviPageInfo.h"#include <math.h>#include <QTime>#include <kconfig.h>#include <kglobal.h>#include <klocale.h>#include <kmessagebox.h>#include <kmimetype.h>#include <kprogressbar.h>#include <kstandarddirs.h>#include <kvbox.h>#include <q3ptrstack.h>#include <QApplication>#include <QCheckBox>#include <QFileInfo>#include <QHBoxLayout>#include <QLabel>#include <QPainter>#include <QRegExp>//#define DEBUG_DVIRENDERERQPainter *foreGroundPainter; // QPainter used for text//------ now comes the dviRenderer class implementation ----------dviRenderer::dviRenderer() : dviFile(0), resolutionInDPI(0), embedPS_progress(0), embedPS_numOfProgressedFiles(0), shrinkfactor(3), source_href(0), HTML_href(0), editorCommand(""), PostScriptOutPutString(0), PS_interface(new ghostscript_interface), _postscript(false), line_boundary_encountered(false), word_boundary_encountered(false), current_page(0), penWidth_in_mInch(0), number_of_elements_in_path(0), currentlyDrawnPage(0){#ifdef DEBUG_DVIRENDERER //kDebug(kvs::dvi) << "dviRenderer( parent=" << par << " )" << endl;#endif// connect(&font_pool, SIGNAL( setStatusBarText( const QString& ) ), this, SIGNAL( setStatusBarText( const QString& ) ) );// connect( &clearStatusBarTimer, SIGNAL(timeout()), this, SLOT(clearStatusBar()) ); // pass status bar messages through// connect(PS_interface, SIGNAL( setStatusBarText( const QString& ) ), this, SIGNAL( setStatusBarText( const QString& ) ) );}dviRenderer::~dviRenderer(){#ifdef DEBUG_DVIRENDERER kDebug(kvs::dvi) << "~dviRenderer" << endl;#endif QMutexLocker locker(&mutex); delete PS_interface; delete dviFile;}#if 0void dviRenderer::setPrefs(bool flag_showPS, const QString &str_editorCommand, bool useFontHints ){ //QMutexLocker locker(&mutex); _postscript = flag_showPS; editorCommand = str_editorCommand; font_pool.setParameters( useFontHints );}void dviRenderer::showInfo(){ QMutexLocker locker(&mutex); info->setDVIData(dviFile); info->show();}#endif//------ this function calls the dvi interpreter ----------void dviRenderer::drawPage(RenderedDocumentPagePixmap* page){#ifdef DEBUG_DVIRENDERER //kDebug(kvs::dvi) << "dviRenderer::drawPage(documentPage *) called, page number " << page->pageNumber << endl;#endif // Paranoid safety checks if (page == 0) { kError(kvs::dvi) << "dviRenderer::drawPage(documentPage *) called with argument == 0" << endl; return; } // Paranoid safety checks if (page->pageNumber == 0) { kError(kvs::dvi) << "dviRenderer::drawPage(documentPage *) called for a documentPage with page number 0" << endl; return; } QMutexLocker locker(&mutex); if ( dviFile == 0 ) { kError(kvs::dvi) << "dviRenderer::drawPage(documentPage *) called, but no dviFile class allocated." << endl; page->clear(); return; } if (page->pageNumber > dviFile->total_pages) { kError(kvs::dvi) << "dviRenderer::drawPage(documentPage *) called for a documentPage with page number " << page->pageNumber << " but the current dviFile has only " << dviFile->total_pages << " pages." << endl; return; } if ( dviFile->dvi_Data() == 0 ) { kError(kvs::dvi) << "dviRenderer::drawPage(documentPage *) called, but no dviFile is loaded yet." << endl; page->clear(); return; } double resolution = page->resolution; if (resolution != resolutionInDPI) setResolution(resolution); currentlyDrawnPage = page; shrinkfactor = 1200/resolutionInDPI; current_page = page->pageNumber-1; // Reset colors colorStack.clear(); globalColor = Qt::black; int pageWidth = page->width; int pageHeight = page->height; QImage img(pageWidth, pageHeight, QImage::Format_RGB32); foreGroundPainter = new QPainter(&img); if (foreGroundPainter != 0) { errorMsg = QString::null; draw_page(); delete foreGroundPainter; foreGroundPainter = 0; } else { kDebug(kvs::dvi) << "painter creation failed." << endl; } page->img = img;//page->setImage(img); // Postprocess hyperlinks // Without that, based on the way TeX draws certain characters like german "Umlaute", // some hyperlinks would be broken into two overlapping parts, in the middle of a word. QVector<Hyperlink>::iterator i = page->hyperLinkList.begin(); QVector<Hyperlink>::iterator j; while (i != page->hyperLinkList.end()) { // Iterator j always points to the element after i. j = i; j++; if (j == page->hyperLinkList.end()) break; Hyperlink& hi = *i; Hyperlink& hj = *j; bool merged = false; // Merge all hyperlinks that point to the same target, and have the same baseline. while (hi.linkText == hj.linkText && hi.baseline == hj.baseline) { merged = true; hi.box = hi.box.unite(hj.box); j++; if (j == page->hyperLinkList.end()) break; hj = *j; } if (merged) { i = page->hyperLinkList.erase(++i, j); } else { i++; } }#if 0 page->isEmpty = false; if (errorMsg.isEmpty() != true) { KMessageBox::detailedError(parentWidget, i18n("<qt><strong>File corruption</strong> KDVI could not interprete your DVI file. This is " "most commonly caused by a corrupted file.</qt>"), errorMsg, i18n("DVI File Error")); errorMsg = QString::null; currentlyDrawnPage = 0; return; } // Tell the user (once) if the DVI file contains source specials // ... we don't want our great feature to go unnoticed. RenderedDviPagePixmap* currentDVIPage = dynamic_cast<RenderedDviPagePixmap*>(currentlyDrawnPage); if (currentDVIPage) { if ((dviFile->sourceSpecialMarker == true) && (currentDVIPage->sourceHyperLinkList.size() > 0)) { dviFile->sourceSpecialMarker = false; // Show the dialog as soon as event processing is finished, and // the program is idle //FIXME //QTimer::singleShot( 0, this, SLOT(showThatSourceInformationIsPresent()) ); } }#endif currentlyDrawnPage = 0;}void dviRenderer::getText(RenderedDocumentPagePixmap* page){ bool postscriptBackup = _postscript; // Disable postscript-specials temporarely to speed up text extraction. _postscript = false; drawPage(page); _postscript = postscriptBackup;}#if 0void dviRenderer::showThatSourceInformationIsPresent(){ // In principle, we should use a KMessagebox here, but we want to // add a button "Explain in more detail..." which opens the // Helpcenter. Thus, we practically re-implement the KMessagebox // here. Most of the code is stolen from there. // Check if the 'Don't show again' feature was used KConfig *config = KGlobal::config(); KConfigGroup saver(config, "Notification Messages"); bool showMsg = config->readEntry( "KDVI-info_on_source_specials", true); if (showMsg) { KDialogBase dialog(i18n("KDVI: Information"), KDialogBase::Yes, KDialogBase::Yes, KDialogBase::Yes, parentWidget, "information", true, true, KStdGuiItem::ok()); KVBox *topcontents = new KVBox (&dialog); topcontents->setSpacing(KDialog::spacingHint()*2); topcontents->setMargin(KDialog::marginHint()*2); QWidget *contents = new QWidget(topcontents); QHBoxLayout * lay = new QHBoxLayout(contents); lay->setSpacing(KDialog::spacingHint()*2); lay->addStretch(1); QLabel *label1 = new QLabel( contents); label1->setPixmap(QMessageBox::standardIcon(QMessageBox::Information)); lay->addWidget(label1); QLabel *label2 = new QLabel( i18n("<qt>This DVI file contains source file information. You may click into the text with the " "middle mouse button, and an editor will open the TeX-source file immediately.</qt>"), contents); label2->setMinimumSize(label2->sizeHint()); lay->addWidget(label2); lay->addStretch(1); QSize extraSize = QSize(50,30); QCheckBox *checkbox = new QCheckBox(i18n("Do not show this message again"), topcontents); extraSize = QSize(50,0); dialog.setHelpLinkText(i18n("Explain in more detail...")); dialog.setHelp("inverse-search", "kdvi"); dialog.enableLinkedHelp(true); dialog.setMainWidget(topcontents); dialog.enableButtonSeparator(false); dialog.incInitialSize( extraSize ); dialog.exec(); showMsg = !checkbox->isChecked(); if (!showMsg) { KConfigGroup saver(config, "Notification Messages"); config->writeEntry( "KDVI-info_on_source_specials", showMsg); } config->sync(); }}#endifvoid dviRenderer::embedPostScript(){#ifdef DEBUG_DVIRENDERER kDebug(kvs::dvi) << "dviRenderer::embedPostScript()" << endl;#endif if (!dviFile) return;/* embedPS_progress = new KProgressDialog(parentWidget, i18n("Embedding PostScript Files"), QString::null, true); */ if (!embedPS_progress) return; embedPS_progress->setAllowCancel(false); embedPS_progress->showCancelButton(false); embedPS_progress->setMinimumDuration(400); embedPS_progress->progressBar()->setMaximum(dviFile->numberOfExternalPSFiles); embedPS_progress->progressBar()->setValue(0); embedPS_numOfProgressedFiles = 0; quint16 currPageSav = current_page; errorMsg = QString::null; for(current_page=0; current_page < dviFile->total_pages; current_page++) { if (current_page < dviFile->total_pages) { command_pointer = dviFile->dvi_Data() + dviFile->page_offset[int(current_page)]; end_pointer = dviFile->dvi_Data() + dviFile->page_offset[int(current_page+1)]; } else command_pointer = end_pointer = 0; memset((char *) &currinf.data, 0, sizeof(currinf.data)); currinf.fonttable = &(dviFile->tn_table); currinf._virtual = NULL; prescan(&dviRenderer::prescan_embedPS); } delete embedPS_progress; embedPS_progress = 0; if (!errorMsg.isEmpty()) { errorMsg = "<qt>" + errorMsg + "</qt>";// KMessageBox::detailedError(parentWidget, "<qt>" + i18n("Not all PostScript files could be embedded into your document.") + "</qt>", errorMsg); errorMsg = QString::null; } else/* KMessageBox::information(parentWidget, "<qt>" + i18n("All external PostScript files were embedded into your document. You " "will probably want to save the DVI file now.") + "</qt>", QString::null, "embeddingDone");*/ // Prescan phase starts here#ifdef PERFORMANCE_MEASUREMENT //kDebug(kvs::dvi) << "Time elapsed till prescan phase starts " << performanceTimer.elapsed() << "ms" << endl; //QTime preScanTimer; //preScanTimer.start();#endif dviFile->numberOfExternalPSFiles = 0; prebookmarks.clear(); for(current_page=0; current_page < dviFile->total_pages; current_page++) { PostScriptOutPutString = new QString(); if (current_page < dviFile->total_pages) { command_pointer = dviFile->dvi_Data() + dviFile->page_offset[int(current_page)]; end_pointer = dviFile->dvi_Data() + dviFile->page_offset[int(current_page+1)]; } else command_pointer = end_pointer = 0; memset((char *) &currinf.data, 0, sizeof(currinf.data)); currinf.fonttable = &(dviFile->tn_table); currinf._virtual = NULL; prescan(&dviRenderer::prescan_parseSpecials); if (!PostScriptOutPutString->isEmpty()) PS_interface->setPostScript(current_page, *PostScriptOutPutString); delete PostScriptOutPutString; } PostScriptOutPutString = NULL;#ifdef PERFORMANCE_MEASUREMENT
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?