Repository navigation
Description
Follow-up to #2016. A core font can end up under a hashed name ({stem}-{sha8}{ext}) in two ways, and every reader of a family's files has to handle both. Add one method that answers "what is this family file's own copy, and is it really on disk", and move the readers onto it. Best done after #2016 and the PRs based on it (#2008, #2010 to #2014) have landed.
The two ways
- A Font Manager record has the name: a name rewrite.
Model_Font_Sources::get_record_collisions()maps the plain name to the hashed name,use_hashed_names()writes that into the family's font data, andwith_record_aliases()adds the hashed name to the manifest. The family's file is then actually calledFoo-abcd1234.ttf. - Any other conflict: a path rewrite. The family's file stays
Foo.ttf, andget_font_path()returns the hashed copy if there is one, otherwise the plain file.
What it costs
get_hashed_name()needs an "already hashed" case, because hashed names are manifest keys under the first scheme.Model_Font_Downloader::get_core_font_row()has to translate names itself so sizes and previews read the font's own copy. Under the first scheme they were already right, which is how that was missed.get_core_families()counts a file as on disk throughget_font_path(), which falls back to the plain file. Another font's file with no hashed copy therefore lists as the family's core font, with that file's size, anddelete_downloaded_font()deletes it, whileis_installed()rejects the same file.remove_older_hashed_copies()only runs on a conflict save, so a family with a record collision leaves the older release's hashed copy behind when a new manifest changes the sha. That orphan no longer matchesis_hashed_copy(), soadd_unregistered_fonts_to_mPDF()can register it as a user font.is_on_disk()still uses the plain-name check, so Sun-ExtA/ExtB substitution can disagree with what the finder would load when only a hashed copy exists.- There are several overlapping "is this font present" checks:
is_downloaded(),is_installed(),is_size_conflict(),has_hashed_copy(), and the downloader'sis_conflict()andis_resolved().
Proposal
Add a single resolver on Model_Font_Sources, and have get_core_families(), register_font_data(), the Font Manager rows, delete and the older-copy cleanup use it, ideally without hashed-name aliases in the manifest.
The two schemes can't fully merge, so this is about unifying the reading side:
- A record conflict has to stay a name rewrite that reaches mPDF's font data. mPDF only gives the finder a file name, so if a record and a family both asked for
Foo.ttf, the finder couldn't tell them apart. - Making every conflict a name rewrite would mean a stat per family file whenever font data is registered, and font data that changes whenever a conflict appears.
To decide
Should deleting a family remove another font's file at its name when no hashed copy exists? Delete is currently deliberately "whatever its hash", and tests in Test_Downloaded_Fonts expect that. Counting only the font's own files would protect the file, and would make those tests change. With downloads off, such a family would also drop out of the Font Manager list.
Watch out for
- Failures and back-offs are keyed by the manifest name, and the required-font list and sync read family files, so check those if the manifest's keys change.
- Nothing new on the render path should hash an existing file.
- Constructor signatures stay as they are.
Activity
Use one resolver for a core font's own copy
Use one resolver for a core font's own copy