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 + -
显示快捷键?