repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / apps / haikudepot / ui_generic / SharedBitmap.cpp
blob6bc3f1a75d1246ff7bb18432086c709c3c5504d9
1 /*
2 * Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
6 #include "SharedBitmap.h"
8 #include <algorithm>
9 #include <stdio.h>
11 #include <Application.h>
12 #include <Bitmap.h>
13 #include <DataIO.h>
14 #include <IconUtils.h>
15 #include <Message.h>
16 #include <MimeType.h>
17 #include <Resources.h>
18 #include <TranslationUtils.h>
20 #include "support.h"
23 SharedBitmap::SharedBitmap(BBitmap* bitmap)
25 BReferenceable(),
26 fResourceID(-1),
27 fBuffer(NULL),
28 fSize(0),
29 fMimeType()
31 fBitmap[0] = bitmap;
32 fBitmap[1] = NULL;
33 fBitmap[2] = NULL;
34 fBitmap[3] = NULL;
38 SharedBitmap::SharedBitmap(int32 resourceID)
40 BReferenceable(),
41 fResourceID(resourceID),
42 fBuffer(NULL),
43 fSize(0),
44 fMimeType()
46 fBitmap[0] = NULL;
47 fBitmap[1] = NULL;
48 fBitmap[2] = NULL;
49 fBitmap[3] = NULL;
53 SharedBitmap::SharedBitmap(const char* mimeType)
55 BReferenceable(),
56 fResourceID(-1),
57 fBuffer(NULL),
58 fSize(0),
59 fMimeType(mimeType)
61 fBitmap[0] = NULL;
62 fBitmap[1] = NULL;
63 fBitmap[2] = NULL;
64 fBitmap[3] = NULL;
68 SharedBitmap::SharedBitmap(BPositionIO& data)
70 BReferenceable(),
71 fResourceID(-1),
72 fBuffer(NULL),
73 fSize(0),
74 fMimeType()
76 status_t status = data.GetSize(&fSize);
77 const off_t kMaxSize = 1024 * 1024;
78 if (status == B_OK && fSize > 0 && fSize <= kMaxSize) {
79 fBuffer = new(std::nothrow) uint8[fSize];
80 if (fBuffer != NULL) {
81 data.Seek(0, SEEK_SET);
83 off_t bytesRead = 0;
84 size_t chunkSize = std::min((off_t)4096, fSize);
85 while (bytesRead < fSize) {
86 ssize_t read = data.Read(fBuffer + bytesRead, chunkSize);
87 if (read > 0)
88 bytesRead += read;
89 else
90 break;
93 if (bytesRead != fSize) {
94 delete[] fBuffer;
95 fBuffer = NULL;
96 fSize = 0;
98 } else
99 fSize = 0;
100 } else {
101 fprintf(stderr, "SharedBitmap(): Stream too large: %" B_PRIi64
102 ", max: %" B_PRIi64 "\n", fSize, kMaxSize);
105 fBitmap[0] = NULL;
106 fBitmap[1] = NULL;
107 fBitmap[2] = NULL;
108 fBitmap[3] = NULL;
112 SharedBitmap::~SharedBitmap()
114 delete fBitmap[0];
115 delete fBitmap[1];
116 delete fBitmap[2];
117 delete fBitmap[3];
118 delete[] fBuffer;
122 const BBitmap*
123 SharedBitmap::Bitmap(Size which)
125 if (fResourceID == -1 && fMimeType.Length() == 0 && fBuffer == NULL)
126 return fBitmap[0];
128 int32 index = 0;
129 int32 size = 16;
131 switch (which) {
132 default:
133 case SIZE_16:
134 break;
136 case SIZE_22:
137 index = 1;
138 size = 22;
139 break;
141 case SIZE_32:
142 index = 2;
143 size = 32;
144 break;
146 case SIZE_64:
147 index = 3;
148 size = 64;
149 break;
152 if (fBitmap[index] == NULL) {
153 if (fResourceID >= 0)
154 fBitmap[index] = _CreateBitmapFromResource(size);
155 else if (fBuffer != NULL)
156 fBitmap[index] = _CreateBitmapFromBuffer(size);
157 else if (fMimeType.Length() > 0)
158 fBitmap[index] = _CreateBitmapFromMimeType(size);
161 return fBitmap[index];
165 BBitmap*
166 SharedBitmap::_CreateBitmapFromResource(int32 size) const
168 BResources resources;
169 status_t status = get_app_resources(resources);
170 if (status != B_OK)
171 return NULL;
173 size_t dataSize;
174 const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, fResourceID,
175 &dataSize);
176 if (data != NULL)
177 return _LoadIconFromBuffer(data, dataSize, size);
179 data = resources.LoadResource(B_MESSAGE_TYPE, fResourceID, &dataSize);
180 if (data != NULL)
181 return _LoadBitmapFromBuffer(data, dataSize);
183 return NULL;
187 BBitmap*
188 SharedBitmap::_CreateBitmapFromBuffer(int32 size) const
190 BBitmap* bitmap = _LoadIconFromBuffer(fBuffer, fSize, size);
192 if (bitmap == NULL)
193 bitmap = _LoadBitmapFromBuffer(fBuffer, fSize);
195 return bitmap;
199 BBitmap*
200 SharedBitmap::_CreateBitmapFromMimeType(int32 size) const
202 BMimeType mimeType(fMimeType.String());
203 status_t status = mimeType.InitCheck();
204 if (status != B_OK)
205 return NULL;
207 BBitmap* bitmap = new BBitmap(BRect(0, 0, size - 1, size - 1), 0, B_RGBA32);
208 status = bitmap->InitCheck();
209 if (status == B_OK)
210 status = mimeType.GetIcon(bitmap, B_MINI_ICON);
212 if (status != B_OK) {
213 delete bitmap;
214 bitmap = NULL;
217 return bitmap;
221 BBitmap*
222 SharedBitmap::_LoadBitmapFromBuffer(const void* buffer, size_t size) const
224 BMemoryIO stream(buffer, size);
226 // Try to read as an archived bitmap.
227 BBitmap* bitmap = _LoadArchivedBitmapFromStream(stream);
229 if (bitmap == NULL) {
230 // Try to read as a translator bitmap
231 stream.Seek(0, SEEK_SET);
232 bitmap = _LoadTranslatorBitmapFromStream(stream);
235 if (bitmap != NULL) {
236 status_t status = bitmap->InitCheck();
237 if (status != B_OK) {
238 delete bitmap;
239 bitmap = NULL;
243 return bitmap;
247 BBitmap*
248 SharedBitmap::_LoadArchivedBitmapFromStream(BPositionIO& stream) const
250 BMessage archive;
251 status_t status = archive.Unflatten(&stream);
252 if (status != B_OK)
253 return NULL;
255 return new BBitmap(&archive);
259 BBitmap*
260 SharedBitmap::_LoadTranslatorBitmapFromStream(BPositionIO& stream) const
262 return BTranslationUtils::GetBitmap(&stream);
266 BBitmap*
267 SharedBitmap::_LoadIconFromBuffer(const void* data, size_t dataSize,
268 int32 size) const
270 BBitmap* bitmap = new BBitmap(BRect(0, 0, size - 1, size - 1), 0,
271 B_RGBA32);
272 status_t status = bitmap->InitCheck();
273 if (status == B_OK) {
274 status = BIconUtils::GetVectorIcon(
275 reinterpret_cast<const uint8*>(data), dataSize, bitmap);
278 if (status != B_OK) {
279 delete bitmap;
280 bitmap = NULL;
283 return bitmap;