Guest User

Untitled

a guest
Dec 13th, 2017
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.48 KB | None | 0 0
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Distributed under the BSD license:
  3. *
  4. * Copyright (c) 2010, Ajax.org B.V.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * * Neither the name of Ajax.org B.V. nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * ***** END LICENSE BLOCK ***** */
  30.  
  31. define(function(require, exports, module) {
  32. "use strict";
  33.  
  34. var ArabicAlefBetIntervalsBegine = ['\u0621', '\u0641'];
  35. var ArabicAlefBetIntervalsEnd = ['\u063A', '\u064a'];
  36. var dir = 0, hiLevel = 0;
  37. var lastArabic = false, hasUBAT_AL = false, hasUBAT_B = false, hasUBAT_S = false, hasBlockSep = false, hasSegSep = false;
  38.  
  39. var impTab_LTR = [
  40. /* L, R, EN, AN, N, IL, Cond */
  41. /* 0 LTR text */ [ 0, 3, 0, 1, 0, 0, 0 ],
  42. /* 1 LTR+AN */ [ 0, 3, 0, 1, 2, 2, 0 ],
  43. /* 2 LTR+AN+N */ [ 0, 3, 0, 0x11, 2, 0, 1 ],
  44. /* 3 RTL text */ [ 0, 3, 5, 5, 4, 1, 0 ],
  45. /* 4 RTL cont */ [ 0, 3, 0x15, 0x15, 4, 0, 1 ],
  46. /* 5 RTL+EN/AN */ [ 0, 3, 5, 5, 4, 2, 0 ]
  47. ];
  48.  
  49. var impTab_RTL = [
  50. /* L, R, EN, AN, N, IL, Cond */
  51. /* 0 RTL text */ [ 2, 0, 1, 1, 0, 1, 0 ],
  52. /* 1 RTL+EN/AN */ [ 2, 0, 1, 1, 0, 2, 0 ],
  53. /* 2 LTR text */ [ 2, 0, 2, 1, 3, 2, 0 ],
  54. /* 3 LTR+cont */ [ 2, 0, 2, 0x21, 3, 1, 1 ]
  55. ];
  56.  
  57. var LTR = 0, RTL = 1;
  58.  
  59. var L = 0; /* left to right */
  60. var R = 1; /* right to left */
  61. var EN = 2; /* European digit */
  62. var AN = 3; /* Arabic-Indic digit */
  63. var ON = 4; /* neutral */
  64. var B = 5; /* block separator */
  65. var S = 6; /* segment separator */
  66. var AL = 7; /* Arabic Letter */
  67. var WS = 8; /* white space */
  68. var CS = 9; /* common digit separator */
  69. var ES = 10; /* European digit separator */
  70. var ET = 11; /* European digit terminator */
  71. var NSM = 12; /* Non Spacing Mark */
  72. var LRE = 13; /* LRE */
  73. var RLE = 14; /* RLE */
  74. var PDF = 15; /* PDF */
  75. var LRO = 16; /* LRO */
  76. var RLO = 17; /* RLO */
  77. var BN = 18; /* Boundary Neutral */
  78.  
  79. var UnicodeTBL00 = [
  80. BN,BN,BN,BN,BN,BN,BN,BN,BN,S,B,S,WS,B,BN,BN,
  81. BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,B,B,B,S,
  82. WS,ON,ON,ET,ET,ET,ON,ON,ON,ON,ON,ES,CS,ES,CS,CS,
  83. EN,EN,EN,EN,EN,EN,EN,EN,EN,EN,CS,ON,ON,ON,ON,ON,
  84. ON,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,
  85. L,L,L,L,L,L,L,L,L,L,L,ON,ON,ON,ON,ON,
  86. ON,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,
  87. L,L,L,L,L,L,L,L,L,L,L,ON,ON,ON,ON,BN,
  88. BN,BN,BN,BN,BN,B,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,
  89. BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,
  90. CS,ON,ET,ET,ET,ET,ON,ON,ON,ON,L,ON,ON,BN,ON,ON,
  91. ET,ET,EN,EN,ON,L,ON,ON,ON,EN,L,ON,ON,ON,ON,ON
  92. ];
  93.  
  94. var UnicodeTBL20 = [
  95. WS,WS,WS,WS,WS,WS,WS,WS,WS,WS,WS,BN,BN,BN,L,R ,
  96. ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,
  97. ON,ON,ON,ON,ON,ON,ON,ON,WS,B,LRE,RLE,PDF,LRO,RLO,CS,
  98. ET,ET,ET,ET,ET,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,
  99. ON,ON,ON,ON,CS,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,
  100. ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,WS
  101. ];
  102.  
  103. function _computeLevels(chars, levels, len, charTypes) {
  104. var impTab = dir ? impTab_RTL : impTab_LTR
  105. , prevState = null, newClass = null, newLevel = null, newState = 0
  106. , action = null, cond = null, condPos = -1, i = null, ix = null, classes = [];
  107.  
  108. if (!charTypes) {
  109. for (i = 0, charTypes = []; i < len; i++) {
  110. charTypes[i] = _getCharacterType(chars[i]);
  111. }
  112. }
  113. hiLevel = dir;
  114. lastArabic = false;
  115. hasUBAT_AL = false;
  116. hasUBAT_B = false;
  117. hasUBAT_S = false;
  118. for (ix = 0; ix < len; ix++){
  119. prevState = newState;
  120. classes[ix] = newClass = _getCharClass(chars, charTypes, classes, ix);
  121. newState = impTab[prevState][newClass];
  122. action = newState & 0xF0;
  123. newState &= 0x0F;
  124. levels[ix] = newLevel = impTab[newState][5];
  125. if (action > 0){
  126. if (action == 0x10){
  127. for(i = condPos; i < ix; i++){
  128. levels[i] = 1;
  129. }
  130. condPos = -1;
  131. } else {
  132. condPos = -1;
  133. }
  134. }
  135. cond = impTab[newState][6];
  136. if (cond){
  137. if(condPos == -1){
  138. condPos = ix;
  139. }
  140. }else{
  141. if (condPos > -1){
  142. for(i = condPos; i < ix; i++){
  143. levels[i] = newLevel;
  144. }
  145. condPos = -1;
  146. }
  147. }
  148. if (charTypes[ix] == B){
  149. levels[ix] = 0;
  150. }
  151. hiLevel |= newLevel;
  152. }
  153. if (hasUBAT_S){
  154. for(i = 0; i < len; i++){
  155. if(charTypes[i] == S){
  156. levels[i] = dir;
  157. for(var j = i - 1; j >= 0; j--){
  158. if(charTypes[j] == WS){
  159. levels[j] = dir;
  160. }else{
  161. break;
  162. }
  163. }
  164. }
  165. }
  166. }
  167. }
  168.  
  169. function _invertLevel(lev, levels, _array) {
  170. if (hiLevel < lev){
  171. return;
  172. }
  173. if (lev == 1 && dir == RTL && !hasUBAT_B){
  174. _array.reverse();
  175. return;
  176. }
  177. var len = _array.length, start = 0, end, lo, hi, tmp;
  178. while(start < len){
  179. if (levels[start] >= lev){
  180. end = start + 1;
  181. while(end < len && levels[end] >= lev){
  182. end++;
  183. }
  184. for(lo = start, hi = end - 1 ; lo < hi; lo++, hi--){
  185. tmp = _array[lo];
  186. _array[lo] = _array[hi];
  187. _array[hi] = tmp;
  188. }
  189. start = end;
  190. }
  191. start++;
  192. }
  193. }
  194.  
  195. function _getCharClass(chars, types, classes, ix) {
  196. var cType = types[ix], wType, nType, len, i;
  197. switch(cType){
  198. case L:
  199. case R:
  200. lastArabic = false;
  201. case ON:
  202. case AN:
  203. return cType;
  204. case EN:
  205. return lastArabic ? AN : EN;
  206. case AL:
  207. lastArabic = true;
  208. hasUBAT_AL = true;
  209. return R;
  210. case WS:
  211. return ON;
  212. case CS:
  213. if (ix < 1 || (ix + 1) >= types.length ||
  214. ((wType = classes[ix - 1]) != EN && wType != AN) ||
  215. ((nType = types[ix + 1]) != EN && nType != AN)){
  216. return ON;
  217. }
  218. if (lastArabic){nType = AN;}
  219. return nType == wType ? nType : ON;
  220. case ES:
  221. wType = ix > 0 ? classes[ix - 1] : B;
  222. if (wType == EN && (ix + 1) < types.length && types[ix + 1] == EN){
  223. return EN;
  224. }
  225. return ON;
  226. case ET:
  227. if (ix > 0 && classes[ix - 1] == EN){
  228. return EN;
  229. }
  230. if (lastArabic){
  231. return ON;
  232. }
  233. i = ix + 1;
  234. len = types.length;
  235. while (i < len && types[i] == ET){
  236. i++;
  237. }
  238. if (i < len && types[i] == EN){
  239. return EN;
  240. }
  241. return ON;
  242. case NSM:
  243. len = types.length;
  244. i = ix + 1;
  245. while (i < len && types[i] == NSM){
  246. i++;
  247. }
  248. if (i < len){
  249. var c = chars[ix], rtlCandidate = (c >= 0x0591 && c <= 0x08FF) || c == 0xFB1E;
  250.  
  251. wType = types[i];
  252. if (rtlCandidate && (wType == R || wType == AL)){
  253. return R;
  254. }
  255. }
  256.  
  257. if (ix < 1 || (wType = types[ix - 1]) == B){
  258. return ON;
  259. }
  260. return classes[ix - 1];
  261. case B:
  262. lastArabic = false;
  263. hasUBAT_B = true;
  264. return dir;
  265. case S:
  266. hasUBAT_S = true;
  267. return ON;
  268. case LRE:
  269. case RLE:
  270. case LRO:
  271. case RLO:
  272. case PDF:
  273. lastArabic = false;
  274. case BN:
  275. return ON;
  276. }
  277. }
  278.  
  279. function _getCharacterType( ch ) {
  280. var uc = ch.charCodeAt(0), hi = uc >> 8;
  281.  
  282. if (hi == 0) {
  283. return ((uc > 0x00BF) ? L : UnicodeTBL00[uc]);
  284. } else if (hi == 5) {
  285. return (/[\u0591-\u05f4]/.test(ch) ? R : L);
  286. } else if (hi == 6) {
  287. if (/[\u0610-\u061a\u064b-\u065f\u06d6-\u06e4\u06e7-\u06ed]/.test(ch))
  288. return NSM;
  289. else if (/[\u0660-\u0669\u066b-\u066c]/.test(ch))
  290. return AN;
  291. else if (uc == 0x066A)
  292. return ET;
  293. else if (/[\u06f0-\u06f9]/.test(ch))
  294. return EN;
  295. else
  296. return AL;
  297. } else if (hi == 0x20 && uc <= 0x205F) {
  298. return UnicodeTBL20[uc & 0xFF];
  299. } else if (hi == 0xFE) {
  300. return (uc >= 0xFE70 ? AL : ON);
  301. }
  302. return ON;
  303. }
  304.  
  305. function _isArabicDiacritics( ch ) {
  306. return (ch >= '\u064b' && ch <= '\u0655');
  307. }
  308.  
  309. /* Strong LTR character (0 - even), regular width */
  310. exports.L = L;
  311. /* Strong RTL character (1 - odd), Bidi width */
  312. exports.R = R;
  313. /* European digit (2 - even), regular width */
  314. exports.EN = EN;
  315. /* Neutral RTL-by-context character (3 - odd), regular width */
  316. exports.ON_R = 3;
  317. /* Hindi (Arabic) digit (4 - even), Bidi width */
  318. exports.AN = 4;
  319. /* Arabic LamAlef (5 - odd), Half Bidi width */
  320. exports.R_H = 5;
  321. /* invisible EOL (6 - even), zero width */
  322. exports.B = 6;
  323.  
  324. exports.DOT = "\xB7";
  325.  
  326. /**
  327. * Performs text reordering by implementing Unicode Bidi algorithm
  328. * with aim to produce logical<->visual map and Bidi levels
  329. * @param {String} text string to be reordered
  330. * @param {Array} unicode character types produced by call to 'hasBidiCharacters'
  331. * @param {Boolean} 'true' for right-to-left text direction, otherwise 'false'
  332. *
  333. * @return {Object} An object containing logicalFromVisual map and Bidi levels
  334. **/
  335. exports.doBidiReorder = function(text, textCharTypes, isRtl) {
  336. if (text.length < 2)
  337. return {};
  338.  
  339. var chars = text.split(""), logicalFromVisual = new Array(chars.length),
  340. bidiLevels = new Array(chars.length), levels = [];
  341.  
  342. dir = isRtl ? RTL : LTR;
  343.  
  344. _computeLevels(chars, levels, chars.length, textCharTypes);
  345.  
  346. for (var i = 0; i < logicalFromVisual.length; logicalFromVisual[i] = i, i++);
  347.  
  348. _invertLevel(2, levels, logicalFromVisual);
  349. _invertLevel(1, levels, logicalFromVisual);
  350.  
  351. for (var i = 0; i < logicalFromVisual.length - 1; i++) { //fix levels to reflect character width
  352. if (textCharTypes[i] === AN) {
  353. levels[i] = exports.AN;
  354. } else if (levels[i] === R && ((textCharTypes[i] > AL && textCharTypes[i] < LRE)
  355. || textCharTypes[i] === ON || textCharTypes[i] === BN)) {
  356. levels[i] = exports.ON_R;
  357. } else if ((i > 0 && chars[i - 1] === '\u0644') && /\u0622|\u0623|\u0625|\u0627/.test(chars[i])) {
  358. levels[i - 1] = levels[i] = exports.R_H;
  359. i++;
  360. }
  361. }
  362. /* fix level to mark zero length EOL */
  363. if (chars[chars.length - 1] === exports.DOT)
  364. levels[chars.length - 1] = exports.B;
  365.  
  366. for (var i = 0; i < logicalFromVisual.length; i++) {
  367. bidiLevels[i] = levels[logicalFromVisual[i]];
  368. }
  369.  
  370. return {'logicalFromVisual': logicalFromVisual, 'bidiLevels': bidiLevels};
  371. };
  372.  
  373. /**
  374. * Performs character classification, to be used in Unicode Bidi algorithm.
  375. * @param {String} text string to be reordered
  376. * @param {Array} unicode character types (to be filled by this method)
  377. *
  378. * @return {Boolean} 'true' if text contains Bidi characters, otherwise 'false'
  379. **/
  380. exports.hasBidiCharacters = function(text, textCharTypes){
  381. var ret = false;
  382. for (var i = 0; i < text.length; i++){
  383. textCharTypes[i] = _getCharacterType(text.charAt(i));
  384. if (!ret && (textCharTypes[i] == R || textCharTypes[i] == AL))
  385. ret = true;
  386. }
  387. return ret;
  388. };
  389.  
  390. /**
  391. * Returns visual index corresponding to logical index basing on logicalFromvisual
  392. * map provided by Unicode Bidi algorithm.
  393. * @param {int} logical index of character in text buffer
  394. * @param {Object} object containing logicalFromVisual map
  395. *
  396. * @return {int} visual index (on display) corresponding to logical index
  397. **/
  398. exports.getVisualFromLogicalIdx = function(logIdx, rowMap) {
  399. for (var i = 0; i < rowMap.logicalFromVisual.length; i++) {
  400. if (rowMap.logicalFromVisual[i] == logIdx)
  401. return i;
  402. }
  403. return 0;
  404. };
  405.  
  406. });
Add Comment
Please, Sign In to add comment