The substitution BLACK_FLAG + CANCEL_TAG => UNKNOWN_FLAG is alrady handled by the _add_fallback_subs_for_unknown_flags method, added in the previous commit.
There's no BLACK_FLAG + CANCEL_TAG => BLACK_FLAG substituion in the current NotoColorEmoji.ttf CBDT font.
In fact, it makes much more sense that all unsupported subdivision flag sequences, i.e. BLACK_FLAG + (zero or more non-cancel tags) + CANCEL_TAG, are all displayed with the unknown flag. No reason to special case BLACK_FLAG + CANCEL_TAG.
I'm not sure where the conclusion about the BLACK_FLAG + CANCEL_TAG => BLACK_FLAG came from (got to ask Rod).
Any invalid/unsupported emoji flag sequence (whether using regional indicators or subdivision tags) gets replaced by the 'unknown flag' (PUA 0xFE28B), a flag with a blue question mark in the middle.
The logic is mutated from the GSUB table of NotoColorEmoji.tmpl.ttx. We build these extra lookups using feaLib on an temporary empty font (that matches the glyph order of our destination CORLv1 font), then update our font's GSUB with them.
The PUA for the unknown flag is then removed from the cmap, as it's no longer needed. It's also deleted from the CBDT NotoColorEmoji (see emoji_builder.py).
copy values from CBDT font, adapt to the different UPEM (CBDT has 2048, COLRv1 has 1024, nanoemoji's default)
Maybe we shold just make the UPEM the same for both?
the border can be added directly to the input waved flags SVGs like a regular path, we don't need to use PaintComposite multiply operator, regular alpha blending produces the same effect since the border is a semi transparent shade of gray.
I renamed the script colrv1_add_soft_light_to_flags.py, and modified so that it doesn't require any additional glyphs to be present; an unbounded PaintLinearGradient is built on the fly and clipped using the flag as a mask (using SRC_IN compositing mode).