diff --git a/OTFbuild/CLAUDE.md b/OTFbuild/CLAUDE.md index 8e76f80..6bcbb88 100644 --- a/OTFbuild/CLAUDE.md +++ b/OTFbuild/CLAUDE.md @@ -141,6 +141,7 @@ The bitmap font engine normalises Devanagari consonants to internal PUA forms be | U+0915-0939 +48 | 0xF0170-0xF0194 | Nukta forms (consonant + U+093C) | | U+0915-0939 +240 | 0xF0230-0xF0254 | Half forms (consonant + virama) | | U+0915-0939 +480 | 0xF0320-0xF0404 | RA-appended forms (consonant + virama + RA) | +| U+0915-0939 +720 | 0xF0410-0xF04F4 | RA-appended half forms (consonant + virama + RA + virama) | Mapping formula: `to_deva_internal(c)` = `c - 0x0915 + 0xF0140` for U+0915-0939. diff --git a/OTFbuild/opentype_features.py b/OTFbuild/opentype_features.py index 0b601d0..97ce73a 100644 --- a/OTFbuild/opentype_features.py +++ b/OTFbuild/opentype_features.py @@ -627,11 +627,13 @@ def _generate_devanagari(glyphs, has, replacewith_subs=None): # --- half: consonant (PUA) + virama -> half form --- # After ccmp, consonants are in PUA form, so reference PUA here. - # Conjuncts are NOT here because half uses per-glyph masking (only - # pre-base consonants), preventing 3-glyph matches across the base. + # Covers all PUA consonants including conjuncts produced by akhn + # (e.g. DD.G + virama -> half-DD.G). The half feature uses + # per-glyph masking (only pre-base consonants get the mask), so + # conjunct glyphs formed by akhn inherit the pre-base mask and + # their following virama also has the pre-base mask. half_subs = [] - for uni_cp in range(0x0915, 0x093A): - internal = SC.to_deva_internal(uni_cp) + for internal in SC.DEVANAGARI_PRESENTATION_CONSONANTS: half_form = internal + 240 if has(internal) and has(SC.DEVANAGARI_VIRAMA) and has(half_form): half_subs.append( @@ -668,15 +670,39 @@ def _generate_devanagari(glyphs, has, replacewith_subs=None): # with the preceding consonant to produce the ra-appended glyph. # Covers all PUA consonants: basic, nukta forms, AND conjuncts # (e.g. DD.G + rakaar -> DD.G.RA). - cjct_subs = [] + # + # A second lookup converts RA-appended + virama -> RA-appended half, + # since the half feature has already run before cjct. + cjct_lines = [] + + # Lookup 1: consonant + rakaar -> RA-appended form + ra_append_subs = [] for internal in SC.DEVANAGARI_PRESENTATION_CONSONANTS: ra_form = internal + 480 if has(internal) and has(ra_sub) and has(ra_form): - cjct_subs.append( - f" sub {glyph_name(internal)} {glyph_name(ra_sub)} by {glyph_name(ra_form)};" + ra_append_subs.append( + f" sub {glyph_name(internal)} {glyph_name(ra_sub)} by {glyph_name(ra_form)};" ) - if cjct_subs: - features.append("feature cjct {\n script dev2;\n" + '\n'.join(cjct_subs) + "\n} cjct;") + if ra_append_subs: + cjct_lines.append(" lookup CjctRaAppend {") + cjct_lines.extend(ra_append_subs) + cjct_lines.append(" } CjctRaAppend;") + + # Lookup 2: RA-appended + virama -> RA-appended half form + ra_half_subs = [] + for ra_form in SC.DEVANAGARI_PRESENTATION_CONSONANTS_WITH_RA: + ra_half = ra_form + 240 # +240 from RA-appended = +720 from base + if has(ra_form) and has(SC.DEVANAGARI_VIRAMA) and has(ra_half): + ra_half_subs.append( + f" sub {glyph_name(ra_form)} {glyph_name(SC.DEVANAGARI_VIRAMA)} by {glyph_name(ra_half)};" + ) + if ra_half_subs: + cjct_lines.append(" lookup CjctRaHalf {") + cjct_lines.extend(ra_half_subs) + cjct_lines.append(" } CjctRaHalf;") + + if cjct_lines: + features.append("feature cjct {\n script dev2;\n" + '\n'.join(cjct_lines) + "\n} cjct;") # --- blws: RA/RRA/HA (PUA) + U/UU -> special syllables --- blws_subs = [] diff --git a/src/assets/devanagari_variable.tga b/src/assets/devanagari_variable.tga index c0bf64f..6262823 100644 --- a/src/assets/devanagari_variable.tga +++ b/src/assets/devanagari_variable.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:328654c5791f9cb147f2b7273ffcc846ba36a8551e394fb14d4272735e2b2499 +oid sha256:d0e62cb837710cb1838824703a77cbb92134486d41b159a91e532d499856d05f size 1474578 diff --git a/work_files/devanagari_variable.psd b/work_files/devanagari_variable.psd index b63ca13..d19aa46 100644 --- a/work_files/devanagari_variable.psd +++ b/work_files/devanagari_variable.psd @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:616c92ef95ca6aa61de8a2554740dc0f18d92c8730a64147b6cc5a9ba3c019be -size 1453565 +oid sha256:b3d0fbfb962df918b2316e2077d90cb0c1e34eace4dace9922370b174fc1d422 +size 1453551