1/*
2* Copyright 2010, Haiku. All rights reserved.
3* Distributed under the terms of the MIT License.
4*
5* Authors:
6*		Michael Pfeiffer
7*/
8#include "GPParameterVisitor.h"
9
10#include <String.h>
11
12
13const char* kJobMode = "JobMode";
14const char* kJob = "Job";
15
16const char* kPrintingMode = "PrintingMode";
17const char* kColor = "Color";
18const char* kBlackAndWhite = "BW";
19
20const char* kResolution = "Resolution";
21const char* kFakeResolutionKey = "";
22
23const char* kPageSize = "PageSize";
24
25const char* kChannelBitDepth = "ChannelBitDepth";
26
27
28GPParameterVisitor::GPParameterVisitor()
29	:
30	fVariables(NULL),
31	fHasResolutionParameter(false)
32{
33}
34
35
36GPParameterVisitor::~GPParameterVisitor()
37{
38}
39
40
41void
42GPParameterVisitor::Visit(const stp_printer_t* printer)
43{
44	// this code is based on Gutenprint printer_options.c
45	const stp_vars_t* defaultVariables = stp_printer_get_defaults(printer);
46	stp_vars_t* variables = stp_vars_create_copy(defaultVariables);
47	fVariables = variables;
48
49	stp_set_string_parameter(variables, kJobMode, kJob);
50
51	stp_parameter_t printingMode;
52	stp_describe_parameter(variables, kPrintingMode, &printingMode);
53	bool isColorPrinter = stp_string_list_is_present(printingMode.bounds.str,
54		kColor) != 0;
55	stp_parameter_description_destroy(&printingMode);
56
57	if (isColorPrinter)
58		stp_set_string_parameter(variables, kPrintingMode, kColor);
59	else
60		stp_set_string_parameter(variables, kPrintingMode, kBlackAndWhite);
61
62	stp_set_string_parameter(variables, kChannelBitDepth, "8");
63
64	stp_parameter_list_t list = stp_get_parameter_list(variables);
65	int size = stp_parameter_list_count(list);
66
67	for (int i = 0; i < size; i ++) {
68		const stp_parameter_t* parameter = stp_parameter_list_param(list, i);
69		stp_parameter_t description;
70		stp_describe_parameter(fVariables, parameter->name, &description);
71		VisitParameter(list, parameter, &description);
72		stp_parameter_description_destroy(&description);
73	}
74
75	// TODO check if this can really happen
76	if (!fHasResolutionParameter) {
77		AddMissingResolution();
78	}
79
80	EndVisit();
81
82	stp_parameter_list_destroy(list);
83	stp_vars_destroy(variables);
84	fVariables = NULL;
85}
86
87
88void
89GPParameterVisitor::AddMissingResolution()
90{
91	// some printer definitions don't have resolution parameter
92	// however "libprint" needs to know it for rasterization
93
94	// TODO find out if other parameters influence the resolution
95	// e.g. color vs black and white
96	int x, y;
97	stp_describe_resolution(fVariables, &x, &y);
98
99	BeginParameter(kResolution, "Resolution", STP_PARAMETER_CLASS_FEATURE);
100	DefaultStringParameter(kResolution, kFakeResolutionKey);
101	StringParameterSize(kResolution, 1);
102
103	if (x <= 0 || y <= 0) {
104		// TODO decide if more resolutions (150, 600) should be possible
105		x = 300;
106		y = 300;
107	}
108
109	BString displayName;
110	if (x != y)
111		displayName << x << " x " << y << " DPI";
112	else
113		displayName << x << " DPI";
114
115	ResolutionParameter(kResolution, kFakeResolutionKey, displayName.String(),
116		x, y);
117
118	EndParameter(kResolution);
119}
120
121
122void
123GPParameterVisitor::VisitParameter(stp_parameter_list_t list,
124	const stp_parameter_t* parameter, stp_parameter_t* description)
125{
126	// TODO decide which parameters should be revealed to user
127	// e.g. up to STP_PARAMETER_LEVEL_ADVANCED4;
128	// const stp_parameter_level_t kMaxLevel = STP_PARAMETER_LEVEL_ADVANCED4;
129	const stp_parameter_level_t kMaxLevel = STP_PARAMETER_LEVEL_BASIC;
130	stp_parameter_class_t parameterClass = parameter->p_class;
131	if (parameter->read_only ||
132		(parameter->p_level > kMaxLevel
133			&& strcmp(parameter->name, kResolution) != 0)
134		|| (parameterClass != STP_PARAMETER_CLASS_OUTPUT
135			&& parameterClass != STP_PARAMETER_CLASS_CORE
136			&& parameterClass != STP_PARAMETER_CLASS_FEATURE))
137		return;
138
139	if (!description->is_active)
140		return;
141
142	switch (description->p_type) {
143		case STP_PARAMETER_TYPE_STRING_LIST:
144			if (!BeginParameter(description->name, description->text,
145				parameterClass))
146				return;
147			VisitStringList(description);
148			EndParameter(description->name);
149			break;
150
151		case STP_PARAMETER_TYPE_BOOLEAN:
152			VisitBooleanParameter(description, parameterClass);
153			break;
154
155		case STP_PARAMETER_TYPE_DOUBLE:
156			VisitDoubleParameter(description, parameterClass);
157			break;
158
159		case STP_PARAMETER_TYPE_INT:
160			VisitIntParameter(description, parameterClass);
161			break;
162
163		case STP_PARAMETER_TYPE_DIMENSION:
164			VisitDimensionParameter(description, parameterClass);
165			break;
166
167		default:
168			break;
169	}
170
171}
172
173
174void
175GPParameterVisitor::VisitStringList(stp_parameter_t* parameter)
176{
177	stp_string_list_t* list = parameter->bounds.str;
178	int count = stp_string_list_count(list);
179	if (count <= 0)
180		return;
181
182	const char* name = parameter->name;
183	if (parameter->is_mandatory)
184		DefaultStringParameter(name, parameter->deflt.str);
185	else
186		DefaultStringParameter(name, NULL);
187
188	StringParameterSize(name, count);
189
190	for (int i = 0; i < count; i ++) {
191		const stp_param_string_t* entry = stp_string_list_param(list, i);
192		const char* key = entry->name;
193		const char* displayName = entry->text;
194		if (strcmp(name, kResolution) == 0) {
195			stp_set_string_parameter(fVariables, kResolution, key);
196
197			int x, y;
198			stp_describe_resolution(fVariables, &x, &y);
199
200			ResolutionParameter(name, key, displayName, x, y);
201
202			fHasResolutionParameter = true;
203		} else if (strcmp(name, kPageSize) == 0) {
204			stp_set_string_parameter(fVariables, kPageSize, key);
205
206			stp_dimension_t width;
207			stp_dimension_t height;
208			stp_get_media_size(fVariables, &width, &height);
209			BSize pageSize(width, height);
210
211			stp_dimension_t left, right, top, bottom;
212			stp_get_imageable_area(fVariables, &left, &right, &bottom, &top);
213			BRect imageableArea(left, top, right, bottom);
214
215			PageSizeParameter(name, key, displayName, pageSize, imageableArea);
216		} else {
217			StringParameter(name, key, displayName);
218		}
219	}
220}
221
222
223void
224GPParameterVisitor::VisitBooleanParameter(stp_parameter_t* description,
225	stp_parameter_class_t parameterClass)
226{
227	bool defaultValue = true;
228	if (description->is_mandatory)
229		defaultValue = description->deflt.boolean;
230	BooleanParameter(description->name, description->text, defaultValue,
231		parameterClass);
232}
233
234
235void
236GPParameterVisitor::VisitDoubleParameter(stp_parameter_t* description,
237			stp_parameter_class_t parameterClass)
238{
239	const char* name = description->name;
240	const char* text = description->text;
241	double lower = description->bounds.dbl.lower;
242	double upper = description->bounds.dbl.upper;
243	double defaultValue = description->deflt.dbl;
244	if (lower <= defaultValue && defaultValue <= upper)
245		DoubleParameter(name, text, lower, upper, defaultValue, parameterClass);
246}
247
248
249void
250GPParameterVisitor::VisitIntParameter(stp_parameter_t* description,
251			stp_parameter_class_t parameterClass)
252{
253	const char* name = description->name;
254	const char* text = description->text;
255	int lower = description->bounds.integer.lower;
256	int upper = description->bounds.integer.upper;
257	int defaultValue = description->deflt.integer;
258	if (lower <= defaultValue && defaultValue <= upper)
259		IntParameter(name, text, lower, upper, defaultValue, parameterClass);
260}
261
262
263void
264GPParameterVisitor::VisitDimensionParameter(stp_parameter_t* description,
265			stp_parameter_class_t parameterClass)
266{
267	const char* name = description->name;
268	const char* text = description->text;
269	double lower = description->bounds.dimension.lower;
270	double upper = description->bounds.dimension.upper;
271	double defaultValue = description->deflt.dimension;
272	if (lower <= defaultValue && defaultValue <= upper)
273		DimensionParameter(name, text, lower, upper, defaultValue,
274			parameterClass);
275}
276