* cleanup for consistency in FlatIconFormat.h

* used Axels proposals for vector icon attribute name
* added a BIconUtils class, currently only dealing with vector icons,
  it will render a vector icon from either a BNode attribute or a flat
  buffer in memory into a provided bitmap. The bitmap needs to be of
  B_RGBA32 colorspace, the size of the bitmap determines the scaling
  of the vector icon, width and height should currently be the same
  (square bitmap)
* TODO:
  - add reading of "old" BeOS icons / move icon reading from other
    places (BMimeType?) into BIconUtils
  - add reading icons from resources?
  - suggestions?


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18400 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2006-08-05 13:12:43 +00:00
parent faa8b41dac
commit 70f4b8c0ae
8 changed files with 274 additions and 24 deletions

View File

@ -122,6 +122,13 @@ Icon::~Icon()
delete fStyles;
}
// InitCheck
status_t
Icon::InitCheck() const
{
return fStyles && fPaths && fShapes ? B_OK : B_NO_MEMORY;
}
#ifdef ICON_O_MATIC
// ShapeAdded
void

View File

@ -44,6 +44,8 @@ class Icon {
Icon(const Icon& other);
virtual ~Icon();
status_t InitCheck() const;
StyleContainer* Styles() const
{ return fStyles; }
PathContainer* Paths() const

195
src/libs/icon/IconUtils.cpp Normal file
View File

@ -0,0 +1,195 @@
/*
* Copyright 2006, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "IconUtils.h"
#include <fs_attr.h>
#include <Bitmap.h>
#include <Node.h>
#include <TypeConstants.h>
#include "Icon.h"
#include "IconRenderer.h"
#include "FlatIconImporter.h"
// GetVectorIcon
status_t
BIconUtils::GetVectorIcon(BNode* node, const char* attrName,
BBitmap* result)
{
if (!node || !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_RAW_TYPE;
// TODO: introduce special 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];
node->ReadAttr(attrName, attrType, 0, buffer, attrInfo.size);
#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;
if (result->ColorSpace() != B_RGBA32 && result->ColorSpace() != B_RGB32)
return B_BAD_VALUE;
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(result);
renderer.SetIcon(&icon);
renderer.SetScale((result->Bounds().Width() + 1.0) / 64.0);
renderer.Render();
// TODO: would be nice to get rid of this
// (B_RGBA32_PREMULTIPLIED or better yes, 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 B_OK;
}
// 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;
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);
}
// ConvertFromCMAP8
status_t
BIconUtils::ConvertFromCMAP8(const uint8* src,
uint32 width, uint32 height, uint32 srcBPR,
BBitmap* result)
{
if (!src || !result || srcBPR == 0)
return B_BAD_VALUE;
status_t ret = result->InitCheck();
if (ret < B_OK)
return ret;
uint32 dstWidth = result->Bounds().IntegerWidth() + 1;
uint32 dstHeight = result->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)
}
#if __HAIKU__
return result->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8);
#else
if (result->ColorSpace() != B_RGBA32 && result->ColorSpace() != B_RGB32) {
// TODO: support other color spaces
return B_BAD_VALUE;
}
uint8* dst = (uint8*)result->Bits();
uint32 dstBPR = result->BytesPerRow();
const rgb_color* colorMap = system_colors()->color_list;
for (uint32 y = 0; y < dstHeight; y++) {
uint32* d = (uint32*)dst;
const uint8* s = src;
for (uint32 x = 0; x < dstWidth; x++) {
const rgb_color c = colorMap[*s];
uint8 alpha = 255;
if (*s == B_TRANSPARENT_MAGIC_CMAP8)
alpha = 0;
*d = (alpha << 24) | (c.red << 16) | (c.green << 8) | (c.blue);
s++;
d++;
}
src += srcBPR;
dst += dstBPR;
}
return B_OK;
#endif // __HAIKU__
}
// #pragma mark - forbidden
BIconUtils::BIconUtils() {}
BIconUtils::~BIconUtils() {}
BIconUtils::BIconUtils(const BIconUtils&) {}
BIconUtils& BIconUtils::operator=(const BIconUtils&) { return *this; }

44
src/libs/icon/IconUtils.h Normal file
View File

@ -0,0 +1,44 @@
/*
* Copyright 2006, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
*/
#ifndef ICON_UTILS_H
#define ICON_UTILS_H
#include <SupportDefs.h>
class BBitmap;
class BNode;
// This class is a little different from many other classes.
// You don't create an instance of it; you just call its various
// static member functions for utility-like operations.
class BIconUtils {
BIconUtils();
~BIconUtils();
BIconUtils(const BIconUtils&);
BIconUtils& operator=(const BIconUtils&);
public:
static status_t GetVectorIcon(BNode* node,
const char* attrName,
BBitmap* result);
static status_t GetVectorIcon(const uint8* buffer,
size_t size,
BBitmap* result);
static status_t ConvertFromCMAP8(BBitmap* source,
BBitmap* result);
static status_t ConvertFromCMAP8(const uint8* data,
uint32 width, uint32 height,
uint32 bytesPerRow,
BBitmap* result);
};
#endif // ICON_UTILS_H

View File

@ -54,5 +54,6 @@ StaticLibrary libicon.a :
Icon.cpp
IconRenderer.cpp
IconUtils.cpp
;

View File

@ -12,8 +12,8 @@
const uint32 FLAT_ICON_MAGIC = 'ficn';
const char* kVectorAttrNodeName = "BEOS:I:STD_ICON";
const char* kVectorAttrMimeName = "META:I:STD_ICON";
const char* kVectorAttrNodeName = "BEOS:ICON";
const char* kVectorAttrMimeName = "META:ICON";
// read_coord
bool

View File

@ -12,20 +12,21 @@
#include <SupportDefs.h>
extern const uint32 FLAT_ICON_MAGIC;
extern const char* kVectorAttrNodeName;
extern const char* kVectorAttrMimeName;
enum {
TAG_STYLE_SOLID_COLOR = 1,
TAG_STYLE_GRADIENT = 2,
TAG_STYLE_SOLID_COLOR_NO_ALPHA = 3,
STYLE_TYPE_SOLID_COLOR = 1,
STYLE_TYPE_GRADIENT = 2,
STYLE_TYPE_SOLID_COLOR_NO_ALPHA = 3,
TAG_SHAPE_PATH_SOURCE = 10,
SHAPE_TYPE_PATH_SOURCE = 10,
TAG_TRANSFORMER_AFFINE = 20,
TAG_TRANSFORMER_CONTOUR = 21,
TAG_TRANSFORMER_PERSPECTIVE = 22,
TAG_TRANSFORMER_STROKE = 23,
TRANSFORMER_TYPE_AFFINE = 20,
TRANSFORMER_TYPE_CONTOUR = 21,
TRANSFORMER_TYPE_PERSPECTIVE = 22,
TRANSFORMER_TYPE_STROKE = 23,
};
enum {
@ -35,9 +36,9 @@ enum {
};
enum {
PATH_FLAGS_CLOSED = 1 << 1,
PATH_FLAGS_USES_COMMANDS = 1 << 2,
PATH_FLAGS_NO_CURVES = 1 << 3,
PATH_FLAG_CLOSED = 1 << 1,
PATH_FLAG_USES_COMMANDS = 1 << 2,
PATH_FLAG_NO_CURVES = 1 << 3,
};
enum {

View File

@ -243,17 +243,17 @@ FlatIconImporter::_ParseStyles(LittleEndianBuffer& buffer,
if (!buffer.Read(styleType))
return B_ERROR;
Style* style = NULL;
if (styleType == TAG_STYLE_SOLID_COLOR) {
if (styleType == STYLE_TYPE_SOLID_COLOR) {
// solid color
style = _ReadColorStyle(buffer, true);
if (!style)
return B_NO_MEMORY;
} else if (styleType == TAG_STYLE_SOLID_COLOR_NO_ALPHA) {
} else if (styleType == STYLE_TYPE_SOLID_COLOR_NO_ALPHA) {
// solid color without alpha
style = _ReadColorStyle(buffer, false);
if (!style)
return B_NO_MEMORY;
} else if (styleType == TAG_STYLE_GRADIENT) {
} else if (styleType == STYLE_TYPE_GRADIENT) {
// gradient
style = _ReadGradientStyle(buffer);
if (!style)
@ -351,10 +351,10 @@ FlatIconImporter::_ParsePaths(LittleEndianBuffer& buffer,
// chose path reading strategy depending on path flags
bool error = false;
if (pathFlags & PATH_FLAGS_NO_CURVES) {
if (pathFlags & PATH_FLAG_NO_CURVES) {
if (!read_path_no_curves(buffer, path, pointCount))
error = true;
} else if (pathFlags & PATH_FLAGS_USES_COMMANDS) {
} else if (pathFlags & PATH_FLAG_USES_COMMANDS) {
if (!read_path_with_commands(buffer, path, pointCount))
error = true;
} else {
@ -368,7 +368,7 @@ FlatIconImporter::_ParsePaths(LittleEndianBuffer& buffer,
}
// post process path to clean it up
path->CleanUp();
if (pathFlags & PATH_FLAGS_CLOSED)
if (pathFlags & PATH_FLAG_CLOSED)
path->SetClosed(true);
// add path to container
if (!paths->AddPath(path)) {
@ -389,7 +389,7 @@ _ReadTransformer(LittleEndianBuffer& buffer, VertexSource& source)
return NULL;
switch (transformerType) {
case TAG_TRANSFORMER_AFFINE: {
case TRANSFORMER_TYPE_AFFINE: {
AffineTransformer* affine
= new (nothrow) AffineTransformer(source);
if (!affine)
@ -406,7 +406,7 @@ _ReadTransformer(LittleEndianBuffer& buffer, VertexSource& source)
affine->load_from(matrix);
return affine;
}
case TAG_TRANSFORMER_CONTOUR: {
case TRANSFORMER_TYPE_CONTOUR: {
ContourTransformer* contour
= new (nothrow) ContourTransformer(source);
uint8 width;
@ -424,14 +424,14 @@ _ReadTransformer(LittleEndianBuffer& buffer, VertexSource& source)
contour->miter_limit(miterLimit);
return contour;
}
case TAG_TRANSFORMER_PERSPECTIVE: {
case TRANSFORMER_TYPE_PERSPECTIVE: {
PerspectiveTransformer* perspective
= new (nothrow) PerspectiveTransformer(source);
// TODO: upgrade AGG to be able to support storage of
// trans_perspective
return perspective;
}
case TAG_TRANSFORMER_STROKE: {
case TRANSFORMER_TYPE_STROKE: {
StrokeTransformer* stroke
= new (nothrow) StrokeTransformer(source);
uint8 width;
@ -566,7 +566,7 @@ FlatIconImporter::_ParseShapes(LittleEndianBuffer& buffer,
if (!buffer.Read(shapeType))
return B_ERROR;
Shape* shape = NULL;
if (shapeType == TAG_SHAPE_PATH_SOURCE) {
if (shapeType == SHAPE_TYPE_PATH_SOURCE) {
// path source shape
shape = _ReadPathSourceShape(buffer, styles, paths);
if (!shape)