From d95-bli at nada.kth.se Tue Oct 12 17:47:58 2004 From: d95-bli at nada.kth.se (=?iso-8859-1?q?Bj=F6rn_Lindberg?=) Date: Tue, 12 Oct 2004 17:47:58 -0000 Subject: [cl-pdf-devel] Generating embeddable Postscript? Message-ID: My ultimate goal is to be able to programmatically generate Postscript histograms, and embed them into Latex documents. For this, cl-pdf seems at least to be a good start. At the very least I should be able to generate PDF files containing the histograms, convert them to (E)PS, and include them into the Latex documents. What I am wondering is wether it is possible to (a) Avoid having to put the histograms on a "page", so that I don't have to prune it later. (b) Would it even be possible to make cl-pdf output PS directly? (c) Is there a much better approach to all this which I am missing? Thanks, Bj?rn From marc.battyani at fractalconcept.com Tue Oct 12 18:46:12 2004 From: marc.battyani at fractalconcept.com (Marc Battyani) Date: Tue, 12 Oct 2004 20:46:12 +0200 Subject: [cl-pdf-devel] Generating embeddable Postscript? References: Message-ID: <171a01c4b08b$bf4e9f00$0a02a8c0@marcxp> Hi Bj?rn, Bj?rn Lindberg wrote: >My ultimate goal is to be able to programmatically generate Postscript >histograms, and embed them into Latex documents. For this, cl-pdf >seems at least to be a good start. At the very least I should be able >to generate PDF files containing the histograms, convert them to >(E)PS, and include them into the Latex documents. AFAIK, you can directly include PDF files in LaTeX so you don't need to generated them in Postscript. BTW LaTeX is deprecated you should use cl-typesetting ;-) >What I am wondering is wether it is possible to >(a) Avoid having to put the histograms on a "page", so that I don't > have to prune it later. You can't have a standalone histogram. The graphic stream is not enough, you at least need the fonts. But you can make a small page that has exactly the size needed to put the histogram. >(b) Would it even be possible to make cl-pdf output PS directly? There is no need for this. Postscript devices can render PDF files directly and there are utilities like pdftops which can convert a PDF file to PS and EPS. >(c) Is there a much better approach to all this which I am missing? Yes, keep the PDF as LaTeX can include it. Or even better you could switch to cl-typesetting :) If you really want Postscript, you should look at: http://www.cliki.net/PLisp Marc From d95-bli at nada.kth.se Wed Oct 13 10:33:57 2004 From: d95-bli at nada.kth.se (=?iso-8859-1?q?Bj=F6rn_Lindberg?=) Date: Wed, 13 Oct 2004 10:33:57 -0000 Subject: [cl-pdf-devel] Generating embeddable Postscript? In-Reply-To: <171a01c4b08b$bf4e9f00$0a02a8c0@marcxp> References: <171a01c4b08b$bf4e9f00$0a02a8c0@marcxp> Message-ID: "Marc Battyani" writes: > Hi Bj?rn, > > Bj?rn Lindberg wrote: > > > >My ultimate goal is to be able to programmatically generate Postscript > >histograms, and embed them into Latex documents. For this, cl-pdf > >seems at least to be a good start. At the very least I should be able > >to generate PDF files containing the histograms, convert them to > >(E)PS, and include them into the Latex documents. > > AFAIK, you can directly include PDF files in LaTeX so you don't need to > generated them in Postscript. > BTW LaTeX is deprecated you should use cl-typesetting ;-) > > >What I am wondering is wether it is possible to > > >(a) Avoid having to put the histograms on a "page", so that I don't > > have to prune it later. > > You can't have a standalone histogram. The graphic stream is not enough, you > at least need the fonts. > But you can make a small page that has exactly the size needed to put the > histogram. This seems to work well, I have been experimenting with the :bounds argument to with-page, and the results are good. The only problem now is that when I try to include the PDF file in Latex, it complains that ! LaTeX Error: Cannot determine size of graphic in \unhbox \voidb at x \penalty \@ M \ /src/lisp/pdf.pdf (no BoundingBox). >From googling it seems that the PDF file is missing a BoundingBox parameter that tells Latex the coordinates of the figure. I tried converting to PS and to EPS, but to no avail. Would you happen to have any idea on how to work around this? > >(b) Would it even be possible to make cl-pdf output PS directly? > > There is no need for this. Postscript devices can render PDF files directly > and there are utilities like pdftops which can convert a PDF file to PS and > EPS. > > >(c) Is there a much better approach to all this which I am missing? > > Yes, keep the PDF as LaTeX can include it. > Or even better you could switch to cl-typesetting :) I already have a large part of this document in Latex, and also I have to use a certain document class. But next time, I will have a look at cl-typesetting. One step at a time... :-) If cl-pdf works out for what I want to do it would be a huge time saver for me. The data for the histograms is produced by a lisp program, so generating texable histograms is hopefully just a matter of writing one more lisp function. Thanks for your help, and thanks for the very cool cl-pdf! Bj?rn From d95-bli at nada.kth.se Wed Oct 13 11:25:37 2004 From: d95-bli at nada.kth.se (=?iso-8859-1?q?Bj=F6rn_Lindberg?=) Date: Wed, 13 Oct 2004 11:25:37 -0000 Subject: [cl-pdf-devel] Generating embeddable Postscript? In-Reply-To: References: <171a01c4b08b$bf4e9f00$0a02a8c0@marcxp> Message-ID: d95-bli at nada.kth.se (Bj?rn Lindberg) writes: > "Marc Battyani" writes: > > > Hi Bj?rn, > > > > Bj?rn Lindberg wrote: > > > > > > >My ultimate goal is to be able to programmatically generate Postscript > > >histograms, and embed them into Latex documents. For this, cl-pdf > > >seems at least to be a good start. At the very least I should be able > > >to generate PDF files containing the histograms, convert them to > > >(E)PS, and include them into the Latex documents. > > > > AFAIK, you can directly include PDF files in LaTeX so you don't need to > > generated them in Postscript. > > BTW LaTeX is deprecated you should use cl-typesetting ;-) > > > > >What I am wondering is wether it is possible to > > > > >(a) Avoid having to put the histograms on a "page", so that I don't > > > have to prune it later. > > > > You can't have a standalone histogram. The graphic stream is not enough, you > > at least need the fonts. > > But you can make a small page that has exactly the size needed to put the > > histogram. > > This seems to work well, I have been experimenting with the :bounds > argument to with-page, and the results are good. The only problem now > is that when I try to include the PDF file in Latex, it complains that > > ! LaTeX Error: Cannot determine size of graphic in \unhbox > \voidb at x \penalty \@ M \ /src/lisp/pdf.pdf (no BoundingBox). > > >From googling it seems that the PDF file is missing a BoundingBox > parameter that tells Latex the coordinates of the figure. I tried > converting to PS and to EPS, but to no avail. Would you happen to have > any idea on how to work around this? Disregard this message. I managed to get it working by converting to EPS with 'pdftops -eps ...'. I had some path troubles earlier which hid the fact that this is working. The PDF from cl-pdf still has the bounding box problem though, but perhaps it doesn't matter for its intended use. Bj?rn From marc.battyani at fractalconcept.com Wed Oct 13 17:06:54 2004 From: marc.battyani at fractalconcept.com (Marc Battyani) Date: Wed, 13 Oct 2004 19:06:54 +0200 Subject: [cl-pdf-devel] Generating embeddable Postscript? References: <171a01c4b08b$bf4e9f00$0a02a8c0@marcxp> Message-ID: <1a9301c4b147$0ab0a680$0a02a8c0@marcxp> Bj?rn Lindberg wrote: [...] > From googling it seems that the PDF file is missing a BoundingBox > parameter that tells Latex the coordinates of the figure. I tried > converting to PS and to EPS, but to no avail. Would you happen to have > any idea on how to work around this? >Disregard this message. I managed to get it working by converting to >EPS with 'pdftops -eps ...'. I had some path troubles earlier which >hid the fact that this is working. Great to know that it works for you now. :) > The PDF from cl-pdf still has the >bounding box problem though, but perhaps it doesn't matter for its >intended use. About the bounding box problem, there is no bounding box in PDF. There is a MediaBox for the pages but each page has its own MediaBox and there is no BBox in the file Metadata. Marc From divanov at aha.ru Wed Oct 27 08:03:23 2004 From: divanov at aha.ru (Dmitri Ivanov) Date: Wed, 27 Oct 2004 12:03:23 +0400 Subject: [cl-pdf-devel] Named destinations proposal and small amendments Message-ID: <000201c4bbfb$95c11160$4c4d02c3@digo> Hello, Below are: 1) Sketch of code implementing named destinations, 2) Suggestion of the single add-link function replacing multiple add--link functions, 3) An example. ;================================================= (defun pdf-name (obj &optional (prefix #\/)) ;;; Helper (akin to pdf-string) to escape non-alphanumeric characters in PDF names ;; by writing 2-digit hexadecimal code, preceded by the number sign character (#). ;; CAUTION: PDF names are case-sensitive! (let ((string (if (stringp obj) (if (and prefix (char= (schar obj 0) prefix)) (return-from pdf-name obj) ; PDF-ready obj) (princ-to-string obj)))) (with-output-to-string (stream nil #-cmu :element-type #-cmu (array-element-type string)) (when prefix (write-char prefix stream)) (dotimes (i (length string)) (let ((char (schar string i))) (if (or (alphanumericp char) (find char "-_." :test #'char=)) ; often used regular chars (write-char char stream) (format stream "#~2,'0x" (char-code char)))))))) (defmacro enforce-/ (&rest names) ;;; Verify and prefix each name by / unless it is PDF-ready. `(setf ,@(loop for name in names collect name collect `(pdf-name ,name)))) (defun register-destination (destination &optional (display "/Fit") &rest args) ;;; Register named destination as named object or string. (cond ((symbolp destination) ;; PDF 1.1: Include into the Dest entry of in the document's Catalog dictionary. ;; Limited by maxumim dictionary size. (let ((entry (pdf-name destination)) (value (apply #'vector *page* display args)) (dests (get-dict-value (content (catalog *document*)) "/Dests"))) (if dests (add-dict-value dests entry value) (add-dict-value (content (catalog *document*)) "/Dests" (setf dests (make-instance 'dictionary :dict-values `((,entry . ,value)))))))) ((stringp destination) ;; PDF 1.2: Dests entry in the document's Names dictionary, located via ;; the Names entry in the document's Catalog dictionary. (error "Name trees are not implemeted!")))) (defun add-link (x y dx dy &key reference destination uri filename (border #(0 0 0)) (display "/Fit") args) ;;; "Generic" link adder. ;; Args: reference Named reference inside the current document ;; destinaion Named destination in the current document or the remote filename: ;; - either symbol designating named object; ;; - or string through the name tree (not implemented); ;; - or integer interpreted as a page number (for remote only?) ;; Other types of links are welcome. (let ((annotation (make-instance 'annotation :rect (vector x y (+ x dx) (+ y dy)) :type "/Link" :border border)) (action (cond (uri (make-instance 'dictionary :dict-values '(("/S" . "/URI")))) (filename (make-instance 'dictionary :dict-values '(("/S" . "/GoToR"))))))) (if action (add-dict-value (content annotation) "/A" action) ;; Named reference or destination in the current document (push (cons "/Dest" (cond (reference (get-named-reference reference)) ((symbolp destination) (pdf-name destination)) (t (error "not implemeted")))) (dict-values (content annotation)))) (cond (uri (add-dict-value action "/URI" (pdf-string uri))) (filename (add-dict-value action "/F" (pdf-string filename)) (add-dict-value action "/D" (cond ((numberp destination) ; page number (apply #'vector destination display args)) ((symbolp destination) (pdf-name destination)) (t (error "not implemeted"))))) ) annotation)) ;===================== Example ======================== (defun ex-dest (&optional (file #P"/tmp/ex-dest.pdf")) (pdf:with-document () (let* ((helvetica (pdf:get-font "Helvetica"))) (loop for i from 1 to 7 do (pdf:with-page () (pdf:with-outline-level ((format nil "Page ~d" i)(pdf:register-page-reference)) (pdf::register-destination (make-symbol (format nil "top-of-page~d" i)) "/FitH" 810) (pdf:in-text-mode (pdf:set-font helvetica 10) (pdf:move-text 50 800) (pdf:draw-text (format nil "go to next page ~d" (1+ i)))) (pdf:add-link 50 800 80 10 :destination (make-symbol (format nil "top-of-page~d" (1+ i)))) (pdf:in-text-mode (pdf:set-font helvetica 12) (pdf:move-text 400 800) (pdf:draw-text "cl-pdf: Named destiantions")) (pdf:in-text-mode (pdf:set-font helvetica 36) (pdf:move-text 100 600) (pdf:draw-text (format nil "Hello world - page ~d" i))) (pdf:in-text-mode (pdf:set-font helvetica 10) (pdf:move-text 50 50) (pdf:draw-text (format nil "go to previous page ~d" (1- i)))) (pdf:add-link 50 50 80 10 :destination (make-symbol (format nil "bottom-of-page~d" (1- i)))) (pdf::register-destination (make-symbol (format nil "bottom-of-page~d" i)) ))) )) (pdf:write-document file))) (ex-dest (current-pathname "ex-dest.pdf")) ;======================= End of Example ===================== Named destinations could benefit when using Acrobat Interapplication Communication. For example, in LWW, you can automate AcroReader via DDE as follows: (setq fullpath "E:\\Projects\\cl-pdf\\examples\\ex-dest.pdf") (win32:dde-execute-command* 'acroview 'control "DocOpen" `(,fullpath)) ;; The first page is numbered 0. (win32:dde-execute-command* 'acroview 'control "DocGoTo" `(,fullpath 0)) (win32:dde-execute-command* 'acroview 'control "DocGoToNameDest" `(,fullpath "top-of-page3")) (win32:dde-execute-command* 'acroview 'control "DocGoToNameDest" `(,fullpath "bottom-of-page6")) (win32:dde-execute-command* 'acroview 'control "DocClose" `(,fullpath)) -- Sincerely, Dmitri Ivanov lisp.ystok.ru From emarsden at laas.fr Wed Oct 27 09:24:55 2004 From: emarsden at laas.fr (Eric Marsden) Date: Wed, 27 Oct 2004 11:24:55 +0200 Subject: [cl-pdf-devel] Named destinations proposal and small amendments In-Reply-To: <000201c4bbfb$95c11160$4c4d02c3@digo> (Dmitri Ivanov's message of "Wed, 27 Oct 2004 12:03:23 +0400") References: <000201c4bbfb$95c11160$4c4d02c3@digo> Message-ID: >>>>> "di" == Dmitri Ivanov writes: di> 1) Sketch of code implementing named destinations, di> 2) Suggestion of the single add-link function replacing multiple di> add--link functions, di> 3) An example. I looked into implementing something similar a while ago (I was trying to add support for PDF Annotations: text annotations, link annotations etc, but lost enthusiasm after a while). I also moved to a single ADD-LINK function, but made it a generic function dispatching on specializations of a DESTINATION class. I think this is more extensible than dispatching by hand inside ADD-LINK. Rough code follows. (defclass destination () ()) (defclass explicit-destination (destination) ((page :initarg :page :type integer :accessor destination-page) (position :initarg :position :initform "/Fit" :accessor destination-position))) (defmethod write-object ((dest explicit-destination) &optional root-level) (declare (ignore root-level)) (write-object (vector (destination-page dest) (destination-position dest)))) (defclass named-destination (destination) ((name :initarg :name :accessor destination-name))) (defclass action-destination (destination) ((action :initarg :action :accessor destination-action))) (defclass uri-destination (action-destination) ((uri :initarg :uri :accessor destination-uri))) (defmethod add-link (x y dx dy (dest destination)) (make-instance 'link-annotation :rect (vector x y (+ x dx) (+ y dy)) :border border :destination dest)) (defclass annotation (indirect-object) ((type :accessor annotation-type :initarg :type) (rect :accessor annotation-rect :initarg :rect) (border :accessor annotation-border :initarg :border :initform #(0 0 0)))) (defmethod initialize-instance :after ((annotation annotation) &rest init-options &key flags &allow-other-keys) (declare (type (or null integer) flags)) (vector-push-extend annotation (annotations *page*)) (setf (content annotation) (make-instance 'dictionary :dict-values `(("/Type" . "/Annot") ("/Subtype" . ,(annotation-type annotation)) ("/Rect" . ,(annotation-rect annotation)) ,@(when flags `(("/F" . ,flags))))))) ;; unfortunately this type of annotation does not seem to be displayed ;; by xpdf or by Ghostscript. It works with Acrobat Reader. (defclass text-annotation (annotation) ((type :initform "/Text") (text :accessor annotation-text :initarg :text))) (defmethod initialize-instance :after ((annotation text-annotation) &rest init-options &key &allow-other-keys) (add-dict-value (content annotation) "/Contents" (format nil "(~A)" (annotation-text annotation)))) (defclass link-annotation (annotation) ((type :initform "/Link") (destination :accessor annotation-destination :initarg :destination))) (defmethod initialize-instance :after ((annotation link-annotation) &rest init-options &key &allow-other-keys) (add-dict-value (content annotation) "/Dest" (annotation-destination annotation))) ;; FIXME add free-text-annotation, line-annotation, square-annotation, ;; highlight-annotation, underline-annotation -- Eric Marsden From divanov at aha.ru Wed Oct 27 10:28:08 2004 From: divanov at aha.ru (Dmitri Ivanov) Date: Wed, 27 Oct 2004 14:28:08 +0400 Subject: [cl-pdf-devel] Named destinations proposal and small amendments References: <000201c4bbfb$95c11160$4c4d02c3@digo> Message-ID: <000301c4bc14$1a45b400$4c4d02c3@digo> Hello Eric, | I also moved to a single ADD-LINK function, but made it a generic | function dispatching on specializations of a DESTINATION class. I | think this is more extensible than dispatching by hand inside | ADD-LINK. Rough code follows. Thanks, looks a bit more extensive :-) | (defclass destination () ()) | | (defclass explicit-destination (destination) | ((page :initarg :page | :type integer | :accessor destination-page) | (position :initarg :position | :initform "/Fit" | :accessor destination-position))) | | (defmethod write-object ((dest explicit-destination) &optional | root-level)(declare (ignore root-level)) | (write-object (vector (destination-page dest) (destination-position | dest)))) But how do you handle destination possitions with arguments, e.g. "/XYZ" top left zoom? -- Sincerely, Dmitri Ivanov lisp.ystok.ru From emarsden at laas.fr Wed Oct 27 13:45:37 2004 From: emarsden at laas.fr (Eric Marsden) Date: Wed, 27 Oct 2004 15:45:37 +0200 Subject: [cl-pdf-devel] Named destinations proposal and small amendments In-Reply-To: <000301c4bc14$1a45b400$4c4d02c3@digo> (Dmitri Ivanov's message of "Wed, 27 Oct 2004 14:28:08 +0400") References: <000201c4bbfb$95c11160$4c4d02c3@digo> <000301c4bc14$1a45b400$4c4d02c3@digo> Message-ID: >>>>> "di" == Dmitri Ivanov writes: di> But how do you handle destination possitions with arguments, e.g. "/XYZ" top di> left zoom? I never finished this code (I was disappointed that xpdf has no support for normal Text annotations), and my memory of the PDF spec is vague. However, I think that this could be handled using for example (add-link x y dx dy (make-instance 'explicit-destination :position "/XYZ")) -- Eric Marsden