From 4d8de9164cf634c13fe9aecd0945d0e13ee8e23e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20Am=C3=A9rico?= Date: Fri, 15 Nov 2019 22:56:10 -0300 Subject: [PATCH] Fix gradient with multiple stops (#1045) --- lib/gradient.js | 9 +++-- tests/unit/gradient.spec.js | 76 +++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 tests/unit/gradient.spec.js diff --git a/lib/gradient.js b/lib/gradient.js index f499f36..8f81e34 100644 --- a/lib/gradient.js +++ b/lib/gradient.js @@ -46,14 +46,15 @@ class PDFGradient { embed(m) { let fn; - if (this.stops.length === 0) { + const stopsLength = this.stops.length; + if (stopsLength === 0) { return; } this.embedded = true; this.matrix = m; // if the last stop comes before 100%, add a copy at 100% - const last = this.stops[this.stops.length - 1]; + const last = this.stops[stopsLength - 1]; if (last[0] < 1) { this.stops.push([1, last[1], last[2]]); } @@ -62,7 +63,7 @@ class PDFGradient { const encode = []; const stops = []; - for (let i = 0, stopsLength = this.stops.length - 1; i < stopsLength; i++) { + for (let i = 0; i < stopsLength - 1; i++) { encode.push(0, 1); if (i + 2 !== stopsLength) { bounds.push(this.stops[i + 1][0]); @@ -81,7 +82,7 @@ class PDFGradient { } // if there are only two stops, we don't need a stitching function - if (stops.length === 1) { + if (stopsLength === 1) { fn = stops[0]; } else { fn = this.doc.ref({ diff --git a/tests/unit/gradient.spec.js b/tests/unit/gradient.spec.js new file mode 100644 index 0000000..79f528e --- /dev/null +++ b/tests/unit/gradient.spec.js @@ -0,0 +1,76 @@ +import PDFDocument from '../../lib/document'; +import { logData } from './helpers'; + +describe('Gradient', function() { + let document; + + beforeEach(() => { + document = new PDFDocument({ + info: { CreationDate: new Date(Date.UTC(2018, 1, 1)) } + }); + }); + + test('Multiple stops', () => { + const docData = logData(document); + const gradient = document.linearGradient(0, 0, 300, 0); + gradient + .stop(0, 'green') + .stop(0.5, 'red') + .stop(1, 'green'); + document.rect(0, 0, 300, 300).fill(gradient); + document.end(); + + expect(docData).toContainChunk([ + '8 0 obj', + `<< +/FunctionType 2 +/Domain [0 1] +/C0 [0 0.501961 0] +/C1 [1 0 0] +/N 1 +>>` + ]); + expect(docData).toContainChunk([ + '9 0 obj', + `<< +/FunctionType 2 +/Domain [0 1] +/C0 [1 0 0] +/C1 [0 0.501961 0] +/N 1 +>>` + ]); + + expect(docData).toContainChunk([ + '10 0 obj', + `<< +/FunctionType 3 +/Domain [0 1] +/Functions [8 0 R 9 0 R] +/Bounds [0.5] +/Encode [0 1 0 1] +>>` + ]); + + expect(docData).toContainChunk([ + '11 0 obj', + `<< +/ShadingType 2 +/ColorSpace /DeviceRGB +/Coords [0 0 300 0] +/Function 10 0 R +/Extend [true true] +>>` + ]); + + expect(docData).toContainChunk([ + '12 0 obj', + `<< +/Type /Pattern +/PatternType 2 +/Shading 11 0 R +/Matrix [1 0 0 -1 0 792] +>>` + ]); + }); +});