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 "GPCapabilityExtractor.h"
9
10#include "PrinterCap.h"
11
12
13const char* kInputSlot = "InputSlot";
14
15
16#if 1
17#define GP_PRINT(...) \
18	fprintf(stderr, __VA_ARGS__)
19#else
20#define GP_PRINT(...) \
21	{}
22#endif
23
24GPCapabilityExtractor::GPCapabilityExtractor(GPCapabilities* capabilities)
25	:
26	fState(kIgnoreParameter),
27	fCapabilities(capabilities),
28	fIndex(0),
29	fNextDriverSpecificCategoryID(PrinterCap::kDriverSpecificCapabilitiesBegin)
30{
31
32}
33
34
35bool
36GPCapabilityExtractor::BeginParameter(const char* name, const char* displayName,
37	stp_parameter_class_t parameterClass)
38{
39	fState = kIgnoreParameter;
40	if (strcmp(kPageSize, name) == 0) {
41		GP_PRINT("Supported parameter: %s\n", name);
42		fState = kExtractPageSizeParameter;
43	} else if (strcmp(kResolution, name) == 0) {
44		GP_PRINT("Supported parameter: %s\n", name);
45		fState = kExtractResolutionParameter;
46	} else if (strcmp(kInputSlot, name) == 0) {
47		GP_PRINT("Supported parameter: %s\n", name);
48		fState = kExtractInputSlotParameter;
49	} else if (strcmp(kPrintingMode, name) == 0) {
50		GP_PRINT("Supported parameter: %s\n", name);
51		fState = kExtractPrintingModeParameter;
52	} else {
53		GP_PRINT("Parameter: %s - %s\n", name, displayName);
54		if (!Supportsed(parameterClass))
55			return false;
56
57		fState = kExtractParameter;
58		DriverSpecificCap* capability = new DriverSpecificCap(displayName,
59			fNextDriverSpecificCategoryID, DriverSpecificCap::kList);
60		capability->fKey = name;
61
62		fDriverSpecificCategories.push_back(capability);
63	}
64	return true;
65}
66
67
68void
69GPCapabilityExtractor::DefaultStringParameter(const char* name,
70		const char* key)
71{
72	if (key == NULL)
73		fDefaultKey = "";
74	else
75		fDefaultKey = key;
76}
77
78
79void
80GPCapabilityExtractor::StringParameterSize(const char* name, int size)
81{
82	fIndex = 0;
83
84	switch (fState) {
85		case kExtractPageSizeParameter:
86			fCapabilities->fPageSizes.SetSize(size);
87			break;
88
89		case kExtractResolutionParameter:
90			fCapabilities->fResolutions.SetSize(size);
91			break;
92
93		case kExtractInputSlotParameter:
94			fCapabilities->fInputSlots.SetSize(size);
95			break;
96
97		case kExtractPrintingModeParameter:
98			fCapabilities->fPrintingModes.SetSize(size);
99			break;
100
101		case kExtractParameter:
102			fState = kExtractListParameter;
103			fCapabilities->fDriverSpecificCapabilities[
104							 fNextDriverSpecificCategoryID].SetSize(size);
105			break;
106
107		default:
108			break;
109	}
110}
111
112
113void
114GPCapabilityExtractor::StringParameter(const char* name, const char* key,
115		const char* displayName)
116{
117	bool isDefault = fDefaultKey == key;
118	EnumCap* capability;
119
120	switch (fState) {
121		case kExtractResolutionParameter:
122			GP_PRINT("GPCapabilityExtractor: ResolutionParameter expected\n");
123			break;
124
125		case kExtractInputSlotParameter:
126			capability = new PaperSourceCap(displayName, isDefault,
127				static_cast<JobData::PaperSource>(fIndex));
128			AddCapability(fCapabilities->fInputSlots, capability, key);
129			break;
130
131		case kExtractPrintingModeParameter:
132			capability = new ColorCap(displayName, isDefault,
133				static_cast<JobData::Color>(fIndex));
134			AddCapability(fCapabilities->fPrintingModes, capability, key);
135			break;
136
137		case kExtractListParameter:
138			capability = new ListItemCap(displayName, isDefault, fIndex);
139			AddCapability(fCapabilities->fDriverSpecificCapabilities[
140				 fNextDriverSpecificCategoryID], capability, key);
141			break;
142
143		default:
144			break;
145	}
146
147}
148
149
150void
151GPCapabilityExtractor::ResolutionParameter(const char* name, const char* key,
152		const char* displayName, int x, int y)
153{
154	bool isDefault = fDefaultKey == key;
155	EnumCap* capability;
156	int resolution;
157
158	switch (fState) {
159		case kExtractResolutionParameter:
160			if (x <= 0 || y <= 0) {
161				// usually this is the entry for the "Default" resolution
162				// if we want to show this in the UI, we need a way to
163				// determine the resolution (x and y) for it, because
164				// libprint needs it for rasterization
165				fCapabilities->fResolutions.DecreaseSize();
166				break;
167			}
168
169			// TODO remove this workaround when libprint supports x != y too
170			// for now use the maximum resolution to render the page bands
171			resolution = max_c(x, y);
172
173			capability = new ResolutionCap(displayName,	isDefault, fIndex,
174				resolution, resolution);
175			AddCapability(fCapabilities->fResolutions, capability, key);
176			break;
177
178		default:
179			break;
180	}
181}
182
183
184void
185GPCapabilityExtractor::PageSizeParameter(const char* name, const char* key,
186	const char* displayName, BSize pageSize, BRect imageableArea)
187{
188	bool isDefault = fDefaultKey == key;
189	EnumCap* capability;
190
191	switch (fState) {
192		case kExtractPageSizeParameter:
193			capability = new PaperCap(displayName, isDefault,
194				static_cast<JobData::Paper>(fIndex),
195				BRect(0, 0, pageSize.width, pageSize.height),
196				imageableArea);
197			AddCapability(fCapabilities->fPageSizes, capability, key);
198			break;
199
200		default:
201			break;
202	}
203}
204
205
206void
207GPCapabilityExtractor::EndParameter(const char* name)
208{
209	if (fState == kExtractListParameter) {
210		fNextDriverSpecificCategoryID ++;
211	}
212}
213
214
215void
216GPCapabilityExtractor::BooleanParameter(const char* name,
217	const char* displayName, bool defaultValue,
218	stp_parameter_class_t parameterClass)
219{
220	if (!Supportsed(parameterClass))
221		return;
222
223	BooleanCap* capability = new BooleanCap(displayName, defaultValue);
224	AddDriverSpecificCapability(name, displayName, DriverSpecificCap::kBoolean,
225		capability);
226}
227
228
229void
230GPCapabilityExtractor::DoubleParameter(const char* name,
231	const char* displayName, double lower, double upper, double defaultValue,
232	stp_parameter_class_t parameterClass)
233{
234	if (!Supportsed(parameterClass))
235		return;
236
237	DoubleRangeCap* capability = new DoubleRangeCap(displayName, lower, upper,
238		defaultValue);
239	AddDriverSpecificCapability(name, displayName,
240		DriverSpecificCap::kDoubleRange, capability);
241}
242
243
244void
245GPCapabilityExtractor::IntParameter(const char* name, const char* displayName,
246	int lower, int upper, int defaultValue,
247	stp_parameter_class_t parameterClass)
248{
249	if (!Supportsed(parameterClass))
250		return;
251
252	IntRangeCap* capability = new IntRangeCap(displayName, lower, upper,
253		defaultValue);
254	AddDriverSpecificCapability(name, displayName, DriverSpecificCap::kIntRange,
255		capability);
256}
257
258
259void
260GPCapabilityExtractor::DimensionParameter(const char* name,
261	const char* displayName, int lower, int upper, int defaultValue,
262	stp_parameter_class_t parameterClass)
263{
264	if (!Supportsed(parameterClass))
265		return;
266
267	IntRangeCap* capability = new IntRangeCap(displayName, lower, upper,
268		defaultValue);
269	AddDriverSpecificCapability(name, displayName,
270		DriverSpecificCap::kIntDimension, capability);
271}
272
273
274void
275GPCapabilityExtractor::EndVisit()
276{
277	if (fCapabilities->fInputSlots.Size() == 0)
278		AddDefaultInputSlot();
279	SetDriverSpecificCategories();
280}
281
282
283bool
284GPCapabilityExtractor::Supportsed(stp_parameter_class_t parameterClass)
285{
286	return parameterClass == STP_PARAMETER_CLASS_FEATURE
287		|| parameterClass == STP_PARAMETER_CLASS_OUTPUT;
288}
289
290
291void
292GPCapabilityExtractor::AddDefaultInputSlot()
293{
294	BeginParameter(kInputSlot, "Input Slot", STP_PARAMETER_CLASS_FEATURE);
295	DefaultStringParameter(kInputSlot, "");
296	StringParameterSize(kInputSlot, 1);
297	StringParameter(kInputSlot, "", "Default");
298	EndParameter(kInputSlot);
299}
300
301
302void
303GPCapabilityExtractor::SetDriverSpecificCategories()
304{
305	int size = fDriverSpecificCategories.size();
306	if (size == 0)
307		return;
308
309	fCapabilities->fDriverSpecificCategories.SetSize(size);
310	struct BaseCap** array = fCapabilities->fDriverSpecificCategories.Array();
311	list<DriverSpecificCap*>::iterator it = fDriverSpecificCategories.begin();
312	for (int index = 0; it != fDriverSpecificCategories.end(); it ++,
313		index ++) {
314		array[index] = *it;
315	}
316}
317
318void
319GPCapabilityExtractor::AddCapability(GPArray<struct BaseCap>& array,
320	EnumCap* capability, const char* key)
321{
322	capability->fKey = key;
323	array.Array()[fIndex] = capability;
324	fIndex ++;
325}
326
327
328void
329GPCapabilityExtractor::AddDriverSpecificCapability(const char* name,
330	const char*	displayName, DriverSpecificCap::Type type, BaseCap* capability)
331{
332	DriverSpecificCap* parent = new DriverSpecificCap(displayName,
333		fNextDriverSpecificCategoryID, type);
334	parent->fKey = name;
335
336	fDriverSpecificCategories.push_back(parent);
337
338	GPArray<struct BaseCap>& array = fCapabilities->fDriverSpecificCapabilities
339		[fNextDriverSpecificCategoryID];
340	array.SetSize(1);
341	array.Array()[0] = capability;
342
343	fNextDriverSpecificCategoryID++;
344}
345