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
ICNSTranslator()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
~ICNSTranslator()98 ICNSTranslator::~ICNSTranslator()
99 {
100 }
101
102
103 status_t
DerivedIdentify(BPositionIO * stream,const translation_format * format,BMessage * ioExtension,translator_info * info,uint32 outType)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 strlcpy(info->name, iconName.String(), sizeof(info->name));
149 strcpy(info->MIME, kICNSMimeType);
150
151 return B_OK;
152 }
153
154
155 status_t
DerivedTranslate(BPositionIO * source,const translator_info * info,BMessage * ioExtension,uint32 outType,BPositionIO * target,int32 baseType)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
DerivedCanHandleImageSize(float width,float height) const214 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 *
NewConfigView(TranslatorSettings * settings)223 ICNSTranslator::NewConfigView(TranslatorSettings *settings)
224 {
225 return new ConfigView(settings);
226 }
227
228
229 // #pragma mark -
230
231
232 BTranslator *
make_nth_translator(int32 n,image_id you,uint32 flags,...)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