package com.scrivenvar.preview;
import com.scrivenvar.Services;
import com.scrivenvar.service.events.Notifier;
import org.apache.commons.io.FilenameUtils;
import org.w3c.dom.Element;
import org.xhtmlrenderer.extend.ReplacedElement;
import org.xhtmlrenderer.extend.ReplacedElementFactory;
import org.xhtmlrenderer.extend.UserAgentCallback;
import org.xhtmlrenderer.layout.LayoutContext;
import org.xhtmlrenderer.render.BlockBox;
import org.xhtmlrenderer.simple.extend.FormSubmissionListener;
import org.xhtmlrenderer.swing.ImageReplacedElement;
import java.awt.*;
import java.util.LinkedHashMap;
import java.util.Map;
import static com.scrivenvar.preview.SVGRasterizer.rasterize;
public class SVGReplacedElementFactory
implements ReplacedElementFactory {
private final static Notifier sNotifier = Services.load( Notifier.class );
private static final String SVG_FILE = "svg";
private static final String HTML_IMAGE = "img";
private static final String HTML_IMAGE_SRC = "src";
private static final int MAX_CACHED_IMAGES = 100;
private final Map<String, Image> mImageCache = new LinkedHashMap<>() {
@Override
protected boolean removeEldestEntry(
final Map.Entry<String, Image> eldest ) {
return size() > MAX_CACHED_IMAGES;
}
};
@Override
public ReplacedElement createReplacedElement(
final LayoutContext c,
final BlockBox box,
final UserAgentCallback uac,
final int cssWidth,
final int cssHeight ) {
final Element e = box.getElement();
if( e != null ) {
final String nodeName = e.getNodeName();
if( HTML_IMAGE.equals( nodeName ) ) {
final String src = e.getAttribute( HTML_IMAGE_SRC );
final String ext = FilenameUtils.getExtension( src );
if( SVG_FILE.equalsIgnoreCase( ext ) ) {
try {
final int width = box.getContentWidth();
final Image image = getImage( src, width );
final int w = image.getWidth( null );
final int h = image.getHeight( null );
return new ImageReplacedElement( image, w, h );
} catch( final Exception ex ) {
getNotifier().notify( ex );
}
}
}
}
return null;
}
@Override
public void reset() {
}
@Override
public void remove( final Element e ) {
}
@Override
public void setFormSubmissionListener( FormSubmissionListener listener ) {
}
private Image getImage( final String src, final int width ) {
return mImageCache.computeIfAbsent( src, v -> rasterize( src, width ) );
}
private Notifier getNotifier() {
return sNotifier;
}
}