質問

I am currently trying to creating a custom JComponent (ViewerComponent) that scales and displays a SVG image using apache batik. Currently the ViewerComponent scales the SVG image proportionally; however, I would like for it to scale to fit the size of the component, ignoring proportionality. The code below shows a simple test I have written for the ViewerComponent. How can I modify it the ViewerComponent to behave as I mentioned above?

import java.awt.*;
import java.awt.event.*;
import java.net.*;
import javax.swing.*;
import org.apache.batik.swing.*;
import org.apache.batik.swing.gvt.*;
import org.apache.batik.util.*;
import org.w3c.dom.svg.*;

public final class View extends JPanel {

    public static final Dimension VIEW_SIZE = new Dimension(2000, 2000);
    public static final Dimension WINDOW_SIZE = new Dimension(600, 600);
    public static final String BACKGROUND_IMAGE
            = "file:///Users/home/Desktop/wiki.svg";

    private JScrollPane scrollPane;
    private ViewerComponent canvas;

    View() throws URISyntaxException {
        setUpGUI();
        createViewerBasedOnViewportSize();
    }

    private void setUpGUI() throws HeadlessException {
        setUpView();
        setUpScrollPane();
        setUpFrame();
    }

    private void setUpView() {
        this.setPreferredSize(VIEW_SIZE);
        this.setBackground(Color.WHITE);
    }

    private void setUpScrollPane() {
        scrollPane = new JScrollPane(this);
    }

    private void setUpFrame() throws HeadlessException {
        JFrame frame = new JFrame("SVG Viewer Test");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setContentPane(scrollPane);
        frame.setPreferredSize(WINDOW_SIZE);
        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);
        frame.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                adjustBackgroundComponentScale();
                repaint();
            }
        });
    }

    private void adjustBackgroundComponentScale() {
        if (canvas != null) {
            Dimension windowSize = calculateWindowSize();
            canvas.setFinalViewerSize(windowSize);
        }
    }

    private void createViewerBasedOnViewportSize() throws URISyntaxException {
        Dimension windowSize = calculateWindowSize();
        URI uri = retrieveURI();
        createViewer(uri, windowSize);
    }

    private Dimension calculateWindowSize() {
        final JViewport vp = (JViewport) getParent();
        final Dimension windowSize = vp.getVisibleRect().getSize();
        return windowSize;
    }

    private URI retrieveURI() throws URISyntaxException {
        URI uri = new URI(BACKGROUND_IMAGE);
        return uri;
    }

    void createViewer(final URI uri,
            final Dimension preferredSize) {
        canvas = new ViewerComponent(uri);
        canvas.addGVTTreeRendererListener(new GVTTreeRendererAdapter() {
            @Override
            public void gvtRenderingCompleted(final GVTTreeRendererEvent e) {
                canvas.setFinalViewerSize(preferredSize);
                canvas.revalidate();
                canvas.removeGVTTreeRendererListener(this);
            }
        });
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (canvas != null) {
            setAndPaintViewer(g);
        }
    }

    private void setAndPaintViewer(Graphics g) {
        Graphics backgroundGraphics = g.create();
        try {
            setBackgroundComponentLocation(backgroundGraphics);
            canvas.paint(backgroundGraphics);
            repaint();
        } finally {
            backgroundGraphics.dispose();
        }
    }

    private void setBackgroundComponentLocation(Graphics g) {
        final JViewport vp = (JViewport) getParent();
        final Point viewPosition = vp.getViewPosition();
        g.translate(viewPosition.x, viewPosition.y);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    new View();
                } catch (URISyntaxException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

}

class ViewerComponent extends JSVGCanvas {

    private static final long serialVersionUID = 1L;
    private Dimension originalSize = null;

    public Dimension getOriginalSize() {
        return new Dimension(originalSize);
    }

    public void setFinalViewerSize(final Dimension size) {
        final JSVGCanvas canvas = this;
        canvas.setPreferredSize(size);
        canvas.setMySize(size);
        canvas.setSize(size);
    }

    public void setDraftViewerSize(final Dimension size) {
        setFinalViewerSize(size);
    }

    public void setFinalViewerSize(final float zoom) {
        int scaledWidth = (int) (originalSize.width * zoom);
        int scaledHeight = (int) (originalSize.height * zoom);
        setFinalViewerSize(new Dimension(scaledWidth, scaledHeight));
    }

    public ViewerComponent(final URI uri) {
        super(null, false, false);
        setDocumentState(ALWAYS_STATIC);
        setSize(1, 1);
        setRecenterOnResize(true);
        addGVTTreeRendererListener(new GVTTreeRendererAdapter() {
            @Override
            public void gvtRenderingStarted(final GVTTreeRendererEvent e) {
                super.gvtRenderingStarted(e);
                final SVGDocument document = getSVGDocument();
                final SVGSVGElement rootElement = document.getRootElement();
                final SVGLength width = rootElement.getWidth().getBaseVal();
                final SVGLength height = rootElement.getHeight()
                        .getBaseVal();
                float defaultWidth = (float) Math.ceil(width.getValue());
                float defaultHeigth = (float) Math.ceil(height.getValue());
                if (defaultWidth == 1f && defaultHeigth == 1f) {
                    defaultWidth = 200;
                    defaultHeigth = 200;
                }
                originalSize = new Dimension((int) defaultWidth,
                        (int) defaultHeigth);
                if ("".equals(rootElement.getAttributeNS(null,
                        SVGConstants.SVG_VIEW_BOX_ATTRIBUTE))) {
                    rootElement.setAttributeNS(null,
                            SVGConstants.SVG_VIEW_BOX_ATTRIBUTE, "0 0 "
                            + defaultWidth + " " + defaultHeigth);
                }
                setSize(originalSize);
                removeGVTTreeRendererListener(this);
            }
        });
        setURI(uri.toString());
    }

    @Override
    public Dimension getPreferredSize() {
        if (originalSize == null) {
            return new Dimension(1, 1);
        }
        return super.getPreferredSize();
    }

}
役に立ちましたか?

解決

You'll need to set the preserveAspectRatio attribute to none. So it will be something like:

rootElement.setAttribute("preserveAspectRatio", "none");

I haven't used the batik library this way myself, but that's the DOM way of achieving this result.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top