forked from fanruan/design
9 changed files with 70 additions and 799 deletions
@ -1,148 +0,0 @@ |
|||||||
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.Icon; |
|
||||||
import javax.swing.ImageIcon; |
|
||||||
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; |
|
||||||
} |
|
||||||
} |
|
@ -1,101 +0,0 @@ |
|||||||
package com.fr.base.svg; |
|
||||||
|
|
||||||
import com.fr.general.IOUtils; |
|
||||||
|
|
||||||
import javax.swing.Icon; |
|
||||||
import java.awt.Component; |
|
||||||
import java.awt.Graphics; |
|
||||||
import java.awt.Graphics2D; |
|
||||||
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); |
|
||||||
} |
|
||||||
} |
|
@ -1,92 +0,0 @@ |
|||||||
package com.fr.base.svg; |
|
||||||
|
|
||||||
import com.fr.general.IOUtils; |
|
||||||
import org.apache.batik.transcoder.TranscoderException; |
|
||||||
import org.apache.batik.transcoder.TranscoderInput; |
|
||||||
import org.apache.xmlgraphics.java2d.Dimension2DDouble; |
|
||||||
import org.jetbrains.annotations.NotNull; |
|
||||||
import org.jetbrains.annotations.Nullable; |
|
||||||
|
|
||||||
import java.awt.Image; |
|
||||||
import java.io.IOException; |
|
||||||
import java.net.URL; |
|
||||||
|
|
||||||
/** |
|
||||||
* SVG图标加载器 |
|
||||||
* @author Yvan |
|
||||||
* @version 10.0 |
|
||||||
* Created by Yvan on 2020/12/17 |
|
||||||
*/ |
|
||||||
public class SVGLoader { |
|
||||||
public static final int ICON_DEFAULT_SIZE = 16; |
|
||||||
|
|
||||||
public SVGLoader() { |
|
||||||
} |
|
||||||
|
|
||||||
@Nullable |
|
||||||
public static Image load(@NotNull String url) { |
|
||||||
try { |
|
||||||
URL resource = IOUtils.getResource(url, SVGLoader.class); |
|
||||||
if (resource == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
return load(resource, SVGIcon.SYSTEM_SCALE); |
|
||||||
} catch (IOException ignore) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Nullable |
|
||||||
public static Image load(@NotNull URL url) throws IOException { |
|
||||||
return load(url, SVGIcon.SYSTEM_SCALE); |
|
||||||
} |
|
||||||
|
|
||||||
@Nullable |
|
||||||
public static Image load(@NotNull URL url, double scale) throws IOException { |
|
||||||
try { |
|
||||||
String svgUri = url.toString(); |
|
||||||
TranscoderInput input = new TranscoderInput(svgUri); |
|
||||||
return SVGTranscoder.createImage(scale, input).getImage(); |
|
||||||
} catch (TranscoderException ignore) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Nullable |
|
||||||
public static Image load(@NotNull URL url, double scale, Dimension2DDouble dimension) throws IOException { |
|
||||||
try { |
|
||||||
String svgUri = url.toString(); |
|
||||||
TranscoderInput input = new TranscoderInput(svgUri); |
|
||||||
return SVGTranscoder.createImage(scale, input, |
|
||||||
(float) (dimension.getWidth() * scale), (float) (dimension.getHeight() * scale)).getImage(); |
|
||||||
} catch (TranscoderException ignore) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Nullable |
|
||||||
public static Image load(@NotNull URL url, double scale, double overriddenWidth, double overriddenHeight) throws IOException { |
|
||||||
try { |
|
||||||
String svgUri = url.toString(); |
|
||||||
TranscoderInput input = new TranscoderInput(svgUri); |
|
||||||
return SVGTranscoder.createImage(scale, input, (float) (overriddenWidth * scale), (float) (overriddenHeight * scale)).getImage(); |
|
||||||
} catch (TranscoderException ignore) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Nullable |
|
||||||
public static Image load(@NotNull String url, float width, float height) { |
|
||||||
try { |
|
||||||
URL resource = IOUtils.getResource(url, SVGLoader.class); |
|
||||||
if (resource == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
TranscoderInput input = new TranscoderInput(resource.toString()); |
|
||||||
return SVGTranscoder.createImage(SVGIcon.SYSTEM_SCALE, input, -1, -1, width, height).getImage(); |
|
||||||
} catch (TranscoderException ignore) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,181 +0,0 @@ |
|||||||
package com.fr.base.svg; |
|
||||||
|
|
||||||
import com.fr.stable.AssistUtils; |
|
||||||
import com.fr.value.AtomicNotNullLazyValue; |
|
||||||
import org.apache.batik.anim.dom.SAXSVGDocumentFactory; |
|
||||||
import org.apache.batik.anim.dom.SVGOMDocument; |
|
||||||
import org.apache.batik.bridge.BridgeContext; |
|
||||||
import org.apache.batik.bridge.UserAgent; |
|
||||||
import org.apache.batik.transcoder.SVGAbstractTranscoder; |
|
||||||
import org.apache.batik.transcoder.TranscoderException; |
|
||||||
import org.apache.batik.transcoder.TranscoderInput; |
|
||||||
import org.apache.batik.transcoder.TranscoderOutput; |
|
||||||
import org.apache.batik.transcoder.image.ImageTranscoder; |
|
||||||
import org.apache.batik.util.XMLResourceDescriptor; |
|
||||||
import org.jetbrains.annotations.NotNull; |
|
||||||
import org.jetbrains.annotations.Nullable; |
|
||||||
import org.w3c.dom.Element; |
|
||||||
import org.w3c.dom.svg.SVGDocument; |
|
||||||
|
|
||||||
import java.awt.GraphicsDevice; |
|
||||||
import java.awt.GraphicsEnvironment; |
|
||||||
import java.awt.Rectangle; |
|
||||||
import java.awt.geom.AffineTransform; |
|
||||||
import java.awt.image.BufferedImage; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.StringReader; |
|
||||||
|
|
||||||
/** |
|
||||||
* 可以根据某个缩放倍数scale,将SVG图片转化为Image对象 |
|
||||||
* @author Yvan |
|
||||||
* @version 10.0 |
|
||||||
* Created by Yvan on 2020/12/17 |
|
||||||
*/ |
|
||||||
public class SVGTranscoder extends ImageTranscoder { |
|
||||||
|
|
||||||
private static final float DEFAULT_VALUE = -1.0F; |
|
||||||
public static final float ICON_DEFAULT_SIZE = 16F; |
|
||||||
private float origDocWidth; |
|
||||||
private float origDocHeight; |
|
||||||
@Nullable |
|
||||||
private BufferedImage image; |
|
||||||
private final double scale; |
|
||||||
|
|
||||||
@NotNull |
|
||||||
private static AtomicNotNullLazyValue<Double> iconMaxSize = new AtomicNotNullLazyValue<Double>() { |
|
||||||
@NotNull |
|
||||||
@Override |
|
||||||
protected Double compute() { |
|
||||||
double maxSize = Double.MAX_VALUE; |
|
||||||
if (!GraphicsEnvironment.isHeadless()) { |
|
||||||
GraphicsDevice defaultScreenDevice = GraphicsEnvironment |
|
||||||
.getLocalGraphicsEnvironment() |
|
||||||
.getDefaultScreenDevice(); |
|
||||||
Rectangle bounds = defaultScreenDevice.getDefaultConfiguration().getBounds(); |
|
||||||
AffineTransform tx = defaultScreenDevice |
|
||||||
.getDefaultConfiguration() |
|
||||||
.getDefaultTransform(); |
|
||||||
maxSize = Math.max(bounds.width * tx.getScaleX(), bounds.height * tx.getScaleY()); |
|
||||||
} |
|
||||||
return maxSize; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
public SVGTranscoder(double scale) { |
|
||||||
this.scale = scale; |
|
||||||
this.width = ICON_DEFAULT_SIZE; |
|
||||||
this.height = ICON_DEFAULT_SIZE; |
|
||||||
} |
|
||||||
|
|
||||||
public SVGTranscoder(double scale, float width, float height) { |
|
||||||
this.scale = scale; |
|
||||||
this.width = width; |
|
||||||
this.height = height; |
|
||||||
} |
|
||||||
|
|
||||||
public final float getOrigDocWidth() { |
|
||||||
return this.origDocWidth; |
|
||||||
} |
|
||||||
|
|
||||||
public final void setOrigDocWidth(float origDocWidth) { |
|
||||||
this.origDocWidth = origDocWidth; |
|
||||||
} |
|
||||||
|
|
||||||
public final float getOrigDocHeight() { |
|
||||||
return this.origDocHeight; |
|
||||||
} |
|
||||||
|
|
||||||
public final void setOrigDocHeight(float origDocHeight) { |
|
||||||
this.origDocHeight = origDocHeight; |
|
||||||
} |
|
||||||
|
|
||||||
public static double getIconMaxSize() { |
|
||||||
return iconMaxSize.getValue(); |
|
||||||
} |
|
||||||
|
|
||||||
@Nullable |
|
||||||
public final BufferedImage getImage() { |
|
||||||
return this.image; |
|
||||||
} |
|
||||||
|
|
||||||
@NotNull |
|
||||||
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input) throws TranscoderException { |
|
||||||
return createImage(scale, input, -1, -1); |
|
||||||
} |
|
||||||
|
|
||||||
@NotNull |
|
||||||
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input, float overriddenWidth, float overriddenHeight) throws TranscoderException { |
|
||||||
return createImage(scale, input, overriddenWidth, overriddenHeight, ICON_DEFAULT_SIZE, ICON_DEFAULT_SIZE); |
|
||||||
} |
|
||||||
|
|
||||||
@NotNull |
|
||||||
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input, float overriddenWidth, float overriddenHeight, float width, float height) throws TranscoderException { |
|
||||||
SVGTranscoder transcoder = new SVGTranscoder(scale, width, height); |
|
||||||
if (!AssistUtils.equals(overriddenWidth, DEFAULT_VALUE)) { |
|
||||||
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, overriddenWidth); |
|
||||||
} |
|
||||||
|
|
||||||
if (!AssistUtils.equals(overriddenHeight, DEFAULT_VALUE)) { |
|
||||||
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, overriddenHeight); |
|
||||||
} |
|
||||||
|
|
||||||
double iconMaxSize = SVGTranscoder.iconMaxSize.getValue(); |
|
||||||
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MAX_WIDTH, (float) iconMaxSize); |
|
||||||
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MAX_HEIGHT, (float) iconMaxSize); |
|
||||||
transcoder.transcode(input, null); |
|
||||||
return transcoder; |
|
||||||
} |
|
||||||
|
|
||||||
private static SVGDocument createFallbackPlaceholder() { |
|
||||||
try { |
|
||||||
String fallbackIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\">\n" + |
|
||||||
" <rect x=\"1\" y=\"1\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"red\" stroke-width=\"2\"/>\n" + |
|
||||||
" <line x1=\"1\" y1=\"1\" x2=\"15\" y2=\"15\" stroke=\"red\" stroke-width=\"2\"/>\n" + |
|
||||||
" <line x1=\"1\" y1=\"15\" x2=\"15\" y2=\"1\" stroke=\"red\" stroke-width=\"2\"/>\n" + |
|
||||||
"</svg>\n"; |
|
||||||
|
|
||||||
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName()); |
|
||||||
return (SVGDocument) factory.createDocument(null, new StringReader(fallbackIcon)); |
|
||||||
} catch (IOException e) { |
|
||||||
throw new IllegalStateException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void setImageSize(float docWidth, float docHeight) { |
|
||||||
super.setImageSize((float) (docWidth * this.scale), (float) (docHeight * this.scale)); |
|
||||||
this.origDocWidth = docWidth; |
|
||||||
this.origDocHeight = docHeight; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
@NotNull |
|
||||||
public BufferedImage createImage(int width, int height) { |
|
||||||
return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void writeImage(@NotNull BufferedImage image, @Nullable TranscoderOutput output) { |
|
||||||
this.image = image; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
@NotNull |
|
||||||
protected UserAgent createUserAgent() { |
|
||||||
return new SVGAbstractTranscoderUserAgent() { |
|
||||||
@Override |
|
||||||
@NotNull |
|
||||||
public SVGDocument getBrokenLinkDocument(@NotNull Element e, @NotNull String url, @NotNull String message) { |
|
||||||
return createFallbackPlaceholder(); |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 开放访问权限 |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public BridgeContext createBridgeContext(SVGOMDocument doc) { |
|
||||||
return super.createBridgeContext(doc); |
|
||||||
} |
|
||||||
} |
|
@ -1,101 +0,0 @@ |
|||||||
package com.fr.base.svg; |
|
||||||
|
|
||||||
import com.bulenkov.iconloader.util.UIUtil; |
|
||||||
import com.fr.log.FineLoggerFactory; |
|
||||||
import com.fr.stable.StableUtils; |
|
||||||
import com.fr.stable.os.OperatingSystem; |
|
||||||
import org.jetbrains.annotations.NotNull; |
|
||||||
|
|
||||||
import java.awt.GraphicsConfiguration; |
|
||||||
import java.awt.GraphicsDevice; |
|
||||||
import java.awt.GraphicsEnvironment; |
|
||||||
import java.lang.reflect.Method; |
|
||||||
import java.util.concurrent.atomic.AtomicReference; |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取系统Scale相关的工具类 |
|
||||||
* @author Yvan |
|
||||||
* @version 10.0 |
|
||||||
* Created by Yvan on 2020/12/17 |
|
||||||
*/ |
|
||||||
public class SystemScaleUtils { |
|
||||||
|
|
||||||
private static final AtomicReference<Boolean> JRE_HIDPI = new AtomicReference<>(); |
|
||||||
|
|
||||||
private static final String HI_DPI = "hidpi"; |
|
||||||
|
|
||||||
/** |
|
||||||
* 判断是否支持高清 |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static boolean isJreHiDPIEnabled() { |
|
||||||
if (JRE_HIDPI.get() != null) { |
|
||||||
return JRE_HIDPI.get(); |
|
||||||
} |
|
||||||
if (OperatingSystem.isMacos()) { |
|
||||||
// 如果是mac os系统,直接返回true
|
|
||||||
return true; |
|
||||||
} |
|
||||||
if (OperatingSystem.isWindows() && StableUtils.getMajorJavaVersion() <= 8) { |
|
||||||
// 如果是jdk8 + Windows系统,直接返回false
|
|
||||||
return false; |
|
||||||
} |
|
||||||
synchronized (JRE_HIDPI) { |
|
||||||
if (JRE_HIDPI.get() != null) { |
|
||||||
return JRE_HIDPI.get(); |
|
||||||
} |
|
||||||
boolean result = false; |
|
||||||
if (getBooleanProperty(HI_DPI, true)) { |
|
||||||
try { |
|
||||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); |
|
||||||
Class<?> sunGraphicsEnvironmentClass = Class.forName("sun.java2d.SunGraphicsEnvironment"); |
|
||||||
if (sunGraphicsEnvironmentClass.isInstance(ge)) { |
|
||||||
try { |
|
||||||
Method method = sunGraphicsEnvironmentClass.getDeclaredMethod("isUIScaleEnabled"); |
|
||||||
method.setAccessible(true); |
|
||||||
result = (Boolean)method.invoke(ge); |
|
||||||
} |
|
||||||
catch (NoSuchMethodException e) { |
|
||||||
FineLoggerFactory.getLogger().error(e.getMessage()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
catch (Throwable ignore) { |
|
||||||
} |
|
||||||
} |
|
||||||
JRE_HIDPI.set(result); |
|
||||||
return result; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean getBooleanProperty(@NotNull final String key, final boolean defaultValue) { |
|
||||||
final String value = System.getProperty(key); |
|
||||||
return value == null ? defaultValue : Boolean.parseBoolean(value); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取系统Scale |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static float sysScale() { |
|
||||||
// 如果检测到是retina,直接返回2
|
|
||||||
if (UIUtil.isRetina()) { |
|
||||||
return 2.0f; |
|
||||||
} |
|
||||||
float scale = 1.0f; |
|
||||||
// 先判断是否支持高清,不支持代表此时是Windows + jdk8 的设计器,返回的scale值为1.0
|
|
||||||
if (isJreHiDPIEnabled()) { |
|
||||||
// 获取屏幕图形设备对象
|
|
||||||
GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); |
|
||||||
if (graphicsDevice != null) { |
|
||||||
// 获取图形配置对象
|
|
||||||
GraphicsConfiguration configuration = graphicsDevice.getDefaultConfiguration(); |
|
||||||
if (configuration != null && configuration.getDevice().getType() != GraphicsDevice.TYPE_PRINTER) { |
|
||||||
// 获取屏幕缩放率,Windows+jdk11环境下会得到用户设置的dpi值
|
|
||||||
scale = (float) configuration.getDefaultTransform().getScaleX(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return scale; |
|
||||||
} |
|
||||||
} |
|
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Loading…
Reference in new issue