⛏️ index : haiku.git

/*
 * Copyright 2009, Haiku, Inc.
 * Distributed under the terms of the MIT license.
 *
 * Authors:
 *		Michael Lotz, mmlr@mlotz.ch
 */

#include "HVIFTranslator.h"
#include "HVIFView.h"

#include <Bitmap.h>
#include <BitmapStream.h>
#include <Catalog.h>
#include <IconUtils.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define HVIF_FORMAT_CODE				'HVIF'
#define HVIF_TRANSLATION_QUALITY		1.0
#define HVIF_TRANSLATION_CAPABILITY		1.0

#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "HVIFTranslator"


static const translation_format sInputFormats[] = {
	{
		HVIF_FORMAT_CODE,
		B_TRANSLATOR_BITMAP,
		HVIF_TRANSLATION_QUALITY,
		HVIF_TRANSLATION_CAPABILITY,
		"application/x-vnd.Haiku-icon",
		"Native Haiku vector icon"
	}
};


static const translation_format sOutputFormats[] = {
	{
		B_TRANSLATOR_BITMAP,
		B_TRANSLATOR_BITMAP,
		0.4,
		0.4,
		"image/x-be-bitmap",
		"Be Bitmap format (HVIFTranslator)"
	}
};


static const TranSetting sDefaultSettings[] = {
	{ HVIF_SETTING_RENDER_SIZE, TRAN_SETTING_INT32, 64 }
};

const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);



BTranslator *
make_nth_translator(int32 n, image_id image, uint32 flags, ...)
{
	if (n == 0)
		return new HVIFTranslator();
	return NULL;
}


HVIFTranslator::HVIFTranslator()
	: BaseTranslator(B_TRANSLATE("HVIF icons"), 
		B_TRANSLATE("Haiku vector icon translator"),
		HVIF_TRANSLATOR_VERSION,
		sInputFormats, kNumInputFormats,
		sOutputFormats, kNumOutputFormats,
		"HVIFTranslator_Settings",
		sDefaultSettings, kNumDefaultSettings,
		B_TRANSLATOR_BITMAP, HVIF_FORMAT_CODE)
{
}


HVIFTranslator::~HVIFTranslator()
{
}


status_t
HVIFTranslator::DerivedIdentify(BPositionIO *inSource,
	const translation_format *inFormat, BMessage *ioExtension,
	translator_info *outInfo, uint32 outType)
{
	// TODO: we do the fully work twice!
	if (outType != B_TRANSLATOR_BITMAP)
		return B_NO_TRANSLATOR;

	// filter out invalid sizes
	off_t size = inSource->Seek(0, SEEK_END);
	if (size <= 0 || size > 256 * 1024 || inSource->Seek(0, SEEK_SET) != 0)
		return B_NO_TRANSLATOR;

	uint8 *buffer = (uint8 *)malloc(size);
	if (buffer == NULL)
		return B_NO_MEMORY;

	if (inSource->Read(buffer, size) != size) {
		free(buffer);
		return B_NO_TRANSLATOR;
	}

	BBitmap dummy(BRect(0, 0, 1, 1), B_BITMAP_NO_SERVER_LINK, B_RGBA32);
	if (BIconUtils::GetVectorIcon(buffer, size, &dummy) != B_OK) {
		free(buffer);
		return B_NO_TRANSLATOR;
	}

	if (outInfo) {
		outInfo->type = sInputFormats[0].type;
		outInfo->group = sInputFormats[0].group;
		outInfo->quality = sInputFormats[0].quality;
		outInfo->capability = sInputFormats[0].capability;
		strcpy(outInfo->MIME, sInputFormats[0].MIME);
		strcpy(outInfo->name, sInputFormats[0].name);
	}

	free(buffer);
	return B_OK;
}


status_t
HVIFTranslator::DerivedTranslate(BPositionIO *inSource,
	const translator_info *inInfo, BMessage *ioExtension, uint32 outType,
	BPositionIO *outDestination, int32 baseType)
{
	if (outType != B_TRANSLATOR_BITMAP)
		return B_NO_TRANSLATOR;

	// filter out invalid sizes
	off_t size = inSource->Seek(0, SEEK_END);
	if (size <= 0 || size > 256 * 1024 || inSource->Seek(0, SEEK_SET) != 0)
		return B_NO_TRANSLATOR;

	uint8 *buffer = (uint8 *)malloc(size);
	if (buffer == NULL)
		return B_NO_MEMORY;

	if (inSource->Read(buffer, size) != size) {
		free(buffer);
		return B_NO_TRANSLATOR;
	}

	int32 renderSize = fSettings->SetGetInt32(HVIF_SETTING_RENDER_SIZE);
	if (renderSize <= 0 || renderSize > 1024)
		renderSize = 64;

	BBitmap rendered(BRect(0, 0, renderSize - 1, renderSize - 1),
		B_BITMAP_NO_SERVER_LINK, B_RGBA32);
	if (BIconUtils::GetVectorIcon(buffer, size, &rendered) != B_OK) {
		free(buffer);
		return B_NO_TRANSLATOR;
	}

	BBitmapStream stream(&rendered);
	stream.Seek(0, SEEK_SET);
	ssize_t read = 0;

	while ((read = stream.Read(buffer, size)) > 0)
		outDestination->Write(buffer, read);

	BBitmap *dummy = NULL;
	stream.DetachBitmap(&dummy);
	free(buffer);
	return B_OK;
}


BView *
HVIFTranslator::NewConfigView(TranslatorSettings *settings)
{
	return new HVIFView(B_TRANSLATE("HVIFTranslator Settings"), 
		B_WILL_DRAW, settings);
}