cmap_spec.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2021 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. var _cmap = require("../../core/cmap.js");
  24. var _test_utils = require("./test_utils.js");
  25. var _api = require("../../display/api.js");
  26. var _primitives = require("../../core/primitives.js");
  27. var _stream = require("../../core/stream.js");
  28. describe("cmap", function () {
  29. let fetchBuiltInCMap;
  30. beforeAll(function (done) {
  31. const CMapReaderFactory = new _api.DefaultCMapReaderFactory({
  32. baseUrl: _test_utils.CMAP_PARAMS.cMapUrl,
  33. isCompressed: _test_utils.CMAP_PARAMS.cMapPacked
  34. });
  35. fetchBuiltInCMap = function (name) {
  36. return CMapReaderFactory.fetch({
  37. name
  38. });
  39. };
  40. done();
  41. });
  42. afterAll(function () {
  43. fetchBuiltInCMap = null;
  44. });
  45. it("parses beginbfchar", function (done) {
  46. const str = "2 beginbfchar\n" + "<03> <00>\n" + "<04> <01>\n" + "endbfchar\n";
  47. const stream = new _stream.StringStream(str);
  48. const cmapPromise = _cmap.CMapFactory.create({
  49. encoding: stream
  50. });
  51. cmapPromise.then(function (cmap) {
  52. expect(cmap.lookup(0x03)).toEqual(String.fromCharCode(0x00));
  53. expect(cmap.lookup(0x04)).toEqual(String.fromCharCode(0x01));
  54. expect(cmap.lookup(0x05)).toBeUndefined();
  55. done();
  56. }).catch(function (reason) {
  57. done.fail(reason);
  58. });
  59. });
  60. it("parses beginbfrange with range", function (done) {
  61. const str = "1 beginbfrange\n" + "<06> <0B> 0\n" + "endbfrange\n";
  62. const stream = new _stream.StringStream(str);
  63. const cmapPromise = _cmap.CMapFactory.create({
  64. encoding: stream
  65. });
  66. cmapPromise.then(function (cmap) {
  67. expect(cmap.lookup(0x05)).toBeUndefined();
  68. expect(cmap.lookup(0x06)).toEqual(String.fromCharCode(0x00));
  69. expect(cmap.lookup(0x0b)).toEqual(String.fromCharCode(0x05));
  70. expect(cmap.lookup(0x0c)).toBeUndefined();
  71. done();
  72. }).catch(function (reason) {
  73. done.fail(reason);
  74. });
  75. });
  76. it("parses beginbfrange with array", function (done) {
  77. const str = "1 beginbfrange\n" + "<0D> <12> [ 0 1 2 3 4 5 ]\n" + "endbfrange\n";
  78. const stream = new _stream.StringStream(str);
  79. const cmapPromise = _cmap.CMapFactory.create({
  80. encoding: stream
  81. });
  82. cmapPromise.then(function (cmap) {
  83. expect(cmap.lookup(0x0c)).toBeUndefined();
  84. expect(cmap.lookup(0x0d)).toEqual(0x00);
  85. expect(cmap.lookup(0x12)).toEqual(0x05);
  86. expect(cmap.lookup(0x13)).toBeUndefined();
  87. done();
  88. }).catch(function (reason) {
  89. done.fail(reason);
  90. });
  91. });
  92. it("parses begincidchar", function (done) {
  93. const str = "1 begincidchar\n" + "<14> 0\n" + "endcidchar\n";
  94. const stream = new _stream.StringStream(str);
  95. const cmapPromise = _cmap.CMapFactory.create({
  96. encoding: stream
  97. });
  98. cmapPromise.then(function (cmap) {
  99. expect(cmap.lookup(0x14)).toEqual(0x00);
  100. expect(cmap.lookup(0x15)).toBeUndefined();
  101. done();
  102. }).catch(function (reason) {
  103. done.fail(reason);
  104. });
  105. });
  106. it("parses begincidrange", function (done) {
  107. const str = "1 begincidrange\n" + "<0016> <001B> 0\n" + "endcidrange\n";
  108. const stream = new _stream.StringStream(str);
  109. const cmapPromise = _cmap.CMapFactory.create({
  110. encoding: stream
  111. });
  112. cmapPromise.then(function (cmap) {
  113. expect(cmap.lookup(0x15)).toBeUndefined();
  114. expect(cmap.lookup(0x16)).toEqual(0x00);
  115. expect(cmap.lookup(0x1b)).toEqual(0x05);
  116. expect(cmap.lookup(0x1c)).toBeUndefined();
  117. done();
  118. }).catch(function (reason) {
  119. done.fail(reason);
  120. });
  121. });
  122. it("decodes codespace ranges", function (done) {
  123. const str = "1 begincodespacerange\n" + "<01> <02>\n" + "<00000003> <00000004>\n" + "endcodespacerange\n";
  124. const stream = new _stream.StringStream(str);
  125. const cmapPromise = _cmap.CMapFactory.create({
  126. encoding: stream
  127. });
  128. cmapPromise.then(function (cmap) {
  129. const c = {};
  130. cmap.readCharCode(String.fromCharCode(1), 0, c);
  131. expect(c.charcode).toEqual(1);
  132. expect(c.length).toEqual(1);
  133. cmap.readCharCode(String.fromCharCode(0, 0, 0, 3), 0, c);
  134. expect(c.charcode).toEqual(3);
  135. expect(c.length).toEqual(4);
  136. done();
  137. }).catch(function (reason) {
  138. done.fail(reason);
  139. });
  140. });
  141. it("decodes 4 byte codespace ranges", function (done) {
  142. const str = "1 begincodespacerange\n" + "<8EA1A1A1> <8EA1FEFE>\n" + "endcodespacerange\n";
  143. const stream = new _stream.StringStream(str);
  144. const cmapPromise = _cmap.CMapFactory.create({
  145. encoding: stream
  146. });
  147. cmapPromise.then(function (cmap) {
  148. const c = {};
  149. cmap.readCharCode(String.fromCharCode(0x8e, 0xa1, 0xa1, 0xa1), 0, c);
  150. expect(c.charcode).toEqual(0x8ea1a1a1);
  151. expect(c.length).toEqual(4);
  152. done();
  153. }).catch(function (reason) {
  154. done.fail(reason);
  155. });
  156. });
  157. it("read usecmap", function (done) {
  158. const str = "/Adobe-Japan1-1 usecmap\n";
  159. const stream = new _stream.StringStream(str);
  160. const cmapPromise = _cmap.CMapFactory.create({
  161. encoding: stream,
  162. fetchBuiltInCMap,
  163. useCMap: null
  164. });
  165. cmapPromise.then(function (cmap) {
  166. expect(cmap instanceof _cmap.CMap).toEqual(true);
  167. expect(cmap.useCMap).not.toBeNull();
  168. expect(cmap.builtInCMap).toBeFalsy();
  169. expect(cmap.length).toEqual(0x20a7);
  170. expect(cmap.isIdentityCMap).toEqual(false);
  171. done();
  172. }).catch(function (reason) {
  173. done.fail(reason);
  174. });
  175. });
  176. it("parses cmapname", function (done) {
  177. const str = "/CMapName /Identity-H def\n";
  178. const stream = new _stream.StringStream(str);
  179. const cmapPromise = _cmap.CMapFactory.create({
  180. encoding: stream
  181. });
  182. cmapPromise.then(function (cmap) {
  183. expect(cmap.name).toEqual("Identity-H");
  184. done();
  185. }).catch(function (reason) {
  186. done.fail(reason);
  187. });
  188. });
  189. it("parses wmode", function (done) {
  190. const str = "/WMode 1 def\n";
  191. const stream = new _stream.StringStream(str);
  192. const cmapPromise = _cmap.CMapFactory.create({
  193. encoding: stream
  194. });
  195. cmapPromise.then(function (cmap) {
  196. expect(cmap.vertical).toEqual(true);
  197. done();
  198. }).catch(function (reason) {
  199. done.fail(reason);
  200. });
  201. });
  202. it("loads built in cmap", function (done) {
  203. const cmapPromise = _cmap.CMapFactory.create({
  204. encoding: _primitives.Name.get("Adobe-Japan1-1"),
  205. fetchBuiltInCMap,
  206. useCMap: null
  207. });
  208. cmapPromise.then(function (cmap) {
  209. expect(cmap instanceof _cmap.CMap).toEqual(true);
  210. expect(cmap.useCMap).toBeNull();
  211. expect(cmap.builtInCMap).toBeTruthy();
  212. expect(cmap.length).toEqual(0x20a7);
  213. expect(cmap.isIdentityCMap).toEqual(false);
  214. done();
  215. }).catch(function (reason) {
  216. done.fail(reason);
  217. });
  218. });
  219. it("loads built in identity cmap", function (done) {
  220. const cmapPromise = _cmap.CMapFactory.create({
  221. encoding: _primitives.Name.get("Identity-H"),
  222. fetchBuiltInCMap,
  223. useCMap: null
  224. });
  225. cmapPromise.then(function (cmap) {
  226. expect(cmap instanceof _cmap.IdentityCMap).toEqual(true);
  227. expect(cmap.vertical).toEqual(false);
  228. expect(cmap.length).toEqual(0x10000);
  229. expect(function () {
  230. return cmap.isIdentityCMap;
  231. }).toThrow(new Error("should not access .isIdentityCMap"));
  232. done();
  233. }).catch(function (reason) {
  234. done.fail(reason);
  235. });
  236. });
  237. it("attempts to load a non-existent built-in CMap", function (done) {
  238. const cmapPromise = _cmap.CMapFactory.create({
  239. encoding: _primitives.Name.get("null"),
  240. fetchBuiltInCMap,
  241. useCMap: null
  242. });
  243. cmapPromise.then(function () {
  244. done.fail("No CMap should be loaded");
  245. }, function (reason) {
  246. expect(reason instanceof Error).toEqual(true);
  247. expect(reason.message).toEqual("Unknown CMap name: null");
  248. done();
  249. });
  250. });
  251. it("attempts to load a built-in CMap without the necessary API parameters", function (done) {
  252. function tmpFetchBuiltInCMap(name) {
  253. const CMapReaderFactory = new _api.DefaultCMapReaderFactory({});
  254. return CMapReaderFactory.fetch({
  255. name
  256. });
  257. }
  258. const cmapPromise = _cmap.CMapFactory.create({
  259. encoding: _primitives.Name.get("Adobe-Japan1-1"),
  260. fetchBuiltInCMap: tmpFetchBuiltInCMap,
  261. useCMap: null
  262. });
  263. cmapPromise.then(function () {
  264. done.fail("No CMap should be loaded");
  265. }, function (reason) {
  266. expect(reason instanceof Error).toEqual(true);
  267. expect(reason.message).toEqual('The CMap "baseUrl" parameter must be specified, ensure that ' + 'the "cMapUrl" and "cMapPacked" API parameters are provided.');
  268. done();
  269. });
  270. });
  271. it("attempts to load a built-in CMap with inconsistent API parameters", function (done) {
  272. function tmpFetchBuiltInCMap(name) {
  273. const CMapReaderFactory = new _api.DefaultCMapReaderFactory({
  274. baseUrl: _test_utils.CMAP_PARAMS.cMapUrl,
  275. isCompressed: false
  276. });
  277. return CMapReaderFactory.fetch({
  278. name
  279. });
  280. }
  281. const cmapPromise = _cmap.CMapFactory.create({
  282. encoding: _primitives.Name.get("Adobe-Japan1-1"),
  283. fetchBuiltInCMap: tmpFetchBuiltInCMap,
  284. useCMap: null
  285. });
  286. cmapPromise.then(function () {
  287. done.fail("No CMap should be loaded");
  288. }, function (reason) {
  289. expect(reason instanceof Error).toEqual(true);
  290. const message = reason.message;
  291. expect(message.startsWith("Unable to load CMap at: ")).toEqual(true);
  292. expect(message.endsWith("/external/bcmaps/Adobe-Japan1-1")).toEqual(true);
  293. done();
  294. });
  295. });
  296. });