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