1;;; knd-util.el --- Support for composing Kannada characters 2 3;; Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 4 5;; Maintainer: Maintainer: CHOWKSEY, Kailash C. <klchxbec@m-net.arbornet.org> 6;; Keywords: multilingual, Kannada 7 8;; This file is part of GNU Emacs. 9 10;; GNU Emacs is free software; you can redistribute it and/or modify 11;; it under the terms of the GNU General Public License as published by 12;; the Free Software Foundation; either version 2, or (at your option) 13;; any later version. 14 15;; GNU Emacs is distributed in the hope that it will be useful, 16;; but WITHOUT ANY WARRANTY; without even the implied warranty of 17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18;; GNU General Public License for more details. 19 20;; You should have received a copy of the GNU General Public License 21;; along with GNU Emacs; see the file COPYING. If not, write to the 22;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23;; Boston, MA 02110-1301, USA. 24 25;; Created: Jul. 14. 2003 26 27;;; Commentary: 28 29;; This file provides character(Unicode) to glyph(CDAC) conversion and 30;; composition of Kannada script characters. 31 32;;; Code: 33 34;;;###autoload 35 36;; Kannada Composable Pattern 37;; C .. Consonants 38;; V .. Vowel 39;; H .. Virama 40;; M .. Matra 41;; V .. Vowel 42;; (N .. Zerowidth Non Joiner) 43;; (J .. Zerowidth Joiner. ) 44;; 1. vowel 45;; V(A)? 46;; 2. syllable : maximum of 5 consecutive consonants. (e.g. kartsnya) 47;; ((CH)?(CH)?(CH)?CH)?C(H|M?)? 48 49(defconst kannada-consonant 50 "[$,1>u(B-$,1?9(B]") 51 52(defconst kannada-consonant-needs-twirl 53 "[$,1>u>w(B-$,1>{>}(B-$,1>~? (B-$,1?"?$(B-$,1?+?-?0?3(B-$,1?9(B]\\($,1?M(B[$,1>u(B-$,1?9(B]\\)*[$,1?A?B?C?D>b(B]?$") 54 55(defconst kannada-composable-pattern 56 (concat 57 "\\([$,1>b(B-$,1>t?`>l(B]\\)\\|[$,1>c(B]" 58 "\\|\\(" 59 "\\(?:\\(?:[$,1>u(B-$,1?9(B]$,1?M(B\\)?\\(?:[$,1>u(B-$,1?9(B]$,1?M(B\\)?\\(?:[$,1>u(B-$,1?9(B]$,1?M(B\\)?[$,1>u(B-$,1?9(B]$,1?M(B\\)?" 60 "[$,1>u(B-$,1?9(B]\\(?:$,1?M(B\\|[$,1?>(B-$,1?M?U?C(B]?\\)?" 61 "\\)") 62 "Regexp matching a composable sequence of Kannada characters.") 63 64;;;###autoload 65(defun kannada-compose-region (from to) 66 (interactive "r") 67 (save-excursion 68 (save-restriction 69 (narrow-to-region from to) 70 (goto-char (point-min)) 71 (while (re-search-forward kannada-composable-pattern nil t) 72 (kannada-compose-syllable-region (match-beginning 0) 73 (match-end 0)))))) 74;;;###autoload 75(defun kannada-compose-string (string) 76 (with-temp-buffer 77 (insert (decompose-string string)) 78 (kannada-compose-region (point-min) (point-max)) 79 (buffer-string))) 80 81;;;###autoload 82(defun kannada-post-read-conversion (len) 83 (save-excursion 84 (save-restriction 85 (let ((buffer-modified-p (buffer-modified-p))) 86 (narrow-to-region (point) (+ (point) len)) 87 (kannada-compose-region (point-min) (point-max)) 88 (set-buffer-modified-p buffer-modified-p) 89 (- (point-max) (point-min)))))) 90 91(defun kannada-range (from to) 92 "Make the list of the integers of range FROM to TO." 93 (let (result) 94 (while (<= from to) (setq result (cons to result) to (1- to))) result)) 95 96(defun kannada-regexp-of-hashtbl-keys (hashtbl) 97 "Return a regular expression that matches all keys in hashtable HASHTBL." 98 (let ((max-specpdl-size 1000)) 99 (regexp-opt 100 (sort 101 (let (dummy) 102 (maphash (function (lambda (key val) (setq dummy (cons key dummy)))) hashtbl) 103 dummy) 104 (function (lambda (x y) (> (length x) (length y)))))))) 105 106(defun kannada-regexp-of-hashtbl-vals (hashtbl) 107 "Return a regular expression that matches all values in hashtable HASHTBL." 108 (let ((max-specpdl-size 1000)) 109 (regexp-opt 110 (sort 111 (let (dummy) 112 (maphash (function (lambda (key val) (setq dummy (cons val dummy)))) hashtbl) 113 dummy) 114 (function (lambda (x y) (> (length x) (length y)))))))) 115 116(defun kannada-composition-function (from to pattern &optional string) 117 "Compose Kannada characters in REGION, or STRING if specified. 118Assume that the REGION or STRING must fully match the composable 119PATTERN regexp." 120 (if string (kannada-compose-syllable-string string) 121 (kannada-compose-syllable-region from to)) 122 (- to from)) 123 124;; Register a function to compose Kannada characters. 125(mapc 126 (function (lambda (ucs) 127 (aset composition-function-table (decode-char 'ucs ucs) 128 (list (cons kannada-composable-pattern 129 'kannada-composition-function))))) 130 (kannada-range #x0c80 #x0cff)) 131 132;; Notes on conversion steps. 133 134;; 1. chars to glyphs 135;; 136;; Rules will not be applied to the virama appeared at the end of the 137;; text. Also, the preceding/following "r" will be treated as special case. 138 139;; 2. glyphs reordering. 140;; 141;; The glyphs are split by virama, and each glyph groups are 142;; re-ordered in the following order. 143;; 144;; Note that `consonant-glyph' mentioned here does not contain the 145;; vertical bar (right modifier) attached at the right of the 146;; consonant. 147;; 148;; If the glyph-group contains right modifier, 149;; (1) consonant-glyphs/vowels 150;; (2) spacing 151;; (3) right modifier (may be matra) 152;; (4) top matra 153;; (5) preceding "r" 154;; (7) following "r" 155;; (8) bottom matra or virama. 156;; 157;; Otherwise, 158;; (1) consonant-glyph/vowels, with nukta sign 159;; (3) left matra 160;; (4) top matra 161;; (5) preceding "r" 162;; (7) following "r" 163;; (8) bottom matra or virama. 164;; (2) spacing 165 166;; 3. glyph to glyph 167;; 168;; For better display, some glyph display would be tuned. 169 170;; 4. Composition. 171;; 172;; left modifiers will be attached at the left. 173;; others will be attached right. 174 175;; Problem:: 176;; Can we generalize this methods to other Indian scripts? 177 178(defvar knd-char-glyph 179 '(("$,1>e(B" . "$,43@(B") 180 ("$,1>f(B" . "$,43A(B") 181 ("$,1?>(B" . "$,44{(B") 182 ("$,1>g(B" . "$,43B(B") 183 ("$,1??(B" . nil) 184 ("$,1>h(B" . "$,43C(B") 185 ("$,1?@(B" . nil) 186 ("$,1>i(B" . "$,43D(B") 187 ("$,1?A(B" . "\$,44(B") 188 ("$,1>j(B" . "$,43E(B") 189 ("$,1?B(B" . "\$,45 (B") 190 ("$,1>k(B" . "$,43F4(B") 191 ("$,1?C(B" . "\$,45$(B") 192 ("$,1?`(B" . "$,43F5 (B") 193 ("$,1?D(B" . "\$,45%(B") 194 ;;("$,1>l(B" . nil) ; not implemented. 195 ;;("$,1?a(B" . nil) 196 ("$,1>n(B" . "$,43G(B") 197 ("$,1>o(B" . "$,43H(B") 198 ("$,1>p(B" . "$,43I(B") 199 ("$,1?F(B" . "\$,45&(B") 200 ("$,1?G(B" . "\$,45&4~(B") 201 ("$,1?H(B" . "\$,45&5'(B") 202 ("$,1>r(B" . "$,43J(B") 203 ("$,1?J(B" . "$,45&5 (B") 204 ("$,1>s(B" . "$,43K(B") 205 ("$,1?K(B" . "\$,45&5 4~(B") 206 ("$,1>t(B" . "$,43L(B") 207 ("$,1?L(B" . "\$,45((B") 208 ("$,1>b(B" . "$,43M(B") 209 ("$,1>c(B" . "$,43N(B") 210 ("$,1>u?M(B" . "$,43O5)(B") ("$,1>u(B" . "$,43O(B") ("$,1>u??(B" . "$,43P(B") ("$,1>u?@(B" . "$,43P4~(B") 211 ("$,1>v?M(B" . "$,43S5)(B") ("$,1>v(B" . "$,43S(B") ("$,1>v??(B" . "$,43T(B") ("$,1>v?@(B" . "$,43T4~(B") ("$,1>v?F(B" . "$,43S5&(B") ("$,1>v?G(B" . "$,43S5&4~(B") ("$,1>v?H(B" . "$,43S5&5'(B") ("$,1>v?J(B" . "$,43S5&5&5 (B") ("$,1>v?K(B" . "$,43S5&5&5 4~(B") ("$,1>v?L(B" . "$,43S5((B") 212 ("$,1>w?M(B" . "$,43V5)(B") ("$,1>w(B" . "$,43V(B") ("$,1>w??(B" . "$,43W(B") ("$,1>w?@(B" . "$,43W4~(B") 213 ("$,1>x?M(B" . "$,43Y5)(B") ("$,1>x(B" . "$,43Y(B") ("$,1>x??(B" . "$,43Z(B") ("$,1>x?@(B" . "$,43Z4~(B") 214 ("$,1>y?M(B" . "$,43\5)(B") ("$,1>y(B" . "$,43\(B") 215 ("$,1>z?M(B" . "$,43^5)(B") ("$,1>z(B" . "$,43^(B") ("$,1>z??(B" . "$,43_(B") ("$,1>z?@(B" . "$,43_4~(B") 216 ("$,1>{?M(B" . "$,43a5)(B") ("$,1>{(B" . "$,43a(B") ("$,1>{??(B" . "$,43b(B") ("$,1>{?@(B" . "$,43b4~(B") 217 ("$,1>|?M(B" . "$,43d5)(B") ("$,1>|(B" . "$,43d(B") ("$,1>|??(B" . "$,43f(B") ("$,1>|?@(B" . "$,43f4~(B") ("$,1>|?F(B" . "$,43e5&(B") ("$,1>|?G(B" . "$,43e5&4~(B") ("$,1>|?H(B" . "$,43e5&5'(B") ("$,1>|?J(B" . "$,43e5&5&5 (B") ("$,1>|?K(B" . "$,43e5&5&5 4~(B") ("$,1>|?L(B" . "$,43e5((B") 218 ("$,1>}?M(B" . "$,44a4z3h45)(B") ("$,1>}(B" . "$,44a4z3h4(B") ("$,1>}??(B" . "$,44b3h4(B") ("$,1>}?@(B" . "$,44b3h44~(B") ("$,1>}?B(B". "$,44a4z3h5 (B") ("$,1>}?J(B". "$,44a5&3h5 (B") ("$,1>}?K(B". "$,44a5&3h5 4~(B") 219 ("$,1>~?M(B" . "$,43j5)(B") ("$,1>~(B" . "$,43j(B") 220 ("$,1>?M(B" . "$,43m5)(B") ("$,1>(B" . "$,43l(B") ("$,1?#?>(B" . "$,43m4{(B") ("$,1>??(B" . "$,43n(B") ("$,1>?@(B" . "$,43n4~(B") ("$,1>?F(B" . "$,43m5&(B") ("$,1>?G(B" . "$,43m5&4~(B") ("$,1>?H(B" . "$,43m5&5'(B") ("$,1>?J(B" . "$,43m5&5&5 (B") ("$,1>?K(B" . "$,43m5&5&5 4~(B") ("$,1>?L(B" . "$,43m5((B") 221 ("$,1? ?M(B" . "$,43p5)(B") ("$,1? (B" . "$,43p(B") ("$,1? ??(B" . "$,43q(B") ("$,1? ?@(B" . "$,43q4~(B") 222 ("$,1?!?M(B" . "$,43s5)(B") ("$,1?!(B" . "$,43s(B") ("$,1?!??(B" . "$,43t(B") ("$,1?!?@(B" . "$,43t4~(B") 223 ("$,1?"?M(B" . "$,43v5)(B") ("$,1?"(B" . "$,43v(B") ("$,1?"??(B" . "$,43w(B") ("$,1?"?@(B" . "$,43w4~(B") 224 ("$,1?#?M(B" . "$,43z5)(B") ("$,1?#(B" . "$,43y(B") ("$,1?#?>(B" . "$,43z4{(B") ("$,1?#??(B" . "$,43{(B") ("$,1?#?@(B" . "$,43{4~(B") ("$,1?#?F(B" . "$,43z5&(B") ("$,1?#?G(B" . "$,43z5&4~(B") ("$,1?#?H(B" . "$,43z5&5'(B") ("$,1?#?J(B" . "$,43z5&5&5 (B") ("$,1?#?K(B" . "$,43z5&5&5 4~(B") ("$,1?#?L(B" . "$,43z5((B") 225 ("$,1?$?M(B" . "$,43}5)(B") ("$,1?$(B" . "$,43}(B") ("$,1?$??(B" . "$,43~(B") ("$,1?$?@(B" . "$,43~4~(B") 226 ("$,1?%?M(B" . "$,44B5)(B") ("$,1?%(B" . "$,44B(B") ("$,1?%??(B" . "$,44C(B") ("$,1?%?@(B" . "$,44C4~(B") 227 ("$,1?&?M(B" . "$,44E5)(B") ("$,1?&(B" . "$,44E(B") ("$,1?&??(B" . "$,44F(B") ("$,1?&?@(B" . "$,44F4~(B") 228 ("$,1?'?M(B" . "$,44H5)(B") ("$,1?'(B" . "$,44H(B") ("$,1?'??(B" . "$,44I(B") ("$,1?'?@(B" . "$,44I4~(B") 229 ("$,1?(?M(B" . "$,44K5)(B") ("$,1?((B" . "$,44K(B") ("$,1?(??(B" . "$,44L(B") ("$,1?(?@(B" . "$,44L4~(B") 230 ("$,1?*?M(B" . "$,44N5)(B") ("$,1?*(B" . "$,44N(B") ("$,1?*??(B" . "$,44O(B") ("$,1?*?@(B" . "$,44O4~(B") ("$,1?*?A(B" . "$,44N5"(B") ("$,1?*?B(B" . "$,44N5#(B") ("$,1?*?J(B" . "$,44N5&5#(B") ("$,1?*?K(B" . "$,44N5&5#4~(B") 231 ("$,1?+?M(B" . "$,44Q5)(B") ("$,1?+(B" . "$,44Q(B") ("$,1?+??(B" . "$,44R(B") ("$,1?+?@(B" . "$,44R4~(B") ("$,1?+?A(B" . "$,44Q5"(B") ("$,1?+?B(B" . "$,44Q5#(B") ("$,1?+?J(B" . "$,44Q5&5#(B") ("$,1?+?K(B" . "$,44Q5&5#4~(B") 232 ("$,1?,?M(B" . "$,44W5)(B") ("$,1?,(B" . "$,44V(B") ("$,1?,?>(B". "$,44W4{(B") ("$,1?,??(B" . "$,44X(B") ("$,1?,?@(B" . "$,44X4~(B") ("$,1?,?F(B" . "$,44W5&(B") ("$,1?,?G(B" . "$,44W5&4~(B") ("$,1?,?H(B" . "$,44W5&5'(B") ("$,1?,?J(B" . "$,44W5&5&5 (B") ("$,1?,?K(B" . "$,44W5&5&5 4~(B") ("$,1?,?L(B" . "$,44W5((B") 233 ("$,1?-?M(B" . "$,44Z5)(B") ("$,1?-(B" . "$,44Z(B") ("$,1?-??(B" . "$,44[(B") ("$,1?-?@(B" . "$,44[4~(B") 234 ("$,1?.?M(B" . "$,44h5!5)(B") ("$,1?.(B" . "$,44h4z4(B") ("$,1?.?>(B" . "$,44h4z5!4{(B") ("$,1?.??(B" . "$,44i4(B") ("$,1?.?@(B" . "$,44i44~(B") ("$,1?.?J(B". "$,44h5&5 (B") ("$,1?.?K(B". "$,44h5&5 4~(B") 235 ("$,1?/?M(B" . "$,44^4z5!5)(B") ("$,1?/(B" . "$,44^4z4(B") ("$,1?/?>(B" . "$,44^4z5!4{(B")("$,1?/??(B" . "$,44_4(B") ("$,1?/?@(B" . "$,44_44~(B") ("$,1?/?J(B" . "$,44^5&5 (B") ("$,1?/?K(B" . "$,44^5&5 4~(B") 236 ("$,1?0?M(B" . "$,44a5)(B") ("$,1?0(B" . "$,44a(B") ("$,1?0??(B" . "$,44b(B") ("$,1?0?@(B" . "$,44b4~(B") 237 ("$,1?0?M(B" . "$,44a5)(B") ("$,1?0(B" . "$,44a(B") ("$,1?0??(B" . "$,44b(B") ("$,1?0?@(B" . "$,44b4~(B") 238 ("$,1?2?M(B" . "$,44e5)(B") ("$,1?2(B" . "$,44d(B") ("$,1?2?>(B" . "$,44e4{(B") ("$,1?2??(B" . "$,44f(B") ("$,1?2?@(B" . "$,44f4~(B") ("$,1?2?F(B" . "$,44e5&(B") ("$,1?2?G(B" . "$,44e5&4~(B") ("$,1?2?H(B" . "$,44e5&5'(B") ("$,1?2?J(B" . "$,44e5&5&5 (B") ("$,1?2?K(B" . "$,44e5&5&5 4~(B") ("$,1?2?L(B" . "$,44e5((B") 239 ("$,1?5?M(B" . "$,44h5)(B") ("$,1?5(B" . "$,44h(B") ("$,1?5??(B" . "$,44i(B") ("$,1?5?@(B" . "$,44i4~(B") ("$,1?5?A(B" . "$,44h5"(B") ("$,1?5?B(B" . "$,44h5#(B") ("$,1?5?J(B" . "$,44h5&5#(B") ("$,1?5?K(B" . "$,44h5&5#4~(B") 240 ("$,1?6?M(B" . "$,44k5)(B") ("$,1?6(B" . "$,44k(B") ("$,1?6??(B" . "$,44l(B") ("$,1?6?@(B" . "$,44l4~(B") 241 ("$,1?7?M(B" . "$,44n5)(B") ("$,1?7(B" . "$,44n(B") ("$,1?7??(B" . "$,44o(B") ("$,1?7?@(B" . "$,44o4~(B") 242 ("$,1?8?M(B" . "$,44q5)(B") ("$,1?8(B" . "$,44q(B") ("$,1?8??(B" . "$,44r(B") ("$,1?8?@(B" . "$,44r4~(B") 243 ("$,1?9?M(B" . "$,44t5)(B") ("$,1?9(B" . "$,44t(B") ("$,1?9??(B" . "$,44u(B") ("$,1?9?@(B" . "$,44u4~(B") 244 ("$,1?3?M(B" . "$,44w5)(B") ("$,1?3(B" . "$,44w(B") ("$,1?3??(B" . "$,44x(B") ("$,1?3?@(B" . "$,44x4~(B")) 245"Kannada characters to glyphs conversion table. 246Default value contains only the basic rules.") 247 248(defvar knd-char-glyph-hash 249 (let* ((hash (make-hash-table :test 'equal))) 250 (mapc (function (lambda (x) (puthash (car x) (cdr x) hash))) 251 knd-char-glyph) 252 hash)) 253 254(defvar knd-char-glyph-regexp 255 (kannada-regexp-of-hashtbl-keys knd-char-glyph-hash)) 256 257(defvar knd-conjunct-glyph 258 '(("$,1>u(B" . "$,43Q(B") ("$,1>v(B" . "$,43U(B") ("$,1>w(B" . "$,43X(B") ("$,1>x(B" . "$,43[(B") ("$,1>y(B" . "$,43](B") 259 ("$,1>z(B" . "$,43`(B") ("$,1>{(B" . "$,43c(B") ("$,1>|(B" . "$,43g(B") ("$,1>}(B" . "$,43i(B") ("$,1>~(B" . "$,43k(B") 260 ("$,1>(B" . "$,43o(B") ("$,1? (B" . "$,43r(B") ("$,1?!(B" . "$,43u(B") ("$,1?"(B" . "$,43x(B") ("$,1?#(B" . "$,43|(B") 261 ("$,1?$(B" . "$,44A(B") ("$,1?%(B" . "$,44D(B") ("$,1?&(B" . "$,44G(B") ("$,1?'(B" . "$,44J(B") ("$,1?((B" . "$,44M(B") 262 ("$,1?*(B" . "$,44P(B") ("$,1?+(B" . "$,44U(B") ("$,1?,(B" . "$,44Y(B") ("$,1?-(B" . "$,44\(B") ("$,1?.(B" . "$,44](B") 263 ("$,1?/(B" . "$,44`(B") ("$,1?0(B" . "$,44c(B") ("$,1?2(B" . "$,44g(B") ("$,1?3(B" . "$,44y(B") ("$,1?5(B" . "$,44j(B") 264 ("$,1?6(B" . "$,44m(B") ("$,1?7(B" . "$,44p(B") ("$,1?8(B" . "$,44s(B") ("$,1?9(B" . "$,44v(B")) 265"Kannada characters to conjunct glyphs conversion table.") 266 267(defvar knd-conjunct-glyph-hash 268 (let* ((hash (make-hash-table :test 'equal))) 269 (mapc (function (lambda (x) (puthash (car x) (cdr x) hash))) 270 knd-conjunct-glyph) 271 hash)) 272 273(defvar knd-conjunct-glyph-regexp 274 (kannada-regexp-of-hashtbl-vals knd-conjunct-glyph-hash)) 275 276(mapc 277 (function (lambda (x) 278 (put-char-code-property (aref (cdr x) 0) 'reference-point '(5 . 3)))) 279 knd-conjunct-glyph) 280 281;; glyph-to-glyph conversion table. 282;; it is supposed that glyphs are ordered in 283;; [consonant/nukta] - [matra/virama] - [preceding-r] - [anuswar]. 284 285(defvar knd-glyph-glyph 286 '(("$,45$4A(B" . "$,45*(B") 287 ("$,45'4A(B" . "$,45+(B") 288 ("$,44A3g(B" . "$,45,(B") 289 ("$,45$3Q(B" . "$,45-(B"))) 290 291(defvar knd-glyph-glyph-hash 292 (let* ((hash (make-hash-table :test 'equal))) 293 (mapc (function (lambda (x) (puthash (car x) (cdr x) hash))) 294 knd-glyph-glyph) 295 hash)) 296(defvar knd-glyph-glyph-regexp 297 (kannada-regexp-of-hashtbl-keys knd-glyph-glyph-hash)) 298 299(defun knd-charseq (from &optional to) 300 (if (null to) (setq to from)) 301 (mapcar (function (lambda (x) (indian-glyph-char x 'kannada))) 302 (kannada-range from to))) 303 304(defvar knd-glyph-cv 305 (append 306 (knd-charseq #x40 #x50) 307 (knd-charseq #x52 #x54) 308 (knd-charseq #x56 #x57) 309 (knd-charseq #x59 #x5a) 310 (knd-charseq #x5c) 311 (knd-charseq #x5e #x5f) 312 (knd-charseq #x61 #x62) 313 (knd-charseq #x64 #x66) 314 (knd-charseq #x6a) 315 (knd-charseq #x6c #x6e) 316 (knd-charseq #x70 #x71) 317 (knd-charseq #x73 #x74) 318 (knd-charseq #x76 #x77) 319 (knd-charseq #x79 #x7b) 320 (knd-charseq #x7d #x7e) 321 (knd-charseq #xa2 #xa3) 322 (knd-charseq #xa5 #xa6) 323 (knd-charseq #xa8 #xa9) 324 (knd-charseq #xab #xac) 325 (knd-charseq #xae #xaf) 326 (knd-charseq #xb1 #xb2) 327 (knd-charseq #xb6 #xb8) 328 (knd-charseq #xb6 #xb8) 329 (knd-charseq #xba #xbb) 330 (knd-charseq #xbe #xbf) 331 (knd-charseq #xc1 #xc2) 332 (knd-charseq #xc4 #xc6) 333 (knd-charseq #xc8 #xc9) 334 (knd-charseq #xcb #xcc) 335 (knd-charseq #xce #xcf) 336 (knd-charseq #xd1 #xd2) 337 (knd-charseq #xd4 #xd5) 338 (knd-charseq #xd7 #xd8) 339 (knd-charseq #xc3)) 340 "Kannada Consonants/Vowels/Nukta Glyphs") 341 342(defvar knd-glyph-space 343 (knd-charseq #xb3 #xb4) 344 "Kannada Spacing Glyphs") 345 346(defvar knd-glyph-right-modifier 347 (append 348 (knd-charseq #xdb #xdd) 349 (knd-charseq #xdf) 350 (knd-charseq #xe0 #xe3) 351 (knd-charseq #xe9)) 352 "Kannada Modifiers attached at the right side.") 353 354(defvar knd-glyph-right-modifier-regexp 355 (concat "[" knd-glyph-right-modifier "]")) 356 357(defvar knd-glyph-jha-tail 358 (knd-charseq #x68) 359 "Kannada tail for jha.") 360 361(defvar knd-glyph-top-matra 362 (append 363 (knd-charseq #xda) 364 (knd-charseq #xdd) 365 (knd-charseq #xe6) 366 (knd-charseq #xe8)) 367 "Kannada Matras attached at the top side.") 368 369(defvar knd-glyph-bottom-matra 370 (append 371 (knd-charseq #xe4 #xe5) 372 (knd-charseq #xe7)) 373 "Kannada Matras attached at the bottom.") 374 375(defvar knd-glyph-end-marks 376 (append 377 (knd-charseq #x25) 378 (knd-charseq #x4d #x4e) 379 (knd-charseq #xde)) 380 "Kannada end marks: arkavattu, virama, au and diirghaa.") 381 382(defvar knd-glyph-bottom-modifier 383 (append 384 (knd-charseq #x51) 385 (knd-charseq #x55) 386 (knd-charseq #x58) 387 (knd-charseq #x5b) 388 (knd-charseq #x5d) 389 (knd-charseq #x60) 390 (knd-charseq #x63) 391 (knd-charseq #x67) 392 (knd-charseq #x69) 393 (knd-charseq #x6b) 394 (knd-charseq #x6f) 395 (knd-charseq #x72) 396 (knd-charseq #x75) 397 (knd-charseq #x78) 398 (knd-charseq #x7c) 399 (knd-charseq #xa1) 400 (knd-charseq #xa4) 401 (knd-charseq #xa7) 402 (knd-charseq #xaa) 403 (knd-charseq #xad) 404 (knd-charseq #xb0) 405 (knd-charseq #xb5) 406 (knd-charseq #xb9) 407 (knd-charseq #xbc #xbd) 408 (knd-charseq #xc0) 409 (knd-charseq #xc3) 410 (knd-charseq #xc7) 411 (knd-charseq #xca) 412 (knd-charseq #xcd) 413 (knd-charseq #xd0) 414 (knd-charseq #xd3) 415 (knd-charseq #xd6) 416 (knd-charseq #xd9) 417 (knd-charseq #xea #xef)) 418 "Kannada Modifiers attached at the bottom.") 419 420(defvar knd-glyph-order 421 `((,knd-glyph-cv . 1) 422 (,knd-glyph-top-matra . 2) 423 (,knd-glyph-jha-tail . 3) 424 (,knd-glyph-right-modifier . 4) 425 (,knd-glyph-space . 5) 426 (,knd-glyph-bottom-modifier . 5) 427 (,knd-glyph-bottom-matra . 6) 428 (,knd-glyph-end-marks . 7) 429 )) 430 431(mapc 432 (function (lambda (x) 433 (mapc 434 (function (lambda (y) 435 (put-char-code-property y 'composition-order (cdr x)))) 436 (car x)))) 437 knd-glyph-order) 438 439(defun kannada-compose-syllable-string (string) 440 (with-temp-buffer 441 (insert (decompose-string string)) 442 (kannada-compose-syllable-region (point-min) (point-max)) 443 (buffer-string))) 444 445;; kch 446(defun kannada-compose-syllable-region (from to) 447 "Compose kannada syllable in region FROM to TO." 448 (let ((glyph-str nil) (cons-num 0) (glyph-str-list nil) 449 (last-virama nil) (preceding-r nil) (last-modifier nil) 450 (last-char (char-before to)) match-str pos 451 glyph-block split-pos (conj nil) (rest nil)) 452 (save-excursion 453 (save-restriction 454 ;;; *** char-to-glyph conversion *** 455 ;; Special rule 1. -- Last virama must be preserved. 456 (if (eq last-char ?$,1?M(B) 457 (progn 458 (setq last-virama t) 459 (narrow-to-region from (1- to))) 460 (narrow-to-region from to)) 461 (goto-char (point-min)) 462 ;; Special rule 2. -- preceding "r virama" must be modifier. 463 (when (looking-at "$,1?0?M(B.") 464 (setq preceding-r t) 465 (goto-char (+ 2 (point)))) 466 ;; remove conjunct consonants 467 (while (re-search-forward knd-char-glyph-regexp nil t) 468 (setq match-str (match-string 0)) 469 (if (and (string-match kannada-consonant match-str) 470 (> cons-num 0)) 471 (progn 472 (setq conj (concat conj (gethash (match-string 0 match-str) 473 knd-conjunct-glyph-hash))) 474 (setq match-str (replace-match "" t nil match-str)) 475 (if (string-match "$,1?M(B" rest) 476 (setq rest (replace-match "" t nil rest))))) 477 (setq rest (concat rest match-str)) 478 ;; count the number of consonant-glyhs. 479 (if (string-match kannada-consonant match-str) 480 (setq cons-num (1+ cons-num)))) 481 ;; translate the rest characters into glyphs 482 (setq pos 0) 483 (while (string-match knd-char-glyph-regexp rest pos) 484 (setq match-str (match-string 0 rest)) 485 (setq pos (match-end 0)) 486 (setq glyph-str 487 (concat glyph-str (gethash match-str knd-char-glyph-hash)))) 488 489 (if conj (setq glyph-str (concat glyph-str conj))) 490 (if last-virama (setq glyph-str (concat glyph-str "$,45)(B")) 491 (goto-char (point-min)) 492 (if (re-search-forward kannada-consonant-needs-twirl nil t) 493 (progn 494 (setq match-str (match-string 0)) 495 (setq glyph-str (concat glyph-str "$,44z(B"))))) 496 ;; preceding-r must be attached 497 (if preceding-r 498 (setq glyph-str (concat glyph-str "$,43%(B"))) 499 ;;; *** glyph-to-glyph conversion *** 500 (when (string-match knd-glyph-glyph-regexp glyph-str) 501 (setq glyph-str 502 (replace-match (gethash (match-string 0 glyph-str) 503 knd-glyph-glyph-hash) 504 nil t glyph-str))) 505 ;;; *** glyph reordering *** 506 (while (setq split-pos (string-match "$,45)(B\\|.$" glyph-str)) 507 (setq glyph-block (substring glyph-str 0 (1+ split-pos))) 508 (setq glyph-str (substring glyph-str (1+ split-pos))) 509 (setq 510 glyph-block 511 (sort (string-to-list glyph-block) 512 (function (lambda (x y) 513 (< (get-char-code-property x 'composition-order) 514 (get-char-code-property y 'composition-order)))))) 515 (setq glyph-str-list (nconc glyph-str-list glyph-block))) 516 ;;; *** insert space glyphs for kerning *** 517 (if (> cons-num 0) 518 (let ((curr glyph-str-list) (prev nil) (last-bott nil) bott co) 519 (while curr 520 (setq co (get-char-code-property 521 (car curr) 'composition-order) 522 bott (or (eq co 5) (eq co 6))) 523 (if (and bott last-bott) 524 (setcdr prev (cons ?$,44T(B curr))) 525 (setq last-bott bott prev curr curr (cdr curr))))) 526 ;; concatenate and attach reference-points. 527 (setq glyph-str 528 (cdr 529 (apply 530 'nconc 531 (mapcar 532 (function (lambda (x) 533 (list 534 (or (get-char-code-property x 'reference-point) 535 '(5 . 3) ;; default reference point. 536 ) 537 x))) 538 glyph-str-list)))))) 539 (compose-region from to glyph-str))) 540 541(provide 'knd-util) 542 543;;; arch-tag: 78d32230-a960-46a5-b622-61ed6ffcf8fc 544;;; knd-util.el ends here 545