diff --git a/TeXmacs/doc/devel/scheme/api/glue-auto-doc.en.tm b/TeXmacs/doc/devel/scheme/api/glue-auto-doc.en.tm
index 064cc45e..8974e1e6 100644
--- a/TeXmacs/doc/devel/scheme/api/glue-auto-doc.en.tm
+++ b/TeXmacs/doc/devel/scheme/api/glue-auto-doc.en.tm
@@ -1274,6 +1274,14 @@ source code.
     <scm|array_double>.
   </explain>
 
+  <\explain>
+    <scm|(cpp-gspdf2eps <scm-arg|url> <scm-arg|url>)>
+<explain-synopsis|no synopsis>
+  <|explain>
+    Calls the <c++> function <cpp|gs_to_eps> which returns
+    <scm|void>.
+  </explain>
+
   <\explain>
     <scm|(tree-\<gtr\>stree <scm-arg|tree>)>
 <explain-synopsis|no synopsis>
diff --git a/TeXmacs/progs/convert/images/init-images.scm b/TeXmacs/progs/convert/images/init-images.scm
index 3f0f2542..2e8cce9c 100644
--- a/TeXmacs/progs/convert/images/init-images.scm
+++ b/TeXmacs/progs/convert/images/init-images.scm
@@ -17,24 +17,84 @@
 ;; Helper functions for testing available converters
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+(define inkscape-check -1)
+(define gs-check -1)
+(define rsvg-check -1)
+
+(define (imagemagick-binary)
+  (if (os-mingw?) "magick" ;; avoid collision with Windows native command (imagemagick v>=7.0) 
+       "convert"))
+    
 (tm-define (has-convert?)
-  (and (not (os-mingw?)) ;; avoid name collision wrt Windows native command
-       (url-exists-in-path? "convert")))
+  (url-exists-in-path? (imagemagick-binary)))
 
 (tm-define (has-pdftocairo?)
   (url-exists-in-path? "pdftocairo"))
 
