19295cd64SMichael Pfeiffer/*
29295cd64SMichael Pfeiffer* Copyright 2010, Haiku. All rights reserved.
39295cd64SMichael Pfeiffer* Distributed under the terms of the MIT License.
49295cd64SMichael Pfeiffer*
59295cd64SMichael Pfeiffer* Authors:
69295cd64SMichael Pfeiffer*		Michael Pfeiffer
79295cd64SMichael Pfeiffer*/
89295cd64SMichael Pfeiffer#include "GPJob.h"
99295cd64SMichael Pfeiffer
109295cd64SMichael Pfeiffer#include <Debug.h>
119295cd64SMichael Pfeiffer
129295cd64SMichael Pfeiffer
13d6d2c9b1SMichael Pfeiffer// 72 DPI
14d6d2c9b1SMichael Pfeifferstatic const int32 kGutenprintUnit = 72;
15d6d2c9b1SMichael Pfeiffer
16d6d2c9b1SMichael Pfeifferclass CoordinateSystem
17d6d2c9b1SMichael Pfeiffer{
18d6d2c9b1SMichael Pfeifferpublic:
19d6d2c9b1SMichael Pfeiffer	CoordinateSystem()
20d6d2c9b1SMichael Pfeiffer	:
21d6d2c9b1SMichael Pfeiffer	fXDPI(0),
22d6d2c9b1SMichael Pfeiffer	fYDPI(0)
23d6d2c9b1SMichael Pfeiffer	{
24d6d2c9b1SMichael Pfeiffer	}
25d6d2c9b1SMichael Pfeiffer
26d6d2c9b1SMichael Pfeiffer
27d6d2c9b1SMichael Pfeiffer	void SetDPI(int32 x, int32 y) {
28d6d2c9b1SMichael Pfeiffer		fXDPI = x;
29d6d2c9b1SMichael Pfeiffer		fYDPI = y;
30d6d2c9b1SMichael Pfeiffer	}
31d6d2c9b1SMichael Pfeiffer
32d6d2c9b1SMichael Pfeiffer
3389f1fd65SJérôme Duval	void ToGutenprint(int32 fromX, int32 fromY, double& toX, double& toY) {
34d6d2c9b1SMichael Pfeiffer		toX = fromX * kGutenprintUnit / fXDPI;
35d6d2c9b1SMichael Pfeiffer		toY = fromY * kGutenprintUnit / fYDPI;
36d6d2c9b1SMichael Pfeiffer	}
37d6d2c9b1SMichael Pfeiffer
38d6d2c9b1SMichael Pfeiffer
3989f1fd65SJérôme Duval	void ToGutenprintCeiling(int32 fromX, int32 fromY, double& toX,
4089f1fd65SJérôme Duval		double& toY) {
41d6d2c9b1SMichael Pfeiffer		toX = (fromX * kGutenprintUnit + fXDPI - 1) / fXDPI;
42d6d2c9b1SMichael Pfeiffer		toY = (fromY * kGutenprintUnit + fYDPI - 1) / fYDPI;
43d6d2c9b1SMichael Pfeiffer	}
44d6d2c9b1SMichael Pfeiffer
45d6d2c9b1SMichael Pfeiffer
4689f1fd65SJérôme Duval	void FromGutenprint(double fromX, double fromY, int32& toX, int32& toY) {
4789f1fd65SJérôme Duval		toX = (int32)(fromX * fXDPI / kGutenprintUnit);
4889f1fd65SJérôme Duval		toY = (int32)(fromY * fYDPI / kGutenprintUnit);
49d6d2c9b1SMichael Pfeiffer	}
50d6d2c9b1SMichael Pfeiffer
5189f1fd65SJérôme Duval	void FromGutenprintCeiling(double fromX, double fromY, int32& toX,
5289f1fd65SJérôme Duval		int32& toY) {
5389f1fd65SJérôme Duval		toX = (int32)((fromX * fXDPI + kGutenprintUnit - 1) / kGutenprintUnit);
5489f1fd65SJérôme Duval		toY = (int32)((fromY * fYDPI + kGutenprintUnit - 1) / kGutenprintUnit);
55d6d2c9b1SMichael Pfeiffer	}
56d6d2c9b1SMichael Pfeiffer
5789f1fd65SJérôme Duval	void SizeFromGutenprint(double fromWidth, double fromHeight,
58d6d2c9b1SMichael Pfeiffer		int32& toWidth, int32& toHeight) {
5989f1fd65SJérôme Duval		toWidth = (int32)(fromWidth * fXDPI / kGutenprintUnit);
6089f1fd65SJérôme Duval		toHeight = (int32)(fromHeight * fYDPI / kGutenprintUnit);
61d6d2c9b1SMichael Pfeiffer	}
62d6d2c9b1SMichael Pfeiffer
63d6d2c9b1SMichael Pfeiffer	void RoundUpToWholeInches(int32& width, int32& height) {
64d6d2c9b1SMichael Pfeiffer		width = ((width + kGutenprintUnit - 1) / kGutenprintUnit)
65d6d2c9b1SMichael Pfeiffer			* kGutenprintUnit;
66d6d2c9b1SMichael Pfeiffer		height = ((height + kGutenprintUnit - 1) / kGutenprintUnit)
67d6d2c9b1SMichael Pfeiffer			* kGutenprintUnit;
68d6d2c9b1SMichael Pfeiffer	}
69d6d2c9b1SMichael Pfeiffer
70d6d2c9b1SMichael Pfeifferprivate:
7189f1fd65SJérôme Duval	double fXDPI;
7289f1fd65SJérôme Duval	double fYDPI;
73d6d2c9b1SMichael Pfeiffer};
74d6d2c9b1SMichael Pfeiffer
75d6d2c9b1SMichael Pfeiffer
769295cd64SMichael PfeifferGPJob::GPJob()
779295cd64SMichael Pfeiffer	:
789295cd64SMichael Pfeiffer	fApplicationName(),
799295cd64SMichael Pfeiffer	fOutputStream(NULL),
809295cd64SMichael Pfeiffer	fConfiguration(NULL),
81fad05958SMichael Pfeiffer	fHasPages(false),
829295cd64SMichael Pfeiffer	fVariables(NULL),
8305a2fec5SMichael Pfeiffer	fPrinter(NULL),
849295cd64SMichael Pfeiffer	fBands(NULL),
859295cd64SMichael Pfeiffer	fCachedBand(NULL),
86c0aa3379SMichael Pfeiffer	fStatus(B_OK)
879295cd64SMichael Pfeiffer{
889295cd64SMichael Pfeiffer	fImage.init = ImageInit;
899295cd64SMichael Pfeiffer	fImage.reset = ImageReset;
909295cd64SMichael Pfeiffer	fImage.width = ImageWidth;
919295cd64SMichael Pfeiffer	fImage.height = ImageHeight;
929295cd64SMichael Pfeiffer	fImage.get_row = ImageGetRow;
939295cd64SMichael Pfeiffer	fImage.get_appname = ImageGetAppname;
949295cd64SMichael Pfeiffer	fImage.conclude = ImageConclude;
959295cd64SMichael Pfeiffer	fImage.rep = this;
969295cd64SMichael Pfeiffer}
979295cd64SMichael Pfeiffer
989295cd64SMichael Pfeiffer
999295cd64SMichael PfeifferGPJob::~GPJob()
1009295cd64SMichael Pfeiffer{
1019295cd64SMichael Pfeiffer}
1029295cd64SMichael Pfeiffer
1039295cd64SMichael Pfeiffer
1049295cd64SMichael Pfeiffervoid
1059295cd64SMichael PfeifferGPJob::SetApplicationName(const BString& applicationName)
1069295cd64SMichael Pfeiffer{
1079295cd64SMichael Pfeiffer	fApplicationName = applicationName;
1089295cd64SMichael Pfeiffer}
1099295cd64SMichael Pfeiffer
1109295cd64SMichael Pfeiffer
1119295cd64SMichael Pfeiffervoid
1129295cd64SMichael PfeifferGPJob::SetConfiguration(GPJobConfiguration* configuration)
1139295cd64SMichael Pfeiffer{
1149295cd64SMichael Pfeiffer	fConfiguration = configuration;
1159295cd64SMichael Pfeiffer}
1169295cd64SMichael Pfeiffer
1179295cd64SMichael Pfeiffer
1189295cd64SMichael Pfeiffervoid
1199295cd64SMichael PfeifferGPJob::SetOutputStream(OutputStream* outputStream)
1209295cd64SMichael Pfeiffer{
1219295cd64SMichael Pfeiffer	fOutputStream = outputStream;
1229295cd64SMichael Pfeiffer}
1239295cd64SMichael Pfeiffer
1249295cd64SMichael Pfeiffer
1259295cd64SMichael Pfeifferstatus_t
1269295cd64SMichael PfeifferGPJob::Begin()
1279295cd64SMichael Pfeiffer{
128c0aa3379SMichael Pfeiffer	fStatus = B_OK;
1299295cd64SMichael Pfeiffer
1309295cd64SMichael Pfeiffer	stp_init();
1319295cd64SMichael Pfeiffer
1329295cd64SMichael Pfeiffer	fPrinter = stp_get_printer_by_driver(fConfiguration->fDriver);
1339295cd64SMichael Pfeiffer	if (fPrinter == NULL) {
1349295cd64SMichael Pfeiffer		fprintf(stderr, "GPJob Begin: driver %s not found!\n",
1359295cd64SMichael Pfeiffer			fConfiguration->fDriver.String());
1369295cd64SMichael Pfeiffer		return B_ERROR;
1379295cd64SMichael Pfeiffer	}
1389295cd64SMichael Pfeiffer
1399295cd64SMichael Pfeiffer	fVariables = stp_vars_create();
1409295cd64SMichael Pfeiffer	if (fVariables == NULL) {
1419295cd64SMichael Pfeiffer		fprintf(stderr, "GPJob Begin: out of memory\n");
1429295cd64SMichael Pfeiffer		return B_NO_MEMORY;
1439295cd64SMichael Pfeiffer	}
1449295cd64SMichael Pfeiffer	stp_set_printer_defaults(fVariables, fPrinter);
1459295cd64SMichael Pfeiffer
1469295cd64SMichael Pfeiffer	stp_set_outfunc(fVariables, OutputFunction);
1479295cd64SMichael Pfeiffer	stp_set_errfunc(fVariables, ErrorFunction);
1489295cd64SMichael Pfeiffer	stp_set_outdata(fVariables, this);
1499295cd64SMichael Pfeiffer	stp_set_errdata(fVariables, this);
1509295cd64SMichael Pfeiffer
1519295cd64SMichael Pfeiffer	stp_set_string_parameter(fVariables, "PageSize",
1529295cd64SMichael Pfeiffer		fConfiguration->fPageSize);
1539295cd64SMichael Pfeiffer
1549295cd64SMichael Pfeiffer	if (fConfiguration->fResolution != "")
1559295cd64SMichael Pfeiffer		stp_set_string_parameter(fVariables, "Resolution",
1569295cd64SMichael Pfeiffer			fConfiguration->fResolution);
1579295cd64SMichael Pfeiffer
1589295cd64SMichael Pfeiffer	stp_set_string_parameter(fVariables, "InputSlot",
1599295cd64SMichael Pfeiffer		fConfiguration->fInputSlot);
1609295cd64SMichael Pfeiffer
1619295cd64SMichael Pfeiffer	stp_set_string_parameter(fVariables, "PrintingMode",
1629295cd64SMichael Pfeiffer		fConfiguration->fPrintingMode);
1639295cd64SMichael Pfeiffer
164f14cab2dSMichael Pfeiffer	{
165f14cab2dSMichael Pfeiffer		map<string, string>::iterator it = fConfiguration->fStringSettings.
166f14cab2dSMichael Pfeiffer			begin();
167f14cab2dSMichael Pfeiffer		for (; it != fConfiguration->fStringSettings.end(); it ++) {
168f14cab2dSMichael Pfeiffer			stp_set_string_parameter(fVariables, it->first.c_str(),
169f14cab2dSMichael Pfeiffer				it->second.c_str());
170f14cab2dSMichael Pfeiffer		}
171f14cab2dSMichael Pfeiffer	}
172f14cab2dSMichael Pfeiffer
173f14cab2dSMichael Pfeiffer	{
174f14cab2dSMichael Pfeiffer		map<string, bool>::iterator it = fConfiguration->fBooleanSettings.
175f14cab2dSMichael Pfeiffer			begin();
176f14cab2dSMichael Pfeiffer		for (; it != fConfiguration->fBooleanSettings.end(); it ++) {
177f14cab2dSMichael Pfeiffer			stp_set_boolean_parameter(fVariables, it->first.c_str(),
178f14cab2dSMichael Pfeiffer				it->second);
179f14cab2dSMichael Pfeiffer		}
180f14cab2dSMichael Pfeiffer	}
181f14cab2dSMichael Pfeiffer
182f14cab2dSMichael Pfeiffer	{
183f14cab2dSMichael Pfeiffer		map<string, int32>::iterator it = fConfiguration->fIntSettings.
184f14cab2dSMichael Pfeiffer			begin();
185f14cab2dSMichael Pfeiffer		for (; it != fConfiguration->fIntSettings.end(); it ++) {
186f14cab2dSMichael Pfeiffer			stp_set_int_parameter(fVariables, it->first.c_str(),
187f14cab2dSMichael Pfeiffer				it->second);
188f14cab2dSMichael Pfeiffer		}
189f14cab2dSMichael Pfeiffer	}
190f14cab2dSMichael Pfeiffer
191f14cab2dSMichael Pfeiffer	{
192f14cab2dSMichael Pfeiffer		map<string, int32>::iterator it = fConfiguration->fDimensionSettings.
193f14cab2dSMichael Pfeiffer			begin();
194f14cab2dSMichael Pfeiffer		for (; it != fConfiguration->fDimensionSettings.end(); it ++) {
195f14cab2dSMichael Pfeiffer			stp_set_dimension_parameter(fVariables, it->first.c_str(),
196f14cab2dSMichael Pfeiffer				it->second);
197f14cab2dSMichael Pfeiffer		}
198f14cab2dSMichael Pfeiffer	}
199f14cab2dSMichael Pfeiffer
200f14cab2dSMichael Pfeiffer	{
201f14cab2dSMichael Pfeiffer		map<string, double>::iterator it = fConfiguration->fDoubleSettings.
202f14cab2dSMichael Pfeiffer			begin();
203f14cab2dSMichael Pfeiffer		for (; it != fConfiguration->fDoubleSettings.end(); it ++) {
204f14cab2dSMichael Pfeiffer			stp_set_float_parameter(fVariables, it->first.c_str(),
205f14cab2dSMichael Pfeiffer				it->second);
206f14cab2dSMichael Pfeiffer		}
2079295cd64SMichael Pfeiffer	}
2089295cd64SMichael Pfeiffer
2099295cd64SMichael Pfeiffer	stp_set_string_parameter(fVariables, "InputImageType",
2109295cd64SMichael Pfeiffer		"RGB");
2119295cd64SMichael Pfeiffer	stp_set_string_parameter(fVariables, "ChannelBitDepth",
2129295cd64SMichael Pfeiffer		"8");
2139295cd64SMichael Pfeiffer	stp_set_float_parameter(fVariables, "Density",
2149295cd64SMichael Pfeiffer		1.0f);
2159295cd64SMichael Pfeiffer	stp_set_string_parameter(fVariables, "JobMode", "Job");
2169295cd64SMichael Pfeiffer
2179295cd64SMichael Pfeiffer	stp_set_printer_defaults_soft(fVariables, fPrinter);
2189295cd64SMichael Pfeiffer
2199295cd64SMichael Pfeiffer	return B_OK;
2209295cd64SMichael Pfeiffer}
2219295cd64SMichael Pfeiffer
2229295cd64SMichael Pfeiffer
2239295cd64SMichael Pfeiffervoid
2249295cd64SMichael PfeifferGPJob::End()
2259295cd64SMichael Pfeiffer{
2269295cd64SMichael Pfeiffer	if (fVariables == NULL)
2279295cd64SMichael Pfeiffer		return;
2289295cd64SMichael Pfeiffer
229fad05958SMichael Pfeiffer	if (fHasPages)
2309295cd64SMichael Pfeiffer		stp_end_job(fVariables, &fImage);
2319295cd64SMichael Pfeiffer
2329295cd64SMichael Pfeiffer	stp_vars_destroy(fVariables);
2339295cd64SMichael Pfeiffer	fVariables = NULL;
2349295cd64SMichael Pfeiffer}
2359295cd64SMichael Pfeiffer
2369295cd64SMichael Pfeifferstatus_t
2379295cd64SMichael PfeifferGPJob::PrintPage(list<GPBand*>& bands) {
238c0aa3379SMichael Pfeiffer	if (fStatus != B_OK)
239c0aa3379SMichael Pfeiffer		return fStatus;
2409295cd64SMichael Pfeiffer
2419295cd64SMichael Pfeiffer	fBands = &bands;
2429295cd64SMichael Pfeiffer	fCachedBand = NULL;
2439295cd64SMichael Pfeiffer
24489f1fd65SJérôme Duval	Rectangle<stp_dimension_t> imageableArea;
245d6d2c9b1SMichael Pfeiffer	stp_get_imageable_area(fVariables, &imageableArea.left,
246d6d2c9b1SMichael Pfeiffer		&imageableArea.right, &imageableArea.bottom, &imageableArea.top);
24789f1fd65SJérôme Duval	fprintf(stderr, "GPJob imageable area left %f, top %f, right %f, "
24889f1fd65SJérôme Duval		"bottom %f\n",
249d6d2c9b1SMichael Pfeiffer		imageableArea.left, imageableArea.top, imageableArea.right,
250d6d2c9b1SMichael Pfeiffer		imageableArea.bottom);
25189f1fd65SJérôme Duval	fprintf(stderr, "GPJob width %f %s, height %f %s\n",
252d6d2c9b1SMichael Pfeiffer		imageableArea.Width(),
25389f1fd65SJérôme Duval		std::fmod(imageableArea.Width(), 72.) == 0.0 ? "whole inches" : "not whole inches",
254d6d2c9b1SMichael Pfeiffer		imageableArea.Height(),
25589f1fd65SJérôme Duval		std::fmod(imageableArea.Height(), 72.) == 0.0 ? "whole inches" : "not whole inches"
256d6d2c9b1SMichael Pfeiffer		);
257d6d2c9b1SMichael Pfeiffer
258d6d2c9b1SMichael Pfeiffer	CoordinateSystem coordinateSystem;
259d6d2c9b1SMichael Pfeiffer	coordinateSystem.SetDPI(fConfiguration->fXDPI, fConfiguration->fYDPI);
2609295cd64SMichael Pfeiffer	{
261d6d2c9b1SMichael Pfeiffer		// GPBand offset is relative to imageable area left, top
262d6d2c9b1SMichael Pfeiffer		// but it has to be absolute to left, top of page
263d6d2c9b1SMichael Pfeiffer		int32 offsetX;
264d6d2c9b1SMichael Pfeiffer		int32 offsetY;
265d6d2c9b1SMichael Pfeiffer		coordinateSystem.FromGutenprintCeiling(imageableArea.left,
266d6d2c9b1SMichael Pfeiffer			imageableArea.top, offsetX, offsetY);
267d6d2c9b1SMichael Pfeiffer
268d6d2c9b1SMichael Pfeiffer		BPoint offset(offsetX, offsetY);
269d6d2c9b1SMichael Pfeiffer		list<GPBand*>::iterator it = fBands->begin();
270d6d2c9b1SMichael Pfeiffer		for (; it != fBands->end(); it++) {
271d6d2c9b1SMichael Pfeiffer			(*it)->fWhere += offset;
272d6d2c9b1SMichael Pfeiffer		}
2739295cd64SMichael Pfeiffer	}
2749295cd64SMichael Pfeiffer
275d6d2c9b1SMichael Pfeiffer	fPrintRect = GetPrintRectangle(bands);
276d6d2c9b1SMichael Pfeiffer
2779295cd64SMichael Pfeiffer	{
2789295cd64SMichael Pfeiffer		int left = (int)fPrintRect.left;
2799295cd64SMichael Pfeiffer		int top = (int)fPrintRect.top;
280d6d2c9b1SMichael Pfeiffer		int width = fPrintRect.Width() + 1;
281d6d2c9b1SMichael Pfeiffer		int height = fPrintRect.Height() + 1;
2829295cd64SMichael Pfeiffer
283d6d2c9b1SMichael Pfeiffer		fprintf(stderr, "GPJob bitmap bands frame left %d, top %d, width %d, "
284d6d2c9b1SMichael Pfeiffer			"height %d\n",
2859295cd64SMichael Pfeiffer			left, top, width, height);
2869295cd64SMichael Pfeiffer	}
2879295cd64SMichael Pfeiffer
288d6d2c9b1SMichael Pfeiffer	// calculate the position and size of the image to be printed on the page
289d6d2c9b1SMichael Pfeiffer	// unit: 1/72 Inches
290d6d2c9b1SMichael Pfeiffer	// constraints: the image must be inside the imageable area
29189f1fd65SJérôme Duval	double left;
29289f1fd65SJérôme Duval	double top;
293d6d2c9b1SMichael Pfeiffer	coordinateSystem.ToGutenprint(fPrintRect.left, fPrintRect.top, left, top);
294d6d2c9b1SMichael Pfeiffer	if (left < imageableArea.left)
295d6d2c9b1SMichael Pfeiffer		left = imageableArea.left;
296d6d2c9b1SMichael Pfeiffer	if (top < imageableArea.top)
297d6d2c9b1SMichael Pfeiffer		top = imageableArea.top;
298d6d2c9b1SMichael Pfeiffer
29989f1fd65SJérôme Duval	double right;
30089f1fd65SJérôme Duval	double bottom;
301d6d2c9b1SMichael Pfeiffer	coordinateSystem.ToGutenprintCeiling(fPrintRect.right, fPrintRect.bottom,
302d6d2c9b1SMichael Pfeiffer		right, bottom);
303d6d2c9b1SMichael Pfeiffer	if (right > imageableArea.right)
304d6d2c9b1SMichael Pfeiffer		right = imageableArea.right;
305d6d2c9b1SMichael Pfeiffer	if (bottom > imageableArea.bottom)
306d6d2c9b1SMichael Pfeiffer		bottom = imageableArea.bottom;
307d6d2c9b1SMichael Pfeiffer
30889f1fd65SJérôme Duval	double width = right - left;
30989f1fd65SJérôme Duval	double height = bottom - top;
3109295cd64SMichael Pfeiffer
311d6d2c9b1SMichael Pfeiffer	// because of rounding and clipping in the previous step,
312d6d2c9b1SMichael Pfeiffer	// now the image frame has to be synchronized
313d6d2c9b1SMichael Pfeiffer	coordinateSystem.FromGutenprint(left, top, fPrintRect.left, fPrintRect.top);
314d6d2c9b1SMichael Pfeiffer	int32 printRectWidth;
315d6d2c9b1SMichael Pfeiffer	int32 printRectHeight;
316d6d2c9b1SMichael Pfeiffer	coordinateSystem.SizeFromGutenprint(width, height, printRectWidth,
317d6d2c9b1SMichael Pfeiffer		printRectHeight);
318d6d2c9b1SMichael Pfeiffer	fPrintRect.right = fPrintRect.left + printRectWidth - 1;
319d6d2c9b1SMichael Pfeiffer	fPrintRect.bottom = fPrintRect.top + printRectHeight - 1;
3209295cd64SMichael Pfeiffer	{
321d6d2c9b1SMichael Pfeiffer		int left = fPrintRect.left;
322d6d2c9b1SMichael Pfeiffer		int top = fPrintRect.top;
323d6d2c9b1SMichael Pfeiffer		int width = fPrintRect.Width() + 1;
324d6d2c9b1SMichael Pfeiffer		int height = fPrintRect.Height() + 1;
3259295cd64SMichael Pfeiffer
326d6d2c9b1SMichael Pfeiffer		fprintf(stderr, "GPJob image dimensions left %d, top %d, width %d, "
327d6d2c9b1SMichael Pfeiffer			"height %d\n",
3289295cd64SMichael Pfeiffer			left, top, width, height);
3299295cd64SMichael Pfeiffer	}
3309295cd64SMichael Pfeiffer
331d6d2c9b1SMichael Pfeiffer	fprintf(stderr, "GPJob image dimensions in 1/72 Inches: "
332d6d2c9b1SMichael Pfeiffer		"left %d, top %d, right %d, bottom %d\n",
333d6d2c9b1SMichael Pfeiffer		(int)left, (int)top, (int)right, (int)bottom);
3349295cd64SMichael Pfeiffer
335d6d2c9b1SMichael Pfeiffer	stp_set_width(fVariables, right - left);
336d6d2c9b1SMichael Pfeiffer	stp_set_height(fVariables, bottom - top);
3379295cd64SMichael Pfeiffer	stp_set_left(fVariables, left);
3389295cd64SMichael Pfeiffer	stp_set_top(fVariables, top);
3399295cd64SMichael Pfeiffer
3409295cd64SMichael Pfeiffer	stp_merge_printvars(fVariables, stp_printer_get_defaults(fPrinter));
3419295cd64SMichael Pfeiffer
3429295cd64SMichael Pfeiffer	if (!stp_verify(fVariables)) {
3439295cd64SMichael Pfeiffer		fprintf(stderr, "GPJob PrintPage: invalid variables\n");
3449295cd64SMichael Pfeiffer		return B_ERROR;
3459295cd64SMichael Pfeiffer	}
3469295cd64SMichael Pfeiffer
347fad05958SMichael Pfeiffer	if (!fHasPages) {
348fad05958SMichael Pfeiffer		fHasPages = true;
3499295cd64SMichael Pfeiffer		stp_start_job(fVariables, &fImage);
3509295cd64SMichael Pfeiffer	}
3519295cd64SMichael Pfeiffer
3529295cd64SMichael Pfeiffer	stp_print(fVariables, &fImage);
3539295cd64SMichael Pfeiffer
354c0aa3379SMichael Pfeiffer	return fStatus;
355c0aa3379SMichael Pfeiffer}
356c0aa3379SMichael Pfeiffer
357c0aa3379SMichael Pfeiffer
358c0aa3379SMichael Pfeiffervoid
359c0aa3379SMichael PfeifferGPJob::GetErrorMessage(BString& message)
360c0aa3379SMichael Pfeiffer{
361c0aa3379SMichael Pfeiffer	message = fErrorMessage;
3629295cd64SMichael Pfeiffer}
3639295cd64SMichael Pfeiffer
3649295cd64SMichael Pfeiffer
365d6d2c9b1SMichael PfeifferRectInt32
3669295cd64SMichael PfeifferGPJob::GetPrintRectangle(list<GPBand*>& bands)
3679295cd64SMichael Pfeiffer{
3689295cd64SMichael Pfeiffer	list<GPBand*>::iterator it = bands.begin();
3699295cd64SMichael Pfeiffer	if (it == bands.end())
3709295cd64SMichael Pfeiffer		return BRect(0, 0, 0, 0);
3719295cd64SMichael Pfeiffer
3729295cd64SMichael Pfeiffer	GPBand* first = *it;
3739295cd64SMichael Pfeiffer	BRect rect = first->GetBoundingRectangle();
3749295cd64SMichael Pfeiffer	for (it ++; it != bands.end(); it ++) {
3759295cd64SMichael Pfeiffer		GPBand* band = *it;
3769295cd64SMichael Pfeiffer		rect = rect | band->GetBoundingRectangle();
3779295cd64SMichael Pfeiffer	}
3789295cd64SMichael Pfeiffer	return rect;
3799295cd64SMichael Pfeiffer}
3809295cd64SMichael Pfeiffer
3819295cd64SMichael Pfeiffer
3829295cd64SMichael Pfeiffervoid
3839295cd64SMichael PfeifferGPJob::Init()
3849295cd64SMichael Pfeiffer{
3859295cd64SMichael Pfeiffer
3869295cd64SMichael Pfeiffer}
3879295cd64SMichael Pfeiffer
3889295cd64SMichael Pfeiffer
3899295cd64SMichael Pfeiffervoid
3909295cd64SMichael PfeifferGPJob::Reset()
3919295cd64SMichael Pfeiffer{
3929295cd64SMichael Pfeiffer
3939295cd64SMichael Pfeiffer}
3949295cd64SMichael Pfeiffer
3959295cd64SMichael Pfeiffer
3969295cd64SMichael Pfeifferint
3979295cd64SMichael PfeifferGPJob::Width()
3989295cd64SMichael Pfeiffer{
399d6d2c9b1SMichael Pfeiffer	return fPrintRect.Width() + 1;
4009295cd64SMichael Pfeiffer}
4019295cd64SMichael Pfeiffer
4029295cd64SMichael Pfeiffer
4039295cd64SMichael Pfeifferint
4049295cd64SMichael PfeifferGPJob::Height()
4059295cd64SMichael Pfeiffer{
406d6d2c9b1SMichael Pfeiffer	return fPrintRect.Height() + 1;
4079295cd64SMichael Pfeiffer}
4089295cd64SMichael Pfeiffer
4099295cd64SMichael Pfeiffer
4109295cd64SMichael Pfeifferstp_image_status_t
4119295cd64SMichael PfeifferGPJob::GetRow(unsigned char* data, size_t size, int row)
4129295cd64SMichael Pfeiffer{
413c0aa3379SMichael Pfeiffer	if (fStatus != B_OK)
4149295cd64SMichael Pfeiffer		return STP_IMAGE_STATUS_ABORT;
4159295cd64SMichael Pfeiffer
4169295cd64SMichael Pfeiffer	// row is relative to left, top of image
417d6d2c9b1SMichael Pfeiffer	// convert it to absolute y coordinate value
418d6d2c9b1SMichael Pfeiffer	int line = fPrintRect.top + row;
4199295cd64SMichael Pfeiffer
4209295cd64SMichael Pfeiffer	FillWhite(data, size);
4219295cd64SMichael Pfeiffer
4229295cd64SMichael Pfeiffer	GPBand* band = FindBand(line);
4239295cd64SMichael Pfeiffer	if (band != NULL)
4249295cd64SMichael Pfeiffer		FillRow(band, data, size, line);
4259295cd64SMichael Pfeiffer
4269295cd64SMichael Pfeiffer	return STP_IMAGE_STATUS_OK;
4279295cd64SMichael Pfeiffer}
4289295cd64SMichael Pfeiffer
4299295cd64SMichael Pfeiffer
4309295cd64SMichael PfeifferGPBand*
4319295cd64SMichael PfeifferGPJob::FindBand(int line)
4329295cd64SMichael Pfeiffer{
4339295cd64SMichael Pfeiffer	if (fCachedBand != NULL && fCachedBand->ContainsLine(line))
4349295cd64SMichael Pfeiffer		return fCachedBand;
4359295cd64SMichael Pfeiffer
4369295cd64SMichael Pfeiffer	list<GPBand*>::iterator it = fBands->begin();
4379295cd64SMichael Pfeiffer	for (; it != fBands->end(); it ++) {
4389295cd64SMichael Pfeiffer		GPBand* band = *it;
4399295cd64SMichael Pfeiffer		if (band->ContainsLine(line)) {
4409295cd64SMichael Pfeiffer			fCachedBand = band;
4419295cd64SMichael Pfeiffer			return band;
4429295cd64SMichael Pfeiffer		}
4439295cd64SMichael Pfeiffer	}
4449295cd64SMichael Pfeiffer
4459295cd64SMichael Pfeiffer	fCachedBand = NULL;
4469295cd64SMichael Pfeiffer	return NULL;
4479295cd64SMichael Pfeiffer}
4489295cd64SMichael Pfeiffer
4499295cd64SMichael Pfeiffer
4509295cd64SMichael Pfeiffervoid
4519295cd64SMichael PfeifferGPJob::FillRow(GPBand* band, unsigned char* data, size_t size, int line)
4529295cd64SMichael Pfeiffer{
4539295cd64SMichael Pfeiffer	int imageTop = line - static_cast<int>(band->fWhere.y -
4549295cd64SMichael Pfeiffer		band->fValidRect.top);
4559295cd64SMichael Pfeiffer	int imageLeft = static_cast<int>(band->fValidRect.left);
4569295cd64SMichael Pfeiffer
457d6d2c9b1SMichael Pfeiffer	const int sourceBytesPerRow = band->fBitmap.BytesPerRow();
4589295cd64SMichael Pfeiffer	const int kSourceBytesPerPixel = 4; // BGRA
4599295cd64SMichael Pfeiffer	const unsigned char* source =
4609295cd64SMichael Pfeiffer		static_cast<unsigned char*>(band->fBitmap.Bits())
461d6d2c9b1SMichael Pfeiffer		+ imageTop * sourceBytesPerRow
4629295cd64SMichael Pfeiffer		+ imageLeft * kSourceBytesPerPixel;
4639295cd64SMichael Pfeiffer
4649295cd64SMichael Pfeiffer	int dataLeft = static_cast<int>(band->fWhere.x - fPrintRect.left);
465d6d2c9b1SMichael Pfeiffer	int sourcePixelsToSkip = 0;
466d6d2c9b1SMichael Pfeiffer	if (dataLeft < 0) {
467d6d2c9b1SMichael Pfeiffer		sourcePixelsToSkip = -dataLeft;
468d6d2c9b1SMichael Pfeiffer		dataLeft = 0;
469d6d2c9b1SMichael Pfeiffer	}
470d6d2c9b1SMichael Pfeiffer	int width = band->fValidRect.IntegerWidth() + 1 - sourcePixelsToSkip;
471d6d2c9b1SMichael Pfeiffer	source += sourcePixelsToSkip * kSourceBytesPerPixel;
472d6d2c9b1SMichael Pfeiffer	if (width <= 0)
473d6d2c9b1SMichael Pfeiffer		return;
4749295cd64SMichael Pfeiffer
4759295cd64SMichael Pfeiffer	const int kTargetBytesPerPixel = 3; // RGB
4769295cd64SMichael Pfeiffer	unsigned char* target = &data[dataLeft * kTargetBytesPerPixel];
477d6d2c9b1SMichael Pfeiffer	int maxWidth = size / kTargetBytesPerPixel - dataLeft;
478d6d2c9b1SMichael Pfeiffer	if (width > maxWidth)
479d6d2c9b1SMichael Pfeiffer		width = maxWidth;
4809295cd64SMichael Pfeiffer
4819295cd64SMichael Pfeiffer	ASSERT(0 <= imageTop && imageTop <= band->fValidRect.IntegerHeight());
4829295cd64SMichael Pfeiffer	ASSERT((dataLeft + width) * kTargetBytesPerPixel <= size);
4839295cd64SMichael Pfeiffer
4849295cd64SMichael Pfeiffer	for (int i = 0; i < width; i ++) {
4859295cd64SMichael Pfeiffer		target[0] = source[2];
4869295cd64SMichael Pfeiffer		target[1] = source[1];
4879295cd64SMichael Pfeiffer		target[2] = source[0];
4889295cd64SMichael Pfeiffer		target += kTargetBytesPerPixel;
4899295cd64SMichael Pfeiffer		source += kSourceBytesPerPixel;
4909295cd64SMichael Pfeiffer	}
4919295cd64SMichael Pfeiffer}
4929295cd64SMichael Pfeiffer
4939295cd64SMichael Pfeiffer
4949295cd64SMichael Pfeiffervoid
4959295cd64SMichael PfeifferGPJob::FillWhite(unsigned char* data, size_t size)
4969295cd64SMichael Pfeiffer{
4979295cd64SMichael Pfeiffer	for (size_t i = 0; i < size; i ++)
4989295cd64SMichael Pfeiffer		data[i] = 0xff;
4999295cd64SMichael Pfeiffer}
5009295cd64SMichael Pfeiffer
5019295cd64SMichael Pfeiffer
5029295cd64SMichael Pfeifferconst char*
5039295cd64SMichael PfeifferGPJob::GetAppname()
5049295cd64SMichael Pfeiffer{
5059295cd64SMichael Pfeiffer	return fApplicationName.String();
5069295cd64SMichael Pfeiffer}
5079295cd64SMichael Pfeiffer
5089295cd64SMichael Pfeiffer
5099295cd64SMichael Pfeiffervoid
5109295cd64SMichael PfeifferGPJob::Conclude()
5119295cd64SMichael Pfeiffer{
5129295cd64SMichael Pfeiffer	// nothing to do
5139295cd64SMichael Pfeiffer}
5149295cd64SMichael Pfeiffer
5159295cd64SMichael Pfeiffer
5169295cd64SMichael Pfeiffervoid
5179295cd64SMichael PfeifferGPJob::Write(const char* data, size_t size)
5189295cd64SMichael Pfeiffer{
5199295cd64SMichael Pfeiffer	try {
5209295cd64SMichael Pfeiffer		fOutputStream->Write(data, size);
5219295cd64SMichael Pfeiffer	} catch (TransportException e) {
522c0aa3379SMichael Pfeiffer		fStatus = B_IO_ERROR;
5239295cd64SMichael Pfeiffer	}
5249295cd64SMichael Pfeiffer}
5259295cd64SMichael Pfeiffer
5269295cd64SMichael Pfeiffer
5279295cd64SMichael Pfeiffervoid
5289295cd64SMichael PfeifferGPJob::ReportError(const char* data, size_t size)
5299295cd64SMichael Pfeiffer{
530c0aa3379SMichael Pfeiffer	if (fStatus == B_OK)
531c0aa3379SMichael Pfeiffer		fStatus = B_ERROR;
532c0aa3379SMichael Pfeiffer	fErrorMessage.Append(data, size);
5339295cd64SMichael Pfeiffer}
5349295cd64SMichael Pfeiffer
5359295cd64SMichael Pfeiffer
5369295cd64SMichael Pfeiffervoid
5379295cd64SMichael PfeifferGPJob::ImageInit(stp_image_t* image)
5389295cd64SMichael Pfeiffer{
5399295cd64SMichael Pfeiffer	GPJob* job = static_cast<GPJob*>(image->rep);
5409295cd64SMichael Pfeiffer	job->Init();
5419295cd64SMichael Pfeiffer}
5429295cd64SMichael Pfeiffer
5439295cd64SMichael Pfeiffer
5449295cd64SMichael Pfeiffervoid
5459295cd64SMichael PfeifferGPJob::ImageReset(stp_image_t* image)
5469295cd64SMichael Pfeiffer{
5479295cd64SMichael Pfeiffer	GPJob* job = static_cast<GPJob*>(image->rep);
5489295cd64SMichael Pfeiffer	job->Reset();
5499295cd64SMichael Pfeiffer}
5509295cd64SMichael Pfeiffer
5519295cd64SMichael Pfeiffer
5529295cd64SMichael Pfeifferint
5539295cd64SMichael PfeifferGPJob::ImageWidth(stp_image_t* image)
5549295cd64SMichael Pfeiffer{
5559295cd64SMichael Pfeiffer	GPJob* job = static_cast<GPJob*>(image->rep);
5569295cd64SMichael Pfeiffer	return job->Width();
5579295cd64SMichael Pfeiffer}
5589295cd64SMichael Pfeiffer
5599295cd64SMichael Pfeiffer
5609295cd64SMichael Pfeifferint
5619295cd64SMichael PfeifferGPJob::ImageHeight(stp_image_t *image)
5629295cd64SMichael Pfeiffer{
5639295cd64SMichael Pfeiffer	GPJob* job = static_cast<GPJob*>(image->rep);
5649295cd64SMichael Pfeiffer	return job->Height();
5659295cd64SMichael Pfeiffer}
5669295cd64SMichael Pfeiffer
5679295cd64SMichael Pfeiffer
5689295cd64SMichael Pfeifferstp_image_status_t
5699295cd64SMichael PfeifferGPJob::ImageGetRow(stp_image_t* image, unsigned char* data, size_t size,
5709295cd64SMichael Pfeiffer	int row)
5719295cd64SMichael Pfeiffer{
5729295cd64SMichael Pfeiffer	GPJob* job = static_cast<GPJob*>(image->rep);
5739295cd64SMichael Pfeiffer	return job->GetRow(data, size, row);
5749295cd64SMichael Pfeiffer}
5759295cd64SMichael Pfeiffer
5769295cd64SMichael Pfeiffer
5779295cd64SMichael Pfeifferconst char*
5789295cd64SMichael PfeifferGPJob::ImageGetAppname(stp_image_t* image)
5799295cd64SMichael Pfeiffer{
5809295cd64SMichael Pfeiffer	GPJob* job = static_cast<GPJob*>(image->rep);
5819295cd64SMichael Pfeiffer	return job->GetAppname();
5829295cd64SMichael Pfeiffer}
5839295cd64SMichael Pfeiffer
5849295cd64SMichael Pfeiffer
585