Merge pull request #14856 from Snuffleupagus/rm-forceClamped

[api-minor] Remove the `forceClamped`-functionality in the Streams (issue 14849)
This commit is contained in:
Jonas Jenwald 2022-04-29 15:19:17 +02:00 committed by GitHub
commit 24d5d5d761
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 44 additions and 94 deletions

View File

@ -40,7 +40,7 @@ class BaseStream {
unreachable("Abstract method `getByte` called"); unreachable("Abstract method `getByte` called");
} }
getBytes(length, forceClamped = false) { getBytes(length) {
unreachable("Abstract method `getBytes` called"); unreachable("Abstract method `getBytes` called");
} }
@ -52,8 +52,8 @@ class BaseStream {
return peekedByte; return peekedByte;
} }
peekBytes(length, forceClamped = false) { peekBytes(length) {
const bytes = this.getBytes(length, forceClamped); const bytes = this.getBytes(length);
this.pos -= bytes.length; this.pos -= bytes.length;
return bytes; return bytes;
} }
@ -80,7 +80,7 @@ class BaseStream {
} }
getString(length) { getString(length) {
return bytesToString(this.getBytes(length, /* forceClamped = */ false)); return bytesToString(this.getBytes(length));
} }
skip(n) { skip(n) {

View File

@ -169,7 +169,7 @@ class ChunkedStream extends Stream {
return this.bytes[this.pos++]; return this.bytes[this.pos++];
} }
getBytes(length, forceClamped = false) { getBytes(length) {
const bytes = this.bytes; const bytes = this.bytes;
const pos = this.pos; const pos = this.pos;
const strEnd = this.end; const strEnd = this.end;
@ -178,9 +178,7 @@ class ChunkedStream extends Stream {
if (strEnd > this.progressiveDataLength) { if (strEnd > this.progressiveDataLength) {
this.ensureRange(pos, strEnd); this.ensureRange(pos, strEnd);
} }
const subarray = bytes.subarray(pos, strEnd); return bytes.subarray(pos, strEnd);
// `this.bytes` is always a `Uint8Array` here.
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
} }
let end = pos + length; let end = pos + length;
@ -192,9 +190,7 @@ class ChunkedStream extends Stream {
} }
this.pos = end; this.pos = end;
const subarray = bytes.subarray(pos, end); return bytes.subarray(pos, end);
// `this.bytes` is always a `Uint8Array` here.
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
} }
getByteRange(begin, end) { getByteRange(begin, end) {

View File

@ -73,7 +73,7 @@ class DecodeStream extends BaseStream {
return this.buffer[this.pos++]; return this.buffer[this.pos++];
} }
getBytes(length, forceClamped = false) { getBytes(length) {
const pos = this.pos; const pos = this.pos;
let end; let end;
@ -96,11 +96,7 @@ class DecodeStream extends BaseStream {
} }
this.pos = end; this.pos = end;
const subarray = this.buffer.subarray(pos, end); return this.buffer.subarray(pos, end);
// `this.buffer` is either a `Uint8Array` or `Uint8ClampedArray` here.
return forceClamped && !(subarray instanceof Uint8ClampedArray)
? new Uint8ClampedArray(subarray)
: subarray;
} }
reset() { reset() {

View File

@ -613,10 +613,7 @@ class PartialEvaluator {
// for later. // for later.
const interpolate = dict.get("I", "Interpolate"); const interpolate = dict.get("I", "Interpolate");
const bitStrideLength = (w + 7) >> 3; const bitStrideLength = (w + 7) >> 3;
const imgArray = image.getBytes( const imgArray = image.getBytes(bitStrideLength * h);
bitStrideLength * h,
/* forceClamped = */ true
);
const decode = dict.getArray("D", "Decode"); const decode = dict.getArray("D", "Decode");
if (this.parsingType3Font) { if (this.parsingType3Font) {

View File

@ -308,15 +308,6 @@ class PDFImage {
inverseDecode, inverseDecode,
interpolate, interpolate,
}) { }) {
if (
typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")
) {
assert(
imgArray instanceof Uint8ClampedArray,
'PDFImage.createRawMask: Unsupported "imgArray" type.'
);
}
// |imgArray| might not contain full data for every pixel of the mask, so // |imgArray| might not contain full data for every pixel of the mask, so
// we need to distinguish between |computedLength| and |actualLength|. // we need to distinguish between |computedLength| and |actualLength|.
// In particular, if inverseDecode is true, then the array we return must // In particular, if inverseDecode is true, then the array we return must
@ -332,14 +323,11 @@ class PDFImage {
// form, so we can just transfer it. // form, so we can just transfer it.
data = imgArray; data = imgArray;
} else if (!inverseDecode) { } else if (!inverseDecode) {
data = new Uint8ClampedArray(actualLength); data = new Uint8Array(imgArray);
data.set(imgArray);
} else { } else {
data = new Uint8ClampedArray(computedLength); data = new Uint8Array(computedLength);
data.set(imgArray); data.set(imgArray);
for (i = actualLength; i < computedLength; i++) { data.fill(0xff, actualLength);
data[i] = 0xff;
}
} }
// If necessary, invert the original mask data (but not any extra we might // If necessary, invert the original mask data (but not any extra we might
@ -363,16 +351,6 @@ class PDFImage {
inverseDecode, inverseDecode,
interpolate, interpolate,
}) { }) {
if (
typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")
) {
assert(
imgArray instanceof Uint8ClampedArray,
'PDFImage.createMask: Unsupported "imgArray" type.'
);
}
const isSingleOpaquePixel = const isSingleOpaquePixel =
width === 1 && width === 1 &&
height === 1 && height === 1 &&
@ -682,7 +660,6 @@ class PDFImage {
// Rows start at byte boundary. // Rows start at byte boundary.
const rowBytes = (originalWidth * numComps * bpc + 7) >> 3; const rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
let imgArray;
if (!forceRGBA) { if (!forceRGBA) {
// If it is a 1-bit-per-pixel grayscale (i.e. black-and-white) image // If it is a 1-bit-per-pixel grayscale (i.e. black-and-white) image
@ -710,20 +687,8 @@ class PDFImage {
drawHeight === originalHeight drawHeight === originalHeight
) { ) {
imgData.kind = kind; imgData.kind = kind;
imgData.data = this.getImageBytes(originalHeight * rowBytes, {});
imgArray = this.getImageBytes(originalHeight * rowBytes);
// If imgArray came from a DecodeStream, we're safe to transfer it
// (and thus detach its underlying buffer) because it will constitute
// the entire DecodeStream's data. But if it came from a Stream, we
// need to copy it because it'll only be a portion of the Stream's
// data, and the rest will be read later on.
if (this.image instanceof DecodeStream) {
imgData.data = imgArray;
} else {
const newArray = new Uint8ClampedArray(imgArray.length);
newArray.set(imgArray);
imgData.data = newArray;
}
if (this.needsDecode) { if (this.needsDecode) {
// Invert the buffer (which must be grayscale if we reached here). // Invert the buffer (which must be grayscale if we reached here).
assert( assert(
@ -748,18 +713,19 @@ class PDFImage {
case "DeviceRGB": case "DeviceRGB":
case "DeviceCMYK": case "DeviceCMYK":
imgData.kind = ImageKind.RGB_24BPP; imgData.kind = ImageKind.RGB_24BPP;
imgData.data = this.getImageBytes( imgData.data = this.getImageBytes(imageLength, {
imageLength,
drawWidth, drawWidth,
drawHeight, drawHeight,
/* forceRGB = */ true forceRGB: true,
); });
return imgData; return imgData;
} }
} }
} }
imgArray = this.getImageBytes(originalHeight * rowBytes); const imgArray = this.getImageBytes(originalHeight * rowBytes, {
internal: true,
});
// imgArray can be incomplete (e.g. after CCITT fax encoding). // imgArray can be incomplete (e.g. after CCITT fax encoding).
const actualHeight = const actualHeight =
0 | (((imgArray.length / rowBytes) * drawHeight) / originalHeight); 0 | (((imgArray.length / rowBytes) * drawHeight) / originalHeight);
@ -834,7 +800,7 @@ class PDFImage {
// rows start at byte boundary // rows start at byte boundary
const rowBytes = (width * numComps * bpc + 7) >> 3; const rowBytes = (width * numComps * bpc + 7) >> 3;
const imgArray = this.getImageBytes(height * rowBytes); const imgArray = this.getImageBytes(height * rowBytes, { internal: true });
const comps = this.getComponents(imgArray); const comps = this.getComponents(imgArray);
let i, length; let i, length;
@ -867,12 +833,29 @@ class PDFImage {
} }
} }
getImageBytes(length, drawWidth, drawHeight, forceRGB = false) { getImageBytes(
length,
{ drawWidth, drawHeight, forceRGB = false, internal = false }
) {
this.image.reset(); this.image.reset();
this.image.drawWidth = drawWidth || this.width; this.image.drawWidth = drawWidth || this.width;
this.image.drawHeight = drawHeight || this.height; this.image.drawHeight = drawHeight || this.height;
this.image.forceRGB = !!forceRGB; this.image.forceRGB = !!forceRGB;
return this.image.getBytes(length, /* forceClamped = */ true); const imageBytes = this.image.getBytes(length);
// If imageBytes came from a DecodeStream, we're safe to transfer it
// (and thus detach its underlying buffer) because it will constitute
// the entire DecodeStream's data. But if it came from a Stream, we
// need to copy it because it'll only be a portion of the Stream's
// data, and the rest will be read later on.
if (internal || this.image instanceof DecodeStream) {
return imageBytes;
}
assert(
imageBytes instanceof Uint8Array,
'PDFImage.getImageBytes: Unsupported "imageBytes" type.'
);
return new Uint8Array(imageBytes);
} }
} }

View File

@ -14,7 +14,6 @@
*/ */
import { import {
assert,
ImageKind, ImageKind,
OPS, OPS,
RenderingIntentFlag, RenderingIntentFlag,
@ -109,7 +108,7 @@ addState(
} }
const imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING; const imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
const imgHeight = currentY + maxLineHeight + IMAGE_PADDING; const imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
const imgData = new Uint8ClampedArray(imgWidth * imgHeight * 4); const imgData = new Uint8Array(imgWidth * imgHeight * 4);
const imgRowSize = imgWidth << 2; const imgRowSize = imgWidth << 2;
for (let q = 0; q < count; q++) { for (let q = 0; q < count; q++) {
const data = argsArray[iFirstPIIXO + (q << 2)][0].data; const data = argsArray[iFirstPIIXO + (q << 2)][0].data;
@ -678,17 +677,6 @@ 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 (
typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")
) {
assert(
arg.data instanceof Uint8ClampedArray ||
typeof arg.data === "string",
'OperatorList._transfers: Unsupported "arg.data" type.'
);
}
if ( if (
!arg.cached && !arg.cached &&
arg.data && arg.data &&

View File

@ -45,24 +45,20 @@ class Stream extends BaseStream {
return this.bytes[this.pos++]; return this.bytes[this.pos++];
} }
getBytes(length, forceClamped = false) { getBytes(length) {
const bytes = this.bytes; const bytes = this.bytes;
const pos = this.pos; const pos = this.pos;
const strEnd = this.end; const strEnd = this.end;
if (!length) { if (!length) {
const subarray = bytes.subarray(pos, strEnd); return bytes.subarray(pos, strEnd);
// `this.bytes` is always a `Uint8Array` here.
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
} }
let end = pos + length; let end = pos + length;
if (end > strEnd) { if (end > strEnd) {
end = strEnd; end = strEnd;
} }
this.pos = end; this.pos = end;
const subarray = bytes.subarray(pos, end); return bytes.subarray(pos, end);
// `this.bytes` is always a `Uint8Array` here.
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
} }
getByteRange(begin, end) { getByteRange(begin, end) {

View File

@ -36,12 +36,6 @@ describe("stream", function () {
const result = predictor.getBytes(6); const result = predictor.getBytes(6);
expect(result).toEqual(new Uint8Array([100, 3, 101, 2, 102, 1])); expect(result).toEqual(new Uint8Array([100, 3, 101, 2, 102, 1]));
predictor.reset();
const clampedResult = predictor.getBytes(6, /* forceClamped = */ true);
expect(clampedResult).toEqual(
new Uint8ClampedArray([100, 3, 101, 2, 102, 1])
);
}); });
}); });
}); });