mirror of https://github.com/stella-emu/stella.git
added reading and displaying image labels
This commit is contained in:
parent
15ecfc1887
commit
b243e4867b
|
@ -38,7 +38,7 @@ PNGLibrary::PNGLibrary(OSystem& osystem)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PNGLibrary::loadImage(const string& filename, FBSurface& surface)
|
||||
void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantList& comments)
|
||||
{
|
||||
png_structp png_ptr{nullptr};
|
||||
png_infop info_ptr{nullptr};
|
||||
|
@ -114,6 +114,9 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface)
|
|||
// We're finished reading
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
|
||||
// Read the comments we got
|
||||
readComments(png_ptr, info_ptr, comments);
|
||||
|
||||
// Load image into the surface, setting the correct dimensions
|
||||
loadImagetoSurface(surface);
|
||||
|
||||
|
@ -335,6 +338,7 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
|||
// Some text fields to add to the PNG snapshot
|
||||
VariantList comments;
|
||||
ostringstream version;
|
||||
VarList::push_back(comments, "Title", "Snapshot");
|
||||
version << "Stella " << STELLA_VERSION << " (Build " << STELLA_BUILD << ") ["
|
||||
<< BSPF::ARCH << "]";
|
||||
VarList::push_back(comments, "Software", version.str());
|
||||
|
@ -448,6 +452,23 @@ void PNGLibrary::writeComments(const png_structp png_ptr, png_infop info_ptr,
|
|||
png_set_text(png_ptr, info_ptr, text_ptr.data(), numComments);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PNGLibrary::readComments(const png_structp png_ptr, png_infop info_ptr,
|
||||
VariantList& comments)
|
||||
{
|
||||
png_textp text_ptr;
|
||||
int numComments = 0;
|
||||
|
||||
// TODO: currently works only if comments are *before* the image data
|
||||
png_get_text(png_ptr, info_ptr, &text_ptr, &numComments);
|
||||
|
||||
comments.clear();
|
||||
for(int i = 0; i < numComments; ++i)
|
||||
{
|
||||
VarList::push_back(comments, text_ptr[i].key, text_ptr[i].text);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PNGLibrary::png_read_data(const png_structp ctx, png_bytep area, png_size_t size)
|
||||
{
|
||||
|
|
|
@ -52,7 +52,7 @@ class PNGLibrary
|
|||
runtime_error is thrown containing a more detailed
|
||||
error message.
|
||||
*/
|
||||
void loadImage(const string& filename, FBSurface& surface);
|
||||
void loadImage(const string& filename, FBSurface& surface, VariantList& comments);
|
||||
|
||||
/**
|
||||
Save the current FrameBuffer image to a PNG file. Note that in most
|
||||
|
@ -183,6 +183,12 @@ class PNGLibrary
|
|||
void writeComments(const png_structp png_ptr, png_infop info_ptr,
|
||||
const VariantList& comments);
|
||||
|
||||
/**
|
||||
Read PNG tEXt chunks from the image.
|
||||
*/
|
||||
void readComments(const png_structp png_ptr, png_infop info_ptr,
|
||||
VariantList& comments);
|
||||
|
||||
/** PNG library callback functions */
|
||||
static void png_read_data(const png_structp ctx, png_bytep area, png_size_t size);
|
||||
static void png_write_data(const png_structp ctx, png_bytep area, png_size_t size);
|
||||
|
|
|
@ -305,8 +305,8 @@ void LauncherDialog::addRomWidgets(int ypos)
|
|||
const int listHeight = _h - ypos - VBORDER - buttonHeight - VGAP * 3;
|
||||
|
||||
const float imgZoom = getRomInfoZoom(listHeight);
|
||||
const int romWidth = imgZoom * TIAConstants::viewableWidth;
|
||||
const int listWidth = _w - (romWidth > 0 ? romWidth + fontWidth : 0) - HBORDER * 2;
|
||||
const int imageWidth = imgZoom * TIAConstants::viewableWidth;
|
||||
const int listWidth = _w - (imageWidth > 0 ? imageWidth + fontWidth : 0) - HBORDER * 2;
|
||||
|
||||
// remember initial ROM directory for returning there via home button
|
||||
instance().settings().setValue("startromdir", getRomDir());
|
||||
|
@ -319,7 +319,7 @@ void LauncherDialog::addRomWidgets(int ypos)
|
|||
wid.push_back(myList);
|
||||
|
||||
// Add ROM info area (if enabled)
|
||||
if(romWidth > 0)
|
||||
if(imageWidth > 0)
|
||||
{
|
||||
xpos += myList->getWidth() + fontWidth;
|
||||
|
||||
|
@ -327,16 +327,22 @@ void LauncherDialog::addRomWidgets(int ypos)
|
|||
const Common::Size imgSize(TIAConstants::viewableWidth * imgZoom,
|
||||
TIAConstants::viewableHeight * imgZoom);
|
||||
// Calculate font area, and in the process the font that can be used
|
||||
const Common::Size fontArea(romWidth - fontWidth * 2,
|
||||
myList->getHeight() - imgSize.h - VGAP * 3);
|
||||
|
||||
// Infofont is unknown yet, but used in image label too. Assuming maximum font height.
|
||||
int imageHeight = imgSize.h + RomImageWidget::labelHeight(_font);
|
||||
|
||||
const Common::Size fontArea(imageWidth - fontWidth * 2,
|
||||
myList->getHeight() - imageHeight - VGAP * 4);
|
||||
setRomInfoFont(fontArea);
|
||||
|
||||
// Now we have the correct font height
|
||||
imageHeight = imgSize.h + RomImageWidget::labelHeight(*myROMInfoFont);
|
||||
myRomImageWidget = new RomImageWidget(this, *myROMInfoFont,
|
||||
xpos, ypos, romWidth, imgSize.h);
|
||||
xpos, ypos, imageWidth, imageHeight);
|
||||
|
||||
int yofs = imgSize.h + _font.getFontHeight() / 2;
|
||||
const int yofs = imageHeight + VGAP * 2;
|
||||
myRomInfoWidget = new RomInfoWidget(this, *myROMInfoFont,
|
||||
xpos, ypos + yofs, romWidth, myList->getHeight() - yofs);
|
||||
xpos, ypos + yofs, imageWidth, myList->getHeight() - yofs);
|
||||
}
|
||||
addToFocusList(wid);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ RomImageWidget::RomImageWidget(GuiObject* boss, const GUI::Font& font,
|
|||
_flags = Widget::FLAG_ENABLED;
|
||||
_bgcolor = kDlgColor;
|
||||
_bgcolorlo = kBGColorLo;
|
||||
myImageHeight = _h - labelHeight(font);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -85,7 +86,7 @@ void RomImageWidget::parseProperties(const FSNode& node)
|
|||
if(mySurface == nullptr)
|
||||
{
|
||||
mySurface = instance().frameBuffer().allocateSurface(
|
||||
_w, _h, ScalingInterpolation::blur);
|
||||
_w, myImageHeight, ScalingInterpolation::blur);
|
||||
mySurface->applyAttributes();
|
||||
|
||||
dialog().addRenderCallback([this]() {
|
||||
|
@ -105,24 +106,22 @@ void RomImageWidget::parseProperties(const FSNode& node)
|
|||
// Get a valid filename representing a snapshot file for this rom and load the snapshot
|
||||
const string& path = instance().snapshotLoadDir().getPath();
|
||||
|
||||
myImageList.clear();
|
||||
myImageIdx = 0;
|
||||
// 1. Try to load snapshots by property name
|
||||
if(getImageList(path + myProperties.get(PropType::Cart_Name)))
|
||||
mySurfaceIsValid = loadPng(myImageList[0].getPath());
|
||||
//mySurfaceIsValid = loadPng(path + myProperties.get(PropType::Cart_Name) + ".png");
|
||||
|
||||
// 2. Also try to load snapshot images by filename
|
||||
if(getImageList(path + node.getNameWithExt("")))
|
||||
mySurfaceIsValid = loadPng(myImageList[0].getPath());
|
||||
|
||||
if(!mySurfaceIsValid)
|
||||
{
|
||||
// 2. If no snapshots with property name exists, try to load snapshot images by filename
|
||||
if(getImageList(path + node.getNameWithExt("")))
|
||||
mySurfaceIsValid = loadPng(myImageList[0].getPath());
|
||||
//mySurfaceIsValid = loadPng(path + node.getNameWithExt("") + ".png");
|
||||
|
||||
if(!mySurfaceIsValid)
|
||||
{
|
||||
// 3. If no ROM snapshots exist, try to load a default snapshot
|
||||
mySurfaceIsValid = loadPng(path + "default_snapshot.png");
|
||||
}
|
||||
// 3. If no ROM snapshots exist, try to load a default snapshot
|
||||
mySurfaceIsValid = loadPng(path + "default_snapshot.png");
|
||||
}
|
||||
|
||||
#else
|
||||
mySurfaceErrorMsg = "PNG image loading not supported";
|
||||
#endif
|
||||
|
@ -144,7 +143,6 @@ bool RomImageWidget::getImageList(const string& filename)
|
|||
|
||||
FSNode node(instance().snapshotLoadDir().getPath());
|
||||
|
||||
myImageList.clear();
|
||||
node.getChildren(myImageList, FSNode::ListMode::FilesOnly, filter, false, false);
|
||||
return myImageList.size() > 0;
|
||||
}
|
||||
|
@ -154,14 +152,29 @@ bool RomImageWidget::loadPng(const string& filename)
|
|||
{
|
||||
try
|
||||
{
|
||||
instance().png().loadImage(filename, *mySurface);
|
||||
VariantList comments;
|
||||
instance().png().loadImage(filename, *mySurface, comments);
|
||||
|
||||
// Scale surface to available image area
|
||||
const Common::Rect& src = mySurface->srcRect();
|
||||
const float scale = std::min(float(_w) / src.w(), float(_h) / src.h()) *
|
||||
const float scale = std::min(float(_w) / src.w(), float(myImageHeight) / src.h()) *
|
||||
instance().frameBuffer().hidpiScaleFactor();
|
||||
mySurface->setDstSize(static_cast<uInt32>(src.w() * scale), static_cast<uInt32>(src.h() * scale));
|
||||
|
||||
// Retrieve label for loaded image
|
||||
myLabel = "";
|
||||
for(auto comment = comments.begin(); comment != comments.end(); ++comment)
|
||||
{
|
||||
if(comment->first == "Title")
|
||||
{
|
||||
myLabel = comment->second.toString();
|
||||
break;
|
||||
}
|
||||
if(comment->first == "Software"
|
||||
&& comment->second.toString().find("Stella") == 0)
|
||||
myLabel = "Snapshot"; // default for Stella snapshots with missing "Title" comment
|
||||
}
|
||||
|
||||
setDirty();
|
||||
return true;
|
||||
}
|
||||
|
@ -177,7 +190,7 @@ bool RomImageWidget::loadPng(const string& filename)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RomImageWidget::handleMouseUp(int x, int y, MouseButton b, int clickCount)
|
||||
{
|
||||
if(isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h)
|
||||
if(isEnabled() && x >= 0 && x < _w && y >= 0 && y < myImageHeight)
|
||||
{
|
||||
if(x < _w/2)
|
||||
{
|
||||
|
@ -186,7 +199,7 @@ void RomImageWidget::handleMouseUp(int x, int y, MouseButton b, int clickCount)
|
|||
loadPng(myImageList[--myImageIdx].getPath());
|
||||
}
|
||||
}
|
||||
else if(myImageIdx < myImageList.size())
|
||||
else if(myImageIdx < myImageList.size() - 1)
|
||||
{
|
||||
loadPng(myImageList[++myImageIdx].getPath());
|
||||
}
|
||||
|
@ -204,10 +217,10 @@ void RomImageWidget::handleMouseMoved(int x, int y)
|
|||
void RomImageWidget::drawWidget(bool hilite)
|
||||
{
|
||||
FBSurface& s = dialog().surface();
|
||||
const int yoff = _h + _font.getFontHeight() / 2;
|
||||
const int yoff = myImageHeight;
|
||||
|
||||
s.fillRect(_x+2, _y+2, _w-4, _h-4, _bgcolor);
|
||||
s.frameRect(_x, _y, _w, _h, kColor);
|
||||
s.fillRect(_x+1, _y+1, _w-2, _h-1, _bgcolor);
|
||||
s.frameRect(_x, _y, _w, myImageHeight, kColor);
|
||||
|
||||
if(!myHaveProperties)
|
||||
{
|
||||
|
@ -220,7 +233,7 @@ void RomImageWidget::drawWidget(bool hilite)
|
|||
const Common::Rect& dst = mySurface->dstRect();
|
||||
const uInt32 scale = instance().frameBuffer().hidpiScaleFactor();
|
||||
const uInt32 x = _x * scale + ((_w * scale - dst.w()) >> 1);
|
||||
const uInt32 y = _y * scale + ((_h * scale - dst.h()) >> 1);
|
||||
const uInt32 y = _y * scale + ((myImageHeight * scale - dst.h()) >> 1);
|
||||
|
||||
// Make sure when positioning the snapshot surface that we take
|
||||
// the dialog surface position into account
|
||||
|
@ -233,6 +246,15 @@ void RomImageWidget::drawWidget(bool hilite)
|
|||
const uInt32 y = _y + ((yoff - _font.getLineHeight()) >> 1);
|
||||
s.drawString(_font, mySurfaceErrorMsg, x, y, _w - 10, _textcolor);
|
||||
}
|
||||
ostringstream buf;
|
||||
buf << myImageIdx + 1 << "/" << myImageList.size();
|
||||
const int yText = _y + myImageHeight + _font.getFontHeight() / 8;
|
||||
const int wText = _font.getStringWidth(buf.str());
|
||||
|
||||
if(myLabel.length())
|
||||
s.drawString(_font, myLabel, _x, yText, _w - wText - _font.getMaxCharWidth() * 2, _textcolor);
|
||||
if(myImageList.size())
|
||||
s.drawString(_font, buf.str(), _x + _w - wText, yText, wText, _textcolor);
|
||||
|
||||
#ifdef PNG_SUPPORT
|
||||
if(isHighlighted())
|
||||
|
|
|
@ -31,6 +31,11 @@ class RomImageWidget : public Widget, public CommandSender
|
|||
int x, int y, int w, int h);
|
||||
~RomImageWidget() override = default;
|
||||
|
||||
static int labelHeight(const GUI::Font& font)
|
||||
{
|
||||
return font.getFontHeight() * 9 / 8;
|
||||
}
|
||||
|
||||
void setProperties(const FSNode& node, const string& md5);
|
||||
void clearProperties();
|
||||
void reloadProperties(const FSNode& node);
|
||||
|
@ -66,6 +71,8 @@ class RomImageWidget : public Widget, public CommandSender
|
|||
string mySurfaceErrorMsg;
|
||||
|
||||
#ifdef PNG_SUPPORT
|
||||
int myImageHeight{0};
|
||||
|
||||
// Contains the list of image names for the current ROM
|
||||
FSList myImageList;
|
||||
|
||||
|
@ -74,6 +81,9 @@ class RomImageWidget : public Widget, public CommandSender
|
|||
|
||||
// Current x-position of the mouse
|
||||
int myMouseX{0};
|
||||
|
||||
// Label for the loaded image
|
||||
string myLabel;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue