帆软报表设计器源代码。
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

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);
}
}