1/*
2 * Copyright 2009, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
4 *
5 * Authors:
6 *		Michael Lotz, mmlr@mlotz.ch
7 */
8
9#include "HVIFTranslator.h"
10#include "HVIFView.h"
11
12#include <Bitmap.h>
13#include <BitmapStream.h>
14#include <Catalog.h>
15#include <IconUtils.h>
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21#define HVIF_FORMAT_CODE				'HVIF'
22#define HVIF_TRANSLATION_QUALITY		1.0
23#define HVIF_TRANSLATION_CAPABILITY		1.0
24
25#undef B_TRANSLATION_CONTEXT
26#define B_TRANSLATION_CONTEXT "HVIFTranslator"
27
28
29static const translation_format sInputFormats[] = {
30	{
31		HVIF_FORMAT_CODE,
32		B_TRANSLATOR_BITMAP,
33		HVIF_TRANSLATION_QUALITY,
34		HVIF_TRANSLATION_CAPABILITY,
35		"application/x-vnd.Haiku-icon",
36		"Native Haiku vector icon"
37	}
38};
39
40
41static const translation_format sOutputFormats[] = {
42	{
43		B_TRANSLATOR_BITMAP,
44		B_TRANSLATOR_BITMAP,
45		0.4,
46		0.4,
47		"image/x-be-bitmap",
48		"Be Bitmap format (HVIFTranslator)"
49	}
50};
51
52
53static const TranSetting sDefaultSettings[] = {
54	{ HVIF_SETTING_RENDER_SIZE, TRAN_SETTING_INT32, 64 }
55};
56
57const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
58const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
59const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
60
61
62
63BTranslator *
64make_nth_translator(int32 n, image_id image, uint32 flags, ...)
65{
66	if (n == 0)
67		return new HVIFTranslator();
68	return NULL;
69}
70
71
72HVIFTranslator::HVIFTranslator()
73	: BaseTranslator(B_TRANSLATE("HVIF icons"),
74		B_TRANSLATE("Haiku vector icon translator"),
75		HVIF_TRANSLATOR_VERSION,
76		sInputFormats, kNumInputFormats,
77		sOutputFormats, kNumOutputFormats,
78		"HVIFTranslator_Settings",
79		sDefaultSettings, kNumDefaultSettings,
80		B_TRANSLATOR_BITMAP, HVIF_FORMAT_CODE)
81{
82}
83
84
85HVIFTranslator::~HVIFTranslator()
86{
87}
88
89
90status_t
91HVIFTranslator::DerivedIdentify(BPositionIO *inSource,
92	const translation_format *inFormat, BMessage *ioExtension,
93	translator_info *outInfo, uint32 outType)
94{
95	// TODO: we do the fully work twice!
96	if (outType != B_TRANSLATOR_BITMAP)
97		return B_NO_TRANSLATOR;
98
99	// filter out invalid sizes
100	off_t size = inSource->Seek(0, SEEK_END);
101	if (size <= 0 || size > 256 * 1024 || inSource->Seek(0, SEEK_SET) != 0)
102		return B_NO_TRANSLATOR;
103
104	uint8 *buffer = (uint8 *)malloc(size);
105	if (buffer == NULL)
106		return B_NO_MEMORY;
107
108	if (inSource->Read(buffer, size) != size) {
109		free(buffer);
110		return B_NO_TRANSLATOR;
111	}
112
113	BBitmap dummy(BRect(0, 0, 1, 1), B_BITMAP_NO_SERVER_LINK, B_RGBA32);
114	if (BIconUtils::GetVectorIcon(buffer, size, &dummy) != B_OK) {
115		free(buffer);
116		return B_NO_TRANSLATOR;
117	}
118
119	if (outInfo) {
120		outInfo->type = sInputFormats[0].type;
121		outInfo->group = sInputFormats[0].group;
122		outInfo->quality = sInputFormats[0].quality;
123		outInfo->capability = sInputFormats[0].capability;
124		strcpy(outInfo->MIME, sInputFormats[0].MIME);
125		strcpy(outInfo->name, sInputFormats[0].name);
126	}
127
128	free(buffer);
129	return B_OK;
130}
131
132
133status_t
134HVIFTranslator::DerivedTranslate(BPositionIO *inSource,
135	const translator_info *inInfo, BMessage *ioExtension, uint32 outType,
136	BPositionIO *outDestination, int32 baseType)
137{
138	if (outType != B_TRANSLATOR_BITMAP)
139		return B_NO_TRANSLATOR;
140
141	// filter out invalid sizes
142	off_t size = inSource->Seek(0, SEEK_END);
143	if (size <= 0 || size > 256 * 1024 || inSource->Seek(0, SEEK_SET) != 0)
144		return B_NO_TRANSLATOR;
145
146	uint8 *buffer = (uint8 *)malloc(size);
147	if (buffer == NULL)
148		return B_NO_MEMORY;
149
150	if (inSource->Read(buffer, size) != size) {
151		free(buffer);
152		return B_NO_TRANSLATOR;
153	}
154
155	int32 renderSize = fSettings->SetGetInt32(HVIF_SETTING_RENDER_SIZE);
156	if (renderSize <= 0 || renderSize > 1024)
157		renderSize = 64;
158
159	BBitmap rendered(BRect(0, 0, renderSize - 1, renderSize - 1),
160		B_BITMAP_NO_SERVER_LINK, B_RGBA32);
161	if (BIconUtils::GetVectorIcon(buffer, size, &rendered) != B_OK) {
162		free(buffer);
163		return B_NO_TRANSLATOR;
164	}
165
166	BBitmapStream stream(&rendered);
167	stream.Seek(0, SEEK_SET);
168	ssize_t read = 0;
169
170	while ((read = stream.Read(buffer, size)) > 0)
171		outDestination->Write(buffer, read);
172
173	BBitmap *dummy = NULL;
174	stream.DetachBitmap(&dummy);
175	free(buffer);
176	return B_OK;
177}
178
179
180BView *
181HVIFTranslator::NewConfigView(TranslatorSettings *settings)
182{
183	return new HVIFView(B_TRANSLATE("HVIFTranslator Settings"),
184		B_WILL_DRAW, settings);
185}
186