Update of /project/mcclim/cvsroot/mcclim/Backends/PostScript In directory common-lisp.net:/tmp/cvs-serv32722/Backends/PostScript
Modified Files: class.lisp graphics.lisp paper.lisp sheet.lisp Log Message: Add support for EPS output in the postscript backend.
Essentially this is done by using output recording; we draw to a recording stream, measure the bounding box, then replay the output record. There's a currently unused (and undefined) hook for outputing device fonts, which we are using locally in the tablature editor; however, our implementation of device fonts sucks utterly majorly.
Also add rudimentary test file.
Date: Mon Oct 31 11:21:14 2005 Author: crhodes
Index: mcclim/Backends/PostScript/class.lisp diff -u mcclim/Backends/PostScript/class.lisp:1.6 mcclim/Backends/PostScript/class.lisp:1.7 --- mcclim/Backends/PostScript/class.lisp:1.6 Thu Jul 4 08:57:43 2002 +++ mcclim/Backends/PostScript/class.lisp Mon Oct 31 11:21:14 2005 @@ -37,7 +37,8 @@ ;;;; Medium
(defclass postscript-medium (basic-medium) - ()) + ((device-fonts :initform nil + :accessor device-fonts)))
(defmacro postscript-medium-graphics-state (medium) `(first (slot-value (medium-sheet ,medium) 'graphics-state-stack))) @@ -84,7 +85,9 @@ *default-postscript-title*)) (for (or (getf header-comments :for) *default-postscript-for*)) - (region (paper-region device-type orientation)) + (region (case device-type + ((:eps) +everywhere+) + (t (paper-region device-type orientation)))) (transform (make-postscript-transformation device-type orientation))) (make-instance 'postscript-stream :file-stream file-stream
Index: mcclim/Backends/PostScript/graphics.lisp diff -u mcclim/Backends/PostScript/graphics.lisp:1.13 mcclim/Backends/PostScript/graphics.lisp:1.14 --- mcclim/Backends/PostScript/graphics.lisp:1.13 Mon Aug 1 18:50:43 2005 +++ mcclim/Backends/PostScript/graphics.lisp Mon Oct 31 11:21:14 2005 @@ -169,23 +169,25 @@ "Native transformation")
;;; Postscript output utilities -(defmacro with-graphics-state ((medium) &body body) - `(invoke-with-graphics-state ,medium +(defmacro with-graphics-state ((stream) &body body) + `(invoke-with-graphics-state ,stream (lambda () ,@body)))
-(defun postscript-save-graphics-state (medium) - (push (copy-list (postscript-medium-graphics-state medium)) - (slot-value (medium-sheet medium) 'graphics-state-stack)) - (format (postscript-medium-file-stream medium) "gsave~%")) - -(defun postscript-restore-graphics-state (medium) - (pop (slot-value (medium-sheet medium) 'graphics-state-stack)) - (format (postscript-medium-file-stream medium) "grestore~%")) +(defun postscript-save-graphics-state (stream) + (push (copy-list (first (slot-value stream 'graphics-state-stack))) + (slot-value stream 'graphics-state-stack)) + (when (stream-drawing-p stream) + (format (postscript-stream-file-stream stream) "gsave~%"))) + +(defun postscript-restore-graphics-state (stream) + (pop (slot-value stream 'graphics-state-stack)) + (when (stream-drawing-p stream) + (format (postscript-stream-file-stream stream) "grestore~%")))
-(defun invoke-with-graphics-state (medium continuation) - (postscript-save-graphics-state medium) +(defun invoke-with-graphics-state (stream continuation) + (postscript-save-graphics-state stream) (funcall continuation) - (postscript-restore-graphics-state medium)) + (postscript-restore-graphics-state stream))
;;; Postscript path functions @@ -346,8 +348,8 @@ ;; does only one level of saving graphics state, so we can restore ;; and save again GS to obtain an initial CP. It is ugly, but I see ;; no other way now. -- APD, 2002-02-11 - (postscript-restore-graphics-state medium) - (postscript-save-graphics-state medium) + (postscript-restore-graphics-state (medium-sheet medium)) + (postscript-save-graphics-state (medium-sheet medium)) (postscript-set-clipping-region stream (medium-clipping-region medium)))
@@ -494,7 +496,7 @@ (let ((*transformation* (sheet-native-transformation (medium-sheet medium)))) (let ((file-stream (postscript-medium-file-stream medium))) (postscript-actualize-graphics-state file-stream medium :color :text-style) - (with-graphics-state (medium) + (with-graphics-state ((medium-sheet medium)) #+ignore (when transform-glyphs ;;
Index: mcclim/Backends/PostScript/paper.lisp diff -u mcclim/Backends/PostScript/paper.lisp:1.2 mcclim/Backends/PostScript/paper.lisp:1.3 --- mcclim/Backends/PostScript/paper.lisp:1.2 Fri May 31 04:32:10 2002 +++ mcclim/Backends/PostScript/paper.lisp Mon Oct 31 11:21:14 2005 @@ -55,6 +55,9 @@ (make-rectangle* 0 0 width height)))
(defun make-postscript-transformation (paper-size-name orientation) + (when (eq paper-size-name :eps) + (return-from make-postscript-transformation + (make-reflection-transformation* 0 0 1 0))) (multiple-value-bind (width height) (paper-size paper-size-name) (case orientation (:portrait (make-3-point-transformation* @@ -63,4 +66,4 @@ (:landscape (make-3-point-transformation* 0 0 0 width height 0 width height 0 height width 0)) - (t (error "Unknown orientation"))))) \ No newline at end of file + (t (error "Unknown orientation")))))
Index: mcclim/Backends/PostScript/sheet.lisp diff -u mcclim/Backends/PostScript/sheet.lisp:1.9 mcclim/Backends/PostScript/sheet.lisp:1.10 --- mcclim/Backends/PostScript/sheet.lisp:1.9 Thu Apr 1 06:26:46 2004 +++ mcclim/Backends/PostScript/sheet.lisp Mon Oct 31 11:21:14 2005 @@ -58,29 +58,45 @@ orientation header-comments))) (unwind-protect (progn + (with-output-recording-options (stream :record t :draw nil) + (with-graphics-state (stream) + ;; we need at least one level of saving -- APD, 2002-02-11 + (funcall continuation stream))) (with-slots (file-stream title for orientation paper) stream - (format file-stream "%!PS-Adobe-3.0~%") + (format file-stream "%!PS-Adobe-3.0~@[ EPSF-3.0~*~]~%" + (eq device-type :eps)) (format file-stream "%%Creator: McCLIM~%") (format file-stream "%%Title: ~A~%" title) (format file-stream "%%For: ~A~%" for) (format file-stream "%%LanguageLevel: 2~%") - (multiple-value-bind (width height) - (paper-size paper) - (format file-stream "%%BoundingBox: 0 0 ~A ~A~%" width height) - (format file-stream "%%DocumentMedia: ~A ~A ~A 0 () ()~%" - paper width height)) - (format file-stream "%%Orientation: ~A~%" - (ecase orientation - (:portrait "Portrait") - (:landscape "Landscape"))) - (format file-stream "%%Pages: (atend)~%") + (case paper + ((:eps) + (let ((record (stream-output-history stream))) + (multiple-value-bind (lx ly ux uy) (bounding-rectangle* record) + (format file-stream "%%BoundingBox: ~A ~A ~A ~A~%" + (floor lx) (- (ceiling uy)) + (ceiling ux) (- (floor ly)))))) + (t + (multiple-value-bind (width height) + (paper-size paper) + (format file-stream "%%BoundingBox: 0 0 ~A ~A~%" width height) + (format file-stream "%%DocumentMedia: ~A ~A ~A 0 () ()~%" + paper width height)) + (format file-stream "%%Orientation: ~A~%" + (ecase orientation + (:portrait "Portrait") + (:landscape "Landscape"))) + (format file-stream "%%Pages: (atend)~%"))) (format file-stream "%%DocumentNeededResources: (atend)~%") (format file-stream "%%EndComments~%~%") (write-postcript-dictionary file-stream) - (start-page stream)) - (with-graphics-state ((sheet-medium stream)) - ;; we need at least one level of saving -- APD, 2002-02-11 - (funcall continuation stream))) + (dolist (text-style (device-fonts (sheet-medium stream))) + (write-font-to-postscript-stream (sheet-medium stream) text-style)) + (start-page stream) + (let ((record (stream-output-history stream))) + (with-output-recording-options (stream :draw t :record nil) + (with-graphics-state (stream) + (replay record stream)))))) (with-slots (file-stream current-page) stream (format file-stream "end~%showpage~%~%") (format file-stream "%%Trailer~%")