[Scummvm-git-logs] scummvm master -> eea428cbc350501c70ded31081721cb722440585
sev-
noreply at scummvm.org
Mon Aug 7 08:22:16 UTC 2023
This automated email contains information about 9 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
5e6c5ca07b MTROPOLIS: Fix project platform returning the wrong value
3777a3bf9a GUI: Force Unix newlines on Windows for default.inc
3c1efe4f89 COMMON: Add file format info API
7bacf7b430 GUI: Add image album dialog for viewing images exported by an engine, mainly for supporting printing features
6f005a75a4 TESTBED: Add tests for image album
46a0aca354 MTROPOLIS: Hook up MPZ-1000 to image album
58271a834c COMMON: Remove #pragma once
9598e343a3 GUI: Add imagealbum-dialog.cpp to POTFILES
eea428cbc3 GUI: Update theme binaries
Commit: 5e6c5ca07b245d428c2d9dcdde7359ab2692b534
https://github.com/scummvm/scummvm/commit/5e6c5ca07b245d428c2d9dcdde7359ab2692b534
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-07T10:22:09+02:00
Commit Message:
MTROPOLIS: Fix project platform returning the wrong value
Changed paths:
engines/mtropolis/modifiers.cpp
engines/mtropolis/runtime.cpp
engines/mtropolis/runtime.h
diff --git a/engines/mtropolis/modifiers.cpp b/engines/mtropolis/modifiers.cpp
index c9304542daf..b8f95e27e08 100644
--- a/engines/mtropolis/modifiers.cpp
+++ b/engines/mtropolis/modifiers.cpp
@@ -2339,11 +2339,11 @@ bool KeyboardMessengerModifier::checkKeyEventTrigger(Runtime *runtime, Common::E
return false;
if (_keyModCommand) {
- if (runtime->getPlatform() == kProjectPlatformWindows) {
+ if (runtime->getProject()->getPlatform() == kProjectPlatformWindows) {
// Windows projects check "alt"
if ((keyEvt.flags & Common::KBD_ALT) == 0)
return false;
- } else if (runtime->getPlatform() == kProjectPlatformMacintosh) {
+ } else if (runtime->getProject()->getPlatform() == kProjectPlatformMacintosh) {
if ((keyEvt.flags & Common::KBD_META) == 0)
return false;
}
@@ -2377,7 +2377,7 @@ bool KeyboardMessengerModifier::checkKeyEventTrigger(Runtime *runtime, Common::E
break;
case Common::KEYCODE_F1:
// Windows projects map F1 to "help"
- if (runtime->getPlatform() == kProjectPlatformWindows)
+ if (runtime->getProject()->getPlatform() == kProjectPlatformWindows)
resolvedType = kHelp;
break;
case Common::KEYCODE_BACKSPACE:
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index aaf7aa3cd29..6c6dfb4a53a 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -4255,7 +4255,7 @@ Runtime::Runtime(OSystem *system, Audio::Mixer *mixer, ISaveUIProvider *saveProv
: _system(system), _mixer(mixer), _saveProvider(saveProvider), _loadProvider(loadProvider),
_nextRuntimeGUID(1), _realDisplayMode(kColorDepthModeInvalid), _fakeDisplayMode(kColorDepthModeInvalid),
_displayWidth(1024), _displayHeight(768), _realTime(0), _realTimeBase(0), _playTime(0), _playTimeBase(0), _sceneTransitionState(kSceneTransitionStateNotTransitioning),
- _lastFrameCursor(nullptr), _lastFrameMouseVisible(false), _defaultCursor(new DefaultCursorGraphic()), _platform(kProjectPlatformUnknown),
+ _lastFrameCursor(nullptr), _lastFrameMouseVisible(false), _defaultCursor(new DefaultCursorGraphic()),
_cachedMousePosition(Common::Point(0, 0)), _realMousePosition(Common::Point(0, 0)), _trackedMouseOutside(false),
_forceCursorRefreshOnce(true), _autoResetCursor(false), _haveModifierOverrideCursor(false), _haveCursorElement(false), _sceneGraphChanged(false), _isQuitting(false),
_collisionCheckTime(0), /*_elementCursorUpdateTime(0), */_defaultVolumeState(true), _activeSceneTransitionEffect(nullptr), _sceneTransitionStartTime(0), _sceneTransitionEndTime(0),
@@ -5938,10 +5938,6 @@ void Runtime::setVolume(double volume) {
mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, static_cast<int>(volume * Audio::Mixer::kMaxMixerVolume));
}
-ProjectPlatform Runtime::getPlatform() const {
- return _platform;
-}
-
void Runtime::onMouseDown(int32 x, int32 y, Actions::MouseButton mButton) {
_realMousePosition.x = x;
_realMousePosition.y = y;
@@ -6927,7 +6923,8 @@ Project::AssetDesc::AssetDesc() : typeCode(0), id(0), streamID(0), filePosition(
Project::Project(Runtime *runtime)
: Structural(runtime), _projectFormat(Data::kProjectFormatUnknown), _isBigEndian(false),
_haveGlobalObjectInfo(false), _haveProjectStructuralDef(false), _playMediaSignaller(new PlayMediaSignaller()),
- _keyboardEventSignaller(new KeyboardEventSignaller()), _guessedVersion(MTropolisVersions::kMTropolisVersion1_0) {
+ _keyboardEventSignaller(new KeyboardEventSignaller()), _guessedVersion(MTropolisVersions::kMTropolisVersion1_0),
+ _platform(kProjectPlatformUnknown) {
}
Project::~Project() {
@@ -6957,6 +6954,7 @@ void Project::loadFromDescription(const ProjectDescription &desc, const Hacks &h
_resources = desc.getResources();
_cursorGraphics = desc.getCursorGraphics();
_subtitles = desc.getSubtitles();
+ _platform = desc.getPlatform();
debug(1, "Loading new project...");
@@ -7451,6 +7449,10 @@ MTropolisVersions::MTropolisVersion Project::guessVersion() const {
return _guessedVersion;
}
+ProjectPlatform Project::getPlatform() const {
+ return _platform;
+}
+
void Project::loadPresentationSettings(const Data::PresentationSettings &presentationSettings) {
_presentationSettings.bitsPerPixel = presentationSettings.bitsPerPixel;
if (_presentationSettings.bitsPerPixel != 8 && _presentationSettings.bitsPerPixel != 16) {
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index 166b30e1b03..9c5c7e1b650 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -1651,8 +1651,6 @@ public:
void setVolume(double volume);
- ProjectPlatform getPlatform() const;
-
void onMouseDown(int32 x, int32 y, Actions::MouseButton mButton);
void onMouseMove(int32 x, int32 y);
void onMouseUp(int32 x, int32 y, Actions::MouseButton mButton);
@@ -1930,8 +1928,6 @@ private:
Common::WeakPtr<Window> _keyFocusWindow;
- ProjectPlatform _platform;
-
Common::SharedPtr<SystemInterface> _systemInterface;
Common::SharedPtr<WorldManagerInterface> _worldManagerInterface;
Common::SharedPtr<AssetManagerInterface> _assetManagerInterface;
@@ -2438,6 +2434,7 @@ public:
const SubtitleTables &getSubtitles() const;
MTropolisVersions::MTropolisVersion guessVersion() const;
+ ProjectPlatform getPlatform() const;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Project"; }
@@ -2553,6 +2550,7 @@ private:
SubtitleTables _subtitles;
MTropolisVersions::MTropolisVersion _guessedVersion;
+ ProjectPlatform _platform;
};
class Section : public Structural {
Commit: 3777a3bf9a1066a32301267771557baae04412ef
https://github.com/scummvm/scummvm/commit/3777a3bf9a1066a32301267771557baae04412ef
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-07T10:22:09+02:00
Commit Message:
GUI: Force Unix newlines on Windows for default.inc
Changed paths:
gui/themes/scummtheme.py
diff --git a/gui/themes/scummtheme.py b/gui/themes/scummtheme.py
index a6fe93f49b1..2f8322b2141 100755
--- a/gui/themes/scummtheme.py
+++ b/gui/themes/scummtheme.py
@@ -85,7 +85,7 @@ def parseSTX(theme_file, def_file, subcount):
return subcount
def buildDefTheme(themeName):
- def_file = open("default.inc", "w")
+ def_file = open("default.inc", mode="w", newline="\n")
if not os.path.isdir(themeName):
print ("Cannot open default theme dir.")
Commit: 3c1efe4f895437cb07754b48251fbe8990280597
https://github.com/scummvm/scummvm/commit/3c1efe4f895437cb07754b48251fbe8990280597
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-07T10:22:09+02:00
Commit Message:
COMMON: Add file format info API
Changed paths:
A common/formats/formatinfo.cpp
A common/formats/formatinfo.h
common/formats/module.mk
po/POTFILES
diff --git a/common/formats/formatinfo.cpp b/common/formats/formatinfo.cpp
new file mode 100644
index 00000000000..ff8e6dcc6a4
--- /dev/null
+++ b/common/formats/formatinfo.cpp
@@ -0,0 +1,152 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/formats/formatinfo.h"
+
+#include "common/translation.h"
+#include "common/util.h"
+
+#include "image/bmp.h"
+#include "image/png.h"
+
+namespace Common {
+
+namespace FormatInfo {
+
+struct FormatTypeInfo {
+ const char *_shortExtension; ///< Extension limited to 3 characters
+ const char *_longExtension; ///< Extension with no length limit
+};
+
+const FormatTypeInfo g_formatTypeInfo[kCount] = {
+ {nullptr},
+
+ // Image formats
+ {"bmp"},
+ {"png"},
+ {"jpg"},
+ {"pct", "pict"},
+
+ // Binary formats
+ {"application/octet-stream", nullptr},
+};
+
+ImageFormatCharacteristics::ImageFormatCharacteristics()
+ : _lossiness(kLossinessUnknown), _supportAlpha(false), _supportPalette(false), _maxBitDepth(0) {
+}
+
+ImageSaveProperties::ImageSaveProperties() : _qualityLevel(75) {
+}
+
+bool getImageFormatCharacteristics(FormatID format, ImageFormatCharacteristics &outCharacteristics) {
+ outCharacteristics = ImageFormatCharacteristics();
+
+ switch (format) {
+ case kPICT:
+ outCharacteristics._supportPalette = true;
+ outCharacteristics._maxBitDepth = 24;
+ outCharacteristics._lossiness = kLossinessEither;
+ break;
+ case kBMP:
+ outCharacteristics._supportPalette = true;
+ outCharacteristics._maxBitDepth = 24;
+ outCharacteristics._lossiness = kLossinessLossless;
+ break;
+ case kPNG:
+ outCharacteristics._supportPalette = true;
+ outCharacteristics._supportAlpha = true;
+ outCharacteristics._maxBitDepth = 32;
+ outCharacteristics._lossiness = kLossinessLossless;
+ break;
+ case kJPEG:
+ outCharacteristics._maxBitDepth = 24;
+ outCharacteristics._lossiness = kLossinessLossy;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+const char *getFormatExtension(Common::FormatInfo::FormatID format, bool limitTo3Characters) {
+ const FormatTypeInfo &typeInfo = g_formatTypeInfo[format];
+
+ if (!limitTo3Characters && typeInfo._longExtension != nullptr)
+ return typeInfo._longExtension;
+
+ return typeInfo._shortExtension;
+}
+
+Common::U32String getFormatSaveDescription(Common::FormatInfo::FormatID format) {
+ switch (format) {
+ case kBMP:
+ return _("Bitmap Image File");
+ case kPNG:
+ return _("PNG Image File");
+ case kJPEG:
+ return _("JPEG Image File");
+ case kPICT:
+ return _("QuickDraw PICT Image File");
+ case kUntypedBinary:
+ default:
+ return _("Data File");
+ }
+}
+
+#ifdef USE_PNG
+static bool savePNG(Common::WriteStream &stream, const Graphics::Surface &surf, const byte *palette, const ImageSaveProperties &props) {
+ return Image::writePNG(stream, surf, palette);
+}
+#endif
+
+static bool saveBMP(Common::WriteStream &stream, const Graphics::Surface &surf, const byte *palette, const ImageSaveProperties &props) {
+ return Image::writeBMP(stream, surf, palette);
+}
+
+ImageSaveCallback_t getImageSaveFunction(FormatID format) {
+ switch (format) {
+#ifdef USE_PNG
+ case kPNG:
+ return savePNG;
+#endif
+ case kBMP:
+ return saveBMP;
+ default:
+ return nullptr;
+ }
+}
+
+FormatSupportLevel getFormatSupportLevel(Common::FormatInfo::FormatID format) {
+ switch (format) {
+ case kPICT:
+ return kFormatSupportLevelAvoid;
+ case kPNG:
+ case kJPEG:
+ return kFormatSupportLevelPreferred;
+ default:
+ return kFormatSupportLevelDefault;
+ }
+}
+
+} // End of namespace FormatInfo
+
+} // End of namespace Common
diff --git a/common/formats/formatinfo.h b/common/formats/formatinfo.h
new file mode 100644
index 00000000000..05d6769155f
--- /dev/null
+++ b/common/formats/formatinfo.h
@@ -0,0 +1,120 @@
+#pragma once
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef COMMON_FORMATS_FORMATINFO_H
+#define COMMON_FORMATS_FORMATINFO_H
+
+#include "common/str.h"
+#include "image/bmp.h"
+
+namespace Graphics {
+
+struct Surface;
+
+} // End of namespace Graphics
+
+namespace Common {
+
+namespace FormatInfo {
+
+enum Lossiness {
+ kLossinessUnknown,
+
+ kLossinessLossless,
+ kLossinessLossy,
+ kLossinessEither,
+};
+
+
+/**
+ * Values representing support for saving or sharing file types on the system.
+ */
+enum FormatSupportLevel {
+ kFormatSupportLevelNone, ///< Not supported at all
+ kFormatSupportLevelAvoid, ///< Can be saved/loaded but most likely unsupported even by third-party tools
+ kFormatSupportLevelDefault, ///< Not natively supported by the operating system, support by third-party tools is either available or unknown
+ kFormatSupportLevelSupported, ///< Well-supported by the operating system
+ kFormatSupportLevelPreferred, ///< Supported by operating system, preferred over other formats if lossless conversion is possible
+};
+
+enum FormatID {
+ kFormatUnknown,
+
+ // Image formats
+ kBMP, kFirstImageFormat = kBMP,
+ kPNG,
+ kJPEG,
+ kPICT, // Macintosh PICT
+
+ // Binary formats
+ kUntypedBinary, kFirstBinaryFormat = kUntypedBinary,
+
+ // End of list
+ kCount,
+
+ kLastImageFormat = kFirstBinaryFormat - 1,
+ kLastBinaryFormat = kCount - 1,
+};
+
+struct ImageFormatCharacteristics {
+ ImageFormatCharacteristics();
+
+ Lossiness _lossiness;
+ bool _supportAlpha;
+ bool _supportPalette;
+ uint _maxBitDepth;
+};
+
+struct ImageSaveProperties {
+ ImageSaveProperties();
+
+ uint8 _qualityLevel;
+};
+
+typedef bool (*ImageSaveCallback_t)(Common::WriteStream &stream, const Graphics::Surface &surf, const byte *palette, const ImageSaveProperties &saveProperties);
+
+/**
+ * Returns the default file extension for a format
+ *
+ * @param format The file format
+ * @param limitTo3Characters If true, limit the extension to 3 characters
+ * @return
+*/
+const char *getFormatExtension(Common::FormatInfo::FormatID format, bool limitTo3Characters);
+
+Common::U32String getFormatSaveDescription(Common::FormatInfo::FormatID format);
+
+ImageSaveCallback_t getImageSaveFunction(FormatID format);
+
+
+bool getImageFormatCharacteristics(FormatID format, ImageFormatCharacteristics &outCharacteristics);
+
+/**
+ * Returns the OS's level of support of a file format.
+ */
+FormatSupportLevel getFormatSupportLevel(Common::FormatInfo::FormatID format);
+
+} // End of namespace FormatInfo
+
+} // End of namespace Common
+
+#endif
diff --git a/common/formats/module.mk b/common/formats/module.mk
index 566fffbebcc..9537f8def77 100644
--- a/common/formats/module.mk
+++ b/common/formats/module.mk
@@ -1,6 +1,7 @@
MODULE := common/formats
MODULE_OBJS := \
+ formatinfo.o \
iff_container.o \
ini-file.o \
json.o \
diff --git a/po/POTFILES b/po/POTFILES
index 0ede7f511b4..f1cafc86a24 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -37,6 +37,7 @@ common/rendermode.cpp
common/translation.cpp
common/updates.cpp
common/util.cpp
+common/formats/formatinfo.cpp
dists/android.strings.xml.cpp
dists/org.scummvm.scummvm.metainfo.xml.cpp
Commit: 7bacf7b4306ecd41a806474c72d16ef82befaf42
https://github.com/scummvm/scummvm/commit/7bacf7b4306ecd41a806474c72d16ef82befaf42
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-07T10:22:09+02:00
Commit Message:
GUI: Add image album dialog for viewing images exported by an engine, mainly for supporting printing features
Changed paths:
A gui/imagealbum-dialog.cpp
A gui/imagealbum-dialog.h
gui/module.mk
gui/themes/common/highres_layout.stx
gui/themes/common/lowres_layout.stx
gui/themes/default.inc
gui/themes/scummclassic/classic_layout.stx
gui/themes/scummclassic/classic_layout_lowres.stx
diff --git a/gui/imagealbum-dialog.cpp b/gui/imagealbum-dialog.cpp
new file mode 100644
index 00000000000..c7d392cbd4b
--- /dev/null
+++ b/gui/imagealbum-dialog.cpp
@@ -0,0 +1,472 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "gui/imagealbum-dialog.h"
+
+#include "gui/dialog.h"
+#include "gui/filebrowser-dialog.h"
+#include "gui/gui-manager.h"
+#include "gui/ThemeEval.h"
+#include "gui/widget.h"
+
+#include "gui/widgets/scrollcontainer.h"
+
+#include "image/bmp.h"
+#include "image/png.h"
+
+#include "common/dialogs.h"
+#include "common/savefile.h"
+#include "common/stream.h"
+#include "common/translation.h"
+
+namespace GUI {
+
+ImageAlbumImageSupplier::~ImageAlbumImageSupplier() {
+}
+
+class ImageAlbumDialog : public Dialog {
+public:
+ ImageAlbumDialog(const Common::U32String &title, ImageAlbumImageSupplier *imageSupplier, uint initialSlot);
+ ~ImageAlbumDialog();
+
+ void open() override;
+ void close() override;
+
+ void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
+
+private:
+ ImageAlbumDialog() = delete;
+ ImageAlbumDialog(const ImageAlbumDialog &) = delete;
+
+ void changeToSlot(uint slot);
+ void saveImageInSlot(uint slot);
+
+ ImageAlbumImageSupplier *_imageSupplier;
+ uint _currentSlot;
+ uint _numSlots;
+
+ ButtonWidget *_prevButton;
+ ButtonWidget *_nextButton;
+ ButtonWidget *_saveButton;
+
+ StaticTextWidget *_imageNumberLabel;
+
+ ContainerWidget *_imageContainer;
+ GraphicsWidget *_imageGraphic;
+
+ bool _canAlwaysSaveImage;
+
+ enum {
+ kPrevCmd = 'PREV',
+ kNextCmd = 'NEXT',
+ kSaveCmd = 'SAVE',
+ };
+};
+
+
+ImageAlbumDialog::ImageAlbumDialog(const Common::U32String &title, ImageAlbumImageSupplier *imageSupplier, uint initialSlot)
+ : Dialog("ImageAlbum"), _imageSupplier(imageSupplier), _currentSlot(initialSlot), _numSlots(0), _imageGraphic(nullptr), _canAlwaysSaveImage(false) {
+
+ _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
+
+ _numSlots = imageSupplier->getNumSlots();
+
+ assert(_numSlots > 0);
+
+ new StaticTextWidget(this, "ImageAlbum.Title", title);
+
+ if (initialSlot >= _numSlots)
+ initialSlot = _numSlots - 1;
+
+ // Buttons
+ if (_numSlots > 1) {
+ _prevButton = new ButtonWidget(this, "ImageAlbum.Prev", _("Prev"), Common::U32String(), kPrevCmd);
+ _nextButton = new ButtonWidget(this, "ImageAlbum.Next", _("Next"), Common::U32String(), kNextCmd);
+ _imageNumberLabel = new StaticTextWidget(this, "ImageAlbum.ImageNumber", Common::U32String());
+ } else {
+ _prevButton = nullptr;
+ _nextButton = nullptr;
+ _imageNumberLabel = nullptr;
+ }
+
+ _saveButton = nullptr;
+
+
+ bool canSaveAnyFormat = false;
+ for (uint fmtID = Common::FormatInfo::kFirstImageFormat; fmtID <= Common::FormatInfo::kLastImageFormat; fmtID++) {
+ Common::FormatInfo::FormatID format = static_cast<Common::FormatInfo::FormatID>(fmtID);
+
+ if (Common::FormatInfo::getFormatSupportLevel(format) > Common::FormatInfo::kFormatSupportLevelNone) {
+ canSaveAnyFormat = true;
+ if (Common::FormatInfo::getImageSaveFunction(format) != nullptr) {
+ _canAlwaysSaveImage = true;
+ break;
+ }
+ }
+ }
+
+ if (canSaveAnyFormat) {
+ _saveButton = new ButtonWidget(this, "ImageAlbum.Save", _("Save Image..."), Common::U32String(), kSaveCmd);
+ _saveButton->setEnabled(!_canAlwaysSaveImage);
+ }
+
+ new ButtonWidget(this, "ImageAlbum.Close", _("Close"), Common::U32String(), kCloseCmd);
+
+ _imageContainer = new ContainerWidget(this, "ImageAlbum.ImageContainer");
+
+ _imageGraphic = nullptr;
+}
+
+ImageAlbumDialog::~ImageAlbumDialog() {
+}
+
+void ImageAlbumDialog::open() {
+ Dialog::open();
+
+ changeToSlot(_currentSlot);
+}
+
+void ImageAlbumDialog::changeToSlot(uint slot) {
+ ContainerWidget *container = _imageContainer;
+ container = _imageContainer;
+
+ bool canSaveImage = _canAlwaysSaveImage;
+
+ if (_imageGraphic) {
+ _imageContainer->removeWidget(_imageGraphic);
+ delete _imageGraphic;
+ _imageGraphic = nullptr;
+ }
+
+ Common::Rect graphicRect = Common::Rect(0, 0, _imageContainer->getWidth(), _imageContainer->getHeight());
+
+ int inset = g_gui.xmlEval()->getVar("Globals.ImageAlbum.ImageInset", 0);
+ graphicRect.grow(-inset);
+
+ if (graphicRect.isValidRect()) {
+ uint32 graphicRectWidth = graphicRect.width();
+ uint32 graphicRectHeight = graphicRect.height();
+
+ const Graphics::Surface *surf = nullptr;
+ bool hasPalette = false;
+ byte palette[256 * 3];
+ ImageAlbumImageMetadata metadata;
+
+ for (byte &paletteByte : palette)
+ paletteByte = 0;
+
+ if (_imageSupplier->loadImageSlot(slot, surf, hasPalette, palette, metadata)) {
+ if (!canSaveImage) {
+ // If we can't always save the image (meaning we don't have an image write-out function) then see if we can
+ // at least save this file in its native format.
+ Common::FormatInfo::FormatID format = Common::FormatInfo::kFormatUnknown;
+ if (_imageSupplier->getFileFormatForImageSlot(slot, format)) {
+ if (Common::FormatInfo::getFormatSupportLevel(format) > Common::FormatInfo::kFormatSupportLevelNone)
+ canSaveImage = true;
+ }
+ }
+
+ uint32 imageWidth = surf->w;
+ uint32 imageHeight = surf->h;
+
+ uint32 scaledWidth = graphicRectWidth;
+ uint32 scaledHeight = graphicRectHeight;
+
+ bool needs90Rotate = (metadata._viewTransformation == kImageAlbumViewTransformationRotate90CCW || metadata._viewTransformation == kImageAlbumViewTransformationRotate90CW);
+
+ uint32 imageRotatedWidth = imageWidth;
+ uint32 imageRotatedHeight = imageHeight;
+ if (needs90Rotate) {
+ imageRotatedWidth = imageHeight;
+ imageRotatedHeight = imageWidth;
+ }
+
+ // if (imageRotatedWidth / imageRotatedHeight > graphicRectWidth / graphicRectHeight)
+ if (imageRotatedWidth * graphicRectHeight >= graphicRectWidth * imageRotatedHeight) {
+ // Image aspect ratio is wider than the graphic space, or same
+ scaledWidth = graphicRectWidth;
+ scaledHeight = imageRotatedHeight * graphicRectWidth / imageRotatedWidth;
+ } else {
+ // Image aspect ratio is taller than the graphic space
+ scaledWidth = imageRotatedWidth * graphicRectHeight / imageRotatedHeight;
+ scaledHeight = graphicRectHeight;
+ }
+
+ if (scaledWidth < 1)
+ scaledWidth = 1;
+ if (scaledHeight < 1)
+ scaledHeight = 1;
+
+ Graphics::ManagedSurface rescaledGraphic;
+ rescaledGraphic.create(scaledWidth, scaledHeight, surf->format);
+ if (hasPalette)
+ rescaledGraphic.setPalette(palette, 0, 256);
+
+ if (needs90Rotate) {
+ bool isClockwise = metadata._viewTransformation == kImageAlbumViewTransformationRotate90CW;
+
+ for (uint32 destX = 0; destX < scaledWidth; destX++) {
+ uint32 srcY = destX * imageHeight / scaledWidth;
+ if (isClockwise)
+ srcY = imageHeight - 1 - srcY;
+
+ for (uint32 destY = 0; destY < scaledHeight; destY++) {
+ uint32 srcX = destY * imageWidth / scaledHeight;
+
+ if (!isClockwise)
+ srcX = imageWidth - 1 - srcX;
+
+ rescaledGraphic.setPixel(destX, destY, surf->getPixel(srcX, srcY));
+ }
+ }
+ } else if (metadata._viewTransformation == kImageAlbumViewTransformationRotate180) {
+ for (uint32 destX = 0; destX < scaledWidth; destX++) {
+ uint32 srcX = (imageWidth - 1 - (destX * imageWidth / scaledWidth));
+
+ for (uint32 destY = 0; destY < scaledHeight; destY++) {
+ uint32 srcY = (imageHeight - 1 - (destY * imageHeight / scaledHeight));
+
+ rescaledGraphic.setPixel(destX, destY, surf->getPixel(srcX, srcY));
+ }
+ }
+ } else {
+ rescaledGraphic.blitFrom(*surf, Common::Rect(0, 0, imageWidth, imageHeight), Common::Rect(0, 0, scaledWidth, scaledHeight));
+ }
+
+ _imageSupplier->releaseImageSlot(slot);
+
+ if (rescaledGraphic.format.bytesPerPixel == 1)
+ rescaledGraphic.convertToInPlace(Graphics::createPixelFormat<888>(), palette);
+
+ int32 xCoord = (static_cast<int32>(_imageContainer->getWidth()) - static_cast<int32>(scaledWidth)) / 2u;
+ int32 yCoord = (static_cast<int32>(_imageContainer->getHeight()) - static_cast<int32>(scaledHeight)) / 2u;
+
+ _imageGraphic = new GraphicsWidget(_imageContainer, xCoord, yCoord, xCoord + static_cast<int32>(scaledWidth), yCoord + static_cast<int32>(scaledHeight));
+
+ _imageGraphic->setGfx(&rescaledGraphic, false);
+
+ if (_numSlots > 1) {
+ _imageNumberLabel->setLabel(Common::U32String::format(_("%u of %u"), static_cast<uint>(slot + 1u), _numSlots));
+ _prevButton->setEnabled(slot > 0);
+ _nextButton->setEnabled(slot < _numSlots - 1u);
+ }
+
+ _currentSlot = slot;
+ } else {
+ warning("Image album failed to retrieve slot %u", slot);
+ }
+ }
+
+ if (_saveButton)
+ _saveButton->setEnabled(canSaveImage);
+}
+
+void ImageAlbumDialog::saveImageInSlot(uint slot) {
+ Common::U32String defaultFileName = _imageSupplier->getDefaultFileNameForSlot(slot);
+
+ Common::FormatInfo::FormatID nativeFormat = Common::FormatInfo::kFormatUnknown;
+
+ Common::U32String fileExt;
+ Common::U32String fileDesc;
+
+ bool hasExtension = 0;
+ uint extensionPos = 0;
+ for (uint i = 0; i < defaultFileName.size(); i++) {
+ if (defaultFileName[i] == '.') {
+ hasExtension = true;
+ extensionPos = i;
+ }
+ }
+ Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
+
+ Common::FormatInfo::FormatSupportLevel bestFormatSupportLevel = Common::FormatInfo::kFormatSupportLevelNone;
+ Common::FormatInfo::FormatID bestFormat = Common::FormatInfo::kFormatUnknown;
+ bool bestFormatIsLossy = true;
+
+ // Find the best format we can write the image as
+ for (uint fmtID = Common::FormatInfo::kFirstImageFormat; fmtID <= Common::FormatInfo::kLastImageFormat; fmtID++) {
+ Common::FormatInfo::FormatID candidateFormat = static_cast<Common::FormatInfo::FormatID>(fmtID);
+
+ if (!Common::FormatInfo::getImageSaveFunction(candidateFormat))
+ continue;
+
+ Common::FormatInfo::FormatSupportLevel supportLevel = Common::FormatInfo::getFormatSupportLevel(candidateFormat);
+
+ bool formatIsLossy = false;
+ Common::FormatInfo::ImageFormatCharacteristics characteristics;
+ if (Common::FormatInfo::getImageFormatCharacteristics(candidateFormat, characteristics))
+ formatIsLossy = (characteristics._lossiness == Common::FormatInfo::kLossinessLossy);
+
+ bool isBetter = false;
+
+ // If the best format we have chosen is lossy, and this is a lossless format that is at least supported, it is better
+ // If this format is the same lossiness, but is better-supported, it is better
+ if (bestFormatIsLossy && !formatIsLossy && supportLevel >= Common::FormatInfo::kFormatSupportLevelSupported)
+ isBetter = true;
+ else if (bestFormatIsLossy == formatIsLossy && supportLevel > bestFormatSupportLevel)
+ isBetter = true;
+ else if (bestFormat == Common::FormatInfo::kFormatUnknown && supportLevel >= Common::FormatInfo::kFormatSupportLevelNone)
+ isBetter = true;
+
+ if (isBetter) {
+ bestFormatSupportLevel = supportLevel;
+ bestFormat = candidateFormat;
+ bestFormatIsLossy = formatIsLossy;
+ }
+ }
+
+ assert(bestFormat != Common::FormatInfo::kFormatUnknown);
+
+ if (_imageSupplier->getFileFormatForImageSlot(slot, nativeFormat)) {
+ if (nativeFormat != bestFormat) {
+ Common::FormatInfo::FormatSupportLevel nativeSupportLevel = Common::FormatInfo::getFormatSupportLevel(nativeFormat);
+
+ if (nativeSupportLevel > Common::FormatInfo::kFormatSupportLevelNone) {
+ bool nativeFormatIsLossy = false;
+
+ Common::FormatInfo::ImageFormatCharacteristics characteristics;
+ if (Common::FormatInfo::getImageFormatCharacteristics(nativeFormat, characteristics))
+ nativeFormatIsLossy = (characteristics._lossiness == Common::FormatInfo::kLossinessLossy);
+
+ // If the native format is lossy and is at least supported, prefer using it directly, otherwise only use it if it has a higher support level
+ if ((nativeFormatIsLossy && nativeSupportLevel >= Common::FormatInfo::kFormatSupportLevelSupported) || nativeSupportLevel >= bestFormatSupportLevel) {
+ bestFormat = nativeFormat;
+ bestFormatSupportLevel = nativeSupportLevel;
+ }
+ }
+ }
+ }
+
+ // This shouldn't be possible, the Save button should not be visible unless there is either a saveable format,
+ // or the file's native format is saveable, and in either of those circumstances, a format should have been selected by this point.
+ assert(bestFormatSupportLevel > Common::FormatInfo::kFormatSupportLevelNone);
+
+ bool needsConversion = false;
+
+ if (nativeFormat == bestFormat) {
+ // Save in the preferred format
+ if (hasExtension)
+ fileExt = defaultFileName.substr(extensionPos + 1);
+ } else {
+ // Save in the preferred format
+ needsConversion = true;
+
+ fileExt = Common::U32String(Common::FormatInfo::getFormatExtension(bestFormat, true));
+
+ if (hasExtension)
+ defaultFileName = defaultFileName.substr(0, extensionPos) + Common::U32String(".") + fileExt;
+ }
+
+ fileDesc = Common::FormatInfo::getFormatSaveDescription(bestFormat);
+
+ Common::U32String title = _("Save Image");
+
+ if (needsConversion) {
+ const Graphics::Surface *surf = nullptr;
+ bool hasPalette = false;
+ byte palette[256 * 3];
+ ImageAlbumImageMetadata metadata;
+
+ for (byte &paletteByte : palette)
+ paletteByte = 0;
+
+ if (_imageSupplier->loadImageSlot(slot, surf, hasPalette, palette, metadata)) {
+ Common::ScopedPtr<Common::SeekableWriteStream> writeStream;
+
+ GUI::FileBrowserDialog browser(title.encode(Common::kUtf8).c_str(), fileExt.encode(Common::kUtf8).c_str(), GUI::kFBModeSave, nullptr, defaultFileName.encode(Common::kUtf8).c_str());
+
+ if (browser.runModal() > 0) {
+ Common::String path = browser.getResult();
+ writeStream.reset(saveFileManager->openForSaving(path, false));
+ if (writeStream) {
+ assert(writeStream);
+
+ Common::FormatInfo::ImageSaveCallback_t saveCallback = Common::FormatInfo::getImageSaveFunction(bestFormat);
+ assert(saveCallback);
+
+ Common::FormatInfo::ImageSaveProperties saveProps;
+ saveCallback(*writeStream, *surf, hasPalette ? palette : nullptr, saveProps);
+ } else {
+ warning("Failed to open image output stream");
+ }
+ }
+
+ _imageSupplier->releaseImageSlot(slot);
+ }
+ } else {
+ Common::ScopedPtr<Common::SeekableReadStream> readStream;
+ readStream.reset(_imageSupplier->createReadStreamForSlot(slot));
+ if (!readStream) {
+ warning("Failed to open input stream for slot %u", slot);
+ return;
+ }
+
+ Common::ScopedPtr<Common::SeekableWriteStream> writeStream;
+
+ GUI::FileBrowserDialog browser(title.encode(Common::kUtf8).c_str(), fileExt.encode(Common::kUtf8).c_str(), GUI::kFBModeSave, nullptr, defaultFileName.encode(Common::kUtf8).c_str());
+
+ if (browser.runModal() > 0) {
+ Common::String path = browser.getResult();
+ writeStream.reset(saveFileManager->openForSaving(path, false));
+
+ if (writeStream) {
+ assert(writeStream);
+
+ byte copyBuffer[2048];
+ uint32 bytesRead = readStream->read(copyBuffer, sizeof(copyBuffer));
+ while (bytesRead) {
+ writeStream->write(copyBuffer, bytesRead);
+ bytesRead = readStream->read(copyBuffer, sizeof(copyBuffer));
+ }
+ } else {
+ warning("Failed to open image output stream");
+ }
+ }
+ }
+}
+
+void ImageAlbumDialog::close() {
+ Dialog::close();
+}
+
+void ImageAlbumDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ switch (cmd) {
+ case kPrevCmd:
+ if (_currentSlot > 0)
+ changeToSlot(_currentSlot - 1);
+ break;
+ case kNextCmd:
+ if (_currentSlot < _numSlots - 1)
+ changeToSlot(_currentSlot + 1);
+ break;
+ case kSaveCmd:
+ saveImageInSlot(_currentSlot);
+ break;
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ }
+}
+
+GUI::Dialog *createImageAlbumDialog(const Common::U32String &title, ImageAlbumImageSupplier *imageSupplier, uint initialSlot) {
+ return new ImageAlbumDialog(title, imageSupplier, initialSlot);
+}
+
+} // End of namespace GUI
diff --git a/gui/imagealbum-dialog.h b/gui/imagealbum-dialog.h
new file mode 100644
index 00000000000..dffd884db56
--- /dev/null
+++ b/gui/imagealbum-dialog.h
@@ -0,0 +1,125 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef IMAGEALBUM_DIALOG_H
+#define IMAGEALBUM_DIALOG_H
+
+#include "common/formats/formatinfo.h"
+#include "common/str.h"
+#include "common/rational.h"
+
+namespace Common {
+
+class SeekableReadStream;
+
+} // End of namespace Common
+
+namespace Graphics {
+
+struct Surface;
+
+} // End of namespace Graphics
+
+namespace GUI {
+
+class Dialog;
+
+enum ImageAlbumImageOrientation {
+ kImageAlbumImageOrientationUnspecified,
+
+ kImageAlbumImageOrientationLandscape,
+ kImageAlbumImageOrientationPortrait,
+};
+
+enum ImageAlbumViewTransformation {
+ kImageAlbumViewTransformationNone,
+ kImageAlbumViewTransformationRotate90CCW,
+ kImageAlbumViewTransformationRotate90CW,
+ kImageAlbumViewTransformationRotate180,
+};
+
+struct ImageAlbumImageMetadata {
+ ImageAlbumImageMetadata() : _orientation(kImageAlbumImageOrientationUnspecified), _viewTransformation(kImageAlbumViewTransformationNone), _hdpi(72, 1), _vdpi(72, 1) {}
+
+ ImageAlbumViewTransformation _viewTransformation; ///< Transformation required to present the image at its normal intended viewing orientation
+ ImageAlbumImageOrientation _orientation; ///< Orientation of the image after view transformation
+ Common::Rational _hdpi; ///< Horizontal DPI of the image
+ Common::Rational _vdpi; ///< Vertical DPI of the image
+};
+
+/**
+ * @brief Interface that supplies images to the image album dialog.
+ */
+class ImageAlbumImageSupplier {
+public:
+ virtual ~ImageAlbumImageSupplier();
+
+ /**
+ * @brief Loads and returns the image for a specified slot
+ * @param slot The image slot to load
+ * @param outSurface An outputted pointer to a surface containing the image data
+ * @param outHasPalette An outputted boolean containing true if the image has a palette and false if not
+ * @param outPalette Outputted palette colors if the image has a palette
+ * @param outMetadata Outputted metadata for the image
+ * @return True if the image loaded successfully, false if it failed
+ */
+ virtual bool loadImageSlot(uint slot, const Graphics::Surface *&outSurface, bool &outHasPalette, byte (&outPalette)[256 * 3], ImageAlbumImageMetadata &outMetadata) = 0;
+
+ /**
+ * @brief Releases any resources for an image loaded with loadImageSlot
+ * @param slot The image slot to release
+ */
+ virtual void releaseImageSlot(uint slot) = 0;
+
+ /**
+ * Returns the file format of the image in the specified image slot, if it's capable of being loaded as raw file data.
+ *
+ * @param slot The image slot to load
+ * @param outFormat A reference to a file format ID to set to the file format
+ * @return true if the slot is loadable as raw data and has a MIME type available, false if not
+ */
+ virtual bool getFileFormatForImageSlot(uint slot, Common::FormatInfo::FormatID &outFormat) const = 0;
+
+ /**
+ * @brief Opens a slot as a read stream containing raw file data.
+ * @param slot The image slot to load
+ * @return The created read stream, if it could be created, or nullptr if it failed
+ */
+ virtual Common::SeekableReadStream *createReadStreamForSlot(uint slot) = 0;
+
+ /**
+ * @brief Returns the number of image slots
+ * @return The number of slots
+ */
+ virtual uint getNumSlots() const = 0;
+
+ /**
+ * @brief Returns the default filename, including extension, for the specified slot
+ * @return The filename of the slot without an extension
+ */
+ virtual Common::U32String getDefaultFileNameForSlot(uint slot) const = 0;
+};
+
+Dialog *createImageAlbumDialog(const Common::U32String &title, ImageAlbumImageSupplier *imageSupplier, uint initialSlot);
+
+} // End of namespace GUI
+
+#endif
diff --git a/gui/module.mk b/gui/module.mk
index 0c16927c1d7..562a11829d7 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -13,6 +13,7 @@ MODULE_OBJS := \
EventRecorder.o \
filebrowser-dialog.o \
gui-manager.o \
+ imagealbum-dialog.o \
launcher.o \
massadd.o \
message.o \
diff --git a/gui/themes/common/highres_layout.stx b/gui/themes/common/highres_layout.stx
index da2dc0dc272..56a527e0cec 100644
--- a/gui/themes/common/highres_layout.stx
+++ b/gui/themes/common/highres_layout.stx
@@ -47,6 +47,7 @@
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '1'/>
<def var = 'RecorderDialog.ExtInfo.Visible' value = '1'/>
+ <def var = 'ImageAlbum.ImageInset' value = '16' scalable = 'yes' />
<def var = 'OnScreenDialog.ShowPics' value = '1'/>
@@ -2450,4 +2451,32 @@
</layout>
</dialog>
+ <dialog name = 'ImageAlbum' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' align = 'center'>
+ <widget name = 'Title' height = 'Globals.Line.Height'/>
+ <widget name = 'ImageContainer' />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Prev'
+ type = 'Button'
+ />
+ <widget name = 'ImageNumber'
+ width = '50'
+ height = 'Globals.Line.Height'
+ textalign = 'center'
+ />
+ <widget name = 'Next'
+ type = 'Button'
+ />
+ <space/>
+ <widget name = 'Save'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Close'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
</layout_info>
diff --git a/gui/themes/common/lowres_layout.stx b/gui/themes/common/lowres_layout.stx
index e0b7030ef09..9a3637d3da0 100644
--- a/gui/themes/common/lowres_layout.stx
+++ b/gui/themes/common/lowres_layout.stx
@@ -39,6 +39,7 @@
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '0'/>
<def var = 'RecorderDialog.ExtInfo.Visible' value = '0'/>
+ <def var = 'ImageAlbum.ImageInset' value = '16' scalable = 'yes' />
<def var = 'OnScreenDialog.ShowPics' value = '1'/>
@@ -2278,4 +2279,32 @@
</layout>
</dialog>
+ <dialog name = 'ImageAlbum' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' align = 'center'>
+ <widget name = 'Title' height = 'Globals.Line.Height'/>
+ <widget name = 'ImageContainer' />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Prev'
+ type = 'Button'
+ />
+ <widget name = 'ImageNumber'
+ width = '50'
+ height = 'Globals.Line.Height'
+ textalign = 'center'
+ />
+ <widget name = 'Next'
+ type = 'Button'
+ />
+ <space/>
+ <widget name = 'Save'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Close'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
</layout_info>
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 115b888d201..32e2c4b80ab 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -1454,6 +1454,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"<def var='ShowChooserPageDisplay' value='1'/>"
"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/>"
"<def var='RecorderDialog.ExtInfo.Visible' value='1'/>"
+"<def var='ImageAlbum.ImageInset' value='16' scalable='yes' />"
"<def var='OnScreenDialog.ShowPics' value='0'/>"
"<def var='KeyMapper.Spacing' value='10' scalable='yes'/>"
"<def var='KeyMapper.ButtonWidth' value='140' scalable='yes'/>"
@@ -3512,6 +3513,33 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"</layout>"
"</layout>"
"</dialog>"
+"<dialog name='ImageAlbum' overlays='screen' inset='8' shading='dim'>"
+"<layout type='vertical' padding='8,8,8,8' align='center'>"
+"<widget name='Title' height='Globals.Line.Height'/>"
+"<widget name='ImageContainer' />"
+"<layout type='horizontal' padding='0,0,16,0'>"
+"<widget name='Prev' "
+"type='Button' "
+"/>"
+"<widget name='ImageNumber' "
+"width='50' "
+"height='Globals.Line.Height' "
+"textalign='center' "
+"/>"
+"<widget name='Next' "
+"type='Button' "
+"/>"
+"<space/>"
+"<widget name='Save' "
+"type='Button' "
+"/>"
+"<space size='16'/>"
+"<widget name='Close' "
+"type='Button' "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
"</layout_info>"
;
const char *defaultXML4 = "<layout_info resolution='y<H'>"
@@ -3528,6 +3556,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"<def var='ShowChooserPageDisplay' value='0'/>"
"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/>"
"<def var='RecorderDialog.ExtInfo.Visible' value='0'/>"
+"<def var='ImageAlbum.ImageInset' value='16' scalable='yes' />"
"<def var='OnScreenDialog.ShowPics' value='0'/>"
"<def var='KeyMapper.Spacing' value='5' scalable='yes'/>"
"<def var='KeyMapper.ButtonWidth' value='100' scalable='yes'/>"
@@ -5563,6 +5592,33 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"</layout>"
"</layout>"
"</dialog>"
+"<dialog name='ImageAlbum' overlays='screen' inset='8' shading='dim'>"
+"<layout type='vertical' padding='8,8,8,8' align='center'>"
+"<widget name='Title' height='Globals.Line.Height'/>"
+"<widget name='ImageContainer' />"
+"<layout type='horizontal' padding='0,0,16,0'>"
+"<widget name='Prev' "
+"type='Button' "
+"/>"
+"<widget name='ImageNumber' "
+"width='50' "
+"height='Globals.Line.Height' "
+"textalign='center' "
+"/>"
+"<widget name='Next' "
+"type='Button' "
+"/>"
+"<space/>"
+"<widget name='Save' "
+"type='Button' "
+"/>"
+"<space size='16'/>"
+"<widget name='Close' "
+"type='Button' "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
"</layout_info>"
;
const char *defaultXML[] = { defaultXML1, defaultXML2, defaultXML3, defaultXML4 };
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 32b87f495a9..41fb110098f 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -39,6 +39,7 @@
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '1'/>
<def var = 'RecorderDialog.ExtInfo.Visible' value = '1'/>
+ <def var = 'ImageAlbum.ImageInset' value = '16' scalable = 'yes' />
<def var = 'OnScreenDialog.ShowPics' value = '0'/>
@@ -2195,4 +2196,32 @@
</layout>
</dialog>
+ <dialog name = 'ImageAlbum' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' align = 'center'>
+ <widget name = 'Title' height = 'Globals.Line.Height'/>
+ <widget name = 'ImageContainer' />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Prev'
+ type = 'Button'
+ />
+ <widget name = 'ImageNumber'
+ width = '50'
+ height = 'Globals.Line.Height'
+ textalign = 'center'
+ />
+ <widget name = 'Next'
+ type = 'Button'
+ />
+ <space/>
+ <widget name = 'Save'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Close'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
</layout_info>
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index 284075fffed..018c076ff3e 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -39,6 +39,7 @@
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '0'/>
<def var = 'RecorderDialog.ExtInfo.Visible' value = '0'/>
+ <def var = 'ImageAlbum.ImageInset' value = '16' scalable = 'yes' />
<def var = 'OnScreenDialog.ShowPics' value = '0'/>
@@ -2172,4 +2173,32 @@
</layout>
</dialog>
+ <dialog name = 'ImageAlbum' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' align = 'center'>
+ <widget name = 'Title' height = 'Globals.Line.Height'/>
+ <widget name = 'ImageContainer' />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Prev'
+ type = 'Button'
+ />
+ <widget name = 'ImageNumber'
+ width = '50'
+ height = 'Globals.Line.Height'
+ textalign = 'center'
+ />
+ <widget name = 'Next'
+ type = 'Button'
+ />
+ <space/>
+ <widget name = 'Save'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Close'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
</layout_info>
Commit: 6f005a75a4b065139a8601d3701c2681e4cd89d0
https://github.com/scummvm/scummvm/commit/6f005a75a4b065139a8601d3701c2681e4cd89d0
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-07T10:22:09+02:00
Commit Message:
TESTBED: Add tests for image album
Changed paths:
A dists/engine-data/testbed-audiocd-files/imagealbum/image1.bmp
A dists/engine-data/testbed-audiocd-files/imagealbum/image2.bmp
A dists/engine-data/testbed-audiocd-files/imagealbum/image3.jpg
engines/testbed/misc.cpp
engines/testbed/misc.h
diff --git a/dists/engine-data/testbed-audiocd-files/imagealbum/image1.bmp b/dists/engine-data/testbed-audiocd-files/imagealbum/image1.bmp
new file mode 100644
index 00000000000..d1e2550be2f
Binary files /dev/null and b/dists/engine-data/testbed-audiocd-files/imagealbum/image1.bmp differ
diff --git a/dists/engine-data/testbed-audiocd-files/imagealbum/image2.bmp b/dists/engine-data/testbed-audiocd-files/imagealbum/image2.bmp
new file mode 100644
index 00000000000..d67ca155453
Binary files /dev/null and b/dists/engine-data/testbed-audiocd-files/imagealbum/image2.bmp differ
diff --git a/dists/engine-data/testbed-audiocd-files/imagealbum/image3.jpg b/dists/engine-data/testbed-audiocd-files/imagealbum/image3.jpg
new file mode 100644
index 00000000000..bd0ca525360
Binary files /dev/null and b/dists/engine-data/testbed-audiocd-files/imagealbum/image3.jpg differ
diff --git a/engines/testbed/misc.cpp b/engines/testbed/misc.cpp
index a0aaee2af4e..c687e1c57d6 100644
--- a/engines/testbed/misc.cpp
+++ b/engines/testbed/misc.cpp
@@ -21,6 +21,12 @@
#include "testbed/misc.h"
#include "common/timer.h"
+#include "common/file.h"
+
+#include "gui/dialog.h"
+#include "gui/imagealbum-dialog.h"
+
+#include "image/jpeg.h"
namespace Testbed {
@@ -182,11 +188,139 @@ TestExitStatus MiscTests::testOpenUrl() {
return kTestPassed;
}
+class ImageAlbumImageSupplier : public GUI::ImageAlbumImageSupplier {
+public:
+ void addFile(const Common::Path &path, Common::FormatInfo::FormatID format, bool dontReportFormat);
+
+ bool loadImageSlot(uint slot, const Graphics::Surface *&outSurface, bool &outHasPalette, byte (&outPalette)[256 * 3], GUI::ImageAlbumImageMetadata &outMetadata) override;
+ void releaseImageSlot(uint slot) override;
+ bool getFileFormatForImageSlot(uint slot, Common::FormatInfo::FormatID &outFormat) const override;
+ Common::SeekableReadStream *createReadStreamForSlot(uint slot) override;
+ uint getNumSlots() const override;
+ Common::U32String getDefaultFileNameForSlot(uint slot) const override;
+
+private:
+ struct FileInfo {
+ FileInfo(const Common::Path &path, Common::FormatInfo::FormatID format, bool dontReportFormat);
+
+ Common::Path _path;
+ Common::FormatInfo::FormatID _format;
+ bool _dontReportFormat;
+
+ Common::SharedPtr<Image::ImageDecoder> _decoder;
+ };
+
+ Common::Array<FileInfo> _slots;
+};
+
+void ImageAlbumImageSupplier::addFile(const Common::Path &path, Common::FormatInfo::FormatID format, bool dontReportFormat) {
+ _slots.push_back(FileInfo(path, format, dontReportFormat));
+}
+
+bool ImageAlbumImageSupplier::loadImageSlot(uint slot, const Graphics::Surface *&outSurface, bool &outHasPalette, byte (&outPalette)[256 * 3], GUI::ImageAlbumImageMetadata &outMetadata) {
+
+ FileInfo &fi = _slots[slot];
+
+ switch (fi._format) {
+ case Common::FormatInfo::kBMP:
+ fi._decoder.reset(new Image::BitmapDecoder());
+ break;
+#ifdef USE_JPEG
+ case Common::FormatInfo::kJPEG:
+ fi._decoder.reset(new Image::JPEGDecoder());
+ break;
+#endif
+ default:
+ return false;
+ }
+
+ Common::ScopedPtr<Common::SeekableReadStream> readStream(createReadStreamForSlot(slot));
+ if (!readStream)
+ return false;
+
+ if (!fi._decoder->loadStream(*readStream))
+ return false;
+
+ outSurface = fi._decoder->getSurface();
+ outHasPalette = fi._decoder->hasPalette();
+ if (fi._decoder->hasPalette())
+ memcpy(outPalette, fi._decoder->getPalette() + fi._decoder->getPaletteStartIndex() * 3, fi._decoder->getPaletteColorCount() * 3);
+ outMetadata = GUI::ImageAlbumImageMetadata();
+
+ return true;
+}
+
+void ImageAlbumImageSupplier::releaseImageSlot(uint slot) {
+ _slots[slot]._decoder.reset();
+}
+
+bool ImageAlbumImageSupplier::getFileFormatForImageSlot(uint slot, Common::FormatInfo::FormatID &outFormat) const {
+ if (_slots[slot]._dontReportFormat)
+ return false;
+
+ outFormat = _slots[slot]._format;
+ return true;
+}
+
+Common::SeekableReadStream *ImageAlbumImageSupplier::createReadStreamForSlot(uint slot) {
+ Common::ScopedPtr<Common::File> f(new Common::File());
+ if (!f->open(_slots[slot]._path))
+ return nullptr;
+
+ return f.release();
+}
+
+uint ImageAlbumImageSupplier::getNumSlots() const {
+ return _slots.size();
+}
+
+Common::U32String ImageAlbumImageSupplier::getDefaultFileNameForSlot(uint slot) const {
+ return Common::U32String(_slots[slot]._path.getLastComponent().toString());
+}
+
+ImageAlbumImageSupplier::FileInfo::FileInfo(const Common::Path &path, Common::FormatInfo::FormatID format, bool dontReportFormat) {
+ _path = path;
+ _format = format;
+ _dontReportFormat = dontReportFormat;
+}
+
+TestExitStatus MiscTests::testImageAlbum() {
+ Common::String info = "Testing ImageAlbum method.\n"
+ "In this test we'll try to display some images,\n"
+ "and you should be able to save them if the backend supports it.\n"
+ "The second image will not report a file format to the backend, the third (if it exists) will be JPEG.\n";
+
+ if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) {
+ Testsuite::logPrintf("Info! Skipping test : ImageAlbum()\n");
+ return kTestSkipped;
+ }
+
+ ImageAlbumImageSupplier imageSupplier;
+ imageSupplier.addFile("imagealbum/image1.bmp", Common::FormatInfo::kBMP, false);
+ imageSupplier.addFile("imagealbum/image2.bmp", Common::FormatInfo::kBMP, true);
+#ifdef USE_JPEG
+ imageSupplier.addFile("imagealbum/image3.jpg", Common::FormatInfo::kJPEG, false);
+#endif
+
+ GUI::Dialog *dialog = GUI::createImageAlbumDialog(Common::U32String("Image Album"), &imageSupplier, 0);
+ dialog->runModal();
+ delete dialog;
+
+ if (Testsuite::handleInteractiveInput("Did the image album work as expected?", "Yes", "No", kOptionRight)) {
+ Testsuite::logDetailedPrintf("Error! ImageAlbum is not working!\n");
+ return kTestFailed;
+ }
+
+ Testsuite::logDetailedPrintf("ImageAlbum is OK\n");
+ return kTestPassed;
+}
+
MiscTestSuite::MiscTestSuite() {
addTest("Datetime", &MiscTests::testDateTime, false);
addTest("Timers", &MiscTests::testTimers, false);
addTest("Mutexes", &MiscTests::testMutexes, false);
addTest("openUrl", &MiscTests::testOpenUrl, true);
+ addTest("ImageAlbum", &MiscTests::testImageAlbum, true);
}
} // End of namespace Testbed
diff --git a/engines/testbed/misc.h b/engines/testbed/misc.h
index 36d339e4621..fd3c4b14359 100644
--- a/engines/testbed/misc.h
+++ b/engines/testbed/misc.h
@@ -51,6 +51,7 @@ TestExitStatus testDateTime();
TestExitStatus testTimers();
TestExitStatus testMutexes();
TestExitStatus testOpenUrl();
+TestExitStatus testImageAlbum();
// add more here
} // End of namespace MiscTests
@@ -71,7 +72,7 @@ public:
return "Misc";
}
const char *getDescription() const override {
- return "Miscellaneous: Timers/Mutexes/Datetime/openUrl";
+ return "Miscellaneous: Timers/Mutexes/Datetime/openUrl/ImageAlbum";
}
};
Commit: 46a0aca35459183eec42646276ae73a93c044e14
https://github.com/scummvm/scummvm/commit/46a0aca35459183eec42646276ae73a93c044e14
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-07T10:22:09+02:00
Commit Message:
MTROPOLIS: Hook up MPZ-1000 to image album
Changed paths:
engines/mtropolis/POTFILES
engines/mtropolis/plugin/mti.cpp
engines/mtropolis/plugin/mti.h
diff --git a/engines/mtropolis/POTFILES b/engines/mtropolis/POTFILES
index 3c7669e2149..4b638b4ab15 100644
--- a/engines/mtropolis/POTFILES
+++ b/engines/mtropolis/POTFILES
@@ -1,3 +1,4 @@
engines/mtropolis/metaengine.cpp
engines/mtropolis/saveload.cpp
engines/mtropolis/mtropolis.cpp
+engines/mtropolis/plugin/mti.cpp
diff --git a/engines/mtropolis/plugin/mti.cpp b/engines/mtropolis/plugin/mti.cpp
index f186e14ed8a..7a913eee285 100644
--- a/engines/mtropolis/plugin/mti.cpp
+++ b/engines/mtropolis/plugin/mti.cpp
@@ -19,6 +19,17 @@
*
*/
+#include "common/file.h"
+#include "common/random.h"
+#include "common/translation.h"
+#include "common/macresman.h"
+
+#include "gui/dialog.h"
+#include "gui/imagealbum-dialog.h"
+
+#include "image/bmp.h"
+#include "image/pict.h"
+
#include "mtropolis/plugin/mti.h"
#include "mtropolis/plugins.h"
@@ -29,8 +40,6 @@
#include "graphics/managed_surface.h"
#include "common/file.h"
-#include "common/random.h"
-
namespace MTropolis {
namespace MTI {
@@ -403,6 +412,126 @@ const char *ShanghaiModifier::getDefaultName() const {
return "Shanghai Modifier"; // ???
}
+class PrintModifierImageSupplier : public GUI::ImageAlbumImageSupplier {
+public:
+ PrintModifierImageSupplier(const Common::String &inputPath, bool isMacVersion);
+
+ bool loadImageSlot(uint slot, const Graphics::Surface *&outSurface, bool &outHasPalette, byte (&outPalette)[256 * 3], GUI::ImageAlbumImageMetadata &outMetadata) override;
+ void releaseImageSlot(uint slot) override;
+ uint getNumSlots() const override;
+ Common::U32String getDefaultFileNameForSlot(uint slot) const override;
+ bool getFileFormatForImageSlot(uint slot, Common::FormatInfo::FormatID &outFormat) const override;
+ Common::SeekableReadStream *createReadStreamForSlot(uint slot) override;
+
+private:
+ Common::String _path;
+
+ Common::SharedPtr<Image::ImageDecoder> _decoder;
+ bool _isMacVersion;
+};
+
+PrintModifierImageSupplier::PrintModifierImageSupplier(const Common::String &inputPath, bool isMacVersion) : _path(inputPath), _isMacVersion(isMacVersion) {
+ if (isMacVersion)
+ _decoder.reset(new Image::PICTDecoder());
+ else
+ _decoder.reset(new Image::BitmapDecoder());
+}
+
+bool PrintModifierImageSupplier::loadImageSlot(uint slot, const Graphics::Surface *&outSurface, bool &outHasPalette, byte (&outPalette)[256 * 3], GUI::ImageAlbumImageMetadata &outMetadata) {
+ Common::ScopedPtr<Common::SeekableReadStream> dataStream(createReadStreamForSlot(slot));
+
+ if (!dataStream)
+ return false;
+
+ if (!_decoder->loadStream(*dataStream)) {
+ warning("Failed to decode print file");
+ return false;
+ }
+
+ dataStream.reset();
+
+ outSurface = _decoder->getSurface();
+ outHasPalette = _decoder->hasPalette();
+
+ if (_decoder->hasPalette())
+ memcpy(outPalette + _decoder->getPaletteStartIndex() * 3, _decoder->getPalette(), _decoder->getPaletteColorCount() * 3);
+
+ outMetadata = GUI::ImageAlbumImageMetadata();
+ outMetadata._orientation = GUI::kImageAlbumImageOrientationLandscape;
+ outMetadata._viewTransformation = GUI::kImageAlbumViewTransformationRotate90CW;
+
+ return true;
+}
+
+void PrintModifierImageSupplier::releaseImageSlot(uint slot) {
+ _decoder->destroy();
+}
+
+uint PrintModifierImageSupplier::getNumSlots() const {
+ return 1;
+}
+
+Common::U32String PrintModifierImageSupplier::getDefaultFileNameForSlot(uint slot) const {
+ Common::String filename = _path;
+
+ size_t lastColonPos = filename.findLastOf(':');
+
+ if (lastColonPos != Common::String::npos)
+ filename = filename.substr(lastColonPos + 1);
+
+ size_t lastDotPos = filename.findLastOf('.');
+ if (lastDotPos != Common::String::npos)
+ filename = filename.substr(0, lastDotPos);
+
+ if (_isMacVersion)
+ filename += Common::U32String(".pict");
+ else
+ filename += Common::U32String(".bmp");
+
+ return filename.decode(Common::kASCII);
+}
+
+bool PrintModifierImageSupplier::getFileFormatForImageSlot(uint slot, Common::FormatInfo::FormatID &outFormat) const {
+ if (slot != 0)
+ return false;
+
+ if (_isMacVersion)
+ outFormat = Common::FormatInfo::kPICT;
+ else
+ outFormat = Common::FormatInfo::kBMP;
+
+ return true;
+}
+
+Common::SeekableReadStream *PrintModifierImageSupplier::createReadStreamForSlot(uint slot) {
+ if (slot != 0)
+ return nullptr;
+
+ size_t lastColonPos = _path.findLastOf(':');
+ Common::String filename;
+
+ if (lastColonPos == Common::String::npos)
+ filename = _path;
+ else
+ filename = _path.substr(lastColonPos + 1);
+
+ Common::Path path(Common::String("MPZ_MTI/") + filename);
+
+ if (_isMacVersion) {
+ // Color images have res fork data so we must load from the data fork
+ return Common::MacResManager::openFileOrDataFork(path);
+ } else {
+ // Win versions are just files
+ Common::File *f = new Common::File();
+
+ if (!f->open(path)) {
+ delete f;
+ return nullptr;
+ }
+ return f;
+ }
+}
+
PrintModifier::PrintModifier() {
}
@@ -414,13 +543,32 @@ bool PrintModifier::respondsToEvent(const Event &evt) const {
}
VThreadState PrintModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
- warning("Print modifier is not implemented");
+ if (_executeWhen.respondsTo(msg->getEvent())) {
+ PrintModifierImageSupplier imageSupplier(_filePath, runtime->getProject()->getPlatform() == kProjectPlatformMacintosh);
+
+ Common::ScopedPtr<GUI::Dialog> dialog(GUI::createImageAlbumDialog(_("Image Viewer"), &imageSupplier, 0));
+ dialog->runModal();
+ }
+
return kVThreadReturn;
}
void PrintModifier::disable(Runtime *runtime) {
}
+MiniscriptInstructionOutcome PrintModifier::writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) {
+ if (attrib == "showdialog") {
+ // This is only ever set to "false"
+ DynamicValueWriteDiscardHelper::create(writeProxy);
+ return kMiniscriptInstructionOutcomeContinue;
+ } else if (attrib == "filepath") {
+ DynamicValueWriteStringHelper::create(&_filePath, writeProxy);
+ return kMiniscriptInstructionOutcomeContinue;
+ }
+
+ return Modifier::writeRefAttribute(thread, writeProxy, attrib);
+}
+
bool PrintModifier::load(const PlugInModifierLoaderContext &context, const Data::MTI::PrintModifier &data) {
if (data.executeWhen.type != Data::PlugInTypeTaggedValue::kEvent)
return false;
diff --git a/engines/mtropolis/plugin/mti.h b/engines/mtropolis/plugin/mti.h
index 637c5484f32..ca013a95601 100644
--- a/engines/mtropolis/plugin/mti.h
+++ b/engines/mtropolis/plugin/mti.h
@@ -103,6 +103,8 @@ public:
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
void disable(Runtime *runtime) override;
+ MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
+
bool load(const PlugInModifierLoaderContext &context, const Data::MTI::PrintModifier &data);
#ifdef MTROPOLIS_DEBUG_ENABLE
Commit: 58271a834cf669bfa0ab2abe89ba437981f1c3c6
https://github.com/scummvm/scummvm/commit/58271a834cf669bfa0ab2abe89ba437981f1c3c6
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-07T10:22:09+02:00
Commit Message:
COMMON: Remove #pragma once
Changed paths:
common/formats/formatinfo.h
diff --git a/common/formats/formatinfo.h b/common/formats/formatinfo.h
index 05d6769155f..206125d9d43 100644
--- a/common/formats/formatinfo.h
+++ b/common/formats/formatinfo.h
@@ -1,4 +1,3 @@
-#pragma once
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
Commit: 9598e343a35eb3d3d452d09f645a4c23adf2f96b
https://github.com/scummvm/scummvm/commit/9598e343a35eb3d3d452d09f645a4c23adf2f96b
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-07T10:22:09+02:00
Commit Message:
GUI: Add imagealbum-dialog.cpp to POTFILES
Changed paths:
po/POTFILES
diff --git a/po/POTFILES b/po/POTFILES
index f1cafc86a24..ba86acdb24b 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -10,6 +10,7 @@ gui/error.cpp
gui/filebrowser-dialog.cpp
gui/fluidsynth-dialog.cpp
gui/gui-manager.cpp
+gui/imagealbum-dialog.cpp
gui/launcher.cpp
gui/massadd.cpp
gui/message.cpp
Commit: eea428cbc350501c70ded31081721cb722440585
https://github.com/scummvm/scummvm/commit/eea428cbc350501c70ded31081721cb722440585
Author: elasota (ejlasota at gmail.com)
Date: 2023-08-07T10:22:09+02:00
Commit Message:
GUI: Update theme binaries
Changed paths:
gui/themes/residualvm.zip
gui/themes/scummclassic.zip
gui/themes/scummmodern.zip
gui/themes/scummremastered.zip
diff --git a/gui/themes/residualvm.zip b/gui/themes/residualvm.zip
index 02aa00024e3..b7935ba4d4b 100644
Binary files a/gui/themes/residualvm.zip and b/gui/themes/residualvm.zip differ
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index e9d2bd8b43b..efb7846a940 100644
Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index 70137e0a9e5..1152b6736b2 100644
Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ
diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip
index dacee6f204f..fc4fd3fa974 100644
Binary files a/gui/themes/scummremastered.zip and b/gui/themes/scummremastered.zip differ
More information about the Scummvm-git-logs
mailing list