https://github.com/akkartik/mu/blob/main/apps/ex15.mu
  1 # Demo of combining-character support in Mu, which can be summarized as, "the
  2 # old typewriter-based approach of backing up one character and adding the
  3 # accent or _matra_ in."
  4 #   https://en.wikipedia.org/wiki/Combining_character
  5 #
  6 # Mu uses this approach for both accents in Latin languages and vowel
  7 # diacritics in Abugida scripts.
  8 #   https://en.wikipedia.org/wiki/Diacritic
  9 #   https://en.wikipedia.org/wiki/Abugida
 10 #
 11 # Steps for trying it out:
 12 #   1. Translate this example into a disk image code.img.
 13 #       ./translate apps/ex15.mu
 14 #   2. Run:
 15 #       qemu-system-i386 -hda code.img -hdb data.img
 16 #
 17 # Expected output, showing off what this approach can and cannot do:
 18 #   'à' in green in a few places near the top-left corner of screen, with
 19 #   other letters nearby showing cases where characters blend to the eye.
 20 #
 21 #   A few Devanagari letter combinations. Devanagari works well except for
 22 #   characters blending together.
 23 #
 24 #   A few Tamil letter combinations. Tamil often doesn't look right, and
 25 #   requires ligatures for many letter combinations.
 26 #
 27 #   Others? (Patches welcome.) I suspect Tibetan in particular will not work
 28 #   well with this approach. But I need native readers to assess quality.
 29 
 30 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
 31   # at the top of screen, the accent is almost cropped
 32   var dummy/eax: int <-    draw-code-point-on-real-screen   0x61/a,                       0/x 0/y, 3/fg 0/bg
 33   var dummy/eax: int <- overlay-code-point-on-real-screen 0x0300/combining-grave-accent,  0/x 0/y, 3/fg 0/bg
 34 
 35   # below a grapheme with a descender, the accent uglily overlaps
 36   #   https://en.wikipedia.org/wiki/Descender
 37   var dummy/eax: int <-    draw-code-point-on-real-screen   0x67/g,                       4/x 3/y, 3/fg 0/bg
 38   var dummy/eax: int <-    draw-code-point-on-real-screen   0x61/a,                       4/x 4/y, 3/fg 0/bg
 39   var dummy/eax: int <- overlay-code-point-on-real-screen 0x0300/combining-grave-accent,  4/x 4/y, 3/fg 0/bg
 40 
 41   # beside a grapheme with a descender, it becomes more obvious that monowidth fonts can't make baselines line up
 42   #   https://en.wikipedia.org/wiki/Baseline_(typography)
 43   var dummy/eax: int <-    draw-code-point-on-real-screen   0x67/g,                       8/x 3/y, 3/fg 0/bg
 44   var dummy/eax: int <-    draw-code-point-on-real-screen   0x61/a,                       9/x 3/y, 3/fg 0/bg
 45   var dummy/eax: int <- overlay-code-point-on-real-screen 0x0300/combining-grave-accent,  9/x 3/y, 3/fg 0/bg
 46 
 47   # a single devanagari letter combined with different vowel _matras_
 48   # ka
 49   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 4/x 8/y, 3/fg 0/bg
 50   # kaa
 51   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 7/x 8/y, 3/fg 0/bg
 52   var dummy/eax: int <- overlay-code-point-on-real-screen 0x093e/devanagari-vowel-aa, 7/x 8/y, 3/fg 0/bg
 53   # ki
 54   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 0xa/x 8/y, 3/fg 0/bg
 55   var dummy/eax: int <- overlay-code-point-on-real-screen 0x093f/devanagari-vowel-i, 0xa/x 8/y, 3/fg 0/bg
 56   # kee
 57   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 0xd/x 8/y, 3/fg 0/bg
 58   var dummy/eax: int <- overlay-code-point-on-real-screen 0x0940/devanagari-vowel-ii, 0xd/x 8/y, 3/fg 0/bg
 59   # ku
 60   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 0x10/x 8/y, 3/fg 0/bg
 61   var dummy/eax: int <- overlay-code-point-on-real-screen 0x0941/devanagari-vowel-u, 0x10/x 8/y, 3/fg 0/bg
 62   # koo
 63   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 0x13/x 8/y, 3/fg 0/bg
 64   var dummy/eax: int <- overlay-code-point-on-real-screen 0x0942/devanagari-vowel-oo, 0x13/x 8/y, 3/fg 0/bg
 65   # kay
 66   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 4/x 9/y, 3/fg 0/bg
 67   var dummy/eax: int <- overlay-code-point-on-real-screen 0x0947/devanagari-vowel-E, 4/x 9/y, 3/fg 0/bg
 68   # kai
 69   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 7/x 9/y, 3/fg 0/bg
 70   var dummy/eax: int <- overlay-code-point-on-real-screen 0x0948/devanagari-vowel-ai, 7/x 9/y, 3/fg 0/bg
 71   # ko
 72   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 0xa/x 9/y, 3/fg 0/bg
 73   var dummy/eax: int <- overlay-code-point-on-real-screen 0x094b/devanagari-vowel-o, 0xa/x 9/y, 3/fg 0/bg
 74   # kow
 75   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 0xd/x 9/y, 3/fg 0/bg
 76   var dummy/eax: int <- overlay-code-point-on-real-screen 0x094f/devanagari-vowel-aw, 0xd/x 9/y, 3/fg 0/bg
 77   # kan
 78   # bump this letter down to show the letter without overlap; we've already established above that overlap is an issue
 79   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 0x10/x 0xa/y, 3/fg 0/bg
 80   var dummy/eax: int <- overlay-code-point-on-real-screen 0x0902/devanagari-anusvara, 0x10/x 0xa/y, 3/fg 0/bg
 81   # kaha
 82   var dummy/eax: int <- draw-code-point-on-real-screen 0x0915/devanagari-letter-ka, 0x13/x 9/y, 3/fg 0/bg
 83   var dummy/eax: int <- overlay-code-point-on-real-screen 0x0903/devanagari-visarga, 0x13/x 9/y, 3/fg 0/bg
 84 
 85   # render the same devanagari letters as a single stream of utf-8 graphemes rather than individual code-points.
 86   var text-storage: (stream byte 0x200)
 87   var text/esi: (addr stream byte) <- address text-storage
 88   var g/eax: grapheme <- to-grapheme 0x0915/devanagari-letter-ka
 89   var ka/ecx: grapheme <- copy g
 90   # ka
 91   write-grapheme text, ka
 92   # kaa
 93   write-grapheme text, ka
 94   g <- to-grapheme 0x093e/devanagari-vowel-aa
 95   write-grapheme text, g
 96   # ki
 97   write-grapheme text, ka
 98   g <- to-grapheme 0x093f/devanagari-vowel-i
 99   write-grapheme text, g
