1 /*global JXG: true, define: true, escape: true, unescape: true*/
  2 /*jslint nomen: true, plusplus: true, bitwise: true*/
  3 
  4 /* depends:
  5  jxg
  6  */
  7 
  8 define(['jxg'], function (JXG) {
  9 
 10     "use strict";
 11 
 12     // constants
 13     var UTF8_ACCEPT = 0,
 14         UTF8_REJECT = 12,
 15         UTF8D = [
 16             // The first part of the table maps bytes to character classes that
 17             // to reduce the size of the transition table and create bitmasks.
 18             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 19             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 20             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 21             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 22             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
 23             7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 24             8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 25             10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3,  11, 6, 6, 6, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
 26 
 27             // The second part is a transition table that maps a combination
 28             // of a state of the automaton and a character class to a state.
 29             0, 12, 24, 36, 60, 96, 84, 12, 12, 12, 48, 72,  12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
 30             12,  0, 12, 12, 12, 12, 12,  0, 12,  0, 12, 12,  12, 24, 12, 12, 12, 12, 12, 24, 12, 24, 12, 12,
 31             12, 12, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12,  12, 24, 12, 12, 12, 12, 12, 12, 12, 24, 12, 12,
 32             12, 12, 12, 12, 12, 12, 12, 36, 12, 36, 12, 12,  12, 36, 12, 12, 12, 12, 12, 36, 12, 36, 12, 12,
 33             12, 36, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12
 34         ];
 35 
 36     // Util namespace
 37     JXG.Util = JXG.Util || {};
 38 
 39     /**
 40      * UTF8 encoding routines
 41      * @namespace
 42      */
 43     JXG.Util.UTF8 = {
 44         /**
 45          * Encode a string to utf-8.
 46          * @param {String} string
 47          * @returns {String} utf8 encoded string
 48          */
 49         encode : function (string) {
 50             var n, c,
 51                 utftext = '',
 52                 len = string.length;
 53 
 54             string = string.replace(/\r\n/g, '\n');
 55 
 56             // See
 57             // http://ecmanaut.blogspot.ca/2006/07/encoding-decoding-utf8-in-javascript.html
 58             // http://monsur.hossa.in/2012/07/20/utf-8-in-javascript.html
 59             if (typeof unescape === 'function' && typeof encodeURIComponent === 'function') {
 60                 return unescape(encodeURIComponent(string));
 61             }
 62 
 63             for (n = 0; n < len; n++) {
 64                 c = string.charCodeAt(n);
 65 
 66                 if (c < 128) {
 67                     utftext += String.fromCharCode(c);
 68                 } else if ((c > 127) && (c < 2048)) {
 69                     utftext += String.fromCharCode((c >> 6) | 192);
 70                     utftext += String.fromCharCode((c & 63) | 128);
 71                 } else {
 72                     utftext += String.fromCharCode((c >> 12) | 224);
 73                     utftext += String.fromCharCode(((c >> 6) & 63) | 128);
 74                     utftext += String.fromCharCode((c & 63) | 128);
 75                 }
 76 
 77             }
 78 
 79             return utftext;
 80         },
 81 
 82         /**
 83          * Decode a string from utf-8.
 84          * @param {String} utftext to decode
 85          * @returns {String} utf8 decoded string
 86          */
 87         decode : function (utftext) {
 88             /*
 89                  The following code is a translation from C99 to JavaScript.
 90 
 91                  The original C99 code can be found at
 92                  http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
 93 
 94                  Original copyright note:
 95 
 96                  Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
 97 
 98                  License: MIT License (see LICENSE.MIT)
 99             */
100 
101             var i, charCode, type,
102                 j = 0,
103                 codepoint = 0,
104                 state = UTF8_ACCEPT,
105                 chars = [],
106                 len = utftext.length,
107                 results = [];
108 
109             for (i = 0; i < len; i++) {
110                 charCode = utftext.charCodeAt(i);
111                 type = UTF8D[charCode];
112 
113                 if (state !== UTF8_ACCEPT) {
114                     codepoint = (charCode & 0x3f) | (codepoint << 6);
115                 } else {
116                     codepoint = (0xff >> type) & charCode;
117                 }
118 
119                 state = UTF8D[256 + state + type];
120 
121                 if (state === UTF8_ACCEPT) {
122                     if (codepoint > 0xffff) {
123                         chars.push(0xD7C0 + (codepoint >> 10), 0xDC00 + (codepoint & 0x3FF));
124                     } else {
125                         chars.push(codepoint);
126                     }
127 
128                     j++;
129 
130                     if (j % 10000 === 0) {
131                         results.push(String.fromCharCode.apply(null, chars));
132                         chars = [];
133                     }
134                 }
135             }
136             results.push(String.fromCharCode.apply(null, chars));
137             return results.join("");
138         },
139 
140         /**
141          * Extends the standard charCodeAt() method of the String class to find the ASCII char code of
142          * a character at a given position in a UTF8 encoded string.
143          * @param {String} str
144          * @param {Number} i position of the character
145          * @returns {Number}
146          */
147         asciiCharCodeAt: function (str, i) {
148             var c = str.charCodeAt(i);
149 
150             if (c > 255) {
151                 switch (c) {
152                 case 8364:
153                     c = 128;
154                     break;
155                 case 8218:
156                     c = 130;
157                     break;
158                 case 402:
159                     c = 131;
160                     break;
161                 case 8222:
162                     c = 132;
163                     break;
164                 case 8230:
165                     c = 133;
166                     break;
167                 case 8224:
168                     c = 134;
169                     break;
170                 case 8225:
171                     c = 135;
172                     break;
173                 case 710:
174                     c = 136;
175                     break;
176                 case 8240:
177                     c = 137;
178                     break;
179                 case 352:
180                     c = 138;
181                     break;
182                 case 8249:
183                     c = 139;
184                     break;
185                 case 338:
186                     c = 140;
187                     break;
188                 case 381:
189                     c = 142;
190                     break;
191                 case 8216:
192                     c = 145;
193                     break;
194                 case 8217:
195                     c = 146;
196                     break;
197                 case 8220:
198                     c = 147;
199                     break;
200                 case 8221:
201                     c = 148;
202                     break;
203                 case 8226:
204                     c = 149;
205                     break;
206                 case 8211:
207                     c = 150;
208                     break;
209                 case 8212:
210                     c = 151;
211                     break;
212                 case 732:
213                     c = 152;
214                     break;
215                 case 8482:
216                     c = 153;
217                     break;
218                 case 353:
219                     c = 154;
220                     break;
221                 case 8250:
222                     c = 155;
223                     break;
224                 case 339:
225                     c = 156;
226                     break;
227                 case 382:
228                     c = 158;
229                     break;
230                 case 376:
231                     c = 159;
232                     break;
233                 default:
234                     break;
235                 }
236             }
237             return c;
238         }
239     };
240 
241     return JXG.Util.UTF8;
242 });
243