Skip to content

Commit cef97fb

Browse files
authored
add context2d setLineDash, getLineDash and lineDashOffset. (parallax#3169)
1 parent 99d4b95 commit cef97fb

File tree

7 files changed

+190
-5
lines changed

7 files changed

+190
-5
lines changed

src/jspdf.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2001,7 +2001,7 @@ function jsPDF(options) {
20012001
font: font,
20022002
out: out,
20032003
newObject: newObject,
2004-
putStream: putStream,
2004+
putStream: putStream
20052005
});
20062006

20072007
if (font.isAlreadyPutted !== true) {

src/libs/FileSaver.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ var saveAs =
9090
/* noop */
9191
}
9292
: // Use download attribute first if possible (#193 Lumia mobile) unless this is a native app
93-
(typeof HTMLAnchorElement !== "undefined" && "download" in HTMLAnchorElement.prototype)
93+
typeof HTMLAnchorElement !== "undefined" &&
94+
"download" in HTMLAnchorElement.prototype
9495
? function saveAs(blob, name, opts) {
9596
var URL = _global.URL || _global.webkitURL;
9697
var a = document.createElement("a");

src/libs/pdfname.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
*/
66
function toPDFName(str) {
77
// eslint-disable-next-line no-control-regex
8-
if(/[^\u0000-\u00ff]/.test(str)){ // non ascii string
9-
throw new Error('Invalid PDF Name Object: ' + str + ', Only accept ASCII characters.');
8+
if (/[^\u0000-\u00ff]/.test(str)) {
9+
// non ascii string
10+
throw new Error(
11+
"Invalid PDF Name Object: " + str + ", Only accept ASCII characters."
12+
);
1013
}
1114
var result = "",
1215
strLength = str.length;

src/modules/cell.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,10 @@ import { jsPDF } from "../jspdf.js";
442442
});
443443
}
444444

445-
if (autoSize || (Array.isArray(headers) && typeof headers[0] === "string")) {
445+
if (
446+
autoSize ||
447+
(Array.isArray(headers) && typeof headers[0] === "string")
448+
) {
446449
var headerName;
447450
for (i = 0; i < headerNames.length; i += 1) {
448451
headerName = headerNames[i];

src/modules/context2d.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ import {
5151
this.currentPoint = ctx.currentPoint || new Point();
5252
this.miterLimit = ctx.miterLimit || 10.0;
5353
this.lastPoint = ctx.lastPoint || new Point();
54+
this.lineDashOffset = ctx.lineDashOffset || 0.0;
55+
this.lineDash = ctx.lineDash || [];
5456

5557
this.ignoreClearRect =
5658
typeof ctx.ignoreClearRect === "boolean" ? ctx.ignoreClearRect : true;
@@ -641,6 +643,33 @@ import {
641643
}
642644
});
643645

646+
/**
647+
* A float specifying the amount of the line dash offset. The default value is 0.0.
648+
*
649+
* @name lineDashOffset
650+
* @default 0.0
651+
*/
652+
Object.defineProperty(this, "lineDashOffset", {
653+
get: function() {
654+
return this.ctx.lineDashOffset;
655+
},
656+
set: function(value) {
657+
this.ctx.lineDashOffset = value;
658+
setLineDash.call(this);
659+
}
660+
});
661+
662+
// Not HTML API
663+
Object.defineProperty(this, "lineDash", {
664+
get: function() {
665+
return this.ctx.lineDash;
666+
},
667+
set: function(value) {
668+
this.ctx.lineDash = value;
669+
setLineDash.call(this);
670+
}
671+
});
672+
644673
// Not HTML API
645674
Object.defineProperty(this, "ignoreClearRect", {
646675
get: function() {
@@ -652,6 +681,32 @@ import {
652681
});
653682
};
654683

684+
/**
685+
* Sets the line dash pattern used when stroking lines.
686+
* @name setLineDash
687+
* @function
688+
* @description It uses an array of values that specify alternating lengths of lines and gaps which describe the pattern.
689+
*/
690+
Context2D.prototype.setLineDash = function(dashArray) {
691+
this.lineDash = dashArray;
692+
};
693+
694+
/**
695+
* gets the current line dash pattern.
696+
* @name getLineDash
697+
* @function
698+
* @returns {Array} An Array of numbers that specify distances to alternately draw a line and a gap (in coordinate space units). If the number, when setting the elements, is odd, the elements of the array get copied and concatenated. For example, setting the line dash to [5, 15, 25] will result in getting back [5, 15, 25, 5, 15, 25].
699+
*/
700+
Context2D.prototype.getLineDash = function() {
701+
if (this.lineDash.length % 2) {
702+
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getLineDash#return_value
703+
return this.lineDash.concat(this.lineDash);
704+
} else {
705+
// The copied value is returned to prevent contamination from outside.
706+
return this.lineDash.slice();
707+
}
708+
};
709+
655710
Context2D.prototype.fill = function() {
656711
pathPreProcess.call(this, "fill", false);
657712
};
@@ -1105,6 +1160,8 @@ import {
11051160
this.lineCap = this.ctx.lineCap;
11061161
this.lineWidth = this.ctx.lineWidth;
11071162
this.lineJoin = this.ctx.lineJoin;
1163+
this.lineDash = this.ctx.lineDash;
1164+
this.lineDashOffset = this.ctx.lineDashOffset;
11081165
}
11091166
};
11101167

@@ -2383,4 +2440,32 @@ import {
23832440
Math.round(maxy - miny)
23842441
);
23852442
};
2443+
2444+
var getPrevLineDashValue = function(lineDash, lineDashOffset) {
2445+
return JSON.stringify({
2446+
lineDash: lineDash,
2447+
lineDashOffset: lineDashOffset
2448+
});
2449+
};
2450+
2451+
var setLineDash = function() {
2452+
// Avoid unnecessary line dash declarations.
2453+
if (
2454+
!this.prevLineDash &&
2455+
!this.ctx.lineDash.length &&
2456+
!this.ctx.lineDashOffset
2457+
) {
2458+
return;
2459+
}
2460+
2461+
// Avoid unnecessary line dash declarations.
2462+
const nextLineDash = getPrevLineDashValue(
2463+
this.ctx.lineDash,
2464+
this.ctx.lineDashOffset
2465+
);
2466+
if (this.prevLineDash !== nextLineDash) {
2467+
this.pdf.setLineDash(this.ctx.lineDash, this.ctx.lineDashOffset);
2468+
this.prevLineDash = nextLineDash;
2469+
}
2470+
};
23862471
})(jsPDF.API);

