hyphenEngine.asm.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /**
  2. * @license hyphenEngine.asm.js 3.4.0 - 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. addr = hashCharCode(cc) | 0;
  50. while ((ui16[addr >> 1] | 0) != (cc | 0)) {
  51. addr = (addr + 2) | 0;
  52. if ((addr | 0) >= 512) {
  53. return 255;
  54. }
  55. }
  56. return ui8[((addr >> 1) + 512) | 0] | 0;
  57. }
  58. function createTranslateMap() {
  59. var i = 0;
  60. var k = 0;
  61. var first = 0;
  62. var second = 0;
  63. var secondInt = 0;
  64. var alphabetCount = 0;
  65. i = (to + 2) | 0;
  66. while ((i | 0) < (po | 0)) {
  67. first = ui16[i >> 1] | 0;
  68. second = ui16[(i + 2) >> 1] | 0;
  69. if ((second | 0) == 0) {
  70. secondInt = 255;
  71. } else {
  72. secondInt = pullFromTranslateMap(second) | 0;
  73. }
  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) == 0) {
  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. } else {
  149. ui8[valueStoreCurrentIdx | 0] = charAti | 0;
  150. valueStorePrevIdx = valueStoreCurrentIdx;
  151. }
  152. count = (count + 1) | 0;
  153. }
  154. //terminate valueStore and save link to valueStoreStartIndex
  155. ui8[(valueStorePrevIdx + 1) | 0] = 255; //mark end of pattern
  156. i32[(rowStart + rowOffset + 4) >> 2] = valueStoreStartIndex | 0;
  157. //reset indizes
  158. valueStoreStartIndex = (valueStorePrevIdx + 2) | 0;
  159. valueStoreCurrentIdx = valueStoreStartIndex;
  160. count = 0;
  161. rowStart = pt;
  162. nextRowStart = pt;
  163. }
  164. }
  165. return alphabetlength | 0;
  166. }
  167. function hyphenate(lm, rm, hc) {
  168. lm = lm | 0;
  169. rm = rm | 0;
  170. hc = hc | 0;
  171. var patternStartPos = 0;
  172. var wordLength = 0;
  173. var charOffset = 0;
  174. var cc = 0;
  175. var row = 0;
  176. var rowOffset2 = 0;
  177. var link = 0;
  178. var value = 0;
  179. var hyphenPointsCount = 0;
  180. var hyphenPoint = 0;
  181. var hpPos = 0;
  182. var translatedChar = 0;
  183. //translate UTF16 word to internal ints and clear hpPos-Array
  184. cc = ui16[wo >> 1] | 0;
  185. while ((cc | 0) != 0) {
  186. translatedChar = pullFromTranslateMap(cc | 0) | 0;
  187. if ((translatedChar | 0) == 255) {
  188. return 0;
  189. }
  190. ui8[(tw + charOffset) | 0] = translatedChar | 0;
  191. charOffset = (charOffset + 1) | 0;
  192. ui8[(hp + charOffset) | 0] = 0;
  193. cc = ui16[(wo + (charOffset << 1)) >> 1] | 0;
  194. }
  195. //find patterns and collect hyphenPoints
  196. wordLength = charOffset;
  197. while ((patternStartPos | 0) < (wordLength | 0)) {
  198. row = pt;
  199. charOffset = patternStartPos | 0;
  200. while ((charOffset | 0) < (wordLength | 0)) {
  201. rowOffset2 = ui8[(tw + charOffset) | 0] << 3;
  202. link = i32[(row + rowOffset2) >> 2] | 0;
  203. value = i32[(row + rowOffset2 + 4) >> 2] | 0;
  204. if ((value | 0) > 0) {
  205. hyphenPointsCount = 0;
  206. hyphenPoint = ui8[value | 0] | 0;
  207. while ((hyphenPoint | 0) != 255) {
  208. hpPos = (hp + patternStartPos + hyphenPointsCount) | 0;
  209. if ((hyphenPoint | 0) > (ui8[hpPos | 0] | 0)) {
  210. ui8[hpPos | 0] = hyphenPoint | 0;
  211. }
  212. hyphenPointsCount = (hyphenPointsCount + 1) | 0;
  213. hyphenPoint = ui8[(value + hyphenPointsCount) | 0] | 0;
  214. }
  215. }
  216. if ((link | 0) > 0) {
  217. row = link | 0;
  218. } else {
  219. break;
  220. }
  221. charOffset = (charOffset + 1) | 0;
  222. }
  223. patternStartPos = (patternStartPos + 1) | 0;
  224. }
  225. //get chars of original word and insert hyphenPoints
  226. charOffset = 1;
  227. hyphenPointsCount = 0;
  228. wordLength = (wordLength - 2) | 0;
  229. while ((charOffset | 0) <= (wordLength | 0)) {
  230. ui16[(hw + (charOffset << 1) + hyphenPointsCount) >> 1] = ui16[(wo + (charOffset << 1)) >> 1] | 0;
  231. if (
  232. (((charOffset | 0) >= (lm | 0)) | 0) &
  233. (((charOffset | 0) <= ((wordLength - rm) | 0)) | 0)
  234. ) {
  235. if (ui8[(hp + charOffset + 1) | 0] & 1) {
  236. hyphenPointsCount = (hyphenPointsCount + 2) | 0;
  237. ui16[(hw + (charOffset << 1) + hyphenPointsCount) >> 1] = hc;
  238. }
  239. }
  240. charOffset = (charOffset + 1) | 0;
  241. }
  242. ui16[hw >> 1] = (wordLength + (hyphenPointsCount >> 1)) | 0;
  243. return 1;
  244. }
  245. return {
  246. convert: convert,
  247. hyphenate: hyphenate
  248. };
  249. }