-(tm-define (gs-binary)
-  (let* ((n1 "$TEXMACS_PATH\\bin\\gs.exe;c:\\Program F*\\gs\\gs*\\gswin*c.exe")
+(tm-define (has-inkscape?)
+  (if (== inkscape-check -1)
+          (with ans (and (url-exists-in-path? "inkscape")
+                     (test-version-num "inkscape -V" "Inkscape " 0 92))
+             (set! inkscape-check (if ans 1 0))
+             ans)
+        (> inkscape-check 0)))
+   
+
+(tm-define (has-rsvg-convert?)
+  (if (== rsvg-check -1)
+          (with ans (and (url-exists-in-path? "rsvg-convert")
+                    (test-version-num "rsvg-convert -v" "version " 2 40))
+             (set! rsvg-check (if ans 1 0))
+             ans)
+        (> rsvg-check 0)))
+  
+(define (gs-url)
+   (let* ((n1 "$TEXMACS_PATH\\bin\\gs.exe;c:\\Program F*\\gs\\gs*\\gswin*c.exe")
          (n2 "$TEXMACS_PATH/bin/gs:gs")
          (name (if (os-mingw?) n1 n2)))
-    (url->system (url-resolve-in-path name))))
+         (url->system (url-resolve-in-path name))))
 
-(tm-define (has-gs?)
-  (url-exists? (gs-binary)))
+(define (gs-binary)
+    (escape-shell (gs-url)))
 
+(tm-define (has-gs?)
+  (if (== gs-check -1)
+        (with ans (and (url-exists? (gs-url))
+                  (test-version-num (string-append (gs-binary) " --version") "" 9 26))
+; because of bug #61991, but maybe a good idea to require even more recent gs (9.50?)
+; see https://www.cvedetails.com/product/36469/Artifex-Ghostscript.html?vendor_id=10846           
+          (set! gs-check (if ans 1 0))
+	      (if ans #t
+	       (begin 
+	          (debug-message "debug-convert" "No Ghostscript for Scheme converters\n")
+	        #f)))
+      (> gs-check 0)))
+    
+(define (test-version-num cmd key major minor)
+;tests if program reports version >=  major.minor
+  (with a (eval-system cmd)
+    (if (string-null? a)
+      #f
+      (with st (if (string-null? key) 
+               0 (string-search-forwards key 0 a))
+        (if (== st -1)
+          #f
+          (let*
+            ((a (substring a (+ st (string-length key))))
+             (a (car (string-split a #\space)))
+             (a (string-split a #\.)) 
+             (v1 (string->number (first a)))
+             (v2 (string->number (second a))))
+            (if (or (> v1 major) (and (== v1 major) (>= v2 minor)))
+              #t
+              (begin 
+                (debug-message "debug-convert" (string-append cmd " reports version " (first a) "." (second a) 
+                 ";\nTeXmacs will not use it as a converter.\n
+                 (minimun required version is " (number->string major) "." (number->string minor) ")\n"))
+                #f))))))))
+    
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Helper functions for conversions
+;; Helpers and function-with-option(s) for converters
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-preferences
@@ -49,61 +109,145 @@
       (escape-shell (url-concretize (url-resolve-in-path cmd)))))
 
 (tm-define (rsvg-convert x opts)
-  (let* ((dest (assoc-ref opts 'dest))
-         (fm (url-format (url-concretize dest)))
+  ;(display* "scm rsvg-convert " x opts "\n")
+  (let* ((last? (assoc-ref opts 'last?))
+         (fm (format-default-suffix (assoc-ref opts 'to-format)))
+         (fm (if (== fm "ps") "eps" fm))
+         (dest (if last? (assoc-ref opts 'dest)
+               (url-glue (url-temp) (string-append "." fm))))
          (res (get-raster-resolution opts))
-	 (cmd (get-shell-command "rsvg-convert")))
-    (system-2 (string-append cmd " -f " fm " -d " res " -o ") dest x)
+         (w (assoc-ref opts 'width)) ; width for export
+         (wstr (if w (string-append " -w "  w) ""))
+         (h (assoc-ref opts 'height))
+         (hstr (if h (string-append " -h "  h) ""))
+         (dstr (if (or (in? fm '("eps" "pdf")) h w) "" (string-append " -d " res)))
+         (cmd (string-append (get-shell-command "rsvg-convert")
+               " -f " fm wstr hstr dstr " -o ")))
+    ;(display* cmd dest " " x "\n")
+    (system-2 cmd dest x)
     (if (url-exists? dest) dest #f)))
 
+(tm-define (inkscape-convert x opts)
+  ;(display* "scm inkscape-convert " x opts "\n")
+  (let* ((last? (assoc-ref opts 'last?))
+         (fm (format-default-suffix (assoc-ref opts 'to-format)))
+         (fm (if (== fm "ps") "eps" fm))
+         (dest (if last? (assoc-ref opts 'dest)
+               (url-glue (url-temp) (string-append "." fm))))
+         (fullname (url-concretize dest))
+         (res (get-raster-resolution opts))
+         (w (assoc-ref opts 'width)) ; width in pixels for raster export
+         (wstr (if w (string-append " -w "  w) ""))
+         (h (assoc-ref opts 'height))
+         (hstr (if h (string-append " -h "  h) ""))
+         (dstr (if (or h w) "" (string-append " -d " res)))
+         (cmd (string-append (get-shell-command "inkscape") 
+               " --export-overwrite --pdf-poppler -l --export-type=" fm
+               hstr wstr dstr " -o ")))
+    ;(display* cmd dest " " x "\n")     
+    (system-2 cmd dest x)
+    (if (url-exists? dest) dest #f)))
+    
 (tm-define (pdf-file->pdftocairo-raster x opts)
-  (let* ((dest (assoc-ref opts 'dest))
+  ;(display* "scm pdf-file->pdftocairo-raster " x opts "\n")
+  (let* ((last? (assoc-ref opts 'last?))
+         (fm (format-default-suffix (assoc-ref opts 'to-format)))
+         (fm (if (== fm "ps") "eps" fm))
+         (dest (if last? (assoc-ref opts 'dest)
+               (url-glue (url-temp) (string-append "." fm))))
          (fullname (url-concretize dest))
-         (fm (url-format fullname))
-         (transp (if (== fm "png") "-transp " ""))
          (suffix (url-suffix fullname))
          (name (string-drop-right fullname (+ 1 (string-length suffix))))
+         (transp (if (== fm "png") "-transp " ""))
+         (w (assoc-ref opts 'width)) ; width in pixels for raster export
+         (wstr (if w (string-append " -scale-to-x "  w) ""))
+         (h (assoc-ref opts 'height))
+         (hstr (if h (string-append " -scale-to-y "  h) ""))
          (res (get-raster-resolution opts))
-	 (cmd (get-shell-command "pdftocairo")))
-    ;;(display (string-append cmd " -singlefile " transp "-" fm " -r " res " " x " "  name))
-    (system-2 (string-append cmd " -singlefile " transp "-" fm " -r " res)
-	      x name)
+         (dstr (if (or h w) "" (string-append " -r " res)))
+         (cmd (string-append (get-shell-command "pdftocairo")" -singlefile " transp "-" fm
+               hstr wstr dstr)))
+    ;(display cmd " " x " "  name)
+    (system-2 cmd x name)
     (if (url-exists? dest) dest #f)))
 
 (tm-define (pdf-file->imagemagick-raster x opts)
-  (let* ((dest (assoc-ref opts 'dest))
+   ;(display* "scm pdf-file->imagemagick-raster " x opts "\n")
+  (let* ((last? (assoc-ref opts 'last?))
+         (fm (format-default-suffix (assoc-ref opts 'to-format)))
+         (dest (if last? (assoc-ref opts 'dest)
+               (url-glue (url-temp) (string-append "." fm))))
+         (orig (url-concretize x))
+         (w (assoc-ref opts 'width)) ; width in pixels
+         (h (assoc-ref opts 'height))
+         (geom (if (or w h) (string-append " -resize "  w "x" h "!") ""))
          (res (get-raster-resolution opts)))
-    ;;(display (string-append "convert -density " res " " x " "  dest))
-    (system-2 (string-append "convert -density " res) x dest)
-    ;; NOTE: changing the resolution to 300 (the default) causes a problem
-    ;; when converting TeXmacs documents to Html with formulas as images:
-    ;; the formulas appear way too large...
-    ;;(system-2 (string-append "convert ") x dest)
+    ;(display (string-append (get-shell-command (imagemagick-binary)) " -density " res " " orig " " geom " "  dest "\n"))
+    (system-1 (string-append (get-shell-command (imagemagick-binary)) " -density " res " " orig " " geom) dest)
     (if (url-exists? dest) dest #f)))
 
-(tm-define (gs-convert x opts)
-  ;; many options for pdf->ps/eps see http://tex.stackexchange.com/a/20884
-  ;; this one does a better rendering than pdf2ps (also based on gs):
-  (let* ((dest (assoc-ref opts 'dest))
-	 (gs (gs-binary)))
-    (system-2 (string-append gs " -q -dNOCACHE -dUseCropBox -dNOPAUSE -dBATCH -dSAFER -sDEVICE=eps2write -sOutputFile=") dest x))
-  ;; problem: 
-  ;; eps2write available starting with gs  9.14 (2014-03-26)
-  ;; epswrite removed in gs 9.16 (2015-03-30)
+(tm-define (gs-pdf2eps x opts)
+  ;(display* "scm gs-pdf2eps " x opts "\n")
+  (let* ((last? (assoc-ref opts 'last?))
+         (dest (if last? (assoc-ref opts 'dest)
+               (url-glue (url-temp) (string-append ".eps")))))
+        (cpp-gspdf2eps x dest)
+  ;; the converter in c++ properly keeps the bounding box, unlike the previous code
+    (if (url-exists? dest) dest #f))
+  )
+
+(tm-define (gs-ps2pdf x opts)
+  (display* "scm gs-ps2pdf " x opts "\n")
+  (let* ((last? (assoc-ref opts 'last?))
+         (dest (if last? (assoc-ref opts 'dest)
+               (url-glue (url-temp) (string-append ".pdf"))))
+         (pdfv (get-preference "texmacs->pdf:version"))
+         (pdfv (if (== pdfv "default") "1.4" pdfv)) 
+         (cmd (string-append (gs-binary) " -dQUIET -dNOPAUSE -dBATCH -dSAFER -sDEVICE=pdfwrite "
+                " -dUseCropBox -dFitPage -dAutoRotatePages=/None " 
+                " -dCompatibilityLevel=" pdfv 
+                " -sOutputFile=" (url-sys-concretize dest)
+                " -f " (url-sys-concretize x))))
+    (display* cmd "\n")
+    (display* (eval-system cmd) "\n")
+    (if (url-exists? dest) dest #f))
   )
 
 (tm-define (pdf-file->gs-raster x opts)
-  (let* ((dest (assoc-ref opts 'dest))
+  ;(display* "scm pdf-file->gs-raster " x opts "\n")
+  (let* ((last? (assoc-ref opts 'last?))
+         (fm (format-default-suffix (assoc-ref opts 'to-format)))
+         (dev (cond ((== fm "jpg") "jpeg")
+                    ((== fm "tif") "tiff24nc")
+                    (else "pngalpha")))
+         (dest (if last? (assoc-ref opts 'dest)
+               (url-glue (url-temp) (string-append "." fm))))
          (res (get-raster-resolution opts))
-	 (gs (gs-binary)))
-    (evaluate-system (list gs "-dBATCH" "-dNOPAUSE" "-dQUIET" "-dSAFER"
-                           "-dNOPROMPT" "-sDEVICE=pngalpha"
-                           (string-append "-r" res)
-                           (string-append "-sOutputFile="
-                                          (url-concretize dest))
-                           (url-concretize x)) '() '() '(1 2))
-    (if (url-exists? dest) dest #f)))
+         (w (assoc-ref opts 'width)) ; width in pixels
+         (h (assoc-ref opts 'height))
+         (gs (gs-binary))
+         (cl (list gs " -dBATCH" " -dNOPAUSE" " -dSAFER"
+                           " -dNOPROMPT" (string-append " -sDEVICE=" dev) " -dUseCropBox"))
+         (cl (if (and w h) (append cl `(" -dPDFFitPage" ,(string-append " -g" w "x" h)) )
+                           (rcons cl (string-append " -r" res))  ))
+         (cl (append cl `(,(string-append " -sOutputFile=" (url-sys-concretize dest))
+                           ,(string-append " " (url-sys-concretize x)))))
+         (cmd (apply string-append cl)))
+    ;(display* cl "\n")
+    ;(evaluate-system cl '() '() '(1 2)) ;for some reason this gives non-zero return code in Windows
+    (with ans (eval-system cmd) 
+      (if (url-exists? dest) dest
+        (begin (debug-message "debug-convert" (string-append "pdf-file->gs-raster failed\n"
+                 "command: " cmd "\n"
+                 "produced output: " ans "\n"))
+           #f)))))
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Formats and converters
+;; Note : Multiple converters can be defined for a given conversion
+;; (e.g. pdftocairo and pdf2svg for pdf -> svg). In that case,
+;; TeXmacs will use the latest defined converter that is available on the system
+;; => converters defined in my-init-texmacs.scm override similar ones defined here.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Graphical document and geometric image formats
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -116,17 +260,15 @@
   (:name "Pdf")
   (:suffix "pdf"))
 
-;;(converter pdf-file postscript-file
-;;  (:require (url-exists-in-path? "pdf2ps"))
-;;  (:shell "pdf2ps" from to))
-
 (converter pdf-file postscript-file
-  (:require (or (os-mingw?) (url-exists-in-path? "gs")))
-  (:function-with-options gs-convert))
+  (:require (has-gs?))
+  (:function-with-options gs-pdf2eps))
 
 (converter postscript-file pdf-file
-  (:require (url-exists-in-path? "ps2pdf"))
-  (:shell "ps2pdf" from to))
+  ;(:require (url-exists-in-path? "ps2pdf"))
+  ;(:shell "ps2pdf" from to))
+  (:require (has-gs?))
+  (:function-with-options gs-ps2pdf))
 
 (define-format xfig
   (:name "Xfig")
@@ -147,22 +289,21 @@
    (:name "Svg")
    (:suffix "svg"))
 
-(converter svg-file postscript-file
-  (:require (url-exists-in-path? "inkscape"))
-  (:shell "inkscape" "-z" "-f" from "-P" to))
-
 (converter svg-file pdf-file
-  (:require (url-exists-in-path? "inkscape"))
-  (:shell "inkscape" "-z" "-f" from "-A" to))
+  (:require (has-rsvg-convert?))
+  (:function-with-options rsvg-convert))
+  
+(converter svg-file postscript-file
+  (:require (has-rsvg-convert?))
+  (:function-with-options rsvg-convert))
 
-(converter svg-file png-file
-  (:require (url-exists-in-path? "inkscape"))
-  (:shell "inkscape" "-z" "-d" "600" from "--export-png" to))
+(converter svg-file postscript-file
+  (:require (has-inkscape?))
+  (:function-with-options inkscape-convert))
 
-(converter svg-file png-file
-  (:require (and (url-exists-in-path? "rsvg-convert")
-                 (not (url-exists-in-path? "inkscape"))))
-    (:function-with-options rsvg-convert))
+(converter svg-file pdf-file
+  (:require (has-inkscape?))
+  (:function-with-options inkscape-convert))
 
 (define-format geogebra
   (:name "Geogebra")
@@ -176,6 +317,14 @@
   (:require (url-exists-in-path? "geogebra"))
   (:shell "geogebra" "--export=" to "--dpi=600" from))
 
+(converter pdf-file svg-file 
+  (:require (has-inkscape?))
+  (:function-with-options inkscape-convert))
+  
+(converter pdf-file svg-file
+  (:require (url-exists-in-path? "pdf2svg"))
+  (:shell "pdf2svg" from to))
+
 ;;(converter pdf-file postscript-document
 ;;  (:require (has-pdftocairo?))
 ;;  (:shell "pdftocairo" "-eps" from to))
@@ -188,17 +337,9 @@
   (:require (has-pdftocairo?))
   (:shell "pdftocairo" "-origpagesizes -nocrop -nocenter -svg" from to))
   
-(converter pdf-file svg-file
-  (:require (url-exists-in-path? "pdf2svg"))
-  (:shell "pdf2svg" from to))
-
-(converter svg-file postscript-document
-  (:require (qt5-or-later-gui?))
-  (:function image->psdoc))
- 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Bitmap image formats
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-format xpm
   (:name "Xpm")
@@ -266,6 +407,18 @@
 
 (converter pnm-file postscript-document
   (:function image->psdoc))
+  
+(define-format webp
+  (:name "Webp")
+  (:suffix "webp"))
+
+(converter webp-file png-file
+  (:require (url-exists-in-path? "dwebp"))
+  (:shell "dwebp" from "-o" to))
+  
+(converter png-file webp-file
+  (:require (url-exists-in-path? "cwebp"))
+  (:shell "cwebp" from "-o" to))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; From vector graphics to bitmaps
@@ -273,21 +426,15 @@
 
 (converter pdf-file png-file
   (:require (has-convert?))
-  (:function-with-options pdf-file->imagemagick-raster)
-  ;;(:option "texmacs->image:raster-resolution" "300")
-  )
+  (:function-with-options pdf-file->imagemagick-raster))
   
 (converter pdf-file jpeg-file
   (:require (has-convert?))
-  (:function-with-options pdf-file->imagemagick-raster)
-  ;;(:option "texmacs->image:raster-resolution" "300")
-  )
+  (:function-with-options pdf-file->imagemagick-raster))
  
 (converter pdf-file tif-file
   (:require (has-convert?))
-  (:function-with-options pdf-file->imagemagick-raster)
-  ;;(:option "texmacs->image:raster-resolution" "300")
-  )
+  (:function-with-options pdf-file->imagemagick-raster))
 
 (converter pdf-file png-file
   (:require (has-pdftocairo?))
@@ -298,9 +445,7 @@
 
 (converter pdf-file jpeg-file
   (:require (has-pdftocairo?))
-  (:function-with-options pdf-file->pdftocairo-raster)
-  ;;(:option "texmacs->image:raster-resolution" "300")
-  )
+  (:function-with-options pdf-file->pdftocairo-raster))
 
 (converter pdf-file png-file
   (:require (has-gs?))
@@ -313,3 +458,11 @@
 (converter pdf-file tif-file
   (:require (has-gs?))
   (:function-with-options pdf-file->gs-raster))
+
+(converter svg-file png-file
+  (:require (has-rsvg-convert?))
+  (:function-with-options rsvg-convert))
+
+(converter svg-file png-file
+  (:require (has-inkscape?))
+  (:function-with-options inkscape-convert))
diff --git a/TeXmacs/progs/convert/images/tmimage.scm b/TeXmacs/progs/convert/images/tmimage.scm
index 3696c689..a78a074f 100644
--- a/TeXmacs/progs/convert/images/tmimage.scm
+++ b/TeXmacs/progs/convert/images/tmimage.scm
@@ -3,13 +3,19 @@
 ;; MODULE      : tmimage.scm
 ;; DESCRIPTION : convert texmacs fragment (selection) to image formats.
 ;;               Try embedding source code in image
-;; COPYRIGHT   : (C) 2012  Philippe Joyez
+;; COPYRIGHT   : (C) 2012-2022  Philippe Joyez
 ;;
 ;; This software falls under the GNU general public license version 3 or later.
 ;; It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
 ;; in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; convert active selection to various graphics format
+;; If target is svg embed texmacs code of the selection in the image for
+;; re-edition (Could be done for other formats too).
+;; the svg produced by this method can be pasted in inkscape via the clipboard
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (texmacs-module (convert images tmimage)
   (:use (convert tmml tmmlout)
@@ -18,30 +24,46 @@
 ;; (display "Texmacs] Loading module tmimage\n")
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; convert active selection to various graphics format
-;; try embedding texmacs code of the selection in metadata of the image for
-;; re-edition.
-;; the svg produced by this method can be pasted in inkscape via the clipboard
+;; Handling of image convertion preferences
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define (default-image-export-format)
   (if (nnot (converter-search "pdf-file" "svg-file")) "svg" "pdf"))
 
 (define-preferences
-  ("texmacs->image:format" (default-image-export-format) noop))
+  ("texmacs->image:format" (default-image-export-format) noop)
+  ("texmacs->image:scale" "2.0" noop)
+  ("texmacs->image:raster-resolution" "300" noop))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; private functions
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-;; temporary files with extensions
-
 (define (url-temp-ext ext)
+;; temporary files with extensions
   (url-glue (url-temp) (string-append "." ext)))
-
-;; new system function call that check that output is produced
-;; and give minimum information if not
-
+  
+(define (myhash s)
+  (if (defined? 'string-hash) 
+    (format #f "~x"  (string-hash s 16777215))
+  ; string-hash not in s7
+  ;computes adler32 with string's bytes 
+  ;adapted for 24 bits to give 6 hex digits
+  (format #f "~x" (myhash-aux 1 0 (vector->list (string->byte-vector  s))) ) 
+  ))
+        
+(define (myhash-aux s1 s2 bl)
+  (let* ((x (car bl))
+         (s3 (modulo (+ s1 x) 4093 )) ;; last 12-bits prime - originally 65521 last 16-bits prime
+         (s4 (modulo (+ s2 s3) 4093 )))
+        (if (= 1 (length bl))
+          (+ (ash s4 12) s3)
+          (myhash-aux s3 s4 (cdr bl) ))
+  )) 
+
+(if (not (defined? 'string-contains)) ; for s7
+    (define (string-contains ss s)
+       (string-position s ss)))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; commodity functions for tree manipulations
@@ -65,13 +87,16 @@
 
 (define (remove-node-raise-children! node . firstlast)
   ;; similar to "remove tag" operation in the editor
+  ;; if no extra args are given all children are raised
+  ;; if only one extra arg is given all children starting from this one are raised
+  ;; if last is specified, children up to last (included) are raised
   (let* ((parent (tree-ref node :up))
-         (pos (+ (tree-index node) 1))
-         (lastindex (if (< (length firstlast) 2) (- (tree-arity node) 1) (cadr firstlast) ))
-         (firstindex (- (if (null? firstlast) 0 (car firstlast)) 1)))
-    (do ((i lastindex (- i 1))) ((= i firstindex))
-      (copy-node! (tree-ref node i) parent pos))
-    (remove-node! node)
+         (pos (tree-index node))
+         (lastindex+1 (if (< (length firstlast) 2) (tree-arity node) (+ (cadr firstlast) 1) ))
+         (firstindex (if (null? firstlast) 0 (car firstlast)))
+         (cl (select node `((:range ,firstindex ,lastindex+1)))))
+    (tree-insert! parent (+ pos 1) cl)
+    (tree-remove! parent pos 1)
     ))
 
 (define (replace-leaftext! leaf newtext)
@@ -79,46 +104,65 @@
   ;; Makes the node a leaf if it wasn't one
   (tree-assign! leaf (string->tree newtext)))
 
+(define (selection-trim-ending)
+ 	  	   (if (selection-active-any?)
+	  	     (with st (selection-tree)
+ 	  	       (if (and (not  (tree-atomic? st ))
+	  	                (tree-empty? (tree-ref st :last)))
+	  	         (begin
+	  	           (selection-set
+ 	  	             (selection-get-start)
+ 	  	             (path-previous (root-tree) (selection-get-end)))
+	  	           (selection-trim-ending))))))
+  
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; 2 functions for remapping cross-referenced items (glyphs)
+;; Main functions needed for making reeditable svg
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define (replace-hlinks! svgroot defs tm-fragment-string)
+;; function for remapping cross-referenced items (glyphs)
 ;; in the svg using unique ids. This is needed to avoid collisions between
 ;; definitions belonging to differents formulas in inkscape
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  (let* 
+    ((deflist (select defs '(:* @ id :%1)))
+     ;; list of all ids in the drawing, pointed to by 'clip-path'
+     ;; attributes or xlink:href attribute of 'use' nodes 
+     (hreflist (select svgroot '(:* @ (:or xlink:href clip-path style) :%1)))
+     (unique (myhash tm-fragment-string))
+     ;; generate a reproducible 6-digit hex number that depends
+     ;; on the tm code of the selection
+     (basename (string-append "tm" unique "-"))
+     (n (length deflist)))
+    (if (> n 0)
+      (do ((i 0 (+ i 1))) ((= i n))
+        (let* 
+          ((labelnode (list-ref deflist i))
+           ;(deftype (tree-label (tree-ref labelnode :up :up :up)))
+           (newlabel (string-append basename (number->string i)))
+           (callerfound #f))
+          (map 
+            (lambda (x) 
+              (let* 
+                ((stylestr (tree->string x))
+                 (labelstr (tree->string labelnode))
+                 (labelength (string-length labelstr))
+                 (pos (string-contains stylestr labelstr)))
+                (if (and pos (or (== (string-length stylestr) (+ pos labelength)) (== (substring stylestr (+ pos labelength) (+ 1 pos labelength)) ")")))
+                  (begin 
+                    (replace-leaftext! x (string-replace stylestr labelstr newlabel))
+                    (set! callerfound #t)))))
+            hreflist)
+          (if callerfound
+            (replace-leaftext! labelnode newlabel)
+            ;(remove-node! (tree-ref labelnode :up :up :up)) ;;that def was previously removed or never used (it happens!)
+            ) 
+        )))))
 
-(define (newids! lablist tm-fragment-string)
-  ;; replaces all ids in the svg
-  ;; plus returns an associationlist for mapping old id to new ones
-  ;; we will use it to replace hyperlinks to the former ids to the new ones
-  (let* ((unique (number->string (string-hash tm-fragment-string 1000000)))
-         ;; generate a reproducible 6-digit number that depends
-         ;; on the tm code of the selection
-         (basename (string-append "tm" unique "-"))
-         (newalist '())
-         (n (length lablist)))
-    (do ((i 0 (+ i 1))) ((= i n))
-      (let* ((newlabel (string-append basename (number->string i)))
-             (labelnode (list-ref lablist i))
-             (oldlabel (tree->string labelnode)))
-        (set! newalist (assoc-set! newalist (string-append "#" oldlabel)
-                                   (string-append "#" newlabel) ))
-        (replace-leaftext! labelnode newlabel)))
-    newalist))
-
-(define (replace-hlinks! hreflist alist)
-  ;; use the above association list to actualy replace
-  ;; the xlink:href items with updated targets
-  (map (lambda (leaf)
-         (let ((newtarget (assoc-ref alist (tree->string leaf))))
-           (replace-leaftext! leaf newtarget)))
-       hreflist))
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; define latex and texmacs string representation of selection
 ;; we escape them to ascii so that they do not interfere with xml
 ;; <  -> &lt;  > -> &gt; \ -> \\, all characters above #127->\xXX ...
 ;; see  TeXmacs/langs/encodings/cork-escaped-to-ascii.scm
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
 (define (latex-encode tm-fragment-tree)
   ;; for the latex representation we mimick what is done when
   ;; "copy to latex" is performed
@@ -131,87 +175,72 @@
 (define (tm-encode tm-fragment-tree)
   (escape-to-ascii (serialize-texmacs tm-fragment-tree)))
 
-(define (remove-clip! clipg)
-  (let* ((parent (tree-ref clipg :up))
-         (pos (+ (tree-index clipg) 1))
-         (lastindex (- (tree-arity clipg) 1)))
-    (do ((i lastindex (- i 1))) ((= i 0))
-      (let* ((node (tree-ref clipg i)))
-             (move-node! node parent pos)))
-    (remove-node! clipg)
-    ))
-
-(tm-define (cr2? s) (or (equal? (tree->stree s) "\n") (equal? (tree->stree s) "\n  ")))
-
-(define (refactor-svg dest tm-fragment)
-  ;; reorganize svg file and inject attributes containing tm code of
-  ;; equation. dest is the url of the svg file to be edited
-  ;; A latex fragment is also added for compatibility with
-  ;; 'textext' inkscape extension
-  ;; FIXME : no error checking, no return value...
-  ;; for improvements (we could pass the style that was used when
-  ;; the equation was created, the fonts,...)
-
+(define (refactor-svg dest tm-fragment relbaseline)
+;; dest is the url of the svg file to be edited
+;; We reorganize & cleanup the svg file and inject attributes containing:
+;; - the tm code of equation
+;; - style info from the original document (style, fonts, layout, ...)
+;; - A latex fragment for compatibility with 'textext' inkscape extension
+;; - the relative position of the baseline to enable vertical alignement
+;;   in an external application
+;; FIXME : no error checking, no return value...
 
   (let*
-      (;; first: load svg and transform to an active tree in
-       ;; temporary buffer so that we can manipulate it
-       ;; using texmacs primitives for trees
-       (svg-in (string-load dest)) ;; load svg file as string
-       (s-svg-in (parse-xml svg-in)) ;; parse to stree
-       (mybuf (buffer-new))
-       ;; create temporary buffer for subsequent manipulations of svg tree
-       (void (buffer-set-body mybuf (tree-assign-node! (stree->tree s-svg-in)
-                                                       'concat)))
-       ;; populate buffer with tree
-       ;; replace *TOP* node by concat otherwise displaying
-       ;; that buffer crashes texmacs
-
-       ;; second: define a bunch of locations in the tree
-       (buftree (buffer-get-body mybuf)) ;; the whole tree
-       (svgroot (car (select buftree '(:* svg)))) ;; the <svg > node
-       (maingroup (car (select svgroot '(g))))
-       ;; the main group in the svg, containing the drawing layout
-       (maingroup-attrib (car (select maingroup '(@))))
-       ;; attributes of the main group
-       (defs (car (select svgroot '(defs))))
-       ;; the defs, containing the glyph vector outlines,
-       ;; hyperlinked from the drawing (a.k.a cloned)
-       (idlist (select svgroot '(:* id :%1)))
-       ;; list of all ids in the drawing, used to label glyph outlines
-       (hreflist (select maingroup '(:* @ xlink:href :%1)))
-       ;; list of hyperlinks to the glyphs labels
-
-       ;; third: the new data we want to insert in the tree
-       (latex-code (latex-encode tm-fragment))
-       (tm-code (tm-encode tm-fragment))
-       (tm-style (tm-encode (get-all-inits)))
-       ;; define new attributes containing latex and texmacs code:
-       (extra-latex-attrib
-        `((xmlns:ns0 "http://www.iki.fi/pav/software/textext/")
-          (ns0:text ,latex-code) (ns0:preamble "texmacs_latex.sty")))
-       (extra-tm-attrib `((xmlns:ns1 "https://www.texmacs.org/")
-                          (ns1:texmacscode ,tm-code) (ns1:texmacstyle ,tm-style)))
-       ;; OK, the texmacs namespace maybe not correctly described at that url
-       (old->new-labels (newids! idlist tm-code))
-       ;; rename all ids, create an association list of old to new ids
-       )
-
-    ;; fourth: modify tree
-    (replace-hlinks! hreflist old->new-labels)
-    ;; replace hlinks with new pointers
-    (map remove-node! (select svgroot '(:* (:match :cr2?))))
-    (map remove-clip! (reverse (select maingroup '(:* g @ clip-path :up :up))))
-    (map remove-node! (select defs '(:* clipPath) ))
-    ;; cleanup & simplify svg tree removing unecessary clips
-    (tree-insert! maingroup-attrib 1 extra-latex-attrib)
-    ;; for textext compatibility
+    ( ;; 1: load svg and transform to an active tree in
+      ;; temporary buffer so that we can manipulate it
+      ;; using texmacs primitives for trees
+      (svg-in (string-load dest)) ;; load svg file as string
+      (s-svg-in (parse-xml svg-in)) ;; parse to stree
+      (mybuf (buffer-new))
+      ;; create temporary buffer for subsequent manipulations of svg tree
+      (void (buffer-set-body mybuf (tree-assign-node! (stree->tree s-svg-in)
+                                                     'concat)))
+      ;; populate buffer with tree
+      ;; replace *TOP* node by concat otherwise displaying
+      ;; that buffer crashes texmacs
+      
+      ;; 2: define a bunch of locations in the tree
+      (buftree (buffer-get-body mybuf)) ;; the whole tree
+      (svgroot (car (select buftree '(:* svg)))) ;; the <svg > node
+      (maingroup (car (select svgroot '(g))))
+      ;; the main group in the svg, containing the drawing layout
+      (maingroup-attrib (car (select maingroup '(@))))
+      ;; attributes of the main group
+      (defs (car (select svgroot '(defs))))
+      ;; the defs, containing the glyph vector outlines,
+      ;; hyperlinked from the drawing (a.k.a cloned)
+      (bgframe (select maingroup '(:* path @ style :%1)))
+      (bgframe (if (null? bgframe) #f (car bgframe)))
+      ;; the solid background we introduced  
+      ;; 3: the new data we want to insert in the tree
+      (latex-code (latex-encode tm-fragment))
+      (tm-code (tm-encode tm-fragment))
+      (tm-style (tm-encode (get-all-inits)))
+      ;; define new attributes containing latex and texmacs code:
+      (extra-latex-attrib
+      `((xmlns:ns0 "http://www.iki.fi/pav/software/textext/")
+        (ns0:text ,latex-code) (ns0:preamble "texmacs_latex.sty")))
+      (extra-tm-attrib 
+      `((xmlns:ns1 "https://www.texmacs.org/")
+        (ns1:texmacscode ,tm-code) (ns1:texmacsstyle ,tm-style)
+        (ns1:texmacsbaseline ,relbaseline)))
+      ;; OK, the texmacs namespace maybe not correctly described at that url ...
+    )
+
+    ;; 4: modify tree
+    ;; 4.1 set the background fully transparent
+    (if (and bgframe (== (tree->string bgframe) " stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:0.007;")) 
+        (tree-set! bgframe " stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:0.00"))
+    ;; 4.2, replace hlinks dest names to avoid collisions in inkscape
+    (replace-hlinks! svgroot defs (string-append tm-code tm-style (get-preference "texmacs->image:scale")))
+    ;; 4.3 (not optional!), add our own new attributes for re-editting equation  
+    (tree-insert! maingroup-attrib 1 extra-latex-attrib) ;; for textext compatibility
     (tree-insert! maingroup-attrib 2 extra-tm-attrib)
-    (move-node! defs maingroup 2)
-    ;; move defs containing the glyph outlines inside main group
+    ;; 4.4 move defs containing the glyph outlines inside main group
     ;; so that they remain together in inkscape
+    (move-node! defs maingroup 2)
 
-    ;; Fifth : finally create output
+    ;; 5: finally create output
     (let* (;; convert back to stree, recreate the *TOP* node,
            ;; and restore *PI* xml
            ;; (instead of *PI* "xml" given by tree->stree -
@@ -240,81 +269,150 @@
     (set-message "Qt GUI only, sorry. Use \"Export selection...\"" "")
     (if (not (selection-active-any?))
       (set-message "no selection!" "")
-      (let* ((format (get-preference "texmacs->image:format"))
+      (begin (selection-trim-ending)
+        (let* ((format (get-preference "texmacs->image:format"))
              (tmpurl (url-temp-ext format)))
-        (export-selection-as-graphics tmpurl)
+          (export-selection-as-graphics tmpurl)
 	;; first generate an image file
-        (graphics-file-to-clipboard tmpurl)
+          (graphics-file-to-clipboard tmpurl)
 	;; place that image on the clipboard
-        (system-remove tmpurl)
-	))))
+          (system-remove tmpurl)
+	)))))
 
 (tm-define (export-selection-as-graphics myurl)
   (:synopsis "Generates graphics format of the current selection")
   (:argument myurl "A full file url with extension")
   (:returns "nothing")
-  ;; global document parameters such as style, fonts, etc. are respected
-  ;; in the typesetting. However they are presently not passed to
-  ;; the svg and therefore lost when re-editing the svg
+  ;; for svg export, the texmacs code of the selection as well as 
+  ;; global document parameters such as style, fonts, etc. are
+  ;; embedded in the drawing to enable re-editing from inkscape
 
-  (when (or (== (url-suffix myurl) "")
-            (not (converter-search "pdf-file" (file-format myurl))))
+  (if (== (url-suffix myurl) "")
     (with format (get-preference "texmacs->image:format")
-      (when (not (converter-search "pdf-file" (string-append format "-file")))
-        (set! format "pdf"))
+      (show-message (string-append "No file extension specified, defaulting to " format) "No image format given" )
       (with suffix (format-default-suffix format)
         (set! myurl (url-glue myurl (string-append "." suffix))))))
-
-  (if (not (selection-active-any?))
-      (set-message "no selection!" "")
-      (let* (
-        ;; step 1 prepare and typeset selection
-        ;; if selection is part of math need to re-encapsulate
-        ;; it with math to obtain proper typesetting :
-        (tm-fragment
-          (if (in-math?)
-              (stree->tree `(equation* (document ,(selection-tree))))
-  	          (selection-tree)))
-        ;; also if selection spans several lines of text,
-        ;; need to encapsulate it in a fixed-width table
-        ;;to enforce pagewidth :
-        (tm-fragment-enforce-pagewidth
-          (if (tree-multi-paragraph? (selection-tree))
-              (stree->tree
-                `(tabular
-                   (tformat (twith "table-width" "1par")
-			               (twith "table-hmode" "exact")
-			               (cwith "1" "1" "1" "1" "cell-hyphen" "t")
-                     (table (row (cell (document ,tm-fragment)))))))
-              (selection-tree)))
-        (temp0 (url-temp-ext "pdf"))
-        (dpi-pref (get-preference "printer dpi"))
-        (suffix (url-suffix myurl)))
-
-       (set-printer-dpi "236") ; 472 is ~ exact size
-       ;;set to a fixed value so our graphics does
-       ;;not depend on the printer dpi
-       ;;We need to set this weird dpi value so that the size of the svg
-       ;;produced is about twice that of direct pdf or ps output. Why??
-       (print-snippet temp0 tm-fragment-enforce-pagewidth #t)
-       ;;typeset fragment to ps as starting point
-       (set-printer-dpi dpi-pref)
-       ;; revert to preference dpi
-       ;; step 2 generate output according to desired output format
-
-       (cond
-        ((== suffix "pdf") (system-copy temp0 myurl))
-        ((== suffix "svg")
-         ;; assume target is inkscape
-         (file-convert temp0 myurl)
-         ;; using either pdf2svg or pdf2cairo converters is crucial
-         ;; for svg inport in inkscape:
-         ;; fonts are properly passed as vector outlines
-         ;; file converters are defined in init-images.scm
-         (refactor-svg myurl tm-fragment))
-         ;; modify svg, embedding texmacs code
-        (else
-         (file-convert temp0 myurl)))
-
-       (system-remove temp0) ;; temp pdf file not needed anymore
-  )))
+  
+  (with suffix (url-suffix myurl)
+    (when (not (file-converter-exists? "x.pdf" (string-append "y." suffix)))
+      (show-message (string-append "Sorry, pdf to " suffix " converter is missing. Generating pdf instead") "Image format not available" )
+      (let* ((sufl (string-length suffix))
+            (surl (url->string myurl))
+            (sl (string-length surl))) 
+        (set! myurl (string->url (string-append (substring surl (- sl sufl) sl) "pdf"))))))
+
+; TODO Handle when output file already exists (presently we overwritte without warning)
+
+  (cond
+   ((not (selection-active-any?)) (set-message "no selection!" ""))
+   (else 
+    (let*
+     (
+;; step 1 prepare and typeset selection
+;; if selection is inside inline or display math preserve inline/display style
+
+      (tm-fragment
+        (cond
+          ((match? (tree->stree (selection-tree)) 
+                    '(:or (equation* :*) (equation :*) (eqnarray :*) (eqnarray* :*) (math :*)))
+            (display "is some math \n") (selection-tree)) 
+          ((==  (tree->string (get-env-tree-at "mode" (selection-get-start))) "math")
+             (if (==  (tree->string (get-env-tree-at "math-display" (selection-get-start))) "true")
+               (begin 
+                 (display "in display math \n") 
+                 (stree->tree `(equation* (document ,(selection-tree)))))
+               (begin 
+                 (display "in math \n")
+	             (stree->tree `(math (document ,(selection-tree)))))))
+          (else (display "other \n")(selection-tree))))
+;; is selection wider than 1par (and needs linebreaks and or hyphenation)?
+      (maxwidth (length-decode "1par"))
+      (partmpt (string-append (number->string maxwidth) "tmpt"))
+      (parcm (length-add  "0cm" partmpt))
+      (pagewcm (length-add  "0cm" (string-append (number->string (+ 1 (*  (get-page-width #t) 10))) "tmpt")))
+      ;; get-page-width return dimension in the cpp "SI" unit which seems to be == "10tmpt"
+;; output scale of image?
+      (str-scale  (get-preference "texmacs->image:scale"))
+      (scale (string->number str-scale))
+
+;; We compute the baseline position only if it's a single-line content
+;; This excludes selections begining with 'document
+;; If the selection is a 'concat we need to check if it does not exceed the page width
+;; If the selection is eqnarray(*) compute it only if it has a single line
+;;  (table-nr-rows) works for this!
+      (iseqnarray (match? (tree->stree tm-fragment) '(:or (eqnarray :*) (eqnarray* :*) (:* align* :*))))
+      (simpleeqnarray (and iseqnarray (== 1 (table-nr-rows)))) 
+      (needbaseline 
+        (if (match? (tree->stree tm-fragment) '(document :*)) 
+          #f   
+         (or
+          simpleeqnarray
+          (< (string->number (cadr (box-info tm-fragment "W"))) (length-decode "1par")))))
+;; the baseline calculation is relative to the size of the background
+;; if not fully transparent, poppler puts the background in the svg image (otherwise no)
+;; (during svg postprocessing  we'll set the opacity of the background to 0)  
+      (fillcolor (if needbaseline "#ffffff02" "#ffffff00")) ; either slightly opaque or fully transparent white
+
+
+;; if needbaseline use a table and set background color
+;; otherwise (multiline selection) use doc-at to get proper pagewidth
+      (tm-fragment-formated 
+         (if iseqnarray 
+           `(document (tformat (twith table-hmode min) ,tm-fragment)) ;reduce table width to min, to avoid wide empty frame
+           tm-fragment))
+      (tm-fragment-formated
+        (if needbaseline
+          (stree->tree `(with "magnify" ,str-scale "page-width" 
+            ,(length-mult scale pagewcm)
+            ;"text-at-valign" "base"
+            ;(text-at 
+             (tabular (tformat 
+                (twith "table-width" ,(length-mult scale parcm))
+                (twith "table-hmode" "min")
+                (twith "table-valign" "B") ;;(=top baseline)
+                (cwith "1" "-1" "1" "-1" "cell-background" ,fillcolor)
+                (cwith "1" "1" "1" "1" "cell-hyphen" "t")
+                (cwith "1" "-1" "1" "-1" "cell-lsep" "0spc")
+                (cwith "1" "-1" "1" "-1" "cell-tsep" "0sep")
+                (cwith "1" "-1" "1" "-1" "cell-rsep" "0spc")
+                (cwith "1" "-1" "1" "-1" "cell-bsep" "0sep")
+                (table (row (cell (document ,tm-fragment))))))
+             ; (point "0par" "0"))
+              ))
+        (stree->tree `(with "magnify" ,str-scale "page-width" 
+          ,(length-mult scale pagewcm) 
+          "doc-at-width" ,(length-mult scale parcm) "doc-at-hmode" "min" "doc-at-padding" "0spc";"doc-at-ppsep" "" 
+             (document-at (document ,tm-fragment-formated ) (point "0par" "0"))))))
+
+    (temp1 (url-temp-ext "pdf"))
+    (suffix (url-suffix myurl))
+
+    (extents (print-snippet temp1 (stree->tree tm-fragment-formated) #t))
+;; compute relative position of baseline from returned box dimensions  see tmhtml.scm
+    (y3 (second extents))
+    (y4 (fourth extents))
+    (y1 (sixth extents))
+    (height (- y4 y3))
+    (relbaseline (if needbaseline (number->string (exact->inexact (/ (- y1) height))) "0.0"))
+		   )
+
+	;; step 2 generate output according to desired output format
+
+	  (cond 
+	    ((== suffix "pdf") (system-copy temp1 myurl))
+	    ((== suffix "svg")
+	       ;; assume target is inkscape
+		   (file-convert temp1 myurl)
+		 ;; file converters are defined in init-images.scm
+		 ;; it is crucial to use poppler-based converters:
+		 ;; either pdf2svg or pdf2cairo or inkscape itself,
+		 ;; this ensures fonts are properly passed
+		 ;; as vector outlines for wysiwyg  svg
+         (display* "relbaseline= " relbaseline "\n")
+         (refactor-svg myurl tm-fragment relbaseline))
+		 ;; modify svg, embedding texmacs code
+	    (else
+            (file-convert temp1 myurl)))
+
+	  (system-remove temp1) ;; temp pdf file not needed anymore
+	))))
diff --git a/TeXmacs/progs/kernel/texmacs/tm-convert.scm b/TeXmacs/progs/kernel/texmacs/tm-convert.scm
index 92276843..b299ba72 100644
--- a/TeXmacs/progs/kernel/texmacs/tm-convert.scm
+++ b/TeXmacs/progs/kernel/texmacs/tm-convert.scm
@@ -237,6 +237,7 @@
         (if fun
             (let* ((last? (null? (cdr path)))
                    (opts1 (acons 'last? last? options))
+                   (opts1 (acons 'to-format (car path) opts1))
                    (opts2 (std-converter-options from (car path)))
                    (what* (fun what (append opts1 opts2)))
                    (result (convert-via what* (car path) (cdr path) options)))
@@ -450,7 +451,7 @@
          '("ps" "eps" "bmp" "gif" "ico" "tga" "pcx" "wbmp" "wmf" "jpg"
            "jpeg" "png" "tif" "jbig" "ras" "pnm" "jp2" "jpc" "pgx"
            "cut" "iff" "lbm" "jng" "koa" "mng" "pbm" "pcd" "pcx"
-           "pgm" "ppm" "psd" "tga" "tiff" "xbm" "xpm"))
+           "pgm" "ppm" "psd" "svg" "tga" "tiff" "xbm" "xpm"))
         ((== fm "image") (format-image-suffixes))
         ((== fm "sound")
          '("au" "cdr" "cvs" "dat" "gsm" "ogg" "snd" "voc" "wav"))
diff --git a/TeXmacs/progs/prog/glue-symbols.scm b/TeXmacs/progs/prog/glue-symbols.scm
index 2fef8eaa..d77251a7 100644
--- a/TeXmacs/progs/prog/glue-symbols.scm
+++ b/TeXmacs/progs/prog/glue-symbols.scm
@@ -184,6 +184,7 @@
 "font-family-main"
 "image->psdoc"
 "anim-control-times"
+"cpp-gspdf2eps"
 "tree->stree"
 "stree->tree"
 "tree->string"
diff --git a/TeXmacs/progs/texmacs/menus/preferences-widgets.scm b/TeXmacs/progs/texmacs/menus/preferences-widgets.scm
index 877e7c50..20a87937 100644
--- a/TeXmacs/progs/texmacs/menus/preferences-widgets.scm
+++ b/TeXmacs/progs/texmacs/menus/preferences-widgets.scm
@@ -596,35 +596,42 @@
    (eval `(define-preference-names "texmacs->image:format" ,@valid-image-format-list))
    (cadr (apply map list valid-image-format-list))))
 
-(define (supports-inkscape?) (url-exists-in-path? "inkscape"))
+;;(define (supports-inkscape?) (url-exists-in-path? "inkscape"))
 
 (tm-widget (image-preferences-widget)
   ======
   (bold (text "TeXmacs -> Image"))
   ===
-  (aligned
-    (item (text "Bitmap resolution (dpi):")
-      (enum (set-preference "texmacs->image:raster-resolution" answer)
-            '("1200" "600" "300" "150" "")
-            (get-preference "texmacs->image:raster-resolution")
-            "8em"))
-    (item (text "Clipboard image format:")
-      (enum (set-pretty-preference "texmacs->image:format" answer)
-            (pretty-format-list)
-            (get-pretty-preference "texmacs->image:format")
-            "8em")))
-  ====== ======
-  (bold (text "Image -> TeXmacs"))
-  ===
-  (aligned
-    (meti
-      (when (supports-inkscape?)
-        (hlist // (text "Use Inkscape for conversion from SVG")))
-      (when (supports-inkscape?)
-        (toggle (set-boolean-preference
-                 "image->texmacs:svg-prefer-inkscape" answer)
-                (get-boolean-preference
-                 "image->texmacs:svg-prefer-inkscape"))))))
+    (aligned
+        (item (text "Clipboard image format:  ")
+          (enum (set-pretty-preference "texmacs->image:format" answer)
+              (pretty-format-list)
+              (get-pretty-preference "texmacs->image:format")
+           "8em"))
+        (item (text "Selection export scale:  ")
+          (enum (set-pretty-preference "texmacs->image:scale" answer)
+            '("1" "1.5" "2" "")
+            (get-pretty-preference "texmacs->image:scale")
+            "8em")) 
+        (item (text "Bitmap export resolution (dpi):  ")
+          (enum (set-preference "texmacs->image:raster-resolution" answer)
+              '("1200" "600" "300" "150" "")
+              (get-preference "texmacs->image:raster-resolution")
+              "8em")))
+;; not used presently
+;;  ====== ======
+;;  (bold (text "Image -> TeXmacs"))
+;;  ===
+;;  (aligned
+;;    (meti
+;;      (when (supports-inkscape?)
+;;        (hlist // (text "Use Inkscape for conversion from SVG")))
+;;      (when (supports-inkscape?)
+;;        (toggle (set-boolean-preference
+;;                 "image->texmacs:svg-prefer-inkscape" answer)
+;;                (get-boolean-preference
+;;                 "image->texmacs:svg-prefer-inkscape")))))
+)
 
 ;; All converters ----------
 
diff --git a/src/Edit/Editor/edit_main.cpp b/src/Edit/Editor/edit_main.cpp
index 5673e5ce..2acaf33b 100644
--- a/src/Edit/Editor/edit_main.cpp
+++ b/src/Edit/Editor/edit_main.cpp
@@ -402,7 +402,11 @@ edit_main_rep::print_snippet (url name, tree t, bool conserve_preamble) {
   env->update ();
   
   if (b->x4 - b->x3 >= 5*PIXEL && b->y4 - b->y3 >= 5*PIXEL) {
-    if (bitmap) make_raster_image (name, b, 5.0);
+    if (bitmap) {
+      int out_dpi = as_int(get_preference ("texmacs->image:raster-resolution"));
+      double zoomf= (double) 5.0*out_dpi/dpi ; //5 hard coded in make_raster_image
+      make_raster_image (name, b, zoomf);
+    }
     else if (ps) make_eps (name, b, dpi);
     else {
       url temp= url_temp (use_pdf ()? ".pdf": ".eps");
diff --git a/src/Plugins/Ghostscript/gs_utilities.cpp b/src/Plugins/Ghostscript/gs_utilities.cpp
index c07b1f1e..70e2a5ef 100644
--- a/src/Plugins/Ghostscript/gs_utilities.cpp
+++ b/src/Plugins/Ghostscript/gs_utilities.cpp
@@ -83,16 +83,8 @@ string
 eps_device () {
   static string dev; // no need to resolve each time
   if (dev == "") {
-    string cmd= gs_prefix ()*" --version";
-    string buf= var_eval_system (cmd);
-    double ver;
-    int pos=0;
-    if (read_double (buf, pos, ver)) {
-      if (DEBUG_CONVERT) debug_convert << "gs version :"<<buf<<LF;
-      if (ver >= 9.14) dev="eps2write";
+      if (gs_version () >= 9.14) dev="eps2write";
       else dev="epswrite";
-    }
-    else  convert_error << "Cannot determine gs version"<<LF;
   }
   return copy(dev);
 }
@@ -323,29 +315,27 @@ gs_to_png (url image, url png, int w, int h) { //Achtung! w,h in pixels
   int bbw, bbh;
   int rw, rh;
   int bx1, by1, bx2, by2;
-  if (suffix (image) == "pdf") 
+  if (suffix (image) == "pdf") {
     image_size (image, bbw, bbh);
     //don't call gs_PDFimage_size 
     //in order to benefit from caching
+    cmd << "-dUseCropBox -dPDFFitPage "; // old gs versions (<9.0 ?) fail if CropBox not explicitly defined
+    cmd << sys_concretize (image);
+  }
   else {
     ps_bounding_box (image, bx1, by1, bx2, by2); //same comment
     bbw=bx2-bx1;
     bbh=by2-by1;
-  }
-  rw=(w*72)/bbw;
-  rh=(h*72)/bbh;
-  cmd << "-r" << as_string (rw) << "x" << as_string (rh) << " ";  
+/*    rw=(w*72)/bbw;
+    rh=(h*72)/bbh;
+    cmd << "-r" << as_string (rw) << "x" << as_string (rh) << " ";  
   
-  if (DEBUG_CONVERT) debug_convert << "w="<<w<<" h="<<h<<LF
+    if (DEBUG_CONVERT) debug_convert << "w="<<w<<" h="<<h<<LF
       << "bbw="<<bbw<<" bbh="<<bbh<<LF
       <<" res ="<<rw<<" * "<<rh <<LF;
-  
-  if (suffix(image) == "pdf") {
-    cmd << "-dUseCropBox "; // old gs versions (<9.0 ?) fail if CropBox not explicitly defined
-    cmd << sys_concretize (image);
-  }
-  else {
-    //don't use -dEPSCrop which works incorrectly if (bx1 != 0 || by1 != 0)
+*/ 
+   cmd << "-dEPSFitPage ";
+   //don't use -dEPSCrop which works incorrectly if (bx1 != 0 || by1 != 0)
     cmd << "-c \" "<< as_string (-bx1) << " "<< as_string (-by1) <<" translate gsave \"  -f "
             << sys_concretize (image) << " -c \" grestore \"";    
   }
@@ -368,6 +358,7 @@ gs_to_eps (url image, url eps) { //this should be used mostly for pdf->eps conve
   cmd << "-dQUIET -dNOPAUSE -dBATCH -dSAFER ";
   cmd << "-sDEVICE=" << eps_device ();
   cmd << " -sOutputFile=" << sys_concretize (eps) << " ";
+  if (suffix (eps) == "eps") cmd << "-sPageList=1 ";
   if (suffix (image) == "pdf") {
     image_size (image, bx2, by2);
     bx1=by1=0;
diff --git a/src/Plugins/Qt/qt_picture.cpp b/src/Plugins/Qt/qt_picture.cpp
index 8e7d8443..27b34f5a 100644
--- a/src/Plugins/Qt/qt_picture.cpp
+++ b/src/Plugins/Qt/qt_picture.cpp
@@ -235,13 +235,30 @@ may_transform (url file_name, const QImage& pm) {
 QImage*
 get_image_for_real (url u, int w, int h, tree eff, SI pixel) {
   QImage *pm = NULL;
-
+  if (DEBUG_CONVERT) debug_convert << "qt loading image " << concretize (u) <<LF;
   if (suffix (u) == "svg") {
-    QSvgRenderer renderer (utf8_to_qstring (concretize (u)));
-    pm= new QImage (w, h, QImage::Format_ARGB32);
-    pm->fill (Qt::transparent);
-    QPainter painter (pm);
-    renderer.render (&painter);
+    //if we have a good scm-defined converter for SVG (Inkscape or rsvg-convert)
+    //always use it as it can handle properly svg full spec, whereas QSvg handles only SVG tiny
+    url temp= url_temp (".png");
+    if (call_scm_converter(u, temp, w, h)) { 
+      pm= new QImage (utf8_to_qstring (as_string (temp)));
+      remove (temp);
+    }
+    else {
+      if (! svg_is_tiny(u)) {
+        convert_warning << "The image '" << concretize (u) << "' is not declared as Tiny SVG;"<< LF
+         << "Texmacs' Qt-based svg image backend may render it incorrectly."<< LF
+         << "In that case, consider converting the image to pdf."<< LF
+         << "As an alternative, you may install Inkscape or rsvg-convert;"<< LF
+         << "TeXmacs will then use it automatically in place of Qt for handling svg."<< LF;
+      }
+      if (DEBUG_CONVERT) debug_convert << "using native qt" <<LF;
+      QSvgRenderer renderer (utf8_to_qstring (concretize (u)));
+      pm= new QImage (w, h, QImage::Format_ARGB32);
+      pm->fill (Qt::transparent);
+      QPainter painter (pm);
+      renderer.render (&painter);
+    }
   } else if (qt_supports (u)) {
     pm= new QImage (utf8_to_qstring (concretize (u)));
   } else {
diff --git a/src/Plugins/Qt/qt_utilities.cpp b/src/Plugins/Qt/qt_utilities.cpp
index 39f976ca..8f9777b9 100644
--- a/src/Plugins/Qt/qt_utilities.cpp
+++ b/src/Plugins/Qt/qt_utilities.cpp
@@ -28,6 +28,7 @@
 #include <QPrintDialog>
 #include <QImageReader>
 #include <QApplication>
+#include <QSvgRenderer>
 
 #include "colors.hpp"
 
@@ -475,61 +476,79 @@ qt_convert_image (url image, url dest, int w, int h) {// w, h in pixels
 
 void
 qt_image_to_pdf (url image, url outfile, int w_pt, int h_pt, int dpi) {
-// use a QPrinter to output raster images to eps or pdf
+// use a QPrinter to output images to eps or pdf
 // dpi is the maximum dpi : the image will either be dowsampled to that dpi
 // or the actual dpi will be lower  
   if (DEBUG_CONVERT) debug_convert << "qt_image_to_eps_or_pdf " << image << " -> "<<outfile<<LF;
-  QPrinter printer;
+  QPrinter printer(QPrinter::HighResolution);
   printer.setOrientation(QPrinter::Portrait);
-  if (suffix(outfile)=="eps") {
-#if (QT_VERSION >= 0x050000)
-    //note that PostScriptFormat is gone in Qt5. a substitute?: http://soft.proindependent.com/eps/
-    cout << "TeXmacs] warning: PostScript format no longer supported in Qt5\n";
-    printer.setOutputFormat(QPrinter::PdfFormat);
-#else    
+#if (QT_VERSION < 0x050000)
+//PostScriptFormat is gone in Qt5. 
+  if (suffix(outfile)=="eps") 
     printer.setOutputFormat(QPrinter::PostScriptFormat);
+  else 
 #endif
-  }
-  else printer.setOutputFormat(QPrinter::PdfFormat);
+    printer.setOutputFormat(QPrinter::PdfFormat);
   printer.setFullPage(true);
   if (!dpi) dpi=96; 
   printer.setResolution(dpi);
   printer.setOutputFileName(utf8_to_qstring (concretize (outfile)));
-  QImage im (utf8_to_qstring (concretize (image)));
-  if (im.isNull ()) {
-    convert_error << "Cannot read image file '" << image << "'"
-    << " in qt_image_to_pdf" << LF;
-  // load the "?" image?
-  }
-  else {
+  printer.setPaperSize(QSizeF(w_pt, h_pt), QPrinter::Point); // in points
+  if (suffix (image) == "svg") {
+    QSvgRenderer renderer (utf8_to_qstring (concretize (image)));
+    if (renderer.isValid()) {
+      if (DEBUG_CONVERT) debug_convert << "qt printing svg to pdf " << image <<LF;
+	  QPainter p;
+      p.begin(&printer);
+      renderer.render (&p);
+      p.end();
+      }
+    else {
+      convert_error << "Cannot load svg image file '" << image << "'"
+      << " in qt_image_to_pdf" << LF;
+      }
+
+  } 
+  else { 
+    QImage im (utf8_to_qstring (concretize (image)));
+  
+    if (im.isNull ()) {
+      convert_error << "Cannot read image file '" << image << "'"
+      << " in qt_image_to_pdf" << LF;
+      // load the "?" image?
+    }
+    else {
 /*  if (DEBUG_CONVERT) debug_convert << "size asked " << w_pt << "x"<<h_pt
   << " at " << maximum dpi <<" dpi"<<LF
   << "dpi set: " << printer.resolution() <<LF;
 */
-    if (dpi > 0 && w_pt > 0 && h_pt > 0) {
-	    printer.setPaperSize(QSizeF(w_pt, h_pt), QPrinter::Point); // in points
-
-      // w_pt and h_pt are dimensions in points (and there are 72 points per inch)
-      int ww = w_pt * dpi / 72;
-      int hh = h_pt * dpi / 72;
-      if ((ww < im.width ()) ||( hh < im.height ())) //downsample if possible to reduce file size
+      if (dpi > 0 && w_pt > 0 && h_pt > 0) {
+        // w_pt and h_pt are dimensions in points (and there are 72 points per inch)
+        int ww = w_pt * dpi / 72; //pixel number needed @ dpi
+        int hh = h_pt * dpi / 72;
+        if ((ww < im.width ()) ||( hh < im.height ())) //downsample if possible to reduce file size
 	      im= im.scaled (ww, hh, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
-  	  else // image was too small, reduce dpi accordingly to fill page
-        printer.setResolution((int) (dpi*im.width())/(double)ww);
-      if (DEBUG_CONVERT) debug_convert << "dpi asked: "<< dpi <<" ; actual dpi set: " << printer.resolution() <<LF;
+  	    else // image was too small, reduce dpi accordingly to fill page
+          printer.setResolution((int) (dpi*im.width())/(double)ww);
+        if (DEBUG_CONVERT) debug_convert << "dpi asked: "<< dpi <<" ; actual dpi set: " << printer.resolution() <<LF;
 	  }
 	  else printer.setPaperSize(QSizeF(im.width (), im.height ()), QPrinter::DevicePixel);
-    QPainter p;
-    p.begin(&printer);
-    p.drawImage(0, 0, im);
-    p.end();
+      QPainter p;
+      p.begin(&printer);
+      p.drawImage(0, 0, im);
+      p.end();
     }
+  }
 }
 
+#if (QT_VERSION < 0x050000) 
 void qt_image_to_eps(url image, url outfile, int w_pt, int h_pt, int dpi) {
   qt_image_to_pdf(image, outfile, w_pt, h_pt, dpi);};
 
-/* not in use anymore : now use a Qt printer that outputs ps.
+#endif 
+/* for QT5+ we could revert to this code used before r10013 (2016)
+// otherwise imagemagick is used. 
+// And maybe we should deprecate printing to PS altogether.
 
 void
 qt_image_to_eps (url image, url eps, int w_pt, int h_pt, int dpi) {
diff --git a/src/Plugins/Qt/qt_utilities.hpp b/src/Plugins/Qt/qt_utilities.hpp
index 75518396..02a4940d 100644
--- a/src/Plugins/Qt/qt_utilities.hpp
+++ b/src/Plugins/Qt/qt_utilities.hpp
@@ -96,8 +96,9 @@ bool qt_native_image_size (url image, int& w, int& h);
 void qt_pretty_image_size (int ww, int hh, string& w, string& h);
 bool qt_pretty_image_size (url image, string& w, string& h);
 void qt_convert_image (url image, url dest, int w =0, int h =0);
+#if (QT_VERSION < 0x050000)
 void qt_image_to_eps (url image, url eps, int w_pt =0, int h_pt =0, int dpi= 0);
-string qt_image_to_eps (url image, int w_pt =0, int h_pt =0, int dpi= 0);
+#endif
 void qt_image_to_pdf (url image, url pdf, int w_pt =0, int h_pt =0, int dpi =0);
 
 string qt_application_directory ();
diff --git a/src/Scheme/Glue/build-glue-basic.scm b/src/Scheme/Glue/build-glue-basic.scm
index 88933f8b..42ee6dde 100644
--- a/src/Scheme/Glue/build-glue-basic.scm
+++ b/src/Scheme/Glue/build-glue-basic.scm
@@ -184,6 +184,7 @@
   ;; routines for images and animations
   (image->psdoc image_to_psdoc (string url))
   (anim-control-times get_control_times (array_double content))
+  (cpp-gspdf2eps gs_to_eps (void url url))
 
   ;; routines for trees
   (tree->stree tree_to_scheme_tree (scheme_tree tree))
diff --git a/src/Scheme/Glue/glue_basic.cpp b/src/Scheme/Glue/glue_basic.cpp
index 4c28250b..eda9ffb4 100644
--- a/src/Scheme/Glue/glue_basic.cpp
+++ b/src/Scheme/Glue/glue_basic.cpp
@@ -1908,6 +1908,21 @@ tmg_anim_control_times (tmscm arg1) {
   return array_double_to_tmscm (out);
 }
 
+tmscm
+tmg_cpp_gspdf2eps (tmscm arg1, tmscm arg2) {
+  TMSCM_ASSERT_URL (arg1, TMSCM_ARG1, "cpp-gspdf2eps");
+  TMSCM_ASSERT_URL (arg2, TMSCM_ARG2, "cpp-gspdf2eps");
+
+  url in1= tmscm_to_url (arg1);
+  url in2= tmscm_to_url (arg2);
+
+  // TMSCM_DEFER_INTS;
+  gs_to_eps (in1, in2);
+  // TMSCM_ALLOW_INTS;
+
+  return TMSCM_UNSPECIFIED;
+}
+
 tmscm
 tmg_tree_2stree (tmscm arg1) {
   TMSCM_ASSERT_TREE (arg1, TMSCM_ARG1, "tree->stree");
@@ -10231,6 +10246,7 @@ initialize_glue_basic () {
   tmscm_install_procedure ("font-family-main",  tmg_font_family_main, 1, 0, 0);
   tmscm_install_procedure ("image->psdoc",  tmg_image_2psdoc, 1, 0, 0);
   tmscm_install_procedure ("anim-control-times",  tmg_anim_control_times, 1, 0, 0);
+  tmscm_install_procedure ("cpp-gspdf2eps",  tmg_cpp_gspdf2eps, 2, 0, 0);
   tmscm_install_procedure ("tree->stree",  tmg_tree_2stree, 1, 0, 0);
   tmscm_install_procedure ("stree->tree",  tmg_stree_2tree, 1, 0, 0);
   tmscm_install_procedure ("tree->string",  tmg_tree_2string, 1, 0, 0);
diff --git a/src/Scheme/Scheme/glue.cpp b/src/Scheme/Scheme/glue.cpp
index 1303321b..978805e5 100644
--- a/src/Scheme/Scheme/glue.cpp
+++ b/src/Scheme/Scheme/glue.cpp
@@ -29,6 +29,7 @@
 #include "Database/database.hpp"
 #include "Sqlite3/sqlite3.hpp"
 #include "Updater/tm_updater.hpp"
+#include "Ghostscript/gs_utilities.hpp"
 
 tmscm 
 blackboxP (tmscm t) {
diff --git a/src/System/Files/image_files.cpp b/src/System/Files/image_files.cpp
index c712e01a..f064877c 100644
--- a/src/System/Files/image_files.cpp
+++ b/src/System/Files/image_files.cpp
@@ -371,17 +371,55 @@ pdf_image_size (url image, int& w, int& h) {
 void
 svg_image_size (url image, int& w, int& h) {
   string content;
-  bool err= load_string (image, content, false);
-  if (!err) {
+  bool ok = ! load_string (image, content, false);
+  if (ok) {
     tree t= parse_xml (content);
     tree result= find_first_element_by_name (t, "svg");
     string width= get_attr_from_element (result, "width", "");
     string height= get_attr_from_element (result, "height", "");
     int try_width= parse_xml_length (width);
     int try_height= parse_xml_length (height);
-    if (try_width > 0) w= try_width;
-    if (try_height > 0) h= try_height;
+    if ((try_width > 0) && (try_height > 0)) {
+       w= try_width; 
+       h= try_height;
+    }
+    else {
+      string viewBox= get_attr_from_element (result, "viewBox", "");
+      int pos = 0;
+      double X1, Y1, W, H;
+      skip_spaces (viewBox, pos);
+      ok= read_double (viewBox, pos, X1);
+      skip_spaces (viewBox, pos);
+      ok= ok && read_double (viewBox, pos, Y1);
+      skip_spaces (viewBox, pos);
+      ok= ok && read_double (viewBox, pos, W);
+      skip_spaces (viewBox, pos);
+      ok= ok && read_double (viewBox, pos, H);
+      if (ok) {
+        w = tm_round(W);
+        h = tm_round(H);
+      }
+    }
+    if (DEBUG_CONVERT) 
+      if (ok) debug_convert<< "svg_image_size : " << w << " x " << h << " for " << image <<"\n";
+      else debug_convert<< "svg_image_size could not determine size of " << image << "\n";
+  }
+}
+
+bool
+svg_is_tiny (url image) {
+  string content;
+  bool err= load_string (image, content, false);
+  if (!err) {
+    tree t= parse_xml (content);
+    tree result= find_first_element_by_name (t, "svg");
+    string version= get_attr_from_element (result, "version", "");
+    string baseProfile= get_attr_from_element (result, "baseProfile", "");
+    if (DEBUG_CONVERT) debug_convert << "svg version '" << version<<"' ; baseprofile:'"<< baseProfile<<"'"<< LF;
+    bool tiny =  ((N(version) > 0) && (version[0] == '1') && (baseProfile == "tiny"));
+    return tiny;
   }
+  else return false;
 }
  
 /******************************************************************************
@@ -389,15 +427,6 @@ svg_image_size (url image, int& w, int& h) {
 * displaying and printing : png, eps, pdf
 ******************************************************************************/
 
-bool
-wrap_qt_supports (url image) {
-#ifdef QTTEXMACS
-  return qt_supports (image);
-#else
-  (void) image; return false;
-#endif
-}
-
 void
 image_to_eps (url image, url eps, int w_pt, int h_pt, int dpi) {
   if (DEBUG_CONVERT) debug_convert << "image_to_eps ...";
@@ -408,12 +437,9 @@ image_to_eps (url image, url eps, int w_pt, int h_pt, int dpi) {
   string s= suffix (image);
   // First try to preserve "vectorialness"
 
-  // Note: since inkscape would most likely be the prog called to
-  // translate svg we could at no additional cost allow other
-  // vector formats supported by inkscape : ai, svgz, cdr, wmf ...
-  if ((s == "svg") && !wrap_qt_supports (image) &&
-      (call_scm_converter (image, eps))) return;
-  
+  if ((s == "svg") && (call_scm_converter (image, eps))) return;
+  // see comment in image_to_pdf
+
 #ifdef USE_GS
   if (gs_supports (image)) {
     if (DEBUG_CONVERT) debug_convert << " using gs" << LF;
@@ -422,7 +448,8 @@ image_to_eps (url image, url eps, int w_pt, int h_pt, int dpi) {
   }
 #endif
   //converters below will yield only raster images.
-#ifdef QTTEXMACS 
+#if (defined(QTTEXMACS)) && (QT_VERSION < 0x050000) 
+// PS support is gone in Qt5
   if (qt_supports (image)) {
     if (DEBUG_CONVERT) debug_convert << " using qt" << LF;
     qt_image_to_eps (image, eps, w_pt, h_pt, dpi);
@@ -454,8 +481,10 @@ image_to_pdf (url image, url pdf, int w_pt, int h_pt, int dpi) {
   if (DEBUG_CONVERT) debug_convert << "image_to_pdf ... ";
   string s= suffix (image);
   // First try to preserve "vectorialness"
-  if ((s == "svg") && !wrap_qt_supports (image) &&
-      call_scm_converter (image, pdf)) return;
+  if ((s == "svg") && call_scm_converter (image, pdf)) return;
+  //for svg, at this point (2022), if available, Inkscape or rsvg-convert are
+  //preferred over Qt because they handle svg full; try using them via scm
+  //additional priorities/preferences regarding svg converters must be handled in scheme (init-images.scm) 
 #ifdef USE_GS
   if (gs_supports (image)) {
     if (DEBUG_CONVERT) debug_convert << " using gs "<<LF;
@@ -463,7 +492,7 @@ image_to_pdf (url image, url pdf, int w_pt, int h_pt, int dpi) {
     return;
   }
 #endif
-  //converters below will yield only raster images.
+  //converters below will yield only raster images (except qt for svg).
 #ifdef QTTEXMACS
   if (qt_supports (image)) {
     if (DEBUG_CONVERT) debug_convert << " using qt "<<LF;
@@ -477,12 +506,15 @@ image_to_pdf (url image, url pdf, int w_pt, int h_pt, int dpi) {
 
 void
 image_to_png (url image, url png, int w, int h) {// IN PIXEL UNITS!
-  string source_suffix= suffix (image);
+  string s= suffix (image);
   if (DEBUG_CONVERT) debug_convert << "image_to_png ... ";
   /* if (suffix (png) != "png") {
      std_warning << concretize (png) << " has no .png suffix\n";
      }
   */
+  if ((s == "svg") &&  (call_scm_converter (image, png, w, h))) return;
+      //see comment in image_to_pdf
+      //When available, also use scm converter for on-creen display, for consistency with printing.
 #ifdef MACOSX_EXTENSIONS
   //cout << "mac convert " << image << ", " << png << "\n";
   if (mac_supports (image)) {
@@ -504,7 +536,7 @@ image_to_png (url image, url png, int w, int h) {// IN PIXEL UNITS!
     if (gs_to_png (image, png, w, h)) return;
   }
 #endif
-  if (call_scm_converter(image, png)) return;
+  if ((s != "svg") && call_scm_converter(image, png, w, h)) return;
   call_imagemagick_convert (image, png, w, h);
   if (! exists(png)) {
     convert_error << image << " could not be converted to png" <<LF;
@@ -513,18 +545,28 @@ image_to_png (url image, url png, int w, int h) {// IN PIXEL UNITS!
 }
 
 bool
-call_scm_converter(url image, url dest) {
-  if (DEBUG_CONVERT) debug_convert << " using scm" <<LF;
+call_scm_converter(url image, url dest, int w, int h) {
+  //for raster target, pass target w and h in pixels to the scm converter
+  // (otherwise the dpi preference (texmacs->image:raster-resolution) & default image size are used)
+  //for vector target, no need to specify w and h (defaulting to zero)
+  if (DEBUG_CONVERT) debug_convert << "trying scm..." <<LF;
   if (as_bool (call ("file-converter-exists?",
                      "x." * suffix (image),
                      "x." * suffix (dest)))) {
-    call ("file-convert", object (image), object (dest));
+    if ((w == 0) && (h == 0)) // w,h not specified : vector format
+      call ("file-convert", object (image), object (dest));
+    else { // w,h pixel numbers of the target raster image
+      call ("file-convert", object (image), object (dest),
+        eval("(cons 'width \"" * as_string(w) * "\")"),
+        eval("(cons 'height \""*as_string(h)*"\")"));
+    }
     bool success= exists (dest);
     if (success && DEBUG_CONVERT)
       debug_convert << "scm file-convert " << concretize (image)
                     << " -> " << concretize (dest) << LF;
     return success;
   }
+  if (DEBUG_CONVERT) debug_convert << "no scm converter found, or conversion failed" <<LF;
   return false;
 }
 
@@ -536,8 +578,7 @@ call_scm_converter(url image, url dest) {
 bool
 has_image_magick (){
 #ifdef OS_MINGW
-	// Qt is used for converion on Windows
-  static bool has_imagemagick = false;
+  static bool has_imagemagick= exists_in_path ("magick");
 #else
   static bool has_imagemagick= exists_in_path ("convert");
 #endif
@@ -549,9 +590,12 @@ imagemagick_cmd () {
   if (has_image_magick()) {
 #ifdef OS_MINGW
     static string image_magick_cmd=
-      sys_concretize (resolve_in_path ("convert"));
+      sys_concretize (resolve_in_path ("magick"));
+      // IM v>=7.0 only
+      // this avoids conflict with OS utility
 #else
     static string image_magick_cmd= "convert";
+    // compatible with IM <7 and >= 7
 #endif
     return copy (image_magick_cmd);
   } 
@@ -561,6 +605,7 @@ imagemagick_cmd () {
 void
 call_imagemagick_convert (url image, url dest, int w_pt, int h_pt, int dpi) {
   if (has_image_magick ()) { 
+    if (DEBUG_CONVERT) debug_convert << "trying imagemagick..." <<LF;
     string cmd= imagemagick_cmd ();
     string s= suffix (image);
     if (s != "pdf" && s != "ps" && s != "eps" &&
@@ -581,12 +626,16 @@ call_imagemagick_convert (url image, url dest, int w_pt, int h_pt, int dpi) {
 bool
 imagemagick_image_size(url image, int& w, int& h, bool pt_units) {
   if (!has_image_magick()) return false;
-  else {		
-    string cmd= "identify"; //ImageMagick utility
+  else {
 #ifdef OS_MINGW
-    cmd = sys_concretize(resolve_in_path(cmd));
+    string cmd= imagemagick_cmd ();
+    cmd << " identify";
+    // IM >= 7
+#else 
+    string cmd= "identify"; //ImageMagick utility
+    // compatible with IM <7 and >= 7
 #endif
-    cmd << " -ping -format \"%w %h %x\\n%y\""; 
+    cmd << " -ping -format \"%w %h %x\\n%U\""; 
     string sz= eval_system (cmd, image);
     int w_px, h_px, ok= true, pos= 0;
     string unit;
@@ -609,11 +658,11 @@ imagemagick_image_size(url image, int& w, int& h, bool pt_units) {
           ok= ok && read_line (sz, pos, unit);    
           // according to the IM doc, units should be in [PixelsPerCentimeter,PixelsPerInch,Undefined]
           // When "Undefined" IM gives the nonsensical default value of 72 "dots per Undefined"
-          // svg is SCALABLE and hence logically gives "Undefined"; in that case we assume 90 dpi
-          // so that the physical image size matches that of svg created with inkscape
+          // svg is SCALABLE and hence logically gives "Undefined"; in that case we assume 96 dpi
+          // so that the physical image size matches that of svg created with recent inkscape
           if (unit == "PixelsPerCentimeter") ptperpix = 72/(2.54*densityx);
           else if (unit == "PixelsPerInch") ptperpix = 72/densityx;
-          else if (unit == "Undefined") ptperpix = 90/densityx; 
+          else if (unit == "Undefined") ptperpix = 96/densityx; 
           w= (int) w_px * ptperpix;
           h= (int) h_px * ptperpix;
           ok= ok && read_double (sz, pos, densityy);
diff --git a/src/System/Files/image_files.hpp b/src/System/Files/image_files.hpp
index eea56045..38d84b46 100644
--- a/src/System/Files/image_files.hpp
+++ b/src/System/Files/image_files.hpp
@@ -25,11 +25,12 @@ string 	      ps_load (url image, bool conv=true);
 void          image_size (url image, int& w, int& h);
 void          pdf_image_size (url image, int& w, int& h);
 void          svg_image_size (url image, int& w, int& h);
+bool          svg_is_tiny (url image);
 void          image_to_eps (url image, url eps, int w_pt= 0, int h_pt= 0, int dpi= 0);
 void          image_to_pdf (url image, url eps, int w_pt= 0, int h_pt= 0, int dpi= 0);
 string        image_to_psdoc (url image);
 void          image_to_png (url image, url png, int w= 0, int h= 0);
-bool          call_scm_converter(url image, url dest);
+bool          call_scm_converter(url image, url dest, int w= 0, int h= 0);
 void          call_imagemagick_convert(url image, url dest, int w_pt=0, int h_pt=0, int dpi=72);
 bool          imagemagick_image_size(url image, int& w, int& h, bool pt_units=true);
 bool          has_image_magick();
