File: | /boot/home/haiku/haiku/src/add-ons/translators/icns/ICNSLoader.cpp |
Location: | line 75, column 3 |
Description: | Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete' |
1 | /* | |||
2 | * Copyright 2012, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved. | |||
3 | * Distributed under the terms of the MIT License. | |||
4 | */ | |||
5 | ||||
6 | #include "ICNSLoader.h" | |||
7 | #include "BaseTranslator.h" | |||
8 | ||||
9 | ||||
10 | static int compareTypes(const void *a, const void *b) | |||
11 | { | |||
12 | icns_type_t typeItemA = *((icns_type_t*)(*((icns_type_t*)a))); | |||
13 | icns_type_t typeItemB = *((icns_type_t*)(*((icns_type_t*)b))); | |||
14 | ||||
15 | icns_icon_info_t imageInfoA = icns_get_image_info_for_type(typeItemA); | |||
16 | icns_icon_info_t imageInfoB = icns_get_image_info_for_type(typeItemB); | |||
17 | ||||
18 | return imageInfoB.iconWidth - imageInfoA.iconWidth; | |||
19 | } | |||
20 | ||||
21 | ||||
22 | icns_type_t | |||
23 | ICNSFormat(float width, float height, color_space colors) | |||
24 | { | |||
25 | int imageWidth = (int)ceil(width); | |||
26 | int imageHeight = (int)ceil(height); | |||
27 | ||||
28 | if (imageWidth != imageHeight) | |||
29 | return ICNS_NULL_TYPE0x00000000; | |||
30 | ||||
31 | //other colors depth not supported now | |||
32 | if (colors != B_RGB32 && colors != B_RGBA32) | |||
33 | return ICNS_NULL_TYPE0x00000000; | |||
34 | ||||
35 | switch (imageWidth) { | |||
36 | case 16: | |||
37 | return ICNS_16x16_32BIT_DATA0x69733332; | |||
38 | case 32: | |||
39 | return ICNS_32x32_32BIT_DATA0x696C3332; | |||
40 | case 48: | |||
41 | return ICNS_48x48_32BIT_DATA0x69683332; | |||
42 | case 128: | |||
43 | return ICNS_128X128_32BIT_DATA0x69743332; | |||
44 | case 256: | |||
45 | return ICNS_256x256_32BIT_ARGB_DATA0x69633038; | |||
46 | case 512: | |||
47 | return ICNS_512x512_32BIT_ARGB_DATA0x69633039; | |||
48 | case 1024: | |||
49 | return ICNS_1024x1024_32BIT_ARGB_DATA0x69633130; | |||
50 | } | |||
51 | return ICNS_NULL_TYPE0x00000000; | |||
52 | } | |||
53 | ||||
54 | ||||
55 | ICNSLoader::ICNSLoader(BPositionIO *stream) | |||
56 | { | |||
57 | fLoaded = false; | |||
58 | fIconsCount = 0; | |||
59 | ||||
60 | stream->Seek(0, SEEK_END2); | |||
61 | fStreamSize = stream->Position(); | |||
62 | stream->Seek(0, SEEK_SET0); | |||
63 | ||||
64 | if (fStreamSize <= 0) | |||
| ||||
65 | return; | |||
66 | ||||
67 | uint8* icnsDataBuffer = new uint8[fStreamSize]; | |||
68 | size_t readedBytes = stream->Read(icnsDataBuffer,fStreamSize); | |||
69 | ||||
70 | fIconFamily = NULL__null; | |||
71 | int status = icns_import_family_data(readedBytes, icnsDataBuffer, | |||
72 | &fIconFamily); | |||
73 | ||||
74 | if (status != 0) { | |||
75 | delete icnsDataBuffer; | |||
| ||||
76 | return; | |||
77 | } | |||
78 | ||||
79 | icns_byte_t *dataPtr = (icns_byte_t*)fIconFamily; | |||
80 | off_t dataOffset = sizeof(icns_type_t) + sizeof(icns_size_t); | |||
81 | ||||
82 | while ((dataOffset+8) < fIconFamily->resourceSize) | |||
83 | { | |||
84 | icns_element_t iconElement; | |||
85 | icns_size_t iconDataSize; | |||
86 | ||||
87 | memcpy(&iconElement, (dataPtr + dataOffset), 8); | |||
88 | iconDataSize = iconElement.elementSize - 8; | |||
89 | ||||
90 | if(IS_SPUPPORTED_TYPE(iconElement.elementType)((iconElement.elementType) == 0x69633130 || (iconElement.elementType ) == 0x69633039 || (iconElement.elementType) == 0x69633038 || (iconElement.elementType) == 0x69743332 || (iconElement.elementType ) == 0x69683332 || (iconElement.elementType) == 0x696C3332 || (iconElement.elementType) == 0x69733332)) { | |||
91 | icns_type_t* newTypeItem = new icns_type_t; | |||
92 | *newTypeItem = iconElement.elementType; | |||
93 | fFormatList.AddItem(newTypeItem); | |||
94 | fIconsCount++; | |||
95 | } | |||
96 | dataOffset += iconElement.elementSize; | |||
97 | } | |||
98 | ||||
99 | fFormatList.SortItems(compareTypes); | |||
100 | ||||
101 | delete icnsDataBuffer; | |||
102 | ||||
103 | fLoaded = true; | |||
104 | } | |||
105 | ||||
106 | ||||
107 | ICNSLoader::~ICNSLoader() | |||
108 | { | |||
109 | if (fIconFamily != NULL__null) | |||
110 | free(fIconFamily); | |||
111 | ||||
112 | icns_type_t* item; | |||
113 | for (int32 i = 0; (item = (icns_type_t*)fFormatList.ItemAt(i)) != NULL__null; i++) | |||
114 | delete item; | |||
115 | fFormatList.MakeEmpty(); | |||
116 | } | |||
117 | ||||
118 | ||||
119 | bool | |||
120 | ICNSLoader::IsLoaded(void) | |||
121 | { | |||
122 | return fLoaded; | |||
123 | } | |||
124 | ||||
125 | ||||
126 | int | |||
127 | ICNSLoader::IconsCount(void) | |||
128 | { | |||
129 | return fIconsCount; | |||
130 | } | |||
131 | ||||
132 | ||||
133 | int | |||
134 | ICNSLoader::GetIcon(BPositionIO *target, int index) | |||
135 | { | |||
136 | if (index < 1 || index > fIconsCount || !fLoaded) | |||
137 | return B_NO_TRANSLATOR(((-2147483647 - 1) + 0x4800) + 1); | |||
138 | ||||
139 | icns_image_t iconImage; | |||
140 | memset(&iconImage, 0, sizeof(icns_image_t)); | |||
141 | ||||
142 | icns_type_t typeItem = *((icns_type_t*)fFormatList.ItemAt(index - 1)); | |||
143 | int status = icns_get_image32_with_mask_from_family(fIconFamily, | |||
144 | typeItem, &iconImage); | |||
145 | ||||
146 | if (status != 0) | |||
147 | return B_NO_TRANSLATOR(((-2147483647 - 1) + 0x4800) + 1); | |||
148 | ||||
149 | TranslatorBitmap bitsHeader; | |||
150 | bitsHeader.magic = B_TRANSLATOR_BITMAP; | |||
151 | bitsHeader.bounds.left = 0; | |||
152 | bitsHeader.bounds.top = 0; | |||
153 | bitsHeader.bounds.right = iconImage.imageWidth - 1; | |||
154 | bitsHeader.bounds.bottom = iconImage.imageHeight - 1; | |||
155 | bitsHeader.rowBytes = sizeof(uint32) * iconImage.imageWidth; | |||
156 | bitsHeader.colors = B_RGBA32; | |||
157 | bitsHeader.dataSize = bitsHeader.rowBytes * iconImage.imageHeight; | |||
158 | if (swap_data(B_UINT32_TYPE, &bitsHeader, | |||
159 | sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK((int)0)) { | |||
160 | icns_free_image(&iconImage); | |||
161 | return B_NO_TRANSLATOR(((-2147483647 - 1) + 0x4800) + 1); | |||
162 | } | |||
163 | target->Write(&bitsHeader, sizeof(TranslatorBitmap)); | |||
164 | ||||
165 | uint8 *rowBuff = new uint8[iconImage.imageWidth * sizeof(uint32)]; | |||
166 | for (uint32 i = 0; i < iconImage.imageHeight; i++) { | |||
167 | uint8 *rowData = iconImage.imageData | |||
168 | + (i * iconImage.imageWidth * sizeof(uint32)); | |||
169 | uint8 *rowBuffPtr = rowBuff; | |||
170 | for (uint32 j=0; j < iconImage.imageWidth; j++) { | |||
171 | rowBuffPtr[0] = rowData[2]; | |||
172 | rowBuffPtr[1] = rowData[1]; | |||
173 | rowBuffPtr[2] = rowData[0]; | |||
174 | rowBuffPtr[3] = rowData[3]; | |||
175 | rowBuffPtr += sizeof(uint32); | |||
176 | rowData += sizeof(uint32); | |||
177 | } | |||
178 | target->Write(rowBuff, iconImage.imageWidth * sizeof(uint32)); | |||
179 | } | |||
180 | delete rowBuff; | |||
181 | icns_free_image(&iconImage); | |||
182 | ||||
183 | return B_OK((int)0); | |||
184 | } | |||
185 | ||||
186 | ||||
187 | ICNSSaver::ICNSSaver(BPositionIO *stream, uint32 rowBytes, icns_type_t type) | |||
188 | { | |||
189 | fCreated = false; | |||
190 | ||||
191 | icns_icon_info_t imageTypeInfo = icns_get_image_info_for_type(type); | |||
192 | int iconWidth = imageTypeInfo.iconWidth; | |||
193 | int iconHeight = imageTypeInfo.iconWidth; | |||
194 | int bpp = 32; | |||
195 | ||||
196 | uint8 *bits = new uint8[iconWidth * iconHeight * sizeof(uint32)]; | |||
197 | ||||
198 | uint8 *rowPtr = bits; | |||
199 | for (int i = 0; i < iconHeight; i++) { | |||
200 | stream->Read(rowPtr, rowBytes); | |||
201 | uint8 *bytePtr = rowPtr; | |||
202 | for (int j=0; j < iconWidth; j++) { | |||
203 | uint8 temp = bytePtr[0]; | |||
204 | bytePtr[0] = bytePtr[2]; | |||
205 | bytePtr[2] = temp; | |||
206 | bytePtr += sizeof(uint32); | |||
207 | } | |||
208 | rowPtr += iconWidth * sizeof(uint32); | |||
209 | } | |||
210 | ||||
211 | icns_create_family(&fIconFamily); | |||
212 | ||||
213 | icns_image_t icnsImage; | |||
214 | icnsImage.imageWidth = iconWidth; | |||
215 | icnsImage.imageHeight = iconHeight; | |||
216 | icnsImage.imageChannels = 4; | |||
217 | icnsImage.imagePixelDepth = 8; | |||
218 | icnsImage.imageDataSize = iconWidth * iconHeight * 4; | |||
219 | icnsImage.imageData = bits; | |||
220 | ||||
221 | icns_icon_info_t iconInfo; | |||
222 | iconInfo.isImage = 1; | |||
223 | iconInfo.iconWidth = icnsImage.imageWidth; | |||
224 | iconInfo.iconHeight = icnsImage.imageHeight; | |||
225 | iconInfo.iconBitDepth = bpp; | |||
226 | iconInfo.iconChannels = (bpp == 32 ? 4 : 1); | |||
227 | iconInfo.iconPixelDepth = bpp / iconInfo.iconChannels; | |||
228 | ||||
229 | icns_type_t iconType = icns_get_type_from_image_info(iconInfo); | |||
230 | ||||
231 | if (iconType == ICNS_NULL_TYPE0x00000000) { | |||
232 | delete bits; | |||
233 | free(fIconFamily); | |||
234 | fIconFamily = NULL__null; | |||
235 | return; | |||
236 | } | |||
237 | ||||
238 | icns_element_t *iconElement = NULL__null; | |||
239 | int icnsErr = icns_new_element_from_image(&icnsImage, iconType, | |||
240 | &iconElement); | |||
241 | ||||
242 | if (iconElement != NULL__null) { | |||
243 | if (icnsErr == ICNS_STATUS_OK0) { | |||
244 | icns_set_element_in_family(&fIconFamily, iconElement); | |||
245 | fCreated = true; | |||
246 | } | |||
247 | free(iconElement); | |||
248 | } | |||
249 | ||||
250 | if (iconType != ICNS_1024x1024_32BIT_ARGB_DATA0x69633130 | |||
251 | && iconType != ICNS_512x512_32BIT_ARGB_DATA0x69633039 | |||
252 | && iconType != ICNS_256x256_32BIT_ARGB_DATA0x69633038) | |||
253 | { | |||
254 | icns_type_t maskType = icns_get_mask_type_for_icon_type(iconType); | |||
255 | ||||
256 | icns_image_t icnsMask; | |||
257 | icns_init_image_for_type(maskType, &icnsMask); | |||
258 | ||||
259 | uint32 iconDataOffset = 0; | |||
260 | uint32 maskDataOffset = 0; | |||
261 | ||||
262 | while (iconDataOffset < icnsImage.imageDataSize | |||
263 | && maskDataOffset < icnsMask.imageDataSize) { | |||
264 | icnsMask.imageData[maskDataOffset] = | |||
265 | icnsImage.imageData[iconDataOffset + 3]; | |||
266 | iconDataOffset += 4; | |||
267 | maskDataOffset += 1; | |||
268 | } | |||
269 | ||||
270 | icns_element_t *maskElement = NULL__null; | |||
271 | icnsErr = icns_new_element_from_mask(&icnsMask, maskType, | |||
272 | &maskElement); | |||
273 | ||||
274 | if (maskElement != NULL__null) { | |||
275 | if (icnsErr == ICNS_STATUS_OK0) | |||
276 | icns_set_element_in_family(&fIconFamily, maskElement); | |||
277 | else | |||
278 | fCreated = false; | |||
279 | free(maskElement); | |||
280 | } | |||
281 | icns_free_image(&icnsMask); | |||
282 | } | |||
283 | ||||
284 | if (!fCreated) { | |||
285 | free(fIconFamily); | |||
286 | fIconFamily = NULL__null; | |||
287 | } | |||
288 | ||||
289 | delete bits; | |||
290 | } | |||
291 | ||||
292 | ||||
293 | ICNSSaver::~ICNSSaver() | |||
294 | { | |||
295 | if (fIconFamily != NULL__null) | |||
296 | free(fIconFamily); | |||
297 | } | |||
298 | ||||
299 | ||||
300 | int | |||
301 | ICNSSaver::SaveData(BPositionIO *target) | |||
302 | { | |||
303 | icns_size_t dataSize; | |||
304 | icns_byte_t *dataPtrOut; | |||
305 | icns_export_family_data(fIconFamily, &dataSize, &dataPtrOut); | |||
306 | if (dataSize != 0 && dataPtrOut != NULL__null) { | |||
307 | if (target->Write(dataPtrOut, dataSize) == dataSize); | |||
308 | return B_OK((int)0); | |||
309 | } | |||
310 | return B_ERROR(-1); | |||
311 | } | |||
312 | ||||
313 | ||||
314 | bool | |||
315 | ICNSSaver::IsCreated(void) | |||
316 | { | |||
317 | return fCreated; | |||
318 | } |