Index: build.xml
===================================================================
--- build.xml	(Revision 19585)
+++ build.xml	(Arbeitskopie)
@@ -1118,11 +1118,6 @@
                 <exclude name="com/drew/metadata/wav/**"/>
                 <exclude name="com/drew/metadata/webp/**"/>
                 <exclude name="com/drew/tools/**"/>
-                <exclude name="com/kitfox/svg/app/ant/**"/>
-                <exclude name="com/kitfox/svg/app/*Dialog*"/>
-                <exclude name="com/kitfox/svg/app/*Frame*"/>
-                <exclude name="com/kitfox/svg/app/*Player*"/>
-                <exclude name="com/kitfox/svg/app/*Viewer*"/>
                 <exclude name="org/apache/commons/compress/PasswordRequiredException*"/>
                 <exclude name="org/apache/commons/compress/archivers/**"/>
                 <exclude name="org/apache/commons/compress/changes/**"/>
Index: ivy.xml
===================================================================
--- ivy.xml	(Revision 19585)
+++ ivy.xml	(Arbeitskopie)
@@ -31,7 +31,8 @@
         <dependency conf="api->default" org="org.tukaani" name="xz" rev="1.11"/>
         <dependency conf="api->default" org="com.adobe.xmp" name="xmpcore" rev="6.1.11"/>
         <dependency conf="api->default" org="com.drewnoakes" name="metadata-extractor" rev="2.19.0" transitive="false"/>
-        <dependency conf="api->default" org="com.formdev" name="svgSalamander" rev="1.1.4"/>
+        <dependency conf="api->default" org="com.github.weisj" name="jsvg" rev="1.7.0"/>
+        <dependency conf="api->default" org="org.jetbrains" name="annotations" rev="24.1.0"/>
         <dependency conf="api->default" org="ch.poole" name="OpeningHoursParser" rev="0.29.0"/>
         <!-- Don't forget to update org.openstreetmap.josm.tools.Tag2Link#PREF_SOURCE -->
         <dependency conf="api->default" org="org.webjars.npm" name="tag2link" rev="2026.6.26"/>
Index: pom.xml
===================================================================
--- pom.xml	(Revision 19585)
+++ pom.xml	(Arbeitskopie)
@@ -123,11 +123,17 @@
       <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.formdev</groupId>
-      <artifactId>svgSalamander</artifactId>
+      <groupId>com.github.weisj</groupId>
+      <artifactId>jsvg</artifactId>
       <scope>compile</scope>
     </dependency>
     <dependency>
+      <groupId>org.jetbrains</groupId>
+      <artifactId>annotations</artifactId>
+      <version>24.1.0</version>
+      <scope>provided</scope> 
+    </dependency>
+    <dependency>
       <groupId>ch.poole</groupId>
       <artifactId>OpeningHoursParser</artifactId>
       <scope>compile</scope>
@@ -661,16 +667,6 @@
                   </excludes>
                 </filter>
                 <filter>
-                  <artifact>com.formdev:svgSalamander</artifact>
-                  <excludes>
-                    <exclude>com/kitfox/svg/app/ant/**</exclude>
-                    <exclude>com/kitfox/svg/app/*Dialog*</exclude>
-                    <exclude>com/kitfox/svg/app/*Frame*</exclude>
-                    <exclude>com/kitfox/svg/app/*Player*</exclude>
-                    <exclude>com/kitfox/svg/app/*Viewer*</exclude>
-                  </excludes>
-                </filter>
-                <filter>
                   <artifact>org.apache.commons:commons-compress</artifact>
                   <excludes>
                     <exclude>org/apache/commons/compress/PasswordRequiredException*</exclude>
Index: src/org/openstreetmap/josm/tools/ImageProvider.java
===================================================================
--- src/org/openstreetmap/josm/tools/ImageProvider.java	(Revision 19585)
+++ src/org/openstreetmap/josm/tools/ImageProvider.java	(Arbeitskopie)
@@ -79,9 +79,11 @@
 import org.xml.sax.XMLReader;
 import org.xml.sax.helpers.DefaultHandler;
 
-import com.kitfox.svg.SVGDiagram;
-import com.kitfox.svg.SVGException;
-import com.kitfox.svg.SVGUniverse;
+import com.github.weisj.jsvg.SVGDocument;
+import com.github.weisj.jsvg.geometry.size.FloatSize;
+import com.github.weisj.jsvg.parser.DocumentLimits;
+import com.github.weisj.jsvg.parser.LoaderContext;
+import com.github.weisj.jsvg.parser.SVGLoader;
 
 /**
  * Helper class to support the application with images.
@@ -252,6 +254,8 @@
         ARCHIVE
     }
 
+    private static final SVGLoader svgloader = new SVGLoader();
+
     /**
      * Property set on {@code BufferedImage} returned by {@link #makeImageTransparent}.
      * @since 7132
@@ -295,8 +299,6 @@
     /** <code>true</code> if multi-resolution image is requested */
     protected boolean multiResolution = true;
 
