You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
6.5 KiB
181 lines
6.5 KiB
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); |
|
} |
|
}
|
|
|