package harfbuzzimport (ucd)// generalCategory is an enum value to allow compact storage (see generalCategories)type generalCategory = ucd.GeneralCategory// Modified combining marksconst (/* Hebrew * * We permute the "fixed-position" classes 10-26 into the order * described in the SBL Hebrew manual: * * https://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf * * (as recommended by: * https://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering/msg22823/) * * More details here: * https://bugzilla.mozilla.org/show_bug.cgi?id=662055 */ mcc10 uint8 = 22/* sheva */ mcc11 uint8 = 15/* hataf segol */ mcc12 uint8 = 16/* hataf patah */ mcc13 uint8 = 17/* hataf qamats */ mcc14 uint8 = 23/* hiriq */ mcc15 uint8 = 18/* tsere */ mcc16 uint8 = 19/* segol */ mcc17 uint8 = 20/* patah */ mcc18 uint8 = 21/* qamats & qamats qatan */ mcc19 uint8 = 14/* holam & holam haser for vav*/ mcc20 uint8 = 24/* qubuts */ mcc21 uint8 = 12/* dagesh */ mcc22 uint8 = 25/* meteg */ mcc23 uint8 = 13/* rafe */ mcc24 uint8 = 10/* shin dot */ mcc25 uint8 = 11/* sin dot */ mcc26 uint8 = 26/* point varika *//* * Arabic * * Modify to move Shadda (ccc=33) before other marks. See: * https://unicode.org/faq/normalization.html#8 * https://unicode.org/faq/normalization.html#9 */ mcc27 uint8 = 28/* fathatan */ mcc28 uint8 = 29/* dammatan */ mcc29 uint8 = 30/* kasratan */ mcc30 uint8 = 31/* fatha */ mcc31 uint8 = 32/* damma */ mcc32 uint8 = 33/* kasra */ mcc33 uint8 = 27/* shadda */ mcc34 uint8 = 34/* sukun */ mcc35 uint8 = 35/* superscript alef *//* Syriac */ mcc36 uint8 = 36/* superscript alaph *//* Telugu * * Modify Telugu length marks (ccc=84, ccc=91). * These are the only matras in the main Indic scripts range that have * a non-zero ccc. That makes them reorder with the Halant (ccc=9). * Assign 4 and 5, which are otherwise unassigned. */ mcc84 uint8 = 4/* length mark */ mcc91 uint8 = 5/* ai length mark *//* Thai * * Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9). * Assign 3, which is unassigned otherwise. * Uniscribe does this reordering too. */ mcc103 uint8 = 3/* sara u / sara uu */ mcc107 uint8 = 107/* mai * *//* Lao */ mcc118 uint8 = 118/* sign u / sign uu */ mcc122 uint8 = 122/* mai * *//* Tibetan * * In case of multiple vowel-signs, use u first (but after achung) * this allows Dzongkha multi-vowel shortcuts to render correctly */ mcc129 = 129/* sign aa */ mcc130 = 132/* sign i */ mcc132 = 131/* sign u */)var modifiedCombiningClass = [256]uint8{0, /* HB_UNICODE_COMBINING_CLASS_NOT_REORDERED */1, /* HB_UNICODE_COMBINING_CLASS_OVERLAY */2, 3, 4, 5, 6,7, /* HB_UNICODE_COMBINING_CLASS_NUKTA */8, /* HB_UNICODE_COMBINING_CLASS_KANA_VOICING */9, /* HB_UNICODE_COMBINING_CLASS_VIRAMA *//* Hebrew */mcc10,mcc11,mcc12,mcc13,mcc14,mcc15,mcc16,mcc17,mcc18,mcc19,mcc20,mcc21,mcc22,mcc23,mcc24,mcc25,mcc26,/* Arabic */mcc27,mcc28,mcc29,mcc30,mcc31,mcc32,mcc33,mcc34,mcc35,/* Syriac */mcc36,37, 38, 39,40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,80, 81, 82, 83,/* Telugu */mcc84,85, 86, 87, 88, 89, 90,mcc91,92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,/* Thai */mcc103,104, 105, 106,mcc107,108, 109, 110, 111, 112, 113, 114, 115, 116, 117,/* Lao */mcc118,119, 120, 121,mcc122,123, 124, 125, 126, 127, 128,/* Tibetan */mcc129,mcc130,131,mcc132,133, 134, 135, 136, 137, 138, 139,140, 141, 142, 143, 144, 145, 146, 147, 148, 149,150, 151, 152, 153, 154, 155, 156, 157, 158, 159,160, 161, 162, 163, 164, 165, 166, 167, 168, 169,170, 171, 172, 173, 174, 175, 176, 177, 178, 179,180, 181, 182, 183, 184, 185, 186, 187, 188, 189,190, 191, 192, 193, 194, 195, 196, 197, 198, 199,200, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT */201,202, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW */203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,214, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE */215,216, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT */217,218, /* HB_UNICODE_COMBINING_CLASS_BELOW_LEFT */219,220, /* HB_UNICODE_COMBINING_CLASS_BELOW */221,222, /* HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT */223,224, /* HB_UNICODE_COMBINING_CLASS_LEFT */225,226, /* HB_UNICODE_COMBINING_CLASS_RIGHT */227,228, /* HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT */229,230, /* HB_UNICODE_COMBINING_CLASS_ABOVE */231,232, /* HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT */233, /* HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW */234, /* HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE */235, 236, 237, 238, 239,240, /* HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT */241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,255, /* HB_UNICODE_COMBINING_CLASS_INVALID */}func uniModifiedCombiningClass( rune) uint8 {// Reorder SAKOT to ensure it comes after any tone marks.if == 0x1A60 {return254 }// Reorder PADMA to ensure it comes after any vowel marks.if == 0x0FC6 {return254 }/* Reorder TSA -PHRU to reorder before U+0F74 */if == 0x0F39 {return127 }returnmodifiedCombiningClass[ucd.LookupCombiningClass()]}// IsDefaultIgnorable returns `true` for// codepoints with the Default_Ignorable property// (as defined in unicode data DerivedCoreProperties.txt)func ( rune) bool {// Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable, // we do NOT want to hide them, as the way Uniscribe has implemented them // is with regular spacing glyphs, and that's the way fonts are made to work. // As such, we make exceptions for those four. // Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503 := >> 16if == 0 {/* BMP */ := >> 8switch {case0x00:return ( == 0x00AD)case0x03:return ( == 0x034F)case0x06:return ( == 0x061C)case0x17:return0x17B4 <= && <= 0x17B5case0x18:return0x180B <= && <= 0x180Ecase0x20:return0x200B <= && <= 0x200F ||0x202A <= && <= 0x202E ||0x2060 <= && <= 0x206Fcase0xFE:return0xFE00 <= && <= 0xFE0F || == 0xFEFFcase0xFF:return0xFFF0 <= && <= 0xFFF8default:returnfalse } } else {/* Other planes */switch {case0x01:return0x1D173 <= && <= 0x1D17Acase0x0E:return0xE0000 <= && <= 0xE0FFFdefault:returnfalse } }}/* Space estimates based on: * https://unicode.org/charts/PDF/U2000.pdf * https://docs.microsoft.com/en-us/typography/develop/character-design-standards/whitespace */const ( spaceEM16 = 16 + iota space4EM18 // 4/18th of an EM! space spaceFigure spacePunctuation spaceNarrow notSpace = 0 spaceEM = 1 spaceEM2 = 2 spaceEM3 = 3 spaceEM4 = 4 spaceEM5 = 5 spaceEM6 = 6)func uniSpaceFallbackType( rune) uint8 {switch {// all GC=Zs chars that can use a fallback.case0x0020:returnspace/* U+0020 SPACE */case0x00A0:returnspace/* U+00A0 NO-BREAK SPACE */case0x2000:returnspaceEM2/* U+2000 EN QUAD */case0x2001:returnspaceEM/* U+2001 EM QUAD */case0x2002:returnspaceEM2/* U+2002 EN SPACE */case0x2003:returnspaceEM/* U+2003 EM SPACE */case0x2004:returnspaceEM3/* U+2004 THREE-PER-EM SPACE */case0x2005:returnspaceEM4/* U+2005 FOUR-PER-EM SPACE */case0x2006:returnspaceEM6/* U+2006 SIX-PER-EM SPACE */case0x2007:returnspaceFigure/* U+2007 FIGURE SPACE */case0x2008:returnspacePunctuation/* U+2008 PUNCTUATION SPACE */case0x2009:returnspaceEM5/* U+2009 THIN SPACE */case0x200A:returnspaceEM16/* U+200A HAIR SPACE */case0x202F:returnspaceNarrow/* U+202F NARROW NO-BREAK SPACE */case0x205F:returnspace4EM18/* U+205F MEDIUM MATHEMATICAL SPACE */case0x3000:returnspaceEM/* U+3000 IDEOGRAPHIC SPACE */default:returnnotSpace/* U+1680 OGHAM SPACE MARK */ }}func uniIsVariationSelector( rune) bool {/* U+180B..180D, U+180F MONGOLIAN FREE VARIATION SELECTORs are handled in the * Arabic shaper. No need to match them here. */ /* VARIATION SELECTOR-1..16 */ /* VARIATION SELECTOR-17..256 */return (0xFE00 <= && <= 0xFE0F) || (0xE0100 <= && <= 0xE01EF)}/* Prepare */func isRegionalIndicator( rune) bool { return0x1F1E6 <= && <= 0x1F1FF }// Implement enough of Unicode Graphemes here that shaping// in reverse-direction wouldn't break graphemes. Namely,// we mark all marks and ZWJ and ZWJ,Extended_Pictographic// sequences as continuations. The foreach_grapheme()// macro uses this bit.//// https://www.unicode.org/reports/tr29/#Regex_Definitionsfunc ( *Buffer) () { := .Infofor := 0; < len(); ++ { := [].codepoint [].setUnicodeProps()if < 0x80 {continue } := [].unicode.generalCategory()if == ucd.Ll || == ucd.Lu || == ucd.Lt || == ucd.Lo || == ucd.Zs {continue }/* Marks are already set as continuation by the above line. * Handle Emoji_Modifier and ZWJ-continuation. */if == ucd.Sk && (0x1F3FB <= && <= 0x1F3FF) { [].setContinuation() } elseif != 0 && isRegionalIndicator() {/* Regional_Indicators are hairy as hell... * https://github.com/harfbuzz/harfbuzz/issues/2265 */ifisRegionalIndicator([-1].codepoint) && ![-1].isContinuation() { [].setContinuation() } } elseif [].isZwj() { [].setContinuation()if +1 < len(.Info) && ucd.IsExtendedPictographic([+1].codepoint) { ++ [].setUnicodeProps() [].setContinuation() } } elseif (0xFF9E <= && <= 0xFF9F) || (0xE0020 <= && <= 0xE007F) {// Or part of the Other_Grapheme_Extend that is not marks. // As of Unicode 15 that is just: // // 200C ; Other_Grapheme_Extend # Cf ZERO WIDTH NON-JOINER // FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK // E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG // // ZWNJ is special, we don't want to merge it as there's no need, and keeping // it separate results in more granular clusters. // Tags are used for Emoji sub-region flag sequences: // https://github.com/harfbuzz/harfbuzz/issues/1556 // Katakana ones were requested: // https://github.com/harfbuzz/harfbuzz/issues/3844 [].setContinuation() } elseif == 0x2044/* FRACTION SLASH */ { .scratchFlags |= bsfHasFractionSlash } }}func ( *Buffer) ( *Font) {if .Flags&DoNotinsertDottedCircle != 0 {return }if .Flags&Bot == 0 || len(.context[0]) != 0 ||len(.Info) == 0 || !.Info[0].isUnicodeMark() {return }if !.hasGlyph(0x25CC) {return } := GlyphInfo{codepoint: 0x25CC} .setUnicodeProps() .clearOutput() .idx = 0 .Cluster = .cur(0).Cluster .Mask = .cur(0).Mask .outInfo = append(.outInfo, ) .swapBuffers()}func ( *Buffer) () {if .scratchFlags&bsfHasContinuations == 0 {return } , := .graphemesIterator()if .ClusterLevel == MonotoneGraphemes {for , := .next(); < ; , = .next() { .mergeClusters(, ) } } else {for , := .next(); < ; , = .next() { .unsafeToBreak(, ) } }}func ( *Buffer) () { := .Props.Direction := getHorizontalDirection(.Props.Script)// Numeric runs in natively-RTL scripts are actually native-LTR, so we reset // the horiz_dir if the run contains at least one decimal-number char, and no // letter chars (ideally we should be checking for chars with strong // directionality but hb-unicode currently lacks bidi categories). // // This allows digit sequences in Arabic etc to be shaped in "native" // direction, so that features like ligatures will work as intended. // // https://github.com/harfbuzz/harfbuzz/issues/501 // // Similar thing about Regional_Indicators; They are bidi=L, but Script=Common. // If they are present in a run of natively-RTL text, they get assigned a script // with natively RTL direction, which would result in wrong shaping if we // assign such native RTL direction to them then. Detect that as well. // // https://github.com/harfbuzz/harfbuzz/issues/3314 //if == RightToLeft && == LeftToRight {var , , boolfor , := range .Info { := .unicode.generalCategory()if .IsLetter() { = truebreak } elseif == ucd.Nd { = true } elseifisRegionalIndicator(.codepoint) { = true } }if ( || ) && ! { = LeftToRight } }if (.isHorizontal() && != && != 0) || (.isVertical() && != TopToBottom) {reverseGraphemes() .Props.Direction = .Props.Direction.Reverse() }}// the returned flag must be ORed with the currentfunc computeUnicodeProps( rune) (unicodeProp, bufferScratchFlags) { := ucd.LookupGeneralCategory() := unicodeProp()varbufferScratchFlagsif >= 0x80 {ifIsDefaultIgnorable() { |= bsfHasDefaultIgnorables |= upropsMaskIgnorableif == 0x200C { |= upropsMaskCfZwnj } elseif == 0x200D { |= upropsMaskCfZwj } elseif (0x180B <= && <= 0x180D) || == 0x180F {/* Mongolian Free Variation Selectors need to be remembered * because although we need to hide them like default-ignorables, * they need to non-ignorable during shaping. This is similar to * what we do for joiners in Indic-like shapers, but since the * FVSes are GC=Mn, we have use a separate bit to remember them. * Fixes: * https://github.com/harfbuzz/harfbuzz/issues/234 */ |= upropsMaskHidden } elseif0xE0020 <= && <= 0xE007F {/* TAG characters need similar treatment. Fixes: * https://github.com/harfbuzz/harfbuzz/issues/463 */ |= upropsMaskHidden } elseif == 0x034F {/* COMBINING GRAPHEME JOINER should not be skipped during GSUB either. * https://github.com/harfbuzz/harfbuzz/issues/554 */ |= bsfHasCGJ |= upropsMaskHidden } }if .IsMark() { |= bsfHasContinuations |= upropsMaskContinuation |= unicodeProp(uniModifiedCombiningClass()) << 8 } }return , }
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.