Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
354 changes: 354 additions & 0 deletions src/embedded.cpp

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions src/embedded.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include <QImage>
#include <QString>

// Thumbnails from a file's own bytes: the picture an EPUB, comic book, OpenDocument, Office Open XML, 3MF, FreeCAD, Krita or OpenRaster file keeps in its zip, or a font's own letters.
namespace Embedded {

bool handles(const QString &mime, const QString &path);

// The kept picture, upright and at most `pixels` on its longer side, or the font's letters on a square of `pixels`; null when there is none.
QImage thumbnail(const QString &path, const QString &mime, int pixels);

} // namespace Embedded
2 changes: 2 additions & 0 deletions src/foldermodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ QString FolderModel::kindForMime(const QString &mime) {
if (mime.startsWith("image/")) return "image";
if (mime.startsWith("video/")) return "video";
if (mime.startsWith("audio/")) return "audio";
// A Type 1 font is PostScript, and so text, to the MIME database; it is shown as the font it is.
if (mime == "application/x-font-type1") return "other";
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Resolved
// Anything readable as text (source code, config, JSON, Ruby, ...) is
// text, whatever its own type is called.
static const QMimeDatabase types;
Expand Down
3 changes: 3 additions & 0 deletions src/previewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ QString Previewer::viewerFor(const QString &mime, bool isDir) {
}
if (mime == "text/markdown")
return "markdown";
// A Type 1 font is PostScript, and so text, to the MIME database; it shows its sample like every other font, never its source.
if (mime == "application/x-font-type1")
return "other";
const QMimeType type = QMimeDatabase().mimeTypeForName(mime);
if (mime.startsWith("text/") || type.inherits("text/plain"))
return "text";
Expand Down
3 changes: 1 addition & 2 deletions src/rawembed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ constexpr quint64 kEntryLength = 12;
constexpr quint64 kMaxValue = 65536;
// SubIFD fan-out is capped, so one count cannot queue unbounded work.
constexpr quint32 kMaxPointers = 64;
// No camera's preview holds more pixels than this; a frame header that claims more would cost a vast decode for nothing.
constexpr quint64 kMaxPixels = 250000000;
using RawEmbed::kMaxPixels;
// The largest embedded JPEG read into memory; a real one is a few MiB.
constexpr quint64 kMaxJpeg = 64 * 1048576;
// SOI plus one frame header: anything shorter is no picture.
Expand Down
3 changes: 3 additions & 0 deletions src/rawembed.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ namespace RawEmbed {

bool handles(const QString &mime);

// No camera's preview holds more pixels than this; a frame header that claims more would cost a vast decode for nothing.
inline constexpr quint64 kMaxPixels = 250000000;

// The largest valid embedded JPEG, upright and at most `pixels` on its longer side; null when the file holds none.
QImage thumbnail(const QString &path, int pixels);

Expand Down
12 changes: 7 additions & 5 deletions src/thumbnails.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "thumbnails.h"
#include "embedded.h"
#include "rawembed.h"

#include <QBuffer>
Expand Down Expand Up @@ -321,9 +322,9 @@ Thumbnails::Thumbnails(const QString &cacheDirectory, const QStringList &thumbna
}

QString Thumbnails::missingPackage(const QString &mime) const {
// Qt draws its own pictures in-process, an installed thumbnailer needs nothing more, and pdftoppm draws a PDF without one.
// Qt draws its own pictures in-process, as Folio draws a picture a file keeps, an installed thumbnailer needs nothing more, and pdftoppm draws a PDF without one.
if ((mime.startsWith("image/") && QImageReader::supportedMimeTypes().contains(mime.toLatin1()))
|| m_thumbnailers.contains(mime)
|| Embedded::handles(mime, {}) || m_thumbnailers.contains(mime)
|| (mime == "application/pdf" && !QStandardPaths::findExecutable("pdftoppm").isEmpty()))
return {};
return packageFor().value(mime);
Expand Down Expand Up @@ -403,10 +404,11 @@ QImage Thumbnails::load(const QString &path, const QString &mime, int size) cons
}

QImage Thumbnails::generate(const QString &path, const QString &mime, int pixels, bool &attempted) const {
// A camera RAW with no installed thumbnailer, the desktop's own answer, shows the JPEG the camera embedded.
if (RawEmbed::handles(mime) && !m_thumbnailers.contains(mime)) {
// A camera RAW, a file that keeps its picture in a zip, or a font, with no installed thumbnailer, the desktop's own answer, is drawn from its own bytes.
if ((RawEmbed::handles(mime) || Embedded::handles(mime, path)) && !m_thumbnailers.contains(mime)) {
attempted = true;
if (const QImage image = RawEmbed::thumbnail(path, pixels); !image.isNull())
const QImage image = RawEmbed::handles(mime) ? RawEmbed::thumbnail(path, pixels) : Embedded::thumbnail(path, mime, pixels);
if (!image.isNull())
return image;
}
// Common photo formats decode fastest in-process; anything Qt can't read
Expand Down
5 changes: 3 additions & 2 deletions src/thumbnails.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ class Thumbnails : public QObject {

static QString cacheKey(const QString &path);
// The spec's fail/<program>-<version>: the number is raised when Folio learns to draw more, so old failures are tried
// again. 3: names with a thumbnailer's codes in them, and PDFs whose thumbnailer couldn't start, are drawn now.
static inline const QString failures = QStringLiteral("fail/folio-3");
// again. 3: names with a thumbnailer's codes in them, and PDFs whose thumbnailer couldn't start, are drawn now. 4: the
// picture a zip keeps inside, as an EPUB or an OpenDocument does.
static inline const QString failures = QStringLiteral("fail/folio-4");
static QString bucketFor(int size);
// A text file's first lines set on a page in the given colors. Made
// fresh each time rather than cached, since the colors follow the theme.
Expand Down
Loading