diff options
Diffstat (limited to 'scribus/plugins/scriptplugin/objprinter.cpp')
| -rw-r--r-- | scribus/plugins/scriptplugin/objprinter.cpp | 613 |
1 files changed, 613 insertions, 0 deletions
diff --git a/scribus/plugins/scriptplugin/objprinter.cpp b/scribus/plugins/scriptplugin/objprinter.cpp new file mode 100644 index 0000000..eb60f4f --- /dev/null +++ b/scribus/plugins/scriptplugin/objprinter.cpp @@ -0,0 +1,613 @@ +/* +For general Scribus (>=1.3.2) copyright and licensing information please refer +to the COPYING file provided with the program. Following this notice may exist +a copyright and/or license notice that predates the release of Scribus 1.3.2 +for which a new license (GPL+exception) is in place. +*/ +#include <vector> +#include <iostream> + +#include "objprinter.h" +#include "cmdutil.h" +#include "prefsmanager.h" + +#include <structmember.h> +#include <QFileInfo> +#include <QDir> + +#include "pslib.h" +#include "scpaths.h" +#include "scribuscore.h" +#include "util_file.h" +#include "util_ghostscript.h" +#include "util_printer.h" + +#ifdef HAVE_CUPS +#include <cups/cups.h> +#endif +// these functions are located at utils.cpp +bool SCRIBUS_API loadText(QString nam, QString *Buffer); +void SCRIBUS_API ReOrderText(ScribusDoc *doc, ScribusView *view); +// end of utils.cpp + +#if defined(_WIN32) +#include "scprintengine_gdi.h" +#endif + +typedef struct +{ + PyObject_HEAD + PyObject *allPrinters; // list of strings - names of installed printers + PyObject *printer; // string - selected printer + PyObject *file; // string - name of file to print into (eg. output.ps) + PyObject *cmd; // string - if "" use standard command else use this as command (eg. "kprinter", "xpp" ...) + PyObject *pages; // list of integers - pages to be printed + int copies; // numer of printed copies + PyObject *separation; // string - No; All; Cyan; Magenta; Yellow; Black + int color; // bool - do we print in color=1 or greyscale=0 + int useICC; // bool - do we use ICC Profiles 0 = No 1 = Yes + int pslevel; // integer - 1, 2 or 3 level of used postscript + int mph; // bool - mirror pages horizontally + int mpv; // bool - mirror pages vertically + int ucr; // bool - Under Color Removal +} Printer; + + +static void Printer_dealloc(Printer* self) +{ + Py_XDECREF(self->allPrinters); + Py_XDECREF(self->printer); + Py_XDECREF(self->file); + Py_XDECREF(self->cmd); + Py_XDECREF(self->pages); + Py_XDECREF(self->separation); + self->ob_type->tp_free((PyObject *)self); +} + +static PyObject * Printer_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/) +{ +// do not create new object if there is no opened document + if (!ScCore->primaryMainWindow()->HaveDoc) { + PyErr_SetString(PyExc_SystemError, "Need to open document first"); + return NULL; + } + + Printer *self; + self = (Printer *)type->tp_alloc(type, 0); + if (self != NULL) { +// set allPrinters attribute + self->allPrinters = PyList_New(0); + if (self->allPrinters == NULL){ + Py_DECREF(self); + return NULL; + } +// set printer attribute + self->printer = PyString_FromString(""); + if (self->printer == NULL){ + Py_DECREF(self); + return NULL; + } +// set file attribute + self->file = PyString_FromString(""); + if (self->file == NULL){ + Py_DECREF(self); + return NULL; + } +// set cmd attribute + self->cmd = PyString_FromString(""); + if (self->cmd == NULL){ + Py_DECREF(self); + return NULL; + } +// set pages attribute + self->pages = PyList_New(0); + if (self->pages == NULL){ + Py_DECREF(self); + return NULL; + } +// set separation attribute + self->separation = PyString_FromString("No"); + if (self->separation == NULL){ + Py_DECREF(self); + return NULL; + } +// set color attribute + self->color = 1; +// set useICC attribute + self->useICC = 0; +// set pslevel attribute + self->pslevel = 3; +// set mph attribute + self->mph = 0; +// set mpv attribute + self->mpv = 0; +// set ucr attribute + self->ucr = 1; +// set copies attribute + self->copies = 1; + } + return (PyObject *) self; +} + +static int Printer_init(Printer *self, PyObject * /*args*/, PyObject * /*kwds*/) +{ +// pool system for installed printers +// most code is stolen and little adopted from druck.cpp + PyObject *allPrinters = PyList_New(0); + if (allPrinters){ + Py_DECREF(self->allPrinters); + self->allPrinters = allPrinters; + } + QStringList printers = PrinterUtil::getPrinterNames(); + for (int i = 0; i < printers.count(); ++i) + { + QString prn = printers[i]; + if (prn.isEmpty()) + continue; + PyObject *tmppr = PyString_FromString(prn.toLocal8Bit().constData()); + if (tmppr){ + PyList_Append(self->allPrinters, tmppr); + Py_DECREF(tmppr); + } + } + PyObject *tmp2 = PyString_FromString("File"); + PyList_Append(self->allPrinters, tmp2); + Py_DECREF(tmp2); +// as defaut set to print into file + PyObject *printer = NULL; + printer = PyString_FromString("File"); + if (printer){ + Py_DECREF(self->printer); + self->printer = printer; + } +// set defaul name of file to print into + QString tf = ScCore->primaryMainWindow()->doc->PDF_Options.fileName; + if (tf.isEmpty()) { + QFileInfo fi = QFileInfo(ScCore->primaryMainWindow()->doc->DocName); + tf = fi.path()+"/"+fi.baseName()+".pdf"; + } + PyObject *file = NULL; + file = PyString_FromString(tf.toAscii()); + if (file){ + Py_DECREF(self->file); + self->file = file; + } else { + PyErr_SetString(PyExc_SystemError, "Can not initialize 'file' attribute"); + return -1; + } +// alternative printer commands default to "" + PyObject *cmd = NULL; + cmd = PyString_FromString(""); + if (cmd){ + Py_DECREF(self->cmd); + self->cmd = cmd; + } +// if document exist when created Printer instance +// set to print all pages + PyObject *pages = NULL; + int num = 0; + if (ScCore->primaryMainWindow()->HaveDoc) + // which one should I use ??? + // new = ScCore->primaryMainWindow()->view->Pages.count() + num = ScCore->primaryMainWindow()->doc->Pages->count(); + pages = PyList_New(num); + if (pages){ + Py_DECREF(self->pages); + self->pages = pages; + } + for (int i = 0; i<num; i++) { + PyObject *tmp=NULL; + tmp = PyInt_FromLong((long)i+1L); // instead of 1 put here first page number + if (tmp) + PyList_SetItem(self->pages, i, tmp); + } +// do not print separation + PyObject *separation = NULL; + separation = PyString_FromString("No"); + if (separation){ + Py_DECREF(self->separation); + self->separation = separation; + } +// print in color + self->color = 1; +// do not use ICC Profile + self->useICC = 0; +// use PostScrip level 3 + self->pslevel = 3; +// do not mirror pages + self->mph = 0; +// do not mirror pages + self->mpv = 0; +// apply Under Color Removal as default + self->ucr = 1; +// number of copies + self->copies = 1; + return 0; +} + +static PyMemberDef Printer_members[] = { + {const_cast<char*>("copies"), T_INT, offsetof(Printer, copies), 0, const_cast<char*>("Number of copies")}, + {const_cast<char*>("color"), T_INT, offsetof(Printer, color), 0, const_cast<char*>("Print in color.\n\t True - color -- Default\n\t False - greyscale")}, + {const_cast<char*>("useICC"), T_INT, offsetof(Printer, useICC), 0, const_cast<char*>("Use ICC Profile\n\tTrue\n\tFalse -- Default")}, + {const_cast<char*>("pslevel"), T_INT, offsetof(Printer, pslevel), 0, const_cast<char*>("PostScript Level\nCan be 1 or 2 or 3 -- Default is 3.")}, + {const_cast<char*>("mph"), T_INT, offsetof(Printer, mph), 0, const_cast<char*>("Mirror Pages Horizontal\n\tTrue\n\tFalse -- Default")}, + {const_cast<char*>("mpv"), T_INT, offsetof(Printer, mpv), 0, const_cast<char*>("Mirror Pages Vertical\n\t True\n\tFalse -- Default")}, + {const_cast<char*>("ucr"), T_INT, offsetof(Printer, ucr), 0, const_cast<char*>("Apply Under Color Removal\n\tTrue -- Default\n\tFalse")}, + {NULL, 0, 0, 0, NULL} // sentinel +}; + +/* Here begins Getter & Setter functions */ + +static PyObject *Printer_getallPrinters(Printer *self, void * /*closure*/) +{ + Py_INCREF(self->allPrinters); + return self->allPrinters; +} + +static int Printer_setallPrinters(Printer * /*self*/, PyObject * /*value*/, void * /*closure*/) +{ + PyErr_SetString(PyExc_ValueError, "'allPrinters' attribute is READ-ONLY"); + return -1; +} + +static PyObject *Printer_getprinter(Printer *self, void * /*closure*/) +{ + Py_INCREF(self->printer); + return self->printer; +} + +static int Printer_setprinter(Printer *self, PyObject *value, void * /*closure*/) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete 'printer' attribute."); + return -1; + } + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError, "The 'printer' attribute value must be string."); + return -1; + } + int n = PyList_Size(self->allPrinters); + bool same = 0; + for (int i = 0; i<n; i++) + if (PyObject_RichCompareBool(value, PyList_GetItem(self->allPrinters, i), Py_EQ) == 1) + same = true; + if (!same) { + PyErr_SetString(PyExc_ValueError, "'printer' value can be only one of string in 'allPrinters' attribute "); + return -1; + } + Py_DECREF(self->printer); + Py_INCREF(value); + self->printer = value; + return 0; +} + +static PyObject *Printer_getfile(Printer *self, void * /*closure*/) +{ + Py_INCREF(self->file); + return self->file; +} + +static int Printer_setfile(Printer *self, PyObject *value, void * /*closure*/) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete 'file' attribute."); + return -1; + } + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError, "The 'file' attribute value must be string."); + return -1; + } + Py_DECREF(self->file); + Py_INCREF(value); + self->file = value; + return 0; +} + +static PyObject *Printer_getcmd(Printer *self, void * /*closure*/) +{ + Py_INCREF(self->cmd); + return self->cmd; +} + +static int Printer_setcmd(Printer *self, PyObject *value, void * /*closure*/) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete 'cmd' attribute."); + return -1; + } + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError, "The 'cmd' attribute value must be string."); + return -1; + } + Py_DECREF(self->cmd); + Py_INCREF(value); + self->cmd = value; + return 0; +} + +static PyObject *Printer_getpages(Printer *self, void * /*closure*/) +{ + Py_INCREF(self->pages); + return self->pages; +} + +static int Printer_setpages(Printer *self, PyObject *value, void * /*closure*/) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete 'pages' attribute."); + return -1; + } + if (!PyList_Check(value)) { + PyErr_SetString(PyExc_TypeError, "'pages' attribute value must be list of integers."); + return -1; + } + int len = PyList_Size(value); + for (int i = 0; i<len; i++){ + PyObject *tmp = PyList_GetItem(value, i); + if (!PyInt_Check(tmp)){ + PyErr_SetString(PyExc_TypeError, "'pages' attribute must be list containing only integers."); + return -1; + } + if (PyInt_AsLong(tmp) > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count()) || PyInt_AsLong(tmp) < 1) { + PyErr_SetString(PyExc_ValueError, "'pages' value out of range."); + return -1; + } + } + Py_DECREF(self->pages); + Py_INCREF(value); + self->pages = value; + return 0; +} + +static PyObject *Printer_getseparation(Printer *self, void * /*closure*/) +{ + Py_INCREF(self->separation); + return self->separation; +} + +static int Printer_setseparation(Printer *self, PyObject *value, void * /*closure*/) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete 'separation' attribute."); + return -1; + } + if (!PyString_Check(value)) { + PyErr_SetString(PyExc_TypeError, "The 'separation' attribute value must be string."); + return -1; + } + Py_DECREF(self->separation); + Py_INCREF(value); + self->separation = value; + return 0; +} + + +static PyGetSetDef Printer_getseters [] = { + {const_cast<char*>("allPrinters"), (getter)Printer_getallPrinters, (setter)Printer_setallPrinters, const_cast<char*>("List of installed printers -- read only"), NULL}, + {const_cast<char*>("printer"), (getter)Printer_getprinter, (setter)Printer_setprinter, const_cast<char*>("Name of printer to use.\nDefault is 'File' for printing into file"), NULL}, + {const_cast<char*>("file"), (getter)Printer_getfile, (setter)Printer_setfile, const_cast<char*>("Name of file to print into"), NULL}, + {const_cast<char*>("cmd"), (getter)Printer_getcmd, (setter)Printer_setcmd, const_cast<char*>("Alternative Printer Command"), NULL}, + {const_cast<char*>("pages"), (getter)Printer_getpages, (setter)Printer_setpages, const_cast<char*>("List of pages to be printed"), NULL}, + {const_cast<char*>("separation"), (getter)Printer_getseparation, (setter)Printer_setseparation, const_cast<char*>("Print separationl\n\t 'No' -- Default\n\t 'All'\n\t 'Cyan'\n\t 'Magenta'\n\t 'Yellow'\n\t 'Black'\nBeware of misspelling because check is not performed"), NULL}, + {NULL, NULL, NULL, NULL, NULL} // sentinel +}; + +// Here we actually print +static PyObject *Printer_print(Printer *self) +{ + if (!ScCore->primaryMainWindow()->HaveDoc) { + PyErr_SetString(PyExc_SystemError, "Need to open documetnt first"); + return NULL; + } +// copied from void ScribusMainWindow::slotFilePrint() in file scribus.cpp + QString fna, prn, cmd, scmd, cc, data, SepName; + QString printcomm; + bool fil, PSfile; + PSfile = false; + +// ReOrderText(ScCore->primaryMainWindow()->doc, ScCore->primaryMainWindow()->view); + prn = QString(PyString_AsString(self->printer)); + fna = QString(PyString_AsString(self->file)); + fil = (QString(PyString_AsString(self->printer)) == QString("File")) ? true : false; + std::vector<int> pageNs; + PrintOptions options; + for (int i = 0; i < PyList_Size(self->pages); ++i) { + options.pageNumbers.push_back((int)PyInt_AsLong(PyList_GetItem(self->pages, i))); + } + int Nr = (self->copies < 1) ? 1 : self->copies; + SepName = QString(PyString_AsString(self->separation)); + options.printer = prn; + options.prnEngine = (PrintEngine) self->pslevel; + options.toFile = fil; + options.separationName = SepName; + options.outputSeparations = (SepName == QString("No")) ? false : true; + options.useColor = self->color; + options.mirrorH = self->mph; + options.mirrorV = self->mpv; + options.useICC = self->useICC; + options.doGCR = self->ucr; + options.cropMarks = false; + options.bleedMarks = false; + options.registrationMarks = false; + options.colorMarks = false; + options.markOffset = 0.0; + options.bleeds.Top = 0.0; + options.bleeds.Left = 0.0; + options.bleeds.Right = 0.0; + options.bleeds.Bottom = 0.0; + if (!PrinterUtil::checkPrintEngineSupport(options.printer, options.prnEngine, options.toFile)) + options.prnEngine = PrinterUtil::getDefaultPrintEngine(options.printer, options.toFile); + printcomm = QString(PyString_AsString(self->cmd)); + QMap<QString, QMap<uint, FPointArray> > ReallyUsed; + ReallyUsed.clear(); + ScCore->primaryMainWindow()->doc->getUsedFonts(ReallyUsed); + PrefsManager *prefsManager=PrefsManager::instance(); + +#if defined(_WIN32) + if (!options.toFile) + { + QByteArray devMode; + bool printDone = false; + if ( PrinterUtil::getDefaultSettings(prn, options.devMode) ) + { + ScPrintEngine_GDI winPrint; + printDone = winPrint.print( *ScCore->primaryMainWindow()->doc, options ); + } + if (!printDone) + PyErr_SetString(PyExc_SystemError, "Printing failed"); + Py_RETURN_NONE; + } +#endif + + PSLib *dd = new PSLib(options, true, prefsManager->appPrefs.AvailFonts, ReallyUsed, ScCore->primaryMainWindow()->doc->PageColors, false, true); + if (dd != NULL) + { + if (!fil) + fna = QDir::toNativeSeparators(ScPaths::getTempFileDir()+"/tmp.ps"); + PSfile = dd->PS_set_file(fna); + fna = QDir::toNativeSeparators(fna); + if (PSfile) + { + options.setDevParam = false; + options.doClip = false; + dd->CreatePS(ScCore->primaryMainWindow()->doc, options); + if (options.prnEngine == PostScript1 || options.prnEngine == PostScript2) + { + if (ScCore->haveGS()) + { + QString tmp; + QStringList opts; + opts.append( QString("-dDEVICEWIDTHPOINTS=%1").arg(tmp.setNum(ScCore->primaryMainWindow()->doc->pageWidth)) ); + opts.append( QString("-dDEVICEHEIGHTPOINTS=%1").arg(tmp.setNum(ScCore->primaryMainWindow()->doc->pageHeight)) ); + convertPS2PS(fna, fna+".tmp", opts, options.prnEngine); + moveFile( fna + ".tmp", fna ); + } + else + { + PyErr_SetString(PyExc_SystemError, "Printing failed : GhostScript is needed to print to PostScript Level 1 or Level 2"); + Py_RETURN_NONE; + } + } + + if (!fil) + { + if (!printcomm.isEmpty()) + cmd = printcomm + " "+fna; + else + { + cmd = "lpr -P" + prn; + if (Nr > 1) + cmd += " -#" + cc.setNum(Nr); +#ifdef HAVE_CUPS +// This need yet to be implemented by object Printer +// cmd += printer->PrinterOpts; +#endif + cmd += " "+fna; + } + system(cmd.toLocal8Bit().constData()); + unlink(fna.toLocal8Bit().constData()); + } + } + else { + delete dd; + PyErr_SetString(PyExc_SystemError, "Printing failed"); + return NULL; + } + delete dd; + } +// Py_INCREF(Py_None); +// return Py_None; + Py_RETURN_NONE; +} + +static PyMethodDef Printer_methods[] = { + {const_cast<char*>("printNow"), (PyCFunction)Printer_print, METH_NOARGS, const_cast<char*>("Prints selected pages.")}, + {NULL, (PyCFunction)(0), 0, NULL} // sentinel +}; + +PyTypeObject Printer_Type = { + PyObject_HEAD_INIT(NULL) // PyObject_VAR_HEAD + 0, // + const_cast<char*>("Printer"), // char *tp_name; /* For printing, in format "<module>.<name>" */ + sizeof(Printer), // int tp_basicsize, /* For allocation */ + 0, // int tp_itemsize; /* For allocation */ + + /* Methods to implement standard operations */ + + (destructor) Printer_dealloc, // destructor tp_dealloc; + 0, // printfunc tp_print; + 0, // getattrfunc tp_getattr; + 0, // setattrfunc tp_setattr; + 0, // cmpfunc tp_compare; + 0, // reprfunc tp_repr; + + /* Method suites for standard classes */ + + 0, // PyNumberMethods *tp_as_number; + 0, // PySequenceMethods *tp_as_sequence; + 0, // PyMappingMethods *tp_as_mapping; + + /* More standard operations (here for binary compatibility) */ + + 0, // hashfunc tp_hash; + 0, // ternaryfunc tp_call; + 0, // reprfunc tp_str; + 0, // getattrofunc tp_getattro; + 0, // setattrofunc tp_setattro; + + /* Functions to access object as input/output buffer */ + 0, // PyBufferProcs *tp_as_buffer; + + /* Flags to define presence of optional/expanded features */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, // long tp_flags; + + printer__doc__, // char *tp_doc; /* Documentation string */ + + /* Assigned meaning in release 2.0 */ + /* call function for all accessible objects */ + 0, // traverseproc tp_traverse; + + /* delete references to contained objects */ + 0, // inquiry tp_clear; + + /* Assigned meaning in release 2.1 */ + /* rich comparisons */ + 0, // richcmpfunc tp_richcompare; + + /* weak reference enabler */ + 0, // long tp_weaklistoffset; + + /* Added in release 2.2 */ + /* Iterators */ + 0, // getiterfunc tp_iter; + 0, // iternextfunc tp_iternext; + + /* Attribute descriptor and subclassing stuff */ + Printer_methods, // struct PyMethodDef *tp_methods; + Printer_members, // struct PyMemberDef *tp_members; + Printer_getseters, // struct PyGetSetDef *tp_getset; + 0, // struct _typeobject *tp_base; + 0, // PyObject *tp_dict; + 0, // descrgetfunc tp_descr_get; + 0, // descrsetfunc tp_descr_set; + 0, // long tp_dictoffset; + (initproc)Printer_init, // initproc tp_init; + 0, // allocfunc tp_alloc; + Printer_new, // newfunc tp_new; + 0, // freefunc tp_free; /* Low-level free-memory routine */ + 0, // inquiry tp_is_gc; /* For PyObject_IS_GC */ + 0, // PyObject *tp_bases; + 0, // PyObject *tp_mro; /* method resolution order */ + 0, // PyObject *tp_cache; + 0, // PyObject *tp_subclasses; + 0, // PyObject *tp_weaklist; + 0, // destructor tp_del; + +#ifdef COUNT_ALLOCS + /* these must be last and never explicitly initialized */ + // int tp_allocs; + // int tp_frees; + // int tp_maxalloc; + // struct _typeobject *tp_next; +#endif +}; |
