Merge pull request #19736 from Snuffleupagus/compileType3Glyph-worker
[api-minor] Move Type3-glyph compilation to the worker-thread
This commit is contained in:
commit
e5fbf52405
@ -32,6 +32,7 @@ import {
|
|||||||
} from "../shared/util.js";
|
} from "../shared/util.js";
|
||||||
import { CMapFactory, IdentityCMap } from "./cmap.js";
|
import { CMapFactory, IdentityCMap } from "./cmap.js";
|
||||||
import { Cmd, Dict, EOF, isName, Name, Ref, RefSet } from "./primitives.js";
|
import { Cmd, Dict, EOF, isName, Name, Ref, RefSet } from "./primitives.js";
|
||||||
|
import { compileType3Glyph, FontFlags } from "./fonts_utils.js";
|
||||||
import { ErrorFont, Font } from "./fonts.js";
|
import { ErrorFont, Font } from "./fonts.js";
|
||||||
import {
|
import {
|
||||||
fetchBinaryData,
|
fetchBinaryData,
|
||||||
@ -72,7 +73,6 @@ import { bidi } from "./bidi.js";
|
|||||||
import { ColorSpace } from "./colorspace.js";
|
import { ColorSpace } from "./colorspace.js";
|
||||||
import { ColorSpaceUtils } from "./colorspace_utils.js";
|
import { ColorSpaceUtils } from "./colorspace_utils.js";
|
||||||
import { DecodeStream } from "./decode_stream.js";
|
import { DecodeStream } from "./decode_stream.js";
|
||||||
import { FontFlags } from "./fonts_utils.js";
|
|
||||||
import { getFontSubstitution } from "./font_substitutions.js";
|
import { getFontSubstitution } from "./font_substitutions.js";
|
||||||
import { getGlyphsUnicode } from "./glyphlist.js";
|
import { getGlyphsUnicode } from "./glyphlist.js";
|
||||||
import { getMetrics } from "./metrics.js";
|
import { getMetrics } from "./metrics.js";
|
||||||
@ -611,6 +611,12 @@ class PartialEvaluator {
|
|||||||
const decode = dict.getArray("D", "Decode");
|
const decode = dict.getArray("D", "Decode");
|
||||||
|
|
||||||
if (this.parsingType3Font) {
|
if (this.parsingType3Font) {
|
||||||
|
// NOTE: Compared to other image resources we don't bother caching
|
||||||
|
// Type3-glyph image masks, since we've not come across any cases
|
||||||
|
// where that actually helps.
|
||||||
|
// In Type3-glyphs image masks are "always" inline resources,
|
||||||
|
// they're usually fairly small and aren't being re-used either.
|
||||||
|
|
||||||
imgData = PDFImage.createRawMask({
|
imgData = PDFImage.createRawMask({
|
||||||
imgArray,
|
imgArray,
|
||||||
width: w,
|
width: w,
|
||||||
@ -619,25 +625,21 @@ class PartialEvaluator {
|
|||||||
inverseDecode: decode?.[0] > 0,
|
inverseDecode: decode?.[0] > 0,
|
||||||
interpolate,
|
interpolate,
|
||||||
});
|
});
|
||||||
|
args = compileType3Glyph(imgData);
|
||||||
|
|
||||||
imgData.cached = !!cacheKey;
|
if (args) {
|
||||||
|
operatorList.addImageOps(OPS.constructPath, args, optionalContent);
|
||||||
fn = OPS.paintImageMaskXObject;
|
return;
|
||||||
args = [imgData];
|
|
||||||
operatorList.addImageOps(fn, args, optionalContent);
|
|
||||||
|
|
||||||
if (cacheKey) {
|
|
||||||
const cacheData = { fn, args, optionalContent };
|
|
||||||
localImageCache.set(cacheKey, imageRef, cacheData);
|
|
||||||
|
|
||||||
if (imageRef) {
|
|
||||||
this._regionalImageCache.set(
|
|
||||||
/* name = */ null,
|
|
||||||
imageRef,
|
|
||||||
cacheData
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
warn("Cannot compile Type3 glyph.");
|
||||||
|
|
||||||
|
// If compilation failed, or was disabled, fallback to using an inline
|
||||||
|
// image mask; this case should be extremely rare.
|
||||||
|
operatorList.addImageOps(
|
||||||
|
OPS.paintImageMaskXObject,
|
||||||
|
[imgData],
|
||||||
|
optionalContent
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,11 +13,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { DrawOPS, info, OPS } from "../shared/util.js";
|
||||||
import { getEncoding, StandardEncoding } from "./encodings.js";
|
import { getEncoding, StandardEncoding } from "./encodings.js";
|
||||||
import { getGlyphsUnicode } from "./glyphlist.js";
|
import { getGlyphsUnicode } from "./glyphlist.js";
|
||||||
import { getLookupTableFactory } from "./core_utils.js";
|
import { getLookupTableFactory } from "./core_utils.js";
|
||||||
import { getUnicodeForGlyph } from "./unicode.js";
|
import { getUnicodeForGlyph } from "./unicode.js";
|
||||||
import { info } from "../shared/util.js";
|
|
||||||
|
|
||||||
// Accented characters have issues on Windows and Linux. When this flag is
|
// Accented characters have issues on Windows and Linux. When this flag is
|
||||||
// enabled glyphs that use seac and seac style endchar operators are truncated
|
// enabled glyphs that use seac and seac style endchar operators are truncated
|
||||||
@ -207,7 +207,177 @@ const getVerticalPresentationForm = getLookupTableFactory(t => {
|
|||||||
t[0xff5d] = 0xfe38; // FULLWIDTH RIGHT CURLY BRACKET
|
t[0xff5d] = 0xfe38; // FULLWIDTH RIGHT CURLY BRACKET
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// To disable Type3 compilation, set the value to `-1`.
|
||||||
|
const MAX_SIZE_TO_COMPILE = 1000;
|
||||||
|
|
||||||
|
function compileType3Glyph({ data: img, width, height }) {
|
||||||
|
if (width > MAX_SIZE_TO_COMPILE || height > MAX_SIZE_TO_COMPILE) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const POINT_TO_PROCESS_LIMIT = 1000;
|
||||||
|
const POINT_TYPES = new Uint8Array([
|
||||||
|
0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const width1 = width + 1;
|
||||||
|
const points = new Uint8Array(width1 * (height + 1));
|
||||||
|
let i, j, j0;
|
||||||
|
|
||||||
|
// decodes bit-packed mask data
|
||||||
|
const lineSize = (width + 7) & ~7;
|
||||||
|
const data = new Uint8Array(lineSize * height);
|
||||||
|
let pos = 0;
|
||||||
|
for (const elem of img) {
|
||||||
|
let mask = 128;
|
||||||
|
while (mask > 0) {
|
||||||
|
data[pos++] = elem & mask ? 0 : 255;
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// finding interesting points: every point is located between mask pixels,
|
||||||
|
// so there will be points of the (width + 1)x(height + 1) grid. Every point
|
||||||
|
// will have flags assigned based on neighboring mask pixels:
|
||||||
|
// 4 | 8
|
||||||
|
// --P--
|
||||||
|
// 2 | 1
|
||||||
|
// We are interested only in points with the flags:
|
||||||
|
// - outside corners: 1, 2, 4, 8;
|
||||||
|
// - inside corners: 7, 11, 13, 14;
|
||||||
|
// - and, intersections: 5, 10.
|
||||||
|
let count = 0;
|
||||||
|
pos = 0;
|
||||||
|
if (data[pos] !== 0) {
|
||||||
|
points[0] = 1;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
for (j = 1; j < width; j++) {
|
||||||
|
if (data[pos] !== data[pos + 1]) {
|
||||||
|
points[j] = data[pos] ? 2 : 1;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if (data[pos] !== 0) {
|
||||||
|
points[j] = 2;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
for (i = 1; i < height; i++) {
|
||||||
|
pos = i * lineSize;
|
||||||
|
j0 = i * width1;
|
||||||
|
if (data[pos - lineSize] !== data[pos]) {
|
||||||
|
points[j0] = data[pos] ? 1 : 8;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
// 'sum' is the position of the current pixel configuration in the 'TYPES'
|
||||||
|
// array (in order 8-1-2-4, so we can use '>>2' to shift the column).
|
||||||
|
let sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);
|
||||||
|
for (j = 1; j < width; j++) {
|
||||||
|
sum =
|
||||||
|
(sum >> 2) +
|
||||||
|
(data[pos + 1] ? 4 : 0) +
|
||||||
|
(data[pos - lineSize + 1] ? 8 : 0);
|
||||||
|
if (POINT_TYPES[sum]) {
|
||||||
|
points[j0 + j] = POINT_TYPES[sum];
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if (data[pos - lineSize] !== data[pos]) {
|
||||||
|
points[j0 + j] = data[pos] ? 2 : 4;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > POINT_TO_PROCESS_LIMIT) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = lineSize * (height - 1);
|
||||||
|
j0 = i * width1;
|
||||||
|
if (data[pos] !== 0) {
|
||||||
|
points[j0] = 8;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
for (j = 1; j < width; j++) {
|
||||||
|
if (data[pos] !== data[pos + 1]) {
|
||||||
|
points[j0 + j] = data[pos] ? 4 : 8;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if (data[pos] !== 0) {
|
||||||
|
points[j0 + j] = 4;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
if (count > POINT_TO_PROCESS_LIMIT) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// building outlines
|
||||||
|
const steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]);
|
||||||
|
const pathBuf = [];
|
||||||
|
|
||||||
|
// the path shall be painted in [0..1]x[0..1] space
|
||||||
|
const { a, b, c, d, e, f } = new DOMMatrix()
|
||||||
|
.scaleSelf(1 / width, -1 / height)
|
||||||
|
.translateSelf(0, -height);
|
||||||
|
|
||||||
|
for (i = 0; count && i <= height; i++) {
|
||||||
|
let p = i * width1;
|
||||||
|
const end = p + width;
|
||||||
|
while (p < end && !points[p]) {
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
if (p === end) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let x = p % width1;
|
||||||
|
let y = i;
|
||||||
|
pathBuf.push(DrawOPS.moveTo, a * x + c * y + e, b * x + d * y + f);
|
||||||
|
|
||||||
|
const p0 = p;
|
||||||
|
let type = points[p];
|
||||||
|
do {
|
||||||
|
const step = steps[type];
|
||||||
|
do {
|
||||||
|
p += step;
|
||||||
|
} while (!points[p]);
|
||||||
|
|
||||||
|
const pp = points[p];
|
||||||
|
if (pp !== 5 && pp !== 10) {
|
||||||
|
// set new direction
|
||||||
|
type = pp;
|
||||||
|
// delete mark
|
||||||
|
points[p] = 0;
|
||||||
|
} else {
|
||||||
|
// type is 5 or 10, ie, a crossing
|
||||||
|
// set new direction
|
||||||
|
type = pp & ((0x33 * type) >> 4);
|
||||||
|
// set new type for "future hit"
|
||||||
|
points[p] &= (type >> 2) | (type << 2);
|
||||||
|
}
|
||||||
|
x = p % width1;
|
||||||
|
y = (p / width1) | 0;
|
||||||
|
pathBuf.push(DrawOPS.lineTo, a * x + c * y + e, b * x + d * y + f);
|
||||||
|
|
||||||
|
if (!points[p]) {
|
||||||
|
--count;
|
||||||
|
}
|
||||||
|
} while (p0 !== p);
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
OPS.rawFillPath,
|
||||||
|
[new Float32Array(pathBuf)],
|
||||||
|
new Float32Array([0, 0, width, height]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
compileType3Glyph,
|
||||||
FontFlags,
|
FontFlags,
|
||||||
getVerticalPresentationForm,
|
getVerticalPresentationForm,
|
||||||
MacStandardGlyphOrdering,
|
MacStandardGlyphOrdering,
|
||||||
|
|||||||
@ -770,7 +770,7 @@ class OperatorList {
|
|||||||
case OPS.paintInlineImageXObjectGroup:
|
case OPS.paintInlineImageXObjectGroup:
|
||||||
case OPS.paintImageMaskXObject:
|
case OPS.paintImageMaskXObject:
|
||||||
const arg = argsArray[i][0]; // First parameter in imgData.
|
const arg = argsArray[i][0]; // First parameter in imgData.
|
||||||
if (!arg.cached && arg.data?.buffer instanceof ArrayBuffer) {
|
if (arg.data?.buffer instanceof ArrayBuffer) {
|
||||||
transfers.push(arg.data.buffer);
|
transfers.push(arg.data.buffer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -54,9 +54,6 @@ const EXECUTION_TIME = 15; // ms
|
|||||||
// Defines the number of steps before checking the execution time.
|
// Defines the number of steps before checking the execution time.
|
||||||
const EXECUTION_STEPS = 10;
|
const EXECUTION_STEPS = 10;
|
||||||
|
|
||||||
// To disable Type3 compilation, set the value to `-1`.
|
|
||||||
const MAX_SIZE_TO_COMPILE = 1000;
|
|
||||||
|
|
||||||
const FULL_CHUNK_HEIGHT = 16;
|
const FULL_CHUNK_HEIGHT = 16;
|
||||||
|
|
||||||
// Only used in rescaleAndStroke. The goal is to avoid
|
// Only used in rescaleAndStroke. The goal is to avoid
|
||||||
@ -299,169 +296,6 @@ function drawImageAtIntegerCoords(
|
|||||||
return [scaleX * destW, scaleY * destH];
|
return [scaleX * destW, scaleY * destH];
|
||||||
}
|
}
|
||||||
|
|
||||||
function compileType3Glyph(imgData) {
|
|
||||||
const { width, height } = imgData;
|
|
||||||
if (width > MAX_SIZE_TO_COMPILE || height > MAX_SIZE_TO_COMPILE) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const POINT_TO_PROCESS_LIMIT = 1000;
|
|
||||||
const POINT_TYPES = new Uint8Array([
|
|
||||||
0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const width1 = width + 1;
|
|
||||||
const points = new Uint8Array(width1 * (height + 1));
|
|
||||||
let i, j, j0;
|
|
||||||
|
|
||||||
// decodes bit-packed mask data
|
|
||||||
const lineSize = (width + 7) & ~7;
|
|
||||||
const data = new Uint8Array(lineSize * height);
|
|
||||||
let pos = 0;
|
|
||||||
for (const elem of imgData.data) {
|
|
||||||
let mask = 128;
|
|
||||||
while (mask > 0) {
|
|
||||||
data[pos++] = elem & mask ? 0 : 255;
|
|
||||||
mask >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// finding interesting points: every point is located between mask pixels,
|
|
||||||
// so there will be points of the (width + 1)x(height + 1) grid. Every point
|
|
||||||
// will have flags assigned based on neighboring mask pixels:
|
|
||||||
// 4 | 8
|
|
||||||
// --P--
|
|
||||||
// 2 | 1
|
|
||||||
// We are interested only in points with the flags:
|
|
||||||
// - outside corners: 1, 2, 4, 8;
|
|
||||||
// - inside corners: 7, 11, 13, 14;
|
|
||||||
// - and, intersections: 5, 10.
|
|
||||||
let count = 0;
|
|
||||||
pos = 0;
|
|
||||||
if (data[pos] !== 0) {
|
|
||||||
points[0] = 1;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
for (j = 1; j < width; j++) {
|
|
||||||
if (data[pos] !== data[pos + 1]) {
|
|
||||||
points[j] = data[pos] ? 2 : 1;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
if (data[pos] !== 0) {
|
|
||||||
points[j] = 2;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
for (i = 1; i < height; i++) {
|
|
||||||
pos = i * lineSize;
|
|
||||||
j0 = i * width1;
|
|
||||||
if (data[pos - lineSize] !== data[pos]) {
|
|
||||||
points[j0] = data[pos] ? 1 : 8;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
// 'sum' is the position of the current pixel configuration in the 'TYPES'
|
|
||||||
// array (in order 8-1-2-4, so we can use '>>2' to shift the column).
|
|
||||||
let sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);
|
|
||||||
for (j = 1; j < width; j++) {
|
|
||||||
sum =
|
|
||||||
(sum >> 2) +
|
|
||||||
(data[pos + 1] ? 4 : 0) +
|
|
||||||
(data[pos - lineSize + 1] ? 8 : 0);
|
|
||||||
if (POINT_TYPES[sum]) {
|
|
||||||
points[j0 + j] = POINT_TYPES[sum];
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
if (data[pos - lineSize] !== data[pos]) {
|
|
||||||
points[j0 + j] = data[pos] ? 2 : 4;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count > POINT_TO_PROCESS_LIMIT) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = lineSize * (height - 1);
|
|
||||||
j0 = i * width1;
|
|
||||||
if (data[pos] !== 0) {
|
|
||||||
points[j0] = 8;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
for (j = 1; j < width; j++) {
|
|
||||||
if (data[pos] !== data[pos + 1]) {
|
|
||||||
points[j0 + j] = data[pos] ? 4 : 8;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
if (data[pos] !== 0) {
|
|
||||||
points[j0 + j] = 4;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
if (count > POINT_TO_PROCESS_LIMIT) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// building outlines
|
|
||||||
const steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]);
|
|
||||||
const path = new Path2D();
|
|
||||||
|
|
||||||
// the path shall be painted in [0..1]x[0..1] space
|
|
||||||
const { a, b, c, d, e, f } = new DOMMatrix()
|
|
||||||
.scaleSelf(1 / width, -1 / height)
|
|
||||||
.translateSelf(0, -height);
|
|
||||||
|
|
||||||
for (i = 0; count && i <= height; i++) {
|
|
||||||
let p = i * width1;
|
|
||||||
const end = p + width;
|
|
||||||
while (p < end && !points[p]) {
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
if (p === end) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let x = p % width1;
|
|
||||||
let y = i;
|
|
||||||
path.moveTo(a * x + c * y + e, b * x + d * y + f);
|
|
||||||
|
|
||||||
const p0 = p;
|
|
||||||
let type = points[p];
|
|
||||||
do {
|
|
||||||
const step = steps[type];
|
|
||||||
do {
|
|
||||||
p += step;
|
|
||||||
} while (!points[p]);
|
|
||||||
|
|
||||||
const pp = points[p];
|
|
||||||
if (pp !== 5 && pp !== 10) {
|
|
||||||
// set new direction
|
|
||||||
type = pp;
|
|
||||||
// delete mark
|
|
||||||
points[p] = 0;
|
|
||||||
} else {
|
|
||||||
// type is 5 or 10, ie, a crossing
|
|
||||||
// set new direction
|
|
||||||
type = pp & ((0x33 * type) >> 4);
|
|
||||||
// set new type for "future hit"
|
|
||||||
points[p] &= (type >> 2) | (type << 2);
|
|
||||||
}
|
|
||||||
x = p % width1;
|
|
||||||
y = (p / width1) | 0;
|
|
||||||
path.lineTo(a * x + c * y + e, b * x + d * y + f);
|
|
||||||
|
|
||||||
if (!points[p]) {
|
|
||||||
--count;
|
|
||||||
}
|
|
||||||
} while (p0 !== p);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CanvasExtraState {
|
class CanvasExtraState {
|
||||||
constructor(width, height) {
|
constructor(width, height) {
|
||||||
// Are soft masks and alpha values shapes or opacities?
|
// Are soft masks and alpha values shapes or opacities?
|
||||||
@ -821,7 +655,6 @@ class CanvasGraphics {
|
|||||||
this.canvasFactory = canvasFactory;
|
this.canvasFactory = canvasFactory;
|
||||||
this.filterFactory = filterFactory;
|
this.filterFactory = filterFactory;
|
||||||
this.groupStack = [];
|
this.groupStack = [];
|
||||||
this.processingType3 = null;
|
|
||||||
// Patterns are painted relative to the initial page/form transform, see
|
// Patterns are painted relative to the initial page/form transform, see
|
||||||
// PDF spec 8.7.2 NOTE 1.
|
// PDF spec 8.7.2 NOTE 1.
|
||||||
this.baseTransform = null;
|
this.baseTransform = null;
|
||||||
@ -1747,6 +1580,10 @@ class CanvasGraphics {
|
|||||||
this.consumePath(path);
|
this.consumePath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rawFillPath(path) {
|
||||||
|
this.ctx.fill(path);
|
||||||
|
}
|
||||||
|
|
||||||
// Clipping
|
// Clipping
|
||||||
clip() {
|
clip() {
|
||||||
this.pendingClip = NORMAL_CLIP;
|
this.pendingClip = NORMAL_CLIP;
|
||||||
@ -2267,7 +2104,6 @@ class CanvasGraphics {
|
|||||||
if (!operatorList) {
|
if (!operatorList) {
|
||||||
warn(`Type3 character "${glyph.operatorListId}" is not available.`);
|
warn(`Type3 character "${glyph.operatorListId}" is not available.`);
|
||||||
} else if (this.contentVisible) {
|
} else if (this.contentVisible) {
|
||||||
this.processingType3 = glyph;
|
|
||||||
this.save();
|
this.save();
|
||||||
ctx.scale(fontSize, fontSize);
|
ctx.scale(fontSize, fontSize);
|
||||||
ctx.transform(...fontMatrix);
|
ctx.transform(...fontMatrix);
|
||||||
@ -2282,7 +2118,6 @@ class CanvasGraphics {
|
|||||||
current.x += width * textHScale;
|
current.x += width * textHScale;
|
||||||
}
|
}
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
this.processingType3 = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type3 fonts
|
// Type3 fonts
|
||||||
@ -2703,18 +2538,6 @@ class CanvasGraphics {
|
|||||||
img.count = count;
|
img.count = count;
|
||||||
|
|
||||||
const ctx = this.ctx;
|
const ctx = this.ctx;
|
||||||
const glyph = this.processingType3;
|
|
||||||
|
|
||||||
if (glyph) {
|
|
||||||
if (glyph.compiled === undefined) {
|
|
||||||
glyph.compiled = compileType3Glyph(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glyph.compiled) {
|
|
||||||
ctx.fill(glyph.compiled);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const mask = this._createMaskCanvas(img);
|
const mask = this._createMaskCanvas(img);
|
||||||
const maskCanvas = mask.canvas;
|
const maskCanvas = mask.canvas;
|
||||||
|
|
||||||
|
|||||||
@ -339,6 +339,7 @@ const OPS = {
|
|||||||
constructPath: 91,
|
constructPath: 91,
|
||||||
setStrokeTransparent: 92,
|
setStrokeTransparent: 92,
|
||||||
setFillTransparent: 93,
|
setFillTransparent: 93,
|
||||||
|
rawFillPath: 94,
|
||||||
};
|
};
|
||||||
|
|
||||||
// In order to have a switch statement that is fast (i.e. which use a jump
|
// In order to have a switch statement that is fast (i.e. which use a jump
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user