SVG toolbar icons are rendered all black

Hello, so I was trying to retouch my toolbar icons (svg) in Illustrator and they turned all black on toolbar.

Considerations:
1- They all worked fine until I edit on illustrator;
2- Even simple openning and saving again (without editing) makes them all black.
3- They always renders fine on illustrator or chrome, only SU is showing them black.
4- I’m running SU18 on Win11

Before editing (works fine in SU):

<svg width="48px" height="48px" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="48" height="48" fill="white" fill-opacity="0.01"/>
<path d="M24 44C29.5228 44 34.5228 41.7614 38.1421 38.1421C41.7614 34.5228 44 29.5228 44 24C44 18.4772 41.7614 13.4772 38.1421 9.85786C34.5228 6.23858 29.5228 4 24 4C18.4772 4 13.4772 6.23858 9.85786 9.85786C6.23858 13.4772 4 18.4772 4 24C4 29.5228 6.23858 34.5228 9.85786 38.1421C13.4772 41.7614 18.4772 44 24 44Z" fill="#2F88FF" stroke="black" stroke-width="4" stroke-linejoin="round"/>
<path d="M24 28.6249V24.6249C27.3137 24.6249 30 21.9386 30 18.6249C30 15.3112 27.3137 12.6249 24 12.6249C20.6863 12.6249 18 15.3112 18 18.6249" stroke="white" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24 37.6249C25.3807 37.6249 26.5 36.5056 26.5 35.1249C26.5 33.7442 25.3807 32.6249 24 32.6249C22.6193 32.6249 21.5 33.7442 21.5 35.1249C21.5 36.5056 22.6193 37.6249 24 37.6249Z" fill="white"/>
</svg>

