diff --git a/src/add-ons/translators/pngtranslator/Jamfile b/src/add-ons/translators/pngtranslator/Jamfile index c852d769a0..9d66b75d9d 100644 --- a/src/add-ons/translators/pngtranslator/Jamfile +++ b/src/add-ons/translators/pngtranslator/Jamfile @@ -4,6 +4,7 @@ Translator PNGTranslator : PNGMain.cpp PNGTranslator.cpp PNGView.cpp - PNGWindow.cpp ; + PNGWindow.cpp + PNGTranslatorSettings.cpp ; LinkSharedOSLibs PNGTranslator : be translation png ; diff --git a/src/add-ons/translators/pngtranslator/PNGMain.cpp b/src/add-ons/translators/pngtranslator/PNGMain.cpp index 763491d065..58dfd43757 100644 --- a/src/add-ons/translators/pngtranslator/PNGMain.cpp +++ b/src/add-ons/translators/pngtranslator/PNGMain.cpp @@ -58,7 +58,7 @@ main() BApplication app("application/x-vnd.obos-tiff-translator"); PNGTranslator *ptranslator = new PNGTranslator; BView *view = NULL; - BRect rect(0, 0, 225, 175); + BRect rect(0, 0, PNG_VIEW_WIDTH, PNG_VIEW_HEIGHT); if (ptranslator->MakeConfigurationView(NULL, &view, &rect)) { BAlert *err = new BAlert("Error", "Unable to create the PNGTranslator view.", "OK"); diff --git a/src/add-ons/translators/pngtranslator/PNGTranslator.cpp b/src/add-ons/translators/pngtranslator/PNGTranslator.cpp index ef2ff900e8..5594605797 100644 --- a/src/add-ons/translators/pngtranslator/PNGTranslator.cpp +++ b/src/add-ons/translators/pngtranslator/PNGTranslator.cpp @@ -175,6 +175,10 @@ pngcb_flush_data(png_structp ppng) PNGTranslator::PNGTranslator() : BTranslator() { + fpsettings = new PNGTranslatorSettings; + fpsettings->LoadSettings(); + // load settings from the PNGTranslator settings file + strcpy(fName, "PNG Images"); sprintf(fInfo, "PNG image translator v%d.%d.%d %s", PNG_TRANSLATOR_VERSION / 100, (PNG_TRANSLATOR_VERSION / 10) % 10, @@ -196,6 +200,7 @@ PNGTranslator::PNGTranslator() // --------------------------------------------------------------- PNGTranslator::~PNGTranslator() { + fpsettings->Release(); } // --------------------------------------------------------------- @@ -498,20 +503,8 @@ PNGTranslator::Identify(BPositionIO *inSource, return B_NO_TRANSLATOR; // Read settings from ioExtension - bool bheaderonly = false, bdataonly = false; - if (ioExtension) { - if (ioExtension->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bheaderonly)) - // if failed, make sure bool is default value - bheaderonly = false; - if (ioExtension->FindBool(B_TRANSLATOR_EXT_DATA_ONLY, &bdataonly)) - // if failed, make sure bool is default value - bdataonly = false; - - if (bheaderonly && bdataonly) - // can't both "only write the header" and "only write the data" - // at the same time - return B_BAD_VALUE; - } + if (ioExtension && fpsettings->LoadSettings(ioExtension) != B_OK) + return B_BAD_VALUE; uint32 n32ch; memcpy(&n32ch, ch, sizeof(uint32)); @@ -527,16 +520,32 @@ PNGTranslator::Identify(BPositionIO *inSource, } } -status_t -translate_from_png(BPositionIO *inSource, BMessage *ioExtension, - uint32 outType, BPositionIO *outDestination, ssize_t amtread, uint8 *read, - bool bheaderonly, bool bdataonly) +void +translate_direct_copy(BPositionIO *inSource, BPositionIO *outDestination) { - if (amtread != 8) - return B_ERROR; + const size_t kbufsize = 2048; + uint8 buffer[kbufsize]; + ssize_t ret = inSource->Read(buffer, kbufsize); + while (ret > 0) { + outDestination->Write(buffer, ret); + ret = inSource->Read(buffer, kbufsize); + } +} +status_t +translate_from_png_to_bits(BPositionIO *inSource, BPositionIO *outDestination, + PNGTranslatorSettings &settings) +{ status_t result = B_NO_TRANSLATOR; + bool bheaderonly, bdataonly; + bheaderonly = settings.SetGetHeaderOnly(); + bdataonly = settings.SetGetDataOnly(); + + // for storing decoded PNG row data + png_bytep *prows = NULL, prow = NULL; + png_uint_32 nalloc = 0; + png_structp ppng = NULL; png_infop pinfo = NULL; while (ppng == NULL) { @@ -554,6 +563,9 @@ translate_from_png(BPositionIO *inSource, BMessage *ioExtension, } // set error handling if (setjmp(png_jmpbuf(ppng))) { + // When an error occurs in libpng, it uses + // the longjmp function to continue execution + // from this point result = B_ERROR; break; } @@ -562,7 +574,7 @@ translate_from_png(BPositionIO *inSource, BMessage *ioExtension, png_set_read_fn(ppng, static_cast(inSource), pngcb_read_data); // Read in PNG image info - png_set_sig_bytes(ppng, amtread); + png_set_sig_bytes(ppng, 8); png_read_info(ppng, pinfo); png_uint_32 width, height; @@ -610,30 +622,37 @@ translate_from_png(BPositionIO *inSource, BMessage *ioExtension, if (rowbytes < kbytes * width) rowbytes = kbytes * width; - // Write out the data to outDestination - // Construct and write Be bitmap header - TranslatorBitmap bitsHeader; - bitsHeader.magic = B_TRANSLATOR_BITMAP; - bitsHeader.bounds.left = 0; - bitsHeader.bounds.top = 0; - bitsHeader.bounds.right = width - 1; - bitsHeader.bounds.bottom = height - 1; - bitsHeader.rowBytes = 4 * width; - if (balpha) - bitsHeader.colors = B_RGBA32; - else - bitsHeader.colors = B_RGB32; - bitsHeader.dataSize = bitsHeader.rowBytes * height; - if (swap_data(B_UINT32_TYPE, &bitsHeader, - sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) { - result = B_ERROR; - break; + if (!bdataonly) { + // Write out the data to outDestination + // Construct and write Be bitmap header + TranslatorBitmap bitsHeader; + bitsHeader.magic = B_TRANSLATOR_BITMAP; + bitsHeader.bounds.left = 0; + bitsHeader.bounds.top = 0; + bitsHeader.bounds.right = width - 1; + bitsHeader.bounds.bottom = height - 1; + bitsHeader.rowBytes = 4 * width; + if (balpha) + bitsHeader.colors = B_RGBA32; + else + bitsHeader.colors = B_RGB32; + bitsHeader.dataSize = bitsHeader.rowBytes * height; + if (swap_data(B_UINT32_TYPE, &bitsHeader, + sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) { + result = B_ERROR; + break; + } + outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap)); + + if (bheaderonly) { + result = B_OK; + break; + } } - outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap)); if (interlace_type == PNG_INTERLACE_NONE) { // allocate buffer for storing PNG row - png_bytep prow = new png_byte[rowbytes]; + prow = new png_byte[rowbytes]; if (!prow) { result = B_NO_MEMORY; break; @@ -646,50 +665,53 @@ translate_from_png(BPositionIO *inSource, BMessage *ioExtension, // finish reading, pass NULL for info because I // don't need the extra data png_read_end(ppng, NULL); - delete[] prow; - prow = NULL; result = B_OK; break; } else { // interlaced PNG image - png_bytep *prows = new png_bytep[height]; + prows = new png_bytep[height]; if (!prows) { result = B_NO_MEMORY; break; } // allocate enough memory to store the whole image - png_uint_32 n; - for (n = 0; n < height; n++) { - prows[n] = new png_byte[rowbytes]; - if (!prows[n]) + for (nalloc = 0; nalloc < height; nalloc++) { + prows[nalloc] = new png_byte[rowbytes]; + if (!prows[nalloc]) break; } - if (n < height) + if (nalloc < height) result = B_NO_MEMORY; else { png_read_image(ppng, prows); + png_read_end(ppng, NULL); + for (png_uint_32 i = 0; i < height; i++) outDestination->Write(prows[i], width * kbytes); result = B_OK; } - // delete row pointers and array of pointers to rows - while (n) { - n--; - delete[] prows[n]; - } - delete[] prows; - prows = NULL; - break; } } if (ppng) { + delete[] prow; + prow = NULL; + + // delete row pointers and array of pointers to rows + while (nalloc) { + nalloc--; + delete[] prows[nalloc]; + } + delete[] prows; + prows = NULL; + + // free PNG handle / info structures if (!pinfo) png_destroy_read_struct(&ppng, png_infopp_NULL, png_infopp_NULL); else @@ -699,6 +721,26 @@ translate_from_png(BPositionIO *inSource, BMessage *ioExtension, return result; } +status_t +translate_from_png(BPositionIO *inSource, BMessage *ioExtension, + uint32 outType, BPositionIO *outDestination, ssize_t amtread, uint8 *read, + PNGTranslatorSettings &settings) +{ + if (amtread != 8) + return B_ERROR; + + if (outType == B_TRANSLATOR_BITMAP) + return translate_from_png_to_bits(inSource, outDestination, + settings); + else { + // Translate from PNG to PNG + outDestination->Write(read, amtread); + translate_direct_copy(inSource, outDestination); + + return B_OK; + } +} + // --------------------------------------------------------------- // Translate // @@ -755,49 +797,38 @@ PNGTranslator::Translate(BPositionIO *inSource, const translator_info *inInfo, return B_NO_TRANSLATOR; // Read settings from ioExtension - bool bheaderonly = false, bdataonly = false; - if (ioExtension) { - if (ioExtension->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bheaderonly)) - // if failed, make sure bool is default value - bheaderonly = false; - if (ioExtension->FindBool(B_TRANSLATOR_EXT_DATA_ONLY, &bdataonly)) - // if failed, make sure bool is default value - bdataonly = false; - - if (bheaderonly && bdataonly) - // can't both "only write the header" and "only write the data" - // at the same time - return B_BAD_VALUE; - } + if (ioExtension && fpsettings->LoadSettings(ioExtension) != B_OK) + return B_BAD_VALUE; uint32 n32ch; memcpy(&n32ch, ch, sizeof(uint32)); if (n32ch == nbits) { // B_TRANSLATOR_BITMAP type outDestination->Write(ch, 4); - - const size_t kbufsize = 2048; - uint8 buffer[kbufsize]; - ssize_t ret = inSource->Read(buffer, kbufsize); - while (ret > 0) { - outDestination->Write(buffer, ret); - ret = inSource->Read(buffer, kbufsize); - } + translate_direct_copy(inSource, outDestination); return B_OK; } else { - // Might be PNG image + // Might be PNG image, read in the rest of + // the signature and check it if (inSource->Read(ch + 4, 4) != 4) return B_NO_TRANSLATOR; if (!png_check_sig(ch, 8)) return B_NO_TRANSLATOR; return translate_from_png(inSource, ioExtension, outType, - outDestination, 8, ch, bheaderonly, bdataonly); + outDestination, 8, ch, *fpsettings); } } +// returns the current translator settings into ioExtension +status_t +PNGTranslator::GetConfigurationMessage(BMessage *ioExtension) +{ + return fpsettings->GetConfigurationMessage(ioExtension); +} + // --------------------------------------------------------------- // MakeConfigurationView // @@ -827,9 +858,12 @@ PNGTranslator::MakeConfigurationView(BMessage *ioExtension, BView **outView, { if (!outView || !outExtent) return B_BAD_VALUE; + if (ioExtension && fpsettings->LoadSettings(ioExtension) != B_OK) + return B_BAD_VALUE; - PNGView *view = new PNGView(BRect(0, 0, 225, 175), - "PNGTranslator Settings", B_FOLLOW_ALL, B_WILL_DRAW); + PNGView *view = new PNGView(BRect(0, 0, PNG_VIEW_WIDTH, PNG_VIEW_HEIGHT), + "PNGTranslator Settings", B_FOLLOW_ALL, B_WILL_DRAW, + AcquireSettings()); if (!view) return B_NO_MEMORY; @@ -839,4 +873,9 @@ PNGTranslator::MakeConfigurationView(BMessage *ioExtension, BView **outView, return B_OK; } +PNGTranslatorSettings * +PNGTranslator::AcquireSettings() +{ + return fpsettings->Acquire(); +} diff --git a/src/add-ons/translators/pngtranslator/PNGTranslator.h b/src/add-ons/translators/pngtranslator/PNGTranslator.h index d6c4b19d2b..fe2af4a202 100644 --- a/src/add-ons/translators/pngtranslator/PNGTranslator.h +++ b/src/add-ons/translators/pngtranslator/PNGTranslator.h @@ -41,6 +41,7 @@ #include #include #include +#include "PNGTranslatorSettings.h" // IO Extension Names: @@ -93,10 +94,16 @@ public: // it translates the data in inSource to outDestination // using the format outType + virtual status_t GetConfigurationMessage(BMessage *ioExtension); + // write the current state of the translator into + // the supplied BMessage object + virtual status_t MakeConfigurationView(BMessage *ioExtension, BView **outView, BRect *outExtent); // creates and returns the view for displaying information // about this translator + + PNGTranslatorSettings *AcquireSettings(); protected: virtual ~PNGTranslator(); @@ -104,7 +111,9 @@ protected: // Release() function instead of being deleted directly by // the user -private: +private: + PNGTranslatorSettings *fpsettings; + char fName[30]; char fInfo[100]; }; diff --git a/src/add-ons/translators/pngtranslator/PNGTranslatorSettings.cpp b/src/add-ons/translators/pngtranslator/PNGTranslatorSettings.cpp new file mode 100644 index 0000000000..339450051e --- /dev/null +++ b/src/add-ons/translators/pngtranslator/PNGTranslatorSettings.cpp @@ -0,0 +1,446 @@ +/*****************************************************************************/ +// PNGTranslatorSettings +// Written by Michael Wilber +// +// PNGTranslatorSettings.cpp +// +// This class manages (saves/loads/locks/unlocks) the settings +// for the PNGTranslator. +// +// +// Copyright (c) 2003 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#include +#include +#include +#include + // for B_TRANSLATOR_EXT_* +#include "PNGTranslatorSettings.h" + +// --------------------------------------------------------------- +// Constructor +// +// Sets the default settings, location for the settings file +// and sets the reference count to 1 +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +PNGTranslatorSettings::PNGTranslatorSettings() + : flock("PNG Settings Lock") +{ + if (find_directory(B_USER_SETTINGS_DIRECTORY, &fsettingsPath)) + fsettingsPath.SetTo("/tmp"); + fsettingsPath.Append(PNG_SETTINGS_FILENAME); + + frefCount = 1; + + // Default Settings + // (Used when loading from the settings file or from + // a BMessage fails) + fmsgSettings.AddBool(B_TRANSLATOR_EXT_HEADER_ONLY, false); + fmsgSettings.AddBool(B_TRANSLATOR_EXT_DATA_ONLY, false); + fmsgSettings.AddInt32(PNG_SETTING_INTERLACE, PNG_INTERLACE_NONE); + // interlacing is off by default +} + +// --------------------------------------------------------------- +// Acquire +// +// Returns a pointer to the PNGTranslatorSettings and increments +// the reference count. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: pointer to this PNGTranslatorSettings object +// --------------------------------------------------------------- +PNGTranslatorSettings * +PNGTranslatorSettings::Acquire() +{ + PNGTranslatorSettings *psettings = NULL; + + flock.Lock(); + frefCount++; + psettings = this; + flock.Unlock(); + + return psettings; +} + +// --------------------------------------------------------------- +// Release +// +// Decrements the reference count and deletes the +// PNGTranslatorSettings if the reference count is zero. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: pointer to this PNGTranslatorSettings object if +// the reference count is greater than zero, returns NULL +// if the reference count is zero and the PNGTranslatorSettings +// object has been deleted +// --------------------------------------------------------------- +PNGTranslatorSettings * +PNGTranslatorSettings::Release() +{ + PNGTranslatorSettings *psettings = NULL; + + flock.Lock(); + frefCount--; + if (frefCount > 0) { + psettings = this; + flock.Unlock(); + } else + delete this; + // delete this object and + // release locks + + return psettings; +} + +// --------------------------------------------------------------- +// Destructor +// +// Does nothing! +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +PNGTranslatorSettings::~PNGTranslatorSettings() +{ +} + +// --------------------------------------------------------------- +// LoadSettings +// +// Loads the settings by reading them from the default +// settings file. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: B_OK if there were no errors or an error code from +// BFile::SetTo() or BMessage::Unflatten() if there were errors +// --------------------------------------------------------------- +status_t +PNGTranslatorSettings::LoadSettings() +{ + status_t result; + + flock.Lock(); + + BFile settingsFile; + result = settingsFile.SetTo(fsettingsPath.Path(), B_READ_ONLY); + if (result == B_OK) { + BMessage msg; + result = msg.Unflatten(&settingsFile); + if (result == B_OK) + result = LoadSettings(&msg); + } + + flock.Unlock(); + + return result; +} + +// --------------------------------------------------------------- +// LoadSettings +// +// Loads the settings from a BMessage passed to the function. +// +// Preconditions: +// +// Parameters: pmsg pointer to BMessage that contains the +// settings +// +// Postconditions: +// +// Returns: B_BAD_VALUE if pmsg is NULL or invalid options +// have been found, B_OK if there were no +// errors or an error code from BMessage::FindBool() or +// BMessage::ReplaceBool() if there were other errors +// --------------------------------------------------------------- +status_t +PNGTranslatorSettings::LoadSettings(BMessage *pmsg) +{ + status_t result = B_BAD_VALUE; + + if (pmsg) { + // Make certain that no PNG settings + // are missing from the file + int32 interlace; + bool bheaderOnly, bdataOnly; + + flock.Lock(); + result = pmsg->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bheaderOnly); + if (result != B_OK) + bheaderOnly = SetGetHeaderOnly(); + + result = pmsg->FindBool(B_TRANSLATOR_EXT_DATA_ONLY, &bdataOnly); + if (result != B_OK) + bdataOnly = SetGetDataOnly(); + + result = pmsg->FindInt32(PNG_SETTING_INTERLACE, &interlace); + if (result != B_OK) + interlace = SetGetInterlace(); + + if (bheaderOnly && bdataOnly) + // "write header only" and "write data only" + // are mutually exclusive + result = B_BAD_VALUE; + else { + result = B_OK; + + result = fmsgSettings.ReplaceBool( + B_TRANSLATOR_EXT_HEADER_ONLY, bheaderOnly); + + if (result == B_OK) + result = fmsgSettings.ReplaceBool( + B_TRANSLATOR_EXT_DATA_ONLY, bdataOnly); + + if (result == B_OK) + result = fmsgSettings.ReplaceInt32(PNG_SETTING_INTERLACE, + interlace); + } + flock.Unlock(); + } + + return result; +} + +// --------------------------------------------------------------- +// SaveSettings +// +// Saves the settings as a flattened BMessage to the default +// settings file +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: B_OK if no errors or an error code from BFile::SetTo() +// or BMessage::Flatten() if there were errors +// --------------------------------------------------------------- +status_t +PNGTranslatorSettings::SaveSettings() +{ + status_t result; + + flock.Lock(); + + BFile settingsFile; + result = settingsFile.SetTo(fsettingsPath.Path(), + B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + if (result == B_OK) + result = fmsgSettings.Flatten(&settingsFile); + + flock.Unlock(); + + return result; +} + +// --------------------------------------------------------------- +// GetConfigurationMessage +// +// Saves the current settings to the BMessage passed to the +// function +// +// Preconditions: +// +// Parameters: pmsg pointer to BMessage where the settings +// will be stored +// +// Postconditions: +// +// Returns: B_OK if there were no errors or an error code from +// BMessage::RemoveName() or BMessage::AddBool() if there were +// errors +// --------------------------------------------------------------- +status_t +PNGTranslatorSettings::GetConfigurationMessage(BMessage *pmsg) +{ + status_t result = B_BAD_VALUE; + + if (pmsg) { + const char *kNames[] = { + B_TRANSLATOR_EXT_HEADER_ONLY, + B_TRANSLATOR_EXT_DATA_ONLY, + PNG_SETTING_INTERLACE + }; + const int32 klen = sizeof(kNames) / sizeof(const char *); + int32 i; + for (i = 0; i < klen; i++) { + result = pmsg->RemoveName(kNames[i]); + if (result != B_OK && result != B_NAME_NOT_FOUND) + break; + } + if (i == klen) { + flock.Lock(); + result = B_OK; + + result = pmsg->AddBool(B_TRANSLATOR_EXT_HEADER_ONLY, + SetGetHeaderOnly()); + + if (result == B_OK) + result = pmsg->AddBool(B_TRANSLATOR_EXT_DATA_ONLY, + SetGetDataOnly()); + + if (result == B_OK) + result = pmsg->AddInt32(PNG_SETTING_INTERLACE, + SetGetInterlace()); + + flock.Unlock(); + } + } + + return result; +} + +// --------------------------------------------------------------- +// SetGetHeaderOnly +// +// Sets the state of the HeaderOnly setting (if pbHeaderOnly +// is not NULL) and returns the previous value of the +// HeaderOnly setting. +// +// If the HeaderOnly setting is true, only the header of +// the image will be output; the data will not be output. +// +// Preconditions: +// +// Parameters: pbHeaderOnly pointer to a bool specifying +// the new value of the +// HeaderOnly setting +// +// Postconditions: +// +// Returns: the prior value of the HeaderOnly setting +// --------------------------------------------------------------- +bool +PNGTranslatorSettings::SetGetHeaderOnly(bool *pbHeaderOnly) +{ + bool bprevValue = false; + // set to default value in case FindBool fails + + flock.Lock(); + fmsgSettings.FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bprevValue); + if (pbHeaderOnly) + fmsgSettings.ReplaceBool(B_TRANSLATOR_EXT_HEADER_ONLY, *pbHeaderOnly); + flock.Unlock(); + + return bprevValue; +} + +// --------------------------------------------------------------- +// SetGetDataOnly +// +// Sets the state of the DataOnly setting (if pbDataOnly +// is not NULL) and returns the previous value of the +// DataOnly setting. +// +// If the DataOnly setting is true, only the data of +// the image will be output; the header will not be output. +// +// Preconditions: +// +// Parameters: pbDataOnly pointer to a bool specifying +// the new value of the +// DataOnly setting +// +// Postconditions: +// +// Returns: the prior value of the DataOnly setting +// --------------------------------------------------------------- +bool +PNGTranslatorSettings::SetGetDataOnly(bool *pbDataOnly) +{ + bool bprevValue = false; + // set to default value in case FindBool fails + + flock.Lock(); + fmsgSettings.FindBool(B_TRANSLATOR_EXT_DATA_ONLY, &bprevValue); + if (pbDataOnly) + fmsgSettings.ReplaceBool(B_TRANSLATOR_EXT_DATA_ONLY, *pbDataOnly); + flock.Unlock(); + + return bprevValue; +} + +// --------------------------------------------------------------- +// SetGetInterlace +// +// Sets the state of the interlace setting (if pinterlace is +// not NULL) and returns the previous value of the interlace +// setting. +// +// If the interlace setting is PNG_INTERLACE_ADAM7, PNG images +// created by the PNGTranslator will be interlaced using the +// Adam7 method. If the setting is PNG_INTERLACE_NONE, PNG +// images created by the PNGTranslator will NOT be interlaced. +// +// Preconditions: +// +// Parameters: pinterlace pointer to int32 which specifies the +// new value for the interlace setting +// +// Postconditions: +// +// Returns: the prior value of the interlace setting +// --------------------------------------------------------------- +int32 +PNGTranslatorSettings::SetGetInterlace(int32 *pinterlace) +{ + int32 nprevValue = PNG_INTERLACE_NONE; + // set to default value in case FindBool fails + + flock.Lock(); + fmsgSettings.FindInt32(PNG_SETTING_INTERLACE, &nprevValue); + if (pinterlace) + fmsgSettings.ReplaceInt32(PNG_SETTING_INTERLACE, *pinterlace); + flock.Unlock(); + + return nprevValue; +} + diff --git a/src/add-ons/translators/pngtranslator/PNGTranslatorSettings.h b/src/add-ons/translators/pngtranslator/PNGTranslatorSettings.h new file mode 100644 index 0000000000..cf9a72d9f3 --- /dev/null +++ b/src/add-ons/translators/pngtranslator/PNGTranslatorSettings.h @@ -0,0 +1,90 @@ +/*****************************************************************************/ +// PNGTranslatorSettings +// Written by Michael Wilber +// +// PNGTranslatorSettings.h +// +// This class manages (saves/loads/locks/unlocks) the settings +// for the PNGTranslator. +// +// +// Copyright (c) 2003 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#ifndef PNG_TRANSLATOR_SETTINGS_H +#define PNG_TRANSLATOR_SETTINGS_H + +#include +#include +#include + +#define PNG_SETTINGS_FILENAME "PNGTranslator_Settings" + +// PNG Translator Settings +#define PNG_SETTING_INTERLACE "png /interlace" + +class PNGTranslatorSettings { +public: + PNGTranslatorSettings(); + + PNGTranslatorSettings *Acquire(); + // increments the reference count, returns this + PNGTranslatorSettings *Release(); + // decrements the reference count, deletes this + // when count reaches zero, returns this when + // ref count is greater than zero, NULL when + // ref count is zero + + status_t LoadSettings(); + status_t LoadSettings(BMessage *pmsg); + status_t SaveSettings(); + status_t GetConfigurationMessage(BMessage *pmsg); + + bool SetGetHeaderOnly(bool *pbHeaderOnly = NULL); + // sets / gets HeaderOnly setting + // specifies if only the image header should be + // outputted + bool SetGetDataOnly(bool *pbDataOnly = NULL); + // sets / gets DataOnly setting + // specifiees if only the image data should be + // outputted + int32 SetGetInterlace(int32 *pinterlace = NULL); + // sets /gets Interlace setting + // specifies if interlacing will be used + // when the PNGTranslator creates PNG images + +private: + ~PNGTranslatorSettings(); + // private so that Release() must be used + // to delete the object + + BLocker flock; + int32 frefCount; + BPath fsettingsPath; + // where the settings file will be loaded from / + // saved to + + BMessage fmsgSettings; + // the actual settings +}; + +#endif // #ifndef PNG_TRANSLATOR_SETTTINGS_H + diff --git a/src/add-ons/translators/pngtranslator/PNGView.cpp b/src/add-ons/translators/pngtranslator/PNGView.cpp index 576a64285b..12dc900945 100644 --- a/src/add-ons/translators/pngtranslator/PNGView.cpp +++ b/src/add-ons/translators/pngtranslator/PNGView.cpp @@ -30,9 +30,19 @@ #include #include +#include +#include #include "PNGView.h" #include "PNGTranslator.h" +BMessage * +interlace_msg(int option) +{ + BMessage *pmsg = new BMessage(M_PNG_SET_INTERLACE); + pmsg->AddInt32(PNG_SETTING_INTERLACE, option); + return pmsg; +} + // --------------------------------------------------------------- // Constructor // @@ -47,16 +57,37 @@ // Returns: // --------------------------------------------------------------- PNGView::PNGView(const BRect &frame, const char *name, - uint32 resize, uint32 flags) + uint32 resize, uint32 flags, PNGTranslatorSettings *psettings) : BView(frame, name, resize, flags) { + fpsettings = psettings; + SetViewColor(220,220,220,0); + + // setup PNG interlace options menu + fpmnuInterlace = new BPopUpMenu("Interlace Option"); + BMenuItem *pitmNone, *pitmAdam7; + pitmNone = new BMenuItem("None", interlace_msg(PNG_INTERLACE_NONE)); + pitmAdam7 = new BMenuItem("Adam7", interlace_msg(PNG_INTERLACE_ADAM7)); + fpmnuInterlace->AddItem(pitmNone); + fpmnuInterlace->AddItem(pitmAdam7); + + fpfldInterlace = new BMenuField(BRect(20, 50, 200, 70), "PNG Interlace Menu", + "Interlacing Type", fpmnuInterlace); + fpfldInterlace->SetViewColor(ViewColor()); + AddChild(fpfldInterlace); + + // set Interlace option to show the current configuration + if (fpsettings->SetGetInterlace() == PNG_INTERLACE_NONE) + pitmNone->SetMarked(true); + else + pitmAdam7->SetMarked(true); } // --------------------------------------------------------------- // Destructor // -// Does nothing +// Releases the PNGTranslator settings // // Preconditions: // @@ -68,6 +99,23 @@ PNGView::PNGView(const BRect &frame, const char *name, // --------------------------------------------------------------- PNGView::~PNGView() { + fpsettings->Release(); +} + +void +PNGView::AllAttached() +{ + // Tell all controls that this view is the target for + // messages from controls on this view + BView::AllAttached(); + BMessenger msgr(this); + + // set target for interlace options menu items + for (int32 i = 0; i < fpmnuInterlace->CountItems(); i++) { + BMenuItem *pitm = fpmnuInterlace->ItemAt(i); + if (pitm) + pitm->SetTarget(msgr); + } } // --------------------------------------------------------------- @@ -108,15 +156,32 @@ PNGView::Draw(BRect area) PNG_TRANSLATOR_VERSION % 10, __DATE__); DrawString(detail, BPoint(xbold, yplain + ybold)); - int32 lineno = 4; + int32 lineno = 6; DrawString("PNG Library:", BPoint(xbold, yplain * lineno + ybold)); - lineno += 2; + lineno += 1; - char libtiff[] = "BEER!"; - char *tok = strtok(libtiff, "\n"); + const int32 kinfolen = 512; + char libinfo[kinfolen] = { 0 }; + strncpy(libinfo, png_get_copyright(NULL), kinfolen - 1); + char *tok = strtok(libinfo, "\n"); while (tok) { DrawString(tok, BPoint(xbold, yplain * lineno + ybold)); lineno++; tok = strtok(NULL, "\n"); } } + +void +PNGView::MessageReceived(BMessage *pmsg) +{ + if (pmsg->what == M_PNG_SET_INTERLACE) { + // change setting for interlace option + int32 option; + if (pmsg->FindInt32(PNG_SETTING_INTERLACE, &option) == B_OK) { + fpsettings->SetGetInterlace(&option); + fpsettings->SaveSettings(); + } + } else + BView::MessageReceived(pmsg); +} + diff --git a/src/add-ons/translators/pngtranslator/PNGView.h b/src/add-ons/translators/pngtranslator/PNGView.h index d0dc8152d1..a2edf58c5c 100644 --- a/src/add-ons/translators/pngtranslator/PNGView.h +++ b/src/add-ons/translators/pngtranslator/PNGView.h @@ -34,18 +34,37 @@ #include #include #include +#include +#include "PNGTranslatorSettings.h" + +#define PNG_VIEW_WIDTH 300 +#define PNG_VIEW_HEIGHT 250 + +// Config panel messages +#define M_PNG_SET_INTERLACE 'pnsi' + class PNGView : public BView { public: PNGView(const BRect &frame, const char *name, uint32 resize, - uint32 flags); + uint32 flags, PNGTranslatorSettings *psettings); // sets up the view ~PNGView(); - // does nothing + // releases the PNGTranslator settings + virtual void AllAttached(); virtual void Draw(BRect area); // draws information about the PNGTranslator + virtual void MessageReceived(BMessage *pmsg); + +private: + BPopUpMenu *fpmnuInterlace; + BMenuField *fpfldInterlace; + + PNGTranslatorSettings *fpsettings; + // the actual settings for the translator, + // shared with the translator }; #endif // #ifndef PNGVIEW_H