2 changed files with 246 additions and 0 deletions
@ -0,0 +1,147 @@
|
||||
package com.fr.base.svg; |
||||
|
||||
import com.fr.general.IOUtils; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.bridge.StableFactory; |
||||
import com.fr.stable.fun.ResourcePathTransformer; |
||||
import com.fr.stable.plugin.ExtraClassManagerProvider; |
||||
|
||||
import javax.swing.*; |
||||
import java.util.Arrays; |
||||
import java.util.HashSet; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* 主要是用来读取svgIcon的工具类 |
||||
* @author Yvan |
||||
* @version 10.0 |
||||
* Created by Yvan on 2020/12/23 |
||||
*/ |
||||
public class IconUtils { |
||||
|
||||
private static final String ICON_SUFFIX_SVG = ".svg"; |
||||
private static final String ICON_SUFFIX_PNG = ".png"; |
||||
private static final String ICON_SUFFIX_GIF = ".gif"; |
||||
private static final String SUFFIX_SEPARATOR = "."; |
||||
|
||||
public static final String ICON_TYPE_NORMAL= "_normal.svg"; |
||||
public static final String ICON_TYPE_DISABLED= "_disabled.svg"; |
||||
public static final String ICON_TYPE_PRESSED= "_pressed.svg"; |
||||
|
||||
|
||||
/** |
||||
* 可以读取SVG图标或者普通图标,并且可以读取不带扩展名的文件 |
||||
* 不带扩展名时以svg优先、其次png,最后gif |
||||
* @param resource 图片路径 |
||||
* @return 图标 |
||||
*/ |
||||
public static Icon readIcon(String resource) { |
||||
// 判断是否有.XXX文件后缀
|
||||
if (resource.contains(SUFFIX_SEPARATOR)) { |
||||
// 判断是否以.svg结尾
|
||||
if (resource.endsWith(ICON_SUFFIX_SVG)) { |
||||
if (IOUtils.readResource(resource) != null) { |
||||
return SVGIcon.readSVGIcon(transformPath(resource)); |
||||
} |
||||
// 适配插件
|
||||
return adjustPluginsPng(resource); |
||||
} |
||||
return IOUtils.readIcon(resource); |
||||
} |
||||
// 文件无后缀时
|
||||
return readNoSuffixResource(resource, ICON_TYPE_NORMAL); |
||||
} |
||||
|
||||
/** |
||||
* 适配插件中使用_normal.png、_selected.png、_disabled.png的情况 |
||||
* @param resource 图片路径 |
||||
* @return Icon |
||||
*/ |
||||
private static Icon adjustPluginsPng(String resource) { |
||||
String pngResource = resource.replace(ICON_SUFFIX_SVG, ICON_SUFFIX_PNG); |
||||
// 考虑到某些插件可能只会使用三种图标中的一部分,这里做个判断,不然就会因为资源不存在而报错
|
||||
return IOUtils.readResource(pngResource) == null ? new ImageIcon() : IOUtils.readIcon(pngResource); |
||||
} |
||||
|
||||
/** |
||||
* 尝试读取不带扩展名的图标,svg优先,其次png,最后gif,都没读到就打印错误日志,返回空白Icon |
||||
* @param resource 图片路径 |
||||
* @param svgIconType 针对svg来说的图标类型 |
||||
* 取值为:ICON_TYPE_NORMAL、ICON_TYPE_DISABLED、ICON_TYPE_PRESSED |
||||
* @return 图标 |
||||
*/ |
||||
private static Icon readNoSuffixResource(String resource, String svgIconType) { |
||||
String svgPath = resource + svgIconType; |
||||
if (IOUtils.readResource(svgPath) != null) { |
||||
return SVGIcon.readSVGIcon(transformPath(svgPath)); |
||||
} |
||||
String pngPath = resource + ICON_SUFFIX_PNG; |
||||
if (IOUtils.readResource(pngPath) != null) { |
||||
return IOUtils.readIcon(transformPath(pngPath)); |
||||
} |
||||
String gifPath = resource + ICON_SUFFIX_GIF; |
||||
if (IOUtils.readResource(gifPath) != null) { |
||||
return IOUtils.readIcon(transformPath(gifPath)); |
||||
} |
||||
FineLoggerFactory.getLogger().error("File not exists:{}", resource); |
||||
return new ImageIcon(); |
||||
} |
||||
|
||||
/** |
||||
* 读取指定类型的svgIcon |
||||
* @param resource |
||||
* @param svgIconType |
||||
* @return |
||||
*/ |
||||
public static Icon readSVGIcon(String resource, String svgIconType) { |
||||
// 判断下是否有后缀
|
||||
if (!resource.contains(SUFFIX_SEPARATOR)) { |
||||
return readNoSuffixResource(resource, svgIconType); |
||||
} |
||||
// 如果是".png"后缀,就替换为传入的svgIconType,然后读取图标
|
||||
if (resource.endsWith(ICON_SUFFIX_PNG)) { |
||||
return readSpecifiedTypeIcon(resource, ICON_SUFFIX_PNG, svgIconType); |
||||
} |
||||
// 如果是"_XXXXXX.svg"后缀
|
||||
if (resource.endsWith(ICON_TYPE_NORMAL)) { |
||||
return readSpecifiedTypeIcon(resource, ICON_TYPE_NORMAL, svgIconType); |
||||
} |
||||
if (resource.endsWith(ICON_TYPE_DISABLED)) { |
||||
return readSpecifiedTypeIcon(resource, ICON_TYPE_DISABLED, svgIconType); |
||||
} |
||||
if (resource.endsWith(ICON_TYPE_PRESSED)) { |
||||
return readSpecifiedTypeIcon(resource, ICON_TYPE_PRESSED, svgIconType); |
||||
} |
||||
return readIcon(resource); |
||||
} |
||||
|
||||
private static Icon readSpecifiedTypeIcon(String resource, String oldSuffix, String newSuffix) { |
||||
String iconPath = resource.replace(oldSuffix, newSuffix); |
||||
if (IOUtils.readResource(iconPath) != null) { |
||||
return SVGIcon.readSVGIcon(transformPath(iconPath)); |
||||
} |
||||
return readIcon(resource); |
||||
} |
||||
|
||||
private static String transformPath(String path) { |
||||
Set<ResourcePathTransformer> set = getResourcePathTransformers(); |
||||
for (ResourcePathTransformer transformer : set) { |
||||
if (transformer.accept(path)) { |
||||
return transformer.transform(path); |
||||
} |
||||
} |
||||
return path; |
||||
} |
||||
|
||||
private static Set<ResourcePathTransformer> getResourcePathTransformers() { |
||||
Set<ResourcePathTransformer> set = new HashSet<ResourcePathTransformer>(); |
||||
ExtraClassManagerProvider provider = StableFactory.getExtraClassManager(); |
||||
if (provider != null) { |
||||
Set<ResourcePathTransformer> pluginProvided = provider.getArray(ResourcePathTransformer.MARK_STRING); |
||||
set.addAll(pluginProvided); |
||||
} |
||||
ResourcePathTransformer[] oemSet = StableFactory.getMarkedObjectsFromCollection(ResourcePathTransformer.MARK_STRING, ResourcePathTransformer.class); |
||||
set.addAll(Arrays.asList(oemSet)); |
||||
return set; |
||||
} |
||||
} |
@ -0,0 +1,99 @@
|
||||
package com.fr.base.svg; |
||||
|
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
import java.awt.image.BufferedImage; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
/** |
||||
* SVG转化而来的Icon |
||||
* @author Yvan |
||||
* @version 10.0 |
||||
* Created by Yvan on 2020/12/17 |
||||
*/ |
||||
public class SVGIcon implements Icon { |
||||
|
||||
private BufferedImage image; |
||||
|
||||
private static final boolean HI_DPI_SURPORT = SystemScaleUtils.isJreHiDPIEnabled(); |
||||
|
||||
public static final float SYSTEM_SCALE = SystemScaleUtils.sysScale(); |
||||
|
||||
private static final String ICON_PREFIX = "/"; |
||||
|
||||
public SVGIcon(BufferedImage image) { |
||||
this.image = image; |
||||
} |
||||
|
||||
private static Map<String, Icon> iconCache = new ConcurrentHashMap<>(); |
||||
|
||||
@Override |
||||
public void paintIcon(Component c, Graphics g, int x, int y) { |
||||
if (HI_DPI_SURPORT) { |
||||
Graphics2D graphics = (Graphics2D) g.create(x, y, image.getWidth(null), image.getHeight(null)); |
||||
float scale = SYSTEM_SCALE; |
||||
graphics.scale(1 / scale, 1 / scale); |
||||
graphics.drawImage(image, 0, 0, null); |
||||
graphics.scale(1.0D, 1.0D); |
||||
graphics.dispose(); |
||||
} else { |
||||
g.drawImage(image, x, y, null); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int getIconWidth() { |
||||
return HI_DPI_SURPORT ? (int) (image.getWidth() / SYSTEM_SCALE) : image.getWidth(); |
||||
} |
||||
|
||||
@Override |
||||
public int getIconHeight() { |
||||
return HI_DPI_SURPORT ? (int) (image.getHeight() / SYSTEM_SCALE) : image.getHeight(); |
||||
} |
||||
|
||||
/** |
||||
* 读取高清图标 |
||||
* @param url |
||||
* @return |
||||
*/ |
||||
public static Icon readSVGIcon(String url) { |
||||
return readSVGIconWithCache(url, true); |
||||
} |
||||
|
||||
public static Icon readSVGIconWithCache(String url, boolean cacheRead) { |
||||
Icon icon = null; |
||||
if (cacheRead) { |
||||
icon = iconCache.get(url); |
||||
} |
||||
if (icon == null) { |
||||
if (!url.startsWith(ICON_PREFIX)) { |
||||
url = ICON_PREFIX + url; |
||||
} |
||||
BufferedImage image = (BufferedImage) SVGLoader.load(url); |
||||
icon = image == null ? IOUtils.readIcon(url) : new SVGIcon(image); |
||||
//只缓存svg图标
|
||||
if (image != null){ |
||||
iconCache.put(url, icon); |
||||
} |
||||
} |
||||
return icon; |
||||
} |
||||
|
||||
/** |
||||
* 读取指定尺寸的图标 |
||||
* @param url 资源路径 |
||||
* @param width 宽度 |
||||
* @param height 高度 |
||||
* @return |
||||
*/ |
||||
public static Icon readSVGIcon(String url, float width, float height) { |
||||
if (!url.startsWith(ICON_PREFIX)) { |
||||
url = ICON_PREFIX + url; |
||||
} |
||||
BufferedImage image = (BufferedImage) SVGLoader.load(url, width, height); |
||||
return image == null ? IOUtils.readIcon(url) : new SVGIcon(image); |
||||
} |
||||
} |
Loading…
Reference in new issue