Some checks failed
		
		
	
	Types tests / Test (lts/*) (push) Has been cancelled
				
			Lint / Lint (lts/*) (push) Has been cancelled
				
			CodeQL / Analyze (javascript) (push) Has been cancelled
				
			CI / Test (20) (push) Has been cancelled
				
			CI / Test (22) (push) Has been cancelled
				
			CI / Test (24) (push) Has been cancelled
				
			
		
			
				
	
	
		
			254 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			254 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* Copyright 2022 Mozilla Foundation
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 */
 | 
						|
 | 
						|
import { buildGetDocumentParams } from "./test_utils.js";
 | 
						|
import { getDocument } from "../../src/display/api.js";
 | 
						|
import { isNodeJS } from "../../src/shared/util.js";
 | 
						|
import { TextLayer } from "../../src/display/text_layer.js";
 | 
						|
 | 
						|
describe("textLayer", function () {
 | 
						|
  it("creates textLayer from ReadableStream", async function () {
 | 
						|
    if (isNodeJS) {
 | 
						|
      pending("document.createElement is not supported in Node.js.");
 | 
						|
    }
 | 
						|
    const loadingTask = getDocument(buildGetDocumentParams("basicapi.pdf"));
 | 
						|
    const pdfDocument = await loadingTask.promise;
 | 
						|
    const page = await pdfDocument.getPage(1);
 | 
						|
 | 
						|
    const textLayer = new TextLayer({
 | 
						|
      textContentSource: page.streamTextContent(),
 | 
						|
      container: document.createElement("div"),
 | 
						|
      viewport: page.getViewport({ scale: 1 }),
 | 
						|
    });
 | 
						|
    await textLayer.render();
 | 
						|
 | 
						|
    expect(textLayer.textContentItemsStr).toEqual([
 | 
						|
      "Table Of Content",
 | 
						|
      "",
 | 
						|
      "Chapter 1",
 | 
						|
      " ",
 | 
						|
      "..........................................................",
 | 
						|
      " ",
 | 
						|
      "2",
 | 
						|
      "",
 | 
						|
      "Paragraph 1.1",
 | 
						|
      " ",
 | 
						|
      "......................................................",
 | 
						|
      " ",
 | 
						|
      "3",
 | 
						|
      "",
 | 
						|
      "page 1 / 3",
 | 
						|
    ]);
 | 
						|
 | 
						|
    await loadingTask.destroy();
 | 
						|
  });
 | 
						|
 | 
						|
  it("creates textLayer from TextContent", async function () {
 | 
						|
    if (isNodeJS) {
 | 
						|
      pending("document.createElement is not supported in Node.js.");
 | 
						|
    }
 | 
						|
    const loadingTask = getDocument(buildGetDocumentParams("basicapi.pdf"));
 | 
						|
    const pdfDocument = await loadingTask.promise;
 | 
						|
    const page = await pdfDocument.getPage(1);
 | 
						|
 | 
						|
    const textLayer = new TextLayer({
 | 
						|
      textContentSource: await page.getTextContent(),
 | 
						|
      container: document.createElement("div"),
 | 
						|
      viewport: page.getViewport({ scale: 1 }),
 | 
						|
    });
 | 
						|
    await textLayer.render();
 | 
						|
 | 
						|
    expect(textLayer.textContentItemsStr).toEqual([
 | 
						|
      "Table Of Content",
 | 
						|
      "",
 | 
						|
      "Chapter 1",
 | 
						|
      " ",
 | 
						|
      "..........................................................",
 | 
						|
      " ",
 | 
						|
      "2",
 | 
						|
      "",
 | 
						|
      "Paragraph 1.1",
 | 
						|
      " ",
 | 
						|
      "......................................................",
 | 
						|
      " ",
 | 
						|
      "3",
 | 
						|
      "",
 | 
						|
      "page 1 / 3",
 | 
						|
    ]);
 | 
						|
 | 
						|
    await loadingTask.destroy();
 | 
						|
  });
 | 
						|
 | 
						|
  it("creates textLayers in parallel, from ReadableStream", async function () {
 | 
						|
    if (isNodeJS) {
 | 
						|
      pending("document.createElement is not supported in Node.js.");
 | 
						|
    }
 | 
						|
    if (typeof ReadableStream.from !== "function") {
 | 
						|
      pending("ReadableStream.from is not supported.");
 | 
						|
    }
 | 
						|
    const getTransform = container => {
 | 
						|
      const transform = [];
 | 
						|
 | 
						|
      for (const span of container.childNodes) {
 | 
						|
        const t = span.style.transform;
 | 
						|
        expect(t).toMatch(/^scaleX\([\d.]+\)$/);
 | 
						|
 | 
						|
        transform.push(t);
 | 
						|
      }
 | 
						|
      return transform;
 | 
						|
    };
 | 
						|
 | 
						|
    const loadingTask = getDocument(buildGetDocumentParams("basicapi.pdf"));
 | 
						|
    const pdfDocument = await loadingTask.promise;
 | 
						|
    const [page1, page2] = await Promise.all([
 | 
						|
      pdfDocument.getPage(1),
 | 
						|
      pdfDocument.getPage(2),
 | 
						|
    ]);
 | 
						|
 | 
						|
    // Create text-content streams with dummy content.
 | 
						|
    const items1 = [
 | 
						|
      {
 | 
						|
        str: "Chapter A",
 | 
						|
        dir: "ltr",
 | 
						|
        width: 100,
 | 
						|
        height: 20,
 | 
						|
        transform: [20, 0, 0, 20, 45, 744],
 | 
						|
        fontName: "g_d0_f1",
 | 
						|
        hasEOL: false,
 | 
						|
      },
 | 
						|
      {
 | 
						|
        str: "page 1",
 | 
						|
        dir: "ltr",
 | 
						|
        width: 50,
 | 
						|
        height: 20,
 | 
						|
        transform: [20, 0, 0, 20, 45, 744],
 | 
						|
        fontName: "g_d0_f1",
 | 
						|
        hasEOL: false,
 | 
						|
      },
 | 
						|
    ];
 | 
						|
    const items2 = [
 | 
						|
      {
 | 
						|
        str: "Chapter B",
 | 
						|
        dir: "ltr",
 | 
						|
        width: 120,
 | 
						|
        height: 10,
 | 
						|
        transform: [10, 0, 0, 10, 492, 16],
 | 
						|
        fontName: "g_d0_f2",
 | 
						|
        hasEOL: false,
 | 
						|
      },
 | 
						|
      {
 | 
						|
        str: "page 2",
 | 
						|
        dir: "ltr",
 | 
						|
        width: 60,
 | 
						|
        height: 10,
 | 
						|
        transform: [10, 0, 0, 10, 492, 16],
 | 
						|
        fontName: "g_d0_f2",
 | 
						|
        hasEOL: false,
 | 
						|
      },
 | 
						|
    ];
 | 
						|
 | 
						|
    const styles = {
 | 
						|
      g_d0_f1: {
 | 
						|
        ascent: 0.75,
 | 
						|
        descent: -0.25,
 | 
						|
        fontFamily: "serif",
 | 
						|
        vertical: false,
 | 
						|
      },
 | 
						|
      g_d0_f2: {
 | 
						|
        ascent: 0.5,
 | 
						|
        descent: -0.5,
 | 
						|
        fontFamily: "sans-serif",
 | 
						|
        vertical: false,
 | 
						|
      },
 | 
						|
    };
 | 
						|
    const lang = "en";
 | 
						|
 | 
						|
    // Render the textLayers serially, to have something to compare against.
 | 
						|
    const serialContainer1 = document.createElement("div"),
 | 
						|
      serialContainer2 = document.createElement("div");
 | 
						|
 | 
						|
    const serialTextLayer1 = new TextLayer({
 | 
						|
      textContentSource: { items: items1, styles, lang },
 | 
						|
      container: serialContainer1,
 | 
						|
      viewport: page1.getViewport({ scale: 1 }),
 | 
						|
    });
 | 
						|
    await serialTextLayer1.render();
 | 
						|
 | 
						|
    const serialTextLayer2 = new TextLayer({
 | 
						|
      textContentSource: { items: items2, styles, lang },
 | 
						|
      container: serialContainer2,
 | 
						|
      viewport: page2.getViewport({ scale: 1 }),
 | 
						|
    });
 | 
						|
    await serialTextLayer2.render();
 | 
						|
 | 
						|
    const serialTransform1 = getTransform(serialContainer1),
 | 
						|
      serialTransform2 = getTransform(serialContainer2);
 | 
						|
 | 
						|
    expect(serialTransform1.length).toEqual(2);
 | 
						|
    expect(serialTransform2.length).toEqual(2);
 | 
						|
 | 
						|
    // Reset any global textLayer-state before rendering in parallel.
 | 
						|
    TextLayer.cleanup();
 | 
						|
 | 
						|
    const container1 = document.createElement("div"),
 | 
						|
      container2 = document.createElement("div");
 | 
						|
    const waitCapability1 = Promise.withResolvers();
 | 
						|
 | 
						|
    const streamGenerator1 = (async function* () {
 | 
						|
      for (const item of items1) {
 | 
						|
        yield { items: [item], styles, lang };
 | 
						|
        await waitCapability1.promise;
 | 
						|
      }
 | 
						|
    })();
 | 
						|
    const streamGenerator2 = (async function* () {
 | 
						|
      for (const item of items2) {
 | 
						|
        yield { items: [item], styles, lang };
 | 
						|
      }
 | 
						|
    })();
 | 
						|
 | 
						|
    const textLayer1 = new TextLayer({
 | 
						|
      textContentSource: ReadableStream.from(streamGenerator1),
 | 
						|
      container: container1,
 | 
						|
      viewport: page1.getViewport({ scale: 1 }),
 | 
						|
    });
 | 
						|
    const textLayer1Promise = textLayer1.render();
 | 
						|
 | 
						|
    const textLayer2 = new TextLayer({
 | 
						|
      textContentSource: ReadableStream.from(streamGenerator2),
 | 
						|
      container: container2,
 | 
						|
      viewport: page2.getViewport({ scale: 1 }),
 | 
						|
    });
 | 
						|
    await textLayer2.render();
 | 
						|
 | 
						|
    // Ensure that the first textLayer has its rendering "paused" while
 | 
						|
    // the second textLayer renders.
 | 
						|
    waitCapability1.resolve();
 | 
						|
    await textLayer1Promise;
 | 
						|
 | 
						|
    // Sanity check to make sure that all text was parsed.
 | 
						|
    expect(textLayer1.textContentItemsStr).toEqual(["Chapter A", "page 1"]);
 | 
						|
    expect(textLayer2.textContentItemsStr).toEqual(["Chapter B", "page 2"]);
 | 
						|
 | 
						|
    // Ensure that the transforms are identical when parsing in series/parallel.
 | 
						|
    const transform1 = getTransform(container1),
 | 
						|
      transform2 = getTransform(container2);
 | 
						|
 | 
						|
    expect(transform1).toEqual(serialTransform1);
 | 
						|
    expect(transform2).toEqual(serialTransform2);
 | 
						|
 | 
						|
    await loadingTask.destroy();
 | 
						|
  });
 | 
						|
});
 |