* fixed a couple of remaining issues with vector icons,
there is some unfortunate code duplication in AppFileInfo, because it cannot use BMimeType/BNode alone to retrieve icons, now it works closer to the code in BIconUtils, this fixes R5 icons not displaying for other icon sizes * implemented a bilinear scaling function, I don't know if it is very fast, but I hope it is reasonable. Now that I see the results though, I wonder if R5 icons should be scaled with nearest neighbor instead... * corrected a small bug in the icon format stuff... 7 bit coords are -32-+95, not 96 * improved comment for BIconUtils function git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19302 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6f095d6a03
commit
9f5078060d
@ -27,9 +27,8 @@ class BIconUtils {
|
||||
// has either of the provided attribute names. Which icon type
|
||||
// is preferred (vector, small or large B_CMAP8 icon) depends
|
||||
// on the colorspace of the provided bitmap. If the colorspace
|
||||
// is B_CMAP8, B_CMAP8 icons are preferred. If no vector icon
|
||||
// is available, the bitmap size must match the provided
|
||||
// icon_size "size"!
|
||||
// is B_CMAP8, B_CMAP8 icons are preferred. In that case, the
|
||||
// bitmap size must also match the provided icon_size "size"!
|
||||
static status_t GetIcon(BNode* node,
|
||||
const char* vectorIconAttrName,
|
||||
const char* smallIconAttrName,
|
||||
|
@ -823,8 +823,8 @@ BAppFileInfo::SetVersionInfo(const version_info *info, version_kind kind)
|
||||
- other error codes
|
||||
*/
|
||||
status_t
|
||||
BAppFileInfo::GetIconForType(const char *type, BBitmap *icon,
|
||||
icon_size which) const
|
||||
BAppFileInfo::GetIconForType(const char* type, BBitmap* icon,
|
||||
icon_size size) const
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return B_NO_INIT;
|
||||
@ -857,7 +857,12 @@ BAppFileInfo::GetIconForType(const char *type, BBitmap *icon,
|
||||
return error;
|
||||
}
|
||||
|
||||
// no vector icon if we got this far
|
||||
// no vector icon if we got this far,
|
||||
// align size argument just in case
|
||||
if (size < B_LARGE_ICON)
|
||||
size = B_MINI_ICON;
|
||||
else
|
||||
size = B_LARGE_ICON;
|
||||
|
||||
error = B_OK;
|
||||
// set some icon size related variables
|
||||
@ -865,7 +870,7 @@ BAppFileInfo::GetIconForType(const char *type, BBitmap *icon,
|
||||
BRect bounds;
|
||||
uint32 attrType = 0;
|
||||
size_t attrSize = 0;
|
||||
switch (which) {
|
||||
switch (size) {
|
||||
case B_MINI_ICON:
|
||||
attributeString = kMiniIconAttribute;
|
||||
bounds.Set(0, 0, 15, 15);
|
||||
@ -892,21 +897,23 @@ BAppFileInfo::GetIconForType(const char *type, BBitmap *icon,
|
||||
|
||||
attribute = attributeString.String();
|
||||
|
||||
// check parameter and initialization
|
||||
if (icon->Bounds() != bounds)
|
||||
// check parameters
|
||||
// currently, scaling B_CMAP8 icons is not supported
|
||||
if (icon->ColorSpace() == B_CMAP8 && icon->Bounds() != bounds)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// read the data
|
||||
if (error == B_OK) {
|
||||
bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
|
||||
char *buffer = NULL;
|
||||
bool tempBuffer = (icon->ColorSpace() != B_CMAP8
|
||||
|| icon->Bounds() != bounds);
|
||||
uint8* buffer = NULL;
|
||||
size_t read;
|
||||
if (otherColorSpace) {
|
||||
// other color space than stored in attribute
|
||||
buffer = new(nothrow) char[attrSize];
|
||||
if (!buffer)
|
||||
if (tempBuffer) {
|
||||
// other color space or bitmap size than stored in attribute
|
||||
buffer = new(nothrow) uint8[attrSize];
|
||||
if (!buffer) {
|
||||
error = B_NO_MEMORY;
|
||||
if (error == B_OK) {
|
||||
} else {
|
||||
error = _ReadData(attribute, -1, attrType, buffer, attrSize,
|
||||
read);
|
||||
}
|
||||
@ -916,11 +923,14 @@ BAppFileInfo::GetIconForType(const char *type, BBitmap *icon,
|
||||
}
|
||||
if (error == B_OK && read != attrSize)
|
||||
error = B_ERROR;
|
||||
if (otherColorSpace) {
|
||||
if (tempBuffer) {
|
||||
// other color space than stored in attribute
|
||||
if (error == B_OK) {
|
||||
error = icon->ImportBits(buffer, attrSize, B_ANY_BYTES_PER_ROW,
|
||||
0, B_CMAP8);
|
||||
error = BIconUtils::ConvertFromCMAP8(buffer,
|
||||
(uint32)size,
|
||||
(uint32)size,
|
||||
(uint32)size,
|
||||
icon);
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <new>
|
||||
#include <fs_attr.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Node.h>
|
||||
@ -55,6 +56,13 @@ BIconUtils::GetIcon(BNode* node,
|
||||
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,
|
||||
@ -123,7 +131,9 @@ bigtime_t startTime = system_time();
|
||||
return B_BAD_VALUE;
|
||||
|
||||
uint8 buffer[attrInfo.size];
|
||||
node->ReadAttr(attrName, attrType, 0, 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();
|
||||
@ -242,6 +252,11 @@ BIconUtils::GetCMAP8Icon(BNode* node,
|
||||
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
|
||||
@ -249,11 +264,11 @@ BIconUtils::GetCMAP8Icon(BNode* node,
|
||||
uint8* buffer = NULL;
|
||||
ssize_t read;
|
||||
if (tempBuffer) {
|
||||
// other color space than stored in attribute
|
||||
// other color space or bitmap size than stored in attribute
|
||||
buffer = new(nothrow) uint8[attrSize];
|
||||
if (!buffer)
|
||||
if (!buffer) {
|
||||
ret = B_NO_MEMORY;
|
||||
if (ret == B_OK) {
|
||||
} else {
|
||||
read = node->ReadAttr(attribute, attrType, 0, buffer,
|
||||
attrSize);
|
||||
}
|
||||
@ -264,7 +279,7 @@ BIconUtils::GetCMAP8Icon(BNode* node,
|
||||
if (ret == B_OK) {
|
||||
if (read < 0)
|
||||
ret = read;
|
||||
else if (read != attrInfo.size)
|
||||
else if (read != (ssize_t)attrSize)
|
||||
ret = B_ERROR;
|
||||
}
|
||||
if (tempBuffer) {
|
||||
@ -304,6 +319,73 @@ BIconUtils::ConvertFromCMAP8(BBitmap* source, BBitmap* result)
|
||||
return ConvertFromCMAP8(src, width, height, srcBPR, result);
|
||||
}
|
||||
|
||||
// scale_bilinear
|
||||
static void
|
||||
scale_bilinear(uint8* bits, int32 srcWidth, int32 srcHeight,
|
||||
int32 dstWidth, int32 dstHeight, uint32 bpr)
|
||||
{
|
||||
// first pass: scale bottom to top
|
||||
|
||||
uint8* dst = bits + (dstHeight - 1) * bpr;
|
||||
// offset to bottom left pixel in target size
|
||||
for (int32 x = 0; x < srcWidth; x++) {
|
||||
uint8* d = dst;
|
||||
for (int32 y = dstHeight - 1; y >= 0; y--) {
|
||||
int32 lineF = y * 256 * srcHeight / (dstHeight - 1);
|
||||
int32 lineI = lineF >> 8;
|
||||
uint8 weight = (uint8)(lineF & 0xff);
|
||||
uint8* s1 = bits + lineI * bpr + 4 * x;
|
||||
if (weight == 0) {
|
||||
d[0] = s1[0];
|
||||
d[1] = s1[1];
|
||||
d[2] = s1[2];
|
||||
d[3] = s1[3];
|
||||
} else {
|
||||
uint8* s2 = s1 + bpr;
|
||||
|
||||
d[0] = (((s2[0] - s1[0]) * weight) + (s1[0] << 8)) >> 8;
|
||||
d[1] = (((s2[1] - s1[1]) * weight) + (s1[1] << 8)) >> 8;
|
||||
d[2] = (((s2[2] - s1[2]) * weight) + (s1[2] << 8)) >> 8;
|
||||
d[3] = (((s2[3] - s1[3]) * weight) + (s1[3] << 8)) >> 8;
|
||||
}
|
||||
|
||||
d -= bpr;
|
||||
}
|
||||
dst += 4;
|
||||
}
|
||||
|
||||
// second pass: scale right to left
|
||||
|
||||
dst = bits + (dstWidth - 1) * 4;
|
||||
// offset to top left pixel in target size
|
||||
for (int32 y = 0; y < dstWidth; y++) {
|
||||
uint8* d = dst;
|
||||
for (int32 x = dstWidth - 1; x >= 0; x--) {
|
||||
int32 columnF = x * 256 * srcWidth / (dstWidth - 1);
|
||||
int32 columnI = columnF >> 8;
|
||||
uint8 weight = (uint8)(columnF & 0xff);
|
||||
uint8* s1 = bits + y * bpr + 4 * columnI;
|
||||
if (weight == 0) {
|
||||
d[0] = s1[0];
|
||||
d[1] = s1[1];
|
||||
d[2] = s1[2];
|
||||
d[3] = s1[3];
|
||||
} else {
|
||||
uint8* s2 = s1 + 4;
|
||||
|
||||
d[0] = (((s2[0] - s1[0]) * weight) + (s1[0] << 8)) >> 8;
|
||||
d[1] = (((s2[1] - s1[1]) * weight) + (s1[1] << 8)) >> 8;
|
||||
d[2] = (((s2[2] - s1[2]) * weight) + (s1[2] << 8)) >> 8;
|
||||
d[3] = (((s2[3] - s1[3]) * weight) + (s1[3] << 8)) >> 8;
|
||||
}
|
||||
|
||||
d -= 4;
|
||||
}
|
||||
dst += bpr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ConvertFromCMAP8
|
||||
status_t
|
||||
BIconUtils::ConvertFromCMAP8(const uint8* src,
|
||||
@ -323,10 +405,6 @@ BIconUtils::ConvertFromCMAP8(const uint8* src,
|
||||
if (dstWidth < width || dstHeight < height) {
|
||||
// TODO: down scaling
|
||||
return B_ERROR;
|
||||
} else if (dstWidth > width || dstHeight > height) {
|
||||
// TODO: up scaling
|
||||
// (currently copies bitmap into result at left-top)
|
||||
memset(result->Bits(), 255, result->BitsLength());
|
||||
}
|
||||
|
||||
//#if __HAIKU__
|
||||
@ -361,6 +439,12 @@ memset(result->Bits(), 255, result->BitsLength());
|
||||
dst += dstBPR;
|
||||
}
|
||||
|
||||
if (dstWidth > width || dstHeight > height) {
|
||||
// up scaling
|
||||
scale_bilinear((uint8*)result->Bits(), width, height,
|
||||
dstWidth, dstHeight, dstBPR);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
|
||||
//#endif // __HAIKU__
|
||||
|
@ -49,7 +49,7 @@ write_coord(LittleEndianBuffer& buffer, float coord)
|
||||
coord = 192.0;
|
||||
|
||||
if (int(coord * 100.0) == (int)coord * 100
|
||||
&& coord >= - 32.0 && coord <= 96.0) {
|
||||
&& coord >= - 32.0 && coord <= 95.0) {
|
||||
// saving coord in 7 bit is sufficient
|
||||
uint8 value = (uint8)(coord + 32.0);
|
||||
return buffer.Write(value);
|
||||
|
Loading…
Reference in New Issue
Block a user