mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-11 05:07:00 -04:00
Fix: images were not being loaded from zip files.
wxImage::LoadFile requires the file to be seekable to peek at the header. We work around this by buffering the header in a wrapper class.
This commit is contained in:
+88
-2
@@ -133,9 +133,95 @@ void draw_checker(RotatedDC& dc, const RealRect& rect) {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Image related
|
// ----------------------------------------------------------------------------- : Image related
|
||||||
|
|
||||||
|
/// A wxInputStream in which we can seek, even if the underlying stream can't
|
||||||
|
/** Seeking is used by the wxImage format detection code, to peek at the header.
|
||||||
|
* So we only need to be able to seek back to the beginning.
|
||||||
|
* The solution is to keep a small buffer of the file header.
|
||||||
|
*/
|
||||||
|
class SeekableInputStream : public wxInputStream {
|
||||||
|
public:
|
||||||
|
SeekableInputStream(wxInputStream& stream)
|
||||||
|
: stream(stream) {
|
||||||
|
}
|
||||||
|
bool IsOk() const override {
|
||||||
|
return stream.IsOk();
|
||||||
|
}
|
||||||
|
bool IsSeekable() const override {
|
||||||
|
return pos < BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
size_t LastRead() const override {
|
||||||
|
return last_read;
|
||||||
|
}
|
||||||
|
char Peek() override {
|
||||||
|
if (pos < stream_pos) {
|
||||||
|
return buffer[pos];
|
||||||
|
} else {
|
||||||
|
return stream.Peek();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wxInputStream& Read(void* out_buffer, size_t size) override {
|
||||||
|
last_read = 0;
|
||||||
|
if (pos < stream_pos) {
|
||||||
|
// take from buffer
|
||||||
|
size_t n = min(size, min((size_t)stream_pos, BUFFER_SIZE) - (size_t)pos);
|
||||||
|
memcpy(out_buffer, buffer + pos, n);
|
||||||
|
size -= n;
|
||||||
|
out_buffer = (char*)out_buffer + n;
|
||||||
|
last_read += n;
|
||||||
|
pos += n;
|
||||||
|
}
|
||||||
|
if (size > 0) {
|
||||||
|
assert(pos == stream_pos);
|
||||||
|
// take from stream
|
||||||
|
stream.Read(out_buffer, size);
|
||||||
|
size_t read = stream.LastRead();
|
||||||
|
last_read += read;
|
||||||
|
if (pos < BUFFER_SIZE) {
|
||||||
|
// update buffer
|
||||||
|
memcpy(buffer + pos, out_buffer, min(BUFFER_SIZE - (size_t)pos, read));
|
||||||
|
}
|
||||||
|
stream_pos += read;
|
||||||
|
pos += read;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
wxFileOffset SeekI(wxFileOffset target, wxSeekMode mode = wxFromStart) override {
|
||||||
|
assert(mode == wxFromStart);
|
||||||
|
assert(target < BUFFER_SIZE);
|
||||||
|
if (target < BUFFER_SIZE) {
|
||||||
|
pos = target;
|
||||||
|
return target;
|
||||||
|
} else {
|
||||||
|
return wxInvalidOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wxFileOffset TellI() const override {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
size_t OnSysRead(void* out_buffer, size_t size) override {
|
||||||
|
Read(out_buffer, size);
|
||||||
|
return last_read;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
wxInputStream& stream;
|
||||||
|
static const size_t BUFFER_SIZE = 16;
|
||||||
|
Byte buffer[BUFFER_SIZE];
|
||||||
|
// positions:
|
||||||
|
// Invariant: pos < stream_pos ==> pos < BUFFER_SIZE && buffer[i] is valid for i<=pos
|
||||||
|
wxFileOffset stream_pos = 0; // position in underlying stream
|
||||||
|
wxFileOffset pos = 0; // position taking into account any seeking done.
|
||||||
|
size_t last_read = 0;
|
||||||
|
};
|
||||||
|
|
||||||
bool image_load_file(Image& image, wxInputStream &stream) {
|
bool image_load_file(Image& image, wxInputStream &stream) {
|
||||||
wxLogNull noLog;
|
wxLogNull noLog; // prevent wx from showing popups about sRGB profiles and other notices
|
||||||
return image.LoadFile(stream);
|
if (!stream.IsSeekable()) {
|
||||||
|
SeekableInputStream seek_stream(stream);
|
||||||
|
return image.LoadFile(seek_stream);
|
||||||
|
} else {
|
||||||
|
return image.LoadFile(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool image_load_file(Image& image, const wxString &name) {
|
bool image_load_file(Image& image, const wxString &name) {
|
||||||
|
|||||||
@@ -144,8 +144,9 @@ void Package::clearKeepFlag() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Package : inside
|
// ----------------------------------------------------------------------------- : Streams
|
||||||
|
|
||||||
|
/// Class to use as a superclass
|
||||||
class FileInputStream_aux {
|
class FileInputStream_aux {
|
||||||
protected:
|
protected:
|
||||||
wxFileInputStream file_stream;
|
wxFileInputStream file_stream;
|
||||||
@@ -164,8 +165,7 @@ public:
|
|||||||
, wxZipInputStream(file_stream)
|
, wxZipInputStream(file_stream)
|
||||||
{}
|
{}
|
||||||
ZipFileInputStream(const String& filename, wxZipEntry* entry)
|
ZipFileInputStream(const String& filename, wxZipEntry* entry)
|
||||||
: FileInputStream_aux(filename)
|
: ZipFileInputStream(filename)
|
||||||
, wxZipInputStream(file_stream)
|
|
||||||
{
|
{
|
||||||
OpenEntry(*entry);
|
OpenEntry(*entry);
|
||||||
}
|
}
|
||||||
@@ -184,6 +184,8 @@ public:
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Package : inside
|
||||||
|
|
||||||
unique_ptr<wxInputStream> Package::openIn(const String& file) {
|
unique_ptr<wxInputStream> Package::openIn(const String& file) {
|
||||||
if (!file.empty() && file.GetChar(0) == _('/')) {
|
if (!file.empty() && file.GetChar(0) == _('/')) {
|
||||||
// absolute path, open file from another package
|
// absolute path, open file from another package
|
||||||
|
|||||||
Reference in New Issue
Block a user