为什么使用Apache Batik和Mac Renderer不会调整SVG图像的大小?

时间:2014-03-15 04:34:39

标签: java apache svg resize batik

目前我正在使用一个应用程序,该应用程序使用扩展JSVGCanvas的自定义查看器JComponent来扩展和显示SVG背景图像。将View类添加到JViewPort后,它应加载SVG图像,调整其大小以适应JViewPort的大小,然后显示图像。

结果应如下所示:

Properly scaled SVG image

然而,在使用Java 1.7.0_51的MacBook(OS X 10.8.5)上,它如下所示:

SVG image has not been scaled

在我的Mac上,当我调整应用程序窗口大小(从而激活componentResized方法)时,SVG图像会正确调整大小,如第一张图片所示。

我试过了:

  • 在调用loadBackgroundImage()之后添加对adjustBackgroundComponentScale()的调用。
  • 使用三个不同的SVG图像,所有这些图像都表现为第二张图片 - 这意味着图像本身不是问题。
  • 向paintComponent方法添加断点。 backgroundComponent的大小为1342x552,这是视口的大小。但是,gvtRoot>边界显示399 x 397(大约是图像的原始大小 - 意味着图像没有缩放)。

我对这个问题发生的地方感到困惑。如果背景组件的大小已正确设置为1342x552,为什么在调整窗口大小之前图像不会调整大小?

以下是View类的相关部分:

public class View extends JPanel {

    private final class BackgroundImageLoader implements AncestorListener {
        private ComponentListener listener;

        BackgroundImageLoader(final ComponentListener listener) {
            this.listener = listener;
        }

        public void ancestorAdded(AncestorEvent event) {
            loadBackgroundImage();
            getParent().addComponentListener(listener);
        }

        public void ancestorRemoved(AncestorEvent event) {
            getParent().removeComponentListener(listener);
        }

        public void ancestorMoved(AncestorEvent event) {
        }
    }

    private JComponent backgroundComponent;
    private boolean fitToViewport;

    public MapView() {
        // Other code...
        final String fitToViewportAsString = MapStyle
                .getController(modeController).getPropertySetDefault(model,
            MapStyle.FIT_TO_VIEWPORT);
        fitToViewport = Boolean.parseBoolean(fitToViewportAsString);
        final ComponentAdapter backgroundImageResizer = 
                new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                if (fitToViewport) {
                    adjustBackgroundComponentScale();
                }
            }
        };
        addAncestorListener(new BackgroundImageLoader(backgroundImageResizer));
    }

    public void mapChanged(final MapChangeEvent event) {
        final Object property = event.getProperty();
        if (property.equals(MapStyle.RESOURCES_BACKGROUND_IMAGE)) {
            loadBackgroundImage();
            adjustViewportScrollMode();
        }
        if (property.equals(MapStyle.FIT_TO_VIEWPORT)) {
            final String fitToViewportAsString = MapStyle
                    .getController(modeController).getPropertySetDefault(model,
                MapStyle.FIT_TO_VIEWPORT);
            fitToViewport = Boolean.parseBoolean(fitToViewportAsString);
            adjustViewportScrollMode();
            adjustBackgroundComponentScale();
        }
    }

    private void loadBackgroundImage() {
        final MapStyle mapStyle = getModeController().getExtension(MapStyle.class);
        final String uriString = mapStyle
                .getProperty(model, MapStyle.RESOURCES_BACKGROUND_IMAGE);
        backgroundComponent = null;
        if (uriString != null) {
            URI uri = assignAbsoluteURI(uriString);
            final ViewerController vc = getModeController()
                    .getExtension(ViewerController.class);
            final IViewerFactory factory = vc.getCombiFactory();
            if (uri != null) {
                assignViewerToBackgroundComponent(factory, uri);
            }
        }
        adjustViewportScrollMode();
    }

    private URI assignAbsoluteURI(final String uriString) {
        final UrlManager urlManager = getModeController()
                .getExtension(UrlManager.class);
        URI uri = null;
        try {
            uri = urlManager.getAbsoluteUri(model, new URI(uriString));
        }
        catch (final URISyntaxException e) {
            LogUtils.severe(e);
        }
        catch (MalformedURLException e) {
            LogUtils.severe(e);
        }
        return uri;
    }

    private void assignViewerToBackgroundComponent(final IViewerFactory factory, 
                                                   final URI uri) {
        try {
            final JViewport vp = (JViewport) getParent();
            if (vp != null) {
                final Dimension viewPortSize = vp.getVisibleRect().getSize();
                backgroundComponent = (JComponent) factory
                        .createViewer(uri, viewPortSize);
            }
            ((ScalableComponent) backgroundComponent).setCenter(true);
            ((ScalableComponent) backgroundComponent)
            .setImageLoadingListener(new ImageLoadingListener() {
                public void imageLoaded() {
                    repaint();
                }
            });
        }
        catch (final MalformedURLException e1) {
            LogUtils.severe(e1);
        }
        catch (final IOException e1) {
            LogUtils.severe(e1);
        }
    }

    @Override
    protected void paintComponent(final Graphics g) {
        super.paintComponent(g);
        if (backgroundComponent != null) {
            paintBackgroundComponent(g);
        }
    }

    private void paintBackgroundComponent(final Graphics g) {
        Graphics backgroundGraphics = g.create();
        try {
            setBackgroundComponentLocation(backgroundGraphics);
            backgroundComponent.paint(backgroundGraphics);
        }
        finally {
            backgroundGraphics.dispose();
        }
    }

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

    private void adjustBackgroundComponentScale() {
        if (backgroundComponent != null) {
            final JViewport vp = (JViewport) getParent();
            final Dimension viewPortSize = vp.getVisibleRect().getSize();
            ((ScalableComponent) backgroundComponent)
            .setFinalViewerSize(viewPortSize);
        }
    }
}

以下是自定义查看器组件的相关部分:

public class SvgViewerFactory implements IViewerFactory {
    private ViewerComponent canvas;

    private final class ViewerComponent extends 
                        JSVGCanvas implements ScalableComponent {

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

        public void setFinalViewerSize(final Dimension sizeWithScaleCorrection) {
            setRenderingTransform(initialTransform);
            setPreferredSize(sizeWithScaleCorrection);
            setMySize(sizeWithScaleCorrection);
            setSize(sizeWithScaleCorrection);
        }

        public ViewerComponent(final URI uri) {
            this(uri, null);
        }

        public ViewerComponent(final URI uri, final Dimension size) {
            super(null, false, false);
            setDocumentState(ALWAYS_STATIC);
            setSize(1, 1);
            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 = ResourceController
                                .getResourceController().getIntProperty(
                            "default_external_component_width", 200);
                        defaultHeigth = ResourceController
                                .getResourceController().getIntProperty(
                            "default_external_component_height", 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);
                    }
                    if (size == null) {
                        setSize(originalSize);
                    }
                    else {
                        setSize(size);
                    }
                    removeGVTTreeRendererListener(this);
                }
            });
            setURI(uri.toString());
        }

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

        public void setImageLoadingListener(final ImageLoadingListener listener) 
        {
            addGVTTreeRendererListener(new GVTTreeRendererAdapter() {
                @Override
                public void gvtRenderingCompleted(GVTTreeRendererEvent e) {
                    listener.imageLoaded();
                }
            });
        }
    }

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

    public ScalableComponent getComponent() {
        return canvas;
    }
}

0 个答案:

没有答案