* Added ConvertToCMAP8() bitmap variant.
* Put header guards in the system namespace. * Cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27035 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,17 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2008, Haiku. All rights reserved.
|
* Copyright 2006-2008, Haiku. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
#ifndef _ICON_UTILS_H
|
||||||
|
#define _ICON_UTILS_H
|
||||||
|
|
||||||
#ifndef ICON_UTILS_H
|
|
||||||
#define ICON_UTILS_H
|
|
||||||
|
|
||||||
#include <Mime.h>
|
#include <Mime.h>
|
||||||
|
|
||||||
class BBitmap;
|
class BBitmap;
|
||||||
class BNode;
|
class BNode;
|
||||||
|
|
||||||
|
|
||||||
// This class is a little different from many other classes.
|
// This class is a little different from many other classes.
|
||||||
// You don't create an instance of it; you just call its various
|
// You don't create an instance of it; you just call its various
|
||||||
// static member functions for utility-like operations.
|
// static member functions for utility-like operations.
|
||||||
@@ -65,6 +65,8 @@ public:
|
|||||||
// to make any sense).
|
// to make any sense).
|
||||||
static status_t ConvertFromCMAP8(BBitmap* source,
|
static status_t ConvertFromCMAP8(BBitmap* source,
|
||||||
BBitmap* result);
|
BBitmap* result);
|
||||||
|
static status_t ConvertToCMAP8(BBitmap* source,
|
||||||
|
BBitmap* result);
|
||||||
|
|
||||||
static status_t ConvertFromCMAP8(const uint8* data,
|
static status_t ConvertFromCMAP8(const uint8* data,
|
||||||
uint32 width, uint32 height,
|
uint32 width, uint32 height,
|
||||||
@@ -75,4 +77,4 @@ public:
|
|||||||
uint32 bytesPerRow, BBitmap* result);
|
uint32 bytesPerRow, BBitmap* result);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ICON_UTILS_H
|
#endif // _ICON_UTILS_H
|
||||||
|
|||||||
+335
-319
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2007, Haiku. All rights reserved.
|
* Copyright 2006-2008, Haiku. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -33,315 +33,9 @@ using namespace BPrivate::Icon;
|
|||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
|
|
||||||
|
|
||||||
// GetIcon
|
|
||||||
status_t
|
|
||||||
BIconUtils::GetIcon(BNode* node,
|
|
||||||
const char* vectorIconAttrName,
|
|
||||||
const char* smallIconAttrName,
|
|
||||||
const char* largeIconAttrName,
|
|
||||||
icon_size size,
|
|
||||||
BBitmap* result)
|
|
||||||
{
|
|
||||||
if (!result || result->InitCheck())
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
status_t ret = B_ERROR;
|
|
||||||
|
|
||||||
switch (result->ColorSpace()) {
|
|
||||||
case B_RGBA32:
|
|
||||||
case B_RGB32:
|
|
||||||
// prefer vector icon
|
|
||||||
ret = GetVectorIcon(node, vectorIconAttrName, result);
|
|
||||||
if (ret < B_OK) {
|
|
||||||
// try to fallback to B_CMAP8 icons
|
|
||||||
// (converting to B_RGBA32 is handled)
|
|
||||||
|
|
||||||
// override size
|
|
||||||
if (result->Bounds().IntegerWidth() + 1 >= 32)
|
|
||||||
size = B_LARGE_ICON;
|
|
||||||
else
|
|
||||||
size = B_MINI_ICON;
|
|
||||||
|
|
||||||
ret = GetCMAP8Icon(node,
|
|
||||||
smallIconAttrName,
|
|
||||||
largeIconAttrName,
|
|
||||||
size, result);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_CMAP8:
|
|
||||||
// prefer old B_CMAP8 icons
|
|
||||||
ret = GetCMAP8Icon(node,
|
|
||||||
smallIconAttrName,
|
|
||||||
largeIconAttrName,
|
|
||||||
size, result);
|
|
||||||
if (ret < B_OK) {
|
|
||||||
// try to fallback to vector icon
|
|
||||||
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
|
||||||
BBitmap temp(result->Bounds(),
|
|
||||||
B_BITMAP_NO_SERVER_LINK, B_RGBA32);
|
|
||||||
#else
|
|
||||||
BBitmap temp(result->Bounds(), B_RGBA32);
|
|
||||||
#endif
|
|
||||||
ret = temp.InitCheck();
|
|
||||||
if (ret < B_OK)
|
|
||||||
break;
|
|
||||||
ret = GetVectorIcon(node, vectorIconAttrName, &temp);
|
|
||||||
if (ret < B_OK)
|
|
||||||
break;
|
|
||||||
uint32 width = temp.Bounds().IntegerWidth() + 1;
|
|
||||||
uint32 height = temp.Bounds().IntegerHeight() + 1;
|
|
||||||
uint32 bytesPerRow = temp.BytesPerRow();
|
|
||||||
ret = ConvertToCMAP8((uint8*)temp.Bits(),
|
|
||||||
width, height, bytesPerRow, result);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("BIconUtils::GetIcon() - unsupported colorspace\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
// GetVectorIcon
|
|
||||||
status_t
|
|
||||||
BIconUtils::GetVectorIcon(BNode* node, const char* attrName,
|
|
||||||
BBitmap* result)
|
|
||||||
{
|
|
||||||
if (!node || node->InitCheck() < B_OK || !attrName)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
#if TIME_VECTOR_ICONS
|
|
||||||
bigtime_t startTime = system_time();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// get the attribute info and check type and size of the attr contents
|
|
||||||
attr_info attrInfo;
|
|
||||||
status_t ret = node->GetAttrInfo(attrName, &attrInfo);
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
type_code attrType = B_VECTOR_ICON_TYPE;
|
|
||||||
|
|
||||||
if (attrInfo.type != attrType)
|
|
||||||
return B_BAD_TYPE;
|
|
||||||
|
|
||||||
// chicken out on unrealisticly large attributes
|
|
||||||
if (attrInfo.size > 16 * 1024)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
uint8 buffer[attrInfo.size];
|
|
||||||
ssize_t read = node->ReadAttr(attrName, attrType, 0, buffer, attrInfo.size);
|
|
||||||
if (read != attrInfo.size)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
#if TIME_VECTOR_ICONS
|
|
||||||
bigtime_t importTime = system_time();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = GetVectorIcon(buffer, attrInfo.size, result);
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
#if TIME_VECTOR_ICONS
|
|
||||||
bigtime_t finishTime = system_time();
|
|
||||||
printf("read: %lld, import: %lld\n", importTime - startTime, finishTime - importTime);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetVectorIcon
|
|
||||||
status_t
|
|
||||||
BIconUtils::GetVectorIcon(const uint8* buffer, size_t size,
|
|
||||||
BBitmap* result)
|
|
||||||
{
|
|
||||||
if (!result)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
status_t ret = result->InitCheck();
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
BBitmap* temp = result;
|
|
||||||
ObjectDeleter<BBitmap> deleter;
|
|
||||||
|
|
||||||
if (result->ColorSpace() != B_RGBA32 && result->ColorSpace() != B_RGB32) {
|
|
||||||
temp = new (nothrow) BBitmap(result->Bounds(),
|
|
||||||
B_BITMAP_NO_SERVER_LINK, B_RGBA32);
|
|
||||||
deleter.SetTo(temp);
|
|
||||||
if (!temp || temp->InitCheck() != B_OK)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
Icon icon;
|
|
||||||
ret = icon.InitCheck();
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
FlatIconImporter importer;
|
|
||||||
ret = importer.Import(&icon, const_cast<uint8*>(buffer), size);
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
IconRenderer renderer(temp);
|
|
||||||
renderer.SetIcon(&icon);
|
|
||||||
renderer.SetScale((temp->Bounds().Width() + 1.0) / 64.0);
|
|
||||||
renderer.Render();
|
|
||||||
|
|
||||||
if (temp != result) {
|
|
||||||
uint8* src = (uint8*)temp->Bits();
|
|
||||||
uint32 width = temp->Bounds().IntegerWidth() + 1;
|
|
||||||
uint32 height = temp->Bounds().IntegerHeight() + 1;
|
|
||||||
uint32 srcBPR = temp->BytesPerRow();
|
|
||||||
ret = ConvertToCMAP8(src, width, height, srcBPR, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: would be nice to get rid of this
|
|
||||||
// (B_RGBA32_PREMULTIPLIED or better yet, new blending_mode)
|
|
||||||
// NOTE: probably not necessary only because
|
|
||||||
// transparent colors are "black" in all existing icons
|
|
||||||
// lighter transparent colors should be too dark if
|
|
||||||
// app_server uses correct blending
|
|
||||||
// renderer.Demultiply();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BIconUtils::GetCMAP8Icon(BNode* node,
|
|
||||||
const char* smallIconAttrName,
|
|
||||||
const char* largeIconAttrName,
|
|
||||||
icon_size size,
|
|
||||||
BBitmap* icon)
|
|
||||||
{
|
|
||||||
// check parameters and initialization
|
|
||||||
if (!icon || icon->InitCheck() != B_OK
|
|
||||||
|| !node || node->InitCheck() != B_OK
|
|
||||||
|| !smallIconAttrName || !largeIconAttrName)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
status_t ret = B_OK;
|
|
||||||
|
|
||||||
// NOTE: this might be changed if other icon
|
|
||||||
// sizes are supported in B_CMAP8 attributes,
|
|
||||||
// but this is currently not the case, so we
|
|
||||||
// relax the requirement to pass an icon
|
|
||||||
// of just the right size
|
|
||||||
if (size < B_LARGE_ICON)
|
|
||||||
size = B_MINI_ICON;
|
|
||||||
else
|
|
||||||
size = B_LARGE_ICON;
|
|
||||||
|
|
||||||
// set some icon size related variables
|
|
||||||
const char *attribute = NULL;
|
|
||||||
BRect bounds;
|
|
||||||
uint32 attrType = 0;
|
|
||||||
size_t attrSize = 0;
|
|
||||||
switch (size) {
|
|
||||||
case B_MINI_ICON:
|
|
||||||
attribute = smallIconAttrName;
|
|
||||||
bounds.Set(0, 0, 15, 15);
|
|
||||||
attrType = B_MINI_ICON_TYPE;
|
|
||||||
attrSize = 16 * 16;
|
|
||||||
break;
|
|
||||||
case B_LARGE_ICON:
|
|
||||||
attribute = largeIconAttrName;
|
|
||||||
bounds.Set(0, 0, 31, 31);
|
|
||||||
attrType = B_LARGE_ICON_TYPE;
|
|
||||||
attrSize = 32 * 32;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// can not happen, see above
|
|
||||||
ret = B_BAD_VALUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the attribute info and check type and size of the attr contents
|
|
||||||
attr_info attrInfo;
|
|
||||||
if (ret == B_OK)
|
|
||||||
ret = node->GetAttrInfo(attribute, &attrInfo);
|
|
||||||
if (ret == B_OK && attrInfo.type != attrType)
|
|
||||||
ret = B_BAD_TYPE;
|
|
||||||
if (ret == B_OK && attrInfo.size != attrSize)
|
|
||||||
ret = B_BAD_DATA;
|
|
||||||
|
|
||||||
// check parameters
|
|
||||||
// currently, scaling B_CMAP8 icons is not supported
|
|
||||||
if (icon->ColorSpace() == B_CMAP8 && icon->Bounds() != bounds)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// read the attribute
|
|
||||||
if (ret == B_OK) {
|
|
||||||
bool tempBuffer = (icon->ColorSpace() != B_CMAP8
|
|
||||||
|| icon->Bounds() != bounds);
|
|
||||||
uint8* buffer = NULL;
|
|
||||||
ssize_t read;
|
|
||||||
if (tempBuffer) {
|
|
||||||
// other color space or bitmap size than stored in attribute
|
|
||||||
buffer = new(nothrow) uint8[attrSize];
|
|
||||||
if (!buffer) {
|
|
||||||
ret = B_NO_MEMORY;
|
|
||||||
} else {
|
|
||||||
read = node->ReadAttr(attribute, attrType, 0, buffer,
|
|
||||||
attrSize);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
read = node->ReadAttr(attribute, attrType, 0, icon->Bits(),
|
|
||||||
attrSize);
|
|
||||||
}
|
|
||||||
if (ret == B_OK) {
|
|
||||||
if (read < 0)
|
|
||||||
ret = read;
|
|
||||||
else if (read != (ssize_t)attrSize)
|
|
||||||
ret = B_ERROR;
|
|
||||||
}
|
|
||||||
if (tempBuffer) {
|
|
||||||
// other color space than stored in attribute
|
|
||||||
if (ret == B_OK) {
|
|
||||||
ret = ConvertFromCMAP8(buffer,
|
|
||||||
(uint32)size, (uint32)size,
|
|
||||||
(uint32)size, icon);
|
|
||||||
}
|
|
||||||
delete[] buffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
// ConvertFromCMAP8
|
|
||||||
status_t
|
|
||||||
BIconUtils::ConvertFromCMAP8(BBitmap* source, BBitmap* result)
|
|
||||||
{
|
|
||||||
if (!source)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
status_t ret = source->InitCheck();
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (source->ColorSpace() != B_CMAP8)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
uint8* src = (uint8*)source->Bits();
|
|
||||||
uint32 srcBPR = source->BytesPerRow();
|
|
||||||
uint32 width = source->Bounds().IntegerWidth() + 1;
|
|
||||||
uint32 height = source->Bounds().IntegerHeight() + 1;
|
|
||||||
|
|
||||||
return ConvertFromCMAP8(src, width, height, srcBPR, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// scale_bilinear
|
|
||||||
static void
|
static void
|
||||||
scale_bilinear(uint8* bits, int32 srcWidth, int32 srcHeight,
|
scale_bilinear(uint8* bits, int32 srcWidth, int32 srcHeight, int32 dstWidth,
|
||||||
int32 dstWidth, int32 dstHeight, uint32 bpr)
|
int32 dstHeight, uint32 bpr)
|
||||||
{
|
{
|
||||||
// first pass: scale bottom to top
|
// first pass: scale bottom to top
|
||||||
|
|
||||||
@@ -405,11 +99,332 @@ scale_bilinear(uint8* bits, int32 srcWidth, int32 srcHeight,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ConvertFromCMAP8
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BIconUtils::ConvertFromCMAP8(const uint8* src,
|
BIconUtils::GetIcon(BNode* node, const char* vectorIconAttrName,
|
||||||
uint32 width, uint32 height, uint32 srcBPR,
|
const char* smallIconAttrName, const char* largeIconAttrName,
|
||||||
BBitmap* result)
|
icon_size size, BBitmap* result)
|
||||||
|
{
|
||||||
|
if (!result || result->InitCheck())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
status_t ret = B_ERROR;
|
||||||
|
|
||||||
|
switch (result->ColorSpace()) {
|
||||||
|
case B_RGBA32:
|
||||||
|
case B_RGB32:
|
||||||
|
// prefer vector icon
|
||||||
|
ret = GetVectorIcon(node, vectorIconAttrName, result);
|
||||||
|
if (ret < B_OK) {
|
||||||
|
// try to fallback to B_CMAP8 icons
|
||||||
|
// (converting to B_RGBA32 is handled)
|
||||||
|
|
||||||
|
// override size
|
||||||
|
if (result->Bounds().IntegerWidth() + 1 >= 32)
|
||||||
|
size = B_LARGE_ICON;
|
||||||
|
else
|
||||||
|
size = B_MINI_ICON;
|
||||||
|
|
||||||
|
ret = GetCMAP8Icon(node, smallIconAttrName, largeIconAttrName,
|
||||||
|
size, result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_CMAP8:
|
||||||
|
// prefer old B_CMAP8 icons
|
||||||
|
ret = GetCMAP8Icon(node, smallIconAttrName, largeIconAttrName,
|
||||||
|
size, result);
|
||||||
|
if (ret < B_OK) {
|
||||||
|
// try to fallback to vector icon
|
||||||
|
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
||||||
|
BBitmap temp(result->Bounds(), B_BITMAP_NO_SERVER_LINK,
|
||||||
|
B_RGBA32);
|
||||||
|
#else
|
||||||
|
BBitmap temp(result->Bounds(), B_RGBA32);
|
||||||
|
#endif
|
||||||
|
ret = temp.InitCheck();
|
||||||
|
if (ret < B_OK)
|
||||||
|
break;
|
||||||
|
ret = GetVectorIcon(node, vectorIconAttrName, &temp);
|
||||||
|
if (ret < B_OK)
|
||||||
|
break;
|
||||||
|
uint32 width = temp.Bounds().IntegerWidth() + 1;
|
||||||
|
uint32 height = temp.Bounds().IntegerHeight() + 1;
|
||||||
|
uint32 bytesPerRow = temp.BytesPerRow();
|
||||||
|
ret = ConvertToCMAP8((uint8*)temp.Bits(), width, height,
|
||||||
|
bytesPerRow, result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("BIconUtils::GetIcon() - unsupported colorspace\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BIconUtils::GetVectorIcon(BNode* node, const char* attrName, BBitmap* result)
|
||||||
|
{
|
||||||
|
if (!node || node->InitCheck() < B_OK || !attrName)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
#if TIME_VECTOR_ICONS
|
||||||
|
bigtime_t startTime = system_time();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// get the attribute info and check type and size of the attr contents
|
||||||
|
attr_info attrInfo;
|
||||||
|
status_t ret = node->GetAttrInfo(attrName, &attrInfo);
|
||||||
|
if (ret < B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
type_code attrType = B_VECTOR_ICON_TYPE;
|
||||||
|
|
||||||
|
if (attrInfo.type != attrType)
|
||||||
|
return B_BAD_TYPE;
|
||||||
|
|
||||||
|
// chicken out on unrealisticly large attributes
|
||||||
|
if (attrInfo.size > 16 * 1024)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
uint8 buffer[attrInfo.size];
|
||||||
|
ssize_t read = node->ReadAttr(attrName, attrType, 0, buffer, attrInfo.size);
|
||||||
|
if (read != attrInfo.size)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
#if TIME_VECTOR_ICONS
|
||||||
|
bigtime_t importTime = system_time();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = GetVectorIcon(buffer, attrInfo.size, result);
|
||||||
|
if (ret < B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
#if TIME_VECTOR_ICONS
|
||||||
|
bigtime_t finishTime = system_time();
|
||||||
|
printf("read: %lld, import: %lld\n", importTime - startTime, finishTime - importTime);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BIconUtils::GetVectorIcon(const uint8* buffer, size_t size, BBitmap* result)
|
||||||
|
{
|
||||||
|
if (!result)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
status_t ret = result->InitCheck();
|
||||||
|
if (ret < B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
BBitmap* temp = result;
|
||||||
|
ObjectDeleter<BBitmap> deleter;
|
||||||
|
|
||||||
|
if (result->ColorSpace() != B_RGBA32 && result->ColorSpace() != B_RGB32) {
|
||||||
|
temp = new (nothrow) BBitmap(result->Bounds(),
|
||||||
|
B_BITMAP_NO_SERVER_LINK, B_RGBA32);
|
||||||
|
deleter.SetTo(temp);
|
||||||
|
if (!temp || temp->InitCheck() != B_OK)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
Icon icon;
|
||||||
|
ret = icon.InitCheck();
|
||||||
|
if (ret < B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
FlatIconImporter importer;
|
||||||
|
ret = importer.Import(&icon, const_cast<uint8*>(buffer), size);
|
||||||
|
if (ret < B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
IconRenderer renderer(temp);
|
||||||
|
renderer.SetIcon(&icon);
|
||||||
|
renderer.SetScale((temp->Bounds().Width() + 1.0) / 64.0);
|
||||||
|
renderer.Render();
|
||||||
|
|
||||||
|
if (temp != result) {
|
||||||
|
uint8* src = (uint8*)temp->Bits();
|
||||||
|
uint32 width = temp->Bounds().IntegerWidth() + 1;
|
||||||
|
uint32 height = temp->Bounds().IntegerHeight() + 1;
|
||||||
|
uint32 srcBPR = temp->BytesPerRow();
|
||||||
|
ret = ConvertToCMAP8(src, width, height, srcBPR, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: would be nice to get rid of this
|
||||||
|
// (B_RGBA32_PREMULTIPLIED or better yet, new blending_mode)
|
||||||
|
// NOTE: probably not necessary only because
|
||||||
|
// transparent colors are "black" in all existing icons
|
||||||
|
// lighter transparent colors should be too dark if
|
||||||
|
// app_server uses correct blending
|
||||||
|
// renderer.Demultiply();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BIconUtils::GetCMAP8Icon(BNode* node, const char* smallIconAttrName,
|
||||||
|
const char* largeIconAttrName, icon_size size, BBitmap* icon)
|
||||||
|
{
|
||||||
|
// check parameters and initialization
|
||||||
|
if (!icon || icon->InitCheck() != B_OK
|
||||||
|
|| !node || node->InitCheck() != B_OK
|
||||||
|
|| !smallIconAttrName || !largeIconAttrName)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
status_t ret = B_OK;
|
||||||
|
|
||||||
|
// NOTE: this might be changed if other icon
|
||||||
|
// sizes are supported in B_CMAP8 attributes,
|
||||||
|
// but this is currently not the case, so we
|
||||||
|
// relax the requirement to pass an icon
|
||||||
|
// of just the right size
|
||||||
|
if (size < B_LARGE_ICON)
|
||||||
|
size = B_MINI_ICON;
|
||||||
|
else
|
||||||
|
size = B_LARGE_ICON;
|
||||||
|
|
||||||
|
// set some icon size related variables
|
||||||
|
const char *attribute = NULL;
|
||||||
|
BRect bounds;
|
||||||
|
uint32 attrType = 0;
|
||||||
|
size_t attrSize = 0;
|
||||||
|
switch (size) {
|
||||||
|
case B_MINI_ICON:
|
||||||
|
attribute = smallIconAttrName;
|
||||||
|
bounds.Set(0, 0, 15, 15);
|
||||||
|
attrType = B_MINI_ICON_TYPE;
|
||||||
|
attrSize = 16 * 16;
|
||||||
|
break;
|
||||||
|
case B_LARGE_ICON:
|
||||||
|
attribute = largeIconAttrName;
|
||||||
|
bounds.Set(0, 0, 31, 31);
|
||||||
|
attrType = B_LARGE_ICON_TYPE;
|
||||||
|
attrSize = 32 * 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// can not happen, see above
|
||||||
|
ret = B_BAD_VALUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the attribute info and check type and size of the attr contents
|
||||||
|
attr_info attrInfo;
|
||||||
|
if (ret == B_OK)
|
||||||
|
ret = node->GetAttrInfo(attribute, &attrInfo);
|
||||||
|
if (ret == B_OK && attrInfo.type != attrType)
|
||||||
|
ret = B_BAD_TYPE;
|
||||||
|
if (ret == B_OK && attrInfo.size != attrSize)
|
||||||
|
ret = B_BAD_DATA;
|
||||||
|
|
||||||
|
// check parameters
|
||||||
|
// currently, scaling B_CMAP8 icons is not supported
|
||||||
|
if (icon->ColorSpace() == B_CMAP8 && icon->Bounds() != bounds)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// read the attribute
|
||||||
|
if (ret == B_OK) {
|
||||||
|
bool tempBuffer = (icon->ColorSpace() != B_CMAP8
|
||||||
|
|| icon->Bounds() != bounds);
|
||||||
|
uint8* buffer = NULL;
|
||||||
|
ssize_t read;
|
||||||
|
if (tempBuffer) {
|
||||||
|
// other color space or bitmap size than stored in attribute
|
||||||
|
buffer = new(nothrow) uint8[attrSize];
|
||||||
|
if (!buffer) {
|
||||||
|
ret = B_NO_MEMORY;
|
||||||
|
} else {
|
||||||
|
read = node->ReadAttr(attribute, attrType, 0, buffer, attrSize);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
read = node->ReadAttr(attribute, attrType, 0, icon->Bits(),
|
||||||
|
attrSize);
|
||||||
|
}
|
||||||
|
if (ret == B_OK) {
|
||||||
|
if (read < 0)
|
||||||
|
ret = read;
|
||||||
|
else if (read != (ssize_t)attrSize)
|
||||||
|
ret = B_ERROR;
|
||||||
|
}
|
||||||
|
if (tempBuffer) {
|
||||||
|
// other color space than stored in attribute
|
||||||
|
if (ret == B_OK) {
|
||||||
|
ret = ConvertFromCMAP8(buffer, (uint32)size, (uint32)size,
|
||||||
|
(uint32)size, icon);
|
||||||
|
}
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BIconUtils::ConvertFromCMAP8(BBitmap* source, BBitmap* result)
|
||||||
|
{
|
||||||
|
if (source == NULL || source->ColorSpace() != B_CMAP8)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
status_t status = source->InitCheck();
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = result->InitCheck();
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
uint8* src = (uint8*)source->Bits();
|
||||||
|
uint32 srcBPR = source->BytesPerRow();
|
||||||
|
uint32 width = source->Bounds().IntegerWidth() + 1;
|
||||||
|
uint32 height = source->Bounds().IntegerHeight() + 1;
|
||||||
|
|
||||||
|
return ConvertFromCMAP8(src, width, height, srcBPR, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BIconUtils::ConvertToCMAP8(BBitmap* source, BBitmap* result)
|
||||||
|
{
|
||||||
|
if (source == NULL || source->ColorSpace() != B_RGBA32
|
||||||
|
|| result->ColorSpace() != B_CMAP8)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
status_t status = source->InitCheck();
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = result->InitCheck();
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
uint8* src = (uint8*)source->Bits();
|
||||||
|
uint32 srcBPR = source->BytesPerRow();
|
||||||
|
uint32 width = source->Bounds().IntegerWidth() + 1;
|
||||||
|
uint32 height = source->Bounds().IntegerHeight() + 1;
|
||||||
|
|
||||||
|
return ConvertToCMAP8(src, width, height, srcBPR, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height,
|
||||||
|
uint32 srcBPR, BBitmap* result)
|
||||||
{
|
{
|
||||||
if (!src || !result || srcBPR == 0)
|
if (!src || !result || srcBPR == 0)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -460,8 +475,8 @@ BIconUtils::ConvertFromCMAP8(const uint8* src,
|
|||||||
|
|
||||||
if (dstWidth > width || dstHeight > height) {
|
if (dstWidth > width || dstHeight > height) {
|
||||||
// up scaling
|
// up scaling
|
||||||
scale_bilinear((uint8*)result->Bits(), width, height,
|
scale_bilinear((uint8*)result->Bits(), width, height, dstWidth,
|
||||||
dstWidth, dstHeight, dstBPR);
|
dstHeight, dstBPR);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -469,11 +484,10 @@ BIconUtils::ConvertFromCMAP8(const uint8* src,
|
|||||||
//#endif // __HAIKU__
|
//#endif // __HAIKU__
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertToCMAP8
|
|
||||||
status_t
|
status_t
|
||||||
BIconUtils::ConvertToCMAP8(const uint8* src,
|
BIconUtils::ConvertToCMAP8(const uint8* src, uint32 width, uint32 height,
|
||||||
uint32 width, uint32 height, uint32 srcBPR,
|
uint32 srcBPR, BBitmap* result)
|
||||||
BBitmap* result)
|
|
||||||
{
|
{
|
||||||
if (!src || !result || srcBPR == 0)
|
if (!src || !result || srcBPR == 0)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -534,8 +548,10 @@ memset(result->Bits(), 255, result->BitsLength());
|
|||||||
//#endif // __HAIKU__
|
//#endif // __HAIKU__
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - forbidden
|
// #pragma mark - forbidden
|
||||||
|
|
||||||
|
|
||||||
BIconUtils::BIconUtils() {}
|
BIconUtils::BIconUtils() {}
|
||||||
BIconUtils::~BIconUtils() {}
|
BIconUtils::~BIconUtils() {}
|
||||||
BIconUtils::BIconUtils(const BIconUtils&) {}
|
BIconUtils::BIconUtils(const BIconUtils&) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user