xref: /haiku/src/add-ons/translators/icns/ICNSTranslator.cpp (revision e705c841d784f0035a0ef3e9e96f6e017df16681)
1 /*
2  * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Copyright 2012, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include "ICNSTranslator.h"
8 
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 
13 #include "ConfigView.h"
14 #include "ICNSLoader.h"
15 
16 #include <Catalog.h>
17 
18 #undef B_TRANSLATION_CONTEXT
19 #define B_TRANSLATION_CONTEXT "ICNSTranslator"
20 
21 extern "C" {
22 #include "icns.h"
23 }
24 
25 const char *kDocumentCount = "/documentCount";
26 const char *kDocumentIndex = "/documentIndex";
27 
28 #define kICNSMimeType "image/icns"
29 #define kICNSName "Apple Icon"
30 
31 // The input formats that this translator supports.
32 static const translation_format sInputFormats[] = {
33 	{
34 		ICNS_IMAGE_FORMAT,
35 		B_TRANSLATOR_BITMAP,
36 		ICNS_IN_QUALITY,
37 		ICNS_IN_CAPABILITY,
38 		kICNSMimeType,
39 		kICNSName
40 	},
41 	{
42 		B_TRANSLATOR_BITMAP,
43 		B_TRANSLATOR_BITMAP,
44 		BITS_IN_QUALITY,
45 		BITS_IN_CAPABILITY,
46 		"image/x-be-bitmap",
47 		"Be Bitmap Format (ICNSTranslator)"
48 	},
49 };
50 
51 // The output formats that this translator supports.
52 static const translation_format sOutputFormats[] = {
53 	{
54 		ICNS_IMAGE_FORMAT,
55 		B_TRANSLATOR_BITMAP,
56 		ICNS_OUT_QUALITY,
57 		ICNS_OUT_CAPABILITY,
58 		kICNSMimeType,
59 		kICNSName
60 	},
61 	{
62 		B_TRANSLATOR_BITMAP,
63 		B_TRANSLATOR_BITMAP,
64 		BITS_OUT_QUALITY,
65 		BITS_OUT_CAPABILITY,
66 		"image/x-be-bitmap",
67 		"Be Bitmap Format (ICNSTranslator)"
68 	},
69 };
70 
71 // Default settings for the Translator
72 static const TranSetting sDefaultSettings[] = {
73 	{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
74 	{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}
75 };
76 
77 const uint32 kNumInputFormats = sizeof(sInputFormats)
78 	/ sizeof(translation_format);
79 const uint32 kNumOutputFormats = sizeof(sOutputFormats)
80 	/ sizeof(translation_format);
81 const uint32 kNumDefaultSettings = sizeof(sDefaultSettings)
82 	/ sizeof(TranSetting);
83 
84 
85 ICNSTranslator::ICNSTranslator()
86 	: BaseTranslator(B_TRANSLATE("Apple icons"),
87 		B_TRANSLATE("Apple icon translator"),
88 		ICNS_TRANSLATOR_VERSION,
89 		sInputFormats, kNumInputFormats,
90 		sOutputFormats, kNumOutputFormats,
91 		"ICNSTranslator",
92 		sDefaultSettings, kNumDefaultSettings,
93 		B_TRANSLATOR_BITMAP, ICNS_IMAGE_FORMAT)
94 {
95 }
96 
97 
98 ICNSTranslator::~ICNSTranslator()
99 {
100 }
101 
102 
103 status_t
104 ICNSTranslator::DerivedIdentify(BPositionIO *stream,
105 	const translation_format *format, BMessage *ioExtension,
106 	translator_info *info, uint32 outType)
107 {
108 	if (!outType)
109 		outType = B_TRANSLATOR_BITMAP;
110 	if (outType != B_TRANSLATOR_BITMAP && outType != ICNS_IMAGE_FORMAT)
111 		return B_NO_TRANSLATOR;
112 
113 	uint32 signatureData;
114 	ssize_t signatureSize = 4;
115 	if (stream->Read(&signatureData, signatureSize) != signatureSize)
116 		return B_IO_ERROR;
117 
118 	const uint32 kICNSMagic = B_HOST_TO_BENDIAN_INT32('icns');
119 
120 	if (signatureData != kICNSMagic)
121 		return B_ILLEGAL_DATA;
122 
123 
124 	ICNSLoader icnsFile(stream);
125 	if(!icnsFile.IsLoaded() || icnsFile.IconsCount() <= 0)
126 		return B_ILLEGAL_DATA;
127 
128 	int32 documentCount = icnsFile.IconsCount();
129 	int32 documentIndex = 1;
130 
131 	if (ioExtension) {
132 		if (ioExtension->FindInt32(DOCUMENT_INDEX, &documentIndex) != B_OK)
133 			documentIndex = 1;
134 		if (documentIndex < 1 || documentIndex > documentCount)
135 			return B_NO_TRANSLATOR;
136 
137 		ioExtension->RemoveName(DOCUMENT_COUNT);
138 		ioExtension->AddInt32(DOCUMENT_COUNT, documentCount);
139 	}
140 
141 	info->type = ICNS_IMAGE_FORMAT;
142 	info->group = B_TRANSLATOR_BITMAP;
143 	info->quality = ICNS_IN_QUALITY;
144 	info->capability = ICNS_IN_CAPABILITY;
145 	BString iconName("Apple icon");
146 	if (documentCount > 1)
147 		iconName << " #" << documentIndex;
148 	snprintf(info->name, sizeof(info->name), iconName.String());
149 	strcpy(info->MIME, kICNSMimeType);
150 
151 	return B_OK;
152 }
153 
154 
155 status_t
156 ICNSTranslator::DerivedTranslate(BPositionIO *source,
157 	const translator_info *info, BMessage *ioExtension,
158 	uint32 outType, BPositionIO *target, int32 baseType)
159 {
160 	if (!outType)
161 		outType = B_TRANSLATOR_BITMAP;
162 	if (outType != B_TRANSLATOR_BITMAP && outType != ICNS_IMAGE_FORMAT)
163 		return B_NO_TRANSLATOR;
164 
165 	switch (baseType) {
166 		case 1:
167 		{
168 			TranslatorBitmap bitsHeader;
169 			status_t result;
170 			result = identify_bits_header(source, NULL, &bitsHeader);
171 			if (result != B_OK)
172 				return B_NO_TRANSLATOR;
173 
174 			icns_type_t type = ICNSFormat(bitsHeader.bounds.Width() + 1,
175 				bitsHeader.bounds.Height() + 1, bitsHeader.colors);
176 			if (type == ICNS_NULL_TYPE)
177 				return B_NO_TRANSLATOR;
178 
179 			if (outType == ICNS_IMAGE_FORMAT) {
180 				ICNSSaver icnsFile(source, bitsHeader.rowBytes, type);
181 				if (icnsFile.IsCreated())
182 					return icnsFile.SaveData(target);
183 			}
184 
185 			return B_NO_TRANSLATOR;
186 		}
187 
188 		case 0:
189 		{
190 			if (outType != B_TRANSLATOR_BITMAP)
191 				return B_NO_TRANSLATOR;
192 
193 			ICNSLoader icnsFile(source);
194 			if (!icnsFile.IsLoaded() || icnsFile.IconsCount() <= 0)
195 				return B_NO_TRANSLATOR;
196 
197 			int32 documentIndex = 1;
198 
199 			if (ioExtension) {
200 				if (ioExtension->FindInt32(DOCUMENT_INDEX, &documentIndex) != B_OK)
201 					documentIndex = 1;
202 			}
203 
204 			return icnsFile.GetIcon(target, documentIndex);
205 		}
206 
207 		default:
208 			return B_NO_TRANSLATOR;
209 	}
210 }
211 
212 
213 status_t
214 ICNSTranslator::DerivedCanHandleImageSize(float width, float height) const
215 {
216 	if (ICNSFormat(width, height, B_RGBA32) == ICNS_NULL_TYPE)
217 		return B_NO_TRANSLATOR;
218 	return B_OK;
219 }
220 
221 
222 BView *
223 ICNSTranslator::NewConfigView(TranslatorSettings *settings)
224 {
225 	return new ConfigView(settings);
226 }
227 
228 
229 //	#pragma mark -
230 
231 
232 BTranslator *
233 make_nth_translator(int32 n, image_id you, uint32 flags, ...)
234 {
235 	if (n != 0)
236 		return NULL;
237 
238 	return new ICNSTranslator();
239 }
240 
241