Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:slowphil:texmacs-devel
texmacs
my_current.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File my_current.patch of Package texmacs
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 1095fcd9e..c51d4b891 100644 --- a/TeXmacs/doc/devel/scheme/api/glue-auto-doc.en.tm +++ b/TeXmacs/doc/devel/scheme/api/glue-auto-doc.en.tm @@ -1290,6 +1290,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/misc/pixmaps/modern/32x32/settings/tm_plugins_prefs.xpm b/TeXmacs/misc/pixmaps/modern/32x32/settings/tm_plugins_prefs.xpm new file mode 100644 index 000000000..747661dec --- /dev/null +++ b/TeXmacs/misc/pixmaps/modern/32x32/settings/tm_plugins_prefs.xpm @@ -0,0 +1,90 @@ +/* XPM */ +static char *plugins_prefs[] = { +/* columns rows colors chars-per-pixel */ +"32 32 52 1 ", +" c gray50", +". c #808080", +"X c #818181", +"o c gray51", +"O c #838383", +"+ c #848484", +"@ c gray52", +"# c #868686", +"$ c gray53", +"% c #888888", +"& c gray54", +"* c gray55", +"= c #8D8D8D", +"- c #8E8E8E", +"; c gray56", +": c gray57", +"> c #929292", +", c #939393", +"< c #959595", +"1 c #979797", +"2 c #989898", +"3 c gray60", +"4 c #9A9A9A", +"5 c #9B9B9B", +"6 c #9D9D9D", +"7 c gray64", +"8 c #A4A4A4", +"9 c #A5A5A5", +"0 c gray65", +"q c #A7A7A7", +"w c #A9A9A9", +"e c #AAAAAA", +"r c gray67", +"t c #ACACAC", +"y c gray68", +"u c #AEAEAE", +"i c #AFAFAF", +"p c gray69", +"a c #B2B2B2", +"s c #B4B4B4", +"d c gray71", +"f c #B6B6B6", +"g c #B7B7B7", +"h c gray72", +"j c #B9B9B9", +"k c #BBBBBB", +"l c #BCBCBC", +"z c gray74", +"x c gray", +"c c gray75", +"v c #C0C0C0", +"b c None", +/* pixels */ +"bbbbb.bbbbbb.bbbbbbbbbbbbbbbbbbb", +"bbbb.#.bbb..#.bbbbbbbbbbbbbbbbbb", +"bbb.*c%.bb.<c.bbbbbbbbbbbbbbbbbb", +"bbb.:v*.bb#6v..bbbbbbbbbbbbbbbbb", +"bbb.*v*.bb.4v..bbbbbbbbbbbbbbbbb", +"bbb.:v*.bb#4v..bbbbbbbbbbbbbbbbb", +"bbb.*v*.bb.6v..bbbbbbbbbbbbbbbbb", +"b...:v*....6v. .bbbbbbbbbbbbbbb", +".%aasvaiiiisvaii.bbbbbbbbbbbbbbb", +".*ccvvvvvvvvvvcc.bbbbbbbbbbbbbbb", +".*vvvvvvvvvvvvvc.bbbbbbbbbbbbbbb", +".*vvvvvvvvvvvvvc.bbbbbbbbbbbbbbb", +".*vvvvvvvvvvvvvc.bbbbbbbbbbbbbbb", +".%vvvvvvvvvvvvch.bbbbbbbbbbbbbbb", +"b.cvvvvvvvvvvvvi.bbbbbbbbbbbbbbb", +"b.7vvvvvvvvvvvv<.bbbbbbbbbbbbbbb", +"b.#hvvvvvvvvvvi.bbbbbb.... b", +"bb.*cvvvvvvvva#.bbbbb..49eieei<.", +"bbb.%ivvvvvv9..bbbb..<cvvvvvvv7.", +"bbbb..%6ch4%..bbbbb.4vh4# ......", +"bbbbbb..hi bbbbbb.%ch%..bbbbbbb", +"bbbbbbb.ci.bbbbbbb.9v:.bbbbbbbbb", +"bbbbbbb hi.bbbbbbb.ss.bbbbbbbbbb", +"bbbbbbb ci.bbbbbbb.ci.bbbbbbbbbb", +"bbbbbbb.ss.bbbbbb.%v9.bbbbbbbbbb", +"bbbbbbb.9v%.bbbbb.4v4.bbbbbbbbbb", +"bbbbbbb.*ce .bbb.#ch# bbbbbbbbbb", +"bbbbbbbb.9ve#...*hv<.bbbbbbbbbbb", +"bbbbbbbb..evhiisvv6.bbbbbbbbbbbb", +"bbbbbbbbb..:icvh9%..bbbbbbbbbbbb", +"bbbbbbbbbbb.......bbbbbbbbbbbbbb", +"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" +}; diff --git a/TeXmacs/misc/pixmaps/modern/32x32/settings/tm_prefs_plugins.svg b/TeXmacs/misc/pixmaps/modern/32x32/settings/tm_prefs_plugins.svg new file mode 100644 index 000000000..07302ffd2 --- /dev/null +++ b/TeXmacs/misc/pixmaps/modern/32x32/settings/tm_prefs_plugins.svg @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + width="32px" + height="32px" + id="svg5078" + version="1.1"> + <metadata + id="metadata856"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs5080" /> + <g + id="g4" + style="fill:#c0c0c0;fill-opacity:1;stroke:#808080;stroke-width:24.1333;stroke-opacity:1" + transform="matrix(0.0621549,0,0,0.0621549,1.0331262,0.69944239)"> + <path + d="m 489.8,280.92 c 0,-13.9 -11.3,-25.2 -25.2,-25.2 h -74.1 c -62.1,0 -112.4,50.2 -112.7,112.2 -0.1,32.3 -23,61 -55,65 -38.4,4.8 -71.2,-25.2 -71.2,-62.6 v -56.4 c 57.6,-11.7 101,-62.6 101,-123.7 v -64 c 0,-9.1 -7.3,-16.4 -16.4,-16.4 h -31.3 v -79.1 c 0,-12.4 -9,-23.4 -21.3,-24.6 -14.1,-1.4 -26,9.7 -26,23.6 v 80.1 H 95.2 v -79.1 c 0,-12.4 -9,-23.4 -21.4,-24.6 -14.1,-1.3 -26,9.7 -26,23.6 v 80.1 H 16.4 c -9.1,0 -16.4,7.3 -16.4,16.4 v 64 c 0,61.1 43.4,112 101,123.7 v 53.5 c 0,61.5 47.7,114 109.2,116.3 64.6,2.4 118,-49.4 118,-113.5 v -0.9 c 0,-34.9 28.3,-63.1 63.1,-63.1 h 73.2 c 14,-0.1 25.3,-11.4 25.3,-25.3 z" + id="path2" + style="fill:#c0c0c0;fill-opacity:1;stroke:#808080;stroke-width:24.1333;stroke-opacity:1" /> + </g> +</svg> diff --git a/TeXmacs/progs/convert/images/init-images.scm b/TeXmacs/progs/convert/images/init-images.scm index 8115eebc4..9ecfb7bc9 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)))) + +(define (gs-binary) + (escape-shell (gs-url))) (tm-define (has-gs?) - (url-exists? (gs-binary))) + (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)) +(tm-define (imagemagick-any->raster x opts) + ;(display* "scm imagemagick-any->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,89 +260,82 @@ (: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 (has-gs?)) + (:function-with-options gs-ps2pdf)) (define-format xfig (:name "Xfig") (:suffix "fig")) -(converter xfig-file postscript-file - (:shell "fig2ps" from to)) +;(converter xfig-file postscript-file +; (:shell "fig2ps" from to)) + +(converter xfig-file pdf-file + (:require (url-exists-in-path? "fig2pdf")) + (:shell "fig2pdf" from to)) -(define-format xmgrace - (:name "Xmgrace") - (:suffix "agr" "xmgr")) +; as of 2023 grace is still available in linux distros but it seems a dead project +; there are now several other OSS Wysiwyg graphers +;(define-format xmgrace +; (:name "Xmgrace") +; (:suffix "agr" "xmgr")) -(converter xmgrace-file postscript-file - (:require (url-exists-in-path? "xmgrace")) - (:shell "xmgrace" "-noask -hardcopy -hdevice EPS -printfile" to from)) +;(converter xmgrace-file postscript-file +; (:require (url-exists-in-path? "xmgrace")) +; (:shell "xmgrace" "-noask -hardcopy -hdevice EPS -printfile" to from)) (define-format svg (: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 png-file - (:require (url-exists-in-path? "inkscape")) - (:shell "inkscape" "-z" "-d" "600" from "--export-png" to)) +;(converter svg-file postscript-file +; (:require (has-rsvg-convert?)) +; (:function-with-options rsvg-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 postscript-file +; (:require (has-inkscape?)) +; (:function-with-options inkscape-convert)) + +(converter svg-file pdf-file + (:require (has-inkscape?)) + (:function-with-options inkscape-convert)) (define-format geogebra (:name "Geogebra") (:suffix "ggb")) -(converter geogebra-file postscript-file +(converter geogebra-file pdf-file (:require (url-exists-in-path? "geogebra")) - (:shell "geogebra" "--export=" to "--dpi=600" from)) + (:shell "geogebra" "--export=" to from)) -(converter geogebra-file svg-file +(converter geogebra-file png-file (:require (url-exists-in-path? "geogebra")) (:shell "geogebra" "--export=" to "--dpi=600" from)) -;;(converter pdf-file postscript-document -;; (:require (has-pdftocairo?)) -;; (:shell "pdftocairo" "-eps" from to)) -;; -;;(converter pdf-file postscript-file -;; (:require (has-pdftocairo?)) -;; (:shell "pdftocairo" "-eps" from to)) - (converter pdf-file svg-file - (:require (has-pdftocairo?)) - (:shell "pdftocairo" "-origpagesizes -nocrop -nocenter -svg" from to)) - + (:require (has-inkscape?)) + (:function-with-options inkscape-convert)) + (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)) - +(converter pdf-file svg-file + (:require (has-pdftocairo?)) + (:shell "pdftocairo" "-origpagesizes -nocrop -nocenter -svg" from to)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Bitmap image formats -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define-format xpm (:name "Xpm") @@ -223,12 +360,16 @@ (:name "Tif") (:suffix "tif" "tiff")) -(converter tif-file postscript-document - (:function image->psdoc)) +;(converter tif-file postscript-document +; (:function image->psdoc)) (converter tif-file png-file (:require (has-convert?)) (:shell "convert" from to)) + +(converter tif-file pdf-file + (:require (has-convert?)) + (:shell "convert" from to)) (define-format ppm (:name "Ppm") @@ -253,12 +394,12 @@ (:name "Png") (:suffix "png")) -(converter png-file postscript-document - (:function image->psdoc)) +;(converter png-file postscript-document +; (:function image->psdoc)) -(converter png-file pnm-file - (:require (has-convert?)) - (:shell "convert" from to)) +;(converter png-file pnm-file +; (:require (has-convert?)) +; (:shell "convert" from to)) (converter geogebra-file png-file (:require (url-exists-in-path? "geogebra")) @@ -268,8 +409,28 @@ (:name "Pnm") (:suffix "pnm")) -(converter pnm-file postscript-document - (:function image->psdoc)) +;(converter pnm-file postscript-document +; (:function image->psdoc)) + +(converter pnm-file png-file + (:require (has-convert?)) + (:shell "convert" from to)) + +(converter pnm-file png-file + (:require (has-convert?)) + (:shell "convert" from to)) + +(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 @@ -277,22 +438,12 @@ (converter pdf-file png-file (:require (has-convert?)) - (:function-with-options pdf-file->imagemagick-raster) - ;;(:option "texmacs->image:raster-resolution" "300") - ) + (:function-with-options imagemagick-any->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 imagemagick-any->raster)) -(converter pdf-file tif-file - (:require (has-convert?)) - (:function-with-options pdf-file->imagemagick-raster) - ;;(:option "texmacs->image:raster-resolution" "300") - ) - (converter pdf-file png-file (:require (has-pdftocairo?)) (:function-with-options pdf-file->pdftocairo-raster) @@ -302,9 +453,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?)) @@ -314,6 +463,10 @@ (:require (has-gs?)) (:function-with-options pdf-file->gs-raster)) -(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/kernel/texmacs/tm-convert.scm b/TeXmacs/progs/kernel/texmacs/tm-convert.scm index 8849326e8..d671e14ea 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))) @@ -461,7 +462,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/kernel/texmacs/tm-plugins.scm b/TeXmacs/progs/kernel/texmacs/tm-plugins.scm index af0f36e19..b6774b759 100644 --- a/TeXmacs/progs/kernel/texmacs/tm-plugins.scm +++ b/TeXmacs/progs/kernel/texmacs/tm-plugins.scm @@ -530,6 +530,8 @@ (with l (ahash-table->list plugin-initialize-todo) (not (list-or (map cdr l))))) +(tm-define plugins-with-pref-widget '()) + (define-public (plugin-initialize name*) "Initialize plugin with name @name*" (plugin-load-setup) @@ -547,6 +549,8 @@ ;; (display* name " -> " (- (texmacs-time) start) " ms\n")) (load fname) )) + (if (defined? (string->symbol (string-append name "-preferences-widget"))) + (set! plugins-with-pref-widget (rcons plugins-with-pref-widget name) )) (if (plugin-all-initialized?) (plugin-save-setup))))) (define-public (lazy-plugin-initialize name) diff --git a/TeXmacs/progs/prog/glue-symbols.scm b/TeXmacs/progs/prog/glue-symbols.scm index cc0a508a8..d3e7abc20 100644 --- a/TeXmacs/progs/prog/glue-symbols.scm +++ b/TeXmacs/progs/prog/glue-symbols.scm @@ -186,6 +186,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 070c14ed1..093a0289c 100644 --- a/TeXmacs/progs/texmacs/menus/preferences-widgets.scm +++ b/TeXmacs/progs/texmacs/menus/preferences-widgets.scm @@ -598,35 +598,28 @@ (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")) - (tm-widget (image-preferences-widget) ====== (bold (text "TeXmacs -> Image")) === - (aligned - (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")) - (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"))) + +) ;; All converters ---------- @@ -878,6 +871,21 @@ ====== (dynamic (experimental-preferences-widget)))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Tabs for plugins that define a preference widget +;; (such widget must be called pluginname-preferences-widget and defined +;; in pluginname.scm or init-pluginname.scm inside the pluginname/prog subdir) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(tm-widget (plugins-preferences-widget) + (assuming (list>0? plugins-with-pref-widget) + === + (padded + (tabs (loop (plug plugins-with-pref-widget) + (tab (text (upcase-first plug)) + (centered (dynamic (eval `(,(string->symbol (string-append plug "-preferences-widget")))))))))) + ===)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Preferences widget ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -891,18 +899,19 @@ (icon-tab "tm_prefs_keyboard.xpm" (text "Keyboard") (centered (dynamic (keyboard-preferences-widget)))) - ;; TODO: please implement nice icon tabs first before - ;; adding new tabs in the preferences widget - ;; The tabs currently take too much horizontal space - ;;(icon-tab "tm_prefs_other.xpm" (text "Mathematics") ; TODO: icon - ;; (centered - ;; (dynamic (math-preferences-widget)))) + (icon-tab "tm_math_preferences.xpm" (text "Mathematics") + (centered + (dynamic (math-preferences-widget)))) (icon-tab "tm_prefs_convert.xpm" (text "Convert") (dynamic (conversion-preferences-widget))) (assuming (== (get-preference "experimental encryption") "on") (icon-tab "tm_prefs_security.xpm" (text "Security") (centered (dynamic (security-preferences-widget))))) + (assuming (list>0? plugins-with-pref-widget) + (icon-tab "tm_plugins_prefs.xpm" (text "Plugins") + (centered + (dynamic (plugins-preferences-widget))))) (icon-tab "tm_prefs_other.xpm" (text "Other") (centered (dynamic (other-preferences-widget))))))) diff --git a/src/Edit/Editor/edit_main.cpp b/src/Edit/Editor/edit_main.cpp index f2ed1c88d..a770b520a 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 c07b1f1e9..9770e1b16 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/QTMMenuHelper.cpp b/src/Plugins/Qt/QTMMenuHelper.cpp index 1fba9b2d2..8c75958f2 100644 --- a/src/Plugins/Qt/QTMMenuHelper.cpp +++ b/src/Plugins/Qt/QTMMenuHelper.cpp @@ -26,6 +26,9 @@ #include <QCompleter> #include <QKeyEvent> #include <QApplication> +#include <QStylePainter> +#include <QIcon> +#include <QStyleOptionTab> /****************************************************************************** * QTMCommand @@ -761,6 +764,8 @@ QTMLineEdit::focusOutEvent (QFocusEvent* ev) QTMTabWidget::QTMTabWidget (QWidget *p) : QTabWidget(p) { QObject::connect (this, SIGNAL (currentChanged (int)), this, SLOT (resizeOthers (int))); + QTMTabBar* tabbar = new QTMTabBar(this); + setTabBar(tabbar); } /*! Resizes the widget to the size of the tab given by the index. @@ -794,6 +799,49 @@ BEGIN_SLOT END_SLOT } +/****************************************************************************** + * QTMTabBar + ******************************************************************************/ +// Overloads QTabBar so that tabs with icons appear with icon and text vertically stacked +QTMTabBar::QTMTabBar (QWidget *p) : QTabBar(p) {} + +QSize QTMTabBar::tabSizeHint(int index) const { + QIcon icon = tabIcon (index); + if (icon.isNull() ) return QTabBar::tabSizeHint(index); + else { + // Hack. Source Qt code cannot be easily adapted + // because it uses private classes & functions + QSize osize = QTabBar::tabSizeHint(index); + QSize isize = iconSize(); + return QSize(qMax(osize.width() - isize.width() -20, 3*isize.width()/2 + 8), osize.height() + 3*isize.height()/2); + } +} + +void +QTMTabBar::paintEvent(QPaintEvent* event) { + if (count()>0) {//needed? + QIcon icon = tabIcon (0); + if (icon.isNull()) + //if no icons draw as usual + QTabBar::paintEvent(event); + else { + QStylePainter painter(this); + for(int i = 0; i < count(); ++i) { + QStyleOptionTab tab; + initStyleOption(&tab, i); + QRect tabrect = tabRect(i); //uses tabSizeHint under the hood + tabrect.adjust(0, 6, 0, -3);//small vertical padding + icon = tab.icon; + QPixmap pixmap = icon.pixmap(3*iconSize()/2); //looks better with icon larger than when all inline + painter.drawControl(QStyle::CE_TabBarTabShape, tab); + painter.drawItemPixmap(tabrect, Qt::AlignTop|Qt::AlignHCenter, pixmap); + painter.drawItemText(tabrect, Qt::AlignBottom|Qt::AlignHCenter, palette(), 1, tab.text); + } + } + } +} + + /****************************************************************************** * QTMRefreshWidget ******************************************************************************/ diff --git a/src/Plugins/Qt/QTMMenuHelper.hpp b/src/Plugins/Qt/QTMMenuHelper.hpp index 6d505ac8c..b01c1dbfb 100644 --- a/src/Plugins/Qt/QTMMenuHelper.hpp +++ b/src/Plugins/Qt/QTMMenuHelper.hpp @@ -33,6 +33,7 @@ #include <QScrollArea> #include <QTabWidget> #include <QToolButton> +#include <QTabBar> /*! Handles TeXmacs commands in the QT way. @@ -318,6 +319,17 @@ public slots: void resizeOthers(int index); }; +/*! A QTabBar where tabs' icon and text are stacked. */ +class QTMTabBar : public QTabBar { + Q_OBJECT + +public: + QTMTabBar (QWidget* p = NULL); + QSize tabSizeHint(int index) const; + +protected: + void paintEvent(QPaintEvent* event); +}; /*! A container widget which redraws the widgets it owns. */ class QTMRefreshWidget : public QWidget { diff --git a/src/Plugins/Qt/qt_picture.cpp b/src/Plugins/Qt/qt_picture.cpp index 8e7d8443e..ed357a27a 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 479d541ab..e006a79c9 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" @@ -479,61 +480,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? + 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 755183961..02a4940d7 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 b35410fba..8e9d1bb65 100644 --- a/src/Scheme/Glue/build-glue-basic.scm +++ b/src/Scheme/Glue/build-glue-basic.scm @@ -186,6 +186,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 ce6b89d23..35a198de7 100644 --- a/src/Scheme/Glue/glue_basic.cpp +++ b/src/Scheme/Glue/glue_basic.cpp @@ -1936,6 +1936,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"); @@ -10321,6 +10336,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 6df9ab2ed..19a70734a 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 6798e52cf..f977363b4 100644 --- a/src/System/Files/image_files.cpp +++ b/src/System/Files/image_files.cpp @@ -379,17 +379,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; } /****************************************************************************** @@ -397,15 +435,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 ..."; @@ -416,12 +445,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; @@ -430,7 +456,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); @@ -462,8 +489,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; @@ -471,7 +500,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; @@ -485,12 +514,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)) { @@ -512,7 +544,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; @@ -521,18 +553,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; } @@ -544,8 +586,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 @@ -557,9 +598,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); } @@ -569,6 +613,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" && @@ -589,10 +634,14 @@ 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 %U\\n%y\""; string sz= eval_system (cmd, image); @@ -617,11 +666,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 67214a0bc..8c7059ca4 100644 --- a/src/System/Files/image_files.hpp +++ b/src/System/Files/image_files.hpp @@ -26,11 +26,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();
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor