#include "Bitmaps.h"
#include "Utilities.h"
#include <Autolock.h>
#include <Bitmap.h>
#include <Debug.h>
#include <DataIO.h>
#include <File.h>
#include <IconUtils.h>
#include <String.h>
#include <SupportDefs.h>
BImageResources::BImageResources(void* memAddr)
{
image_id image = find_image(memAddr);
image_info info;
if (get_image_info(image, &info) == B_OK) {
#if _SUPPORTS_RESOURCES
BFile file(&info.name[0], B_READ_ONLY);
#else
BString name(&info.name[0]);
name += ".rsrc";
BFile file(name.String(), B_READ_ONLY);
#endif
if (file.InitCheck() == B_OK)
fResources.SetTo(&file);
}
}
BImageResources::~BImageResources()
{
}
const BResources*
BImageResources::ViewResources() const
{
if (fLock.Lock() != B_OK)
return NULL;
return &fResources;
}
BResources*
BImageResources::ViewResources()
{
if (fLock.Lock() != B_OK)
return NULL;
return &fResources;
}
status_t
BImageResources::FinishResources(BResources* res) const
{
ASSERT(res == &fResources);
if (res != &fResources)
return B_BAD_VALUE;
fLock.Unlock();
return B_OK;
}
const void*
BImageResources::LoadResource(type_code type, int32 id,
size_t* out_size) const
{
BAutolock lock(fLock);
if (!lock.IsLocked())
return 0;
return const_cast<BResources*>(&fResources)->LoadResource(type, id,
out_size);
}
const void*
BImageResources::LoadResource(type_code type, const char* name,
size_t* out_size) const
{
BAutolock lock(fLock);
if (!lock.IsLocked())
return NULL;
return const_cast<BResources*>(&fResources)->LoadResource(type, name,
out_size);
}
status_t
BImageResources::GetIconResource(int32 id, icon_size size,
BBitmap* dest) const
{
size_t length = 0;
const void* data;
data = LoadResource(B_VECTOR_ICON_TYPE, id, &length);
if (data != NULL
&& BIconUtils::GetVectorIcon((uint8*)data, length, dest) == B_OK) {
return B_OK;
}
length = 0;
size = (size == B_MINI_ICON ? B_MINI_ICON : B_LARGE_ICON);
data = LoadResource(size == B_MINI_ICON ? 'MICN' : 'ICON', id, &length);
if (data == NULL || length != (size_t)(size * size)) {
return B_ERROR;
}
if (dest->ColorSpace() == B_RGBA32) {
uint8* destBits = (uint8*)dest->Bits();
int32 i = 0;
while (i < dest->BitsLength()) {
destBits[i++] = B_TRANSPARENT_32_BIT.red;
destBits[i++] = B_TRANSPARENT_32_BIT.green;
destBits[i++] = B_TRANSPARENT_32_BIT.blue;
destBits[i++] = B_TRANSPARENT_32_BIT.alpha;
}
if (BIconUtils::ConvertFromCMAP8((uint8*)data, size, size, size,
dest) == B_OK) {
return B_OK;
}
} else {
uint8* destBits = (uint8*)dest->Bits();
for (int32 i = 0; i < dest->BitsLength(); i++)
destBits[i] = B_TRANSPARENT_MAGIC_CMAP8;
}
float x = roundf((dest->Bounds().Width() - size) / 2);
float y = roundf((dest->Bounds().Height() - size) / 2);
return dest->ImportBits(data, (int32)length, size, B_CMAP8,
BPoint(0, 0), BPoint(x, y), BSize(size - 1, size - 1));
}
status_t
BImageResources::GetIconResource(int32 id, const uint8** iconData,
size_t* iconSize) const
{
size_t length = 0;
const void* data = LoadResource(B_VECTOR_ICON_TYPE, id, &length);
if (data == NULL)
return B_ERROR;
*iconData = (const uint8*)data;
*iconSize = length;
return B_OK;
}
image_id
BImageResources::find_image(void* memAddr) const
{
image_info info;
int32 cookie = 0;
while (get_next_image_info(0, &cookie, &info) == B_OK) {
if ((info.text <= memAddr
&& (((uint8*)info.text)+info.text_size) > memAddr)
|| (info.data <= memAddr
&& (((uint8*)info.data)+info.data_size) > memAddr)) {
return info.id;
}
}
return -1;
}
status_t
BImageResources::GetBitmapResource(type_code type, int32 id,
BBitmap** out) const
{
*out = NULL;
size_t len = 0;
const void* data = LoadResource(type, id, &len);
if (data == NULL) {
TRESPASS();
return B_ERROR;
}
BMemoryIO stream(data, len);
stream.Seek(0, SEEK_SET);
BMessage archive;
status_t result = archive.Unflatten(&stream);
if (result != B_OK)
return result;
*out = new BBitmap(&archive);
if (*out == NULL)
return B_ERROR;
result = (*out)->InitCheck();
if (result != B_OK) {
delete *out;
*out = NULL;
}
return result;
}
static BLocker resLock;
static BImageResources* resources = NULL;
class _TTrackerCleanupResources {
public:
_TTrackerCleanupResources()
{
}
~_TTrackerCleanupResources()
{
delete resources;
resources = NULL;
}
};
namespace BPrivate {
static _TTrackerCleanupResources CleanupResources;
BImageResources* GetTrackerResources()
{
if (!resources) {
BAutolock lock(&resLock);
resources = new BImageResources(&resources);
}
return resources;
}
}