This modifies the Postscript printer to be able to insert a pipe in between the Postscript generation
and the transport addon. The actual command use as pipe is retrieved from the PPD that can be selected at printer creation time. Currently PPD selection is not shown (as the PPD directory is not available) and therefore the pipe will not be inserted. This still needs a bit of TLC, so hope to commit the last changes to fully support this later this week. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36173 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
954af58694
commit
f7b0c08cae
@ -20,9 +20,9 @@ class BNode;
|
||||
class PrinterData {
|
||||
public:
|
||||
PrinterData(BNode *node = NULL);
|
||||
~PrinterData();
|
||||
void load();
|
||||
void save();
|
||||
virtual ~PrinterData();
|
||||
virtual void load();
|
||||
virtual void save();
|
||||
|
||||
const string &getDriverName() const;
|
||||
const string &getPrinterName() const;
|
||||
@ -40,14 +40,13 @@ protected:
|
||||
PrinterData(const PrinterData &printer_data);
|
||||
PrinterData &operator = (const PrinterData &printer_data);
|
||||
|
||||
BNode *fNode;
|
||||
private:
|
||||
string fDriverName;
|
||||
string fPrinterName;
|
||||
string fComments;
|
||||
string fTransport;
|
||||
int fProtocolClass;
|
||||
|
||||
BNode *fNode;
|
||||
};
|
||||
|
||||
inline const string &PrinterData::getDriverName() const
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
virtual const char* GetCopyright() const = 0;
|
||||
|
||||
virtual PrinterCap* InstantiatePrinterCap(PrinterData* printerData) = 0;
|
||||
virtual PrinterData* InstantiatePrinterData(BNode* node);
|
||||
virtual GraphicsDriver* InstantiateGraphicsDriver(BMessage* settings, PrinterData* printerData, PrinterCap* printerCap) = 0;
|
||||
|
||||
void InitPrinterDataAndCap();
|
||||
|
131
src/add-ons/print/drivers/postscript/FilterIO.cpp
Normal file
131
src/add-ons/print/drivers/postscript/FilterIO.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2010, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
|
||||
*/
|
||||
|
||||
#include "FilterIO.h"
|
||||
|
||||
#include <String.h>
|
||||
#include <image.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
FilterIO::FilterIO(const BString& cmdline)
|
||||
: BDataIO()
|
||||
{
|
||||
BString cmd(cmdline);
|
||||
const char *argv[4];
|
||||
|
||||
argv[0] = strdup("/bin/sh");
|
||||
argv[1] = strdup("-c");
|
||||
argv[2] = strdup(cmd.String());
|
||||
argv[3] = NULL;
|
||||
|
||||
InitData(3,argv);
|
||||
|
||||
free((void*)argv[0]);
|
||||
free((void*)argv[1]);
|
||||
free((void*)argv[2]);
|
||||
}
|
||||
|
||||
|
||||
FilterIO::FilterIO(int argc, const char **argv, const char **envp)
|
||||
: BDataIO()
|
||||
{
|
||||
InitData(argc,argv,envp);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FilterIO::InitData(int argc, const char **argv, const char **envp)
|
||||
{
|
||||
fStdIn =
|
||||
fStdOut =
|
||||
fStdErr = -1;
|
||||
fInitErr = B_OK;
|
||||
|
||||
fThreadId = PipeCommand(argc, argv, fStdIn, fStdOut, fStdErr, envp);
|
||||
if (fThreadId < 0)
|
||||
fInitErr = fThreadId;
|
||||
|
||||
// lower the command priority since it is a background task.
|
||||
set_thread_priority(fThreadId, B_LOW_PRIORITY);
|
||||
resume_thread(fThreadId);
|
||||
|
||||
return fInitErr;
|
||||
}
|
||||
|
||||
|
||||
FilterIO::~FilterIO()
|
||||
{
|
||||
::close(fStdIn);
|
||||
::close(fStdOut);
|
||||
::close(fStdErr);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
FilterIO::Read(void *buffer, size_t size)
|
||||
{
|
||||
return ::read(fStdOut, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
FilterIO::Write(const void *buffer, size_t size)
|
||||
{
|
||||
return ::write(fStdIn, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
thread_id
|
||||
FilterIO::PipeCommand(int argc, const char **argv, int &in, int &out, int &err, const char **envp)
|
||||
{
|
||||
// This function written by Peter Folk <pfolk@uni.uiuc.edu>
|
||||
// and published in the BeDevTalk FAQ
|
||||
// http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209
|
||||
|
||||
if (!envp)
|
||||
envp = (const char**)environ;
|
||||
|
||||
// Save current FDs
|
||||
int old_in = dup(0);
|
||||
int old_out = dup(1);
|
||||
int old_err = dup(2);
|
||||
|
||||
int filedes[2];
|
||||
|
||||
/* Create new pipe FDs as stdin, stdout, stderr */
|
||||
pipe(filedes); dup2(filedes[0], 0); close(filedes[0]);
|
||||
in = filedes[1]; // Write to in, appears on cmd's stdin
|
||||
pipe(filedes); dup2(filedes[1], 1); close(filedes[1]);
|
||||
out = filedes[0]; // Read from out, taken from cmd's stdout
|
||||
pipe(filedes); dup2(filedes[1], 2); close(filedes[1]);
|
||||
err = filedes[0]; // Read from err, taken from cmd's stderr
|
||||
|
||||
// "load" command.
|
||||
thread_id ret = load_image(argc, argv, envp);
|
||||
if (ret < B_OK)
|
||||
goto cleanup;
|
||||
|
||||
// thread ret is now suspended.
|
||||
|
||||
setpgid(ret, ret);
|
||||
|
||||
cleanup:
|
||||
// Restore old FDs
|
||||
close(0); dup(old_in); close(old_in);
|
||||
close(1); dup(old_out); close(old_out);
|
||||
close(2); dup(old_err); close(old_err);
|
||||
|
||||
/* Theoretically I should do loads of error checking, but
|
||||
the calls aren't very likely to fail, and that would
|
||||
muddy up the example quite a bit. YMMV. */
|
||||
|
||||
return ret;
|
||||
}
|
40
src/add-ons/print/drivers/postscript/FilterIO.h
Normal file
40
src/add-ons/print/drivers/postscript/FilterIO.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
|
||||
*/
|
||||
|
||||
#ifndef FILTERIO_H
|
||||
#define FILTERIO_H
|
||||
|
||||
#include <DataIO.h>
|
||||
#include <OS.h>
|
||||
|
||||
class BString;
|
||||
|
||||
class FilterIO : public BDataIO
|
||||
{
|
||||
public:
|
||||
FilterIO(int argc, const char **argv, const char **envp = NULL);
|
||||
FilterIO(const BString& cmdline);
|
||||
~FilterIO();
|
||||
|
||||
status_t InitCheck() const
|
||||
{
|
||||
return fInitErr;
|
||||
}
|
||||
|
||||
ssize_t Read(void *buffer, size_t size);
|
||||
ssize_t Write(const void *buffer, size_t size);
|
||||
private:
|
||||
int fStdIn, fStdOut, fStdErr;
|
||||
thread_id fThreadId;
|
||||
status_t fInitErr;
|
||||
|
||||
status_t InitData(int argc, const char **argv, const char **envp = NULL);
|
||||
thread_id PipeCommand(int argc, const char **argv, int &in, int &out, int &err, const char **envp = NULL);
|
||||
};
|
||||
|
||||
#endif /* FILTERIO_H */
|
@ -10,6 +10,10 @@ Addon PS\ Compatible :
|
||||
PSEntry.cpp
|
||||
PS.cpp
|
||||
PSCap.cpp
|
||||
PSData.cpp
|
||||
SelectPPDDlg.cpp
|
||||
PPDParser.cpp
|
||||
FilterIO.cpp
|
||||
: be libprint.a $(TARGET_LIBSTDC++)
|
||||
;
|
||||
|
||||
|
93
src/add-ons/print/drivers/postscript/PPDParser.cpp
Normal file
93
src/add-ons/print/drivers/postscript/PPDParser.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2010, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
|
||||
*/
|
||||
|
||||
#include "PPDParser.h"
|
||||
|
||||
#include <Path.h>
|
||||
#include <File.h>
|
||||
|
||||
|
||||
PPDParser::PPDParser(BFile& file)
|
||||
{
|
||||
InitData(file);
|
||||
}
|
||||
|
||||
|
||||
PPDParser::PPDParser(const BDirectory& dir, const char *fname)
|
||||
{
|
||||
BFile file(&dir,fname, B_READ_ONLY);
|
||||
InitData(file);
|
||||
}
|
||||
|
||||
|
||||
PPDParser::PPDParser(const BPath& path)
|
||||
{
|
||||
BFile file(path.Path(), B_READ_ONLY);
|
||||
InitData(file);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPDParser::InitData(BFile& file)
|
||||
{
|
||||
// Check if file exists...
|
||||
if ((fInitErr=file.InitCheck()) != B_OK)
|
||||
return fInitErr;
|
||||
|
||||
// Read entire file into BString
|
||||
ssize_t len;
|
||||
char buffer[1025];
|
||||
while ((len=file.Read(buffer,sizeof(buffer)-1)) > 0) {
|
||||
buffer[len] = '\0';
|
||||
fContent << buffer;
|
||||
}
|
||||
|
||||
// Convert DOS/Windows newlines to UNIX ones
|
||||
fContent.ReplaceAll("\r\n", "\n");
|
||||
// Handle line continuation
|
||||
fContent.ReplaceAll("&&\n", "");
|
||||
// Make sure file ends with newline
|
||||
fContent << '\n';
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
PPDParser::GetParameter(const BString& param)
|
||||
{
|
||||
BString result, line;
|
||||
int32 pos = 0, next;
|
||||
BString pattern;
|
||||
|
||||
pattern << "*" << param << ":";
|
||||
|
||||
while ((next=fContent.FindFirst('\n', pos)) > 0) {
|
||||
// Grab line (without newline)
|
||||
fContent.CopyInto(line, pos, next-pos);
|
||||
// Found our parameter?
|
||||
if (line.Compare(pattern,pattern.Length()) == 0) {
|
||||
// Copy result
|
||||
line.CopyInto(result, pattern.Length(), line.Length() - pattern.Length()).Trim();
|
||||
// If result is quoted, remove quotes
|
||||
if (result[0] == '"') {
|
||||
result.Truncate(result.Length() -1);
|
||||
result.Remove(0,1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
pos = next +1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
PPDParser::~PPDParser()
|
||||
{
|
||||
}
|
31
src/add-ons/print/drivers/postscript/PPDParser.h
Normal file
31
src/add-ons/print/drivers/postscript/PPDParser.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef PPDPARSER_H
|
||||
#define PPDPARSER_H
|
||||
|
||||
#include <String.h>
|
||||
|
||||
class BPath;
|
||||
class BFile;
|
||||
class BDirectory;
|
||||
|
||||
class PPDParser
|
||||
{
|
||||
public:
|
||||
PPDParser(const BDirectory& dir, const char *fname);
|
||||
PPDParser(const BPath& path);
|
||||
PPDParser(BFile& file);
|
||||
~PPDParser();
|
||||
|
||||
status_t InitCheck() const
|
||||
{
|
||||
return fInitErr;
|
||||
}
|
||||
|
||||
BString GetParameter(const BString& param);
|
||||
private:
|
||||
status_t InitData(BFile& file);
|
||||
|
||||
BString fContent;
|
||||
status_t fInitErr;
|
||||
};
|
||||
|
||||
#endif /* PPDPARSER_H */
|
@ -2,13 +2,16 @@
|
||||
* PS.cpp
|
||||
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
|
||||
* Copyright 2003 Michael Pfeiffer.
|
||||
* Copyright 2010 Ithamar Adema.
|
||||
*/
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Bitmap.h>
|
||||
#include <File.h>
|
||||
#include <Path.h>
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "PS.h"
|
||||
#include "UIDriver.h"
|
||||
#include "JobData.h"
|
||||
@ -18,6 +21,9 @@
|
||||
#include "Halftone.h"
|
||||
#include "ValidRect.h"
|
||||
#include "DbgMsg.h"
|
||||
#include "PSData.h"
|
||||
#include "FilterIO.h"
|
||||
#include "PPDParser.h"
|
||||
|
||||
|
||||
#if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE))
|
||||
@ -26,16 +32,86 @@ using namespace std;
|
||||
#define std
|
||||
#endif
|
||||
|
||||
|
||||
PSDriver::PSDriver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap)
|
||||
: GraphicsDriver(msg, printer_data, printer_cap)
|
||||
{
|
||||
fPrintedPages = 0;
|
||||
fHalftone = NULL;
|
||||
fFilterIO = NULL;
|
||||
}
|
||||
|
||||
bool PSDriver::startDoc()
|
||||
|
||||
void
|
||||
PSDriver::StartFilterIfNeeded()
|
||||
{
|
||||
const PSData *data = dynamic_cast<const PSData*>(getPrinterData());
|
||||
PPDParser parser(BPath(data->fPPD.String()));
|
||||
if (parser.InitCheck() == B_OK) {
|
||||
BString param = parser.GetParameter("FoomaticRIPCommandLine");
|
||||
char str[3] = "%?";
|
||||
// for now, we don't have any extra substitutions to do...
|
||||
// (will be added once we support configuration options from the PPD)
|
||||
for (str[1] = 'A'; str[1] <= 'Z'; str[1]++)
|
||||
param.ReplaceAll(str, "");
|
||||
|
||||
if (param.Length())
|
||||
fFilterIO = new FilterIO(param);
|
||||
|
||||
if (!fFilterIO || fFilterIO->InitCheck() != B_OK) {
|
||||
delete fFilterIO;
|
||||
fFilterIO = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDriver::FlushFilterIfNeeded()
|
||||
{
|
||||
if (fFilterIO) {
|
||||
char buffer[1024];
|
||||
ssize_t len;
|
||||
|
||||
while ((len = fFilterIO->Read(buffer,sizeof(buffer))) > 0)
|
||||
writeSpoolData(buffer, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDriver::writePSString(const char *format, ...)
|
||||
{
|
||||
char str[256];
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vsprintf(str, format, ap);
|
||||
|
||||
if (fFilterIO)
|
||||
fFilterIO->Write(str, strlen(str));
|
||||
else
|
||||
writeSpoolData(str, strlen(str));
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDriver::writePSData(const void *data, size_t size)
|
||||
{
|
||||
if (fFilterIO)
|
||||
fFilterIO->Write(data, size);
|
||||
else
|
||||
writeSpoolData(data,size);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PSDriver::startDoc()
|
||||
{
|
||||
try {
|
||||
StartFilterIfNeeded();
|
||||
|
||||
jobStart();
|
||||
fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType());
|
||||
return true;
|
||||
@ -45,21 +121,28 @@ bool PSDriver::startDoc()
|
||||
}
|
||||
}
|
||||
|
||||
bool PSDriver::startPage(int page)
|
||||
|
||||
bool
|
||||
PSDriver::startPage(int page)
|
||||
{
|
||||
page ++;
|
||||
writeSpoolString("%%%%Page: %d %d\n", page, page);
|
||||
writeSpoolString("gsave\n");
|
||||
writePSString("%%%%Page: %d %d\n", page, page);
|
||||
writePSString("gsave\n");
|
||||
setupCTM();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PSDriver::endPage(int)
|
||||
|
||||
bool
|
||||
PSDriver::endPage(int)
|
||||
{
|
||||
try {
|
||||
fPrintedPages ++;
|
||||
writeSpoolString("grestore\n");
|
||||
writeSpoolString("showpage\n");
|
||||
writePSString("grestore\n");
|
||||
writePSString("showpage\n");
|
||||
|
||||
FlushFilterIfNeeded();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (TransportException &err) {
|
||||
@ -67,26 +150,31 @@ bool PSDriver::endPage(int)
|
||||
}
|
||||
}
|
||||
|
||||
void PSDriver::setupCTM() {
|
||||
|
||||
void
|
||||
PSDriver::setupCTM()
|
||||
{
|
||||
const float leftMargin = getJobData()->getPrintableRect().left;
|
||||
const float topMargin = getJobData()->getPrintableRect().top;
|
||||
if (getJobData()->getOrientation() == JobData::kPortrait) {
|
||||
// move origin from bottom left to top left
|
||||
// and set margin
|
||||
writeSpoolString("%f %f translate\n", leftMargin, getJobData()->getPaperRect().Height()-topMargin);
|
||||
writePSString("%f %f translate\n", leftMargin, getJobData()->getPaperRect().Height()-topMargin);
|
||||
} else {
|
||||
// landscape:
|
||||
// move origin from bottom left to margin top and left
|
||||
// and rotate page contents
|
||||
writeSpoolString("%f %f translate\n", topMargin, leftMargin);
|
||||
writeSpoolString("90 rotate\n");
|
||||
writePSString("%f %f translate\n", topMargin, leftMargin);
|
||||
writePSString("90 rotate\n");
|
||||
}
|
||||
// y values increase from top to bottom
|
||||
// units of measure is dpi
|
||||
writeSpoolString("72 %d div 72 -%d div scale\n", getJobData()->getXres(), getJobData()->getYres());
|
||||
writePSString("72 %d div 72 -%d div scale\n", getJobData()->getXres(), getJobData()->getYres());
|
||||
}
|
||||
|
||||
bool PSDriver::endDoc(bool)
|
||||
|
||||
bool
|
||||
PSDriver::endDoc(bool)
|
||||
{
|
||||
try {
|
||||
if (fHalftone) {
|
||||
@ -100,13 +188,17 @@ bool PSDriver::endDoc(bool)
|
||||
}
|
||||
}
|
||||
|
||||
inline uchar hex_digit(uchar value)
|
||||
|
||||
inline uchar
|
||||
hex_digit(uchar value)
|
||||
{
|
||||
if (value <= 9) return '0'+value;
|
||||
else return 'a'+(value-10);
|
||||
}
|
||||
|
||||
bool PSDriver::nextBand(BBitmap *bitmap, BPoint *offset)
|
||||
|
||||
bool
|
||||
PSDriver::nextBand(BBitmap *bitmap, BPoint *offset)
|
||||
{
|
||||
DBGMSG(("> nextBand\n"));
|
||||
|
||||
@ -243,52 +335,60 @@ bool PSDriver::nextBand(BBitmap *bitmap, BPoint *offset)
|
||||
}
|
||||
}
|
||||
|
||||
void PSDriver::jobStart()
|
||||
|
||||
void
|
||||
PSDriver::jobStart()
|
||||
{
|
||||
// PostScript header
|
||||
writeSpoolString("%%!PS-Adobe-3.0\n");
|
||||
writeSpoolString("%%%%LanguageLevel: 1\n");
|
||||
writeSpoolString("%%%%Title: %s\n", getSpoolMetaData()->getDescription().c_str());
|
||||
writeSpoolString("%%%%Creator: %s\n", getSpoolMetaData()->getMimeType().c_str());
|
||||
writeSpoolString("%%%%CreationDate: %s", getSpoolMetaData()->getCreationTime().c_str());
|
||||
writeSpoolString("%%%%DocumentMedia: Plain %d %d white 0 ( )\n", getJobData()->getPaperRect().IntegerWidth(), getJobData()->getPaperRect().IntegerHeight());
|
||||
writeSpoolString("%%%%Pages: (atend)\n");
|
||||
writeSpoolString("%%%%EndComments\n");
|
||||
writePSString("%%!PS-Adobe-3.0\n");
|
||||
writePSString("%%%%LanguageLevel: 1\n");
|
||||
writePSString("%%%%Title: %s\n", getSpoolMetaData()->getDescription().c_str());
|
||||
writePSString("%%%%Creator: %s\n", getSpoolMetaData()->getMimeType().c_str());
|
||||
writePSString("%%%%CreationDate: %s", getSpoolMetaData()->getCreationTime().c_str());
|
||||
writePSString("%%%%DocumentMedia: Plain %d %d white 0 ( )\n", getJobData()->getPaperRect().IntegerWidth(), getJobData()->getPaperRect().IntegerHeight());
|
||||
writePSString("%%%%Pages: (atend)\n");
|
||||
writePSString("%%%%EndComments\n");
|
||||
|
||||
writeSpoolString("%%%%BeginDefaults\n");
|
||||
writeSpoolString("%%%%PageMedia: Plain\n");
|
||||
writeSpoolString("%%%%EndDefaults\n");
|
||||
writePSString("%%%%BeginDefaults\n");
|
||||
writePSString("%%%%PageMedia: Plain\n");
|
||||
writePSString("%%%%EndDefaults\n");
|
||||
}
|
||||
|
||||
void PSDriver::startRasterGraphics(int x, int y, int width, int height, int widthByte)
|
||||
|
||||
void
|
||||
PSDriver::startRasterGraphics(int x, int y, int width, int height, int widthByte)
|
||||
{
|
||||
bool color = getJobData()->getColor() == JobData::kColor;
|
||||
fCompressionMethod = -1;
|
||||
writeSpoolString("gsave\n");
|
||||
writeSpoolString("/s %d string def\n", widthByte);
|
||||
writeSpoolString("%d %d translate\n", x, y);
|
||||
writeSpoolString("%d %d scale\n", width, height);
|
||||
writePSString("gsave\n");
|
||||
writePSString("/s %d string def\n", widthByte);
|
||||
writePSString("%d %d translate\n", x, y);
|
||||
writePSString("%d %d scale\n", width, height);
|
||||
if (color) {
|
||||
writeSpoolString("%d %d 8\n", width, height); // 8 bpp
|
||||
writePSString("%d %d 8\n", width, height); // 8 bpp
|
||||
} else {
|
||||
writeSpoolString("%d %d 1\n", width, height); // 1 bpp
|
||||
writePSString("%d %d 1\n", width, height); // 1 bpp
|
||||
}
|
||||
writeSpoolString("[%d 0 0 %d 0 0]\n", width, height);
|
||||
writeSpoolString("{ currentfile s readhexstring pop }\n");
|
||||
writePSString("[%d 0 0 %d 0 0]\n", width, height);
|
||||
writePSString("{ currentfile s readhexstring pop }\n");
|
||||
if (color) {
|
||||
writeSpoolString("false 3\n"); // single data source, 3 color components
|
||||
writeSpoolString("colorimage\n");
|
||||
writePSString("false 3\n"); // single data source, 3 color components
|
||||
writePSString("colorimage\n");
|
||||
} else {
|
||||
writeSpoolString("image\n\n");
|
||||
writePSString("image\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
void PSDriver::endRasterGraphics()
|
||||
|
||||
void
|
||||
PSDriver::endRasterGraphics()
|
||||
{
|
||||
writeSpoolString("grestore\n");
|
||||
writePSString("grestore\n");
|
||||
}
|
||||
|
||||
void PSDriver::rasterGraphics(
|
||||
|
||||
void
|
||||
PSDriver::rasterGraphics(
|
||||
int compression_method,
|
||||
const uchar *buffer,
|
||||
int size)
|
||||
@ -296,12 +396,16 @@ void PSDriver::rasterGraphics(
|
||||
if (fCompressionMethod != compression_method) {
|
||||
fCompressionMethod = compression_method;
|
||||
}
|
||||
writeSpoolData(buffer, size);
|
||||
writeSpoolString("\n");
|
||||
writePSData(buffer, size);
|
||||
writePSString("\n");
|
||||
}
|
||||
|
||||
void PSDriver::jobEnd()
|
||||
|
||||
void
|
||||
PSDriver::jobEnd()
|
||||
{
|
||||
writeSpoolString("%%%%Pages: %d\n", fPrintedPages);
|
||||
writeSpoolString("%%%%EOF\n");
|
||||
writePSString("%%%%Pages: %d\n", fPrintedPages);
|
||||
writePSString("%%%%EOF\n");
|
||||
|
||||
FlushFilterIfNeeded();
|
||||
}
|
||||
|
@ -8,8 +8,11 @@
|
||||
|
||||
#include "GraphicsDriver.h"
|
||||
|
||||
|
||||
class FilterIO;
|
||||
class Halftone;
|
||||
|
||||
|
||||
class PSDriver : public GraphicsDriver {
|
||||
public:
|
||||
PSDriver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap);
|
||||
@ -32,9 +35,15 @@ private:
|
||||
int size);
|
||||
void jobEnd();
|
||||
|
||||
void StartFilterIfNeeded();
|
||||
void FlushFilterIfNeeded();
|
||||
void writePSString(const char *format, ...);
|
||||
void writePSData(const void *data, size_t size);
|
||||
|
||||
int fPrintedPages;
|
||||
int fCompressionMethod;
|
||||
Halftone *fHalftone;
|
||||
FilterIO *fFilterIO;
|
||||
};
|
||||
|
||||
#endif /* __PS_H */
|
||||
|
27
src/add-ons/print/drivers/postscript/PSData.cpp
Normal file
27
src/add-ons/print/drivers/postscript/PSData.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
|
||||
*/
|
||||
|
||||
#include "PSData.h"
|
||||
|
||||
#include <Node.h>
|
||||
|
||||
#define PD_PPD_PATH "ps:ppd_path"
|
||||
|
||||
void
|
||||
PSData::load()
|
||||
{
|
||||
PrinterData::load();
|
||||
fNode->ReadAttrString(PD_PPD_PATH, &fPPD);
|
||||
}
|
||||
|
||||
void
|
||||
PSData::save()
|
||||
{
|
||||
PrinterData::save();
|
||||
fNode->WriteAttrString(PD_PPD_PATH, &fPPD);
|
||||
}
|
31
src/add-ons/print/drivers/postscript/PSData.h
Normal file
31
src/add-ons/print/drivers/postscript/PSData.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
|
||||
*/
|
||||
|
||||
#ifndef PSDATA_H
|
||||
#define PSDATA_H
|
||||
|
||||
#include "PrinterData.h"
|
||||
#include <String.h>
|
||||
|
||||
|
||||
class BNode;
|
||||
|
||||
|
||||
class PSData : public PrinterData {
|
||||
public:
|
||||
PSData(BNode *node) : PrinterData(node) {}
|
||||
|
||||
// PrinterData overrides
|
||||
virtual void load();
|
||||
virtual void save();
|
||||
|
||||
BString fPPD;
|
||||
};
|
||||
|
||||
|
||||
#endif /* PSDATA_H */
|
@ -2,49 +2,75 @@
|
||||
* PSEntry.cpp
|
||||
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
|
||||
* Copyright 2003 Michael Pfeiffer.
|
||||
* Copyright 2010 Ithamar Adema.
|
||||
*/
|
||||
|
||||
#include "PS.h"
|
||||
#include "PSCap.h"
|
||||
#include "PSData.h"
|
||||
#include "PrinterDriver.h"
|
||||
#include "SelectPPDDlg.h"
|
||||
|
||||
class PSPrinterDriver : public PrinterDriver
|
||||
{
|
||||
#include <Entry.h>
|
||||
#include <Path.h>
|
||||
|
||||
class PSPrinterDriver : public PrinterDriver {
|
||||
public:
|
||||
PSPrinterDriver(BNode* printerFolder) : PrinterDriver(printerFolder) {}
|
||||
|
||||
const char* GetSignature() const
|
||||
PSPrinterDriver(BNode *printerFolder) : PrinterDriver(printerFolder) {}
|
||||
|
||||
const char *GetSignature() const
|
||||
{
|
||||
return "application/x-vnd.PS-compatible";
|
||||
}
|
||||
|
||||
const char* GetDriverName() const
|
||||
{
|
||||
return "PS compatible";
|
||||
}
|
||||
|
||||
const char* GetVersion() const
|
||||
{
|
||||
return "0.1";
|
||||
}
|
||||
|
||||
const char* GetCopyright() const
|
||||
{
|
||||
return "PS driver Copyright © 2003,04 Michael Pfeiffer.\n";
|
||||
return "application/x-vnd.PS-compatible";
|
||||
}
|
||||
|
||||
PrinterCap* InstantiatePrinterCap(PrinterData* printerData)
|
||||
const char *GetDriverName() const
|
||||
{
|
||||
return "PS compatible";
|
||||
}
|
||||
|
||||
const char *GetVersion() const
|
||||
{
|
||||
return "0.1";
|
||||
}
|
||||
|
||||
const char *GetCopyright() const
|
||||
{
|
||||
return "PS driver Copyright © 2003,04 Michael Pfeiffer.\n";
|
||||
}
|
||||
|
||||
char *AddPrinter(char *printerName)
|
||||
{
|
||||
BPath path;
|
||||
if (find_directory(B_SYSTEM_DATA_DIRECTORY, &path) == B_OK
|
||||
&& path.Append("ppd") == B_OK
|
||||
&& BEntry(path.Path()).Exists()) {
|
||||
SelectPPDDlg *dialog = new SelectPPDDlg(dynamic_cast<PSData*>(GetPrinterData()));
|
||||
if (dialog->Go() != B_OK)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return printerName;
|
||||
}
|
||||
|
||||
PrinterData *InstantiatePrinterData(BNode *node)
|
||||
{
|
||||
return new PSData(node);
|
||||
}
|
||||
|
||||
PrinterCap *InstantiatePrinterCap(PrinterData *printerData)
|
||||
{
|
||||
return new PSCap(printerData);
|
||||
}
|
||||
|
||||
GraphicsDriver* InstantiateGraphicsDriver(BMessage* settings, PrinterData* printerData, PrinterCap* printerCap)
|
||||
|
||||
GraphicsDriver *InstantiateGraphicsDriver(BMessage *settings, PrinterData *printerData, PrinterCap *printerCap)
|
||||
{
|
||||
return new PSDriver(settings, printerData, printerCap);
|
||||
}
|
||||
};
|
||||
|
||||
PrinterDriver* instantiate_printer_driver(BNode* printerFolder)
|
||||
|
||||
PrinterDriver *
|
||||
instantiate_printer_driver(BNode *printerFolder)
|
||||
{
|
||||
return new PSPrinterDriver(printerFolder);
|
||||
}
|
||||
|
190
src/add-ons/print/drivers/postscript/SelectPPDDlg.cpp
Normal file
190
src/add-ons/print/drivers/postscript/SelectPPDDlg.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2010, Haiku. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
|
||||
*/
|
||||
|
||||
#include "SelectPPDDlg.h"
|
||||
#include "PPDParser.h"
|
||||
|
||||
#include <GroupLayout.h>
|
||||
#include <GroupLayoutBuilder.h>
|
||||
|
||||
#include <Button.h>
|
||||
#include <Message.h>
|
||||
#include <ListView.h>
|
||||
#include <ScrollView.h>
|
||||
#include <ScrollBar.h>
|
||||
#include <StringItem.h>
|
||||
#include <Directory.h>
|
||||
#include <String.h>
|
||||
#include <Entry.h>
|
||||
#include <Path.h>
|
||||
|
||||
|
||||
enum {
|
||||
kMsgCancel = 'stop',
|
||||
kMsgOK = 'okok',
|
||||
|
||||
kMsgManuSelected = 'msel',
|
||||
kMsgPrinterSelected = 'psel',
|
||||
};
|
||||
|
||||
|
||||
class PPDStringItem : public BStringItem {
|
||||
public:
|
||||
PPDStringItem(const BString& text, const BString& path)
|
||||
: BStringItem(text.String()),
|
||||
fPPDPath(path) {}
|
||||
|
||||
BString fPPDPath;
|
||||
};
|
||||
|
||||
|
||||
SelectPPDDlg::SelectPPDDlg(PSData *data)
|
||||
: DialogWindow(BRect(10, 10, 400, 400),
|
||||
"Select PPD", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
|
||||
B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS),
|
||||
fPSData(data)
|
||||
{
|
||||
SetResult(B_ERROR);
|
||||
|
||||
BButton *ok, *cancel;
|
||||
|
||||
ok = new BButton("btn:ok", "OK", new BMessage(kMsgOK));
|
||||
ok->MakeDefault(true);
|
||||
ok->SetEnabled(false);
|
||||
fOKButton = ok;
|
||||
|
||||
cancel = new BButton("btn:cancel", "Cancel", new BMessage(kMsgCancel));
|
||||
|
||||
BScrollView *manuScroller, *printerScroller;
|
||||
fManufacturersListView = new BListView("olv:manufacturers");
|
||||
manuScroller=new BScrollView("scr:manufacturers", fManufacturersListView, 0, false, true);
|
||||
fPrintersListView = new BListView("olv:printers");
|
||||
printerScroller=new BScrollView("scr:printers", fPrintersListView, 0, false, true);
|
||||
|
||||
fPrintersListView->SetSelectionMessage(new BMessage(kMsgPrinterSelected));
|
||||
fManufacturersListView->SetSelectionMessage(new BMessage(kMsgManuSelected));
|
||||
PopulateManufacturers(B_SYSTEM_DATA_DIRECTORY);
|
||||
|
||||
// Build the layout
|
||||
SetLayout(new BGroupLayout(B_VERTICAL));
|
||||
|
||||
AddChild(BGroupLayoutBuilder(B_VERTICAL, 10)
|
||||
.AddGroup(B_HORIZONTAL, 5)
|
||||
.Add(manuScroller)
|
||||
.Add(printerScroller)
|
||||
.End()
|
||||
.AddGroup(B_HORIZONTAL, 5)
|
||||
.AddGlue()
|
||||
.Add(cancel)
|
||||
.Add(ok)
|
||||
.End()
|
||||
.SetInsets(10, 10, 10, 10)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SelectPPDDlg::PopulateManufacturers(directory_which data_dir)
|
||||
{
|
||||
char name[1024];
|
||||
BDirectory dir;
|
||||
BEntry entry;
|
||||
BPath path;
|
||||
|
||||
if (find_directory(data_dir, &path) == B_OK
|
||||
&& path.Append("ppd") == B_OK
|
||||
&& dir.SetTo(path.Path()) == B_OK) {
|
||||
// Got the directory, now scan it
|
||||
while(dir.GetNextEntry(&entry) == B_OK)
|
||||
if (entry.IsDirectory()
|
||||
&& entry.GetName(name) == B_OK)
|
||||
fManufacturersListView->AddItem(new BStringItem(name));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SelectPPDDlg::PopulatePrinters(directory_which data_dir)
|
||||
{
|
||||
int32 idx = fManufacturersListView->CurrentSelection();
|
||||
char name[1024];
|
||||
BDirectory dir;
|
||||
BString manu;
|
||||
BEntry entry;
|
||||
BPath path;
|
||||
|
||||
// Bail out if no manufacturer is selected
|
||||
if (idx < 0)
|
||||
return;
|
||||
|
||||
manu = ((BStringItem*)fManufacturersListView->ItemAt(idx))->Text();
|
||||
|
||||
if (find_directory(data_dir, &path) == B_OK
|
||||
&& path.Append("ppd") == B_OK
|
||||
&& path.Append(manu) == B_OK
|
||||
&& dir.SetTo(path.Path()) == B_OK) {
|
||||
// Found manufacturer PPD directory, now fill our printer list
|
||||
while(dir.GetNextEntry(&entry) == B_OK)
|
||||
if (entry.GetName(name) == B_OK) {
|
||||
PPDParser parser(dir,name);
|
||||
if (parser.InitCheck() == B_OK) {
|
||||
BString modelName = parser.GetParameter("ModelName");
|
||||
BPath ppdPath = path;
|
||||
ppdPath.Append(name);
|
||||
fPrintersListView->AddItem(new PPDStringItem(modelName, ppdPath.Path()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SelectPPDDlg::PrinterSelected()
|
||||
{
|
||||
int32 idx = fPrintersListView->CurrentSelection();
|
||||
fOKButton->SetEnabled(idx >= 0);
|
||||
}
|
||||
|
||||
void
|
||||
SelectPPDDlg::Save()
|
||||
{
|
||||
BString ppdPath;
|
||||
int32 idx;
|
||||
|
||||
idx = fPrintersListView->CurrentSelection();
|
||||
if (idx >= 0)
|
||||
ppdPath = dynamic_cast<PPDStringItem*>(fPrintersListView->ItemAt(idx))->fPPDPath;
|
||||
|
||||
fPSData->fPPD = ppdPath;
|
||||
fPSData->save();
|
||||
}
|
||||
|
||||
void
|
||||
SelectPPDDlg::MessageReceived(BMessage *msg)
|
||||
{
|
||||
switch (msg->what) {
|
||||
case kMsgManuSelected:
|
||||
fPrintersListView->MakeEmpty();
|
||||
PopulatePrinters(B_SYSTEM_DATA_DIRECTORY);
|
||||
break;
|
||||
case kMsgPrinterSelected:
|
||||
PrinterSelected();
|
||||
break;
|
||||
case kMsgOK:
|
||||
Save();
|
||||
SetResult(B_NO_ERROR);
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
break;
|
||||
|
||||
case kMsgCancel:
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
break;
|
||||
|
||||
default:
|
||||
DialogWindow::MessageReceived(msg);
|
||||
break;
|
||||
}
|
||||
}
|
30
src/add-ons/print/drivers/postscript/SelectPPDDlg.h
Normal file
30
src/add-ons/print/drivers/postscript/SelectPPDDlg.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef SELECTPPDDLG_H
|
||||
#define SELECTPPDDLG_H
|
||||
|
||||
#include "DialogWindow.h"
|
||||
#include "PSData.h"
|
||||
|
||||
#include <storage/FindDirectory.h>
|
||||
|
||||
class BListView;
|
||||
class BButton;
|
||||
class PSData;
|
||||
|
||||
class SelectPPDDlg : public DialogWindow {
|
||||
public:
|
||||
SelectPPDDlg(PSData *data);
|
||||
void MessageReceived(BMessage *msg);
|
||||
private:
|
||||
void PopulateManufacturers(directory_which data_dir);
|
||||
void PopulatePrinters(directory_which data_dir);
|
||||
void PrinterSelected();
|
||||
void Save();
|
||||
|
||||
BListView *fManufacturersListView;
|
||||
BListView *fPrintersListView;
|
||||
BButton *fOKButton;
|
||||
|
||||
PSData *fPSData;
|
||||
};
|
||||
|
||||
#endif /* SELECTPPDDLG_H */
|
@ -17,10 +17,9 @@ const char *PD_TRANSPORT = "transport";
|
||||
const char *PD_PROTOCOL_CLASS = "libprint:protocolClass";
|
||||
|
||||
PrinterData::PrinterData(BNode *node)
|
||||
: fProtocolClass(0)
|
||||
, fNode(node)
|
||||
: fNode(node),
|
||||
fProtocolClass(0)
|
||||
{
|
||||
load();
|
||||
}
|
||||
|
||||
PrinterData::~PrinterData()
|
||||
|
@ -49,9 +49,20 @@ PrinterDriver::~PrinterDriver()
|
||||
fPrinterData = NULL;
|
||||
}
|
||||
|
||||
|
||||
PrinterData*
|
||||
PrinterDriver::InstantiatePrinterData(BNode* node)
|
||||
{
|
||||
return new PrinterData(node);
|
||||
}
|
||||
|
||||
void
|
||||
PrinterDriver::InitPrinterDataAndCap() {
|
||||
fPrinterData = new PrinterData(fSpoolFolder);
|
||||
fPrinterData = InstantiatePrinterData(fSpoolFolder);
|
||||
fPrinterData->load();
|
||||
// NOTE: moved the load above from the constructor of PrinterData as
|
||||
// we're inheriting from PrinterData and want our overridden versions
|
||||
// of load to be called
|
||||
fPrinterCap = InstantiatePrinterCap(fPrinterData);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user