Merge pull request #16106 from bungeman/improve_color_stop_detection
Better approximate gradient color stops
This commit is contained in:
commit
a24e11a91c
@ -157,10 +157,9 @@ class RadialAxialShading extends BaseShading {
|
|||||||
const fnObj = dict.getRaw("Function");
|
const fnObj = dict.getRaw("Function");
|
||||||
const fn = pdfFunctionFactory.createFromArray(fnObj);
|
const fn = pdfFunctionFactory.createFromArray(fnObj);
|
||||||
|
|
||||||
// 10 samples seems good enough for now, but probably won't work
|
// Use lcm(1,2,3,4,5,6,7,8,10) = 840 (including 9 increases this to 2520)
|
||||||
// if there are sharp color changes. Ideally, we would implement
|
// to catch evenly spaced stops. oeis.org/A003418
|
||||||
// the spec faithfully and add lossless optimizations.
|
const NUMBER_OF_SAMPLES = 840;
|
||||||
const NUMBER_OF_SAMPLES = 10;
|
|
||||||
const step = (t1 - t0) / NUMBER_OF_SAMPLES;
|
const step = (t1 - t0) / NUMBER_OF_SAMPLES;
|
||||||
|
|
||||||
const colorStops = (this.colorStops = []);
|
const colorStops = (this.colorStops = []);
|
||||||
@ -176,13 +175,80 @@ class RadialAxialShading extends BaseShading {
|
|||||||
const color = new Float32Array(cs.numComps),
|
const color = new Float32Array(cs.numComps),
|
||||||
ratio = new Float32Array(1);
|
ratio = new Float32Array(1);
|
||||||
let rgbColor;
|
let rgbColor;
|
||||||
for (let i = 0; i <= NUMBER_OF_SAMPLES; i++) {
|
|
||||||
|
let iBase = 0;
|
||||||
|
ratio[0] = t0;
|
||||||
|
fn(ratio, 0, color, 0);
|
||||||
|
let rgbBase = cs.getRgb(color, 0);
|
||||||
|
const cssColorBase = Util.makeHexColor(rgbBase[0], rgbBase[1], rgbBase[2]);
|
||||||
|
colorStops.push([0, cssColorBase]);
|
||||||
|
|
||||||
|
let iPrev = 1;
|
||||||
|
ratio[0] = t0 + step;
|
||||||
|
fn(ratio, 0, color, 0);
|
||||||
|
let rgbPrev = cs.getRgb(color, 0);
|
||||||
|
|
||||||
|
// Slopes are rise / run.
|
||||||
|
// A max slope is from the least value the base component could have been
|
||||||
|
// to the greatest value the current component could have been.
|
||||||
|
// A min slope is from the greatest value the base component could have been
|
||||||
|
// to the least value the current component could have been.
|
||||||
|
// Each component could have been rounded up to .5 from its original value
|
||||||
|
// so the conservative deltas are +-1 (+-.5 for base and -+.5 for current).
|
||||||
|
|
||||||
|
// The run is iPrev - iBase = 1, so omitted.
|
||||||
|
let maxSlopeR = rgbPrev[0] - rgbBase[0] + 1;
|
||||||
|
let maxSlopeG = rgbPrev[1] - rgbBase[1] + 1;
|
||||||
|
let maxSlopeB = rgbPrev[2] - rgbBase[2] + 1;
|
||||||
|
let minSlopeR = rgbPrev[0] - rgbBase[0] - 1;
|
||||||
|
let minSlopeG = rgbPrev[1] - rgbBase[1] - 1;
|
||||||
|
let minSlopeB = rgbPrev[2] - rgbBase[2] - 1;
|
||||||
|
|
||||||
|
for (let i = 2; i < NUMBER_OF_SAMPLES; i++) {
|
||||||
ratio[0] = t0 + i * step;
|
ratio[0] = t0 + i * step;
|
||||||
fn(ratio, 0, color, 0);
|
fn(ratio, 0, color, 0);
|
||||||
rgbColor = cs.getRgb(color, 0);
|
rgbColor = cs.getRgb(color, 0);
|
||||||
const cssColor = Util.makeHexColor(rgbColor[0], rgbColor[1], rgbColor[2]);
|
|
||||||
colorStops.push([i / NUMBER_OF_SAMPLES, cssColor]);
|
// Keep going if the maximum minimum slope <= the minimum maximum slope.
|
||||||
|
// Otherwise add a rgbPrev color stop and make it the new base.
|
||||||
|
|
||||||
|
const run = i - iBase;
|
||||||
|
maxSlopeR = Math.min(maxSlopeR, (rgbColor[0] - rgbBase[0] + 1) / run);
|
||||||
|
maxSlopeG = Math.min(maxSlopeG, (rgbColor[1] - rgbBase[1] + 1) / run);
|
||||||
|
maxSlopeB = Math.min(maxSlopeB, (rgbColor[2] - rgbBase[2] + 1) / run);
|
||||||
|
minSlopeR = Math.max(minSlopeR, (rgbColor[0] - rgbBase[0] - 1) / run);
|
||||||
|
minSlopeG = Math.max(minSlopeG, (rgbColor[1] - rgbBase[1] - 1) / run);
|
||||||
|
minSlopeB = Math.max(minSlopeB, (rgbColor[2] - rgbBase[2] - 1) / run);
|
||||||
|
|
||||||
|
const slopesExist =
|
||||||
|
minSlopeR <= maxSlopeR &&
|
||||||
|
minSlopeG <= maxSlopeG &&
|
||||||
|
minSlopeB <= maxSlopeB;
|
||||||
|
|
||||||
|
if (!slopesExist) {
|
||||||
|
const cssColor = Util.makeHexColor(rgbPrev[0], rgbPrev[1], rgbPrev[2]);
|
||||||
|
colorStops.push([iPrev / NUMBER_OF_SAMPLES, cssColor]);
|
||||||
|
|
||||||
|
// TODO: When fn frequency is high (iPrev - iBase === 1 twice in a row),
|
||||||
|
// send the color space and function to do the sampling display side.
|
||||||
|
|
||||||
|
// The run is i - iPrev = 1, so omitted.
|
||||||
|
maxSlopeR = rgbColor[0] - rgbPrev[0] + 1;
|
||||||
|
maxSlopeG = rgbColor[1] - rgbPrev[1] + 1;
|
||||||
|
maxSlopeB = rgbColor[2] - rgbPrev[2] + 1;
|
||||||
|
minSlopeR = rgbColor[0] - rgbPrev[0] - 1;
|
||||||
|
minSlopeG = rgbColor[1] - rgbPrev[1] - 1;
|
||||||
|
minSlopeB = rgbColor[2] - rgbPrev[2] - 1;
|
||||||
|
|
||||||
|
iBase = iPrev;
|
||||||
|
rgbBase = rgbPrev;
|
||||||
|
}
|
||||||
|
|
||||||
|
iPrev = i;
|
||||||
|
rgbPrev = rgbColor;
|
||||||
}
|
}
|
||||||
|
const cssColor = Util.makeHexColor(rgbPrev[0], rgbPrev[1], rgbPrev[2]);
|
||||||
|
colorStops.push([1, cssColor]);
|
||||||
|
|
||||||
let background = "transparent";
|
let background = "transparent";
|
||||||
if (dict.has("Background")) {
|
if (dict.has("Background")) {
|
||||||
|
2
test/pdfs/.gitignore
vendored
2
test/pdfs/.gitignore
vendored
@ -345,6 +345,7 @@
|
|||||||
!issue12810.pdf
|
!issue12810.pdf
|
||||||
!bug866395.pdf
|
!bug866395.pdf
|
||||||
!issue12010_reduced.pdf
|
!issue12010_reduced.pdf
|
||||||
|
!issue10572.pdf
|
||||||
!issue11718_reduced.pdf
|
!issue11718_reduced.pdf
|
||||||
!bug1027533.pdf
|
!bug1027533.pdf
|
||||||
!bug1028735.pdf
|
!bug1028735.pdf
|
||||||
@ -534,6 +535,7 @@
|
|||||||
!issue15012.pdf
|
!issue15012.pdf
|
||||||
!issue15150.pdf
|
!issue15150.pdf
|
||||||
!poppler-395-0-fuzzed.pdf
|
!poppler-395-0-fuzzed.pdf
|
||||||
|
!issue14165.pdf
|
||||||
!GHOSTSCRIPT-698804-1-fuzzed.pdf
|
!GHOSTSCRIPT-698804-1-fuzzed.pdf
|
||||||
!issue14814.pdf
|
!issue14814.pdf
|
||||||
!poppler-91414-0-53.pdf
|
!poppler-91414-0-53.pdf
|
||||||
|
374
test/pdfs/issue10572.pdf
Normal file
374
test/pdfs/issue10572.pdf
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
%PDF-1.5
|
||||||
|
%¿÷¢þ
|
||||||
|
%QDF-1.0
|
||||||
|
|
||||||
|
%% Original object ID: 20 0
|
||||||
|
1 0 obj
|
||||||
|
<<
|
||||||
|
/Pages 3 0 R
|
||||||
|
/Type /Catalog
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 19 0
|
||||||
|
2 0 obj
|
||||||
|
<<
|
||||||
|
/Creator (cairo 1.9.5 \(http://cairographics.org\))
|
||||||
|
/Producer (cairo 1.9.5 \(http://cairographics.org\))
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 1 0
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/Count 1
|
||||||
|
/Kids [
|
||||||
|
4 0 R
|
||||||
|
]
|
||||||
|
/Type /Pages
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Page 1
|
||||||
|
%% Original object ID: 7 0
|
||||||
|
4 0 obj
|
||||||
|
<<
|
||||||
|
/Contents 5 0 R
|
||||||
|
/Group <<
|
||||||
|
/CS /DeviceRGB
|
||||||
|
/S /Transparency
|
||||||
|
/Type /Group
|
||||||
|
>>
|
||||||
|
/MediaBox [
|
||||||
|
0
|
||||||
|
0
|
||||||
|
612
|
||||||
|
792
|
||||||
|
]
|
||||||
|
/Parent 3 0 R
|
||||||
|
/Resources 7 0 R
|
||||||
|
/Type /Page
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Contents for page 1
|
||||||
|
%% Original object ID: 3 0
|
||||||
|
5 0 obj
|
||||||
|
<<
|
||||||
|
/Length 6 0 R
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
q
|
||||||
|
Q q
|
||||||
|
54 738 504 -661.699 re W n
|
||||||
|
1 1 1 rg /a0 gs
|
||||||
|
54 738 504 -661.699 re f
|
||||||
|
Q q
|
||||||
|
61 716 225 -450 re W n
|
||||||
|
q /Pattern cs /p5 scn /a0 gs
|
||||||
|
61 716 225 -450 re f
|
||||||
|
Q
|
||||||
|
Q q
|
||||||
|
54 738 504 -661.699 re W n
|
||||||
|
0 0 0 RG /a0 gs
|
||||||
|
1 w
|
||||||
|
0 J
|
||||||
|
0 j
|
||||||
|
[] 0.0 d
|
||||||
|
10 M 60.5 716.5 226 -451 re S
|
||||||
|
56 736 424 -23 re W n
|
||||||
|
Q q
|
||||||
|
Q
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
6 0 obj
|
||||||
|
279
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 2 0
|
||||||
|
7 0 obj
|
||||||
|
<<
|
||||||
|
/ExtGState <<
|
||||||
|
/a0 <<
|
||||||
|
/CA 1
|
||||||
|
/ca 1
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
/Pattern <<
|
||||||
|
/p5 9 0 R
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 6 0
|
||||||
|
8 0 obj
|
||||||
|
<<
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 5 0
|
||||||
|
9 0 obj
|
||||||
|
<<
|
||||||
|
/Matrix [
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
-1
|
||||||
|
61
|
||||||
|
716
|
||||||
|
]
|
||||||
|
/PatternType 2
|
||||||
|
/Shading <<
|
||||||
|
/ColorSpace /DeviceRGB
|
||||||
|
/Coords [
|
||||||
|
112.5
|
||||||
|
-900
|
||||||
|
112.5
|
||||||
|
900
|
||||||
|
]
|
||||||
|
/Domain [
|
||||||
|
-6
|
||||||
|
6
|
||||||
|
]
|
||||||
|
/Extend [
|
||||||
|
false
|
||||||
|
false
|
||||||
|
]
|
||||||
|
/Function 13 0 R
|
||||||
|
/ShadingType 2
|
||||||
|
>>
|
||||||
|
/Type /Pattern
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 18 0
|
||||||
|
10 0 obj
|
||||||
|
<<
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 15 0
|
||||||
|
11 0 obj
|
||||||
|
<<
|
||||||
|
/Length 12 0 R
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
12 0 obj
|
||||||
|
0
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 12 0
|
||||||
|
13 0 obj
|
||||||
|
<<
|
||||||
|
/Bounds [
|
||||||
|
-5
|
||||||
|
-4
|
||||||
|
-3
|
||||||
|
-2
|
||||||
|
-1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
]
|
||||||
|
/Domain [
|
||||||
|
-6
|
||||||
|
6
|
||||||
|
]
|
||||||
|
/Encode [
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
]
|
||||||
|
/FunctionType 3
|
||||||
|
/Functions [
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
15 0 R
|
||||||
|
]
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 17 0
|
||||||
|
14 0 obj
|
||||||
|
<<
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 11 0
|
||||||
|
15 0 obj
|
||||||
|
<<
|
||||||
|
/Bounds [
|
||||||
|
0.5
|
||||||
|
0.5
|
||||||
|
]
|
||||||
|
/Domain [
|
||||||
|
0
|
||||||
|
1
|
||||||
|
]
|
||||||
|
/Encode [
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
]
|
||||||
|
/FunctionType 3
|
||||||
|
/Functions [
|
||||||
|
18 0 R
|
||||||
|
19 0 R
|
||||||
|
20 0 R
|
||||||
|
]
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 13 0
|
||||||
|
16 0 obj
|
||||||
|
<<
|
||||||
|
/Length1 9948
|
||||||
|
/Length 17 0 R
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%QDF: ignore_newline
|
||||||
|
17 0 obj
|
||||||
|
0
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 8 0
|
||||||
|
18 0 obj
|
||||||
|
<<
|
||||||
|
/C0 [
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
]
|
||||||
|
/C1 [
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
]
|
||||||
|
/Domain [
|
||||||
|
0
|
||||||
|
1
|
||||||
|
]
|
||||||
|
/FunctionType 2
|
||||||
|
/N 1
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 9 0
|
||||||
|
19 0 obj
|
||||||
|
<<
|
||||||
|
/C0 [
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0
|
||||||
|
]
|
||||||
|
/C1 [
|
||||||
|
0
|
||||||
|
0
|
||||||
|
1
|
||||||
|
]
|
||||||
|
/Domain [
|
||||||
|
0
|
||||||
|
1
|
||||||
|
]
|
||||||
|
/FunctionType 2
|
||||||
|
/N 1
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Original object ID: 10 0
|
||||||
|
20 0 obj
|
||||||
|
<<
|
||||||
|
/C0 [
|
||||||
|
0
|
||||||
|
0
|
||||||
|
1
|
||||||
|
]
|
||||||
|
/C1 [
|
||||||
|
0
|
||||||
|
0
|
||||||
|
1
|
||||||
|
]
|
||||||
|
/Domain [
|
||||||
|
0
|
||||||
|
1
|
||||||
|
]
|
||||||
|
/FunctionType 2
|
||||||
|
/N 1
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
xref
|
||||||
|
0 21
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000053 00000 n
|
||||||
|
0000000135 00000 n
|
||||||
|
0000000293 00000 n
|
||||||
|
0000000402 00000 n
|
||||||
|
0000000661 00000 n
|
||||||
|
0000000995 00000 n
|
||||||
|
0000001042 00000 n
|
||||||
|
0000001187 00000 n
|
||||||
|
0000001236 00000 n
|
||||||
|
0000001608 00000 n
|
||||||
|
0000001659 00000 n
|
||||||
|
0000001716 00000 n
|
||||||
|
0000001763 00000 n
|
||||||
|
0000002259 00000 n
|
||||||
|
0000002310 00000 n
|
||||||
|
0000002543 00000 n
|
||||||
|
0000002637 00000 n
|
||||||
|
0000002683 00000 n
|
||||||
|
0000002846 00000 n
|
||||||
|
0000003010 00000 n
|
||||||
|
trailer <<
|
||||||
|
/Info 2 0 R
|
||||||
|
/Root 1 0 R
|
||||||
|
/Size 21
|
||||||
|
/ID [<68de518de1319b4dc1c1bfbdee95b02c><68de518de1319b4dc1c1bfbdee95b02c>]
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
3146
|
||||||
|
%%EOF
|
336
test/pdfs/issue14165.pdf
Normal file
336
test/pdfs/issue14165.pdf
Normal file
File diff suppressed because one or more lines are too long
@ -5407,6 +5407,12 @@
|
|||||||
"enableXfa": true,
|
"enableXfa": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "issue14165",
|
||||||
|
"file": "pdfs/issue14165.pdf",
|
||||||
|
"md5": "917850af2a387475b34b00010200897d",
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "scorecard_reduced",
|
{ "id": "scorecard_reduced",
|
||||||
"file": "pdfs/scorecard_reduced.pdf",
|
"file": "pdfs/scorecard_reduced.pdf",
|
||||||
"md5": "aa8ed0827092c963eea64adb718a3806",
|
"md5": "aa8ed0827092c963eea64adb718a3806",
|
||||||
@ -6282,6 +6288,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{ "id": "issue10572",
|
||||||
|
"file": "pdfs/issue10572.pdf",
|
||||||
|
"md5": "48ad69ed106338b3c6845fc7101488b2",
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "issue11931",
|
{ "id": "issue11931",
|
||||||
"file": "pdfs/issue11931.pdf",
|
"file": "pdfs/issue11931.pdf",
|
||||||
"md5": "9ea233037992e1f10280420a49e72845",
|
"md5": "9ea233037992e1f10280420a49e72845",
|
||||||
|
Loading…
Reference in New Issue
Block a user