xref: /haiku/src/kits/tracker/Bitmaps.cpp (revision 52f7c9389475e19fc21487b38064b4390eeb6fea)
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 		return B_ERROR;
164 	}
165 
166 	if (dest->ColorSpace() == B_RGBA32) {
167 		// fill with transparent
168 		uint8* destBits = (uint8*)dest->Bits();
169 		int32 i = 0;
170 		while (i < dest->BitsLength()) {
171 			destBits[i++] = B_TRANSPARENT_32_BIT.red;
172 			destBits[i++] = B_TRANSPARENT_32_BIT.green;
173 			destBits[i++] = B_TRANSPARENT_32_BIT.blue;
174 			destBits[i++] = B_TRANSPARENT_32_BIT.alpha;
175 		}
176 
177 		// scale and convert from B_CMAP8 to B_RGBA32
178 		if (BIconUtils::ConvertFromCMAP8((uint8*)data, size, size, size,
179 				dest) == B_OK) {
180 			return B_OK;
181 		}
182 	} else { // assume B_CMAP8
183 		// fill with transparent
184 		uint8* destBits = (uint8*)dest->Bits();
185 		for (int32 i = 0; i < dest->BitsLength(); i++)
186 			destBits[i] = B_TRANSPARENT_MAGIC_CMAP8;
187 	}
188 
189 	// import bits into the middle of dest without scaling
190 	// color space is converted from B_CMAP8 to B_RGBA32
191 	float x = roundf((dest->Bounds().Width() - size) / 2);
192 	float y = roundf((dest->Bounds().Height() - size) / 2);
193 	return dest->ImportBits(data, (int32)length, size, B_CMAP8,
194 		BPoint(0, 0), BPoint(x, y), BSize(size - 1, size - 1));
195 }
196 
197 
198 status_t
199 BImageResources::GetIconResource(int32 id, const uint8** iconData,
200 	size_t* iconSize) const
201 {
202 	// try to load vector icon data from resources
203 	size_t length = 0;
204 	const void* data = LoadResource(B_VECTOR_ICON_TYPE, id, &length);
205 	if (data == NULL)
206 		return B_ERROR;
207 
208 	*iconData = (const uint8*)data;
209 	*iconSize = length;
210 
211 	return B_OK;
212 }
213 
214 
215 image_id
216 BImageResources::find_image(void* memAddr) const
217 {
218 	image_info info;
219 	int32 cookie = 0;
220 	while (get_next_image_info(0, &cookie, &info) == B_OK) {
221 		if ((info.text <= memAddr
222 			&& (((uint8*)info.text)+info.text_size) > memAddr)
223 				|| (info.data <= memAddr
224 				&& (((uint8*)info.data)+info.data_size) > memAddr)) {
225 			// Found the image.
226 			return info.id;
227 		}
228 	}
229 
230 	return -1;
231 }
232 
233 
234 status_t
235 BImageResources::GetBitmapResource(type_code type, int32 id,
236 	BBitmap** out) const
237 {
238 	*out = NULL;
239 
240 	size_t len = 0;
241 	const void* data = LoadResource(type, id, &len);
242 
243 	if (data == NULL) {
244 		TRESPASS();
245 		return B_ERROR;
246 	}
247 
248 	BMemoryIO stream(data, len);
249 
250 	// Try to read as an archived bitmap.
251 	stream.Seek(0, SEEK_SET);
252 	BMessage archive;
253 	status_t result = archive.Unflatten(&stream);
254 	if (result != B_OK)
255 		return result;
256 
257 	*out = new BBitmap(&archive);
258 	if (*out == NULL)
259 		return B_ERROR;
260 
261 	result = (*out)->InitCheck();
262 	if (result != B_OK) {
263 		delete *out;
264 		*out = NULL;
265 	}
266 
267 	return result;
268 }
269 
270 
271 static BLocker resLock;
272 static BImageResources* resources = NULL;
273 
274 // This class is used as a static instance to delete the resources
275 // global object when the image is getting unloaded.
276 class _TTrackerCleanupResources {
277 public:
278 	_TTrackerCleanupResources()
279 	{
280 	}
281 
282 	~_TTrackerCleanupResources()
283 	{
284 		delete resources;
285 		resources = NULL;
286 	}
287 };
288 
289 
290 namespace BPrivate {
291 
292 static _TTrackerCleanupResources CleanupResources;
293 
294 BImageResources* GetTrackerResources()
295 {
296 	if (!resources) {
297 		BAutolock lock(&resLock);
298 		resources = new BImageResources(&resources);
299 	}
300 
301 	return resources;
302 }
303 
304 } // namespace BPrivate
305