-    private static SVGUniverse svgUniverse;
-
     /**
      * The icon cache
      */
@@ -967,20 +969,17 @@
      */
     private static ImageResource getIfAvailableHttp(String url, ImageType type) {
         try (CachedFile cf = new CachedFile(url).setDestDir(
-                new File(Config.getDirs().getCacheDirectory(true), "images").getPath());
-             InputStream is = cf.getInputStream()) {
+                new File(Config.getDirs().getCacheDirectory(true), "images").getPath())) {
+            URL localurl = Utils.fileToURL(cf.getFile());
             switch (type) {
             case SVG:
-                SVGDiagram svg;
-                synchronized (getSvgUniverse()) {
-                    URI uri = getSvgUniverse().loadSVG(is, Utils.fileToURL(cf.getFile()).toString());
-                    svg = getSvgUniverse().getDiagram(uri);
-                }
+                Logging.debug("Load SVG "+url);
+                SVGDocument svg = svgloader.load(localurl, getSVGContext());
                 return svg == null ? null : new ImageResource(svg);
             case OTHER:
                 BufferedImage img = null;
                 try {
-                    img = read(Utils.fileToURL(cf.getFile()), false, false);
+                    img = read(localurl, false, false);
                 } catch (IOException | UnsatisfiedLinkError e) {
                     Logging.log(Logging.LEVEL_WARN, "Exception while reading HTTP image:", e);
                 }
@@ -1017,19 +1016,16 @@
             }
             String mediatype = m.group(1);
             if ("image/svg+xml".equals(mediatype)) {
-                String s = new String(bytes, StandardCharsets.UTF_8);
                 // see #19097: check if s starts with PNG magic
-                if (s.length() > 4 && "PNG".equals(s.substring(1, 4))) {
+                if (bytes.length > 4 && bytes[1] == 'P' && bytes[2] == 'N' && bytes[3] == 'G') {
                     Logging.warn("url contains PNG file " + url);
                     return null;
                 }
-                SVGDiagram svg;
-                synchronized (getSvgUniverse()) {
-                    URI uri = getSvgUniverse().loadSVG(new StringReader(s), Utils.encodeUrl(s));
-                    svg = getSvgUniverse().getDiagram(uri);
-                }
+                InputStream is = new ByteArrayInputStream(bytes);
+                Logging.debug("Load SVG "+url);
+                SVGDocument svg = svgloader.load(is, (URI) null, getSVGContext());
                 if (svg == null) {
-                    Logging.warn("Unable to process svg: "+s);
+                    Logging.warn("Unable to process svg: "+bytes);
                     return null;
                 }
                 return new ImageResource(svg);
@@ -1112,11 +1108,8 @@
                 try (InputStream is = zipFile.getInputStream(entry)) {
                     switch (type) {
                     case SVG:
-                        SVGDiagram svg;
-                        synchronized (getSvgUniverse()) {
-                            URI uri = getSvgUniverse().loadSVG(is, entryName, true);
-                            svg = getSvgUniverse().getDiagram(uri);
-                        }
+                        Logging.debug("Load SVG "+archive+" "+entryName);
+                        SVGDocument svg = svgloader.load(is, (URI) null, getSVGContext());
                         return svg == null ? null : new ImageResource(svg);
                     case OTHER:
                         while (size > 0) {
@@ -1151,24 +1144,27 @@
         Objects.requireNonNull(type, "ImageType must not be null");
         switch (type) {
         case SVG:
-            SVGDiagram svg = null;
-            synchronized (getSvgUniverse()) {
+            SVGDocument svg = null;
+            try {
+                Logging.debug("Load SVG "+path);
+                svg = svgloader.load(path, getSVGContext());
+            } catch (Exception e) {
+                Logging.error("Cannot open {0}: {1}", path, e.getMessage());
+                Logging.trace(e);
+            }
+
+            if (svg == null && "jar".equals(path.getProtocol())) {
                 try {
-                    URI uri = null;
-                    try {
-                        uri = getSvgUniverse().loadSVG(path);
-                    } catch (InvalidPathException e) {
-                        Logging.error("Cannot open {0}: {1}", path, e.getMessage());
-                        Logging.trace(e);
-                    }
-                    if (uri == null && "jar".equals(path.getProtocol())) {
-                        URL betterPath = Utils.betterJarUrl(path);
-                        if (betterPath != null) {
-                            uri = getSvgUniverse().loadSVG(betterPath);
+                    URL betterPath = Utils.betterJarUrl(path);
+                    if (betterPath != null) {
+                        try {
+                            Logging.debug("Load SVG "+betterPath);
+                            svg = svgloader.load(betterPath, getSVGContext());
+                        } catch (Exception e) {
+                            Logging.log(Logging.LEVEL_WARN, "Unable to read SVG from fallback jar URL", e);
                         }
                     }
-                    svg = getSvgUniverse().getDiagram(uri);
-                } catch (SecurityException | IOException e) {
+                } catch (IOException e) {
                     Logging.log(Logging.LEVEL_WARN, "Unable to read SVG", e);
                 }
             }
@@ -1471,36 +1467,22 @@
      * @param resizeMode how to size/resize the image
      * @return an image from the given SVG data at the desired dimension.
      */
-    static BufferedImage createImageFromSvg(SVGDiagram svg, Dimension dim, ImageResizeMode resizeMode) {
+    static BufferedImage createImageFromSvg(SVGDocument svg, Dimension dim, ImageResizeMode resizeMode) {
         if (Logging.isTraceEnabled()) {
-            Logging.trace("createImageFromSvg: {0} {1}", svg.getXMLBase(), dim);
+            Logging.trace("createImageFromSvg: {0}", dim);
         }
-        final float sourceWidth = svg.getWidth();
-        final float sourceHeight = svg.getHeight();
+        FloatSize size = svg.size();
+        final float sourceWidth = size.width;
+        final float sourceHeight = size.height;
         if (sourceWidth <= 0 || sourceHeight <= 0) {
-            Logging.error("createImageFromSvg: {0} {1} sourceWidth={2} sourceHeight={3}", svg.getXMLBase(), dim, sourceWidth, sourceHeight);
+            Logging.error("createImageFromSvg: {0} sourceWidth={1} sourceHeight={2}", dim, sourceWidth, sourceHeight);
             return null;
         }
         return resizeMode.createBufferedImage(dim, new Dimension((int) sourceWidth, (int) sourceHeight), g -> {
-            try {
-                synchronized (getSvgUniverse()) {
-                    svg.render(g);
-                }
-            } catch (SVGException ex) {
-                Logging.log(Logging.LEVEL_ERROR, "Unable to load svg:", ex);
-            }
+            svg.render(null, g);
         }, null);
     }
 
-    private static synchronized SVGUniverse getSvgUniverse() {
-        if (svgUniverse == null) {
-            svgUniverse = new SVGUniverse();
-            // CVE-2017-5617: Allow only data scheme (see #14319)
-            svgUniverse.setImageDataInlineOnly(true);
-        }
-        return svgUniverse;
-    }
-
     /**
      * Returns a <code>BufferedImage</code> as the result of decoding
      * a supplied <code>File</code> with an <code>ImageReader</code>
@@ -1954,6 +1936,11 @@
         return new ImageIcon(new BufferedImage(size.getAdjustedWidth(), size.getAdjustedHeight(), BufferedImage.TYPE_INT_ARGB));
     }
 
+    private static LoaderContext getSVGContext() {
+        return LoaderContext.builder().documentLimits(new DocumentLimits(DocumentLimits.DEFAULT_MAX_NESTING_DEPTH,
+            DocumentLimits.DEFAULT_MAX_USE_NESTING_DEPTH, DocumentLimits.DEFAULT_MAX_PATH_COUNT+3000)).build();
+    }
+
     @Override
     public String toString() {
         return ("ImageProvider ["
Index: src/org/openstreetmap/josm/tools/ImageResource.java
===================================================================
--- src/org/openstreetmap/josm/tools/ImageResource.java	(Revision 19585)
+++ src/org/openstreetmap/josm/tools/ImageResource.java	(Arbeitskopie)
@@ -17,7 +17,7 @@
 
 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
 
-import com.kitfox.svg.SVGDiagram;
+import com.github.weisj.jsvg.SVGDocument;
 
 /**
  * Holds data for one particular image.
@@ -36,7 +36,7 @@
     /**
      * SVG diagram information in case of SVG vector image.
      */
-    private SVGDiagram svg;
+    private SVGDocument svg;
     /**
      * Use this dimension to request original file dimension.
      */
@@ -67,7 +67,7 @@
      * Constructs a new {@code ImageResource} from SVG data.
      * @param svg SVG data
      */
-    public ImageResource(SVGDiagram svg) {
+    public ImageResource(SVGDocument svg) {
         CheckParameterUtil.ensureParameterNotNull(svg);
         this.svg = svg;
     }
