#include "ICNSTranslator.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ConfigView.h"
#include "ICNSLoader.h"
#include <Catalog.h>
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "ICNSTranslator"
extern "C" {
#include "icns.h"
}
const char *kDocumentCount = "/documentCount";
const char *kDocumentIndex = "/documentIndex";
#define kICNSMimeType "image/icns"
#define kICNSName "Apple Icon"
static const translation_format sInputFormats[] = {
{
ICNS_IMAGE_FORMAT,
B_TRANSLATOR_BITMAP,
ICNS_IN_QUALITY,
ICNS_IN_CAPABILITY,
kICNSMimeType,
kICNSName
},
{
B_TRANSLATOR_BITMAP,
B_TRANSLATOR_BITMAP,
BITS_IN_QUALITY,
BITS_IN_CAPABILITY,
"image/x-be-bitmap",
"Be Bitmap Format (ICNSTranslator)"
},
};
static const translation_format sOutputFormats[] = {
{
ICNS_IMAGE_FORMAT,
B_TRANSLATOR_BITMAP,
ICNS_OUT_QUALITY,
ICNS_OUT_CAPABILITY,
kICNSMimeType,
kICNSName
},
{
B_TRANSLATOR_BITMAP,
B_TRANSLATOR_BITMAP,
BITS_OUT_QUALITY,
BITS_OUT_CAPABILITY,
"image/x-be-bitmap",
"Be Bitmap Format (ICNSTranslator)"
},
};
static const TranSetting sDefaultSettings[] = {
{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}
};
const uint32 kNumInputFormats = sizeof(sInputFormats)
/ sizeof(translation_format);
const uint32 kNumOutputFormats = sizeof(sOutputFormats)
/ sizeof(translation_format);
const uint32 kNumDefaultSettings = sizeof(sDefaultSettings)
/ sizeof(TranSetting);
ICNSTranslator::ICNSTranslator()
: BaseTranslator(B_TRANSLATE("Apple icons"),
B_TRANSLATE("Apple icon translator"),
ICNS_TRANSLATOR_VERSION,
sInputFormats, kNumInputFormats,
sOutputFormats, kNumOutputFormats,
"ICNSTranslator",
sDefaultSettings, kNumDefaultSettings,
B_TRANSLATOR_BITMAP, ICNS_IMAGE_FORMAT)
{
}
ICNSTranslator::~ICNSTranslator()
{
}
status_t
ICNSTranslator::DerivedIdentify(BPositionIO *stream,
const translation_format *format, BMessage *ioExtension,
translator_info *info, uint32 outType)
{
if (!outType)
outType = B_TRANSLATOR_BITMAP;
if (outType != B_TRANSLATOR_BITMAP && outType != ICNS_IMAGE_FORMAT)
return B_NO_TRANSLATOR;
uint32 signatureData;
ssize_t signatureSize = 4;
if (stream->Read(&signatureData, signatureSize) != signatureSize)
return B_IO_ERROR;
const uint32 kICNSMagic = B_HOST_TO_BENDIAN_INT32('icns');
if (signatureData != kICNSMagic)
return B_ILLEGAL_DATA;
ICNSLoader icnsFile(stream);
if(!icnsFile.IsLoaded() || icnsFile.IconsCount() <= 0)
return B_ILLEGAL_DATA;
int32 documentCount = icnsFile.IconsCount();
int32 documentIndex = 1;
if (ioExtension) {
if (ioExtension->FindInt32(DOCUMENT_INDEX, &documentIndex) != B_OK)
documentIndex = 1;
if (documentIndex < 1 || documentIndex > documentCount)
return B_NO_TRANSLATOR;
ioExtension->RemoveName(DOCUMENT_COUNT);
ioExtension->AddInt32(DOCUMENT_COUNT, documentCount);
}
info->type = ICNS_IMAGE_FORMAT;
info->group = B_TRANSLATOR_BITMAP;
info->quality = ICNS_IN_QUALITY;
info->capability = ICNS_IN_CAPABILITY;
BString iconName("Apple icon");
if (documentCount > 1)
iconName << " #" << documentIndex;
strlcpy(info->name, iconName.String(), sizeof(info->name));
strcpy(info->MIME, kICNSMimeType);
return B_OK;
}
status_t
ICNSTranslator::DerivedTranslate(BPositionIO *source,
const translator_info *info, BMessage *ioExtension,
uint32 outType, BPositionIO *target, int32 baseType)
{
if (!outType)
outType = B_TRANSLATOR_BITMAP;
if (outType != B_TRANSLATOR_BITMAP && outType != ICNS_IMAGE_FORMAT)
return B_NO_TRANSLATOR;
switch (baseType) {
case 1:
{
TranslatorBitmap bitsHeader;
status_t result;
result = identify_bits_header(source, NULL, &bitsHeader);
if (result != B_OK)
return B_NO_TRANSLATOR;
icns_type_t type = ICNSFormat(bitsHeader.bounds.Width() + 1,
bitsHeader.bounds.Height() + 1, bitsHeader.colors);
if (type == ICNS_NULL_TYPE)
return B_NO_TRANSLATOR;
if (outType == ICNS_IMAGE_FORMAT) {
ICNSSaver icnsFile(source, bitsHeader.rowBytes, type);
if (icnsFile.IsCreated())
return icnsFile.SaveData(target);
}
return B_NO_TRANSLATOR;
}
case 0:
{
if (outType != B_TRANSLATOR_BITMAP)
return B_NO_TRANSLATOR;
ICNSLoader icnsFile(source);
if (!icnsFile.IsLoaded() || icnsFile.IconsCount() <= 0)
return B_NO_TRANSLATOR;
int32 documentIndex = 1;
if (ioExtension) {
if (ioExtension->FindInt32(DOCUMENT_INDEX, &documentIndex) != B_OK)
documentIndex = 1;
}
return icnsFile.GetIcon(target, documentIndex);
}
default:
return B_NO_TRANSLATOR;
}
}
status_t
ICNSTranslator::DerivedCanHandleImageSize(float width, float height) const
{
if (ICNSFormat(width, height, B_RGBA32) == ICNS_NULL_TYPE)
return B_NO_TRANSLATOR;
return B_OK;
}
BView *
ICNSTranslator::NewConfigView(TranslatorSettings *settings)
{
return new ConfigView(settings);
}
BTranslator *
make_nth_translator(int32 n, image_id you, uint32 flags, ...)
{
if (n != 0)
return NULL;
return new ICNSTranslator();
}