Repository: flutter
Issue: [flutter_svg] Stroke width looks off
Labels: package,p: flutter_svg

_Imported from https://github.com/dnfield/flutter_svg/issues/176_

Original report by @DenisShakinov on Jun 14, 2019

I have a simple svg file as follows:

```
<svg xmlns="http://www.w3.org/2000/svg" width="74" height="74" viewBox="0 0 74 74">
    <defs>
        <linearGradient id="a" x1="0%" y1="0%" y2="100%">
            <stop offset="0%" stop-color="#FF7805"/>
            <stop offset="100%" stop-color="#FF0202"/>
        </linearGradient>
    </defs>
    <rect width="68" height="68" fill="none" fill-rule="evenodd" stroke="url(#a)" stroke-width="4.2" rx="29" transform="translate(3 3)"/>
</svg>
```
In desktop svg viewer it renders like this:
![image](https://user-images.githubusercontent.com/2579593/59508460-b39b4400-8eb6-11e9-8e18-48ae7189c427.png)
but in my flutter application it renders like a very thin line (gradients are correct though):
![image](https://user-images.githubusercontent.com/2579593/59508594-345a4000-8eb7-11e9-92c5-03a96b9b6fc0.png)


---
Comment by @dnfield on Jun 14, 2019
What if you remove the width/height attributds from the svg element?

---
Comment by @DenisShakinov on Jun 14, 2019
Nothing changed.

---
Comment by @dnfield on Jun 14, 2019
What version are you using?

---
Comment by @DenisShakinov on Jun 14, 2019
Since I'm using stable Flutter channel, the flutter_svg version is ^0.12.4+2

---
Comment by @thisisgit on Jul 9, 2020
I'm facing the same issue and looks like it's because passing width and height arguments to **SvgPicture** just scales up/down the original svg asset.

For example, here's a sample close icon in svg:
```
<svg xmlns="http://www.w3.org/2000/svg" width="15.414" height="15.414" viewBox="0 0 15.414 15.414">
  <g transform="translate(0.707 0.707)">
    <line x2="14" y2="14" stroke="#000000" stroke-linecap="round" stroke-width="1"/>
    <line x2="14" y2="14" transform="translate(14) rotate(90)" stroke="#000000" stroke-linecap="round" stroke-width="1"/>
  </g>
</svg>
```
Note that both lines have stroke width of 1.
And it looks like this when rendered:
<img width="41" alt="close" src="https://user-images.githubusercontent.com/13231564/86993553-3fc58b00-c1df-11ea-9a75-2b6de93b6318.png">

I was expecting lines to have stroke width of 1 even width and height of the image changes. So with the following code:
```
Row(
              crossAxisAlignment: CrossAxisAlignment.end,
              children: [
                SvgPicture.asset(
                  'assets/close_icon.svg',
                  width: 16,
                  height: 16,
                ),
                SizedBox(
                  width: 16.0,
                ),
                SvgPicture.asset(
                  'assets/close_icon.svg',
                  width: 64.0,
                  height: 64.0,
                )
              ],
            )
```
I expected output to be:
<img width="134" alt="right" src="https://user-images.githubusercontent.com/13231564/86994090-8798e200-c1e0-11ea-8f12-0baec314b5b5.png">

But what rendered was:
<img width="127" alt="uhoh" src="https://user-images.githubusercontent.com/13231564/86994100-92ec0d80-c1e0-11ea-9d34-dfce1f6fb63a.png">

I thought setting width and height value would change the width and height attribute of svg tag. But what it did was to just scale up/down.

Is there any proper way to achieve this or is it a new feature request?
Please correct me if I'm getting this wrong.

@dnfield 

---
Comment by @liri2006 on Dec 16, 2020
Same issue here.

---
Comment by @njovy on May 3, 2021
@dnfield I am having the same issue as well. Is there any workaround for this?
If a stroke refers a linear gradient, then it doesn't render correctly.

---
Comment by @njovy on May 3, 2021
@dnfield The latest version doesn't parse "stroke-width" if a stroke is a linearGradient, can we expect to see a bug fix soon? 

---
Comment by @dnfield on May 3, 2021
I'm not sure I ever got a clear reproduction on this that I could reproduce locally. I can try to look at it again though.

---
Comment by @vishna on May 11, 2021
@thisisgit this is expected behaviour - you need another svg with scaled up values and with width in it that says `1`

---
Comment by @njovy on Jul 29, 2021
@vishna If you look at the flutter svg code, the plugin doesn't parse ```stroke-width``` attribute if a stroke is a linearGradient.

---
Comment by @aytunch on Feb 10, 2022
@njovy I have the exact same problem. There is a `stroke-width` inside a `linearGradient` and it only shows the vector without and width.

Is there a workaround for this? 

---
Comment by @febryardiansyah on Jun 13, 2024
any update for this issue?

---
Comment by @capsulekenny on Nov 1, 2024
Hi All,

This is (in most cases) a misunderstanding in rendering behaviour. Basically, what is happening is the svg is rendered with its default props (in @thisisgit 's example, this is width="15.414" height="15.414" with stroke-width="1") and then scaled via the SvgPicture package.

This package, along with most other packages in other languages, renders the svg at it's original size and then scales to the passed width/height props.

An easy work around is to take the svg as a string and edit all instances of stroke-width at runtime. Fun fact: the SvgImage package can take an entire svg as a string - this is why this method works.

I have attached an example below where I used this method to build an icon widget for use in a component library I'm building. In the example, I have used size tokens but these can be replaced with any double.

```dart
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter/services.dart' show rootBundle;
import '/abstracts/dimension/size_tokens.dart';

class AcaraIcon extends StatefulWidget {
  final String iconPath;
  final Color? color;
  final double size; // customizable width & height
  final double strokeWidth; // customizable stroke width

  const AcaraIcon({
    Key? key,
    required this.iconPath,
    this.color,
    this.size = size24,
    this.strokeWidth = stroke2, // Default stroke width
  }) : super(key: key);

  @override
  AcaraIconState createState() => AcaraIconState();
}

// State used to fetch svg as string at runtime
class AcaraIconState extends State<AcaraIcon> {
  String? svgString;

  @override
  void initState() {
    super.initState();
    loadSvgWithCustomStroke(widget.strokeWidth);
  }

  Future<void> loadSvgWithCustomStroke(double strokeWidth) async {
    // Load the SVG file as a string
    String svgData = await rootBundle.loadString(widget
        .iconPath); //if optimisation errors occur, check this implementation. So far, no perfrormance issues

    // Replace the stroke-width dynamically
    svgData = svgData.replaceAll(
      RegExp(r'stroke-width="[^"]*"'),
      'stroke-width="$strokeWidth"',
    );

    setState(() {
      svgString = svgData;
    });
  }

  @override
  Widget build(BuildContext context) {
    // Render the SVG directly from asset initially; switch to svgString when ready
    return svgString == null
        ? SvgPicture.asset(
            widget.iconPath,
            width: widget.size,
            height: widget.size,
            colorFilter: widget.color != null
                ? ColorFilter.mode(widget.color!, BlendMode.srcIn)
                : null,
          )
        // Render the updated string with new stroke width
        : SvgPicture.string(
            svgString!, // this is raw svg as string
            width: widget.size,
            height: widget.size,
            colorFilter: widget.color != null
                ? ColorFilter.mode(widget.color!, BlendMode.srcIn)
                : null,
          );
  }
}

``` 

Context: I also have a design background and discovered this difference in behaviour between programatic envs vs. design envs. Another fun fact: When using programs like Figma, the software renders the path/shape at its literal size meaning if you were to set size to any other double, the stroke stays at its literal value (in the above case "1") - a way to get around this is to use scale tools so you know how the icon will behave when scaled.

Hope this helped!