If a Supplementary Volume Descriptor is present, check for the Joliet
UCS-2 escape sequences. If found, use the SVD root directory.
Filenames in the SVD root directory are encoded in UCS-2 (big-endian).
The filename length is in bytes, not code points.
NOTE: Currently using a very cheap hack to convert UCS-2 to cp1252,
or more accurately, ISO-8859-1. It's good enough for our purposes
for now. (specifically, getting the icon from AUTORUN.INF.)
TODO: Better character set conversion.
This fixes a Windows build regression from commit 9994c2df94.
([libromdata] RomDataFactory: Explicitly prevent ".ico" and ".cur" from being thumbnailed on Windows.)
This function takes a zero-based index and returns a resource ID for
the given resource type if it's within range. Otherwise, it returns
a negative POSIX error code.
[libromdata] PEResourceReader, NEResourceReader: Implement it.
[libromdata] EXE: Use lookup_resource_ID for positive icon indexes.
This fixes thumbnailing for discs whose AUTORUN.INF specify a
positive, non-zero icon index.
TODO: Older discs may have truncated ISO-9660 filenames. Need to
parse Joliet file systems, maybe...
The icon index can be:
- 0: First icon
- >0: Zero-based icon index
- <0: Resource ID
EXE: New function loadSpecificIcon() to load an icon given an index.
For iconindex == 0, the icon is cached in d->img_icon.
TODO: Implement a function in IResourceReader to look up a resource ID
from the zero-based index.
Uses the first icon in the first available language.
New function loadResourceReader() which ensures rsrcReader is loaded.
[librptexture] ICO: Fix resource loading issues:
- Use the correct resource file pointer, not this->file.
- Add IconRes_Win3 and CursorRes_Win3 cases where appropriate.
- Ensure d->iconType doesn't get overwritten after it's set by the
ICOPrivate constructor for resources.
FIXME: VBoxWindowsAdditions.exe's PNG icon loads fine, but the 128x128
"regular" icon is corrupted.
Also add a note saying EXE shouldn't be registered for thumbnailing,
either.
This will still allow using `rpcli`, and for subclasses to use
EXE to thumbnail e.g. ISO images.
NOT TESTED; need to add it to the EXE class to test it.
(.ico files still work as they did before.)
Added a constructor that takes an IResourceReaderPtr and the
type/id/lang of the icon. Type should be RT_GROUP_ICON or
RT_GROUP_CURSOR. These are all saved in icodir_res.
The dir union is now initialized in the ICOPrivate constructors,
and is only reset in the ICOPrivate destructor.
loadImage_Win3(): Use a new IRpFilePtr for the icon data.
- For .ico, it's a copy of this->file.
- For Windows executables, it's opened from the IResourceReader.
- Starting address is the icon bitmap address for .ico and
0 for IResourceReader.
In file included from src/libromdata/stdafx.h:63,
from src/libromdata/Media/ISO.cpp:10:
src/libromdata/Media/ISO.cpp: In member function ‘virtual uint32_t LibRomData::ISO::imgpf(LibRpBase::RomData::ImageType) const’:
src/libromdata/../common.h:93:45: warning: unused variable ‘d’ [-Wunused-variable]
93 | # define RP_D(klass) klass##Private *const d = static_cast<klass##Private*>(d_ptr)
| ^
src/libromdata/Media/ISO.cpp:984:9: note: in expansion of macro ‘RP_D’
984 | RP_D(const ISO);
| ^~~~
This is a bit cleaner than the casting method, though it is a bit messy
at points.
isResource(): Returns true if it's an icon from a resource.
(Currently not set at all...)
reset_dir_union(): Clear the directory union. Called in ICOPrivate's
destructor and various error paths.
TODO: Add resource loading. May need to move IResourceReader from
libromdata to librpbase.
ICONDIR and GRPICONDIR are basically the same, but ICONDIRENTRY and
GRPICONDIRENTRY have different sizes. Use an rp::uvector<uint8_t>
and casting to handle this.
Still only supports .ico files for now.
Limitations:
- Only supports .ico, not .exe.
- The filename must match the ISO-9660 filename. Some older Win9x
discs use a long filename in AUTORUN.INF that's only listed as
such in the Joliet extension.
Removed some debugging code from the IsoPartition readdir()
implementation testing from earlier.
fromLinearCI4() doesn't support Host_xRGB32, and we're filling
in the alpha channel ourselves.
TODO: Add Host_xRGB32 support to fromLinearCI4()?
fromLinearCI8() supports it...
This fixes a regression from commit de802835f7.
([librptexture] ICO: Handle 8-bit color icons.)
First, the image size is checked. If either width or height are larger
than the previously-selected image, this image is picked. Otherwise,
if the size is identical (both width and height), and bitcount is
higher, then the image is selected.
TODO: Better non-square icon handling? (Use "largest area"?)
- Forgot to move convimg to img when converting from CI8 to ARGB32.
- Make sure sBIT is updated with alpha=1. Otherwise, RpPng::save()
will tell libpng that there's no alpha, so the resulting PNG image
saved using `rpcli -x3` won't be transparent.
iconHeader is now saved in the private class instead of being loaded
in loadImage_Win3().
The dimensions are now set correctly when an icon's "best" image is
in PNG format.
ico_structs.h: Add PNG chunks.
NOTE: BI_BITFIELDS is not supported right now. (Is that even used for
32-bit ARGB, or is it for 16/24 only?)
Fix mask handling for 48x48 icons by aligning stride to 32-bit.
For these icons, an extra transparent color is added.
The image is flipped *after* the mask is applied because the mask is
also upside-down.
TODO:
- Set sBIT.
- Apply the icon mask for CI8 and higher-color icons. (CI8 will need to
be converted to ARGB32.)
This seems to place the mask image at the top of the image once it's
flipped, but maybe it's that it's technically two bitmaps and not
one giant bitmap.
TODO: Test it with a right-side up icon.
The entire icon directory is loaded, but currently the first icon is
loaded instead of selecting the "best" icon.
NOTE: Windows Vista and later determines the "best" icon by looking at
the BITMAPINFOHEADER, not the icon directory. We'll do that too.
loadImage_Win3(): Added support for loading 16-color icons, including
the palette (color table). The mask is loaded, but it isn't applied
yet.
TODO:
- Support more icon formats.
- Apply the mask.
- Determine if the mask isn't present? (e.g. in 32-bit icons)
This converts the Windows 1bpp icon using the mask for transparency.
(Inversion is *not* supported.)
Also, 0 == black, 1 == white. This is the opposite of fromLinearMono(),
which is mostly used for things like VMU icons.
TODO: Handle upside-down images. Win1.x icons and cursors are
right-side up, but Win3.x is upside-down.
ICOPrivate::loadImage_Win1(): Call fromLinearMono_WinIcon().
Tested with the Windows 2.0 DDK icons and cursors, and all of them
appear to be decoding correctly.
This will eventually be used for ISO image thumbnailing, though it might
also be useful on some other systems.
Linux desktop environments typically have their own ICO thumbnailer.
NOTE: This might still be useful even if the system supports ICO:
- 64-bit Windows cannot read 16-bit Windows executables.
- No current Windows version supports Windows 1.x icons.
- Linux thumbnailers typically don't support Windows 1.x icons, either.
This implementation currently *only* supports Windows 1.x icons, and
doesn't handle masking.
TODO: ImageDecoder::fromLinearMono_WinIcon()?
NOTE: Icon MIME types haven't been added to the XDG files yet, so they
won't be thumbnailed yet (or, more likely, conflict with the system
thumbnailer).
This fixes opendir("/NT3x/") for VBoxGuestAdditions.iso.
Note that this may be slightly slower than the old method due to string
copying, but it's much cleaner.
findLastSlash(): Now uses an internal function with a `size` parameter,
and has two wrapper functions: one for `const char*`, and one for
`std::string`.
Tested using VBoxGuestAdditions.iso from VirtualBox 7.1.8.
Skip subdirectories with names "\x00" and "\x01". These are Joliet
"special directory identifiers".
IFst:
- Change `dir_idx` from int to intptr_t.
- Add two explicit constructors with a `dir_idx` parameter.
One takes intptr_t; the other takes void*.
- Added an `extra` parameter for temporary filename storage.
The ISO-9660 directory entry does not have NULL termination for
the filename, so we need the temporary buffer to add the terminator.
GcnFst, WiiUFst:
- Update for the `dir_idx` constructor parameter.
- Zero out the `extra` parameter.
TODO:
- Move it to a new IFst subclass, IsoFst?
- Remove the file version number, e.g. ";1"?
- Handle "/NT3x/". Currently, "/NT3x" works, but the trailing slash
confuses the directory lookup function.
- Joliet subdirectory support?
This ensures the caller won't modify the DirEnt.
Note that this doesn't match POSIX readdir(), but we don't need to
strictly match it. (We're also not returning `struct dirent*`; we're
returning a custom one.)
It's slightly less efficient than manually building the string, but
this lets us reformat the text more easily later on, if needed.
Code size differences: (64-bit Gentoo Linux, gcc-15.1.0, release build, no LTO)
text data bss dec hex filename
14174 72 5 14251 37ab AchQtDBus.cpp.o [kf5] [before]
14221 72 5 14298 37da AchQtDBus.cpp.o [kf5] [after]
+47 0 0 +47 +2f Difference
text data bss dec hex filename
12995 200 5 13200 3390 AchQtDBus.cpp.o [kf6] [before]
13164 200 5 13369 3439 AchQtDBus.cpp.o [kf6] [after]
+169 0 0 +169 +a9 Difference
On Qt5 and Qt6, QString::toStdString() converts the string to a UTF-8
std::string, so this simply wraps around that.
On Qt4, QString::toStdString() uses QString::toAscii(), so instead,
we use QString::toUtf8().constData() and convert that into an std::string.
This is more efficient when saving to an std::string, since Q2U8() only
returns the data pointer, which makes it an implicit-length C string.
Q2U8_StdString() is now used wherever an std::string needs to be saved.
Updated all other uses to use Q2U8() instead of QString::toUtf8().constData().
FIXME: RpFileKio::filename():
- Q2U8() returns a temporary, which may be gone by the time this function
returns...
Code size differences: (64-bit Gentoo Linux, gcc-15.1.0, release build, no LTO)
text data bss dec hex filename
30982 1648 48 32678 7fa6 kfilemetadata_rom-properties-kf5.so [before]
30846 1648 48 32542 7f1e kfilemetadata_rom-properties-kf5.so [after]
-136 0 0 -136 -88 Difference
text data bss dec hex filename
26844 1456 48 28348 6ebc overlayiconplugin_rom-properties-kf5.so [before]
26726 1456 48 28230 6e46 overlayiconplugin_rom-properties-kf5.so [after]
-118 0 0 -118 -76 Difference
text data bss dec hex filename
599947 21896 64 621907 97d53 rom-properties-kf5.so [before]
600363 21896 64 622323 97ef3 rom-properties-kf5.so [after]
+416 0 0 +416 +1a0 Difference
text data bss dec hex filename
55979 2824 48 58851 e5e3 RomThumbnailCreator-kf5.so [before]
55795 2824 48 58667 e52b RomThumbnailCreator-kf5.so [after]
-184 0 0 -184 -b8 Difference
text data bss dec hex filename
78593 5144 48 83785 14749 xattrview-kf5.so [before]
78546 5152 48 83746 14722 xattrview-kf5.so [after]
-47 +8 0 -39 -27 Difference
text data bss dec hex filename
33049 1760 48 34857 8829 kfilemetadata_rom-properties-kf6.so [before]
32497 1752 48 34297 85f9 kfilemetadata_rom-properties-kf6.so [after]
-552 -8 0 -560 -230 Difference
text data bss dec hex filename
28794 1584 48 30426 76da overlayiconplugin_rom-properties-kf6.so [before]
28350 1568 48 29966 750e overlayiconplugin_rom-properties-kf6.so [after]
-444 -16 0 -460 -1cc Difference
text data bss dec hex filename
595782 29168 80 625030 98986 rom-properties-kf6.so [before]
595959 29176 80 625215 98a3f rom-properties-kf6.so [after]
+177 +8 0 +185 +b9 Difference
text data bss dec hex filename
61854 3352 48 65254 fee6 RomThumbnailCreator-kf6.so [before]
61649 3360 48 65057 fe21 RomThumbnailCreator-kf6.so [after]
-205 +8 0 -197 -c5 Difference
text data bss dec hex filename
76033 6224 48 82305 14181 xattrview-kf6.so [before]
75690 6216 48 81954 14022 xattrview-kf6.so [after]
-343 -8 0 -351 -15f Difference
It's only used by librpbase internally.
This is technically an ABI break, even though these functions weren't
used outside of librpbase, so bump the SOVERSION to 7.