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 <String.h>
44#include <SupportDefs.h>
45
46#ifdef __HAIKU__
47#	include <IconUtils.h>
48#endif
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	return B_OK;
103}
104
105
106const void*
107BImageResources::LoadResource(type_code type, int32 id,
108	size_t* out_size) const
109{
110	// Serialize execution.
111	// Looks like BResources is not really thread safe. We should
112	// clean that up in the future and remove the locking from here.
113	BAutolock lock(fLock);
114	if (!lock.IsLocked())
115		return 0;
116
117	// Return the resource.  Because we never change the BResources
118	// object, the returned data will not change until TTracker is
119	// destroyed.
120	return const_cast<BResources*>(&fResources)->LoadResource(type, id,
121		out_size);
122}
123
124
125const void*
126BImageResources::LoadResource(type_code type, const char* name,
127	size_t* out_size) const
128{
129	// Serialize execution.
130	BAutolock lock(fLock);
131	if (!lock.IsLocked())
132		return NULL;
133
134	// Return the resource.  Because we never change the BResources
135	// object, the returned data will not change until TTracker is
136	// destroyed.
137	return const_cast<BResources*>(&fResources)->LoadResource(type, name,
138		out_size);
139}
140
141
142status_t
143BImageResources::GetIconResource(int32 id, icon_size size,
144	BBitmap* dest) const
145{
146	size_t length = 0;
147	const void* data;
148
149#ifdef __HAIKU__
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#endif
157
158	// fall back to R5 icon
159	if (size != B_LARGE_ICON && size != B_MINI_ICON)
160		return B_ERROR;
161
162	length = 0;
163	data = LoadResource(size == B_LARGE_ICON ? 'ICON' : 'MICN', id, &length);
164
165	if (data == NULL
166		|| length != (size_t)(size == B_LARGE_ICON ? 1024 : 256)) {
167		TRESPASS();
168		return B_ERROR;
169	}
170
171#ifdef __HAIKU__
172	if (dest->ColorSpace() != B_CMAP8) {
173		return BIconUtils::ConvertFromCMAP8((uint8*)data, size, size,
174			size, dest);
175	}
176#endif
177
178	dest->SetBits(data, (int32)length, 0, B_CMAP8);
179	return B_OK;
180}
181
182
183status_t
184BImageResources::GetIconResource(int32 id, const uint8** iconData,
185	size_t* iconSize) const
186{
187#ifdef __HAIKU__
188	// try to load vector icon data from resources
189	size_t length = 0;
190	const void* data = LoadResource(B_VECTOR_ICON_TYPE, id, &length);
191	if (data == NULL)
192		return B_ERROR;
193
194	*iconData = (const uint8*)data;
195	*iconSize = length;
196
197	return B_OK;
198#else
199	return B_ERROR;
200#endif
201}
202
203
204image_id
205BImageResources::find_image(void* memAddr) const
206{
207	image_info info;
208	int32 cookie = 0;
209	while (get_next_image_info(0, &cookie, &info) == B_OK)
210		if ((info.text <= memAddr
211			&& (((uint8*)info.text)+info.text_size) > memAddr)
212				|| (info.data <= memAddr
213				&& (((uint8*)info.data)+info.data_size) > memAddr)) {
214			// Found the image.
215			return info.id;
216		}
217
218	return -1;
219}
220
221
222status_t
223BImageResources::GetBitmapResource(type_code type, int32 id,
224	BBitmap** out) const
225{
226	*out = NULL;
227
228	size_t len = 0;
229	const void* data = LoadResource(type, id, &len);
230
231	if (data == NULL) {
232		TRESPASS();
233		return B_ERROR;
234	}
235
236	BMemoryIO stream(data, len);
237
238	// Try to read as an archived bitmap.
239	stream.Seek(0, SEEK_SET);
240	BMessage archive;
241	status_t err = archive.Unflatten(&stream);
242	if (err != B_OK)
243		return err;
244
245	*out = new BBitmap(&archive);
246	if (!*out)
247		return B_ERROR;
248
249	err = (*out)->InitCheck();
250	if (err != B_OK) {
251		delete *out;
252		*out = NULL;
253	}
254
255	return err;
256}
257
258
259static BLocker resLock;
260static BImageResources* resources = NULL;
261
262// This class is used as a static instance to delete the resources
263// global object when the image is getting unloaded.
264class _TTrackerCleanupResources {
265public:
266	_TTrackerCleanupResources() { }
267	~_TTrackerCleanupResources()
268	{
269		delete resources;
270		resources = NULL;
271	}
272};
273
274
275namespace BPrivate {
276
277static _TTrackerCleanupResources CleanupResources;
278
279
280BImageResources* GetTrackerResources()
281{
282	if (!resources) {
283		BAutolock lock(&resLock);
284		resources = new BImageResources(&resources);
285	}
286	return resources;
287}
288
289}
290