/************************************************************************* ** PSInterpreter.hpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** ** Copyright (C) 2005-2024 Martin Gieseking ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** ** published by the Free Software Foundation; either version 3 of ** ** the License, or (at your option) any later version. ** ** ** ** This program is distributed in the hope that it will be useful, but ** ** WITHOUT ANY WARRANTY; without even the implied warranty of ** ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** ** GNU General Public License for more details. ** ** ** ** You should have received a copy of the GNU General Public License ** ** along with this program; if not, see . ** *************************************************************************/ #ifndef PSINTERPRETER_HPP #define PSINTERPRETER_HPP #include #include #include #include #include "BoundingBox.hpp" #include "Ghostscript.hpp" #include "InputReader.hpp" #include "MessageException.hpp" struct PSException : public MessageException { explicit PSException (const std::string &msg) : MessageException(msg) {} }; /** This interface provides the template methods called by PSInterpreter when executing a PS snippet. * Each method corresponds to a PostScript operator of the same name. */ struct PSActions { virtual ~PSActions () =default; virtual void applyscalevals (std::vector &p) =0; virtual void clip (std::vector &p) =0; virtual void clippath (std::vector &p) =0; virtual void closepath (std::vector &p) =0; virtual void curveto (std::vector &p) =0; virtual void eoclip (std::vector &p) =0; virtual void eofill (std::vector &p) =0; virtual void fill (std::vector &p) =0; virtual void gsave (std::vector &p) =0; virtual void grestore (std::vector &p) =0; virtual void grestoreall (std::vector &p) =0; virtual void image (std::vector &p) =0; virtual void initclip (std::vector &p) =0; virtual void lineto (std::vector &p) =0; virtual void makepattern (std::vector &p) =0; virtual void moveto (std::vector &p) =0; virtual void newpath (std::vector &p) =0; virtual void querypos (std::vector &p) =0; virtual void restore (std::vector &p) =0; virtual void rotate (std::vector &p) =0; virtual void save (std::vector &p) =0; virtual void scale (std::vector &p) =0; virtual void setalphaisshape (std::vector &p) =0; virtual void setblendmode (std::vector &p) =0; virtual void setcolorspace (std::vector &p) =0; virtual void setcmykcolor (std::vector &cmyk) =0; virtual void setdash (std::vector &p) =0; virtual void setfillconstantalpha (std::vector &p) =0; virtual void setgray (std::vector &p) =0; virtual void sethsbcolor (std::vector &hsb) =0; virtual void setlinecap (std::vector &p) =0; virtual void setlinejoin (std::vector &p) =0; virtual void setlinewidth (std::vector &p) =0; virtual void setmatrix (std::vector &p) =0; virtual void setmiterlimit (std::vector &p) =0; virtual void setnulldevice (std::vector &p) =0; virtual void setpagedevice (std::vector &p) =0; virtual void setpattern (std::vector &p) =0; virtual void setrgbcolor (std::vector &rgb) =0; virtual void setstrokeconstantalpha (std::vector &p) =0; virtual void shfill (std::vector &p) =0; virtual void stroke (std::vector &p) =0; virtual void translate (std::vector &p) =0; virtual void executed () {} // triggered if one of the above PS operators has been executed }; class PSFilter; struct PSDeviceInfo { std::string name; std::string description; }; /** This class provides methods to execute chunks of PostScript code and calls * several template methods on invocation of selected PS operators (see PSActions). */ class PSInterpreter { enum Mode {PS_NONE, PS_RUNNING, PS_QUIT}; public: explicit PSInterpreter (PSActions *actions=nullptr); PSInterpreter (const PSInterpreter &psi) =delete; bool execute (const char *str, size_t len, bool flush=true); bool execute (const char *str, bool flush=true) {return execute(str, std::strlen(str), flush);} bool execute (const std::string &str, bool flush=true) {return execute(str.c_str(), flush);} bool execute (std::istream &is, bool flush=true); bool executeRaw (const std::string &str, int n); bool active () const {return _mode != PS_QUIT;} void limit (size_t max_bytes) {_bytesToRead = max_bytes;} PSActions* setActions (PSActions *actions); int pdfPageCount (const std::string &fname); BoundingBox pdfPageBox (const std::string &fname, int pageno); const std::vector& rawData () const {return _rawData;} bool setImageDevice (const std::string &deviceStr); bool hasFullOpacitySupport () const {return _gs.revision() >= 952;} bool supportsPDF () const {return _gs.revision() > 0 && _gs.revision() < 10010;} static std::vector getImageDeviceInfos (); static void listImageDeviceInfos (std::ostream &os); static bool imageDeviceKnown (std::string deviceStr); protected: void init (); // callback functions static int GSDLLCALL input (void *inst, char *buf, int len); static int GSDLLCALL output (void *inst, const char *buf, int len); static int GSDLLCALL error (void *inst, const char *buf, int len); void checkStatus (int status); void callActions (InputReader &cib); private: Ghostscript _gs; Mode _mode; ///< current execution mode PSActions *_actions=nullptr; ///< actions to be performed size_t _bytesToRead=0; ///< if > 0, maximal number of bytes to be processed by following calls of execute() std::vector _linebuf; std::string _errorMessage; ///< text of error message bool _inError=false; ///< true if scanning error message bool _initialized=false; ///< true if PSInterpreter has been completely initialized std::vector _rawData; ///< raw data received static const char *PSDEFS; ///< initial PostScript definitions }; #endif