mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-04-22 21:24:04 +02:00
Re-factor the FontRendererFactory class, and related code, to use DataViews when reading data
This commit is contained in:
parent
88abcefea0
commit
a24d86e1cf
@ -25,22 +25,14 @@ import {
|
||||
Util,
|
||||
warn,
|
||||
} from "../shared/util.js";
|
||||
import {
|
||||
isNumberArray,
|
||||
readInt16,
|
||||
readInt8,
|
||||
readUint16,
|
||||
readUint32,
|
||||
} from "./core_utils.js";
|
||||
import { CFFParser } from "./cff_parser.js";
|
||||
import { getGlyphsUnicode } from "./glyphlist.js";
|
||||
import { isNumberArray } from "./core_utils.js";
|
||||
import { StandardEncoding } from "./encodings.js";
|
||||
import { Stream } from "./stream.js";
|
||||
|
||||
// TODO: use DataView and its methods.
|
||||
|
||||
function getFloat214(data, offset) {
|
||||
return readInt16(data, offset) / 16384;
|
||||
function getFloat214(view, offset) {
|
||||
return view.getInt16(offset) / 16384;
|
||||
}
|
||||
|
||||
function getSubroutineBias(subrs) {
|
||||
@ -55,49 +47,50 @@ function getSubroutineBias(subrs) {
|
||||
}
|
||||
|
||||
function parseCmap(data, start, end) {
|
||||
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
||||
const offset =
|
||||
readUint16(data, start + 2) === 1
|
||||
? readUint32(data, start + 8)
|
||||
: readUint32(data, start + 16);
|
||||
const format = readUint16(data, start + offset);
|
||||
view.getUint16(start + 2) === 1
|
||||
? view.getUint32(start + 8)
|
||||
: view.getUint32(start + 16);
|
||||
const format = view.getUint16(start + offset);
|
||||
let ranges, p, i;
|
||||
if (format === 4) {
|
||||
readUint16(data, start + offset + 2); // length
|
||||
const segCount = readUint16(data, start + offset + 6) >> 1;
|
||||
// Skip length, at `start + offset + 2`.
|
||||
const segCount = view.getUint16(start + offset + 6) >> 1;
|
||||
p = start + offset + 14;
|
||||
ranges = [];
|
||||
for (i = 0; i < segCount; i++, p += 2) {
|
||||
ranges[i] = { end: readUint16(data, p) };
|
||||
ranges[i] = { end: view.getUint16(p) };
|
||||
}
|
||||
p += 2;
|
||||
for (i = 0; i < segCount; i++, p += 2) {
|
||||
ranges[i].start = readUint16(data, p);
|
||||
ranges[i].start = view.getUint16(p);
|
||||
}
|
||||
for (i = 0; i < segCount; i++, p += 2) {
|
||||
ranges[i].idDelta = readUint16(data, p);
|
||||
ranges[i].idDelta = view.getUint16(p);
|
||||
}
|
||||
for (i = 0; i < segCount; i++, p += 2) {
|
||||
let idOffset = readUint16(data, p);
|
||||
let idOffset = view.getUint16(p);
|
||||
if (idOffset === 0) {
|
||||
continue;
|
||||
}
|
||||
ranges[i].ids = [];
|
||||
for (let j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) {
|
||||
ranges[i].ids[j] = readUint16(data, p + idOffset);
|
||||
ranges[i].ids[j] = view.getUint16(p + idOffset);
|
||||
idOffset += 2;
|
||||
}
|
||||
}
|
||||
return ranges;
|
||||
} else if (format === 12) {
|
||||
const groups = readUint32(data, start + offset + 12);
|
||||
const groups = view.getUint32(start + offset + 12);
|
||||
p = start + offset + 16;
|
||||
ranges = [];
|
||||
for (i = 0; i < groups; i++) {
|
||||
start = readUint32(data, p);
|
||||
start = view.getUint32(p);
|
||||
ranges.push({
|
||||
start,
|
||||
end: readUint32(data, p + 4),
|
||||
idDelta: readUint32(data, p + 8) - start,
|
||||
end: view.getUint32(p + 4),
|
||||
idDelta: view.getUint32(p + 8) - start,
|
||||
});
|
||||
p += 12;
|
||||
}
|
||||
@ -125,18 +118,19 @@ function parseCff(data, start, end, seacAnalysisEnabled) {
|
||||
}
|
||||
|
||||
function parseGlyfTable(glyf, loca, isGlyphLocationsLong) {
|
||||
const view = new DataView(loca.buffer, loca.byteOffset, loca.byteLength);
|
||||
let itemSize, itemDecode;
|
||||
if (isGlyphLocationsLong) {
|
||||
itemSize = 4;
|
||||
itemDecode = readUint32;
|
||||
itemDecode = (dv, offset) => dv.getUint32(offset);
|
||||
} else {
|
||||
itemSize = 2;
|
||||
itemDecode = (data, offset) => 2 * readUint16(data, offset);
|
||||
itemDecode = (dv, offset) => 2 * dv.getUint16(offset);
|
||||
}
|
||||
const glyphs = [];
|
||||
let startOffset = itemDecode(loca, 0);
|
||||
let startOffset = itemDecode(view, 0);
|
||||
for (let j = itemSize; j < loca.length; j += itemSize) {
|
||||
const endOffset = itemDecode(loca, j);
|
||||
const endOffset = itemDecode(view, j);
|
||||
glyphs.push(glyf.subarray(startOffset, endOffset));
|
||||
startOffset = endOffset;
|
||||
}
|
||||
@ -173,8 +167,8 @@ function compileGlyf(code, cmds, font, visitedGlyphs = new Set()) {
|
||||
warn("compileGlyf: skipping recursive composite glyph reference.");
|
||||
return;
|
||||
}
|
||||
|
||||
visitedGlyphs.add(code);
|
||||
|
||||
function moveTo(x, y) {
|
||||
if (firstPoint) {
|
||||
// Close the current subpath in adding a straight line to the first point.
|
||||
@ -190,8 +184,9 @@ function compileGlyf(code, cmds, font, visitedGlyphs = new Set()) {
|
||||
cmds.add(DrawOPS.quadraticCurveTo, [xa, ya, x, y]);
|
||||
}
|
||||
|
||||
const view = new DataView(code.buffer, code.byteOffset, code.byteLength);
|
||||
let i = 0;
|
||||
const numberOfContours = readInt16(code, i);
|
||||
const numberOfContours = view.getInt16(i);
|
||||
let flags;
|
||||
let firstPoint = null;
|
||||
let x = 0,
|
||||
@ -200,22 +195,22 @@ function compileGlyf(code, cmds, font, visitedGlyphs = new Set()) {
|
||||
if (numberOfContours < 0) {
|
||||
// composite glyph
|
||||
do {
|
||||
flags = readUint16(code, i);
|
||||
const glyphIndex = readUint16(code, i + 2);
|
||||
flags = view.getUint16(i);
|
||||
const glyphIndex = view.getUint16(i + 2);
|
||||
i += 4;
|
||||
let arg1, arg2;
|
||||
if (flags & 0x01) {
|
||||
if (flags & 0x02) {
|
||||
arg1 = readInt16(code, i);
|
||||
arg2 = readInt16(code, i + 2);
|
||||
arg1 = view.getInt16(i);
|
||||
arg2 = view.getInt16(i + 2);
|
||||
} else {
|
||||
arg1 = readUint16(code, i);
|
||||
arg2 = readUint16(code, i + 2);
|
||||
arg1 = view.getUint16(i);
|
||||
arg2 = view.getUint16(i + 2);
|
||||
}
|
||||
i += 4;
|
||||
} else if (flags & 0x02) {
|
||||
arg1 = readInt8(code, i++);
|
||||
arg2 = readInt8(code, i++);
|
||||
arg1 = view.getInt8(i++);
|
||||
arg2 = view.getInt8(i++);
|
||||
} else {
|
||||
arg1 = code[i++];
|
||||
arg2 = code[i++];
|
||||
@ -232,17 +227,17 @@ function compileGlyf(code, cmds, font, visitedGlyphs = new Set()) {
|
||||
scale01 = 0,
|
||||
scale10 = 0;
|
||||
if (flags & 0x08) {
|
||||
scaleX = scaleY = getFloat214(code, i);
|
||||
scaleX = scaleY = getFloat214(view, i);
|
||||
i += 2;
|
||||
} else if (flags & 0x40) {
|
||||
scaleX = getFloat214(code, i);
|
||||
scaleY = getFloat214(code, i + 2);
|
||||
scaleX = getFloat214(view, i);
|
||||
scaleY = getFloat214(view, i + 2);
|
||||
i += 4;
|
||||
} else if (flags & 0x80) {
|
||||
scaleX = getFloat214(code, i);
|
||||
scale01 = getFloat214(code, i + 2);
|
||||
scale10 = getFloat214(code, i + 4);
|
||||
scaleY = getFloat214(code, i + 6);
|
||||
scaleX = getFloat214(view, i);
|
||||
scale01 = getFloat214(view, i + 2);
|
||||
scale10 = getFloat214(view, i + 4);
|
||||
scaleY = getFloat214(view, i + 6);
|
||||
i += 8;
|
||||
}
|
||||
const subglyph = font.glyphs[glyphIndex];
|
||||
@ -265,10 +260,10 @@ function compileGlyf(code, cmds, font, visitedGlyphs = new Set()) {
|
||||
const endPtsOfContours = [];
|
||||
let j, jj;
|
||||
for (j = 0; j < numberOfContours; j++) {
|
||||
endPtsOfContours.push(readUint16(code, i));
|
||||
endPtsOfContours.push(view.getUint16(i));
|
||||
i += 2;
|
||||
}
|
||||
const instructionLength = readUint16(code, i);
|
||||
const instructionLength = view.getUint16(i);
|
||||
i += 2 + instructionLength; // skipping the instructions
|
||||
const numberOfPoints = endPtsOfContours.at(-1) + 1;
|
||||
const points = [];
|
||||
@ -285,7 +280,7 @@ function compileGlyf(code, cmds, font, visitedGlyphs = new Set()) {
|
||||
for (j = 0; j < numberOfPoints; j++) {
|
||||
switch (points[j].flags & 0x12) {
|
||||
case 0x00:
|
||||
x += readInt16(code, i);
|
||||
x += view.getInt16(i);
|
||||
i += 2;
|
||||
break;
|
||||
case 0x02:
|
||||
@ -300,7 +295,7 @@ function compileGlyf(code, cmds, font, visitedGlyphs = new Set()) {
|
||||
for (j = 0; j < numberOfPoints; j++) {
|
||||
switch (points[j].flags & 0x24) {
|
||||
case 0x00:
|
||||
y += readInt16(code, i);
|
||||
y += view.getInt16(i);
|
||||
i += 2;
|
||||
break;
|
||||
case 0x04:
|
||||
@ -384,6 +379,7 @@ function compileCharString(charStringCode, cmds, font, glyphId) {
|
||||
let firstPoint = null;
|
||||
|
||||
function parse(code) {
|
||||
const view = new DataView(code.buffer, code.byteOffset, code.byteLength);
|
||||
let i = 0;
|
||||
while (i < code.length) {
|
||||
let stackClean = false;
|
||||
@ -660,7 +656,7 @@ function compileCharString(charStringCode, cmds, font, glyphId) {
|
||||
}
|
||||
break;
|
||||
case 28:
|
||||
stack.push(readInt16(code, i));
|
||||
stack.push(view.getInt16(i));
|
||||
i += 2;
|
||||
break;
|
||||
case 29: // callgsubr
|
||||
@ -725,13 +721,7 @@ function compileCharString(charStringCode, cmds, font, glyphId) {
|
||||
} else if (v < 255) {
|
||||
stack.push(-(v - 251) * 256 - code[i++] - 108);
|
||||
} else {
|
||||
stack.push(
|
||||
((code[i] << 24) |
|
||||
(code[i + 1] << 16) |
|
||||
(code[i + 2] << 8) |
|
||||
code[i + 3]) /
|
||||
65536
|
||||
);
|
||||
stack.push(view.getInt32(i) / 65536);
|
||||
i += 4;
|
||||
}
|
||||
break;
|
||||
@ -915,13 +905,14 @@ class Type2Compiled extends CompiledFont {
|
||||
|
||||
class FontRendererFactory {
|
||||
static create(font, seacAnalysisEnabled) {
|
||||
const data = new Uint8Array(font.data);
|
||||
const data = new Uint8Array(font.data),
|
||||
view = new DataView(data.buffer);
|
||||
let cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm;
|
||||
const numTables = readUint16(data, 4);
|
||||
const numTables = view.getUint16(4);
|
||||
for (let i = 0, p = 12; i < numTables; i++, p += 16) {
|
||||
const tag = bytesToString(data.subarray(p, p + 4));
|
||||
const offset = readUint32(data, p + 8);
|
||||
const length = readUint32(data, p + 12);
|
||||
const offset = view.getUint32(p + 8);
|
||||
const length = view.getUint32(p + 12);
|
||||
switch (tag) {
|
||||
case "cmap":
|
||||
cmap = parseCmap(data, offset, offset + length);
|
||||
@ -933,8 +924,8 @@ class FontRendererFactory {
|
||||
loca = data.subarray(offset, offset + length);
|
||||
break;
|
||||
case "head":
|
||||
unitsPerEm = readUint16(data, offset + 18);
|
||||
indexToLocFormat = readUint16(data, offset + 50);
|
||||
unitsPerEm = view.getUint16(offset + 18);
|
||||
indexToLocFormat = view.getUint16(offset + 50);
|
||||
break;
|
||||
case "CFF ":
|
||||
cff = parseCff(data, offset, offset + length, seacAnalysisEnabled);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user