1/*
2 * Copyright 2007, Jérôme Duval. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "HPGSTranslator.h"
8#include "ConfigView.h"
9#include "ReadHelper.h"
10
11#include "hpgsimage.h"
12
13#include <Catalog.h>
14#include <Messenger.h>
15#include <TranslatorRoster.h>
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20
21#undef B_TRANSLATION_CONTEXT
22#define B_TRANSLATION_CONTEXT "HPGSTranslator"
23
24
25typedef struct my_hpgs_png_image_st {
26	hpgs_png_image image;
27	BPositionIO *target;
28} my_hpgs_png_image;
29
30
31int
32my_pim_write(hpgs_image *_this, const char *filename)
33{
34	BPositionIO* target = ((my_hpgs_png_image *)_this)->target;
35	unsigned char *row;
36	int stride, depth;
37	_this->vtable->get_data(_this, &row, &stride, &depth);
38	for (int i = 0; i< _this->height; ++i) {
39		ssize_t bytesWritten = target->Write(row, stride);
40		if (bytesWritten < B_OK)
41			return bytesWritten;
42		row += stride;
43	}
44
45	return 0;
46}
47
48
49// The input formats that this translator supports.
50static const translation_format sInputFormats[] = {
51	{
52		HPGS_IMAGE_FORMAT,
53		B_TRANSLATOR_BITMAP,
54		HPGS_IN_QUALITY,
55		HPGS_IN_CAPABILITY,
56		"vector/x-hpgl2",
57		"HP-GL/2"
58	},
59};
60
61// The output formats that this translator supports.
62static const translation_format sOutputFormats[] = {
63	{
64		B_TRANSLATOR_BITMAP,
65		B_TRANSLATOR_BITMAP,
66		BITS_OUT_QUALITY,
67		BITS_OUT_CAPABILITY,
68		"image/x-be-bitmap",
69		"Be Bitmap Format (HPGSTranslator)"
70	},
71};
72
73// Default settings for the Translator
74static const TranSetting sDefaultSettings[] = {
75	{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
76	{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}
77};
78
79const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
80const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
81const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
82
83
84//	#pragma mark -
85
86
87HPGSTranslator::HPGSTranslator()
88	: BaseTranslator(B_TRANSLATE("HPGS images"),
89		B_TRANSLATE("HPGS image translator"),
90		HPGS_TRANSLATOR_VERSION,
91		sInputFormats, kNumInputFormats,
92		sOutputFormats, kNumOutputFormats,
93		"HPGSTranslator_Settings",
94		sDefaultSettings, kNumDefaultSettings,
95		B_TRANSLATOR_BITMAP, HPGS_IMAGE_FORMAT)
96{
97	hpgs_init("/usr/local");
98}
99
100
101HPGSTranslator::~HPGSTranslator()
102{
103	hpgs_cleanup();
104}
105
106
107status_t
108HPGSTranslator::DerivedIdentify(BPositionIO *stream,
109	const translation_format *format, BMessage *settings,
110	translator_info *info, uint32 outType)
111{
112	if (!outType)
113		outType = B_TRANSLATOR_BITMAP;
114	if (outType != B_TRANSLATOR_BITMAP)
115		return B_NO_TRANSLATOR;
116
117	hpgs_istream *istream = hpgs_new_wrapper_istream(stream);
118
119	status_t err = B_OK;
120	int verbosity = 1;
121	hpgs_bool multipage = HPGS_FALSE;
122	hpgs_bool ignore_ps = HPGS_FALSE;
123	hpgs_bool do_linewidth = HPGS_TRUE;
124	hpgs_device *size_dev = (hpgs_device *)hpgs_new_plotsize_device(ignore_ps,
125		do_linewidth);
126	hpgs_reader *reader = hpgs_new_reader(istream, size_dev, multipage,
127		verbosity);
128	if (hpgs_read(reader, HPGS_FALSE) == B_OK) {
129		info->type = HPGS_IMAGE_FORMAT;
130		info->group = B_TRANSLATOR_BITMAP;
131		info->quality = HPGS_IN_QUALITY;
132		info->capability = HPGS_IN_CAPABILITY;
133		snprintf(info->name, sizeof(info->name), B_TRANSLATE("HPGS image"));
134		strcpy(info->MIME, "vector/x-hpgl2");
135	} else
136		err = B_NO_TRANSLATOR;
137
138	free(reader);
139	free(size_dev);
140	hpgs_free_wrapper_istream(istream);
141
142	return err;
143}
144
145
146status_t
147HPGSTranslator::DerivedTranslate(BPositionIO* source,
148	const translator_info* info, BMessage* settings,
149	uint32 outType, BPositionIO* target, int32 baseType)
150{
151	if (!outType)
152		outType = B_TRANSLATOR_BITMAP;
153	if (outType != B_TRANSLATOR_BITMAP || baseType != 0)
154		return B_NO_TRANSLATOR;
155
156	status_t err = B_OK;
157	hpgs_istream *istream = hpgs_new_wrapper_istream(source);
158
159	TranslatorBitmap header;
160	ssize_t bytesWritten;
161	uint32 dataSize;
162
163	double paper_angle = 180.0;
164	double paper_border = 0.0;
165	double paper_width = 0.0;
166	double paper_height = 0.0;
167	int verbosity = 0;
168	int depth = 32;
169	int palette = 0;
170	hpgs_bool multipage = HPGS_FALSE;
171	hpgs_bool ignore_ps = HPGS_FALSE;
172	hpgs_bool do_linewidth = HPGS_TRUE;
173	hpgs_bool do_rop3 = HPGS_TRUE;
174	hpgs_bool antialias = HPGS_FALSE;
175	int image_interpolation = 0;
176	double thin_alpha = 0.25;
177	hpgs_device *size_dev = 0;
178	hpgs_bbox bbox = { 0.0, 0.0, 0.0, 0.0 };
179	hpgs_image *image;
180	hpgs_paint_device *pdv;
181	hpgs_device *plot_dev;
182
183	size_dev = (hpgs_device *)hpgs_new_plotsize_device(ignore_ps, do_linewidth);
184	hpgs_reader *reader = hpgs_new_reader(istream, size_dev, multipage, verbosity);
185	if (hpgs_read(reader, HPGS_FALSE)) {
186		fprintf(stderr, B_TRANSLATE("no hpgs\n"));
187		err = B_NO_TRANSLATOR;
188		goto err1;
189	}
190
191	if (hpgs_getplotsize(size_dev,1,&bbox)<0) {
192		fprintf(stderr, B_TRANSLATE("no hpgs\n"));
193		err = B_NO_TRANSLATOR;
194		goto err1;
195	}
196
197	// set the appropriate page placement.
198	if (paper_width > 0.0 && paper_height > 0.0) {
199		hpgs_reader_set_fixed_page(reader,&bbox,
200			paper_width, paper_height, paper_border, paper_angle);
201	} else {
202		paper_width = 200.0 * 72.0;
203		paper_height = 200.0 * 72.0;
204		hpgs_reader_set_dynamic_page(reader,&bbox,
205			paper_width, paper_height, paper_border, paper_angle);
206	}
207
208	image = (hpgs_image*)hpgs_new_png_image((int)bbox.urx, (int)bbox.ury, depth, palette, do_rop3);
209	image->vtable->write = &my_pim_write;
210	image = (hpgs_image *)realloc(image, sizeof(my_hpgs_png_image));
211	((my_hpgs_png_image *)image)->target = target;
212
213	pdv = hpgs_new_paint_device(image, NULL, &bbox, antialias);
214	hpgs_paint_device_set_image_interpolation(pdv, image_interpolation);
215	hpgs_paint_device_set_thin_alpha(pdv, thin_alpha);
216
217	plot_dev = (hpgs_device *)pdv;
218	if (hpgs_reader_imbue(reader, plot_dev)) {
219		fprintf(stderr, hpgs_i18n(B_TRANSLATE("Error: Cannot imbue plot "
220			"device to reader: %s\n")), hpgs_get_error());
221		err = B_NO_TRANSLATOR;
222		goto err2;
223	}
224
225	dataSize = (int)bbox.urx * 4 * (int)bbox.ury;
226
227	header.magic = B_TRANSLATOR_BITMAP;
228	header.bounds.Set(0, 0, (int)bbox.urx - 1, bbox.ury - 1);
229	header.rowBytes = (int)bbox.urx * 4;
230	header.colors = B_RGBA32;
231	header.dataSize = dataSize;
232
233	// write out Be's Bitmap header
234	swap_data(B_UINT32_TYPE, &header, sizeof(TranslatorBitmap),
235		B_SWAP_HOST_TO_BENDIAN);
236	bytesWritten = target->Write(&header, sizeof(TranslatorBitmap));
237	if (bytesWritten < B_OK) {
238		fprintf(stderr, B_TRANSLATE("Write error %s\n"),
239			strerror(bytesWritten));
240		err = bytesWritten;
241		goto err2;
242	}
243
244	if ((size_t)bytesWritten != sizeof(TranslatorBitmap)) {
245		fprintf(stderr, "TranslatorBitmap\n");
246		err = B_IO_ERROR;
247	}
248
249	if (err == B_OK && hpgs_read(reader, HPGS_FALSE)) {
250		fprintf(stderr, hpgs_i18n(B_TRANSLATE("Error: Cannot process plot "
251			"data %s\n")), hpgs_get_error());
252		err = B_NO_TRANSLATOR;
253	}
254
255err2:
256	free(pdv);
257	free(image);
258
259err1:
260	free(reader);
261	free(size_dev);
262	free(istream->stream);
263	free(istream);
264	return err;
265}
266
267
268BView *
269HPGSTranslator::NewConfigView(TranslatorSettings *settings)
270{
271	return new ConfigView(BRect(0, 0, 225, 175));
272}
273
274
275//	#pragma mark -
276
277
278BTranslator *
279make_nth_translator(int32 n, image_id you, uint32 flags, ...)
280{
281	if (n != 0)
282		return NULL;
283
284	return new HPGSTranslator();
285}
286
287