custom_spec.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* Copyright 2017 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. import { DefaultCanvasFactory, getDocument } from "../../src/display/api.js";
  16. import { buildGetDocumentParams } from "./test_utils.js";
  17. function getTopLeftPixel(canvasContext) {
  18. const imgData = canvasContext.getImageData(0, 0, 1, 1);
  19. return {
  20. r: imgData.data[0],
  21. g: imgData.data[1],
  22. b: imgData.data[2],
  23. a: imgData.data[3],
  24. };
  25. }
  26. describe("custom canvas rendering", function () {
  27. const transparentGetDocumentParams =
  28. buildGetDocumentParams("transparent.pdf");
  29. let CanvasFactory;
  30. let loadingTask;
  31. let page;
  32. beforeAll(async function () {
  33. CanvasFactory = new DefaultCanvasFactory();
  34. loadingTask = getDocument(transparentGetDocumentParams);
  35. const doc = await loadingTask.promise;
  36. const data = await doc.getPage(1);
  37. page = data;
  38. });
  39. afterAll(async function () {
  40. CanvasFactory = null;
  41. page = null;
  42. await loadingTask.destroy();
  43. });
  44. it("renders to canvas with a default white background", async function () {
  45. const viewport = page.getViewport({ scale: 1 });
  46. const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  47. const renderTask = page.render({
  48. canvasContext: canvasAndCtx.context,
  49. viewport,
  50. });
  51. await renderTask.promise;
  52. expect(getTopLeftPixel(canvasAndCtx.context)).toEqual({
  53. r: 255,
  54. g: 255,
  55. b: 255,
  56. a: 255,
  57. });
  58. CanvasFactory.destroy(canvasAndCtx);
  59. });
  60. it("renders to canvas with a custom background", async function () {
  61. const viewport = page.getViewport({ scale: 1 });
  62. const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  63. const renderTask = page.render({
  64. canvasContext: canvasAndCtx.context,
  65. viewport,
  66. background: "rgba(255,0,0,1.0)",
  67. });
  68. await renderTask.promise;
  69. expect(getTopLeftPixel(canvasAndCtx.context)).toEqual({
  70. r: 255,
  71. g: 0,
  72. b: 0,
  73. a: 255,
  74. });
  75. CanvasFactory.destroy(canvasAndCtx);
  76. });
  77. });
  78. describe("custom ownerDocument", function () {
  79. const FontFace = globalThis.FontFace;
  80. const checkFont = font => /g_d\d+_f1/.test(font.family);
  81. const checkFontFaceRule = rule =>
  82. /^@font-face {font-family:"g_d\d+_f1";src:/.test(rule);
  83. beforeEach(() => {
  84. globalThis.FontFace = function MockFontFace(name) {
  85. this.family = name;
  86. };
  87. });
  88. afterEach(() => {
  89. globalThis.FontFace = FontFace;
  90. });
  91. function getMocks() {
  92. const elements = [];
  93. const createElement = name => {
  94. let element =
  95. typeof document !== "undefined" && document.createElement(name);
  96. if (name === "style") {
  97. element = {
  98. tagName: name,
  99. sheet: {
  100. cssRules: [],
  101. insertRule(rule) {
  102. this.cssRules.push(rule);
  103. },
  104. },
  105. };
  106. Object.assign(element, {
  107. remove() {
  108. this.remove.called = true;
  109. },
  110. });
  111. }
  112. elements.push(element);
  113. return element;
  114. };
  115. const ownerDocument = {
  116. fonts: new Set(),
  117. createElement,
  118. documentElement: {
  119. getElementsByTagName: () => [{ append: () => {} }],
  120. },
  121. };
  122. const CanvasFactory = new DefaultCanvasFactory({ ownerDocument });
  123. return {
  124. elements,
  125. ownerDocument,
  126. CanvasFactory,
  127. };
  128. }
  129. it("should use given document for loading fonts (with Font Loading API)", async function () {
  130. const { ownerDocument, elements, CanvasFactory } = getMocks();
  131. const getDocumentParams = buildGetDocumentParams(
  132. "TrueType_without_cmap.pdf",
  133. {
  134. disableFontFace: false,
  135. ownerDocument,
  136. }
  137. );
  138. const loadingTask = getDocument(getDocumentParams);
  139. const doc = await loadingTask.promise;
  140. const page = await doc.getPage(1);
  141. const viewport = page.getViewport({ scale: 1 });
  142. const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  143. await page.render({
  144. canvasContext: canvasAndCtx.context,
  145. viewport,
  146. }).promise;
  147. const style = elements.find(element => element.tagName === "style");
  148. expect(style).toBeFalsy();
  149. expect(ownerDocument.fonts.size).toBeGreaterThanOrEqual(1);
  150. expect(Array.from(ownerDocument.fonts).find(checkFont)).toBeTruthy();
  151. await loadingTask.destroy();
  152. CanvasFactory.destroy(canvasAndCtx);
  153. expect(ownerDocument.fonts.size).toBe(0);
  154. });
  155. it("should use given document for loading fonts (with CSS rules)", async function () {
  156. const { ownerDocument, elements, CanvasFactory } = getMocks();
  157. ownerDocument.fonts = null;
  158. const getDocumentParams = buildGetDocumentParams(
  159. "TrueType_without_cmap.pdf",
  160. {
  161. disableFontFace: false,
  162. ownerDocument,
  163. }
  164. );
  165. const loadingTask = getDocument(getDocumentParams);
  166. const doc = await loadingTask.promise;
  167. const page = await doc.getPage(1);
  168. const viewport = page.getViewport({ scale: 1 });
  169. const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  170. await page.render({
  171. canvasContext: canvasAndCtx.context,
  172. viewport,
  173. }).promise;
  174. const style = elements.find(element => element.tagName === "style");
  175. expect(style.sheet.cssRules.length).toBeGreaterThanOrEqual(1);
  176. expect(style.sheet.cssRules.find(checkFontFaceRule)).toBeTruthy();
  177. await loadingTask.destroy();
  178. CanvasFactory.destroy(canvasAndCtx);
  179. expect(style.remove.called).toBe(true);
  180. });
  181. });