kagof / intellij-pokemon-progress

A Pokémon themed progress bar for IntelliJ IDEA.
https://plugins.jetbrains.com/plugin/15090-pokemon-progress
MIT License
192 stars 21 forks source link

svg support #48

Closed kings1990 closed 6 months ago

kings1990 commented 3 years ago

The icon is too fuzzy! svg dynamic pic support?

kagof commented 3 years ago

I'm definitely not against giving this a go, but it will be quite a bit of work and require some investigation. Some initial things that spring to mind for me are:

  1. I don't draw the sprites myself; finding a good way to convert from pixel art PNGs to SVGs. At a glance I see https://codepen.io/shshaw/pen/XbxvNj, will have to investigate to see if it or other tools work well
  2. does IntelliJ support animated SVGs?
  3. script to migrate existing sprites to .svg format

I'll try looking into this when I have some free time

kagof commented 3 years ago

Here's a little update on the current state of SVG support for this plugin, mainly for me to keep track. The whole process has been a massive yak shaving exercise for me, but it has been fun and I've learned a lot! Currently none of the code mentioned below has been pushed, however I will be pushing a feature branch for this shortly.

Sprite conversion

I've written a CLI in Typescript to convert from pixel art PNGs/GIFs/JPEGs to SVGs that works quite nicely. I'll make it available on npm & Github soon, as it could actually be useful for people in contexts other than this. It should be pretty simple to write a script using it to replace the existing editSprite.sh script.

IntelliJ/Java integration

Animation support

Animated SVGs are not easily supported, which should be no surprise given Java seems to barely even support animated gifs (loading an animated gif via ImageIO.read loses the animation info, but via new ImageIcon(URL) does keep the animation, and repaints components as you would want).

SVG animations are also generally not designed for frame based animations, so it will probably be easier to simply work with one SVG per frame and animate it in code. To that end, I started playing with IntelliJ's AnimatedIcon but I struggled to get it to work, and there is very little documentation around how to use it. So in the end, I've created my own AnimatedIcon class that works better for me. It extends ImageIcon, and implements ScalableIcon which makes it a bit more useful than IntelliJ's anyways.

SVG support

Ho boy. Java does not natively support SVGs.

I've added the Twelvemonkeys imageio-batik module, which allows loading of SVGs into BufferedImages using ImageIO::read. However Since the SVG is converted in to a rasterized image in this process, it does not scale nicely, as scaling is done by directly scaling this rasterized image.

I think I'll need to integrate directly with Apache Batik instead, so that I can do scaling before rasterizing. Currently, I'm thinking of doing something along the lines of extending/wrapping BufferedImage and holding onto the original SVG info in it. Then I can override the getScaledInstance method so it scales the SVG and re-rasterizes it. Or perhaps I should instead implement a RenderableImage. Another option would be to change my AnimatedIcon to AnimatedSvgIcon and not extend ImageIcon, then just hold onto the SVG info & implement the paintIcon method myself.

There's also a few different SVG libraries I need to look into a bit more. In addition to Batik, I am aware of JFreeSVG (however it appears to be more to do with writing SVGs than reading them) and svgSalamander.

I've looked into svgSalamnder, and it seems it has something that will work for me. I should be able to use SVGIcon or create something similar based on it. This is good, because Batik is massive and I wanted to avoid including it if at all possible.

Remaining hurdles

Benefits

kagof commented 6 months ago

Changing the sprites to SVGs has no real effect on blurriness, the issue was with scaling the sprites (regardless of format). Since this issue was raised, I've done changes to how the plugin handles scaling, which I think solves the root problem here. SVGs could still potentially be a bit nicer to use just in terms of file size (not needing to have 4 images for each frame of a Pokémon, only 1 SVG file instead), but for now it likely isn't worth it, especially if it requires adding new libraries to the plugin.

kings1990 commented 6 months ago

This is a hard work, I am not sure com.intellij.ui.AnimatedIcon can help you.