xref: /haiku/src/kits/tracker/Bitmaps.cpp (revision 9e25244c5e9051f6cd333820d6332397361abd6c)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 #include "Bitmaps.h"
36 #include "Utilities.h"
37 
38 #include <Autolock.h>
39 #include <Bitmap.h>
40 #include <Debug.h>
41 #include <DataIO.h>
42 #include <File.h>
43 #include <IconUtils.h>
44 #include <String.h>
45 #include <SupportDefs.h>
46 
47 
48 //	#pragma mark - BImageResources
49 
50 
51 BImageResources::BImageResources(void* memAddr)
52 {
53 	image_id image = find_image(memAddr);
54 	image_info info;
55 	if (get_image_info(image, &info) == B_OK) {
56 #if _SUPPORTS_RESOURCES
57 		BFile file(&info.name[0], B_READ_ONLY);
58 #else
59 		BString name(&info.name[0]);
60 		name += ".rsrc";
61 		BFile file(name.String(), B_READ_ONLY);
62 #endif
63 		if (file.InitCheck() == B_OK)
64 			fResources.SetTo(&file);
65 	}
66 }
67 
68 
69 BImageResources::~BImageResources()
70 {
71 }
72 
73 
74 const BResources*
75 BImageResources::ViewResources() const
76 {
77 	if (fLock.Lock() != B_OK)
78 		return NULL;
79 
80 	return &fResources;
81 }
82 
83 
84 BResources*
85 BImageResources::ViewResources()
86 {
87 	if (fLock.Lock() != B_OK)
88 		return NULL;
89 
90 	return &fResources;
91 }
92 
93 
94 status_t
95 BImageResources::FinishResources(BResources* res) const
96 {
97 	ASSERT(res == &fResources);
98 	if (res != &fResources)
99 		return B_BAD_VALUE;
100 
101 	fLock.Unlock();
102 
103 	return B_OK;
104 }
105 
106 
107 const void*
108 BImageResources::LoadResource(type_code type, int32 id,
109 	size_t* out_size) const
110 {
111 	// Serialize execution.
112 	// Looks like BResources is not really thread safe. We should
113 	// clean that up in the future and remove the locking from here.
114 	BAutolock lock(fLock);
115 	if (!lock.IsLocked())
116 		return 0;
117 
118 	// Return the resource.  Because we never change the BResources
119 	// object, the returned data will not change until TTracker is
120 	// destroyed.
121 	return const_cast<BResources*>(&fResources)->LoadResource(type, id,
122 		out_size);
123 }
124 
125 
126 const void*
127 BImageResources::LoadResource(type_code type, const char* name,
128 	size_t* out_size) const
129 {
130 	// Serialize execution.
131 	BAutolock lock(fLock);
132 	if (!lock.IsLocked())
133 		return NULL;
134 
135 	// Return the resource.  Because we never change the BResources
136 	// object, the returned data will not change until TTracker is
137 	// destroyed.
138 	return const_cast<BResources*>(&fResources)->LoadResource(type, name,
139 		out_size);
140 }
141 
142 
143 status_t
144 BImageResources::GetIconResource(int32 id, icon_size size,
145 	BBitmap* dest) const
146 {
147 	size_t length = 0;
148 	const void* data;
149 
150 	// try to load vector icon
151 	data = LoadResource(B_VECTOR_ICON_TYPE, id, &length);
152 	if (data != NULL
153 		&& BIconUtils::GetVectorIcon((uint8*)data, length, dest) == B_OK) {
154 		return B_OK;
155 	}
156 
157 	// fall back to R5 icon
158 	length = 0;
159 	size = (size == B_MINI_ICON ? B_MINI_ICON : B_LARGE_ICON);
160 
161 	data = LoadResource(size == B_MINI_ICON ? 'MICN' : 'ICON', id, &length);
162 	if (data == NULL || length != (size_t)(size * size)) {
163 		TRESPASS();
164 		return B_ERROR;
165 	}
166 
167 	if (dest->ColorSpace() == B_RGBA32) {
168 		// fill with transparent
169 		uint8* destBits = (uint8*)dest->Bits();
170 		int32 i = 0;
171 		while (i < dest->BitsLength()) {
172 			destBits[i++] = B_TRANSPARENT_32_BIT.red;
173 			destBits[i++] = B_TRANSPARENT_32_BIT.green;
174 			destBits[i++] = B_TRANSPARENT_32_BIT.blue;
175 			destBits[i++] = B_TRANSPARENT_32_BIT.alpha;
176 		}
177 
178 		// scale and convert from B_CMAP8 to B_RGBA32
179 		if (BIconUtils::ConvertFromCMAP8((uint8*)data, size, size, size,
180 				dest) == B_OK) {
181 			return B_OK;
182 		}
183 	} else { // assume B_CMAP8
184 		// fill with transparent
185 		uint8* destBits = (uint8*)dest->Bits();
186 		for (int32 i = 0; i < dest->BitsLength(); i++)
187 			destBits[i] = B_TRANSPARENT_MAGIC_CMAP8;
188 	}
189 
190 	// import bits into the middle of dest without scaling
191 	// color space is converted from B_CMAP8 to B_RGBA32
192 	float x = roundf((dest->Bounds().Width() - size) / 2);
193 	float y = roundf((dest->Bounds().Height() - size) / 2);
194 	return dest->ImportBits(data, (int32)length, size, B_CMAP8,
195 		BPoint(0, 0), BPoint(x, y), BSize(size - 1, size - 1));
196 }
197 
198 
199 status_t
200 BImageResources::GetIconResource(int32 id, const uint8** iconData,
201 	size_t* iconSize) const
202 {
203 	// try to load vector icon data from resources
204 	size_t length = 0;
205 	const void* data = LoadResource(B_VECTOR_ICON_TYPE, id, &length);
206 	if (data == NULL)
207 		return B_ERROR;
208 
209 	*iconData = (const uint8*)data;
210 	*iconSize = length;
211 
212 	return B_OK;
213 }
214 
215 
216 image_id
217 BImageResources::find_image(void* memAddr) const
218 {
219 	image_info info;
220 	int32 cookie = 0;
221 	while (get_next_image_info(0, &cookie, &info) == B_OK) {
222 		if ((info.text <= memAddr
223 			&& (((uint8*)info.text)+info.text_size) > memAddr)
224 				|| (info.data <= memAddr
225 				&& (((uint8*)info.data)+info.data_size) > memAddr)) {
226 			// Found the image.
227 			return info.id;
228 		}
229 	}
230 
231 	return -1;
232 }
233 
234 
235 status_t
236 BImageResources::GetBitmapResource(type_code type, int32 id,
237 	BBitmap** out) const
238 {
239 	*out = NULL;
240 
241 	size_t len = 0;
242 	const void* data = LoadResource(type, id, &len);
243 
244 	if (data == NULL) {
245 		TRESPASS();
246 		return B_ERROR;
247 	}
248 
249 	BMemoryIO stream(data, len);
250 
251 	// Try to read as an archived bitmap.
252 	stream.Seek(0, SEEK_SET);
253 	BMessage archive;
254 	status_t result = archive.Unflatten(&stream);
255 	if (result != B_OK)
256 		return result;
257 
258 	*out = new BBitmap(&archive);
259 	if (*out == NULL)
260 		return B_ERROR;
261 
262 	result = (*out)->InitCheck();
263 	if (result != B_OK) {
264 		delete *out;
265 		*out = NULL;
266 	}
267 
268 	return result;
269 }
270 
271 
272 static BLocker resLock;
273 static BImageResources* resources = NULL;
274 
275 // This class is used as a static instance to delete the resources
276 // global object when the image is getting unloaded.
277 class _TTrackerCleanupResources {
278 public:
279 	_TTrackerCleanupResources()
280 	{
281 	}
282 
283 	~_TTrackerCleanupResources()
284 	{
285 		delete resources;
286 		resources = NULL;
287 	}
288 };
289 
290 
291 namespace BPrivate {
292 
293 static _TTrackerCleanupResources CleanupResources;
294 
295 BImageResources* GetTrackerResources()
296 {
297 	if (!resources) {
298 		BAutolock lock(&resLock);
299 		resources = new BImageResources(&resources);
300 	}
301 
302 	return resources;
303 }
304 
305 } // namespace BPrivate
306