hyphenEngine.asm.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /**
  2. * @license hyphenEngine.asm.js 3.1.1 - client side hyphenation for webbrowsers
  3. * ©2019 Mathias Nater, Zürich (mathiasnater at gmail dot com)
  4. * https://github.com/mnater/Hyphenopoly
  5. *
  6. * Released under the MIT license
  7. * http://mnater.github.io/Hyphenopoly/LICENSE
  8. */
  9. /* eslint-disable */
  10. function asmHyphenEngine(std, x, heap) {
  11. "use asm";
  12. var ui8 = new std.Uint8Array(heap);
  13. var ui16 = new std.Uint16Array(heap);
  14. var i32 = new std.Int32Array(heap);
  15. var imul = std.Math.imul;
  16. var to = x.to | 0;
  17. var po = x.po | 0;
  18. var pl = x.pl | 0;
  19. var vs = x.vs | 0;
  20. var pt = x.pt | 0;
  21. var wo = x.wo | 0;
  22. var tw = x.tw | 0;
  23. var hp = x.hp | 0;
  24. var hw = x.hw | 0;
  25. function hashCharCode(cc) {
  26. //maps BMP-charCode (16bit) to 8bit adresses
  27. //{0, 1, 2, ..., 2^16 - 1} -> {0, 1, 2, ..., 2^8 - 1}
  28. //collisions will occur!
  29. cc = cc | 0;
  30. var h = 0;
  31. h = imul(cc, 40503); // 2^16 (-1 + sqrt(5)) / 2 = 40’503.475...
  32. h = h & 255; //mask 8bits
  33. return h << 1;
  34. }
  35. function pushToTranslateMap(cc, id) {
  36. cc = cc | 0;
  37. id = id | 0;
  38. var addr = 0;
  39. addr = hashCharCode(cc | 0) | 0;
  40. while ((ui16[addr >> 1] | 0) != 0) {
  41. addr = (addr + 2) | 0;
  42. }
  43. ui16[addr >> 1] = cc;
  44. ui8[((addr >> 1) + 512) | 0] = id;
  45. }
  46. function pullFromTranslateMap(cc) {
  47. cc = cc | 0;
  48. var addr = 0;
  49. if ((cc | 0) != 0) {
  50. addr = hashCharCode(cc) | 0;
  51. while ((ui16[addr >> 1] | 0) != (cc | 0)) {
  52. addr = (addr + 2) | 0;
  53. if ((addr | 0) >= 512) {
  54. return 255;
  55. }
  56. }
  57. return ui8[((addr >> 1) + 512) | 0] | 0;
  58. }
  59. return 255;
  60. }
  61. function createTranslateMap() {
  62. var i = 0;
  63. var k = 0;
  64. var first = 0;
  65. var second = 0;
  66. var secondInt = 0;
  67. var alphabetCount = 0;
  68. i = (to + 2) | 0;
  69. k = 12 | 0;
  70. while ((i | 0) < (po | 0)) {
  71. first = ui16[i >> 1] | 0;
  72. second = ui16[(i + 2) >> 1] | 0;
  73. secondInt = pullFromTranslateMap(second) | 0;
  74. if ((secondInt | 0) == 255) {
  75. //there's no such char yet in the TranslateMap
  76. pushToTranslateMap(first, k);
  77. if ((second | 0) != 0) {
  78. //set upperCase representation
  79. pushToTranslateMap(second, k);
  80. }
  81. k = (k + 1) | 0;
  82. } else {
  83. //char is already in TranslateMap -> SUBSTITUTION
  84. pushToTranslateMap(first, secondInt);
  85. }
  86. //add to alphabet
  87. ui16[(768 + (alphabetCount << 1)) >> 1] = first;
  88. alphabetCount = (alphabetCount + 1) | 0;
  89. i = (i + 4) | 0;
  90. }
  91. return alphabetCount | 0;
  92. }
  93. function convert() {
  94. var i = 0;
  95. var charAti = 0;
  96. var plen = 0;
  97. var count = 0;
  98. var nextRowStart = 0;
  99. var trieNextEmptyRow = 0;
  100. var rowStart = 0;
  101. var rowOffset = 0;
  102. var valueStoreStartIndex = 0;
  103. var valueStoreCurrentIdx = 0;
  104. var valueStorePrevIdx = 0;
  105. var alphabetlength = 0;
  106. var first = 0;
  107. var second = 0;
  108. var trieRowLength = 0;
  109. trieRowLength = ((ui16[to >> 1] << 1) + 1) << 2;
  110. nextRowStart = pt;
  111. trieNextEmptyRow = pt;
  112. rowStart = pt;
  113. valueStoreStartIndex = vs;
  114. valueStoreCurrentIdx = vs;
  115. valueStorePrevIdx = vs;
  116. alphabetlength = createTranslateMap() | 0;
  117. i = po | 0;
  118. while ((i | 0) < (po + pl | 0)) {
  119. if ((ui8[i | 0] | 0) == 0) {
  120. plen = ui8[(i + 1) | 0] | 0;
  121. i = (i + 2) | 0;
  122. } else {
  123. if ((ui8[i | 0] | 0) == 255) {
  124. first = ui8[(i + 1) | 0] | 0;
  125. second = ui8[(i + 2) | 0] | 0;
  126. i = (i + 3) | 0;
  127. }
  128. while ((count | 0) < (plen | 0)) {
  129. if ((count | 0) == 0) {
  130. charAti = first;
  131. } else if ((count | 0) == 1) {
  132. charAti = second;
  133. } else {
  134. charAti = ui8[i | 0] | 0;
  135. i = (i + 1) | 0;
  136. }
  137. if ((charAti | 0) > 11) {
  138. valueStoreCurrentIdx = (valueStoreCurrentIdx + 1) | 0;
  139. if ((nextRowStart | 0) == -1) {
  140. //start a new row
  141. trieNextEmptyRow = trieNextEmptyRow + trieRowLength | 0;
  142. nextRowStart = trieNextEmptyRow;
  143. i32[(rowStart + rowOffset) >> 2] = nextRowStart;
  144. }
  145. rowOffset = ((charAti - 12) | 0) << 3;
  146. rowStart = nextRowStart;
  147. nextRowStart = i32[(rowStart + rowOffset) >> 2] | 0;
  148. if ((nextRowStart | 0) == 0) {
  149. i32[(rowStart + rowOffset) >> 2] = -1;
  150. nextRowStart = -1;
  151. }
  152. } else {
  153. ui8[valueStoreCurrentIdx | 0] = charAti | 0;
  154. valueStorePrevIdx = valueStoreCurrentIdx;
  155. }
  156. count = (count + 1) | 0;
  157. }
  158. //terminate valueStore and save link to valueStoreStartIndex
  159. ui8[(valueStorePrevIdx + 1) | 0] = 255; //mark end of pattern
  160. i32[(rowStart + rowOffset + 4) >> 2] = valueStoreStartIndex | 0;
  161. //reset indizes
  162. valueStoreStartIndex = (valueStorePrevIdx + 2) | 0;
  163. valueStoreCurrentIdx = valueStoreStartIndex;
  164. count = 0;
  165. rowStart = pt;
  166. nextRowStart = pt;
  167. }
  168. }
  169. return alphabetlength | 0;
  170. }
  171. function hyphenate(lm, rm) {
  172. lm = lm | 0;
  173. rm = rm | 0;
  174. var patternStartPos = 0;
  175. var wordLength = 0;
  176. var charOffset = 0;
  177. var cc = 0;
  178. var row = 0;
  179. var rowOffset2 = 0;
  180. var link = 0;
  181. var value = 0;
  182. var hyphenPointsCount = 0;
  183. var hyphenPoint = 0;
  184. var hpPos = 0;
  185. var translatedChar = 0;
  186. //translate UTF16 word to internal ints and clear hpPos-Array
  187. cc = ui16[wo >> 1] | 0;
  188. while ((cc | 0) != 0) {
  189. ui8[(hp + charOffset) | 0] = 0;
  190. translatedChar = pullFromTranslateMap(cc | 0) | 0;
  191. if ((translatedChar | 0) == 255) {
  192. return 0;
  193. }
  194. translatedChar = (translatedChar - 12) | 0;
  195. ui8[(tw + charOffset) | 0] = translatedChar | 0;
  196. charOffset = (charOffset + 1) | 0;
  197. cc = ui16[(wo + (charOffset << 1)) >> 1] | 0;
  198. }
  199. ui8[(hp + charOffset) | 0] = 0;
  200. //find patterns and collect hyphenPoints
  201. wordLength = charOffset;
  202. while ((patternStartPos | 0) < (wordLength | 0)) {
  203. row = pt;
  204. charOffset = patternStartPos | 0;
  205. while ((charOffset | 0) < (wordLength | 0)) {
  206. rowOffset2 = ui8[(tw + charOffset) | 0] << 3;
  207. link = i32[(row + rowOffset2) >> 2] | 0;
  208. value = i32[(row + rowOffset2 + 4) >> 2] | 0;
  209. if ((value | 0) > 0) {
  210. hyphenPointsCount = 0;
  211. hyphenPoint = ui8[value | 0] | 0;
  212. while ((hyphenPoint | 0) != 255) {
  213. hpPos = (hp + patternStartPos + hyphenPointsCount) | 0;
  214. if ((hyphenPoint | 0) > (ui8[hpPos | 0] | 0)) {
  215. ui8[hpPos | 0] = hyphenPoint | 0;
  216. }
  217. hyphenPointsCount = (hyphenPointsCount + 1) | 0;
  218. hyphenPoint = ui8[(value + hyphenPointsCount) | 0] | 0;
  219. }
  220. }
  221. if ((link | 0) > 0) {
  222. row = link | 0;
  223. } else {
  224. break;
  225. }
  226. charOffset = (charOffset + 1) | 0;
  227. }
  228. patternStartPos = (patternStartPos + 1) | 0;
  229. }
  230. //get chars of original word and insert hyphenPoints
  231. charOffset = 1;
  232. hyphenPointsCount = 0;
  233. wordLength = (wordLength - 2) | 0;
  234. while ((charOffset | 0) <= (wordLength | 0)) {
  235. ui16[(hw + (charOffset << 1) + hyphenPointsCount) >> 1] = ui16[(wo + (charOffset << 1)) >> 1] | 0;
  236. if (
  237. (((charOffset | 0) >= (lm | 0)) | 0) &
  238. (((charOffset | 0) <= ((wordLength - rm) | 0)) | 0)
  239. ) {
  240. if (ui8[(hp + charOffset + 1) | 0] & 1) {
  241. ui16[(hw + (charOffset << 1) + hyphenPointsCount + 2) >> 1] = 173;
  242. hyphenPointsCount = (hyphenPointsCount + 2) | 0;
  243. }
  244. }
  245. charOffset = (charOffset + 1) | 0;
  246. }
  247. ui16[hw >> 1] = (wordLength + (hyphenPointsCount >> 1)) | 0;
  248. return 1;
  249. }
  250. return {
  251. convert: convert,
  252. hyphenate: hyphenate
  253. };
  254. }