1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30of Be Incorporated in the United States and other countries. Other brand product
31names are registered trademarks or trademarks of their respective holders.
32All 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
51BImageResources::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
69BImageResources::~BImageResources()
70{
71}
72
73
74const BResources*
75BImageResources::ViewResources() const
76{
77	if (fLock.Lock() != B_OK)
78		return NULL;
79
80	return &fResources;
81}
82
83
84BResources*
85BImageResources::ViewResources()
86{
87	if (fLock.Lock() != B_OK)
88		return NULL;
89
90	return &fResources;
91}
92
93
94status_t
95BImageResources::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
107const void*
108BImageResources::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
126const void*
127BImageResources::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
143status_t
144BImageResources::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
198status_t
199BImageResources::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
215image_id
216BImageResources::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
234status_t
235BImageResources::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
271static BLocker resLock;
272static 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.
276class _TTrackerCleanupResources {
277public:
278	_TTrackerCleanupResources()
279	{
280	}
281
282	~_TTrackerCleanupResources()
283	{
284		delete resources;
285		resources = NULL;
286	}
287};
288
289
290namespace BPrivate {
291
292static _TTrackerCleanupResources CleanupResources;
293
294BImageResources* 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