Skip to content

Commit e6658ed

Browse files
committed
Transform gradients in strokes
1 parent f472eb5 commit e6658ed

File tree

1 file changed

+51
-33
lines changed

1 file changed

+51
-33
lines changed

src/transform-applier.js

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -505,14 +505,42 @@ const _parseUrl = (value, windowRef) => {
505505
*/
506506
const transformStrokeWidths = function (svgTag, windowRef, bboxForTesting) {
507507
const inherited = Matrix.identity();
508-
const applyTransforms = (element, matrix, strokeWidth, fill) => {
508+
509+
const makeTransformedGradient = (gradientId, element, matrix) => {
510+
const doc = windowRef.document;
511+
// Need path bounds to transform gradient
512+
const svgSpot = doc.createElement('span');
513+
let bbox;
514+
if (bboxForTesting) {
515+
bbox = bboxForTesting;
516+
} else {
517+
try {
518+
doc.body.appendChild(svgSpot);
519+
const svg = SvgElement.set(windowRef.document.createElementNS(SvgElement.svg, 'svg'));
520+
const path = SvgElement.set(windowRef.document.createElementNS(SvgElement.svg, 'path'));
521+
path.setAttribute('d', element.attributes.d.value);
522+
svg.appendChild(path);
523+
svgSpot.appendChild(svg);
524+
// Take the bounding box.
525+
bbox = svg.getBBox();
526+
} finally {
527+
// Always destroy the element, even if, for example, getBBox throws.
528+
doc.body.removeChild(svgSpot);
529+
}
530+
}
531+
532+
return _createGradient(gradientId, svgTag, bbox, matrix);
533+
};
534+
535+
const applyTransforms = (element, matrix, strokeWidth, fill, stroke) => {
509536
if (_isContainerElement(element)) {
510537
// Push fills and stroke width down to leaves
511538
if (element.attributes['stroke-width']) {
512539
strokeWidth = element.attributes['stroke-width'].value;
513540
}
514-
if (element.attributes && element.attributes.fill) {
515-
fill = element.attributes.fill.value;
541+
if (element.attributes) {
542+
if (element.attributes.fill) fill = element.attributes.fill.value;
543+
if (element.attributes.stroke) stroke = element.attributes.stroke.value;
516544
}
517545

518546
// If any child nodes don't take attributes, leave the attributes
@@ -522,56 +550,42 @@ const transformStrokeWidths = function (svgTag, windowRef, bboxForTesting) {
522550
element.childNodes[i],
523551
Matrix.compose(matrix, _parseTransform(element)),
524552
strokeWidth,
525-
fill
553+
fill,
554+
stroke
526555
);
527556
}
528557
element.removeAttribute('transform');
529558
element.removeAttribute('stroke-width');
530559
element.removeAttribute('fill');
560+
element.removeAttribute('stroke');
531561
} else if (_isPathWithTransformAndStroke(element, strokeWidth)) {
532562
if (element.attributes['stroke-width']) {
533563
strokeWidth = element.attributes['stroke-width'].value;
534564
}
535-
if (element.attributes.fill) {
536-
fill = element.attributes.fill.value;
537-
}
565+
if (element.attributes.fill) fill = element.attributes.fill.value;
566+
if (element.attributes.stroke) stroke = element.attributes.stroke.value;
538567
matrix = Matrix.compose(matrix, _parseTransform(element));
539568
if (Matrix.toString(matrix) === Matrix.toString(Matrix.identity())) {
540569
element.removeAttribute('transform');
541570
element.setAttribute('stroke-width', strokeWidth);
542571
if (fill) element.setAttribute('fill', fill);
572+
if (stroke) element.setAttribute('stroke', stroke);
543573
return;
544574
}
545575

546576
// Transform gradient
547-
const gradientId = _parseUrl(fill, windowRef);
548-
if (gradientId) {
549-
const doc = windowRef.document;
550-
// Need path bounds to transform gradient
551-
const svgSpot = doc.createElement('span');
552-
let bbox;
553-
if (bboxForTesting) {
554-
bbox = bboxForTesting;
555-
} else {
556-
try {
557-
doc.body.appendChild(svgSpot);
558-
const svg = SvgElement.set(windowRef.document.createElementNS(SvgElement.svg, 'svg'));
559-
const path = SvgElement.set(windowRef.document.createElementNS(SvgElement.svg, 'path'));
560-
path.setAttribute('d', element.attributes.d.value);
561-
svg.appendChild(path);
562-
svgSpot.appendChild(svg);
563-
// Take the bounding box.
564-
bbox = svg.getBBox();
565-
} finally {
566-
// Always destroy the element, even if, for example, getBBox throws.
567-
doc.body.removeChild(svgSpot);
568-
}
569-
}
570-
571-
const newRef = _createGradient(gradientId, svgTag, bbox, matrix);
577+
const fillGradientId = _parseUrl(fill, windowRef);
578+
if (fillGradientId) {
579+
const newRef = makeTransformedGradient(fillGradientId, element, matrix);
572580
if (newRef) fill = newRef;
573581
}
574582

583+
const strokeGradientId = _parseUrl(stroke, windowRef);
584+
if (strokeGradientId) {
585+
const newRef = makeTransformedGradient(strokeGradientId, element, matrix);
586+
if (newRef) stroke = newRef;
587+
}
588+
575589
// Transform path data
576590
element.setAttribute('d', _transformPath(element.attributes.d.value, matrix));
577591
element.removeAttribute('transform');
@@ -580,14 +594,18 @@ const transformStrokeWidths = function (svgTag, windowRef, bboxForTesting) {
580594
const matrixScale = _getScaleFactor(matrix);
581595
element.setAttribute('stroke-width', _quadraticMean(matrixScale.x, matrixScale.y) * strokeWidth);
582596
if (fill) element.setAttribute('fill', fill);
597+
if (stroke) element.setAttribute('stroke', stroke);
583598
} else if (_isGraphicsElement(element)) {
584-
// Push stroke width and fill down to leaves
599+
// Push stroke width, fill, and stroke down to leaves
585600
if (strokeWidth && !element.attributes['stroke-width']) {
586601
element.setAttribute('stroke-width', strokeWidth);
587602
}
588603
if (fill && !element.attributes.fill) {
589604
element.setAttribute('fill', fill);
590605
}
606+
if (stroke && !element.attributes.stroke) {
607+
element.setAttribute('stroke', stroke);
608+
}
591609

592610
// Push transform down to leaves
593611
matrix = Matrix.compose(matrix, _parseTransform(element));

0 commit comments

Comments
 (0)