Optimize watch face - #3500
Draft
alexvanyo wants to merge 26 commits into
Draft
Conversation
…ions Pass flags 12 (short-post table format 3.0 and no-hints) to FontForge Generate to omit the 18,000 glyph name strings from the post table and strip unnecessary TrueType instructions. Size reduction: - 342 KB uncompressed per font file - ~11.29 MB uncompressed reduction across all 33 font TTFs
Remove the unused test watchface XML file from the module resources. This file was packaged into the final APK but never referenced. Size reduction: - Module resources: 342,737 bytes uncompressed reduction - Watchface APK: ~13 KB compressed reduction
…mapping Deduplicate repeating Game of Life cell states within each minute in the generated SFD fonts. Once a pattern stabilizes into a still life or periodic oscillator, identical outlines are defined once and mapped to multiple Unicode character codepoints using FontForge AltUni2 encoding (which populates the TrueType cmap table to point multiple codepoints to the single canonical glyph). Size reduction: - Uncompressed font resources: 151,974,816 bytes (144.93 MB, 38.2%) reduction across all 33 hour font TTFs - Watchface APK: ~1.24 MB compressed reduction
Remove unnecessary leading and trailing whitespace formatting from watchface.xml while preserving all XML element structures, attributes, and character entity references. Size reduction: - watchface.xml resource: 700,695 bytes (700 KB, 11.0%) uncompressed reduction - Watchface APK: ~24 KB compressed reduction
Configure packaging options in wear-watchface-wff-version-4 to exclude unused Kotlin metadata (.kotlin_builtins) and version properties that are packaged by default from dependencies. Since the WFF watchface contains no runtime Kotlin code, these files are not required. Size reduction: - Uncompressed APK footprint: ~54 KB reduction (8 files removed) - Watchface APK: ~13 KB compressed reduction
Convert all 33 generated hour font files from TrueType (.ttf) to OpenType CFF (.otf). Type 2 CharStrings in CFF encode orthogonal line segments and coordinate deltas using compact single-byte opcodes without TrueType's loca table overhead and redundant point flags. Size reduction: - Uncompressed font assets: 108,345,096 bytes (103.33 MB, 44.1% reduction across all 33 fonts) - Release Watchface APK: 8,938,281 bytes (8.52 MB, 30.6% APK reduction, dropping from 29.2 MB down to 20.2 MB)
…e stripping Post-process generated OpenType CFF (.otf) fonts using fontTools CharString specialization to combine adjacent line coordinates into compound Type 2 opcodes (hlineto/vlineto/rlineto). Also strips unnecessary FontForge timestamp (FFTM) and glyph definition (GDEF) metadata tables. Size reduction: - Uncompressed font assets: 1,246,344 bytes (1.19 MB reduction across all 33 fonts, dropping total font size to 129.89 MB)
Expand fontTools post-processing in ConvertSfdToOtf to: - Specialize CFF Private Subrs bytecode - Prune redundant Macintosh (platform 1) cmap subtables, retaining only the Windows Unicode BMP (platform 3) table - Prune redundant Macintosh name records, keeping only platform 3 records Size reduction: - Uncompressed font assets: 26,392 bytes reduction across all 33 fonts
….py script Extract Python fontTools post-processing from build.gradle.kts into a dedicated script (wear-watchface-wff-resources/scripts/optimize_otf.py) with comprehensive docstrings and comments detailing: - Type 2 CharString opcode compaction via specializeProgram - Private Subrs bytecode specialization - Windows Unicode BMP cmap table pruning - Windows Unicode name table minimization - FFTM and GDEF table stripping
- Ensure <Variant> precedes <Font> within <TimeText> - Add required name attributes to root <Group> elements - Add Rectangle DrawElements within PartDraw sampling blocks - Fix Expression name casing from IsTwoZero to isTwoZero - Remove invalid duration attributes from Variant elements in version 1 Validated with wff-validator for formats #1 and #4.
- Update DestructionTests.kt to output lightweight minute contour data files (.data) instead of legacy SplineFontDB (.sfd) syntax - Create wear-watchface-wff-resources/scripts/build_hour_otf.py using fontTools.fontBuilder and T2CharStringPen to compile CFF OTF fonts directly in memory - Replace CreateHourSfd and ConvertSfdToOtf Gradle tasks with BuildHourOtf task - Remove fontforgeCommand and FontForge installation dependencies from gradle.properties and GitHub Actions CI workflows - Remove obsolete SFD solution files and optimize_otf.py script Reduces font compilation time from ~20 minutes to under 5 seconds with zero external FontForge dependencies.
… canonicalization - Implement greedy token subroutinizer in build_hour_otf.py extracting high-frequency drawing sequences into CFF Private.Subrs - Canonicalize polygon contour vertex ordering in DestructionTests.kt to start at top-left minimum vertex, ensuring identical token sequences across repeated geometries - Omit redundant width tokens from Type 2 CharStrings by setting width=None in T2CharStringPen Size reduction: - Uncompressed font size: 56,546,080 bytes (53.93 MB, 41.5% reduction, dropping total font size from 129.86 MB down to 75.94 MB) - Total lifetime uncompressed savings: 299.72 MB (-79.0% reduction from baseline ~379 MB)
- In DestructionTests.kt, extract relative polygon shapes as reusable subroutines (SUBR) and represent each glyph as positioned shape instances (INST) - Simplify build_hour_otf.py to directly map Kotlin-extracted shape subroutines to CFF Private.Subrs, eliminating runtime token n-gram scanning in Python - Maintain fast ~3-second font generation pipeline with 93.4 MB total uncompressed font size and 18.58 MB release APK
…ont character mappings
…n in optimizations report
…h blocks to guarantee pixel-perfect centering
…ast Asian fullwidth ideographs
alexvanyo
force-pushed
the
av/optimize-watch-face
branch
from
August 30, 2026 23:50
db7ae18 to
420b82a
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3500 +/- ##
============================================
+ Coverage 76.72% 78.01% +1.28%
- Complexity 0 270 +270
============================================
Files 283 163 -120
Lines 14507 9917 -4590
Branches 1821 1428 -393
============================================
- Hits 11131 7737 -3394
+ Misses 2567 1506 -1061
+ Partials 809 674 -135
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2926