test/reference/lineDash.pdf

3.51 KB
Binary file not shown.

test/specs/context2d.spec.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,99 @@ describe("Context2D: standard tests", () => {
485485
comparePdf(doc.output(), "moveTo_lineTo_stroke_fill.pdf", "context2d");
486486
});
487487

488+
it("context2d: setLineDash(), lineDashOffset", () => {
489+
var doc = new jsPDF({
490+
orientation: "p",
491+
unit: "pt",
492+
format: "a4",
493+
floatPrecision: 2
494+
});
495+
var ctx = doc.context2d;
496+
497+
var y = 20;
498+
var pad = 20;
499+
500+
ctx.lineWidth = 5;
501+
ctx.beginPath();
502+
ctx.moveTo(20, y);
503+
ctx.lineTo(200, y);
504+
ctx.stroke();
505+
y += pad;
506+
ctx.save();
507+
ctx.beginPath();
508+
ctx.setLineDash([10, 20]);
509+
ctx.lineDashOffset = 10;
510+
ctx.moveTo(20, y);
511+
ctx.lineTo(200, y);
512+
ctx.stroke();
513+
y += pad;
514+
ctx.beginPath();
515+
ctx.setLineDash([]);
516+
ctx.lineDashOffset = 0;
517+
ctx.moveTo(20, y);
518+
ctx.lineTo(200, y);
519+
ctx.stroke();
520+
y += pad;
521+
ctx.beginPath();
522+
ctx.setLineDash([10, 20]);
523+
ctx.lineDashOffset = 10;
524+
ctx.moveTo(20, y);
525+
ctx.lineTo(200, y);
526+
ctx.stroke();
527+
y += pad;
528+
ctx.save();
529+
ctx.beginPath();
530+
ctx.setLineDash([]);
531+
ctx.lineDashOffset = 0;
532+
ctx.moveTo(20, y);
533+
ctx.lineTo(200, y);
534+
ctx.stroke();
535+
y += pad;
536+
ctx.restore();
537+
ctx.beginPath();
538+
ctx.moveTo(20, y);
539+
ctx.lineTo(200, y);
540+
ctx.stroke();
541+
y += pad;
542+
ctx.save();
543+
ctx.beginPath();
544+
ctx.moveTo(20, y);
545+
ctx.lineTo(200, y);
546+
ctx.stroke();
547+
y += pad;
548+
ctx.restore();
549+
ctx.beginPath();
550+
ctx.moveTo(20, y);
551+
ctx.lineTo(200, y);
552+
ctx.stroke();
553+
y += pad;
554+
ctx.restore();
555+
ctx.beginPath();
556+
ctx.moveTo(20, y);
557+
ctx.lineTo(200, y);
558+
ctx.stroke();
559+
560+
comparePdf(doc.output(), "lineDash.pdf", "context2d");
561+
});
562+
563+
it("context2d: getLineDash()", () => {
564+
var doc = new jsPDF({
565+
orientation: "p",
566+
unit: "pt",
567+
format: "a4",
568+
floatPrecision: 2
569+
});
570+
var ctx = doc.context2d;
571+
572+
expect(ctx.getLineDash()).toEqual([]);
573+
574+
ctx.setLineDash([1, 2]);
575+
expect(ctx.getLineDash()).toEqual([1, 2]);
576+
577+
ctx.setLineDash([1, 2, 3]);
578+
expect(ctx.getLineDash()).toEqual([1, 2, 3, 1, 2, 3]);
579+
});
580+
488581
it("context2d: textBaseline", () => {
489582
var doc = new jsPDF({
490583
orientation: "p",

0 commit comments

Comments
 (0)