100   # kee
101   write-grapheme text, ka
102   g <- to-grapheme 0x0940/devanagari-vowel-ii
103   write-grapheme text, g
104   # ku
105   write-grapheme text, ka
106   g <- to-grapheme 0x0941/devanagari-vowel-u
107   write-grapheme text, g
108   # koo
109   write-grapheme text, ka
110   g <- to-grapheme 0x0942/devanagari-vowel-oo
111   write-grapheme text, g
112   # kay
113   write-grapheme text, ka
114   g <- to-grapheme 0x0947/devanagari-vowel-E
115   write-grapheme text, g
116   # kai
117   write-grapheme text, ka
118   g <- to-grapheme 0x0948/devanagari-vowel-ai
119   write-grapheme text, g
120   # ko
121   write-grapheme text, ka
122   g <- to-grapheme 0x094b/devanagari-vowel-o
123   write-grapheme text, g
124   # kow
125   write-grapheme text, ka
126   g <- to-grapheme 0x094f/devanagari-vowel-aw
127   write-grapheme text, g
128   # kan
129   write-grapheme text, ka
130   g <- to-grapheme 0x0902/devanagari-anusvara
131   write-grapheme text, g
132   # kaha
133   write-grapheme text, ka
134   g <- to-grapheme 0x0903/devanagari-visarga
135   write-grapheme text, g
136   # render everything
137   set-cursor-position screen, 4/x 0xe/y
138   draw-stream-wrapping-right-then-down-from-cursor-over-full-screen screen, text, 3/fg 0/bg
139 
140   # a stream of tamil graphemes (with interspersed spaces for clarity) that don't look the same in Mu
141   set-cursor-position 0, 4/x 0x12/y
142   draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, "எ ஃ கு ", 3/fg 0/bg
143   set-cursor-position 0, 4/x 0x13/y
144   draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, "அ ன் று ", 3/fg 0/bg
145   set-cursor-position 0, 4/x 0x14/y
146   draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, "அ தா வ து " , 3/fg 0/bg
147   set-cursor-position 0, 4/x 0x15/y
148   draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0, "அ ஃ தா ன் று ", 3/fg 0/bg
149 }