Re-introduce Duotone Icon Support for FA v6/v7#302
Open
DontBullyMeIllCode wants to merge 3 commits intofluttercommunity:masterfrom
Open
Re-introduce Duotone Icon Support for FA v6/v7#302DontBullyMeIllCode wants to merge 3 commits intofluttercommunity:masterfrom
DontBullyMeIllCode wants to merge 3 commits intofluttercommunity:masterfrom
Conversation
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.
Re-introduce duotone icon support for FA v6/v7
I have been a user of font_awesome_flutter since V5. It is the only icon system I use and wanted to contribute as well as enable a feature I have been missing.
Duotone icon support was dropped when Font Awesome v6 switched from separate Unicode codepoints per layer to a ligature-based system that Flutter's
Icon/IconDatapipeline couldn't handle. This PR brings it back by bypassing that pipeline entirely and using stackedRichTextwidgets with OTF name-based ligatures, which Flutter 3.32.5+ resolves correctly via HarfBuzz.Problem
Font Awesome v6/v7 duotone icons encode their two layers (primary and secondary) using OpenType ligature substitution in the font's GSUB table. Flutter's
IconDataonly accepts a single integer codepoint and the icon tree-shaker strips any glyph only reachable via ligatures — making duotone icons impossible through the standardIconwidget.Solution
FaDuotoneIcon— renders duotone icons by stacking twoRichTextwidgets in aStack, one per layer, with independent color and opacity controlsicon-name#produces the primary glyph,icon-name##produces the secondary glyphFontFamily(not an icon font), so Flutter's icon tree-shaker ignores it entirelyFaDuotoneIconData— stores the icon's codepoint (for identification), ligature name (for rendering), and font family. The old v5-era class with twoIconDatafields is replaced--duotoneflag — generatesFontAwesomeDuotoneIconsconstants (withligatureName) directly intofont_awesome_flutter.dartalongsideFontAwesomeIconsFiles changed
lib/src/icon_data.dartFaDuotoneIconData— singlecodePoint+ligatureName+fontFamily, withprimaryGlyph/secondaryGlyphgetterslib/src/fa_duotone_icon.dartFaDuotoneIconwidget with full parity toFaIcon(color, size, shadows, font variations, blend mode, text scaling, semantics)lib/font_awesome_flutter.dartfa_duotone_icon.dartpubspec.yamlutil/lib/main.dart--duotoneflag;generateDuotoneIconDefinitionClass()appendsFontAwesomeDuotoneIconsto main generated file; parses FA v7svgs.duotoneandsvgs.sharp-duotonefamilies with all weight variants; wildcard'duotone'exclusion covers all variants;duotoneStyleToFontFamilydelegates tostyleToFontFamilyfor correct multi-word mappingtest/fa_duotone_icon_test.dartFaDuotoneIconData(ligature strings, equality, all 8 font families) andFaDuotoneIcon(sizing, colors, opacity, swap, font family passthrough, shadows, font variations, blend mode, text scaling, semantics, IconTheme integration)example/lib/main.dartDuotoneShowcasePagewith three demo icons; added palette button in app bar to navigate toDuotoneShowcaseexample/lib/duotone_showcase.dartREADME.md.gitignore**/ephemeral/to ignore Flutter build artifactsHow it works
Usage
Weight variants
All 8 duotone font variants are supported (4 weights x 2 families):
FontAwesomeDuotoneFontAwesomeDuotoneRegularregularFontAwesomeDuotoneLightlightFontAwesomeDuotoneThinthinFontAwesomeSharpDuotonesharpFontAwesomeSharpDuotoneRegularsharpRegularFontAwesomeSharpDuotoneLightsharpLightFontAwesomeSharpDuotoneThinsharpThinThe
--exclude duotoneflag uses wildcard matching to exclude all duotone variants at once(same pattern as
--exclude sharp).Requirements
--duotoneflag to generate icon constantsTest plan
FaDuotoneIconDataunit tests (ligature strings, equality, font family, toString)FaDuotoneIconDataweight variant tests (all 8 font families produce correct ligatures)FaDuotoneIconwidget tests (sizing, colors, opacity swap, layer stacking, semantics)FaDuotoneIconfont family passthrough test (non-default weight renders with correct family)FaDuotoneIcontheme integration tests (IconTheme color/size/opacity/shadows/font variations fallback)FaDuotoneIconadvanced feature tests (blendMode, applyTextScaling, fontWeight)flutter analyzereports zero issues--duotonegenerates correct constants from Proicons.jsonScreenshots
Example App
Duotones Enabled
Duotones Disabled