Skip to content

Thumbnail books, documents, 3D parts, drawings and fonts - #84

Closed
thisisgm wants to merge 2 commits into
omacom:thumbnail-rowsfrom
thisisgm:embedded-thumbnails
Closed

thisisgm wants to merge 2 commits into
omacom:thumbnail-rowsfrom
thisisgm:embedded-thumbnails

Conversation

@thisisgm

@thisisgm thisisgm commented Nov 11, 2026 •

Copy link
Copy Markdown

Files that carry a picture of themselves now show it as their thumbnail, and a font is drawn in its own letters, one commit each with its own tests. This is stacked on #67, whose branch is its base, and adds two commits; the suite goes from 215 to 220 tests. No library or depends entry is added: the containers are zip files read with the zlib #67 already links, and a font is drawn by Qt from the file's bytes.

What you'd notice

  • Books, comics, documents, parts and drawings show their own picture. An EPUB shows its cover, a comic archive (CBZ) its first page, an OpenDocument or Office file the preview it was saved with, a 3MF or FreeCAD part its render, and a Krita or OpenRaster drawing its merged image. Folio reads the zip's directory and that one member by their offsets, never the whole file, on the thumbnail workers like every other thumbnail, with the same cache, the same sizes and the same record of a miss. In the grid, the list, the columns, the details pane and the preview window alike.
  • A font shows "Aa" in itself. A TrueType, OpenType, collection, WOFF, WOFF2 or Type 1 font is drawn black on white from its own bytes and is never added to the application's fonts. A font without those letters shows its first two letters, and one without letters its first two characters. A .otf file is drawn whichever type its extension gives it, since the MIME database shares that ending with an OpenDocument template. A Type 1 font, which is PostScript and so text to the MIME database, is no longer previewed as its source.
  • An installed thumbnailer still wins. As for camera RAW files in Thumbnails: camera RAW, a checked cache, clearer misses #66, Folio draws these only where no thumbnailer is installed for the type, so nothing changes where one already draws them. For a type Folio now draws, the hint that names a package to install is no longer shown.
  • A damaged or hostile file costs nothing. A file is opened without waiting and read only if it is a regular file. At most 8192 entries and 8 MiB of directory are walked, a member over 64 MiB is refused before any memory is taken for it, inflation stops at the size the entry claims, and a picture over the pixel limit RAW files already have is not decoded. Zip64, encrypted and multi-disk archives are refused, and a name inside is only ever compared, never opened as a path.

Screenshots

A folder with two books, a 3MF part, a FreeCAD part, a Krita painting and four fonts, on a machine with no thumbnailer for any of these types. In the grid at its largest tiles: #67 above, this branch below. The symbol font shows what it draws for "A" and "a", an alpha in each case.

The grid before and after

The details pane on a book, each part, the painting and a font: #67 above, this branch below.

The details pane before and after

The same folder as a list: #67 on the left, this branch on the right.

The list before and after

And in columns.

The columns before and after

Tests

Five new cases, each failing without its commit: every type shows the member it keeps, picked out by its size, with both EPUB generations, both ways an Office or 3MF file names its thumbnail, and the fallback members; a container without its picture, or a broken one, is remembered as a miss and not read again; each limit above is shown at its edge (8192 entries drawn and 8193 not, 64 MiB drawn and one byte more not, a stream that inflates past its claim, zip64, encryption, a second disk, an absolute path inside, a picture claiming 20000 by 20000 pixels, a pipe named like a document); a container is read on a thumbnail worker and never once its request is cancelled; and a font is drawn in its own letters with each fallback, as a collection, as WOFF and as an .otf, and never joins the application's fonts. The case that names the package for a type now checks that an OpenDocument file names none. Every commit builds and passes the suite on its own, also with TMPDIR set to a folder whose name has a space, where only extractRefusesWhatWouldLandOutside fails, as it does on main.

Limits

  • WOFF2 and Type 1 fonts are drawn when the system's FreeType decodes them; no case here builds one.
  • A font file over 64 MiB is not drawn.
  • An .otf file is still named an OpenDocument formula template in its type line. Naming it a font is part of Previews: archive names, font sheets, media length #63.

An e-book, a comic book archive, an OpenDocument or Office file, a
3MF or FreeCAD model and a Krita or OpenRaster drawing keep a cover
or a preview picture in their zip. With no thumbnailer installed for
the type, Folio now reads that picture itself, by offset and within
named limits, on the road RAW photos already take.
@greptile-apps

greptile-apps Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge, with the earlier non-blocking font-scan concern still open.

Findings

  1. P2 Symbol fonts waste worker time ▶

Summary

Adds thumbnails from pictures stored inside books, documents, parts, and drawings, plus font samples drawn from each font’s own bytes.

  • Files with saved pictures now show them as thumbnails.
  • Font files show a sample drawn from their own letters.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Thumbnail request] --> B{Fresh cached picture?}
  B -->|Yes| C[Return picture]
  B -->|No| D{Installed thumbnailer?}
  D -->|Yes| E[Run thumbnailer]
  D -->|No, supported embedded format| F[Read stored picture or draw font]
  E --> G[Save picture or failure]
  F --> G
Loading

Reviews (2) · Last reviewed commit: "Thumbnail a font by drawing it" · Reviewed by Greptile

Comment thread src/foldermodel.cpp Resolved
Comment thread src/embedded.cpp
Comment on lines +265 to +269
for (char32_t c = kFirstCharacter; c <= kLastCharacter && letters.size() < 2; ++c) {
const bool letter = QChar::isLetter(c);
if ((!letter && drawable.size() == 2) || !QChar::isPrint(c) || QChar::isSpace(c))
continue;
if (const std::optional<quint32> glyph = glyphFor(font, c)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Symbol fonts waste worker time

sample() scans through 0x10FFFF whenever a font has fewer than two drawable letters. Symbol-only fonts therefore walk the whole Unicode range even after finding both fallback characters, calling glyphFor() for every printable letter. This adds needless work to each uncached thumbnail and holds a thumbnail worker until the scan ends. Walk the font’s mapped characters instead, or bound the search.

A font file showed only its icon unless a font thumbnailer was
installed. Folio now draws "Aa" in the font itself, read from the
file's bytes and never added to the application's fonts, or the
first letters the font has when it lacks those.
@thisisgm
thisisgm force-pushed the embedded-thumbnails branch from 6779b78 to d5d1ed7 Compare November 11, 2026 22:41
@thisisgm thisisgm closed this Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant