File indexing completed on 2024-05-12 16:06:36

0001 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
0002 //
0003 // Class: dviRenderer
0004 //
0005 // Class for rendering TeX DVI files.
0006 // Part of KDVI- A previewer for TeX DVI files.
0007 //
0008 // SPDX-FileCopyrightText: 2001-2006 Stefan Kebekus
0009 // SPDX-License-Identifier: GPL-2.0-or-later
0010 
0011 #ifndef _dvirenderer_h_
0012 #define _dvirenderer_h_
0013 
0014 #include "bigEndianByteReader.h"
0015 //#include "documentRenderer.h"
0016 #include "dviexport.h"
0017 //#include "dvisourceeditor.h"
0018 #include "anchor.h"
0019 #include "dviPageInfo.h"
0020 #include "fontpool.h"
0021 #include "pageSize.h"
0022 #include "prebookmark.h"
0023 
0024 #include <QExplicitlySharedDataPointer>
0025 #include <QHash>
0026 #include <QMutex>
0027 #include <QPolygon>
0028 #include <QPrinter>
0029 #include <QProgressDialog>
0030 #include <QStack>
0031 #include <QTimer>
0032 #include <QUrl>
0033 #include <QVector>
0034 
0035 class Anchor;
0036 class DocumentWidget;
0037 class dvifile;
0038 class dviRenderer;
0039 class ghostscript_interface;
0040 class QEventLoop;
0041 class QProgressDialog;
0042 class PreBookmark;
0043 class TeXFontDefinition;
0044 
0045 extern const int MFResolutions[];
0046 
0047 class DVI_SourceFileAnchor
0048 {
0049 public:
0050     DVI_SourceFileAnchor()
0051     {
0052     }
0053     DVI_SourceFileAnchor(const QString &name, quint32 ln, quint32 pg, const Length _distance_from_top)
0054         : fileName(name)
0055         , line(ln)
0056         , page(pg)
0057         , distance_from_top(_distance_from_top)
0058     {
0059     }
0060 
0061     QString fileName;
0062     quint32 line;
0063     quint32 page;
0064     Length distance_from_top;
0065 };
0066 
0067 /** Compound of registers, as defined in section 2.6.2 of the DVI
0068     driver standard, Level 0, published by the TUG DVI driver
0069     standards committee. */
0070 
0071 struct framedata {
0072     long dvi_h;
0073     long dvi_v;
0074     long w;
0075     long x;
0076     long y;
0077     long z;
0078     int pxl_v;
0079 };
0080 
0081 /* this information is saved when using virtual fonts */
0082 
0083 typedef void (dviRenderer::*set_char_proc)(unsigned int, unsigned int);
0084 typedef void (dviRenderer::*parseSpecials)(char *, quint8 *);
0085 
0086 struct drawinf {
0087     struct framedata data;
0088     TeXFontDefinition *fontp;
0089     set_char_proc set_char_p;
0090 
0091     QHash<int, TeXFontDefinition *> *fonttable;
0092     TeXFontDefinition *_virtual;
0093 };
0094 
0095 class dviRenderer : public QObject /*: public DocumentRenderer*/, bigEndianByteReader
0096 {
0097     Q_OBJECT
0098 
0099 public:
0100     explicit dviRenderer(bool useFontHinting);
0101     ~dviRenderer() override;
0102 
0103     virtual bool setFile(const QString &fname, const QUrl &base);
0104 
0105     dvifile *dviFile;
0106 
0107     virtual bool supportsTextSearch() const
0108     {
0109         return true;
0110     }
0111 
0112     bool showPS()
0113     {
0114         return _postscript;
0115     }
0116     int curr_page()
0117     {
0118         return current_page + 1;
0119     }
0120     virtual bool isValidFile(const QString &fileName) const;
0121 
0122     /** This method will try to parse the reference part of the DVI
0123         file's URL, (either a number, which is supposed to be a page
0124         number, or src:\<line\>\<filename\>) and see if a corresponding
0125         section of the DVI file can be found. If so, it returns an
0126         anchor to that section. If not, it returns an invalid anchor. */
0127     virtual Anchor parseReference(const QString &reference);
0128 
0129     Anchor findAnchor(const QString &);
0130 
0131     virtual PageNumber totalPages() const;
0132 
0133     void setEventLoop(QEventLoop *el);
0134 
0135     // These should not be public... only for the moment
0136     void read_postamble();
0137     void draw_part(double current_dimconv, bool is_vfmacro);
0138     void set_vf_char(unsigned int cmd, unsigned int ch);
0139     void set_char(unsigned int cmd, unsigned int ch);
0140     void set_empty_char(unsigned int cmd, unsigned int ch);
0141     void set_no_char(unsigned int cmd, unsigned int ch);
0142     void applicationDoSpecial(char *cp);
0143 
0144     void special(long nbytes);
0145     void printErrorMsgForSpecials(const QString &msg);
0146     void color_special(const QString &msg);
0147     void html_href_special(const QString &msg);
0148     void html_anchor_end();
0149     void draw_page();
0150     void export_finished(const DVIExport *);
0151     // void          editor_finished(const DVISourceEditor*);
0152 
0153     QVector<PreBookmark> getPrebookmarks() const
0154     {
0155         return prebookmarks;
0156     }
0157 
0158 Q_SIGNALS:
0159     /**
0160      * The following three signals are modeleed on the corresponding signals
0161      * of the Document class.
0162      */
0163     void error(const QString &message, int duration);
0164     void warning(const QString &message, int duration);
0165     void notice(const QString &message, int duration);
0166 
0167 public Q_SLOTS:
0168     void exportPS(const QString &fname = QString(), const QStringList &options = QStringList(), QPrinter *printer = nullptr, QPageLayout::Orientation orientation = QPageLayout::Portrait);
0169     void exportPDF();
0170 
0171     void handleSRCLink(const QString &linkText, const QPoint point, DocumentWidget *widget);
0172 
0173     void embedPostScript();
0174 
0175     virtual void drawPage(RenderedDocumentPagePixmap *page);
0176     virtual void getText(RenderedDocumentPagePixmap *page);
0177 
0178     SimplePageSize sizeOfPage(const PageNumber page);
0179 
0180     const QVector<DVI_SourceFileAnchor> &sourceAnchors()
0181     {
0182         return sourceHyperLinkAnchors;
0183     }
0184 
0185 private Q_SLOTS:
0186     /** This method shows a dialog that tells the user that source
0187         information is present, and gives the opportunity to open the
0188         manual and learn more about forward and inverse search */
0189     //  void          showThatSourceInformationIsPresent();
0190 
0191 private:
0192     friend class DVIExportToPS;
0193     friend class DVIExport;
0194     //  friend class DVISourceEditor;
0195 
0196     /** URL to the DVI file
0197         This field is initialized by the setFile() method. See the
0198         explanation there. */
0199     QUrl baseURL;
0200 
0201     /** This method parses a color specification of type "gray 0.5", "rgb
0202         0.5 0.7 1.0", "hsb ...", "cmyk .." or "PineGreen". See the source
0203         code for details. */
0204     QColor parseColorSpecification(const QString &colorSpec);
0205 
0206     /** This map contains the colors which are known by name. This field
0207         is initialized in the method parseColorSpecification() as soon as
0208         it is needed. */
0209     QMap<QString, QColor> namedColors;
0210 
0211     /** This method locates special PDF characters in a string and
0212         replaces them by UTF8. See Section 3.2.3 of the PDF reference
0213         guide for information */
0214     QString PDFencodingToQString(const QString &pdfstring);
0215 
0216     void setResolution(double resolution_in_DPI);
0217 
0218     fontPool font_pool;
0219 
0220     double resolutionInDPI;
0221 
0222     // @@@ explanation
0223     void prescan(parseSpecials specialParser);
0224     void prescan_embedPS(char *cp, quint8 *);
0225     void prescan_removePageSizeInfo(char *cp, quint8 *);
0226     void prescan_parseSpecials(char *cp, quint8 *);
0227     void prescan_ParsePapersizeSpecial(const QString &cp);
0228     void prescan_ParseBackgroundSpecial(const QString &cp);
0229     void prescan_ParseHTMLAnchorSpecial(const QString &cp);
0230     void prescan_ParsePSHeaderSpecial(const QString &cp);
0231     void prescan_ParsePSBangSpecial(const QString &cp);
0232     void prescan_ParsePSQuoteSpecial(const QString &cp);
0233     void prescan_ParsePSSpecial(const QString &cp);
0234     void prescan_ParsePSFileSpecial(const QString &cp);
0235     void prescan_ParseSourceSpecial(QStringView cp);
0236     void prescan_setChar(unsigned int ch);
0237 
0238     /* */
0239     QVector<PreBookmark> prebookmarks;
0240 
0241     /** Utility fields used by the embedPostScript method*/
0242     QProgressDialog *embedPS_progress;
0243     quint16 embedPS_numOfProgressedFiles;
0244 
0245     /** Shrink factor. Units are not quite clear */
0246     double shrinkfactor;
0247 
0248     QString errorMsg;
0249 
0250     /** Methods which handle certain special commands. */
0251     void epsf_special(const QString &cp);
0252     void source_special(const QString &cp);
0253 
0254     /** TPIC specials */
0255     void TPIC_setPen_special(const QString &cp);
0256     void TPIC_addPath_special(const QString &cp);
0257     void TPIC_flushPath_special();
0258 
0259     // List of source-hyperlinks on all pages. This vector is generated
0260     // when the DVI-file is first loaded, i.e. when draw_part is called
0261     // with PostScriptOutPutString != NULL
0262     QVector<DVI_SourceFileAnchor> sourceHyperLinkAnchors;
0263 
0264     // If not NULL, the text currently drawn represents a source
0265     // hyperlink to the (relative) URL given in the string;
0266     QString *source_href;
0267 
0268     // If not NULL, the text currently drawn represents a hyperlink to
0269     // the (relative) URL given in the string;
0270     QString *HTML_href;
0271 
0272     QString editorCommand;
0273 
0274     /** Stack for register compounds, used for the DVI-commands PUSH/POP
0275         as explained in section 2.5 and 2.6.2 of the DVI driver standard,
0276         Level 0, published by the TUG DVI driver standards committee. */
0277     QStack<framedata> stack;
0278 
0279     /** A stack where color are stored, according to the documentation of
0280         DVIPS */
0281     QStack<QColor> colorStack;
0282 
0283     /** The global color is to be used when the color stack is empty */
0284     QColor globalColor;
0285 
0286     /** If PostScriptOutPutFile is non-zero, then no rendering takes
0287         place. Instead, the PostScript code which is generated by the
0288         \special-commands is written to the PostScriptString */
0289     QString *PostScriptOutPutString;
0290 
0291     ghostscript_interface *PS_interface;
0292 
0293     /** true, if gs should be used, otherwise, only bounding boxes are
0294         drawn. */
0295     bool _postscript;
0296 
0297     /** This flag is used when rendering a dvi-page. It is set to "true"
0298         when any dvi-command other than "set" or "put" series of commands
0299         is encountered. This is considered to mark the end of a word. */
0300     bool line_boundary_encountered;
0301     bool word_boundary_encountered;
0302 
0303     unsigned int current_page;
0304 
0305     /** Data required for handling TPIC specials */
0306     float penWidth_in_mInch;
0307     QPolygon TPIC_path;
0308     quint16 number_of_elements_in_path;
0309 
0310     drawinf currinf;
0311     RenderedDocumentPagePixmap *currentlyDrawnPage;
0312     QMap<const DVIExport *, QExplicitlySharedDataPointer<DVIExport>> all_exports_;
0313     // QExplicitlySharedDataPointer<DVISourceEditor> editor_;
0314 
0315     /** Flag if document is modified
0316 
0317     This flag indicates if the document was modified after it was
0318     loaded. It is set to 'false' in the constructor, in the clear() and
0319     setFile() method. It can be set to 'true' be methods that modify the
0320     document (e.g. the deletePages() method of the djvu implementation
0321     of this class).
0322      */
0323     bool _isModified;
0324 
0325     QMutex mutex;
0326     quint16 numPages;
0327 
0328     // TODO: merge into dviPageInfo
0329     QVector<SimplePageSize> pageSizes;
0330 
0331     QMap<QString, Anchor> anchorList;
0332 
0333     QEventLoop *m_eventLoop;
0334 
0335     QPainter *foreGroundPainter;
0336 
0337     // was the locateFonts method of font pool executed?
0338     bool fontpoolLocateFontsDone;
0339 };
0340 
0341 #endif