diff --git a/src/libs/icon/IconUtils.cpp b/src/libs/icon/IconUtils.cpp index b8293ad5f3..f009ece023 100644 --- a/src/libs/icon/IconUtils.cpp +++ b/src/libs/icon/IconUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006-2013, Haiku. All rights reserved. + * Copyright 2006-2014 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -27,15 +27,20 @@ #include "FlatIconImporter.h" #include "MessageImporter.h" + #ifndef HAIKU_TARGET_PLATFORM_HAIKU # define B_MINI_ICON_TYPE 'MICN' # define B_LARGE_ICON_TYPE 'ICON' #endif + _USING_ICON_NAMESPACE; using std::nothrow; +// #pragma mark - Scaling functions + + static void scale_bilinear(uint8* bits, int32 srcWidth, int32 srcHeight, int32 dstWidth, int32 dstHeight, uint32 bpr) @@ -172,13 +177,13 @@ scale2x(const uint8* srcBits, uint8* dstBits, int32 srcWidth, int32 srcHeight, /* * This implements the AdvanceMAME Scale2x algorithm found on: * http://scale2x.sourceforge.net/ - * + * * It is an incredibly simple and powerful image doubling routine that does * an astonishing job of doubling game graphic data while interpolating out * the jaggies. * * Derived from the (public domain) SDL version of the library by Pete - * Shinners + * Shinners. */ // Assume that both src and dst are 4 BPP (B_RGBA32) @@ -216,13 +221,13 @@ scale3x(const uint8* srcBits, uint8* dstBits, int32 srcWidth, int32 srcHeight, /* * This implements the AdvanceMAME Scale3x algorithm found on: * http://scale2x.sourceforge.net/ - * + * * It is an incredibly simple and powerful image tripling routine that does * an astonishing job of tripling game graphic data while interpolating out * the jaggies. * * Derived from the (public domain) SDL version of the library by Pete - * Shinners + * Shinners. */ // Assume that both src and dst are 4 BPP (B_RGBA32) @@ -292,91 +297,95 @@ scale4x(const uint8* srcBits, uint8* dstBits, int32 srcWidth, int32 srcHeight, } -// #pragma mark - +// #pragma mark - GetIcon() status_t BIconUtils::GetIcon(BNode* node, const char* vectorIconAttrName, const char* smallIconAttrName, const char* largeIconAttrName, - icon_size size, BBitmap* result) + icon_size which, BBitmap* icon) { - if (!result || result->InitCheck()) + if (icon == NULL || icon->InitCheck() != B_OK) return B_BAD_VALUE; - status_t ret = B_ERROR; - - switch (result->ColorSpace()) { + status_t result = B_ERROR; + switch (icon->ColorSpace()) { case B_RGBA32: case B_RGB32: // prefer vector icon - ret = GetVectorIcon(node, vectorIconAttrName, result); - if (ret < B_OK) { + result = GetVectorIcon(node, vectorIconAttrName, icon); + if (result != 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; + if (icon->Bounds().IntegerWidth() + 1 >= 32) + which = B_LARGE_ICON; else - size = B_MINI_ICON; + which = B_MINI_ICON; - ret = GetCMAP8Icon(node, smallIconAttrName, largeIconAttrName, - size, result); + result = GetCMAP8Icon(node, smallIconAttrName, largeIconAttrName, + which, icon); } break; case B_CMAP8: // prefer old B_CMAP8 icons - ret = GetCMAP8Icon(node, smallIconAttrName, largeIconAttrName, - size, result); - if (ret < B_OK) { + result = GetCMAP8Icon(node, smallIconAttrName, largeIconAttrName, + which, icon); + if (result != B_OK) { // try to fallback to vector icon #ifdef HAIKU_TARGET_PLATFORM_HAIKU - BBitmap temp(result->Bounds(), B_BITMAP_NO_SERVER_LINK, + BBitmap temp(icon->Bounds(), B_BITMAP_NO_SERVER_LINK, B_RGBA32); #else - BBitmap temp(result->Bounds(), B_RGBA32); + BBitmap temp(icon->Bounds(), B_RGBA32); #endif - ret = temp.InitCheck(); - if (ret < B_OK) + result = temp.InitCheck(); + if (result != B_OK) break; - ret = GetVectorIcon(node, vectorIconAttrName, &temp); - if (ret < B_OK) + + result = GetVectorIcon(node, vectorIconAttrName, &temp); + if (result != 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); + result = ConvertToCMAP8((uint8*)temp.Bits(), width, height, + bytesPerRow, icon); } break; + default: printf("BIconUtils::GetIcon() - unsupported colorspace\n"); break; } - return ret; + return result; } -// #pragma mark - +// #pragma mark - GetVectorIcon() status_t -BIconUtils::GetVectorIcon(BNode* node, const char* attrName, BBitmap* result) +BIconUtils::GetVectorIcon(BNode* node, const char* attrName, BBitmap* icon) { - if (!node || node->InitCheck() < B_OK || !attrName) + if (node == NULL || node->InitCheck() != B_OK || attrName == NULL + || *attrName == '\0') { return B_BAD_VALUE; + } #if TIME_VECTOR_ICONS -bigtime_t startTime = system_time(); + 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; + status_t result = node->GetAttrInfo(attrName, &attrInfo); + if (result != B_OK) + return result; type_code attrType = B_VECTOR_ICON_TYPE; @@ -399,16 +408,17 @@ bigtime_t startTime = system_time(); return B_ERROR; #if TIME_VECTOR_ICONS -bigtime_t importTime = system_time(); + bigtime_t importTime = system_time(); #endif - ret = GetVectorIcon(buffer, attrInfo.size, result); - if (ret < B_OK) - return ret; + result = GetVectorIcon(buffer, attrInfo.size, icon); + if (result != B_OK) + return result; #if TIME_VECTOR_ICONS -bigtime_t finishTime = system_time(); -printf("read: %lld, import: %lld\n", importTime - startTime, finishTime - importTime); + bigtime_t finishTime = system_time(); + printf("read: %lld, import: %lld\n", importTime - startTime, + finishTime - importTime); #endif return B_OK; @@ -416,53 +426,53 @@ printf("read: %lld, import: %lld\n", importTime - startTime, finishTime - import status_t -BIconUtils::GetVectorIcon(const uint8* buffer, size_t size, BBitmap* result) +BIconUtils::GetVectorIcon(const uint8* buffer, size_t size, BBitmap* icon) { - if (!result) + if (icon == NULL) return B_BAD_VALUE; - status_t ret = result->InitCheck(); - if (ret < B_OK) - return ret; + status_t result = icon->InitCheck(); + if (result != B_OK) + return result; - BBitmap* temp = result; + BBitmap* temp = icon; ObjectDeleter deleter; - if (result->ColorSpace() != B_RGBA32 && result->ColorSpace() != B_RGB32) { - temp = new (nothrow) BBitmap(result->Bounds(), + if (icon->ColorSpace() != B_RGBA32 && icon->ColorSpace() != B_RGB32) { + temp = new (nothrow) BBitmap(icon->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; + Icon vector; + result = vector.InitCheck(); + if (result != B_OK) + return result; FlatIconImporter importer; - ret = importer.Import(&icon, const_cast(buffer), size); - if (ret < B_OK) { + result = importer.Import(&vector, const_cast(buffer), size); + if (result != B_OK) { // try the message based format used by Icon-O-Matic MessageImporter messageImporter; BMemoryIO memoryIO(const_cast(buffer), size); - ret = messageImporter.Import(&icon, &memoryIO); - if (ret < B_OK) - return ret; + result = messageImporter.Import(&vector, &memoryIO); + if (result != B_OK) + return result; } IconRenderer renderer(temp); - renderer.SetIcon(&icon); + renderer.SetIcon(&vector); renderer.SetScale((temp->Bounds().Width() + 1.0) / 64.0); renderer.Render(); - if (temp != result) { + if (temp != icon) { 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); + result = ConvertToCMAP8(src, width, height, srcBPR, icon); } // TODO: would be nice to get rid of this @@ -471,69 +481,74 @@ BIconUtils::GetVectorIcon(const uint8* buffer, size_t size, BBitmap* result) // transparent colors are "black" in all existing icons // lighter transparent colors should be too dark if // app_server uses correct blending -// renderer.Demultiply(); + //renderer.Demultiply(); - return ret; + return result; } -// #pragma mark - +// #pragma mark - GetCMAP8Icon() status_t BIconUtils::GetCMAP8Icon(BNode* node, const char* smallIconAttrName, - const char* largeIconAttrName, icon_size size, BBitmap* icon) + const char* largeIconAttrName, icon_size which, BBitmap* icon) { // check parameters and initialization - if (!icon || icon->InitCheck() != B_OK - || !node || node->InitCheck() != B_OK - || !smallIconAttrName || !largeIconAttrName) + if (icon == NULL || icon->InitCheck() != B_OK + || node == NULL || node->InitCheck() != B_OK + || smallIconAttrName == NULL || largeIconAttrName == NULL) { return B_BAD_VALUE; + } - status_t ret = B_OK; + status_t result = 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; + if (which < B_LARGE_ICON) + which = B_MINI_ICON; else - size = B_LARGE_ICON; + which = B_LARGE_ICON; // set some icon size related variables - const char *attribute = NULL; + const char* attribute = NULL; BRect bounds; uint32 attrType = 0; - size_t attrSize = 0; - switch (size) { + off_t attrSize = 0; + switch (which) { 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; + result = 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; + if (result == B_OK) + result = node->GetAttrInfo(attribute, &attrInfo); + + if (result == B_OK && attrInfo.type != attrType) + result = B_BAD_TYPE; + + if (result == B_OK && attrInfo.size != attrSize) + result = B_BAD_DATA; // check parameters // currently, scaling B_CMAP8 icons is not supported @@ -541,113 +556,116 @@ BIconUtils::GetCMAP8Icon(BNode* node, const char* smallIconAttrName, return B_BAD_VALUE; // read the attribute - if (ret == B_OK) { - bool tempBuffer = (icon->ColorSpace() != B_CMAP8 + if (result == B_OK) { + bool useBuffer = (icon->ColorSpace() != B_CMAP8 || icon->Bounds() != bounds); uint8* buffer = NULL; ssize_t read; - if (tempBuffer) { + if (useBuffer) { // other color space or bitmap size than stored in attribute buffer = new(nothrow) uint8[attrSize]; - if (!buffer) { - ret = B_NO_MEMORY; - } else { + if (buffer == NULL) + result = 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 (result == B_OK) { if (read < 0) - ret = read; + result = read; else if (read != (ssize_t)attrSize) - ret = B_ERROR; + result = B_ERROR; } - if (tempBuffer) { + + if (useBuffer) { // other color space than stored in attribute - if (ret == B_OK) { - ret = ConvertFromCMAP8(buffer, (uint32)size, (uint32)size, - (uint32)size, icon); + if (result == B_OK) { + result = ConvertFromCMAP8(buffer, (uint32)which, (uint32)which, + (uint32)which, icon); } delete[] buffer; } } - return ret; + + return result; } -// #pragma mark - +// #pragma mark - ConvertFromCMAP8() and ConvertToCMAP8() status_t -BIconUtils::ConvertFromCMAP8(BBitmap* source, BBitmap* result) +BIconUtils::ConvertFromCMAP8(BBitmap* source, BBitmap* destination) { if (source == NULL || source->ColorSpace() != B_CMAP8) return B_BAD_VALUE; - status_t status = source->InitCheck(); - if (status < B_OK) - return status; + status_t result = source->InitCheck(); + if (result != B_OK) + return result; - status = result->InitCheck(); - if (status < B_OK) - return status; + result = destination->InitCheck(); + if (result != B_OK) + return result; 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); + return ConvertFromCMAP8(src, width, height, srcBPR, destination); } status_t -BIconUtils::ConvertToCMAP8(BBitmap* source, BBitmap* result) +BIconUtils::ConvertToCMAP8(BBitmap* source, BBitmap* destination) { if (source == NULL || source->ColorSpace() != B_RGBA32 - || result->ColorSpace() != B_CMAP8) + || destination->ColorSpace() != B_CMAP8) { return B_BAD_VALUE; + } - status_t status = source->InitCheck(); - if (status < B_OK) - return status; + status_t result = source->InitCheck(); + if (result != B_OK) + return result; - status = result->InitCheck(); - if (status < B_OK) - return status; + result = destination->InitCheck(); + if (result != B_OK) + return result; 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); + return ConvertToCMAP8(src, width, height, srcBPR, destination); } status_t BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, - uint32 srcBPR, BBitmap* result) + uint32 srcBPR, BBitmap* icon) { - if (src == NULL || result == NULL || srcBPR == 0) + if (src == NULL || icon == NULL || srcBPR == 0) return B_BAD_VALUE; - status_t ret = result->InitCheck(); - if (ret < B_OK) - return ret; + status_t result = icon->InitCheck(); + if (result != B_OK) + return result; - if (result->ColorSpace() != B_RGBA32 && result->ColorSpace() != B_RGB32) { + if (icon->ColorSpace() != B_RGBA32 && icon->ColorSpace() != B_RGB32) { // TODO: support other color spaces return B_BAD_VALUE; } - uint32 dstWidth = result->Bounds().IntegerWidth() + 1; - uint32 dstHeight = result->Bounds().IntegerHeight() + 1; + uint32 dstWidth = icon->Bounds().IntegerWidth() + 1; + uint32 dstHeight = icon->Bounds().IntegerHeight() + 1; - uint8* dst = (uint8*)result->Bits(); - uint32 dstBPR = result->BytesPerRow(); + uint8* dst = (uint8*)icon->Bits(); + uint32 dstBPR = icon->BytesPerRow(); // check for downscaling or integer multiple scaling if (dstWidth < width || dstHeight < height @@ -655,7 +673,7 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, || (dstWidth == 3 * width && dstHeight == 3 * height) || (dstWidth == 4 * width && dstHeight == 4 * height)) { BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1), - result->ColorSpace()); + icon->ColorSpace()); converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8); uint8* convertedBits = (uint8*)converted->Bits(); int32 convertedBPR = converted->BytesPerRow(); @@ -706,7 +724,7 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, && dstWidth < 2 * width && dstHeight < 2 * height) { // scale2x then downscale BBitmap* temp = new BBitmap(BRect(0, 0, width * 2 - 1, height * 2 - 1), - result->ColorSpace()); + icon->ColorSpace()); uint8* tempBits = (uint8*)temp->Bits(); uint32 tempBPR = temp->BytesPerRow(); scale2x(dst, tempBits, width, height, dstBPR, tempBPR); @@ -716,7 +734,7 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, && dstWidth < 3 * width && dstHeight < 3 * height) { // scale3x then downscale BBitmap* temp = new BBitmap(BRect(0, 0, width * 3 - 1, height * 3 - 1), - result->ColorSpace()); + icon->ColorSpace()); uint8* tempBits = (uint8*)temp->Bits(); uint32 tempBPR = temp->BytesPerRow(); scale3x(dst, tempBits, width, height, dstBPR, tempBPR); @@ -726,7 +744,7 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, && dstWidth < 4 * width && dstHeight < 4 * height) { // scale4x then downscale BBitmap* temp = new BBitmap(BRect(0, 0, width * 4 - 1, height * 4 - 1), - result->ColorSpace()); + icon->ColorSpace()); uint8* tempBits = (uint8*)temp->Bits(); uint32 tempBPR = temp->BytesPerRow(); scale4x(dst, tempBits, width, height, dstBPR, tempBPR); @@ -735,11 +753,11 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, } else if (dstWidth > 4 * width && dstHeight > 4 * height) { // scale4x then bilinear BBitmap* temp = new BBitmap(BRect(0, 0, width * 4 - 1, height * 4 - 1), - result->ColorSpace()); + icon->ColorSpace()); uint8* tempBits = (uint8*)temp->Bits(); uint32 tempBPR = temp->BytesPerRow(); scale4x(dst, tempBits, width, height, dstBPR, tempBPR); - result->ImportBits(tempBits, height * tempBPR, tempBPR, 0, + icon->ImportBits(tempBits, height * tempBPR, tempBPR, 0, temp->ColorSpace()); scale_bilinear(dst, width, height, dstWidth, dstHeight, dstBPR); delete temp; @@ -754,38 +772,35 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, status_t BIconUtils::ConvertToCMAP8(const uint8* src, uint32 width, uint32 height, - uint32 srcBPR, BBitmap* result) + uint32 srcBPR, BBitmap* icon) { - if (!src || !result || srcBPR == 0) + if (src == NULL || icon == NULL || srcBPR == 0) return B_BAD_VALUE; - status_t ret = result->InitCheck(); - if (ret < B_OK) - return ret; + status_t result = icon->InitCheck(); + if (result != B_OK) + return result; - if (result->ColorSpace() != B_CMAP8) + if (icon->ColorSpace() != B_CMAP8) return B_BAD_VALUE; - uint32 dstWidth = result->Bounds().IntegerWidth() + 1; - uint32 dstHeight = result->Bounds().IntegerHeight() + 1; + uint32 dstWidth = icon->Bounds().IntegerWidth() + 1; + uint32 dstHeight = icon->Bounds().IntegerHeight() + 1; 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()); + // (currently copies bitmap into icon at left-top) + memset(icon->Bits(), 255, icon->BitsLength()); } //#if __HAIKU__ -// -// return result->ImportBits(src, height * srcBPR, srcBPR, 0, B_RGBA32); -// +// return icon->ImportBits(src, height * srcBPR, srcBPR, 0, B_RGBA32); //#else - - uint8* dst = (uint8*)result->Bits(); - uint32 dstBPR = result->BytesPerRow(); + uint8* dst = (uint8*)icon->Bits(); + uint32 dstBPR = icon->BytesPerRow(); const color_map* colorMap = system_colors(); if (colorMap == NULL) @@ -812,16 +827,14 @@ memset(result->Bits(), 255, result->BitsLength()); } return B_OK; - //#endif // __HAIKU__ } -// #pragma mark - forbidden +// #pragma mark - Forbidden BIconUtils::BIconUtils() {} BIconUtils::~BIconUtils() {} BIconUtils::BIconUtils(const BIconUtils&) {} BIconUtils& BIconUtils::operator=(const BIconUtils&) { return *this; } -