After opening and saving (all black in SU):

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#FFFFFF;fill-opacity:1.000000e-02;}
	.st1{fill:#2F88FF;stroke:#000000;stroke-width:4;stroke-linejoin:round;}
	.st2{fill:none;stroke:#FFFFFF;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;}
	.st3{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
</style>
<rect class="st0" width="48" height="48"/>
<path class="st1" d="M24,44c5.5,0,10.5-2.2,14.1-5.9C41.8,34.5,44,29.5,44,24s-2.2-10.5-5.9-14.1C34.5,6.2,29.5,4,24,4
	S13.5,6.2,9.9,9.9C6.2,13.5,4,18.5,4,24s2.2,10.5,5.9,14.1C13.5,41.8,18.5,44,24,44z"/>
<path class="st2" d="M24,28.6v-4c3.3,0,6-2.7,6-6s-2.7-6-6-6s-6,2.7-6,6"/>
<path class="st3" d="M24,37.6c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5s-2.5,1.1-2.5,2.5S22.6,37.6,24,37.6z"/>
</svg>

We can clearly see its different but I cant tell what makes it not to work.
Theres just too many variables for me to solve by try-error method. (color profiles, svg profiles, encodings)

Anyone:

  • has experienced it?
  • knows in what configs it should be saved for it to work on SU?
  • knows why it doesnt work?
  • knows of some workaround? manual editing method?
  • suggests another svg editor or aproach?

Thanks :v:

Icons.zip (1.3 KB)

I’d guess that you need to add

width="48px" height="48px"

to the svg tag in the ‘not working’ example.

Try it and let us know what happens

1 Like

Thanks for reply but saddly it changed nothing :confused:

Taking a closer look at others svg that works, none of them uses the “style” tag:

<style type="text/css">
	.st0{fill:#2F88FF;stroke:#000000;stroke-width:4;stroke-linejoin:round;}
	.st1{fill:none;stroke:#FFFFFF;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;}
	.st2{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
</style>

Seem to me, at my layman view, that its having a bad time associating the style to the elements.

Now I’m looking if theres a config to disable such styles and assign colors directly.

Thanks anyways :v:

Got it! :tada:

Those are the main params to be aware:


CSS Properties set to “Style Attributes” makes the colors to be assigned directly, like I said.
Its not the lightest format but seems to have less compatibility issues.

Thanks sWilliams :v:

3 Likes

In order to best fit low-DPI monitors it’s best to create the icons in the low-DPI sizes: 32x32 and 24x24. Then you have better control over how they appear on low and high DPI monitors.

Interesting, didn’t thought it could be a thing since it’s svg.
But I checked SU18 icons and they’r mostly 24px so okay.

The thing is, actually that method I’ve shown above don’t give us a “width” and “height” tag :confused:
I’ll experiment with other saving configs, I’ll share it here if I get something.

Thanks :v:


Edit:
I just manually added this to the "<svg " tag and it works just fine.

width="24px" height="24px"

Obs: icons using “stroke-width” property may get bugged (thick borders), so I also reduced it (from 4px to 1px in my case)

I’d like to jump in here and leave a few comments about the initial problem.

According to the SVG 1.1 Specification, and here I quote, “support for inline style sheets using the ‘style’ element and ‘style’ was not required. In SVG 2, these are required.”

Which explains why this example with a ‘style’ element does not work:

<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
  <style>
    circle {
      fill: gold;
      stroke: maroon;
      stroke-width: 2px;
    }
  </style>
  <circle class="abc" cx="5" cy="5" r="4"/>
</svg>

As you have discovered, an example with the ‘style’ attribute does work.

 <svg viewBox="0 0 100 60" xmlns="http://www.w3.org/2000/svg">
  <rect
    width="80"
    height="40"
    x="10"
    y="10"
    style="fill: skyblue; stroke: cadetblue; stroke-width: 2;" />
</svg>

I’m uncertain about what will be supported in future releases, but can add that for C++ developers Microsoft doesn’t appear to be in a hurry to add support for the ‘style’ element (see link).

1 Like

hey thx for contribuiting
Thats good to know, so its about svg version.

Which makes me wonder…

What version SU has been using? is there docs about it?
How it effects mac users? (cant test)
If SU upgrades to svg2 or other would it break old icons?! (since now it requires ‘style’ element)
if so, would there be an easy/smart way to make it work SU17+? without having to:

if Sketchup.version > 2022
   #use SVG2
else
   #use SVG1.1
end

Hopefully SU would just support both :man_shrugging:


Edit: I missed the ball here.
SVG1.1 - supports ‘style’ element and ‘style’ attribute not required.
SVG2 - supports ‘style’ element and ‘style’ attribute is required.
so it wouldnt be a backwards compatib problem.

Mac SketchUp uses pdf for icons, not svg, so it won’t see that specific issue.

What about extensions? I’m using svg icons on mine.
Toolbar API states only .png on its examples :l
Tell me svg works on SU(mac) too, its just not the standard :pray:

Aerilius has also stated some useful info about it.
but it was for win only, and 2019 so not sure how to proceed.
Will svg1.1 work SU17+ on Win and Mac? is it future proof? (about extensions)

NO.

As stated …

I also wondered how on Windows I could save icons for Mac use, so I asked and got a good answer (which I never imagined could be so easy) …

1 Like

Thanks :v:

I think I’ll just stay at .png then so no worries about versions and/or platforms.
Easier to draw and easier to code.

I was using 32x32 and 64x64. Worked fine.
Let me know if there is better resolutions to use. (24x24 - 48x48?)

Which is why your SVG files should probably always include the <!DOCTYPE> declaration that indicates what SVG version the parser should use to read the file.

As long as you use ver 1.1 and stick to style attributes and stay away from inline stylesheets using a <style> element.

But, again it all depends upon whether SketchUp stays with the limited external library it is using now.

Not really. Raster icons do not scale well with display scaling. And coding for vector icons is not much more work at all.

# Test for vector icon support (v2016+) ...
if defined?(::Sketchup::Model::VERSION_2016) # use vector icons
  type = Sketchup.platform == :platform_osx ? 'pdf' : 'svg'
  icon_path = File.join(__dir__,'images',"vector_icon.#{type}")
  cmd.small_icon= icon_path
  cmd.large_icon= icon_path
else # use raster
  type = 'png'
  cmd.small_icon= File.join(__dir__,'images',"small_icon.#{type}")
  cmd.large_icon= File.join(__dir__,'images',"large_icon.#{type}")
end

NOTE: I’m using that fact that the ::Layout module was not defined until SketchUp 2016 as the test for raster vs vector.
CORRECTION: It was the LayOut C API that was released with v16. The ::Layout Ruby API did not come out till 2018. (Changing the above test to Sketchup::Axes.)
CORRECTION (2): The consensus of comments below are for using a version check, so I’m changing the above example, once again (just so future readers seeing only the example are not led astray.)


Thomas just answered this …

2 Likes

Great! thanks, gonna implement it.

We can make it a method so no need to re code for all toolbar icons: (yet to test)

#Saved icon files would be:
#- Help.vec.pdf
#- Help.vec.svg
#- Help.sm.png
#- Help.lr.png

module Taxsola
  def define_icon(item, name, Tooltip, Status_bar, Menu_text)
    # Test for vector icon support (v2016+) ...
    if defined?(::Sketchup::Model::VERSION_2016)
      #use vector icons
      type = Sketchup.platform == :platform_osx ? 'pdf' : 'svg'
      icon_path = File.join(__dir__,'images',"#{name}.vec.#{type}")
      item.small_icon= icon_path
      item.large_icon= icon_path
    else
      #use raster
      type = 'png'
      item.small_icon= File.join(__dir__,'images',"#{name}.sm.#{type}")
      item.large_icon= File.join(__dir__,'images',"#{name}.lr.#{type}")
    end

    item.tooltip = Tooltip
    item.status_bar_text = Status_bar
    item.menu_text = Menu_text
  end


toolbar = UI::Toolbar.new "Test"
cmd = UI::Command.new("Test") {UI.messagebox "Hello World"}

Taxsola.define_icon(cmd, "Help", "Tooltip", "Status_bar", "Menu_text") #Define all in one

toolbar = toolbar.add_item cmd
toolbar.show
end
2 Likes

Sure, and it “travels well” … ie, becomes a library method you can use for multiple extensions.

1 Like

Vector images still have to be rendered to pixels. So when you create vector images it’s worth using a pixel grid to ensure that shapes line up precisely on the pixel grid. At least if you are using shapes that have horizontal or vertical lines. Otherwise you’ll find that edges can look blurry when the anti-aliasing kicks in.

The documentation for UI::Command explains in better details: Class: UI::Command — SketchUp Ruby API Documentation

If you use bitmaps then they won’t scale on high DPI monitors.

That’s what I do for my own extensions as well.

Do you support anything older than SU2017? If you don’t then there’s no need to include bitmap versions and logic.

That’s some confusing logic, using the Layout namespace to determine to use vector images or not. I like detecting features whenever possible, but in this case I’d argue it’s clearer to do a version check: if Sketchup.version.to_i >= 17. Vector support has no relationship with LayOut.

He got this from me. The desire was to determine when vector icon support began which was v16. (Not >= 17) I however made a mistake … ::Layout in Ruby was defined with the 2018 release. I confused this with the Layout C API which was released in v16. (Again, as I’ve said before, having C API features listed in amongst the Ruby API Release Notes is confusing.)

So what I was trying to do is “duck typing” the ObjectSpace. For v16 we could better test for the existence of the Sketchup::Axes class which definitely was defined first with the 2016 release.

@Taxsola I corrected the example above and added a code comment to explain the conditional.

I’d rather do the define check, (which I believe is fast compared to calling 3 methods) to compare against a major version number.

I would argue that neither pattern explains the “why” of the test is without a code comment.


If the API had defined a boolean UI.vector_icon_support? for the 16.0 release we’d have something self explanatory for a “duck type” test …

if UI.respond_to?(:vector_icon_support?)

… too late now. So we use other means for our test.

1 Like

I suppose another valid test could be …

if defined?(::Sketchup::Model::VERSION_2016)
  # use vector
else
  # use raster
end

Makes sense now, thanks

No I’m about SU17+, good to know. (its nice to share all versions practices tho)

Rlly smart to check released features :100:
Same docs also states “Sketchup.version_number” to have been fixed in 2016, it was returning wrong values. So I guess it would be another reason to avoid using it for check purposes, right?
or was it a rlly different method? was “Sketchup.version” a thing back then?

I’m also gonna change my code to use “Sketchup::Axes” as u did. :v: